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