NuPlayer.cpp revision 9575c96b6e418914e2ffc6741ecc8d71e3968dbe
123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck/*
223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * Copyright (C) 2010 The Android Open Source Project
323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck *
423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * Licensed under the Apache License, Version 2.0 (the "License");
523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * you may not use this file except in compliance with the License.
623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * You may obtain a copy of the License at
723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck *
823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck *      http://www.apache.org/licenses/LICENSE-2.0
923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck *
1023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * Unless required by applicable law or agreed to in writing, software
1123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * distributed under the License is distributed on an "AS IS" BASIS,
1223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * See the License for the specific language governing permissions and
1423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck * limitations under the License.
1523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck */
1623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
1723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck//#define LOG_NDEBUG 0
1823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#define LOG_TAG "NuPlayer"
19998a6d81896df8b662cc10ddeb35087b78b38d72John Reck#include <utils/Log.h>
204f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
2123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#include "NuPlayer.h"
2223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
233b20251a355c88193c439f928a84ae69483fb488John Reck#include "HTTPLiveSource.h"
244f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#include "NuPlayerDecoder.h"
25119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck#include "NuPlayerDriver.h"
2623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#include "NuPlayerRenderer.h"
2719b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck#include "NuPlayerSource.h"
283b20251a355c88193c439f928a84ae69483fb488John Reck#include "RTSPSource.h"
2919b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck#include "StreamingSource.h"
304f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#include "GenericSource.h"
3123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#include "mp4/MP4Source.h"
3223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
33f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck#include "ATSParser.h"
34f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck
35f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck#include <cutils/properties.h> // for property_get
3623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#include <media/stagefright/foundation/hexdump.h>
3723b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#include <media/stagefright/foundation/ABuffer.h>
3823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#include <media/stagefright/foundation/ADebug.h>
3923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck#include <media/stagefright/foundation/AMessage.h>
40119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck#include <media/stagefright/ACodec.h>
41119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck#include <media/stagefright/MediaDefs.h>
423b20251a355c88193c439f928a84ae69483fb488John Reck#include <media/stagefright/MediaErrors.h>
433b20251a355c88193c439f928a84ae69483fb488John Reck#include <media/stagefright/MetaData.h>
444f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#include <gui/IGraphicBufferProducer.h>
454f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
464f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck#include "avc_utils.h"
473b20251a355c88193c439f928a84ae69483fb488John Reck
48e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck#include "ESDS.h"
49e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck#include <media/stagefright/Utils.h>
50119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck
51443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Recknamespace android {
5223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
5323b797ab5151eb2474f3bdd679f2f07bfd723042John Reckstruct NuPlayer::Action : public RefBase {
5423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    Action() {}
5517035b0211a3c9d45ea46a99217a6acbe76e8fbeJohn Reck
56119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    virtual void execute(NuPlayer *player) = 0;
57443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck
584f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckprivate:
594f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    DISALLOW_EVIL_CONSTRUCTORS(Action);
6017035b0211a3c9d45ea46a99217a6acbe76e8fbeJohn Reck};
6117035b0211a3c9d45ea46a99217a6acbe76e8fbeJohn Reck
6217035b0211a3c9d45ea46a99217a6acbe76e8fbeJohn Reckstruct NuPlayer::SeekAction : public Action {
6317035b0211a3c9d45ea46a99217a6acbe76e8fbeJohn Reck    SeekAction(int64_t seekTimeUs)
64e2478d45ccbe5b6abb360ac9d44771b5f4a50bdeJohn Reck        : mSeekTimeUs(seekTimeUs) {
654f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    }
664f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
674f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    virtual void execute(NuPlayer *player) {
684f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        player->performSeek(mSeekTimeUs);
6923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
7023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck
7123b797ab5151eb2474f3bdd679f2f07bfd723042John Reckprivate:
72a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    int64_t mSeekTimeUs;
73a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck
74a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    DISALLOW_EVIL_CONSTRUCTORS(SeekAction);
7523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck};
763b20251a355c88193c439f928a84ae69483fb488John Reck
7723b797ab5151eb2474f3bdd679f2f07bfd723042John Reckstruct NuPlayer::SetSurfaceAction : public Action {
7823b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    SetSurfaceAction(const sp<NativeWindowWrapper> &wrapper)
7923b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        : mWrapper(wrapper) {
8023b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
813b20251a355c88193c439f928a84ae69483fb488John Reck
8223b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    virtual void execute(NuPlayer *player) {
8323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        player->performSetSurface(mWrapper);
8423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    }
853b20251a355c88193c439f928a84ae69483fb488John Reck
864f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckprivate:
87dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck    sp<NativeWindowWrapper> mWrapper;
88368cdd85268999997fb495cf90c4417221797de0John Reck
89368cdd85268999997fb495cf90c4417221797de0John Reck    DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction);
904f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck};
914f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
924f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck// Use this if there's no state necessary to save in order to execute
934f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck// the action.
943b20251a355c88193c439f928a84ae69483fb488John Reckstruct NuPlayer::SimpleAction : public Action {
954f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    typedef void (NuPlayer::*ActionFunc)();
964f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
974f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    SimpleAction(ActionFunc func)
98f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck        : mFunc(func) {
99f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    }
100f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck
101dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck    virtual void execute(NuPlayer *player) {
1024f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        (player->*mFunc)();
1034f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    }
104a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck
1054f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckprivate:
1064f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    ActionFunc mFunc;
1073b20251a355c88193c439f928a84ae69483fb488John Reck
1084f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    DISALLOW_EVIL_CONSTRUCTORS(SimpleAction);
1094f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck};
1104f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
1114f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck////////////////////////////////////////////////////////////////////////////////
112a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck
1134f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John ReckNuPlayer::NuPlayer()
114f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck    : mUIDValid(false),
115f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck      mSourceFlags(0),
116a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck      mVideoIsAVC(false),
1171661715d4066a557ab0877271d62762579a38fa9John Reck      mAudioEOS(false),
1184f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck      mVideoEOS(false),
1194f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck      mScanSourcesPending(false),
120058fc640017c90120c599d378a4cbc55668b05b7Chris Craik      mScanSourcesGeneration(0),
121058fc640017c90120c599d378a4cbc55668b05b7Chris Craik      mPollDurationGeneration(0),
1224f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck      mTimeDiscontinuityPending(false),
1234f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck      mFlushingAudio(NONE),
124058fc640017c90120c599d378a4cbc55668b05b7Chris Craik      mFlushingVideo(NONE),
1254f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck      mSkipRenderingAudioUntilMediaTimeUs(-1ll),
1264f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck      mSkipRenderingVideoUntilMediaTimeUs(-1ll),
12763a06673253914510bbeebd500655008682dade1John Reck      mVideoLateByUs(0ll),
12863a06673253914510bbeebd500655008682dade1John Reck      mNumFramesTotal(0ll),
12963a06673253914510bbeebd500655008682dade1John Reck      mNumFramesDropped(0ll),
13063a06673253914510bbeebd500655008682dade1John Reck      mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
131860d155f866cc15a725e7ce03763280987f24901John Reck      mStarted(false) {
132dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck}
133dbc9a86d05e5e835051de22f6cb30ec1921e9705John Reck
1343b20251a355c88193c439f928a84ae69483fb488John ReckNuPlayer::~NuPlayer() {
135860d155f866cc15a725e7ce03763280987f24901John Reck}
136860d155f866cc15a725e7ce03763280987f24901John Reck
13768bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reckvoid NuPlayer::setUID(uid_t uid) {
13868bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck    mUIDValid = true;
139d72e0a339b54af0c4e731513bbad120dff694723John Reck    mUID = uid;
140d72e0a339b54af0c4e731513bbad120dff694723John Reck}
141d72e0a339b54af0c4e731513bbad120dff694723John Reck
14219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reckvoid NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
14319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck    mDriver = driver;
14419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck}
145e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
146f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reckvoid NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) {
14718f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
148e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck
14925fbb3fa1138675379102a44405852555cefccbdJohn Reck    sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
150998a6d81896df8b662cc10ddeb35087b78b38d72John Reck
151998a6d81896df8b662cc10ddeb35087b78b38d72John Reck    char prop[PROPERTY_VALUE_MAX];
152998a6d81896df8b662cc10ddeb35087b78b38d72John Reck    if (property_get("media.stagefright.use-mp4source", prop, NULL)
153ec845a215e343cdb3b2e4c7b6aff7b24beb0236bJohn Reck            && (!strcmp(prop, "1") || !strcasecmp(prop, "true"))) {
154e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        msg->setObject("source", new MP4Source(notify, source));
155119907cd2575c56b1ebf66348b52e67aaf6a88d8John Reck    } else {
156e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck        msg->setObject("source", new StreamingSource(notify, source));
157998a6d81896df8b662cc10ddeb35087b78b38d72John Reck    }
158998a6d81896df8b662cc10ddeb35087b78b38d72John Reck
159998a6d81896df8b662cc10ddeb35087b78b38d72John Reck    msg->post();
160998a6d81896df8b662cc10ddeb35087b78b38d72John Reck}
161a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck
162a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reckstatic bool IsHTTPLiveURL(const char *url) {
163a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    if (!strncasecmp("http://", url, 7)
164a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck            || !strncasecmp("https://", url, 8)) {
165a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck        size_t len = strlen(url);
166a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck        if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
167a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck            return true;
168a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck        }
169a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck
170cd028f336e36b22dbe8cf623eb5bd2361314495cJohn Reck        if (strstr(url,"m3u8")) {
171f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck            return true;
172f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck        }
173f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck    }
174f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck
175e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    return false;
176e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck}
177e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
178f47a594f5250b1914c36423ee6b371f0b8db09d0John Reckvoid NuPlayer::setDataSourceAsync(
179f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck        const char *url, const KeyedVector<String8, String8> *headers) {
180f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
181f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck    size_t len = strlen(url);
182a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck
183a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
184a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck
185a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    sp<Source> source;
186a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    if (IsHTTPLiveURL(url)) {
187e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck        source = new HTTPLiveSource(notify, url, headers, mUIDValid, mUID);
1884f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    } else if (!strncasecmp(url, "rtsp://", 7)) {
189a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craik        source = new RTSPSource(notify, url, headers, mUIDValid, mUID);
1904f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    } else if ((!strncasecmp(url, "http://", 7)
191fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck                || !strncasecmp(url, "https://", 8))
192fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck                    && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
193e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck                    || strstr(url, ".sdp?"))) {
194e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck        source = new RTSPSource(notify, url, headers, mUIDValid, mUID, true);
195e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    } else {
1964f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        source = new GenericSource(notify, url, headers, mUIDValid, mUID);
1973b20251a355c88193c439f928a84ae69483fb488John Reck    }
1984f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
1994f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    msg->setObject("source", source);
200e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    msg->post();
2014f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
202e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck
203fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) {
2045cdb8f998c58a2226112b36e4c391866346e5e17John Reck    sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
2050a97330b98dd633b58dcfff405d94476c89e867dJohn Reck
2060a97330b98dd633b58dcfff405d94476c89e867dJohn Reck    sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
2070a97330b98dd633b58dcfff405d94476c89e867dJohn Reck
2080a97330b98dd633b58dcfff405d94476c89e867dJohn Reck    sp<Source> source = new GenericSource(notify, fd, offset, length);
209e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    msg->setObject("source", source);
2104f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    msg->post();
2114f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck}
2124f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
213e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reckvoid NuPlayer::prepareAsync() {
214e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck    (new AMessage(kWhatPrepare, id()))->post();
215e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck}
2164f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
2174f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reckvoid NuPlayer::setVideoSurfaceTextureAsync(
2184f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        const sp<IGraphicBufferProducer> &bufferProducer) {
2194f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
2204f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
221a7090e0cfd7c719a6d4c03aae34f5db98754cbddChris Craik    if (bufferProducer == NULL) {
2224f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        msg->setObject("native-window", NULL);
223fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    } else {
2244f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck        msg->setObject(
2254f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck                "native-window",
2264f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck                new NativeWindowWrapper(
227fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck                    new SurfaceTextureClient(bufferProducer)));
228fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    }
2294f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck
2304f02bf4eef6af47f35c70c4dda5b7b9523d89ca0John Reck    msg->post();
23123b797ab5151eb2474f3bdd679f2f07bfd723042John Reck}
232fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck
233fe5e7b7346a54537b980796ceeca66bfdbd05561John Reckvoid NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) {
23423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id());
23523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    msg->setObject("sink", sink);
236e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    msg->post();
23718f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck}
238368cdd85268999997fb495cf90c4417221797de0John Reck
239368cdd85268999997fb495cf90c4417221797de0John Reckvoid NuPlayer::start() {
240368cdd85268999997fb495cf90c4417221797de0John Reck    (new AMessage(kWhatStart, id()))->post();
241368cdd85268999997fb495cf90c4417221797de0John Reck}
242e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck
243e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckvoid NuPlayer::pause() {
244fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck    (new AMessage(kWhatPause, id()))->post();
245fe5e7b7346a54537b980796ceeca66bfdbd05561John Reck}
2463b20251a355c88193c439f928a84ae69483fb488John Reck
247e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckvoid NuPlayer::resume() {
248a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    (new AMessage(kWhatResume, id()))->post();
249e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck}
250a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck
251e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reckvoid NuPlayer::resetAsync() {
252e45b1fd03b524d2b57cc6c222d89076a31a08beaJohn Reck    (new AMessage(kWhatReset, id()))->post();
2533b20251a355c88193c439f928a84ae69483fb488John Reck}
254d3d8dafc2f61fb118c060720b52684c59303f3dbJohn Reck
2550d1f634f4b5e1bb37aa51777efb6a68619488d01John Reckvoid NuPlayer::seekToAsync(int64_t seekTimeUs) {
2563b20251a355c88193c439f928a84ae69483fb488John Reck    sp<AMessage> msg = new AMessage(kWhatSeek, id());
2573b20251a355c88193c439f928a84ae69483fb488John Reck    msg->setInt64("seekTimeUs", seekTimeUs);
2580d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck    msg->post();
2590d1f634f4b5e1bb37aa51777efb6a68619488d01John Reck}
2606f07a0dc875a9eac67312085a8e0133b9e2f4771John Reck
2613b20251a355c88193c439f928a84ae69483fb488John Reck// static
26223b797ab5151eb2474f3bdd679f2f07bfd723042John Reckbool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
26323b797ab5151eb2474f3bdd679f2f07bfd723042John Reck    switch (state) {
264998a6d81896df8b662cc10ddeb35087b78b38d72John Reck        case FLUSHING_DECODER:
265998a6d81896df8b662cc10ddeb35087b78b38d72John Reck            if (needShutdown != NULL) {
266998a6d81896df8b662cc10ddeb35087b78b38d72John Reck                *needShutdown = false;
267998a6d81896df8b662cc10ddeb35087b78b38d72John Reck            }
268998a6d81896df8b662cc10ddeb35087b78b38d72John Reck            return true;
269998a6d81896df8b662cc10ddeb35087b78b38d72John Reck
270998a6d81896df8b662cc10ddeb35087b78b38d72John Reck        case FLUSHING_DECODER_SHUTDOWN:
271998a6d81896df8b662cc10ddeb35087b78b38d72John Reck            if (needShutdown != NULL) {
272998a6d81896df8b662cc10ddeb35087b78b38d72John Reck                *needShutdown = true;
273998a6d81896df8b662cc10ddeb35087b78b38d72John Reck            }
274998a6d81896df8b662cc10ddeb35087b78b38d72John Reck            return true;
275998a6d81896df8b662cc10ddeb35087b78b38d72John Reck
276998a6d81896df8b662cc10ddeb35087b78b38d72John Reck        default:
277998a6d81896df8b662cc10ddeb35087b78b38d72John Reck            return false;
278998a6d81896df8b662cc10ddeb35087b78b38d72John Reck    }
279998a6d81896df8b662cc10ddeb35087b78b38d72John Reck}
280998a6d81896df8b662cc10ddeb35087b78b38d72John Reck
281998a6d81896df8b662cc10ddeb35087b78b38d72John Reckvoid NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
282998a6d81896df8b662cc10ddeb35087b78b38d72John Reck    switch (msg->what()) {
283998a6d81896df8b662cc10ddeb35087b78b38d72John Reck        case kWhatSetDataSource:
2843e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck        {
2853e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck            ALOGV("kWhatSetDataSource");
2863e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck
2873e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck            CHECK(mSource == NULL);
2883e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck
2893e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck            sp<RefBase> obj;
2903e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck            CHECK(msg->findObject("source", &obj));
2913e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck
2923e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck            mSource = static_cast<Source *>(obj.get());
2933e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck
2943e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck            looper()->registerHandler(mSource);
2953e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck
2969eb9f6f8cbbbd87d45da8071aa54cb066a797723John Reck            CHECK(mDriver != NULL);
2973e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck            sp<NuPlayerDriver> driver = mDriver.promote();
2983e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck            if (driver != NULL) {
2993e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck                driver->notifySetDataSourceCompleted(OK);
3003e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck            }
3013e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck            break;
3023e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck        }
3033e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck
304443a714fa7c0dd07fee3527cc5bc3d3ca1fb7d44John Reck        case kWhatPrepare:
3053e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck        {
306998a6d81896df8b662cc10ddeb35087b78b38d72John Reck            mSource->prepareAsync();
307998a6d81896df8b662cc10ddeb35087b78b38d72John Reck            break;
308998a6d81896df8b662cc10ddeb35087b78b38d72John Reck        }
3093e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck
3103e8249568cc428296ac76c7ddce3f0382d40fe5bJohn Reck        case kWhatPollDuration:
31119b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        {
31219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck            int32_t generation;
31368bfe0a37a0dcef52abd81688d8520c5d16e1a85John Reck            CHECK(msg->findInt32("generation", &generation));
3143b20251a355c88193c439f928a84ae69483fb488John Reck
31519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck            if (generation != mPollDurationGeneration) {
31619b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck                // stale
317f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck                break;
318f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck            }
3193b20251a355c88193c439f928a84ae69483fb488John Reck
320e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck            int64_t durationUs;
321dff9957cc22a1174a4cf91de6609c50934d29434John Reck            if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
322dcba6725e8b9d3eba9ad7a01258d6aa974feafbaJohn Reck                sp<NuPlayerDriver> driver = mDriver.promote();
323f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck                if (driver != NULL) {
324f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck                    driver->notifyDuration(durationUs);
325f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck                }
326f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck            }
327f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck
328f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck            msg->post(1000000ll);  // poll again in a second.
329f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck            break;
330f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck        }
3313c2b7fa8c584c5ed56f1bd6ad53f2e87f0a6eb44John Reck
332f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck        case kWhatSetVideoNativeWindow:
333f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck        {
334f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck            ALOGV("kWhatSetVideoNativeWindow");
335f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck
336f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck            mDeferredActions.push_back(
337e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck                    new SimpleAction(&NuPlayer::performDecoderShutdown));
338e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck
339e1628b7c6fc3822fa83cf02028ce8ad67abb0afeJohn Reck            sp<RefBase> obj;
340fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck            CHECK(msg->findObject("native-window", &obj));
34119b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck
34219b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck            mDeferredActions.push_back(
34319b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck                    new SetSurfaceAction(
34419b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck                        static_cast<NativeWindowWrapper *>(obj.get())));
3451949e7928eeec22cd3f74b5f763a4eb433238453John Reck
346f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck            if (obj != NULL) {
3473b20251a355c88193c439f928a84ae69483fb488John Reck                // If there is a new surface texture, instantiate decoders
3481949e7928eeec22cd3f74b5f763a4eb433238453John Reck                // again if possible.
3491949e7928eeec22cd3f74b5f763a4eb433238453John Reck                mDeferredActions.push_back(
3501949e7928eeec22cd3f74b5f763a4eb433238453John Reck                        new SimpleAction(&NuPlayer::performScanSources));
351f7d9c1dc84671d4e99657ef071d275700d85bb11John Reck            }
3523b20251a355c88193c439f928a84ae69483fb488John Reck
3531949e7928eeec22cd3f74b5f763a4eb433238453John Reck            processDeferredActions();
3541949e7928eeec22cd3f74b5f763a4eb433238453John Reck            break;
35519b6bcfd83eb7fb92ebd06d2fec89e308311f1d0John Reck        }
356f47a594f5250b1914c36423ee6b371f0b8db09d0John Reck
357fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck        case kWhatSetAudioSink:
358fc53ef27793a39e9effd829e9cae02a9ca14147eJohn Reck        {
3593b20251a355c88193c439f928a84ae69483fb488John Reck            ALOGV("kWhatSetAudioSink");
3603b20251a355c88193c439f928a84ae69483fb488John Reck
3613b20251a355c88193c439f928a84ae69483fb488John Reck            sp<RefBase> obj;
36266f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck            CHECK(msg->findObject("sink", &obj));
36366f0be65a1046f54ddce0498b242c1fa0776b1eaJohn Reck
36423b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get());
36523b797ab5151eb2474f3bdd679f2f07bfd723042John Reck            break;
36623b797ab5151eb2474f3bdd679f2f07bfd723042John Reck        }
367
368        case kWhatStart:
369        {
370            ALOGV("kWhatStart");
371
372            mVideoIsAVC = false;
373            mAudioEOS = false;
374            mVideoEOS = false;
375            mSkipRenderingAudioUntilMediaTimeUs = -1;
376            mSkipRenderingVideoUntilMediaTimeUs = -1;
377            mVideoLateByUs = 0;
378            mNumFramesTotal = 0;
379            mNumFramesDropped = 0;
380            mStarted = true;
381
382            mSource->start();
383
384            mRenderer = new Renderer(
385                    mAudioSink,
386                    new AMessage(kWhatRendererNotify, id()));
387
388            looper()->registerHandler(mRenderer);
389
390            postScanSources();
391            break;
392        }
393
394        case kWhatScanSources:
395        {
396            int32_t generation;
397            CHECK(msg->findInt32("generation", &generation));
398            if (generation != mScanSourcesGeneration) {
399                // Drop obsolete msg.
400                break;
401            }
402
403            mScanSourcesPending = false;
404
405            ALOGV("scanning sources haveAudio=%d, haveVideo=%d",
406                 mAudioDecoder != NULL, mVideoDecoder != NULL);
407
408            bool mHadAnySourcesBefore =
409                (mAudioDecoder != NULL) || (mVideoDecoder != NULL);
410
411            if (mNativeWindow != NULL) {
412                instantiateDecoder(false, &mVideoDecoder);
413            }
414
415            if (mAudioSink != NULL) {
416                instantiateDecoder(true, &mAudioDecoder);
417            }
418
419            if (!mHadAnySourcesBefore
420                    && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
421                // This is the first time we've found anything playable.
422
423                if (mSourceFlags & Source::FLAG_DYNAMIC_DURATION) {
424                    schedulePollDuration();
425                }
426            }
427
428            status_t err;
429            if ((err = mSource->feedMoreTSData()) != OK) {
430                if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
431                    // We're not currently decoding anything (no audio or
432                    // video tracks found) and we just ran out of input data.
433
434                    if (err == ERROR_END_OF_STREAM) {
435                        notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
436                    } else {
437                        notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
438                    }
439                }
440                break;
441            }
442
443            if ((mAudioDecoder == NULL && mAudioSink != NULL)
444                    || (mVideoDecoder == NULL && mNativeWindow != NULL)) {
445                msg->post(100000ll);
446                mScanSourcesPending = true;
447            }
448            break;
449        }
450
451        case kWhatVideoNotify:
452        case kWhatAudioNotify:
453        {
454            bool audio = msg->what() == kWhatAudioNotify;
455
456            sp<AMessage> codecRequest;
457            CHECK(msg->findMessage("codec-request", &codecRequest));
458
459            int32_t what;
460            CHECK(codecRequest->findInt32("what", &what));
461
462            if (what == ACodec::kWhatFillThisBuffer) {
463                status_t err = feedDecoderInputData(
464                        audio, codecRequest);
465
466                if (err == -EWOULDBLOCK) {
467                    if (mSource->feedMoreTSData() == OK) {
468                        msg->post(10000ll);
469                    }
470                }
471            } else if (what == ACodec::kWhatEOS) {
472                int32_t err;
473                CHECK(codecRequest->findInt32("err", &err));
474
475                if (err == ERROR_END_OF_STREAM) {
476                    ALOGV("got %s decoder EOS", audio ? "audio" : "video");
477                } else {
478                    ALOGV("got %s decoder EOS w/ error %d",
479                         audio ? "audio" : "video",
480                         err);
481                }
482
483                mRenderer->queueEOS(audio, err);
484            } else if (what == ACodec::kWhatFlushCompleted) {
485                bool needShutdown;
486
487                if (audio) {
488                    CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
489                    mFlushingAudio = FLUSHED;
490                } else {
491                    CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
492                    mFlushingVideo = FLUSHED;
493
494                    mVideoLateByUs = 0;
495                }
496
497                ALOGV("decoder %s flush completed", audio ? "audio" : "video");
498
499                if (needShutdown) {
500                    ALOGV("initiating %s decoder shutdown",
501                         audio ? "audio" : "video");
502
503                    (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
504
505                    if (audio) {
506                        mFlushingAudio = SHUTTING_DOWN_DECODER;
507                    } else {
508                        mFlushingVideo = SHUTTING_DOWN_DECODER;
509                    }
510                }
511
512                finishFlushIfPossible();
513            } else if (what == ACodec::kWhatOutputFormatChanged) {
514                if (audio) {
515                    int32_t numChannels;
516                    CHECK(codecRequest->findInt32(
517                                "channel-count", &numChannels));
518
519                    int32_t sampleRate;
520                    CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
521
522                    ALOGV("Audio output format changed to %d Hz, %d channels",
523                         sampleRate, numChannels);
524
525                    mAudioSink->close();
526
527                    audio_output_flags_t flags;
528                    int64_t durationUs;
529                    // FIXME: we should handle the case where the video decoder
530                    // is created after we receive the format change indication.
531                    // Current code will just make that we select deep buffer
532                    // with video which should not be a problem as it should
533                    // not prevent from keeping A/V sync.
534                    if (mVideoDecoder == NULL &&
535                            mSource->getDuration(&durationUs) == OK &&
536                            durationUs
537                                > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
538                        flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
539                    } else {
540                        flags = AUDIO_OUTPUT_FLAG_NONE;
541                    }
542
543                    int32_t channelMask;
544                    if (!codecRequest->findInt32("channel-mask", &channelMask)) {
545                        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
546                    }
547
548                    CHECK_EQ(mAudioSink->open(
549                                sampleRate,
550                                numChannels,
551                                (audio_channel_mask_t)channelMask,
552                                AUDIO_FORMAT_PCM_16_BIT,
553                                8 /* bufferCount */,
554                                NULL,
555                                NULL,
556                                flags),
557                             (status_t)OK);
558                    mAudioSink->start();
559
560                    mRenderer->signalAudioSinkChanged();
561                } else {
562                    // video
563
564                    int32_t width, height;
565                    CHECK(codecRequest->findInt32("width", &width));
566                    CHECK(codecRequest->findInt32("height", &height));
567
568                    int32_t cropLeft, cropTop, cropRight, cropBottom;
569                    CHECK(codecRequest->findRect(
570                                "crop",
571                                &cropLeft, &cropTop, &cropRight, &cropBottom));
572
573                    int32_t displayWidth = cropRight - cropLeft + 1;
574                    int32_t displayHeight = cropBottom - cropTop + 1;
575
576                    ALOGV("Video output format changed to %d x %d "
577                         "(crop: %d x %d @ (%d, %d))",
578                         width, height,
579                         displayWidth,
580                         displayHeight,
581                         cropLeft, cropTop);
582
583                    sp<AMessage> videoInputFormat =
584                        mSource->getFormat(false /* audio */);
585
586                    // Take into account sample aspect ratio if necessary:
587                    int32_t sarWidth, sarHeight;
588                    if (videoInputFormat->findInt32("sar-width", &sarWidth)
589                            && videoInputFormat->findInt32(
590                                "sar-height", &sarHeight)) {
591                        ALOGV("Sample aspect ratio %d : %d",
592                              sarWidth, sarHeight);
593
594                        displayWidth = (displayWidth * sarWidth) / sarHeight;
595
596                        ALOGV("display dimensions %d x %d",
597                              displayWidth, displayHeight);
598                    }
599
600                    notifyListener(
601                            MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight);
602                }
603            } else if (what == ACodec::kWhatShutdownCompleted) {
604                ALOGV("%s shutdown completed", audio ? "audio" : "video");
605                if (audio) {
606                    mAudioDecoder.clear();
607
608                    CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
609                    mFlushingAudio = SHUT_DOWN;
610                } else {
611                    mVideoDecoder.clear();
612
613                    CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
614                    mFlushingVideo = SHUT_DOWN;
615                }
616
617                finishFlushIfPossible();
618            } else if (what == ACodec::kWhatError) {
619                ALOGE("Received error from %s decoder, aborting playback.",
620                     audio ? "audio" : "video");
621
622                mRenderer->queueEOS(audio, UNKNOWN_ERROR);
623            } else if (what == ACodec::kWhatDrainThisBuffer) {
624                renderBuffer(audio, codecRequest);
625            } else if (what != ACodec::kWhatComponentAllocated
626                    && what != ACodec::kWhatComponentConfigured
627                    && what != ACodec::kWhatBuffersAllocated) {
628                ALOGV("Unhandled codec notification %d '%c%c%c%c'.",
629                      what,
630                      what >> 24,
631                      (what >> 16) & 0xff,
632                      (what >> 8) & 0xff,
633                      what & 0xff);
634            }
635
636            break;
637        }
638
639        case kWhatRendererNotify:
640        {
641            int32_t what;
642            CHECK(msg->findInt32("what", &what));
643
644            if (what == Renderer::kWhatEOS) {
645                int32_t audio;
646                CHECK(msg->findInt32("audio", &audio));
647
648                int32_t finalResult;
649                CHECK(msg->findInt32("finalResult", &finalResult));
650
651                if (audio) {
652                    mAudioEOS = true;
653                } else {
654                    mVideoEOS = true;
655                }
656
657                if (finalResult == ERROR_END_OF_STREAM) {
658                    ALOGV("reached %s EOS", audio ? "audio" : "video");
659                } else {
660                    ALOGE("%s track encountered an error (%d)",
661                         audio ? "audio" : "video", finalResult);
662
663                    notifyListener(
664                            MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult);
665                }
666
667                if ((mAudioEOS || mAudioDecoder == NULL)
668                        && (mVideoEOS || mVideoDecoder == NULL)) {
669                    notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
670                }
671            } else if (what == Renderer::kWhatPosition) {
672                int64_t positionUs;
673                CHECK(msg->findInt64("positionUs", &positionUs));
674
675                CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs));
676
677                if (mDriver != NULL) {
678                    sp<NuPlayerDriver> driver = mDriver.promote();
679                    if (driver != NULL) {
680                        driver->notifyPosition(positionUs);
681
682                        driver->notifyFrameStats(
683                                mNumFramesTotal, mNumFramesDropped);
684                    }
685                }
686            } else if (what == Renderer::kWhatFlushComplete) {
687                int32_t audio;
688                CHECK(msg->findInt32("audio", &audio));
689
690                ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
691            } else if (what == Renderer::kWhatVideoRenderingStart) {
692                notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
693            }
694            break;
695        }
696
697        case kWhatMoreDataQueued:
698        {
699            break;
700        }
701
702        case kWhatReset:
703        {
704            ALOGV("kWhatReset");
705
706            mDeferredActions.push_back(
707                    new SimpleAction(&NuPlayer::performDecoderShutdown));
708
709            mDeferredActions.push_back(
710                    new SimpleAction(&NuPlayer::performReset));
711
712            processDeferredActions();
713            break;
714        }
715
716        case kWhatSeek:
717        {
718            int64_t seekTimeUs;
719            CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
720
721            ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs);
722
723            mDeferredActions.push_back(
724                    new SimpleAction(&NuPlayer::performDecoderFlush));
725
726            mDeferredActions.push_back(new SeekAction(seekTimeUs));
727
728            processDeferredActions();
729            break;
730        }
731
732        case kWhatPause:
733        {
734            CHECK(mRenderer != NULL);
735            mRenderer->pause();
736            break;
737        }
738
739        case kWhatResume:
740        {
741            CHECK(mRenderer != NULL);
742            mRenderer->resume();
743            break;
744        }
745
746        case kWhatSourceNotify:
747        {
748            onSourceNotify(msg);
749            break;
750        }
751
752        default:
753            TRESPASS();
754            break;
755    }
756}
757
758void NuPlayer::finishFlushIfPossible() {
759    if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
760        return;
761    }
762
763    if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
764        return;
765    }
766
767    ALOGV("both audio and video are flushed now.");
768
769    if (mTimeDiscontinuityPending) {
770        mRenderer->signalTimeDiscontinuity();
771        mTimeDiscontinuityPending = false;
772    }
773
774    if (mAudioDecoder != NULL) {
775        mAudioDecoder->signalResume();
776    }
777
778    if (mVideoDecoder != NULL) {
779        mVideoDecoder->signalResume();
780    }
781
782    mFlushingAudio = NONE;
783    mFlushingVideo = NONE;
784
785    processDeferredActions();
786}
787
788void NuPlayer::postScanSources() {
789    if (mScanSourcesPending) {
790        return;
791    }
792
793    sp<AMessage> msg = new AMessage(kWhatScanSources, id());
794    msg->setInt32("generation", mScanSourcesGeneration);
795    msg->post();
796
797    mScanSourcesPending = true;
798}
799
800status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
801    if (*decoder != NULL) {
802        return OK;
803    }
804
805    sp<AMessage> format = mSource->getFormat(audio);
806
807    if (format == NULL) {
808        return -EWOULDBLOCK;
809    }
810
811    if (!audio) {
812        AString mime;
813        CHECK(format->findString("mime", &mime));
814        mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
815    }
816
817    sp<AMessage> notify =
818        new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
819                     id());
820
821    *decoder = audio ? new Decoder(notify) :
822                       new Decoder(notify, mNativeWindow);
823    looper()->registerHandler(*decoder);
824
825    (*decoder)->configure(format);
826
827    int64_t durationUs;
828    if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
829        sp<NuPlayerDriver> driver = mDriver.promote();
830        if (driver != NULL) {
831            driver->notifyDuration(durationUs);
832        }
833    }
834
835    return OK;
836}
837
838status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
839    sp<AMessage> reply;
840    CHECK(msg->findMessage("reply", &reply));
841
842    if ((audio && IsFlushingState(mFlushingAudio))
843            || (!audio && IsFlushingState(mFlushingVideo))) {
844        reply->setInt32("err", INFO_DISCONTINUITY);
845        reply->post();
846        return OK;
847    }
848
849    sp<ABuffer> accessUnit;
850
851    bool dropAccessUnit;
852    do {
853        status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
854
855        if (err == -EWOULDBLOCK) {
856            return err;
857        } else if (err != OK) {
858            if (err == INFO_DISCONTINUITY) {
859                int32_t type;
860                CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
861
862                bool formatChange =
863                    (audio &&
864                     (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
865                    || (!audio &&
866                            (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
867
868                bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
869
870                ALOGI("%s discontinuity (formatChange=%d, time=%d)",
871                     audio ? "audio" : "video", formatChange, timeChange);
872
873                if (audio) {
874                    mSkipRenderingAudioUntilMediaTimeUs = -1;
875                } else {
876                    mSkipRenderingVideoUntilMediaTimeUs = -1;
877                }
878
879                if (timeChange) {
880                    sp<AMessage> extra;
881                    if (accessUnit->meta()->findMessage("extra", &extra)
882                            && extra != NULL) {
883                        int64_t resumeAtMediaTimeUs;
884                        if (extra->findInt64(
885                                    "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
886                            ALOGI("suppressing rendering of %s until %lld us",
887                                    audio ? "audio" : "video", resumeAtMediaTimeUs);
888
889                            if (audio) {
890                                mSkipRenderingAudioUntilMediaTimeUs =
891                                    resumeAtMediaTimeUs;
892                            } else {
893                                mSkipRenderingVideoUntilMediaTimeUs =
894                                    resumeAtMediaTimeUs;
895                            }
896                        }
897                    }
898                }
899
900                mTimeDiscontinuityPending =
901                    mTimeDiscontinuityPending || timeChange;
902
903                if (formatChange || timeChange) {
904                    if (mFlushingAudio == NONE && mFlushingVideo == NONE) {
905                        // And we'll resume scanning sources once we're done
906                        // flushing.
907                        mDeferredActions.push_front(
908                                new SimpleAction(
909                                    &NuPlayer::performScanSources));
910                    }
911
912                    flushDecoder(audio, formatChange);
913                } else {
914                    // This stream is unaffected by the discontinuity
915
916                    if (audio) {
917                        mFlushingAudio = FLUSHED;
918                    } else {
919                        mFlushingVideo = FLUSHED;
920                    }
921
922                    finishFlushIfPossible();
923
924                    return -EWOULDBLOCK;
925                }
926            }
927
928            reply->setInt32("err", err);
929            reply->post();
930            return OK;
931        }
932
933        if (!audio) {
934            ++mNumFramesTotal;
935        }
936
937        dropAccessUnit = false;
938        if (!audio
939                && mVideoLateByUs > 100000ll
940                && mVideoIsAVC
941                && !IsAVCReferenceFrame(accessUnit)) {
942            dropAccessUnit = true;
943            ++mNumFramesDropped;
944        }
945    } while (dropAccessUnit);
946
947    // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
948
949#if 0
950    int64_t mediaTimeUs;
951    CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
952    ALOGV("feeding %s input buffer at media time %.2f secs",
953         audio ? "audio" : "video",
954         mediaTimeUs / 1E6);
955#endif
956
957    reply->setBuffer("buffer", accessUnit);
958    reply->post();
959
960    return OK;
961}
962
963void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
964    // ALOGV("renderBuffer %s", audio ? "audio" : "video");
965
966    sp<AMessage> reply;
967    CHECK(msg->findMessage("reply", &reply));
968
969    if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) {
970        // We're currently attempting to flush the decoder, in order
971        // to complete this, the decoder wants all its buffers back,
972        // so we don't want any output buffers it sent us (from before
973        // we initiated the flush) to be stuck in the renderer's queue.
974
975        ALOGV("we're still flushing the %s decoder, sending its output buffer"
976             " right back.", audio ? "audio" : "video");
977
978        reply->post();
979        return;
980    }
981
982    sp<ABuffer> buffer;
983    CHECK(msg->findBuffer("buffer", &buffer));
984
985    int64_t &skipUntilMediaTimeUs =
986        audio
987            ? mSkipRenderingAudioUntilMediaTimeUs
988            : mSkipRenderingVideoUntilMediaTimeUs;
989
990    if (skipUntilMediaTimeUs >= 0) {
991        int64_t mediaTimeUs;
992        CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs));
993
994        if (mediaTimeUs < skipUntilMediaTimeUs) {
995            ALOGV("dropping %s buffer at time %lld as requested.",
996                 audio ? "audio" : "video",
997                 mediaTimeUs);
998
999            reply->post();
1000            return;
1001        }
1002
1003        skipUntilMediaTimeUs = -1;
1004    }
1005
1006    mRenderer->queueBuffer(audio, buffer, reply);
1007}
1008
1009void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
1010    if (mDriver == NULL) {
1011        return;
1012    }
1013
1014    sp<NuPlayerDriver> driver = mDriver.promote();
1015
1016    if (driver == NULL) {
1017        return;
1018    }
1019
1020    driver->notifyListener(msg, ext1, ext2);
1021}
1022
1023void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
1024    if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
1025        ALOGI("flushDecoder %s without decoder present",
1026             audio ? "audio" : "video");
1027    }
1028
1029    // Make sure we don't continue to scan sources until we finish flushing.
1030    ++mScanSourcesGeneration;
1031    mScanSourcesPending = false;
1032
1033    (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
1034    mRenderer->flush(audio);
1035
1036    FlushStatus newStatus =
1037        needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
1038
1039    if (audio) {
1040        CHECK(mFlushingAudio == NONE
1041                || mFlushingAudio == AWAITING_DISCONTINUITY);
1042
1043        mFlushingAudio = newStatus;
1044
1045        if (mFlushingVideo == NONE) {
1046            mFlushingVideo = (mVideoDecoder != NULL)
1047                ? AWAITING_DISCONTINUITY
1048                : FLUSHED;
1049        }
1050    } else {
1051        CHECK(mFlushingVideo == NONE
1052                || mFlushingVideo == AWAITING_DISCONTINUITY);
1053
1054        mFlushingVideo = newStatus;
1055
1056        if (mFlushingAudio == NONE) {
1057            mFlushingAudio = (mAudioDecoder != NULL)
1058                ? AWAITING_DISCONTINUITY
1059                : FLUSHED;
1060        }
1061    }
1062}
1063
1064sp<AMessage> NuPlayer::Source::getFormat(bool audio) {
1065    sp<MetaData> meta = getFormatMeta(audio);
1066
1067    if (meta == NULL) {
1068        return NULL;
1069    }
1070
1071    sp<AMessage> msg = new AMessage;
1072
1073    if(convertMetaDataToMessage(meta, &msg) == OK) {
1074        return msg;
1075    }
1076    return NULL;
1077}
1078
1079status_t NuPlayer::setVideoScalingMode(int32_t mode) {
1080    mVideoScalingMode = mode;
1081    if (mNativeWindow != NULL) {
1082        status_t ret = native_window_set_scaling_mode(
1083                mNativeWindow->getNativeWindow().get(), mVideoScalingMode);
1084        if (ret != OK) {
1085            ALOGE("Failed to set scaling mode (%d): %s",
1086                -ret, strerror(-ret));
1087            return ret;
1088        }
1089    }
1090    return OK;
1091}
1092
1093void NuPlayer::schedulePollDuration() {
1094    sp<AMessage> msg = new AMessage(kWhatPollDuration, id());
1095    msg->setInt32("generation", mPollDurationGeneration);
1096    msg->post();
1097}
1098
1099void NuPlayer::cancelPollDuration() {
1100    ++mPollDurationGeneration;
1101}
1102
1103void NuPlayer::processDeferredActions() {
1104    while (!mDeferredActions.empty()) {
1105        // We won't execute any deferred actions until we're no longer in
1106        // an intermediate state, i.e. one more more decoders are currently
1107        // flushing or shutting down.
1108
1109        if (mRenderer != NULL) {
1110            // There's an edge case where the renderer owns all output
1111            // buffers and is paused, therefore the decoder will not read
1112            // more input data and will never encounter the matching
1113            // discontinuity. To avoid this, we resume the renderer.
1114
1115            if (mFlushingAudio == AWAITING_DISCONTINUITY
1116                    || mFlushingVideo == AWAITING_DISCONTINUITY) {
1117                mRenderer->resume();
1118            }
1119        }
1120
1121        if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
1122            // We're currently flushing, postpone the reset until that's
1123            // completed.
1124
1125            ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d",
1126                  mFlushingAudio, mFlushingVideo);
1127
1128            break;
1129        }
1130
1131        sp<Action> action = *mDeferredActions.begin();
1132        mDeferredActions.erase(mDeferredActions.begin());
1133
1134        action->execute(this);
1135    }
1136}
1137
1138void NuPlayer::performSeek(int64_t seekTimeUs) {
1139    ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)",
1140          seekTimeUs,
1141          seekTimeUs / 1E6);
1142
1143    mSource->seekTo(seekTimeUs);
1144
1145    if (mDriver != NULL) {
1146        sp<NuPlayerDriver> driver = mDriver.promote();
1147        if (driver != NULL) {
1148            driver->notifyPosition(seekTimeUs);
1149            driver->notifySeekComplete();
1150        }
1151    }
1152
1153    // everything's flushed, continue playback.
1154}
1155
1156void NuPlayer::performDecoderFlush() {
1157    ALOGV("performDecoderFlush");
1158
1159    if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
1160        return;
1161    }
1162
1163    mTimeDiscontinuityPending = true;
1164
1165    if (mAudioDecoder != NULL) {
1166        flushDecoder(true /* audio */, false /* needShutdown */);
1167    }
1168
1169    if (mVideoDecoder != NULL) {
1170        flushDecoder(false /* audio */, false /* needShutdown */);
1171    }
1172}
1173
1174void NuPlayer::performDecoderShutdown() {
1175    ALOGV("performDecoderShutdown");
1176
1177    if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
1178        return;
1179    }
1180
1181    mTimeDiscontinuityPending = true;
1182
1183    if (mAudioDecoder != NULL) {
1184        flushDecoder(true /* audio */, true /* needShutdown */);
1185    }
1186
1187    if (mVideoDecoder != NULL) {
1188        flushDecoder(false /* audio */, true /* needShutdown */);
1189    }
1190}
1191
1192void NuPlayer::performReset() {
1193    ALOGV("performReset");
1194
1195    CHECK(mAudioDecoder == NULL);
1196    CHECK(mVideoDecoder == NULL);
1197
1198    cancelPollDuration();
1199
1200    ++mScanSourcesGeneration;
1201    mScanSourcesPending = false;
1202
1203    mRenderer.clear();
1204
1205    if (mSource != NULL) {
1206        mSource->stop();
1207
1208        looper()->unregisterHandler(mSource->id());
1209
1210        mSource.clear();
1211    }
1212
1213    if (mDriver != NULL) {
1214        sp<NuPlayerDriver> driver = mDriver.promote();
1215        if (driver != NULL) {
1216            driver->notifyResetComplete();
1217        }
1218    }
1219
1220    mStarted = false;
1221}
1222
1223void NuPlayer::performScanSources() {
1224    ALOGV("performScanSources");
1225
1226    if (!mStarted) {
1227        return;
1228    }
1229
1230    if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
1231        postScanSources();
1232    }
1233}
1234
1235void NuPlayer::performSetSurface(const sp<NativeWindowWrapper> &wrapper) {
1236    ALOGV("performSetSurface");
1237
1238    mNativeWindow = wrapper;
1239
1240    // XXX - ignore error from setVideoScalingMode for now
1241    setVideoScalingMode(mVideoScalingMode);
1242
1243    if (mDriver != NULL) {
1244        sp<NuPlayerDriver> driver = mDriver.promote();
1245        if (driver != NULL) {
1246            driver->notifySetSurfaceComplete();
1247        }
1248    }
1249}
1250
1251void NuPlayer::onSourceNotify(const sp<AMessage> &msg) {
1252    int32_t what;
1253    CHECK(msg->findInt32("what", &what));
1254
1255    switch (what) {
1256        case Source::kWhatPrepared:
1257        {
1258            sp<NuPlayerDriver> driver = mDriver.promote();
1259            if (driver != NULL) {
1260                driver->notifyPrepareCompleted(OK);
1261            }
1262            break;
1263        }
1264
1265        case Source::kWhatFlagsChanged:
1266        {
1267            uint32_t flags;
1268            CHECK(msg->findInt32("flags", (int32_t *)&flags));
1269
1270            if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
1271                    && (!(flags & Source::FLAG_DYNAMIC_DURATION))) {
1272                cancelPollDuration();
1273            } else if (!(mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
1274                    && (flags & Source::FLAG_DYNAMIC_DURATION)
1275                    && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
1276                schedulePollDuration();
1277            }
1278
1279            mSourceFlags = flags;
1280            break;
1281        }
1282
1283        case Source::kWhatVideoSizeChanged:
1284        {
1285            int32_t width, height;
1286            CHECK(msg->findInt32("width", &width));
1287            CHECK(msg->findInt32("height", &height));
1288
1289            notifyListener(MEDIA_SET_VIDEO_SIZE, width, height);
1290            break;
1291        }
1292
1293        default:
1294            TRESPASS();
1295    }
1296}
1297
1298////////////////////////////////////////////////////////////////////////////////
1299
1300void NuPlayer::Source::notifyFlagsChanged(uint32_t flags) {
1301    sp<AMessage> notify = dupNotify();
1302    notify->setInt32("what", kWhatFlagsChanged);
1303    notify->setInt32("flags", flags);
1304    notify->post();
1305}
1306
1307void NuPlayer::Source::notifyVideoSizeChanged(int32_t width, int32_t height) {
1308    sp<AMessage> notify = dupNotify();
1309    notify->setInt32("what", kWhatVideoSizeChanged);
1310    notify->setInt32("width", width);
1311    notify->setInt32("height", height);
1312    notify->post();
1313}
1314
1315void NuPlayer::Source::notifyPrepared() {
1316    sp<AMessage> notify = dupNotify();
1317    notify->setInt32("what", kWhatPrepared);
1318    notify->post();
1319}
1320
1321void NuPlayer::Source::onMessageReceived(const sp<AMessage> &msg) {
1322    TRESPASS();
1323}
1324
1325}  // namespace android
1326