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     if (mLooper != NULL) {
     83         mLooper->stop();
     84         mLooper.clear();
     85 
     86         mReflector.clear();
     87     }
     88 
     89     if (mBuffer != NULL) {
     90         ALOGV("releasing mbuf %p", mBuffer);
     91         mBuffer->release();
     92         mBuffer = NULL;
     93     }
     94 
     95     status_t err = mSource->stop();
     96 
     97     ALOGV("stopped");
     98 
     99     mStarted = false;
    100 
    101     return err;
    102 }
    103 
    104 sp<MetaData> RepeaterSource::getFormat() {
    105     return mSource->getFormat();
    106 }
    107 
    108 status_t RepeaterSource::read(
    109         MediaBuffer **buffer, const ReadOptions *options) {
    110     int64_t seekTimeUs;
    111     ReadOptions::SeekMode seekMode;
    112     CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &seekMode));
    113 
    114     for (;;) {
    115         int64_t bufferTimeUs = -1ll;
    116 
    117         if (mStartTimeUs < 0ll) {
    118             Mutex::Autolock autoLock(mLock);
    119             while ((mLastBufferUpdateUs < 0ll || mBuffer == NULL)
    120                     && mResult == OK) {
    121                 mCondition.wait(mLock);
    122             }
    123 
    124             ALOGV("now resuming.");
    125             mStartTimeUs = ALooper::GetNowUs();
    126             bufferTimeUs = mStartTimeUs;
    127         } else {
    128             bufferTimeUs = mStartTimeUs + (mFrameCount * 1000000ll) / mRateHz;
    129 
    130             int64_t nowUs = ALooper::GetNowUs();
    131             int64_t delayUs = bufferTimeUs - nowUs;
    132 
    133             if (delayUs > 0ll) {
    134                 usleep(delayUs);
    135             }
    136         }
    137 
    138         bool stale = false;
    139 
    140         {
    141             Mutex::Autolock autoLock(mLock);
    142             if (mResult != OK) {
    143                 CHECK(mBuffer == NULL);
    144                 return mResult;
    145             }
    146 
    147 #if SUSPEND_VIDEO_IF_IDLE
    148             int64_t nowUs = ALooper::GetNowUs();
    149             if (nowUs - mLastBufferUpdateUs > 1000000ll) {
    150                 mLastBufferUpdateUs = -1ll;
    151                 stale = true;
    152             } else
    153 #endif
    154             {
    155                 mBuffer->add_ref();
    156                 *buffer = mBuffer;
    157                 (*buffer)->meta_data()->setInt64(kKeyTime, bufferTimeUs);
    158                 ++mFrameCount;
    159             }
    160         }
    161 
    162         if (!stale) {
    163             break;
    164         }
    165 
    166         mStartTimeUs = -1ll;
    167         mFrameCount = 0;
    168         ALOGV("now dormant");
    169     }
    170 
    171     return OK;
    172 }
    173 
    174 void RepeaterSource::postRead() {
    175     (new AMessage(kWhatRead, mReflector->id()))->post();
    176 }
    177 
    178 void RepeaterSource::onMessageReceived(const sp<AMessage> &msg) {
    179     switch (msg->what()) {
    180         case kWhatRead:
    181         {
    182             MediaBuffer *buffer;
    183             status_t err = mSource->read(&buffer);
    184 
    185             ALOGV("read mbuf %p", buffer);
    186 
    187             Mutex::Autolock autoLock(mLock);
    188             if (mBuffer != NULL) {
    189                 mBuffer->release();
    190                 mBuffer = NULL;
    191             }
    192             mBuffer = buffer;
    193             mResult = err;
    194             mLastBufferUpdateUs = ALooper::GetNowUs();
    195 
    196             mCondition.broadcast();
    197 
    198             if (err == OK) {
    199                 postRead();
    200             }
    201             break;
    202         }
    203 
    204         default:
    205             TRESPASS();
    206     }
    207 }
    208 
    209 void RepeaterSource::wakeUp() {
    210     ALOGV("wakeUp");
    211     Mutex::Autolock autoLock(mLock);
    212     if (mLastBufferUpdateUs < 0ll && mBuffer != NULL) {
    213         mLastBufferUpdateUs = ALooper::GetNowUs();
    214         mCondition.broadcast();
    215     }
    216 }
    217 
    218 }  // namespace android
    219