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      mLastBufferUpdateUs(-1ll),
22      mStartTimeUs(-1ll),
23      mFrameCount(0) {
24}
25
26RepeaterSource::~RepeaterSource() {
27    CHECK(!mStarted);
28}
29
30double RepeaterSource::getFrameRate() const {
31    return mRateHz;
32}
33
34void 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
49status_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
77status_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
105sp<MetaData> RepeaterSource::getFormat() {
106    return mSource->getFormat();
107}
108
109status_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
175void RepeaterSource::postRead() {
176    (new AMessage(kWhatRead, mReflector))->post();
177}
178
179void 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
210void 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