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