1 //#define LOG_NDEBUG 0 2 #define LOG_TAG "RepeaterSource" 3 #include <utils/Log.h> 4 5 #include "RepeaterSource.h" 6 7 #include <media/stagefright/foundation/ADebug.h> 8 #include <media/stagefright/foundation/ALooper.h> 9 #include <media/stagefright/foundation/AMessage.h> 10 #include <media/stagefright/MediaBuffer.h> 11 #include <media/stagefright/MetaData.h> 12 13 namespace android { 14 15 RepeaterSource::RepeaterSource(const sp<MediaSource> &source, double rateHz) 16 : mStarted(false), 17 mSource(source), 18 mRateHz(rateHz), 19 mBuffer(NULL), 20 mResult(OK), 21 mLastBufferUpdateUs(-1ll), 22 mStartTimeUs(-1ll), 23 mFrameCount(0) { 24 } 25 26 RepeaterSource::~RepeaterSource() { 27 CHECK(!mStarted); 28 } 29 30 double RepeaterSource::getFrameRate() const { 31 return mRateHz; 32 } 33 34 void RepeaterSource::setFrameRate(double rateHz) { 35 Mutex::Autolock autoLock(mLock); 36 37 if (rateHz == mRateHz) { 38 return; 39 } 40 41 if (mStartTimeUs >= 0ll) { 42 int64_t nextTimeUs = mStartTimeUs + (mFrameCount * 1000000ll) / mRateHz; 43 mStartTimeUs = nextTimeUs; 44 mFrameCount = 0; 45 } 46 mRateHz = rateHz; 47 } 48 49 status_t RepeaterSource::start(MetaData *params) { 50 CHECK(!mStarted); 51 52 status_t err = mSource->start(params); 53 54 if (err != OK) { 55 return err; 56 } 57 58 mBuffer = NULL; 59 mResult = OK; 60 mStartTimeUs = -1ll; 61 mFrameCount = 0; 62 63 mLooper = new ALooper; 64 mLooper->setName("repeater_looper"); 65 mLooper->start(); 66 67 mReflector = new AHandlerReflector<RepeaterSource>(this); 68 mLooper->registerHandler(mReflector); 69 70 postRead(); 71 72 mStarted = true; 73 74 return OK; 75 } 76 77 status_t RepeaterSource::stop() { 78 CHECK(mStarted); 79 80 ALOGV("stopping"); 81 82 if (mLooper != NULL) { 83 mLooper->stop(); 84 mLooper.clear(); 85 86 mReflector.clear(); 87 } 88 89 if (mBuffer != NULL) { 90 ALOGV("releasing mbuf %p", mBuffer); 91 mBuffer->release(); 92 mBuffer = NULL; 93 } 94 95 status_t err = mSource->stop(); 96 97 ALOGV("stopped"); 98 99 mStarted = false; 100 101 return err; 102 } 103 104 sp<MetaData> RepeaterSource::getFormat() { 105 return mSource->getFormat(); 106 } 107 108 status_t RepeaterSource::read( 109 MediaBuffer **buffer, const ReadOptions *options) { 110 int64_t seekTimeUs; 111 ReadOptions::SeekMode seekMode; 112 CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &seekMode)); 113 114 for (;;) { 115 int64_t bufferTimeUs = -1ll; 116 117 if (mStartTimeUs < 0ll) { 118 Mutex::Autolock autoLock(mLock); 119 while ((mLastBufferUpdateUs < 0ll || mBuffer == NULL) 120 && mResult == OK) { 121 mCondition.wait(mLock); 122 } 123 124 ALOGV("now resuming."); 125 mStartTimeUs = ALooper::GetNowUs(); 126 bufferTimeUs = mStartTimeUs; 127 } else { 128 bufferTimeUs = mStartTimeUs + (mFrameCount * 1000000ll) / mRateHz; 129 130 int64_t nowUs = ALooper::GetNowUs(); 131 int64_t delayUs = bufferTimeUs - nowUs; 132 133 if (delayUs > 0ll) { 134 usleep(delayUs); 135 } 136 } 137 138 bool stale = false; 139 140 { 141 Mutex::Autolock autoLock(mLock); 142 if (mResult != OK) { 143 CHECK(mBuffer == NULL); 144 return mResult; 145 } 146 147 #if SUSPEND_VIDEO_IF_IDLE 148 int64_t nowUs = ALooper::GetNowUs(); 149 if (nowUs - mLastBufferUpdateUs > 1000000ll) { 150 mLastBufferUpdateUs = -1ll; 151 stale = true; 152 } else 153 #endif 154 { 155 mBuffer->add_ref(); 156 *buffer = mBuffer; 157 (*buffer)->meta_data()->setInt64(kKeyTime, bufferTimeUs); 158 ++mFrameCount; 159 } 160 } 161 162 if (!stale) { 163 break; 164 } 165 166 mStartTimeUs = -1ll; 167 mFrameCount = 0; 168 ALOGV("now dormant"); 169 } 170 171 return OK; 172 } 173 174 void RepeaterSource::postRead() { 175 (new AMessage(kWhatRead, mReflector->id()))->post(); 176 } 177 178 void RepeaterSource::onMessageReceived(const sp<AMessage> &msg) { 179 switch (msg->what()) { 180 case kWhatRead: 181 { 182 MediaBuffer *buffer; 183 status_t err = mSource->read(&buffer); 184 185 ALOGV("read mbuf %p", buffer); 186 187 Mutex::Autolock autoLock(mLock); 188 if (mBuffer != NULL) { 189 mBuffer->release(); 190 mBuffer = NULL; 191 } 192 mBuffer = buffer; 193 mResult = err; 194 mLastBufferUpdateUs = ALooper::GetNowUs(); 195 196 mCondition.broadcast(); 197 198 if (err == OK) { 199 postRead(); 200 } 201 break; 202 } 203 204 default: 205 TRESPASS(); 206 } 207 } 208 209 void RepeaterSource::wakeUp() { 210 ALOGV("wakeUp"); 211 Mutex::Autolock autoLock(mLock); 212 if (mLastBufferUpdateUs < 0ll && mBuffer != NULL) { 213 mLastBufferUpdateUs = ALooper::GetNowUs(); 214 mCondition.broadcast(); 215 } 216 } 217 218 } // namespace android 219