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