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