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