Home | History | Annotate | Download | only in source
      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