RepeaterSource.cpp revision 4a8b9a2363b7b7b4f98022e6d9aae8b8aa8e35e5
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 int64_t nowUs = ALooper::GetNowUs(); 129 if (nowUs - mLastBufferUpdateUs > 1000000ll) { 130 mLastBufferUpdateUs = -1ll; 131 stale = true; 132 } else { 133 mBuffer->add_ref(); 134 *buffer = mBuffer; 135 (*buffer)->meta_data()->setInt64(kKeyTime, bufferTimeUs); 136 ++mFrameCount; 137 } 138 } 139 140 if (!stale) { 141 break; 142 } 143 144 mStartTimeUs = -1ll; 145 mFrameCount = 0; 146 ALOGV("now dormant"); 147 } 148 149 return OK; 150} 151 152void RepeaterSource::postRead() { 153 (new AMessage(kWhatRead, mReflector->id()))->post(); 154} 155 156void RepeaterSource::onMessageReceived(const sp<AMessage> &msg) { 157 switch (msg->what()) { 158 case kWhatRead: 159 { 160 MediaBuffer *buffer; 161 status_t err = mSource->read(&buffer); 162 163 ALOGV("read mbuf %p", buffer); 164 165 Mutex::Autolock autoLock(mLock); 166 if (mBuffer != NULL) { 167 mBuffer->release(); 168 mBuffer = NULL; 169 } 170 mBuffer = buffer; 171 mResult = err; 172 mLastBufferUpdateUs = ALooper::GetNowUs(); 173 174 mCondition.broadcast(); 175 176 if (err == OK) { 177 postRead(); 178 } 179 break; 180 } 181 182 default: 183 TRESPASS(); 184 } 185} 186 187void RepeaterSource::wakeUp() { 188 ALOGV("wakeUp"); 189 Mutex::Autolock autoLock(mLock); 190 if (mLastBufferUpdateUs < 0ll && mBuffer != NULL) { 191 mLastBufferUpdateUs = ALooper::GetNowUs(); 192 mCondition.broadcast(); 193 } 194} 195 196} // namespace android 197