NuPlayerDecoder.cpp revision 1de1e25cba872bd4c077c2e394f8ca9c70b65856
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 (index >= mInputBuffers.size()) {
418        for (size_t i = mInputBuffers.size(); i <= index; ++i) {
419            mInputBuffers.add();
420            mMediaBuffers.add();
421            mInputBufferIsDequeued.add();
422            mMediaBuffers.editItemAt(i) = NULL;
423            mInputBufferIsDequeued.editItemAt(i) = false;
424        }
425    }
426    mInputBuffers.editItemAt(index) = buffer;
427
428    //CHECK_LT(bufferIx, mInputBuffers.size());
429
430    if (mMediaBuffers[index] != NULL) {
431        mMediaBuffers[index]->release();
432        mMediaBuffers.editItemAt(index) = NULL;
433    }
434    mInputBufferIsDequeued.editItemAt(index) = true;
435
436    if (!mCSDsToSubmit.isEmpty()) {
437        sp<AMessage> msg = new AMessage();
438        msg->setSize("buffer-ix", index);
439
440        sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0);
441        ALOGI("[%s] resubmitting CSD", mComponentName.c_str());
442        msg->setBuffer("buffer", buffer);
443        mCSDsToSubmit.removeAt(0);
444        CHECK(onInputBufferFetched(msg));
445        return true;
446    }
447
448    while (!mPendingInputMessages.empty()) {
449        sp<AMessage> msg = *mPendingInputMessages.begin();
450        if (!onInputBufferFetched(msg)) {
451            break;
452        }
453        mPendingInputMessages.erase(mPendingInputMessages.begin());
454    }
455
456    if (!mInputBufferIsDequeued.editItemAt(index)) {
457        return true;
458    }
459
460    mDequeuedInputBuffers.push_back(index);
461
462    onRequestInputBuffers();
463    return true;
464}
465
466bool NuPlayer::Decoder::handleAnOutputBuffer(
467        size_t index,
468        size_t offset,
469        size_t size,
470        int64_t timeUs,
471        int32_t flags) {
472//    CHECK_LT(bufferIx, mOutputBuffers.size());
473    sp<ABuffer> buffer;
474    mCodec->getOutputBuffer(index, &buffer);
475
476    if (index >= mOutputBuffers.size()) {
477        for (size_t i = mOutputBuffers.size(); i <= index; ++i) {
478            mOutputBuffers.add();
479        }
480    }
481
482    mOutputBuffers.editItemAt(index) = buffer;
483
484    buffer->setRange(offset, size);
485    buffer->meta()->clear();
486    buffer->meta()->setInt64("timeUs", timeUs);
487
488    bool eos = flags & MediaCodec::BUFFER_FLAG_EOS;
489    // we do not expect CODECCONFIG or SYNCFRAME for decoder
490
491    sp<AMessage> reply = new AMessage(kWhatRenderBuffer, this);
492    reply->setSize("buffer-ix", index);
493    reply->setInt32("generation", mBufferGeneration);
494
495    if (eos) {
496        ALOGI("[%s] saw output EOS", mIsAudio ? "audio" : "video");
497
498        buffer->meta()->setInt32("eos", true);
499        reply->setInt32("eos", true);
500    } else if (mSkipRenderingUntilMediaTimeUs >= 0) {
501        if (timeUs < mSkipRenderingUntilMediaTimeUs) {
502            ALOGV("[%s] dropping buffer at time %lld as requested.",
503                     mComponentName.c_str(), (long long)timeUs);
504
505            reply->post();
506            return true;
507        }
508
509        mSkipRenderingUntilMediaTimeUs = -1;
510    }
511
512    // wait until 1st frame comes out to signal resume complete
513    notifyResumeCompleteIfNecessary();
514
515    if (mRenderer != NULL) {
516        // send the buffer to renderer.
517        mRenderer->queueBuffer(mIsAudio, buffer, reply);
518        if (eos && !isDiscontinuityPending()) {
519            mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM);
520        }
521    }
522
523    return true;
524}
525
526void NuPlayer::Decoder::handleOutputFormatChange(const sp<AMessage> &format) {
527    if (!mIsAudio) {
528        sp<AMessage> notify = mNotify->dup();
529        notify->setInt32("what", kWhatVideoSizeChanged);
530        notify->setMessage("format", format);
531        notify->post();
532    } else if (mRenderer != NULL) {
533        uint32_t flags;
534        int64_t durationUs;
535        bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
536        if (!hasVideo &&
537                mSource->getDuration(&durationUs) == OK &&
538                durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
539            flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
540        } else {
541            flags = AUDIO_OUTPUT_FLAG_NONE;
542        }
543
544        mRenderer->openAudioSink(
545                format, false /* offloadOnly */, hasVideo, flags, NULL /* isOffloaed */);
546    }
547}
548
549void NuPlayer::Decoder::releaseAndResetMediaBuffers() {
550    for (size_t i = 0; i < mMediaBuffers.size(); i++) {
551        if (mMediaBuffers[i] != NULL) {
552            mMediaBuffers[i]->release();
553            mMediaBuffers.editItemAt(i) = NULL;
554        }
555    }
556    mMediaBuffers.resize(mInputBuffers.size());
557    for (size_t i = 0; i < mMediaBuffers.size(); i++) {
558        mMediaBuffers.editItemAt(i) = NULL;
559    }
560    mInputBufferIsDequeued.clear();
561    mInputBufferIsDequeued.resize(mInputBuffers.size());
562    for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) {
563        mInputBufferIsDequeued.editItemAt(i) = false;
564    }
565
566    mPendingInputMessages.clear();
567    mDequeuedInputBuffers.clear();
568    mSkipRenderingUntilMediaTimeUs = -1;
569}
570
571void NuPlayer::Decoder::requestCodecNotification() {
572    if (mCodec != NULL) {
573        sp<AMessage> reply = new AMessage(kWhatCodecNotify, this);
574        reply->setInt32("generation", mBufferGeneration);
575        mCodec->requestActivityNotification(reply);
576    }
577}
578
579bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) {
580    int32_t generation;
581    CHECK(msg->findInt32("generation", &generation));
582    return generation != mBufferGeneration;
583}
584
585status_t NuPlayer::Decoder::fetchInputData(sp<AMessage> &reply) {
586    sp<ABuffer> accessUnit;
587    bool dropAccessUnit;
588    do {
589        status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit);
590
591        if (err == -EWOULDBLOCK) {
592            return err;
593        } else if (err != OK) {
594            if (err == INFO_DISCONTINUITY) {
595                int32_t type;
596                CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
597
598                bool formatChange =
599                    (mIsAudio &&
600                     (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
601                    || (!mIsAudio &&
602                            (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
603
604                bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
605
606                ALOGI("%s discontinuity (format=%d, time=%d)",
607                        mIsAudio ? "audio" : "video", formatChange, timeChange);
608
609                bool seamlessFormatChange = false;
610                sp<AMessage> newFormat = mSource->getFormat(mIsAudio);
611                if (formatChange) {
612                    seamlessFormatChange =
613                        supportsSeamlessFormatChange(newFormat);
614                    // treat seamless format change separately
615                    formatChange = !seamlessFormatChange;
616                }
617
618                // For format or time change, return EOS to queue EOS input,
619                // then wait for EOS on output.
620                if (formatChange /* not seamless */) {
621                    mFormatChangePending = true;
622                    err = ERROR_END_OF_STREAM;
623                } else if (timeChange) {
624                    rememberCodecSpecificData(newFormat);
625                    mTimeChangePending = true;
626                    err = ERROR_END_OF_STREAM;
627                } else if (seamlessFormatChange) {
628                    // reuse existing decoder and don't flush
629                    rememberCodecSpecificData(newFormat);
630                    continue;
631                } else {
632                    // This stream is unaffected by the discontinuity
633                    return -EWOULDBLOCK;
634                }
635            }
636
637            // reply should only be returned without a buffer set
638            // when there is an error (including EOS)
639            CHECK(err != OK);
640
641            reply->setInt32("err", err);
642            return ERROR_END_OF_STREAM;
643        }
644
645        if (!mIsAudio) {
646            ++mNumFramesTotal;
647        }
648
649        dropAccessUnit = false;
650        if (!mIsAudio
651                && !mIsSecure
652                && mRenderer->getVideoLateByUs() > 100000ll
653                && mIsVideoAVC
654                && !IsAVCReferenceFrame(accessUnit)) {
655            dropAccessUnit = true;
656            ++mNumFramesDropped;
657        }
658    } while (dropAccessUnit);
659
660    // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video");
661#if 0
662    int64_t mediaTimeUs;
663    CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
664    ALOGV("[%s] feeding input buffer at media time %.3f",
665         mIsAudio ? "audio" : "video",
666         mediaTimeUs / 1E6);
667#endif
668
669    if (mCCDecoder != NULL) {
670        mCCDecoder->decode(accessUnit);
671    }
672
673    reply->setBuffer("buffer", accessUnit);
674
675    return OK;
676}
677
678bool NuPlayer::Decoder::onInputBufferFetched(const sp<AMessage> &msg) {
679    size_t bufferIx;
680    CHECK(msg->findSize("buffer-ix", &bufferIx));
681    CHECK_LT(bufferIx, mInputBuffers.size());
682    sp<ABuffer> codecBuffer = mInputBuffers[bufferIx];
683
684    sp<ABuffer> buffer;
685    bool hasBuffer = msg->findBuffer("buffer", &buffer);
686
687    // handle widevine classic source - that fills an arbitrary input buffer
688    MediaBuffer *mediaBuffer = NULL;
689    if (hasBuffer) {
690        mediaBuffer = (MediaBuffer *)(buffer->getMediaBufferBase());
691        if (mediaBuffer != NULL) {
692            // likely filled another buffer than we requested: adjust buffer index
693            size_t ix;
694            for (ix = 0; ix < mInputBuffers.size(); ix++) {
695                const sp<ABuffer> &buf = mInputBuffers[ix];
696                if (buf->data() == mediaBuffer->data()) {
697                    // all input buffers are dequeued on start, hence the check
698                    if (!mInputBufferIsDequeued[ix]) {
699                        ALOGV("[%s] received MediaBuffer for #%zu instead of #%zu",
700                                mComponentName.c_str(), ix, bufferIx);
701                        mediaBuffer->release();
702                        return false;
703                    }
704
705                    // TRICKY: need buffer for the metadata, so instead, set
706                    // codecBuffer to the same (though incorrect) buffer to
707                    // avoid a memcpy into the codecBuffer
708                    codecBuffer = buffer;
709                    codecBuffer->setRange(
710                            mediaBuffer->range_offset(),
711                            mediaBuffer->range_length());
712                    bufferIx = ix;
713                    break;
714                }
715            }
716            CHECK(ix < mInputBuffers.size());
717        }
718    }
719
720    if (buffer == NULL /* includes !hasBuffer */) {
721        int32_t streamErr = ERROR_END_OF_STREAM;
722        CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
723
724        CHECK(streamErr != OK);
725
726        // attempt to queue EOS
727        status_t err = mCodec->queueInputBuffer(
728                bufferIx,
729                0,
730                0,
731                0,
732                MediaCodec::BUFFER_FLAG_EOS);
733        if (err == OK) {
734            mInputBufferIsDequeued.editItemAt(bufferIx) = false;
735        } else if (streamErr == ERROR_END_OF_STREAM) {
736            streamErr = err;
737            // err will not be ERROR_END_OF_STREAM
738        }
739
740        if (streamErr != ERROR_END_OF_STREAM) {
741            ALOGE("Stream error for %s (err=%d), EOS %s queued",
742                    mComponentName.c_str(),
743                    streamErr,
744                    err == OK ? "successfully" : "unsuccessfully");
745            handleError(streamErr);
746        }
747    } else {
748        sp<AMessage> extra;
749        if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) {
750            int64_t resumeAtMediaTimeUs;
751            if (extra->findInt64(
752                        "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) {
753                ALOGI("[%s] suppressing rendering until %lld us",
754                        mComponentName.c_str(), (long long)resumeAtMediaTimeUs);
755                mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs;
756            }
757        }
758
759        int64_t timeUs = 0;
760        uint32_t flags = 0;
761        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
762
763        int32_t eos, csd;
764        // we do not expect SYNCFRAME for decoder
765        if (buffer->meta()->findInt32("eos", &eos) && eos) {
766            flags |= MediaCodec::BUFFER_FLAG_EOS;
767        } else if (buffer->meta()->findInt32("csd", &csd) && csd) {
768            flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
769        }
770
771        // copy into codec buffer
772        if (buffer != codecBuffer) {
773            CHECK_LE(buffer->size(), codecBuffer->capacity());
774            codecBuffer->setRange(0, buffer->size());
775            memcpy(codecBuffer->data(), buffer->data(), buffer->size());
776        }
777
778        status_t err = mCodec->queueInputBuffer(
779                        bufferIx,
780                        codecBuffer->offset(),
781                        codecBuffer->size(),
782                        timeUs,
783                        flags);
784        if (err != OK) {
785            if (mediaBuffer != NULL) {
786                mediaBuffer->release();
787            }
788            ALOGE("Failed to queue input buffer for %s (err=%d)",
789                    mComponentName.c_str(), err);
790            handleError(err);
791        } else {
792            mInputBufferIsDequeued.editItemAt(bufferIx) = false;
793            if (mediaBuffer != NULL) {
794                CHECK(mMediaBuffers[bufferIx] == NULL);
795                mMediaBuffers.editItemAt(bufferIx) = mediaBuffer;
796            }
797        }
798    }
799    return true;
800}
801
802void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) {
803    status_t err;
804    int32_t render;
805    size_t bufferIx;
806    int32_t eos;
807    CHECK(msg->findSize("buffer-ix", &bufferIx));
808
809    if (!mIsAudio) {
810        int64_t timeUs;
811        sp<ABuffer> buffer = mOutputBuffers[bufferIx];
812        buffer->meta()->findInt64("timeUs", &timeUs);
813
814        if (mCCDecoder != NULL && mCCDecoder->isSelected()) {
815            mCCDecoder->display(timeUs);
816        }
817    }
818
819    if (msg->findInt32("render", &render) && render) {
820        int64_t timestampNs;
821        CHECK(msg->findInt64("timestampNs", &timestampNs));
822        err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs);
823    } else {
824        err = mCodec->releaseOutputBuffer(bufferIx);
825    }
826    if (err != OK) {
827        ALOGE("failed to release output buffer for %s (err=%d)",
828                mComponentName.c_str(), err);
829        handleError(err);
830    }
831    if (msg->findInt32("eos", &eos) && eos
832            && isDiscontinuityPending()) {
833        finishHandleDiscontinuity(true /* flushOnTimeChange */);
834    }
835}
836
837bool NuPlayer::Decoder::isDiscontinuityPending() const {
838    return mFormatChangePending || mTimeChangePending;
839}
840
841void NuPlayer::Decoder::finishHandleDiscontinuity(bool flushOnTimeChange) {
842    ALOGV("finishHandleDiscontinuity: format %d, time %d, flush %d",
843            mFormatChangePending, mTimeChangePending, flushOnTimeChange);
844
845    // If we have format change, pause and wait to be killed;
846    // If we have time change only, flush and restart fetching.
847
848    if (mFormatChangePending) {
849        mPaused = true;
850    } else if (mTimeChangePending) {
851        if (flushOnTimeChange) {
852            doFlush(false /* notifyComplete */);
853            signalResume(false /* notifyComplete */);
854        }
855    }
856
857    // Notify NuPlayer to either shutdown decoder, or rescan sources
858    sp<AMessage> msg = mNotify->dup();
859    msg->setInt32("what", kWhatInputDiscontinuity);
860    msg->setInt32("formatChange", mFormatChangePending);
861    msg->post();
862
863    mFormatChangePending = false;
864    mTimeChangePending = false;
865}
866
867bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(
868        const sp<AMessage> &targetFormat) const {
869    if (targetFormat == NULL) {
870        return true;
871    }
872
873    AString mime;
874    if (!targetFormat->findString("mime", &mime)) {
875        return false;
876    }
877
878    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
879        // field-by-field comparison
880        const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
881        for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
882            int32_t oldVal, newVal;
883            if (!mInputFormat->findInt32(keys[i], &oldVal) ||
884                    !targetFormat->findInt32(keys[i], &newVal) ||
885                    oldVal != newVal) {
886                return false;
887            }
888        }
889
890        sp<ABuffer> oldBuf, newBuf;
891        if (mInputFormat->findBuffer("csd-0", &oldBuf) &&
892                targetFormat->findBuffer("csd-0", &newBuf)) {
893            if (oldBuf->size() != newBuf->size()) {
894                return false;
895            }
896            return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size());
897        }
898    }
899    return false;
900}
901
902bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
903    if (mInputFormat == NULL) {
904        return false;
905    }
906
907    if (targetFormat == NULL) {
908        return true;
909    }
910
911    AString oldMime, newMime;
912    if (!mInputFormat->findString("mime", &oldMime)
913            || !targetFormat->findString("mime", &newMime)
914            || !(oldMime == newMime)) {
915        return false;
916    }
917
918    bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/"));
919    bool seamless;
920    if (audio) {
921        seamless = supportsSeamlessAudioFormatChange(targetFormat);
922    } else {
923        int32_t isAdaptive;
924        seamless = (mCodec != NULL &&
925                mInputFormat->findInt32("adaptive-playback", &isAdaptive) &&
926                isAdaptive);
927    }
928
929    ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str());
930    return seamless;
931}
932
933void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
934    if (format == NULL) {
935        return;
936    }
937    mCSDsForCurrentFormat.clear();
938    for (int32_t i = 0; ; ++i) {
939        AString tag = "csd-";
940        tag.append(i);
941        sp<ABuffer> buffer;
942        if (!format->findBuffer(tag.c_str(), &buffer)) {
943            break;
944        }
945        mCSDsForCurrentFormat.push(buffer);
946    }
947}
948
949void NuPlayer::Decoder::notifyResumeCompleteIfNecessary() {
950    if (mResumePending) {
951        mResumePending = false;
952
953        sp<AMessage> notify = mNotify->dup();
954        notify->setInt32("what", kWhatResumeCompleted);
955        notify->post();
956    }
957}
958
959}  // namespace android
960
961