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