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