NuPlayerDecoder.cpp revision 7137ec7e005a5a6e3c0edb91cfacf16a31f4bf6a
1/*
2 * Copyright 2014 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 "NuPlayerDecoder"
19#include <utils/Log.h>
20#include <inttypes.h>
21
22#include "NuPlayerCCDecoder.h"
23#include "NuPlayerDecoder.h"
24#include "NuPlayerRenderer.h"
25#include "NuPlayerSource.h"
26
27#include <media/ICrypto.h>
28#include <media/stagefright/foundation/ABuffer.h>
29#include <media/stagefright/foundation/ADebug.h>
30#include <media/stagefright/foundation/AMessage.h>
31#include <media/stagefright/MediaBuffer.h>
32#include <media/stagefright/MediaCodec.h>
33#include <media/stagefright/MediaDefs.h>
34#include <media/stagefright/MediaErrors.h>
35
36#include "avc_utils.h"
37#include "ATSParser.h"
38
39namespace android {
40
41NuPlayer::Decoder::Decoder(
42        const sp<AMessage> &notify,
43        const sp<Source> &source,
44        const sp<Renderer> &renderer,
45        const sp<NativeWindowWrapper> &nativeWindow,
46        const sp<CCDecoder> &ccDecoder)
47    : mNotify(notify),
48      mNativeWindow(nativeWindow),
49      mSource(source),
50      mRenderer(renderer),
51      mCCDecoder(ccDecoder),
52      mSkipRenderingUntilMediaTimeUs(-1ll),
53      mNumFramesTotal(0ll),
54      mNumFramesDropped(0ll),
55      mIsAudio(true),
56      mIsVideoAVC(false),
57      mIsSecure(false),
58      mFormatChangePending(false),
59      mBufferGeneration(0),
60      mPaused(true),
61      mComponentName("decoder") {
62    mCodecLooper = new ALooper;
63    mCodecLooper->setName("NPDecoder-CL");
64    mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
65}
66
67NuPlayer::Decoder::~Decoder() {
68    releaseAndResetMediaBuffers();
69}
70
71void NuPlayer::Decoder::getStats(
72        int64_t *numFramesTotal,
73        int64_t *numFramesDropped) const {
74    *numFramesTotal = mNumFramesTotal;
75    *numFramesDropped = mNumFramesDropped;
76}
77
78void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
79    ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str());
80
81    switch (msg->what()) {
82        case kWhatCodecNotify:
83        {
84            if (!isStaleReply(msg)) {
85                int32_t numInput, numOutput;
86
87                if (!msg->findInt32("input-buffers", &numInput)) {
88                    numInput = INT32_MAX;
89                }
90
91                if (!msg->findInt32("output-buffers", &numOutput)) {
92                    numOutput = INT32_MAX;
93                }
94
95                if (!mPaused) {
96                    while (numInput-- > 0 && handleAnInputBuffer()) {}
97                }
98
99                while (numOutput-- > 0 && handleAnOutputBuffer()) {}
100            }
101
102            requestCodecNotification();
103            break;
104        }
105
106        case kWhatRenderBuffer:
107        {
108            if (!isStaleReply(msg)) {
109                onRenderBuffer(msg);
110            }
111            break;
112        }
113
114        default:
115            DecoderBase::onMessageReceived(msg);
116            break;
117    }
118}
119
120void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
121    CHECK(mCodec == NULL);
122
123    mFormatChangePending = false;
124
125    ++mBufferGeneration;
126
127    AString mime;
128    CHECK(format->findString("mime", &mime));
129
130    mIsAudio = !strncasecmp("audio/", mime.c_str(), 6);
131    mIsVideoAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
132
133    sp<Surface> surface = NULL;
134    if (mNativeWindow != NULL) {
135        surface = mNativeWindow->getSurfaceTextureClient();
136    }
137
138    mComponentName = mime;
139    mComponentName.append(" decoder");
140    ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), surface.get());
141
142    mCodec = MediaCodec::CreateByType(mCodecLooper, mime.c_str(), false /* encoder */);
143    int32_t secure = 0;
144    if (format->findInt32("secure", &secure) && secure != 0) {
145        if (mCodec != NULL) {
146            mCodec->getName(&mComponentName);
147            mComponentName.append(".secure");
148            mCodec->release();
149            ALOGI("[%s] creating", mComponentName.c_str());
150            mCodec = MediaCodec::CreateByComponentName(
151                    mCodecLooper, mComponentName.c_str());
152        }
153    }
154    if (mCodec == NULL) {
155        ALOGE("Failed to create %s%s decoder",
156                (secure ? "secure " : ""), mime.c_str());
157        handleError(UNKNOWN_ERROR);
158        return;
159    }
160    mIsSecure = secure;
161
162    mCodec->getName(&mComponentName);
163
164    status_t err;
165    if (mNativeWindow != NULL) {
166        // disconnect from surface as MediaCodec will reconnect
167        err = native_window_api_disconnect(
168                surface.get(), NATIVE_WINDOW_API_MEDIA);
169        // We treat this as a warning, as this is a preparatory step.
170        // Codec will try to connect to the surface, which is where
171        // any error signaling will occur.
172        ALOGW_IF(err != OK, "failed to disconnect from surface: %d", err);
173    }
174    err = mCodec->configure(
175            format, surface, NULL /* crypto */, 0 /* flags */);
176    if (err != OK) {
177        ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err);
178        mCodec->release();
179        mCodec.clear();
180        handleError(err);
181        return;
182    }
183    rememberCodecSpecificData(format);
184
185    // the following should work in configured state
186    CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat));
187    CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat));
188
189    err = mCodec->start();
190    if (err != OK) {
191        ALOGE("Failed to start %s decoder (err=%d)", mComponentName.c_str(), err);
192        mCodec->release();
193        mCodec.clear();
194        handleError(err);
195        return;
196    }
197
198    // the following should work after start
199    CHECK_EQ((status_t)OK, mCodec->getInputBuffers(&mInputBuffers));
200    releaseAndResetMediaBuffers();
201    CHECK_EQ((status_t)OK, mCodec->getOutputBuffers(&mOutputBuffers));
202    ALOGV("[%s] got %zu input and %zu output buffers",
203            mComponentName.c_str(),
204            mInputBuffers.size(),
205            mOutputBuffers.size());
206
207    if (mRenderer != NULL) {
208        requestCodecNotification();
209    }
210    mPaused = false;
211}
212
213void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) {
214    bool hadNoRenderer = (mRenderer == NULL);
215    mRenderer = renderer;
216    if (hadNoRenderer && mRenderer != NULL) {
217        requestCodecNotification();
218    }
219}
220
221void NuPlayer::Decoder::onGetInputBuffers(
222        Vector<sp<ABuffer> > *dstBuffers) {
223    dstBuffers->clear();
224    for (size_t i = 0; i < mInputBuffers.size(); i++) {
225        dstBuffers->push(mInputBuffers[i]);
226    }
227}
228
229void NuPlayer::Decoder::onResume() {
230    mPaused = false;
231}
232
233void NuPlayer::Decoder::onFlush(bool notifyComplete) {
234    if (mCCDecoder != NULL) {
235        mCCDecoder->flush();
236    }
237
238    if (mRenderer != NULL) {
239        mRenderer->flush(mIsAudio, notifyComplete);
240        mRenderer->signalTimeDiscontinuity();
241    }
242
243    status_t err = OK;
244    if (mCodec != NULL) {
245        err = mCodec->flush();
246        mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator
247        ++mBufferGeneration;
248    }
249
250    if (err != OK) {
251        ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err);
252        handleError(err);
253        // finish with posting kWhatFlushCompleted.
254        // we attempt to release the buffers even if flush fails.
255    }
256    releaseAndResetMediaBuffers();
257
258    if (notifyComplete) {
259        sp<AMessage> notify = mNotify->dup();
260        notify->setInt32("what", kWhatFlushCompleted);
261        notify->post();
262        mPaused = true;
263    }
264}
265
266void NuPlayer::Decoder::onShutdown(bool notifyComplete) {
267    status_t err = OK;
268    if (mCodec != NULL) {
269        err = mCodec->release();
270        mCodec = NULL;
271        ++mBufferGeneration;
272
273        if (mNativeWindow != NULL) {
274            // reconnect to surface as MediaCodec disconnected from it
275            status_t error =
276                    native_window_api_connect(
277                            mNativeWindow->getNativeWindow().get(),
278                            NATIVE_WINDOW_API_MEDIA);
279            ALOGW_IF(error != NO_ERROR,
280                    "[%s] failed to connect to native window, error=%d",
281                    mComponentName.c_str(), error);
282        }
283        mComponentName = "decoder";
284    }
285
286    releaseAndResetMediaBuffers();
287
288    if (err != OK) {
289        ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err);
290        handleError(err);
291        // finish with posting kWhatShutdownCompleted.
292    }
293
294    if (notifyComplete) {
295        sp<AMessage> notify = mNotify->dup();
296        notify->setInt32("what", kWhatShutdownCompleted);
297        notify->post();
298        mPaused = true;
299    }
300}
301
302void NuPlayer::Decoder::doRequestBuffers() {
303    if (mFormatChangePending) {
304        return;
305    }
306    status_t err = OK;
307    while (!mDequeuedInputBuffers.empty()) {
308        size_t bufferIx = *mDequeuedInputBuffers.begin();
309        sp<AMessage> msg = new AMessage();
310        msg->setSize("buffer-ix", bufferIx);
311        err = fetchInputData(msg);
312        if (err != OK) {
313            break;
314        }
315        mDequeuedInputBuffers.erase(mDequeuedInputBuffers.begin());
316
317        if (!mPendingInputMessages.empty()
318                || !onInputBufferFetched(msg)) {
319            mPendingInputMessages.push_back(msg);
320        }
321    }
322
323    if (err == -EWOULDBLOCK
324            && mSource->feedMoreTSData() == OK) {
325        scheduleRequestBuffers();
326    }
327}
328
329void NuPlayer::Decoder::handleError(int32_t err)
330{
331    // We cannot immediately release the codec due to buffers still outstanding
332    // in the renderer.  We signal to the player the error so it can shutdown/release the
333    // decoder after flushing and increment the generation to discard unnecessary messages.
334
335    ++mBufferGeneration;
336
337    sp<AMessage> notify = mNotify->dup();
338    notify->setInt32("what", kWhatError);
339    notify->setInt32("err", err);
340    notify->post();
341}
342
343bool NuPlayer::Decoder::handleAnInputBuffer() {
344    if (mFormatChangePending) {
345        return false;
346    }
347    size_t bufferIx = -1;
348    status_t res = mCodec->dequeueInputBuffer(&bufferIx);
349    ALOGV("[%s] dequeued input: %d",
350            mComponentName.c_str(), res == OK ? (int)bufferIx : res);
351    if (res != OK) {
352        if (res != -EAGAIN) {
353            ALOGE("Failed to dequeue input buffer for %s (err=%d)",
354                    mComponentName.c_str(), res);
355            handleError(res);
356        }
357        return false;
358    }
359
360    CHECK_LT(bufferIx, mInputBuffers.size());
361
362    if (mMediaBuffers[bufferIx] != NULL) {
363        mMediaBuffers[bufferIx]->release();
364        mMediaBuffers.editItemAt(bufferIx) = NULL;
365    }
366    mInputBufferIsDequeued.editItemAt(bufferIx) = true;
367
368    if (!mCSDsToSubmit.isEmpty()) {
369        sp<AMessage> msg = new AMessage();
370        msg->setSize("buffer-ix", bufferIx);
371
372        sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0);
373        ALOGI("[%s] resubmitting CSD", mComponentName.c_str());
374        msg->setBuffer("buffer", buffer);
375        mCSDsToSubmit.removeAt(0);
376        CHECK(onInputBufferFetched(msg));
377        return true;
378    }
379
380    while (!mPendingInputMessages.empty()) {
381        sp<AMessage> msg = *mPendingInputMessages.begin();
382        if (!onInputBufferFetched(msg)) {
383            break;
384        }
385        mPendingInputMessages.erase(mPendingInputMessages.begin());
386    }
387
388    if (!mInputBufferIsDequeued.editItemAt(bufferIx)) {
389        return true;
390    }
391
392    mDequeuedInputBuffers.push_back(bufferIx);
393
394    onRequestInputBuffers();
395    return true;
396}
397
398bool NuPlayer::Decoder::handleAnOutputBuffer() {
399    if (mFormatChangePending) {
400        return false;
401    }
402    size_t bufferIx = -1;
403    size_t offset;
404    size_t size;
405    int64_t timeUs;
406    uint32_t flags;
407    status_t res = mCodec->dequeueOutputBuffer(
408            &bufferIx, &offset, &size, &timeUs, &flags);
409
410    if (res != OK) {
411        ALOGV("[%s] dequeued output: %d", mComponentName.c_str(), res);
412    } else {
413        ALOGV("[%s] dequeued output: %d (time=%lld flags=%" PRIu32 ")",
414                mComponentName.c_str(), (int)bufferIx, timeUs, flags);
415    }
416
417    if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
418        res = mCodec->getOutputBuffers(&mOutputBuffers);
419        if (res != OK) {
420            ALOGE("Failed to get output buffers for %s after INFO event (err=%d)",
421                    mComponentName.c_str(), res);
422            handleError(res);
423            return false;
424        }
425        // NuPlayer ignores this
426        return true;
427    } else if (res == INFO_FORMAT_CHANGED) {
428        sp<AMessage> format = new AMessage();
429        res = mCodec->getOutputFormat(&format);
430        if (res != OK) {
431            ALOGE("Failed to get output format for %s after INFO event (err=%d)",
432                    mComponentName.c_str(), res);
433            handleError(res);
434            return false;
435        }
436
437        if (!mIsAudio) {
438            sp<AMessage> notify = mNotify->dup();
439            notify->setInt32("what", kWhatVideoSizeChanged);
440            notify->setMessage("format", format);
441            notify->post();
442        } else if (mRenderer != NULL) {
443            uint32_t flags;
444            int64_t durationUs;
445            bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
446            if (!hasVideo &&
447                    mSource->getDuration(&durationUs) == OK &&
448                    durationUs
449                        > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
450                flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
451            } else {
452                flags = AUDIO_OUTPUT_FLAG_NONE;
453            }
454
455            mRenderer->openAudioSink(
456                    format, false /* offloadOnly */, hasVideo, flags);
457        }
458        return true;
459    } else if (res == INFO_DISCONTINUITY) {
460        // nothing to do
461        return true;
462    } else if (res != OK) {
463        if (res != -EAGAIN) {
464            ALOGE("Failed to dequeue output buffer for %s (err=%d)",
465                    mComponentName.c_str(), res);
466            handleError(res);
467        }
468        return false;
469    }
470
471    CHECK_LT(bufferIx, mOutputBuffers.size());
472    sp<ABuffer> buffer = mOutputBuffers[bufferIx];
473    buffer->setRange(offset, size);
474    buffer->meta()->clear();
475    buffer->meta()->setInt64("timeUs", timeUs);
476    if (flags & MediaCodec::BUFFER_FLAG_EOS) {
477        buffer->meta()->setInt32("eos", true);
478    }
479    // we do not expect CODECCONFIG or SYNCFRAME for decoder
480
481    sp<AMessage> reply = new AMessage(kWhatRenderBuffer, id());
482    reply->setSize("buffer-ix", bufferIx);
483    reply->setInt32("generation", mBufferGeneration);
484
485    if (mSkipRenderingUntilMediaTimeUs >= 0) {
486        if (timeUs < mSkipRenderingUntilMediaTimeUs) {
487            ALOGV("[%s] dropping buffer at time %lld as requested.",
488                     mComponentName.c_str(), (long long)timeUs);
489
490            reply->post();
491            return true;
492        }
493
494        mSkipRenderingUntilMediaTimeUs = -1;
495    }
496
497    if (mRenderer != NULL) {
498        // send the buffer to renderer.
499        mRenderer->queueBuffer(mIsAudio, buffer, reply);
500        if (flags & MediaCodec::BUFFER_FLAG_EOS) {
501            mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM);
502        }
503    }
504
505    return true;
506}
507
508void NuPlayer::Decoder::releaseAndResetMediaBuffers() {
509    for (size_t i = 0; i < mMediaBuffers.size(); i++) {
510        if (mMediaBuffers[i] != NULL) {
511            mMediaBuffers[i]->release();
512            mMediaBuffers.editItemAt(i) = NULL;
513        }
514    }
515    mMediaBuffers.resize(mInputBuffers.size());
516    for (size_t i = 0; i < mMediaBuffers.size(); i++) {
517        mMediaBuffers.editItemAt(i) = NULL;
518    }
519    mInputBufferIsDequeued.clear();
520    mInputBufferIsDequeued.resize(mInputBuffers.size());
521    for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) {
522        mInputBufferIsDequeued.editItemAt(i) = false;
523    }
524
525    mPendingInputMessages.clear();
526    mDequeuedInputBuffers.clear();
527    mSkipRenderingUntilMediaTimeUs = -1;
528}
529
530void NuPlayer::Decoder::requestCodecNotification() {
531    if (mFormatChangePending) {
532        return;
533    }
534    if (mCodec != NULL) {
535        sp<AMessage> reply = new AMessage(kWhatCodecNotify, id());
536        reply->setInt32("generation", mBufferGeneration);
537        mCodec->requestActivityNotification(reply);
538    }
539}
540
541bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) {
542    int32_t generation;
543    CHECK(msg->findInt32("generation", &generation));
544    return generation != mBufferGeneration;
545}
546
547status_t NuPlayer::Decoder::fetchInputData(sp<AMessage> &reply) {
548    sp<ABuffer> accessUnit;
549    bool dropAccessUnit;
550    do {
551        status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit);
552
553        if (err == -EWOULDBLOCK) {
554            return err;
555        } else if (err != OK) {
556            if (err == INFO_DISCONTINUITY) {
557                int32_t type;
558                CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
559
560                bool formatChange =
561                    (mIsAudio &&
562                     (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
563                    || (!mIsAudio &&
564                            (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
565
566                bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
567
568                ALOGI("%s discontinuity (format=%d, time=%d)",
569                        mIsAudio ? "audio" : "video", formatChange, timeChange);
570
571                bool seamlessFormatChange = false;
572                sp<AMessage> newFormat = mSource->getFormat(mIsAudio);
573                if (formatChange) {
574                    seamlessFormatChange =
575                        supportsSeamlessFormatChange(newFormat);
576                    // treat seamless format change separately
577                    formatChange = !seamlessFormatChange;
578                }
579
580                if (formatChange || timeChange) {
581                    sp<AMessage> msg = mNotify->dup();
582                    msg->setInt32("what", kWhatInputDiscontinuity);
583                    msg->setInt32("formatChange", formatChange);
584                    msg->post();
585                }
586
587                if (formatChange /* not seamless */) {
588                    // must change decoder
589                    // return EOS and wait to be killed
590                    mFormatChangePending = true;
591                    return ERROR_END_OF_STREAM;
592                } else if (timeChange) {
593                    // need to flush
594                    // TODO: Ideally we shouldn't need a flush upon time
595                    // discontinuity, flushing will cause loss of frames.
596                    // We probably should queue a time change marker to the
597                    // output queue, and handles it in renderer instead.
598                    rememberCodecSpecificData(newFormat);
599                    onFlush(false /* notifyComplete */);
600                    err = OK;
601                } else if (seamlessFormatChange) {
602                    // reuse existing decoder and don't flush
603                    rememberCodecSpecificData(newFormat);
604                    err = OK;
605                } else {
606                    // This stream is unaffected by the discontinuity
607                    return -EWOULDBLOCK;
608                }
609            }
610
611            reply->setInt32("err", err);
612            return OK;
613        }
614
615        if (!mIsAudio) {
616            ++mNumFramesTotal;
617        }
618
619        dropAccessUnit = false;
620        if (!mIsAudio
621                && !mIsSecure
622                && mRenderer->getVideoLateByUs() > 100000ll
623                && mIsVideoAVC
624                && !IsAVCReferenceFrame(accessUnit)) {
625            dropAccessUnit = true;
626            ++mNumFramesDropped;
627        }
628    } while (dropAccessUnit);
629
630    // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video");
631#if 0
632    int64_t mediaTimeUs;
633    CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
634    ALOGV("feeding %s input buffer at media time %.2f secs",
635         mIsAudio ? "audio" : "video",
636         mediaTimeUs / 1E6);
637#endif
638
639    if (mCCDecoder != NULL) {
640        mCCDecoder->decode(accessUnit);
641    }
642
643    reply->setBuffer("buffer", accessUnit);
644
645    return OK;
646}
647
648bool NuPlayer::Decoder::onInputBufferFetched(const sp<AMessage> &msg) {
649    size_t bufferIx;
650    CHECK(msg->findSize("buffer-ix", &bufferIx));
651    CHECK_LT(bufferIx, mInputBuffers.size());
652    sp<ABuffer> codecBuffer = mInputBuffers[bufferIx];
653
654    sp<ABuffer> buffer;
655    bool hasBuffer = msg->findBuffer("buffer", &buffer);
656
657    // handle widevine classic source - that fills an arbitrary input buffer
658    MediaBuffer *mediaBuffer = NULL;
659    if (hasBuffer) {
660        mediaBuffer = (MediaBuffer *)(buffer->getMediaBufferBase());
661        if (mediaBuffer != NULL) {
662            // likely filled another buffer than we requested: adjust buffer index
663            size_t ix;
664            for (ix = 0; ix < mInputBuffers.size(); ix++) {
665                const sp<ABuffer> &buf = mInputBuffers[ix];
666                if (buf->data() == mediaBuffer->data()) {
667                    // all input buffers are dequeued on start, hence the check
668                    if (!mInputBufferIsDequeued[ix]) {
669                        ALOGV("[%s] received MediaBuffer for #%zu instead of #%zu",
670                                mComponentName.c_str(), ix, bufferIx);
671                        mediaBuffer->release();
672                        return false;
673                    }
674
675                    // TRICKY: need buffer for the metadata, so instead, set
676                    // codecBuffer to the same (though incorrect) buffer to
677                    // avoid a memcpy into the codecBuffer
678                    codecBuffer = buffer;
679                    codecBuffer->setRange(
680                            mediaBuffer->range_offset(),
681                            mediaBuffer->range_length());
682                    bufferIx = ix;
683                    break;
684                }
685            }
686            CHECK(ix < mInputBuffers.size());
687        }
688    }
689
690    if (buffer == NULL /* includes !hasBuffer */) {
691        int32_t streamErr = ERROR_END_OF_STREAM;
692        CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
693
694        if (streamErr == OK) {
695            /* buffers are returned to hold on to */
696            return true;
697        }
698
699        // attempt to queue EOS
700        status_t err = mCodec->queueInputBuffer(
701                bufferIx,
702                0,
703                0,
704                0,
705                MediaCodec::BUFFER_FLAG_EOS);
706        if (err == OK) {
707            mInputBufferIsDequeued.editItemAt(bufferIx) = false;
708        } else if (streamErr == ERROR_END_OF_STREAM) {
709            streamErr = err;
710            // err will not be ERROR_END_OF_STREAM
711        }
712
713        if (streamErr != ERROR_END_OF_STREAM) {
714            ALOGE("Stream error for %s (err=%d), EOS %s queued",
715                    mComponentName.c_str(),
716                    streamErr,
717                    err == OK ? "successfully" : "unsuccessfully");
718            handleError(streamErr);
719        }
720    } else {
721        sp<AMessage> extra;
722        if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) {
723            int64_t resumeAtMediaTimeUs;
724            if (extra->findInt64(
725                        "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) {
726                ALOGI("[%s] suppressing rendering until %lld us",
727                        mComponentName.c_str(), (long long)resumeAtMediaTimeUs);
728                mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs;
729            }
730        }
731
732        int64_t timeUs = 0;
733        uint32_t flags = 0;
734        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
735
736        int32_t eos, csd;
737        // we do not expect SYNCFRAME for decoder
738        if (buffer->meta()->findInt32("eos", &eos) && eos) {
739            flags |= MediaCodec::BUFFER_FLAG_EOS;
740        } else if (buffer->meta()->findInt32("csd", &csd) && csd) {
741            flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
742        }
743
744        // copy into codec buffer
745        if (buffer != codecBuffer) {
746            CHECK_LE(buffer->size(), codecBuffer->capacity());
747            codecBuffer->setRange(0, buffer->size());
748            memcpy(codecBuffer->data(), buffer->data(), buffer->size());
749        }
750
751        status_t err = mCodec->queueInputBuffer(
752                        bufferIx,
753                        codecBuffer->offset(),
754                        codecBuffer->size(),
755                        timeUs,
756                        flags);
757        if (err != OK) {
758            if (mediaBuffer != NULL) {
759                mediaBuffer->release();
760            }
761            ALOGE("Failed to queue input buffer for %s (err=%d)",
762                    mComponentName.c_str(), err);
763            handleError(err);
764        } else {
765            mInputBufferIsDequeued.editItemAt(bufferIx) = false;
766            if (mediaBuffer != NULL) {
767                CHECK(mMediaBuffers[bufferIx] == NULL);
768                mMediaBuffers.editItemAt(bufferIx) = mediaBuffer;
769            }
770        }
771    }
772    return true;
773}
774
775void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) {
776    status_t err;
777    int32_t render;
778    size_t bufferIx;
779    CHECK(msg->findSize("buffer-ix", &bufferIx));
780
781    if (!mIsAudio) {
782        int64_t timeUs;
783        sp<ABuffer> buffer = mOutputBuffers[bufferIx];
784        buffer->meta()->findInt64("timeUs", &timeUs);
785
786        if (mCCDecoder != NULL && mCCDecoder->isSelected()) {
787            mCCDecoder->display(timeUs);
788        }
789    }
790
791    if (msg->findInt32("render", &render) && render) {
792        int64_t timestampNs;
793        CHECK(msg->findInt64("timestampNs", &timestampNs));
794        err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs);
795    } else {
796        err = mCodec->releaseOutputBuffer(bufferIx);
797    }
798    if (err != OK) {
799        ALOGE("failed to release output buffer for %s (err=%d)",
800                mComponentName.c_str(), err);
801        handleError(err);
802    }
803}
804
805bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(
806        const sp<AMessage> &targetFormat) const {
807    if (targetFormat == NULL) {
808        return true;
809    }
810
811    AString mime;
812    if (!targetFormat->findString("mime", &mime)) {
813        return false;
814    }
815
816    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
817        // field-by-field comparison
818        const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
819        for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
820            int32_t oldVal, newVal;
821            if (!mOutputFormat->findInt32(keys[i], &oldVal) ||
822                    !targetFormat->findInt32(keys[i], &newVal) ||
823                    oldVal != newVal) {
824                return false;
825            }
826        }
827
828        sp<ABuffer> oldBuf, newBuf;
829        if (mOutputFormat->findBuffer("csd-0", &oldBuf) &&
830                targetFormat->findBuffer("csd-0", &newBuf)) {
831            if (oldBuf->size() != newBuf->size()) {
832                return false;
833            }
834            return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size());
835        }
836    }
837    return false;
838}
839
840bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
841    if (mOutputFormat == NULL) {
842        return false;
843    }
844
845    if (targetFormat == NULL) {
846        return true;
847    }
848
849    AString oldMime, newMime;
850    if (!mOutputFormat->findString("mime", &oldMime)
851            || !targetFormat->findString("mime", &newMime)
852            || !(oldMime == newMime)) {
853        return false;
854    }
855
856    bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/"));
857    bool seamless;
858    if (audio) {
859        seamless = supportsSeamlessAudioFormatChange(targetFormat);
860    } else {
861        int32_t isAdaptive;
862        seamless = (mCodec != NULL &&
863                mInputFormat->findInt32("adaptive-playback", &isAdaptive) &&
864                isAdaptive);
865    }
866
867    ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str());
868    return seamless;
869}
870
871void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
872    if (format == NULL) {
873        return;
874    }
875    mCSDsForCurrentFormat.clear();
876    for (int32_t i = 0; ; ++i) {
877        AString tag = "csd-";
878        tag.append(i);
879        sp<ABuffer> buffer;
880        if (!format->findBuffer(tag.c_str(), &buffer)) {
881            break;
882        }
883        mCSDsForCurrentFormat.push(buffer);
884    }
885}
886
887}  // namespace android
888
889