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