1 /*
2 * Copyright 2016, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gui/Surface.h>
18
19 #include <media/ICrypto.h>
20 #include <media/stagefright/foundation/ABuffer.h>
21 #include <media/stagefright/foundation/ALooper.h>
22 #include <media/stagefright/foundation/AMessage.h>
23 #include <media/stagefright/foundation/AUtils.h>
24 #include <media/stagefright/MediaBuffer.h>
25 #include <media/stagefright/MediaCodecList.h>
26 #include <media/stagefright/MediaCodec.h>
27 #include <media/stagefright/MetaData.h>
28 #include <media/stagefright/SimpleDecodingSource.h>
29 #include <media/stagefright/Utils.h>
30
31 using namespace android;
32
33 const int64_t kTimeoutWaitForOutputUs = 500000; // 0.5 seconds
34 const int64_t kTimeoutWaitForInputUs = 5000; // 5 milliseconds
35
36 //static
Create(const sp<IMediaSource> & source,uint32_t flags,const sp<ANativeWindow> & nativeWindow,const char * desiredCodec)37 sp<SimpleDecodingSource> SimpleDecodingSource::Create(
38 const sp<IMediaSource> &source, uint32_t flags, const sp<ANativeWindow> &nativeWindow,
39 const char *desiredCodec) {
40 sp<Surface> surface = static_cast<Surface*>(nativeWindow.get());
41 const char *mime = NULL;
42 sp<MetaData> meta = source->getFormat();
43 CHECK(meta->findCString(kKeyMIMEType, &mime));
44
45 sp<AMessage> format = new AMessage;
46 if (convertMetaDataToMessage(source->getFormat(), &format) != OK) {
47 return NULL;
48 }
49
50 Vector<AString> matchingCodecs;
51 MediaCodecList::findMatchingCodecs(
52 mime, false /* encoder */, flags, &matchingCodecs);
53
54 sp<ALooper> looper = new ALooper;
55 looper->setName("stagefright");
56 looper->start();
57
58 sp<MediaCodec> codec;
59
60 for (size_t i = 0; i < matchingCodecs.size(); ++i) {
61 const AString &componentName = matchingCodecs[i];
62 if (desiredCodec != NULL && componentName.compare(desiredCodec)) {
63 continue;
64 }
65
66 ALOGV("Attempting to allocate codec '%s'", componentName.c_str());
67
68 codec = MediaCodec::CreateByComponentName(looper, componentName);
69 if (codec != NULL) {
70 ALOGI("Successfully allocated codec '%s'", componentName.c_str());
71
72 status_t err = codec->configure(format, surface, NULL /* crypto */, 0 /* flags */);
73 if (err == OK) {
74 err = codec->getOutputFormat(&format);
75 }
76 if (err == OK) {
77 return new SimpleDecodingSource(codec, source, looper, surface != NULL, format);
78 }
79
80 ALOGD("Failed to configure codec '%s'", componentName.c_str());
81 codec->release();
82 codec = NULL;
83 }
84 }
85
86 looper->stop();
87 ALOGE("No matching decoder! (mime: %s)", mime);
88 return NULL;
89 }
90
SimpleDecodingSource(const sp<MediaCodec> & codec,const sp<IMediaSource> & source,const sp<ALooper> & looper,bool usingSurface,const sp<AMessage> & format)91 SimpleDecodingSource::SimpleDecodingSource(
92 const sp<MediaCodec> &codec, const sp<IMediaSource> &source, const sp<ALooper> &looper,
93 bool usingSurface, const sp<AMessage> &format)
94 : mCodec(codec),
95 mSource(source),
96 mLooper(looper),
97 mUsingSurface(usingSurface),
98 mProtectedState(format) {
99 mCodec->getName(&mComponentName);
100 }
101
~SimpleDecodingSource()102 SimpleDecodingSource::~SimpleDecodingSource() {
103 mCodec->release();
104 mLooper->stop();
105 }
106
start(MetaData * params)107 status_t SimpleDecodingSource::start(MetaData *params) {
108 (void)params;
109 Mutexed<ProtectedState>::Locked me(mProtectedState);
110 if (me->mState != INIT) {
111 return -EINVAL;
112 }
113 status_t res = mCodec->start();
114 if (res == OK) {
115 res = mSource->start();
116 }
117
118 if (res == OK) {
119 me->mState = STARTED;
120 me->mQueuedInputEOS = false;
121 me->mGotOutputEOS = false;
122 } else {
123 me->mState = ERROR;
124 }
125
126 return res;
127 }
128
stop()129 status_t SimpleDecodingSource::stop() {
130 Mutexed<ProtectedState>::Locked me(mProtectedState);
131 if (me->mState != STARTED) {
132 return -EINVAL;
133 }
134
135 // wait for any pending reads to complete
136 me->mState = STOPPING;
137 while (me->mReading) {
138 me.waitForCondition(me->mReadCondition);
139 }
140
141 status_t res1 = mCodec->stop();
142 if (res1 != OK) {
143 mCodec->release();
144 }
145 status_t res2 = mSource->stop();
146 if (res1 == OK && res2 == OK) {
147 me->mState = STOPPED;
148 } else {
149 me->mState = ERROR;
150 }
151 return res1 != OK ? res1 : res2;
152 }
153
getFormat()154 sp<MetaData> SimpleDecodingSource::getFormat() {
155 Mutexed<ProtectedState>::Locked me(mProtectedState);
156 if (me->mState == STARTED || me->mState == INIT) {
157 sp<MetaData> meta = new MetaData();
158 convertMessageToMetaData(me->mFormat, meta);
159 return meta;
160 }
161 return NULL;
162 }
163
ProtectedState(const sp<AMessage> & format)164 SimpleDecodingSource::ProtectedState::ProtectedState(const sp<AMessage> &format)
165 : mReading(false),
166 mFormat(format),
167 mState(INIT),
168 mQueuedInputEOS(false),
169 mGotOutputEOS(false) {
170 }
171
read(MediaBuffer ** buffer,const ReadOptions * options)172 status_t SimpleDecodingSource::read(
173 MediaBuffer **buffer, const ReadOptions *options) {
174 *buffer = NULL;
175
176 Mutexed<ProtectedState>::Locked me(mProtectedState);
177 if (me->mState != STARTED) {
178 return ERROR_END_OF_STREAM;
179 }
180 me->mReading = true;
181
182 status_t res = doRead(me, buffer, options);
183
184 me.lock();
185 me->mReading = false;
186 if (me->mState != STARTED) {
187 me->mReadCondition.signal();
188 }
189
190 return res;
191 }
192
doRead(Mutexed<ProtectedState>::Locked & me,MediaBuffer ** buffer,const ReadOptions * options)193 status_t SimpleDecodingSource::doRead(
194 Mutexed<ProtectedState>::Locked &me, MediaBuffer **buffer, const ReadOptions *options) {
195 // |me| is always locked on entry, but is allowed to be unlocked on exit
196 CHECK_EQ(me->mState, STARTED);
197
198 size_t out_ix, in_ix, out_offset, out_size;
199 int64_t out_pts;
200 uint32_t out_flags;
201 status_t res;
202
203 // flush codec on seek
204 IMediaSource::ReadOptions::SeekMode mode;
205 if (options != NULL && options->getSeekTo(&out_pts, &mode)) {
206 me->mQueuedInputEOS = false;
207 me->mGotOutputEOS = false;
208 mCodec->flush();
209 }
210
211 if (me->mGotOutputEOS) {
212 return ERROR_END_OF_STREAM;
213 }
214
215 for (int retries = 0; ++retries; ) {
216 // If we fill all available input buffers, we should expect that
217 // the codec produces at least one output buffer. Also, the codec
218 // should produce an output buffer in at most 1 seconds. Retry a
219 // few times nonetheless.
220 while (!me->mQueuedInputEOS) {
221 // allow some time to get input buffer after flush
222 res = mCodec->dequeueInputBuffer(&in_ix, kTimeoutWaitForInputUs);
223 if (res == -EAGAIN) {
224 // no available input buffers
225 break;
226 }
227
228 sp<ABuffer> in_buffer;
229 if (res == OK) {
230 res = mCodec->getInputBuffer(in_ix, &in_buffer);
231 }
232
233 if (res != OK || in_buffer == NULL) {
234 ALOGW("[%s] could not get input buffer #%zu",
235 mComponentName.c_str(), in_ix);
236 me->mState = ERROR;
237 return UNKNOWN_ERROR;
238 }
239
240 MediaBuffer *in_buf;
241 while (true) {
242 in_buf = NULL;
243 me.unlock();
244 res = mSource->read(&in_buf, options);
245 me.lock();
246 if (res != OK || me->mState != STARTED) {
247 if (in_buf != NULL) {
248 in_buf->release();
249 in_buf = NULL;
250 }
251
252 // queue EOS
253 me->mQueuedInputEOS = true;
254 if (mCodec->queueInputBuffer(
255 in_ix, 0 /* offset */, 0 /* size */,
256 0 /* pts */, MediaCodec::BUFFER_FLAG_EOS) != OK) {
257 ALOGI("[%s] failed to queue input EOS", mComponentName.c_str());
258 me->mState = ERROR;
259 return UNKNOWN_ERROR;
260 }
261
262 // don't stop on EOS, but report error or EOS on stop
263 if (res != ERROR_END_OF_STREAM) {
264 me->mState = ERROR;
265 return res;
266 }
267 if (me->mState != STARTED) {
268 return ERROR_END_OF_STREAM;
269 }
270 break;
271 }
272 if (in_buf == NULL) { // should not happen
273 continue;
274 } else if (in_buf->range_length() != 0) {
275 break;
276 }
277 in_buf->release();
278 }
279
280 if (in_buf != NULL) {
281 int64_t timestampUs = 0;
282 CHECK(in_buf->meta_data()->findInt64(kKeyTime, ×tampUs));
283 if (in_buf->range_length() > in_buffer->capacity()) {
284 ALOGW("'%s' received %zu input bytes for buffer of size %zu",
285 mComponentName.c_str(),
286 in_buf->range_length(), in_buffer->capacity());
287 }
288 memcpy(in_buffer->base(), (uint8_t *)in_buf->data() + in_buf->range_offset(),
289 min(in_buf->range_length(), in_buffer->capacity()));
290
291 res = mCodec->queueInputBuffer(
292 in_ix, 0 /* offset */, in_buf->range_length(),
293 timestampUs, 0 /* flags */);
294 if (res != OK) {
295 ALOGI("[%s] failed to queue input buffer #%zu", mComponentName.c_str(), in_ix);
296 me->mState = ERROR;
297 }
298 in_buf->release();
299 }
300 }
301
302 me.unlock();
303 res = mCodec->dequeueOutputBuffer(
304 &out_ix, &out_offset, &out_size, &out_pts,
305 &out_flags, kTimeoutWaitForOutputUs /* timeoutUs */);
306 me.lock();
307 // abort read on stop
308 if (me->mState != STARTED) {
309 if (res == OK) {
310 mCodec->releaseOutputBuffer(out_ix);
311 }
312 return ERROR_END_OF_STREAM;
313 }
314
315 if (res == -EAGAIN) {
316 ALOGD("[%s] did not produce an output buffer. retry count: %d",
317 mComponentName.c_str(), retries);
318 continue;
319 } else if (res == INFO_FORMAT_CHANGED) {
320 if (mCodec->getOutputFormat(&me->mFormat) != OK) {
321 me->mState = ERROR;
322 res = UNKNOWN_ERROR;
323 }
324 return res;
325 } else if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
326 ALOGV("output buffers changed");
327 continue;
328 } else if (res != OK) {
329 me->mState = ERROR;
330 return res;
331 }
332
333 sp<ABuffer> out_buffer;
334 res = mCodec->getOutputBuffer(out_ix, &out_buffer);
335 if (res != OK) {
336 ALOGW("[%s] could not get output buffer #%zu",
337 mComponentName.c_str(), out_ix);
338 me->mState = ERROR;
339 return UNKNOWN_ERROR;
340 }
341 if (out_flags & MediaCodec::BUFFER_FLAG_EOS) {
342 me->mGotOutputEOS = true;
343 // return EOS immediately if last buffer is empty
344 if (out_size == 0) {
345 mCodec->releaseOutputBuffer(out_ix);
346 return ERROR_END_OF_STREAM;
347 }
348 }
349
350 if (mUsingSurface && out_size > 0) {
351 *buffer = new MediaBuffer(0);
352 mCodec->renderOutputBufferAndRelease(out_ix);
353 } else {
354 *buffer = new MediaBuffer(out_size);
355 CHECK_LE(out_buffer->size(), (*buffer)->size());
356 memcpy((*buffer)->data(), out_buffer->data(), out_buffer->size());
357 (*buffer)->meta_data()->setInt64(kKeyTime, out_pts);
358 mCodec->releaseOutputBuffer(out_ix);
359 }
360 return OK;
361 }
362
363 return TIMED_OUT;
364 }
365