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 status_t err = mSource->stop(); 83 84 if (mLooper != NULL) { 85 mLooper->stop(); 86 mLooper.clear(); 87 88 mReflector.clear(); 89 } 90 91 if (mBuffer != NULL) { 92 ALOGV("releasing mbuf %p", mBuffer); 93 mBuffer->release(); 94 mBuffer = NULL; 95 } 96 97 98 ALOGV("stopped"); 99 100 mStarted = false; 101 102 return err; 103 } 104 105 sp<MetaData> RepeaterSource::getFormat() { 106 return mSource->getFormat(); 107 } 108 109 status_t RepeaterSource::read( 110 MediaBuffer **buffer, const ReadOptions *options) { 111 int64_t seekTimeUs; 112 ReadOptions::SeekMode seekMode; 113 CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &seekMode)); 114 115 for (;;) { 116 int64_t bufferTimeUs = -1ll; 117 118 if (mStartTimeUs < 0ll) { 119 Mutex::Autolock autoLock(mLock); 120 while ((mLastBufferUpdateUs < 0ll || mBuffer == NULL) 121 && mResult == OK) { 122 mCondition.wait(mLock); 123 } 124 125 ALOGV("now resuming."); 126 mStartTimeUs = ALooper::GetNowUs(); 127 bufferTimeUs = mStartTimeUs; 128 } else { 129 bufferTimeUs = mStartTimeUs + (mFrameCount * 1000000ll) / mRateHz; 130 131 int64_t nowUs = ALooper::GetNowUs(); 132 int64_t delayUs = bufferTimeUs - nowUs; 133 134 if (delayUs > 0ll) { 135 usleep(delayUs); 136 } 137 } 138 139 bool stale = false; 140 141 { 142 Mutex::Autolock autoLock(mLock); 143 if (mResult != OK) { 144 CHECK(mBuffer == NULL); 145 return mResult; 146 } 147 148 #if SUSPEND_VIDEO_IF_IDLE 149 int64_t nowUs = ALooper::GetNowUs(); 150 if (nowUs - mLastBufferUpdateUs > 1000000ll) { 151 mLastBufferUpdateUs = -1ll; 152 stale = true; 153 } else 154 #endif 155 { 156 mBuffer->add_ref(); 157 *buffer = mBuffer; 158 (*buffer)->meta_data()->setInt64(kKeyTime, bufferTimeUs); 159 ++mFrameCount; 160 } 161 } 162 163 if (!stale) { 164 break; 165 } 166 167 mStartTimeUs = -1ll; 168 mFrameCount = 0; 169 ALOGV("now dormant"); 170 } 171 172 return OK; 173 } 174 175 void RepeaterSource::postRead() { 176 (new AMessage(kWhatRead, mReflector))->post(); 177 } 178 179 void RepeaterSource::onMessageReceived(const sp<AMessage> &msg) { 180 switch (msg->what()) { 181 case kWhatRead: 182 { 183 MediaBuffer *buffer; 184 status_t err = mSource->read(&buffer); 185 186 ALOGV("read mbuf %p", buffer); 187 188 Mutex::Autolock autoLock(mLock); 189 if (mBuffer != NULL) { 190 mBuffer->release(); 191 mBuffer = NULL; 192 } 193 mBuffer = buffer; 194 mResult = err; 195 mLastBufferUpdateUs = ALooper::GetNowUs(); 196 197 mCondition.broadcast(); 198 199 if (err == OK) { 200 postRead(); 201 } 202 break; 203 } 204 205 default: 206 TRESPASS(); 207 } 208 } 209 210 void RepeaterSource::wakeUp() { 211 ALOGV("wakeUp"); 212 Mutex::Autolock autoLock(mLock); 213 if (mLastBufferUpdateUs < 0ll && mBuffer != NULL) { 214 mLastBufferUpdateUs = ALooper::GetNowUs(); 215 mCondition.broadcast(); 216 } 217 } 218 219 } // namespace android 220