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 13namespace android { 14 15RepeaterSource::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 26RepeaterSource::~RepeaterSource() { 27 CHECK(!mStarted); 28} 29 30double RepeaterSource::getFrameRate() const { 31 return mRateHz; 32} 33 34void 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 49status_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 77status_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 105sp<MetaData> RepeaterSource::getFormat() { 106 return mSource->getFormat(); 107} 108 109status_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 175void RepeaterSource::postRead() { 176 (new AMessage(kWhatRead, mReflector->id()))->post(); 177} 178 179void 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 210void 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