• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &timestampUs));
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