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