1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_AUDIO_MONO_PIPE_H 18 #define ANDROID_AUDIO_MONO_PIPE_H 19 20 #include <time.h> 21 #include <utils/LinearTransform.h> 22 #include "NBAIO.h" 23 #include <media/SingleStateQueue.h> 24 25 namespace android { 26 27 typedef SingleStateQueue<AudioTimestamp> AudioTimestampSingleStateQueue; 28 29 // MonoPipe is similar to Pipe except: 30 // - supports only a single reader, called MonoPipeReader 31 // - write() cannot overrun; instead it will return a short actual count if insufficient space 32 // - write() can optionally block if the pipe is full 33 // Like Pipe, it is not multi-thread safe for either writer or reader 34 // but writer and reader can be different threads. 35 class MonoPipe : public NBAIO_Sink { 36 37 friend class MonoPipeReader; 38 39 public: 40 // reqFrames will be rounded up to a power of 2, and all slots are available. Must be >= 2. 41 // Note: whatever shares this object with another thread needs to do so in an SMP-safe way (like 42 // creating it the object before creating the other thread, or storing the object with a 43 // release_store). Otherwise the other thread could see a partially-constructed object. 44 MonoPipe(size_t reqFrames, const NBAIO_Format& format, bool writeCanBlock = false); 45 virtual ~MonoPipe(); 46 47 // NBAIO_Port interface 48 49 //virtual ssize_t negotiate(const NBAIO_Format offers[], size_t numOffers, 50 // NBAIO_Format counterOffers[], size_t& numCounterOffers); 51 //virtual NBAIO_Format format() const; 52 53 // NBAIO_Sink interface 54 55 //virtual size_t framesWritten() const; 56 //virtual size_t framesUnderrun() const; 57 //virtual size_t underruns() const; 58 59 virtual ssize_t availableToWrite() const; 60 virtual ssize_t write(const void *buffer, size_t count); 61 //virtual ssize_t writeVia(writeVia_t via, size_t total, void *user, size_t block); 62 63 // MonoPipe's implementation of getNextWriteTimestamp works in conjunction 64 // with MonoPipeReader. Every time a MonoPipeReader reads from the pipe, it 65 // receives a "readPTS" indicating the point in time for which the reader 66 // would like to read data. This "last read PTS" is offset by the amt of 67 // data the reader is currently mixing and then cached cached along with the 68 // updated read pointer. This cached value is the local time for which the 69 // reader is going to request data next time it reads data (assuming we are 70 // in steady state and operating with no underflows). Writers to the 71 // MonoPipe who would like to know when their next write operation will hit 72 // the speakers can call getNextWriteTimestamp which will return the value 73 // of the last read PTS plus the duration of the amt of data waiting to be 74 // read in the MonoPipe. 75 virtual status_t getNextWriteTimestamp(int64_t *timestamp); 76 77 // average number of frames present in the pipe under normal conditions. 78 // See throttling mechanism in MonoPipe::write() getAvgFrames()79 size_t getAvgFrames() const { return mSetpoint; } 80 void setAvgFrames(size_t setpoint); maxFrames()81 size_t maxFrames() const { return mMaxFrames; } 82 83 // Set the shutdown state for the write side of a pipe. 84 // This may be called by an unrelated thread. When shutdown state is 'true', 85 // a write that would otherwise block instead returns a short transfer count. 86 // There is no guarantee how long it will take for the shutdown to be recognized, 87 // but it will not be an unbounded amount of time. 88 // The state can be restored to normal by calling shutdown(false). 89 void shutdown(bool newState = true); 90 91 // Return true if the write side of a pipe is currently shutdown. 92 bool isShutdown(); 93 94 // Return NO_ERROR if there is a timestamp available 95 status_t getTimestamp(AudioTimestamp& timestamp); 96 97 private: 98 // A pair of methods and a helper variable which allows the reader and the 99 // writer to update and observe the values of mFront and mNextRdPTS in an 100 // atomic lock-less fashion. 101 // 102 // :: Important :: 103 // Two assumptions must be true in order for this lock-less approach to 104 // function properly on all systems. First, there may only be one updater 105 // thread in the system. Second, the updater thread must be running at a 106 // strictly higher priority than the observer threads. Currently, both of 107 // these assumptions are true. The only updater is always a single 108 // FastMixer thread (which runs with SCHED_FIFO/RT priority while the only 109 // observer is always an AudioFlinger::PlaybackThread running with 110 // traditional (non-RT) audio priority. 111 void updateFrontAndNRPTS(int32_t newFront, int64_t newNextRdPTS); 112 void observeFrontAndNRPTS(int32_t *outFront, int64_t *outNextRdPTS); 113 volatile int32_t mUpdateSeq; 114 115 const size_t mReqFrames; // as requested in constructor, unrounded 116 const size_t mMaxFrames; // always a power of 2 117 void * const mBuffer; 118 // mFront and mRear will never be separated by more than mMaxFrames. 119 // 32-bit overflow is possible if the pipe is active for a long time, but if that happens it's 120 // safe because we "&" with (mMaxFrames-1) at end of computations to calculate a buffer index. 121 volatile int32_t mFront; // written by the reader with updateFrontAndNRPTS, observed by 122 // the writer with observeFrontAndNRPTS 123 volatile int32_t mRear; // written by writer with android_atomic_release_store, 124 // read by reader with android_atomic_acquire_load 125 volatile int64_t mNextRdPTS; // written by the reader with updateFrontAndNRPTS, observed by 126 // the writer with observeFrontAndNRPTS 127 bool mWriteTsValid; // whether mWriteTs is valid 128 struct timespec mWriteTs; // time that the previous write() completed 129 size_t mSetpoint; // target value for pipe fill depth 130 const bool mWriteCanBlock; // whether write() should block if the pipe is full 131 132 int64_t offsetTimestampByAudioFrames(int64_t ts, size_t audFrames); 133 LinearTransform mSamplesToLocalTime; 134 135 bool mIsShutdown; // whether shutdown(true) was called, no barriers are needed 136 137 AudioTimestampSingleStateQueue::Shared mTimestampShared; 138 AudioTimestampSingleStateQueue::Mutator mTimestampMutator; 139 AudioTimestampSingleStateQueue::Observer mTimestampObserver; 140 }; 141 142 } // namespace android 143 144 #endif // ANDROID_AUDIO_MONO_PIPE_H 145