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