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