NuPlayerDecoder.cpp revision 216f0177cbfa0d8e911d64fc17ccbb5100ad87b4
11ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck/*
21ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * Copyright 2014 The Android Open Source Project
31ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck *
41ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * Licensed under the Apache License, Version 2.0 (the "License");
51ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * you may not use this file except in compliance with the License.
61ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * You may obtain a copy of the License at
71ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck *
81ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck *      http://www.apache.org/licenses/LICENSE-2.0
91ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck *
101ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * Unless required by applicable law or agreed to in writing, software
111ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * distributed under the License is distributed on an "AS IS" BASIS,
121ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * See the License for the specific language governing permissions and
141ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck * limitations under the License.
151ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck */
161ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
171ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck//#define LOG_NDEBUG 0
181ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#define LOG_TAG "NuPlayerDecoder"
191ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include <utils/Log.h>
201ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include <inttypes.h>
211ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
221ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include "NuPlayerCCDecoder.h"
231ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include "NuPlayerDecoder.h"
241ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include "NuPlayerRenderer.h"
251ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include "NuPlayerSource.h"
261ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
271ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include <cutils/properties.h>
281ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include <media/ICrypto.h>
291ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include <media/stagefright/foundation/ABuffer.h>
301ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include <media/stagefright/foundation/ADebug.h>
311ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include <media/stagefright/foundation/AMessage.h>
321ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include <media/stagefright/MediaBuffer.h>
331ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include <media/stagefright/MediaCodec.h>
341ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include <media/stagefright/MediaDefs.h>
35afb052142a53602ee7b3debb6a3b871de21feac0John Reck#include <media/stagefright/MediaErrors.h>
361ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
371ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include <gui/Surface.h>
381ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
391ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include "avc_utils.h"
401ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck#include "ATSParser.h"
411ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
421ed723723d9e42a064d54799cc24bdc24891e44dJohn Recknamespace android {
43afb052142a53602ee7b3debb6a3b871de21feac0John Reck
441ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckstatic inline bool getAudioDeepBufferSetting() {
451ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    return property_get_bool("media.stagefright.audio.deep", false /* default_value */);
461ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
471ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
481ed723723d9e42a064d54799cc24bdc24891e44dJohn ReckNuPlayer::Decoder::Decoder(
491ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        const sp<AMessage> &notify,
501ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        const sp<Source> &source,
511ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        pid_t pid,
521ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        const sp<Renderer> &renderer,
531ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        const sp<Surface> &surface,
541ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        const sp<CCDecoder> &ccDecoder)
5581a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik    : DecoderBase(notify),
5681a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik      mSurface(surface),
571ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck      mSource(source),
581ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck      mRenderer(renderer),
591ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck      mCCDecoder(ccDecoder),
601ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck      mPid(pid),
611ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck      mSkipRenderingUntilMediaTimeUs(-1ll),
621ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck      mNumFramesTotal(0ll),
631ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck      mNumInputFramesDropped(0ll),
641ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck      mNumOutputFramesDropped(0ll),
651ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck      mVideoWidth(0),
661ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck      mVideoHeight(0),
671ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck      mIsAudio(true),
6881a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik      mIsVideoAVC(false),
691ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck      mIsSecure(false),
701ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck      mFormatChangePending(false),
711ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck      mTimeChangePending(false),
7281a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik      mPaused(true),
731ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck      mResumePending(false),
7481a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik      mComponentName("decoder") {
751ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mCodecLooper = new ALooper;
761ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mCodecLooper->setName("NPDecoder-CL");
771ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
7881a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik}
7981a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik
801ed723723d9e42a064d54799cc24bdc24891e44dJohn ReckNuPlayer::Decoder::~Decoder() {
811ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mCodec->release();
821ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    releaseAndResetMediaBuffers();
831ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
841ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
851ed723723d9e42a064d54799cc24bdc24891e44dJohn Recksp<AMessage> NuPlayer::Decoder::getStats() const {
861ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mStats->setInt64("frames-total", mNumFramesTotal);
871ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mStats->setInt64("frames-dropped-input", mNumInputFramesDropped);
881ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mStats->setInt64("frames-dropped-output", mNumOutputFramesDropped);
891ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    return mStats;
901ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
911ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
921ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckstatus_t NuPlayer::Decoder::setVideoSurface(const sp<Surface> &surface) {
931ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (surface == NULL || ADebug::isExperimentEnabled("legacy-setsurface")) {
941ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        return BAD_VALUE;
951ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
961ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
971ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, this);
981ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
991ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    msg->setObject("surface", surface);
1001ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    sp<AMessage> response;
1011ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    status_t err = msg->postAndAwaitResponse(&response);
1021ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (err == OK && response != NULL) {
1031ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        CHECK(response->findInt32("err", &err));
1041ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
1051ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    return err;
1061ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
1071ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1081ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckvoid NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) {
1091ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str());
1101ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1111ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    switch (msg->what()) {
1121ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        case kWhatCodecNotify:
113afb052142a53602ee7b3debb6a3b871de21feac0John Reck        {
1141ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            int32_t cbID;
1151ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            CHECK(msg->findInt32("callbackID", &cbID));
1161ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1171ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            ALOGV("[%s] kWhatCodecNotify: cbID = %d, paused = %d",
1181ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    mIsAudio ? "audio" : "video", cbID, mPaused);
1191ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1201ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            if (mPaused) {
1211ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                break;
1221ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            }
123b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck
124b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            switch (cbID) {
125b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                case MediaCodec::CB_INPUT_AVAILABLE:
126b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                {
127b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                    int32_t index;
1281ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    CHECK(msg->findInt32("index", &index));
1291ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1301ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    handleAnInputBuffer(index);
1311ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    break;
1321ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                }
13381a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik
1341ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                case MediaCodec::CB_OUTPUT_AVAILABLE:
1351ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                {
1361ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    int32_t index;
1371ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    size_t offset;
1381ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    size_t size;
13925c8d5b1c2d1405e2a8afa857713af072bedad53Chris Craik                    int64_t timeUs;
1401ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    int32_t flags;
1411ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1421ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    CHECK(msg->findInt32("index", &index));
1431ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    CHECK(msg->findSize("offset", &offset));
1441ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    CHECK(msg->findSize("size", &size));
1451ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    CHECK(msg->findInt64("timeUs", &timeUs));
1461ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    CHECK(msg->findInt32("flags", &flags));
1471ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1481ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    handleAnOutputBuffer(index, offset, size, timeUs, flags);
1491ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    break;
1501ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                }
1511ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1521ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:
1531ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                {
1541ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    sp<AMessage> format;
155afb052142a53602ee7b3debb6a3b871de21feac0John Reck                    CHECK(msg->findMessage("format", &format));
1561ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1571ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    handleOutputFormatChange(format);
1581ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    break;
1591ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                }
1601ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1611ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                case MediaCodec::CB_ERROR:
1621ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                {
1631ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    status_t err;
1641ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    CHECK(msg->findInt32("err", &err));
1651ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    ALOGE("Decoder (%s) reported error : 0x%x",
1661ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                            mIsAudio ? "audio" : "video", err);
1671ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1681ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    handleError(err);
1691ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    break;
1707df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck                }
1711ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1721ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                default:
1731ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                {
1741ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    TRESPASS();
1751ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    break;
1761ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                }
1771ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            }
1781ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1791ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            break;
1801ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        }
1811ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
1821ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        case kWhatRenderBuffer:
1831ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        {
1841ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            if (!isStaleReply(msg)) {
1851ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                onRenderBuffer(msg);
1861ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            }
1871ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            break;
1881ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        }
1891ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
190b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        case kWhatSetVideoSurface:
191b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck        {
192b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            sp<AReplyToken> replyID;
193b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            CHECK(msg->senderAwaitsResponse(&replyID));
194b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck
1957df9ff2a08fd4bbd9b2e734a357cffcf64675df9John Reck            sp<RefBase> obj;
196b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            CHECK(msg->findObject("surface", &obj));
197b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            sp<Surface> surface = static_cast<Surface *>(obj.get()); // non-null
198b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            int32_t err = INVALID_OPERATION;
199b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            // NOTE: in practice mSurface is always non-null, but checking here for completeness
200b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            if (mCodec != NULL && mSurface != NULL) {
201b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                // TODO: once AwesomePlayer is removed, remove this automatic connecting
202b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                // to the surface by MediaPlayerService.
203b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                //
204b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                // at this point MediaPlayerService::client has already connected to the
205b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                // surface, which MediaCodec does not expect
206b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                err = native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
207b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                if (err == OK) {
208b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                    err = mCodec->setSurface(surface);
209b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                    ALOGI_IF(err, "codec setSurface returned: %d", err);
210b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                    if (err == OK) {
211b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                        // reconnect to the old surface as MPS::Client will expect to
212b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                        // be able to disconnect from it.
213b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                        (void)native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
214b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                        mSurface = surface;
215b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                    }
216b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                }
217b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                if (err != OK) {
218b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                    // reconnect to the new surface on error as MPS::Client will expect to
219b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                    // be able to disconnect from it.
220b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck                    (void)native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2211ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                }
222b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            }
223b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck
224b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            sp<AMessage> response = new AMessage;
225b5bc454870c8b7df88a633b18c4c6499361c3a08John Reck            response->setInt32("err", err);
2261ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            response->postReply(replyID);
2271ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            break;
2281ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        }
2291ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2301ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        default:
2311ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            DecoderBase::onMessageReceived(msg);
2321ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            break;
2331ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
2341ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck}
2351ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2361ed723723d9e42a064d54799cc24bdc24891e44dJohn Reckvoid NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) {
23781a1d2a15927b06b84359f839ab03ac8a20970bdChris Craik    CHECK(mCodec == NULL);
2381ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2391ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mFormatChangePending = false;
2401ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mTimeChangePending = false;
2411ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2421ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    ++mBufferGeneration;
2431ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2441ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    AString mime;
2451ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    CHECK(format->findString("mime", &mime));
2461ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2471ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mIsAudio = !strncasecmp("audio/", mime.c_str(), 6);
2481ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mIsVideoAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
2491ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2501ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mComponentName = mime;
2511ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mComponentName.append(" decoder");
2521ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), mSurface.get());
2531ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck
2541ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    mCodec = MediaCodec::CreateByType(
2551ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            mCodecLooper, mime.c_str(), false /* encoder */, NULL /* err */, mPid);
2561ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    int32_t secure = 0;
2571ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (format->findInt32("secure", &secure) && secure != 0) {
2581ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        if (mCodec != NULL) {
2591ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            mCodec->getName(&mComponentName);
2601ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            mComponentName.append(".secure");
2611ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            mCodec->release();
2621ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            ALOGI("[%s] creating", mComponentName.c_str());
2631ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck            mCodec = MediaCodec::CreateByComponentName(
2641ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                    mCodecLooper, mComponentName.c_str(), NULL /* err */, mPid);
2651ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        }
2661ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    }
2671ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck    if (mCodec == NULL) {
2681ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck        ALOGE("Failed to create %s%s decoder",
2691ed723723d9e42a064d54799cc24bdc24891e44dJohn Reck                (secure ? "secure " : ""), mime.c_str());
270        handleError(UNKNOWN_ERROR);
271        return;
272    }
273    mIsSecure = secure;
274
275    mCodec->getName(&mComponentName);
276
277    status_t err;
278    if (mSurface != NULL) {
279        // disconnect from surface as MediaCodec will reconnect
280        err = native_window_api_disconnect(
281                mSurface.get(), NATIVE_WINDOW_API_MEDIA);
282        // We treat this as a warning, as this is a preparatory step.
283        // Codec will try to connect to the surface, which is where
284        // any error signaling will occur.
285        ALOGW_IF(err != OK, "failed to disconnect from surface: %d", err);
286    }
287    err = mCodec->configure(
288            format, mSurface, NULL /* crypto */, 0 /* flags */);
289    if (err != OK) {
290        ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err);
291        mCodec->release();
292        mCodec.clear();
293        handleError(err);
294        return;
295    }
296    rememberCodecSpecificData(format);
297
298    // the following should work in configured state
299    CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat));
300    CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat));
301
302    mStats->setString("mime", mime.c_str());
303    mStats->setString("component-name", mComponentName.c_str());
304
305    if (!mIsAudio) {
306        int32_t width, height;
307        if (mOutputFormat->findInt32("width", &width)
308                && mOutputFormat->findInt32("height", &height)) {
309            mStats->setInt32("width", width);
310            mStats->setInt32("height", height);
311        }
312    }
313
314    sp<AMessage> reply = new AMessage(kWhatCodecNotify, this);
315    mCodec->setCallback(reply);
316
317    err = mCodec->start();
318    if (err != OK) {
319        ALOGE("Failed to start %s decoder (err=%d)", mComponentName.c_str(), err);
320        mCodec->release();
321        mCodec.clear();
322        handleError(err);
323        return;
324    }
325
326    releaseAndResetMediaBuffers();
327
328    mPaused = false;
329    mResumePending = false;
330}
331
332void NuPlayer::Decoder::onSetParameters(const sp<AMessage> &params) {
333    if (mCodec == NULL) {
334        ALOGW("onSetParameters called before codec is created.");
335        return;
336    }
337    mCodec->setParameters(params);
338}
339
340void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) {
341    bool hadNoRenderer = (mRenderer == NULL);
342    mRenderer = renderer;
343    if (hadNoRenderer && mRenderer != NULL) {
344        // this means that the widevine legacy source is ready
345        onRequestInputBuffers();
346    }
347}
348
349void NuPlayer::Decoder::onGetInputBuffers(
350        Vector<sp<ABuffer> > *dstBuffers) {
351    CHECK_EQ((status_t)OK, mCodec->getWidevineLegacyBuffers(dstBuffers));
352}
353
354void NuPlayer::Decoder::onResume(bool notifyComplete) {
355    mPaused = false;
356
357    if (notifyComplete) {
358        mResumePending = true;
359    }
360    mCodec->start();
361}
362
363void NuPlayer::Decoder::doFlush(bool notifyComplete) {
364    if (mCCDecoder != NULL) {
365        mCCDecoder->flush();
366    }
367
368    if (mRenderer != NULL) {
369        mRenderer->flush(mIsAudio, notifyComplete);
370        mRenderer->signalTimeDiscontinuity();
371    }
372
373    status_t err = OK;
374    if (mCodec != NULL) {
375        err = mCodec->flush();
376        mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator
377        ++mBufferGeneration;
378    }
379
380    if (err != OK) {
381        ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err);
382        handleError(err);
383        // finish with posting kWhatFlushCompleted.
384        // we attempt to release the buffers even if flush fails.
385    }
386    releaseAndResetMediaBuffers();
387    mPaused = true;
388}
389
390
391void NuPlayer::Decoder::onFlush() {
392    doFlush(true);
393
394    if (isDiscontinuityPending()) {
395        // This could happen if the client starts seeking/shutdown
396        // after we queued an EOS for discontinuities.
397        // We can consider discontinuity handled.
398        finishHandleDiscontinuity(false /* flushOnTimeChange */);
399    }
400
401    sp<AMessage> notify = mNotify->dup();
402    notify->setInt32("what", kWhatFlushCompleted);
403    notify->post();
404}
405
406void NuPlayer::Decoder::onShutdown(bool notifyComplete) {
407    status_t err = OK;
408
409    // if there is a pending resume request, notify complete now
410    notifyResumeCompleteIfNecessary();
411
412    if (mCodec != NULL) {
413        err = mCodec->release();
414        mCodec = NULL;
415        ++mBufferGeneration;
416
417        if (mSurface != NULL) {
418            // reconnect to surface as MediaCodec disconnected from it
419            status_t error =
420                    native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
421            ALOGW_IF(error != NO_ERROR,
422                    "[%s] failed to connect to native window, error=%d",
423                    mComponentName.c_str(), error);
424        }
425        mComponentName = "decoder";
426    }
427
428    releaseAndResetMediaBuffers();
429
430    if (err != OK) {
431        ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err);
432        handleError(err);
433        // finish with posting kWhatShutdownCompleted.
434    }
435
436    if (notifyComplete) {
437        sp<AMessage> notify = mNotify->dup();
438        notify->setInt32("what", kWhatShutdownCompleted);
439        notify->post();
440        mPaused = true;
441    }
442}
443
444/*
445 * returns true if we should request more data
446 */
447bool NuPlayer::Decoder::doRequestBuffers() {
448    // mRenderer is only NULL if we have a legacy widevine source that
449    // is not yet ready. In this case we must not fetch input.
450    if (isDiscontinuityPending() || mRenderer == NULL) {
451        return false;
452    }
453    status_t err = OK;
454    while (err == OK && !mDequeuedInputBuffers.empty()) {
455        size_t bufferIx = *mDequeuedInputBuffers.begin();
456        sp<AMessage> msg = new AMessage();
457        msg->setSize("buffer-ix", bufferIx);
458        err = fetchInputData(msg);
459        if (err != OK && err != ERROR_END_OF_STREAM) {
460            // if EOS, need to queue EOS buffer
461            break;
462        }
463        mDequeuedInputBuffers.erase(mDequeuedInputBuffers.begin());
464
465        if (!mPendingInputMessages.empty()
466                || !onInputBufferFetched(msg)) {
467            mPendingInputMessages.push_back(msg);
468        }
469    }
470
471    return err == -EWOULDBLOCK
472            && mSource->feedMoreTSData() == OK;
473}
474
475void NuPlayer::Decoder::handleError(int32_t err)
476{
477    // We cannot immediately release the codec due to buffers still outstanding
478    // in the renderer.  We signal to the player the error so it can shutdown/release the
479    // decoder after flushing and increment the generation to discard unnecessary messages.
480
481    ++mBufferGeneration;
482
483    sp<AMessage> notify = mNotify->dup();
484    notify->setInt32("what", kWhatError);
485    notify->setInt32("err", err);
486    notify->post();
487}
488
489bool NuPlayer::Decoder::handleAnInputBuffer(size_t index) {
490    if (isDiscontinuityPending()) {
491        return false;
492    }
493
494    sp<ABuffer> buffer;
495    mCodec->getInputBuffer(index, &buffer);
496
497    if (buffer == NULL) {
498        handleError(UNKNOWN_ERROR);
499        return false;
500    }
501
502    if (index >= mInputBuffers.size()) {
503        for (size_t i = mInputBuffers.size(); i <= index; ++i) {
504            mInputBuffers.add();
505            mMediaBuffers.add();
506            mInputBufferIsDequeued.add();
507            mMediaBuffers.editItemAt(i) = NULL;
508            mInputBufferIsDequeued.editItemAt(i) = false;
509        }
510    }
511    mInputBuffers.editItemAt(index) = buffer;
512
513    //CHECK_LT(bufferIx, mInputBuffers.size());
514
515    if (mMediaBuffers[index] != NULL) {
516        mMediaBuffers[index]->release();
517        mMediaBuffers.editItemAt(index) = NULL;
518    }
519    mInputBufferIsDequeued.editItemAt(index) = true;
520
521    if (!mCSDsToSubmit.isEmpty()) {
522        sp<AMessage> msg = new AMessage();
523        msg->setSize("buffer-ix", index);
524
525        sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0);
526        ALOGI("[%s] resubmitting CSD", mComponentName.c_str());
527        msg->setBuffer("buffer", buffer);
528        mCSDsToSubmit.removeAt(0);
529        CHECK(onInputBufferFetched(msg));
530        return true;
531    }
532
533    while (!mPendingInputMessages.empty()) {
534        sp<AMessage> msg = *mPendingInputMessages.begin();
535        if (!onInputBufferFetched(msg)) {
536            break;
537        }
538        mPendingInputMessages.erase(mPendingInputMessages.begin());
539    }
540
541    if (!mInputBufferIsDequeued.editItemAt(index)) {
542        return true;
543    }
544
545    mDequeuedInputBuffers.push_back(index);
546
547    onRequestInputBuffers();
548    return true;
549}
550
551bool NuPlayer::Decoder::handleAnOutputBuffer(
552        size_t index,
553        size_t offset,
554        size_t size,
555        int64_t timeUs,
556        int32_t flags) {
557//    CHECK_LT(bufferIx, mOutputBuffers.size());
558    sp<ABuffer> buffer;
559    mCodec->getOutputBuffer(index, &buffer);
560
561    if (index >= mOutputBuffers.size()) {
562        for (size_t i = mOutputBuffers.size(); i <= index; ++i) {
563            mOutputBuffers.add();
564        }
565    }
566
567    mOutputBuffers.editItemAt(index) = buffer;
568
569    buffer->setRange(offset, size);
570    buffer->meta()->clear();
571    buffer->meta()->setInt64("timeUs", timeUs);
572
573    bool eos = flags & MediaCodec::BUFFER_FLAG_EOS;
574    // we do not expect CODECCONFIG or SYNCFRAME for decoder
575
576    sp<AMessage> reply = new AMessage(kWhatRenderBuffer, this);
577    reply->setSize("buffer-ix", index);
578    reply->setInt32("generation", mBufferGeneration);
579
580    if (eos) {
581        ALOGI("[%s] saw output EOS", mIsAudio ? "audio" : "video");
582
583        buffer->meta()->setInt32("eos", true);
584        reply->setInt32("eos", true);
585    } else if (mSkipRenderingUntilMediaTimeUs >= 0) {
586        if (timeUs < mSkipRenderingUntilMediaTimeUs) {
587            ALOGV("[%s] dropping buffer at time %lld as requested.",
588                     mComponentName.c_str(), (long long)timeUs);
589
590            reply->post();
591            return true;
592        }
593
594        mSkipRenderingUntilMediaTimeUs = -1;
595    }
596
597    mNumFramesTotal += !mIsAudio;
598
599    // wait until 1st frame comes out to signal resume complete
600    notifyResumeCompleteIfNecessary();
601
602    if (mRenderer != NULL) {
603        // send the buffer to renderer.
604        mRenderer->queueBuffer(mIsAudio, buffer, reply);
605        if (eos && !isDiscontinuityPending()) {
606            mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM);
607        }
608    }
609
610    return true;
611}
612
613void NuPlayer::Decoder::handleOutputFormatChange(const sp<AMessage> &format) {
614    if (!mIsAudio) {
615        int32_t width, height;
616        if (format->findInt32("width", &width)
617                && format->findInt32("height", &height)) {
618            mStats->setInt32("width", width);
619            mStats->setInt32("height", height);
620        }
621        sp<AMessage> notify = mNotify->dup();
622        notify->setInt32("what", kWhatVideoSizeChanged);
623        notify->setMessage("format", format);
624        notify->post();
625    } else if (mRenderer != NULL) {
626        uint32_t flags;
627        int64_t durationUs;
628        bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
629        if (getAudioDeepBufferSetting() // override regardless of source duration
630                || (!hasVideo
631                        && mSource->getDuration(&durationUs) == OK
632                        && durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US)) {
633            flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
634        } else {
635            flags = AUDIO_OUTPUT_FLAG_NONE;
636        }
637
638        status_t err = mRenderer->openAudioSink(
639                format, false /* offloadOnly */, hasVideo, flags, NULL /* isOffloaed */);
640        if (err != OK) {
641            handleError(err);
642        }
643    }
644}
645
646void NuPlayer::Decoder::releaseAndResetMediaBuffers() {
647    for (size_t i = 0; i < mMediaBuffers.size(); i++) {
648        if (mMediaBuffers[i] != NULL) {
649            mMediaBuffers[i]->release();
650            mMediaBuffers.editItemAt(i) = NULL;
651        }
652    }
653    mMediaBuffers.resize(mInputBuffers.size());
654    for (size_t i = 0; i < mMediaBuffers.size(); i++) {
655        mMediaBuffers.editItemAt(i) = NULL;
656    }
657    mInputBufferIsDequeued.clear();
658    mInputBufferIsDequeued.resize(mInputBuffers.size());
659    for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) {
660        mInputBufferIsDequeued.editItemAt(i) = false;
661    }
662
663    mPendingInputMessages.clear();
664    mDequeuedInputBuffers.clear();
665    mSkipRenderingUntilMediaTimeUs = -1;
666}
667
668void NuPlayer::Decoder::requestCodecNotification() {
669    if (mCodec != NULL) {
670        sp<AMessage> reply = new AMessage(kWhatCodecNotify, this);
671        reply->setInt32("generation", mBufferGeneration);
672        mCodec->requestActivityNotification(reply);
673    }
674}
675
676bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) {
677    int32_t generation;
678    CHECK(msg->findInt32("generation", &generation));
679    return generation != mBufferGeneration;
680}
681
682status_t NuPlayer::Decoder::fetchInputData(sp<AMessage> &reply) {
683    sp<ABuffer> accessUnit;
684    bool dropAccessUnit;
685    do {
686        status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit);
687
688        if (err == -EWOULDBLOCK) {
689            return err;
690        } else if (err != OK) {
691            if (err == INFO_DISCONTINUITY) {
692                int32_t type;
693                CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
694
695                bool formatChange =
696                    (mIsAudio &&
697                     (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
698                    || (!mIsAudio &&
699                            (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
700
701                bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
702
703                ALOGI("%s discontinuity (format=%d, time=%d)",
704                        mIsAudio ? "audio" : "video", formatChange, timeChange);
705
706                bool seamlessFormatChange = false;
707                sp<AMessage> newFormat = mSource->getFormat(mIsAudio);
708                if (formatChange) {
709                    seamlessFormatChange =
710                        supportsSeamlessFormatChange(newFormat);
711                    // treat seamless format change separately
712                    formatChange = !seamlessFormatChange;
713                }
714
715                // For format or time change, return EOS to queue EOS input,
716                // then wait for EOS on output.
717                if (formatChange /* not seamless */) {
718                    mFormatChangePending = true;
719                    err = ERROR_END_OF_STREAM;
720                } else if (timeChange) {
721                    rememberCodecSpecificData(newFormat);
722                    mTimeChangePending = true;
723                    err = ERROR_END_OF_STREAM;
724                } else if (seamlessFormatChange) {
725                    // reuse existing decoder and don't flush
726                    rememberCodecSpecificData(newFormat);
727                    continue;
728                } else {
729                    // This stream is unaffected by the discontinuity
730                    return -EWOULDBLOCK;
731                }
732            }
733
734            // reply should only be returned without a buffer set
735            // when there is an error (including EOS)
736            CHECK(err != OK);
737
738            reply->setInt32("err", err);
739            return ERROR_END_OF_STREAM;
740        }
741
742        dropAccessUnit = false;
743        if (!mIsAudio
744                && !mIsSecure
745                && mRenderer->getVideoLateByUs() > 100000ll
746                && mIsVideoAVC
747                && !IsAVCReferenceFrame(accessUnit)) {
748            dropAccessUnit = true;
749            ++mNumInputFramesDropped;
750        }
751    } while (dropAccessUnit);
752
753    // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video");
754#if 0
755    int64_t mediaTimeUs;
756    CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
757    ALOGV("[%s] feeding input buffer at media time %.3f",
758         mIsAudio ? "audio" : "video",
759         mediaTimeUs / 1E6);
760#endif
761
762    if (mCCDecoder != NULL) {
763        mCCDecoder->decode(accessUnit);
764    }
765
766    reply->setBuffer("buffer", accessUnit);
767
768    return OK;
769}
770
771bool NuPlayer::Decoder::onInputBufferFetched(const sp<AMessage> &msg) {
772    size_t bufferIx;
773    CHECK(msg->findSize("buffer-ix", &bufferIx));
774    CHECK_LT(bufferIx, mInputBuffers.size());
775    sp<ABuffer> codecBuffer = mInputBuffers[bufferIx];
776
777    sp<ABuffer> buffer;
778    bool hasBuffer = msg->findBuffer("buffer", &buffer);
779
780    // handle widevine classic source - that fills an arbitrary input buffer
781    MediaBuffer *mediaBuffer = NULL;
782    if (hasBuffer) {
783        mediaBuffer = (MediaBuffer *)(buffer->getMediaBufferBase());
784        if (mediaBuffer != NULL) {
785            // likely filled another buffer than we requested: adjust buffer index
786            size_t ix;
787            for (ix = 0; ix < mInputBuffers.size(); ix++) {
788                const sp<ABuffer> &buf = mInputBuffers[ix];
789                if (buf->data() == mediaBuffer->data()) {
790                    // all input buffers are dequeued on start, hence the check
791                    if (!mInputBufferIsDequeued[ix]) {
792                        ALOGV("[%s] received MediaBuffer for #%zu instead of #%zu",
793                                mComponentName.c_str(), ix, bufferIx);
794                        mediaBuffer->release();
795                        return false;
796                    }
797
798                    // TRICKY: need buffer for the metadata, so instead, set
799                    // codecBuffer to the same (though incorrect) buffer to
800                    // avoid a memcpy into the codecBuffer
801                    codecBuffer = buffer;
802                    codecBuffer->setRange(
803                            mediaBuffer->range_offset(),
804                            mediaBuffer->range_length());
805                    bufferIx = ix;
806                    break;
807                }
808            }
809            CHECK(ix < mInputBuffers.size());
810        }
811    }
812
813    if (buffer == NULL /* includes !hasBuffer */) {
814        int32_t streamErr = ERROR_END_OF_STREAM;
815        CHECK(msg->findInt32("err", &streamErr) || !hasBuffer);
816
817        CHECK(streamErr != OK);
818
819        // attempt to queue EOS
820        status_t err = mCodec->queueInputBuffer(
821                bufferIx,
822                0,
823                0,
824                0,
825                MediaCodec::BUFFER_FLAG_EOS);
826        if (err == OK) {
827            mInputBufferIsDequeued.editItemAt(bufferIx) = false;
828        } else if (streamErr == ERROR_END_OF_STREAM) {
829            streamErr = err;
830            // err will not be ERROR_END_OF_STREAM
831        }
832
833        if (streamErr != ERROR_END_OF_STREAM) {
834            ALOGE("Stream error for %s (err=%d), EOS %s queued",
835                    mComponentName.c_str(),
836                    streamErr,
837                    err == OK ? "successfully" : "unsuccessfully");
838            handleError(streamErr);
839        }
840    } else {
841        sp<AMessage> extra;
842        if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) {
843            int64_t resumeAtMediaTimeUs;
844            if (extra->findInt64(
845                        "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) {
846                ALOGI("[%s] suppressing rendering until %lld us",
847                        mComponentName.c_str(), (long long)resumeAtMediaTimeUs);
848                mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs;
849            }
850        }
851
852        int64_t timeUs = 0;
853        uint32_t flags = 0;
854        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
855
856        int32_t eos, csd;
857        // we do not expect SYNCFRAME for decoder
858        if (buffer->meta()->findInt32("eos", &eos) && eos) {
859            flags |= MediaCodec::BUFFER_FLAG_EOS;
860        } else if (buffer->meta()->findInt32("csd", &csd) && csd) {
861            flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG;
862        }
863
864        // copy into codec buffer
865        if (buffer != codecBuffer) {
866            CHECK_LE(buffer->size(), codecBuffer->capacity());
867            codecBuffer->setRange(0, buffer->size());
868            memcpy(codecBuffer->data(), buffer->data(), buffer->size());
869        }
870
871        status_t err = mCodec->queueInputBuffer(
872                        bufferIx,
873                        codecBuffer->offset(),
874                        codecBuffer->size(),
875                        timeUs,
876                        flags);
877        if (err != OK) {
878            if (mediaBuffer != NULL) {
879                mediaBuffer->release();
880            }
881            ALOGE("Failed to queue input buffer for %s (err=%d)",
882                    mComponentName.c_str(), err);
883            handleError(err);
884        } else {
885            mInputBufferIsDequeued.editItemAt(bufferIx) = false;
886            if (mediaBuffer != NULL) {
887                CHECK(mMediaBuffers[bufferIx] == NULL);
888                mMediaBuffers.editItemAt(bufferIx) = mediaBuffer;
889            }
890        }
891    }
892    return true;
893}
894
895void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) {
896    status_t err;
897    int32_t render;
898    size_t bufferIx;
899    int32_t eos;
900    CHECK(msg->findSize("buffer-ix", &bufferIx));
901
902    if (!mIsAudio) {
903        int64_t timeUs;
904        sp<ABuffer> buffer = mOutputBuffers[bufferIx];
905        buffer->meta()->findInt64("timeUs", &timeUs);
906
907        if (mCCDecoder != NULL && mCCDecoder->isSelected()) {
908            mCCDecoder->display(timeUs);
909        }
910    }
911
912    if (msg->findInt32("render", &render) && render) {
913        int64_t timestampNs;
914        CHECK(msg->findInt64("timestampNs", &timestampNs));
915        err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs);
916    } else {
917        mNumOutputFramesDropped += !mIsAudio;
918        err = mCodec->releaseOutputBuffer(bufferIx);
919    }
920    if (err != OK) {
921        ALOGE("failed to release output buffer for %s (err=%d)",
922                mComponentName.c_str(), err);
923        handleError(err);
924    }
925    if (msg->findInt32("eos", &eos) && eos
926            && isDiscontinuityPending()) {
927        finishHandleDiscontinuity(true /* flushOnTimeChange */);
928    }
929}
930
931bool NuPlayer::Decoder::isDiscontinuityPending() const {
932    return mFormatChangePending || mTimeChangePending;
933}
934
935void NuPlayer::Decoder::finishHandleDiscontinuity(bool flushOnTimeChange) {
936    ALOGV("finishHandleDiscontinuity: format %d, time %d, flush %d",
937            mFormatChangePending, mTimeChangePending, flushOnTimeChange);
938
939    // If we have format change, pause and wait to be killed;
940    // If we have time change only, flush and restart fetching.
941
942    if (mFormatChangePending) {
943        mPaused = true;
944    } else if (mTimeChangePending) {
945        if (flushOnTimeChange) {
946            doFlush(false /* notifyComplete */);
947            signalResume(false /* notifyComplete */);
948        }
949    }
950
951    // Notify NuPlayer to either shutdown decoder, or rescan sources
952    sp<AMessage> msg = mNotify->dup();
953    msg->setInt32("what", kWhatInputDiscontinuity);
954    msg->setInt32("formatChange", mFormatChangePending);
955    msg->post();
956
957    mFormatChangePending = false;
958    mTimeChangePending = false;
959}
960
961bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(
962        const sp<AMessage> &targetFormat) const {
963    if (targetFormat == NULL) {
964        return true;
965    }
966
967    AString mime;
968    if (!targetFormat->findString("mime", &mime)) {
969        return false;
970    }
971
972    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
973        // field-by-field comparison
974        const char * keys[] = { "channel-count", "sample-rate", "is-adts" };
975        for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
976            int32_t oldVal, newVal;
977            if (!mInputFormat->findInt32(keys[i], &oldVal) ||
978                    !targetFormat->findInt32(keys[i], &newVal) ||
979                    oldVal != newVal) {
980                return false;
981            }
982        }
983
984        sp<ABuffer> oldBuf, newBuf;
985        if (mInputFormat->findBuffer("csd-0", &oldBuf) &&
986                targetFormat->findBuffer("csd-0", &newBuf)) {
987            if (oldBuf->size() != newBuf->size()) {
988                return false;
989            }
990            return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size());
991        }
992    }
993    return false;
994}
995
996bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const {
997    if (mInputFormat == NULL) {
998        return false;
999    }
1000
1001    if (targetFormat == NULL) {
1002        return true;
1003    }
1004
1005    AString oldMime, newMime;
1006    if (!mInputFormat->findString("mime", &oldMime)
1007            || !targetFormat->findString("mime", &newMime)
1008            || !(oldMime == newMime)) {
1009        return false;
1010    }
1011
1012    bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/"));
1013    bool seamless;
1014    if (audio) {
1015        seamless = supportsSeamlessAudioFormatChange(targetFormat);
1016    } else {
1017        int32_t isAdaptive;
1018        seamless = (mCodec != NULL &&
1019                mInputFormat->findInt32("adaptive-playback", &isAdaptive) &&
1020                isAdaptive);
1021    }
1022
1023    ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str());
1024    return seamless;
1025}
1026
1027void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) {
1028    if (format == NULL) {
1029        return;
1030    }
1031    mCSDsForCurrentFormat.clear();
1032    for (int32_t i = 0; ; ++i) {
1033        AString tag = "csd-";
1034        tag.append(i);
1035        sp<ABuffer> buffer;
1036        if (!format->findBuffer(tag.c_str(), &buffer)) {
1037            break;
1038        }
1039        mCSDsForCurrentFormat.push(buffer);
1040    }
1041}
1042
1043void NuPlayer::Decoder::notifyResumeCompleteIfNecessary() {
1044    if (mResumePending) {
1045        mResumePending = false;
1046
1047        sp<AMessage> notify = mNotify->dup();
1048        notify->setInt32("what", kWhatResumeCompleted);
1049        notify->post();
1050    }
1051}
1052
1053}  // namespace android
1054
1055