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