• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RepeaterSource(const sp<MediaSource> & source,double rateHz)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 
~RepeaterSource()26 RepeaterSource::~RepeaterSource() {
27     CHECK(!mStarted);
28 }
29 
getFrameRate() const30 double RepeaterSource::getFrameRate() const {
31     return mRateHz;
32 }
33 
setFrameRate(double rateHz)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 
start(MetaData * params)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 
stop()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 
getFormat()105 sp<MetaData> RepeaterSource::getFormat() {
106     return mSource->getFormat();
107 }
108 
read(MediaBuffer ** buffer,const ReadOptions * options)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 
postRead()175 void RepeaterSource::postRead() {
176     (new AMessage(kWhatRead, mReflector))->post();
177 }
178 
onMessageReceived(const sp<AMessage> & msg)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 
wakeUp()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