NuPlayer.cpp revision f3b5190f2aa659d498b1d31389b90a441fc879a7
1eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov/* 2eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov * Copyright (C) 2010 The Android Open Source Project 3eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov * 4eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov * Licensed under the Apache License, Version 2.0 (the "License"); 5eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov * you may not use this file except in compliance with the License. 6eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov * You may obtain a copy of the License at 7eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov * 8eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov * http://www.apache.org/licenses/LICENSE-2.0 9eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov * 10eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov * Unless required by applicable law or agreed to in writing, software 11eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov * distributed under the License is distributed on an "AS IS" BASIS, 12eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov * See the License for the specific language governing permissions and 14eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov * limitations under the License. 15eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov */ 16eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 17eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov//#define LOG_NDEBUG 0 18eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#define LOG_TAG "NuPlayer" 19eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include <utils/Log.h> 20eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 21eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "NuPlayer.h" 22eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 23eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "HTTPLiveSource.h" 24eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "NuPlayerDecoder.h" 25eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "NuPlayerDecoderPassThrough.h" 26eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "NuPlayerDriver.h" 27eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "NuPlayerRenderer.h" 28eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "NuPlayerSource.h" 29eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "RTSPSource.h" 30eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "StreamingSource.h" 31eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "GenericSource.h" 32eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "TextDescriptions.h" 33eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 34eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "ATSParser.h" 35eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 36eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include <media/stagefright/foundation/hexdump.h> 37eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include <media/stagefright/foundation/ABuffer.h> 38eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include <media/stagefright/foundation/ADebug.h> 39eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include <media/stagefright/foundation/AMessage.h> 40eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include <media/stagefright/MediaBuffer.h> 41eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include <media/stagefright/MediaDefs.h> 42eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include <media/stagefright/MediaErrors.h> 43eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include <media/stagefright/MetaData.h> 44eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include <gui/IGraphicBufferProducer.h> 45eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 46eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "avc_utils.h" 47eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 48eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include "ESDS.h" 49eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov#include <media/stagefright/Utils.h> 50eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 51eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovnamespace android { 52eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 53eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovstruct NuPlayer::Action : public RefBase { 54eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov Action() {} 55eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 56eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov virtual void execute(NuPlayer *player) = 0; 57eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 58eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovprivate: 59eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov DISALLOW_EVIL_CONSTRUCTORS(Action); 60eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov}; 61eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 62eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovstruct NuPlayer::SeekAction : public Action { 63eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov SeekAction(int64_t seekTimeUs) 64eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov : mSeekTimeUs(seekTimeUs) { 65eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 66eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 67eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov virtual void execute(NuPlayer *player) { 68eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov player->performSeek(mSeekTimeUs); 69eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 70eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 71eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovprivate: 72eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov int64_t mSeekTimeUs; 73eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 74eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov DISALLOW_EVIL_CONSTRUCTORS(SeekAction); 75eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov}; 76eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 77eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovstruct NuPlayer::SetSurfaceAction : public Action { 78eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov SetSurfaceAction(const sp<NativeWindowWrapper> &wrapper) 79eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov : mWrapper(wrapper) { 80eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 81eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 82eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov virtual void execute(NuPlayer *player) { 83eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov player->performSetSurface(mWrapper); 84eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 85eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 86eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovprivate: 87eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov sp<NativeWindowWrapper> mWrapper; 88eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 89eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction); 90eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov}; 91eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 92eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovstruct NuPlayer::ShutdownDecoderAction : public Action { 93eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov ShutdownDecoderAction(bool audio, bool video) 94eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov : mAudio(audio), 95eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mVideo(video) { 96eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 97eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 98eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov virtual void execute(NuPlayer *player) { 99eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov player->performDecoderShutdown(mAudio, mVideo); 100eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 101eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 102eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovprivate: 103eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov bool mAudio; 104eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov bool mVideo; 105eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 106eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov DISALLOW_EVIL_CONSTRUCTORS(ShutdownDecoderAction); 107eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov}; 108eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 109eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovstruct NuPlayer::PostMessageAction : public Action { 110eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov PostMessageAction(const sp<AMessage> &msg) 111eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov : mMessage(msg) { 112eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 113eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 114eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov virtual void execute(NuPlayer *) { 115eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mMessage->post(); 116eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 117eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 118eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovprivate: 119eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov sp<AMessage> mMessage; 120eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 121eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov DISALLOW_EVIL_CONSTRUCTORS(PostMessageAction); 122eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov}; 123eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 124eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov// Use this if there's no state necessary to save in order to execute 125eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov// the action. 126eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovstruct NuPlayer::SimpleAction : public Action { 127eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov typedef void (NuPlayer::*ActionFunc)(); 128eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 129eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov SimpleAction(ActionFunc func) 130eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov : mFunc(func) { 131eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 132eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 133eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov virtual void execute(NuPlayer *player) { 134eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov (player->*mFunc)(); 135eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 136eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 137eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovprivate: 138eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov ActionFunc mFunc; 139eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 140eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov DISALLOW_EVIL_CONSTRUCTORS(SimpleAction); 141eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov}; 142eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 143eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov//////////////////////////////////////////////////////////////////////////////// 144eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 145eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy IvanovNuPlayer::NuPlayer() 146eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov : mUIDValid(false), 147eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mSourceFlags(0), 148eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mCurrentPositionUs(0), 149eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mVideoIsAVC(false), 150eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mOffloadAudio(false), 151eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER), 152eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mAudioDecoderGeneration(0), 153eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mVideoDecoderGeneration(0), 154eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mAudioEOS(false), 155eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mVideoEOS(false), 156eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mScanSourcesPending(false), 157eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mScanSourcesGeneration(0), 158eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mPollDurationGeneration(0), 159eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mTimedTextGeneration(0), 160eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mTimeDiscontinuityPending(false), 161eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mFlushingAudio(NONE), 162eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mFlushingVideo(NONE), 163eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mSkipRenderingAudioUntilMediaTimeUs(-1ll), 164eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mSkipRenderingVideoUntilMediaTimeUs(-1ll), 165eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mVideoLateByUs(0ll), 166eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mNumFramesTotal(0ll), 167eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mNumFramesDropped(0ll), 168eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW), 169eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mStarted(false) { 170eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 171eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 172eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy IvanovNuPlayer::~NuPlayer() { 173eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 174eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 175eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid NuPlayer::setUID(uid_t uid) { 176eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mUIDValid = true; 177eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mUID = uid; 178eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 179eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 180eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) { 181eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov mDriver = driver; 182eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 183eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 184eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) { 185eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); 186eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 187eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov sp<AMessage> notify = new AMessage(kWhatSourceNotify, id()); 188eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 189eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov msg->setObject("source", new StreamingSource(notify, source)); 190eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov msg->post(); 191eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 192eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 193eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovstatic bool IsHTTPLiveURL(const char *url) { 194eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov if (!strncasecmp("http://", url, 7) 195eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov || !strncasecmp("https://", url, 8) 196eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov || !strncasecmp("file://", url, 7)) { 197eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov size_t len = strlen(url); 198eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) { 199eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov return true; 200eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 201eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 202eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov if (strstr(url,"m3u8")) { 203eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov return true; 204eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 205eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 206eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 207eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov return false; 208eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 209eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 210eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid NuPlayer::setDataSourceAsync( 211eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov const sp<IMediaHTTPService> &httpService, 212eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov const char *url, 213eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov const KeyedVector<String8, String8> *headers) { 214eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 215eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); 216eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov size_t len = strlen(url); 217eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 218eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov sp<AMessage> notify = new AMessage(kWhatSourceNotify, id()); 219eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 220eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov sp<Source> source; 221eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov if (IsHTTPLiveURL(url)) { 222eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov source = new HTTPLiveSource(notify, httpService, url, headers); 223eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } else if (!strncasecmp(url, "rtsp://", 7)) { 224eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov source = new RTSPSource( 225eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov notify, httpService, url, headers, mUIDValid, mUID); 226eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } else if ((!strncasecmp(url, "http://", 7) 227eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov || !strncasecmp(url, "https://", 8)) 228eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) 229eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov || strstr(url, ".sdp?"))) { 230eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov source = new RTSPSource( 231eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov notify, httpService, url, headers, mUIDValid, mUID, true); 232eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } else { 233eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov sp<GenericSource> genericSource = 234eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov new GenericSource(notify, mUIDValid, mUID); 235eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov // Don't set FLAG_SECURE on mSourceFlags here for widevine. 236eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov // The correct flags will be updated in Source::kWhatFlagsChanged 237eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov // handler when GenericSource is prepared. 238eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 239eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov status_t err = genericSource->setDataSource(httpService, url, headers); 240eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 241eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov if (err == OK) { 242eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov source = genericSource; 243eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } else { 244eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov ALOGE("Failed to set data source!"); 245eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 246eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 247eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov msg->setObject("source", source); 248eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov msg->post(); 249eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 250eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 251eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) { 252eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); 253eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 254eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov sp<AMessage> notify = new AMessage(kWhatSourceNotify, id()); 255eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 256eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov sp<GenericSource> source = 257eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov new GenericSource(notify, mUIDValid, mUID); 258eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 259eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov status_t err = source->setDataSource(fd, offset, length); 260eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 261eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov if (err != OK) { 262eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov ALOGE("Failed to set data source!"); 263eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov source = NULL; 264eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 265eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 266eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov msg->setObject("source", source); 267eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov msg->post(); 268eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 269eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 270eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid NuPlayer::prepareAsync() { 271eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov (new AMessage(kWhatPrepare, id()))->post(); 272eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 273eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 274eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid NuPlayer::setVideoSurfaceTextureAsync( 275eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov const sp<IGraphicBufferProducer> &bufferProducer) { 276eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id()); 277eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 278eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov if (bufferProducer == NULL) { 279eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov msg->setObject("native-window", NULL); 280eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } else { 281eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov msg->setObject( 282eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov "native-window", 283eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov new NativeWindowWrapper( 284eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov new Surface(bufferProducer, true /* controlledByApp */))); 285eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 286eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 287eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov msg->post(); 288eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 289eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 290eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) { 291eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id()); 292eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov msg->setObject("sink", sink); 293eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov msg->post(); 294eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 295eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 296eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid NuPlayer::start() { 297eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov (new AMessage(kWhatStart, id()))->post(); 298eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 299eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 300eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid NuPlayer::pause() { 301eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov (new AMessage(kWhatPause, id()))->post(); 302eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 303eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 304eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid NuPlayer::resume() { 305eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov (new AMessage(kWhatResume, id()))->post(); 306eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 307eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 308eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid NuPlayer::resetAsync() { 309eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov (new AMessage(kWhatReset, id()))->post(); 310eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 311eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 312eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid NuPlayer::seekToAsync(int64_t seekTimeUs) { 313eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov sp<AMessage> msg = new AMessage(kWhatSeek, id()); 314eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov msg->setInt64("seekTimeUs", seekTimeUs); 315eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov msg->post(); 316eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 317eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 318eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov// static 319eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovbool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) { 320eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov switch (state) { 321eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov case FLUSHING_DECODER: 322eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov if (needShutdown != NULL) { 323eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov *needShutdown = false; 324eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 325eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov return true; 326eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 327eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov case FLUSHING_DECODER_SHUTDOWN: 328eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov if (needShutdown != NULL) { 329eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov *needShutdown = true; 330eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 331eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov return true; 332eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 333eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov default: 334eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov return false; 335eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov } 336eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov} 337eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 338eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanovvoid NuPlayer::writeTrackInfo( 339eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov Parcel* reply, const sp<AMessage> format) const { 340eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov int32_t trackType; 341eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov CHECK(format->findInt32("type", &trackType)); 342eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 343eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov AString lang; 344eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov CHECK(format->findString("language", &lang)); 345eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 346eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov reply->writeInt32(2); // write something non-zero 347eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov reply->writeInt32(trackType); 348eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov reply->writeString16(String16(lang.c_str())); 349eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 350eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) { 351eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov AString mime; 352eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov CHECK(format->findString("mime", &mime)); 353eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov 354eb0bae136f4eeaaf29761dddb148b118fb824632Dmitriy Ivanov int32_t isAuto, isDefault, isForced; 355 CHECK(format->findInt32("auto", &isAuto)); 356 CHECK(format->findInt32("default", &isDefault)); 357 CHECK(format->findInt32("forced", &isForced)); 358 359 reply->writeString16(String16(mime.c_str())); 360 reply->writeInt32(isAuto); 361 reply->writeInt32(isDefault); 362 reply->writeInt32(isForced); 363 } 364} 365 366void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { 367 switch (msg->what()) { 368 case kWhatSetDataSource: 369 { 370 ALOGV("kWhatSetDataSource"); 371 372 CHECK(mSource == NULL); 373 374 status_t err = OK; 375 sp<RefBase> obj; 376 CHECK(msg->findObject("source", &obj)); 377 if (obj != NULL) { 378 mSource = static_cast<Source *>(obj.get()); 379 } else { 380 err = UNKNOWN_ERROR; 381 } 382 383 CHECK(mDriver != NULL); 384 sp<NuPlayerDriver> driver = mDriver.promote(); 385 if (driver != NULL) { 386 driver->notifySetDataSourceCompleted(err); 387 } 388 break; 389 } 390 391 case kWhatPrepare: 392 { 393 mSource->prepareAsync(); 394 break; 395 } 396 397 case kWhatGetTrackInfo: 398 { 399 uint32_t replyID; 400 CHECK(msg->senderAwaitsResponse(&replyID)); 401 402 Parcel* reply; 403 CHECK(msg->findPointer("reply", (void**)&reply)); 404 405 size_t inbandTracks = 0; 406 if (mSource != NULL) { 407 inbandTracks = mSource->getTrackCount(); 408 } 409 410 size_t ccTracks = 0; 411 if (mCCDecoder != NULL) { 412 ccTracks = mCCDecoder->getTrackCount(); 413 } 414 415 // total track count 416 reply->writeInt32(inbandTracks + ccTracks); 417 418 // write inband tracks 419 for (size_t i = 0; i < inbandTracks; ++i) { 420 writeTrackInfo(reply, mSource->getTrackInfo(i)); 421 } 422 423 // write CC track 424 for (size_t i = 0; i < ccTracks; ++i) { 425 writeTrackInfo(reply, mCCDecoder->getTrackInfo(i)); 426 } 427 428 sp<AMessage> response = new AMessage; 429 response->postReply(replyID); 430 break; 431 } 432 433 case kWhatGetSelectedTrack: 434 { 435 status_t err = INVALID_OPERATION; 436 if (mSource != NULL) { 437 err = OK; 438 439 int32_t type32; 440 CHECK(msg->findInt32("type", (int32_t*)&type32)); 441 media_track_type type = (media_track_type)type32; 442 ssize_t selectedTrack = mSource->getSelectedTrack(type); 443 444 Parcel* reply; 445 CHECK(msg->findPointer("reply", (void**)&reply)); 446 reply->writeInt32(selectedTrack); 447 } 448 449 sp<AMessage> response = new AMessage; 450 response->setInt32("err", err); 451 452 uint32_t replyID; 453 CHECK(msg->senderAwaitsResponse(&replyID)); 454 response->postReply(replyID); 455 break; 456 } 457 458 case kWhatSelectTrack: 459 { 460 uint32_t replyID; 461 CHECK(msg->senderAwaitsResponse(&replyID)); 462 463 size_t trackIndex; 464 int32_t select; 465 CHECK(msg->findSize("trackIndex", &trackIndex)); 466 CHECK(msg->findInt32("select", &select)); 467 468 status_t err = INVALID_OPERATION; 469 470 size_t inbandTracks = 0; 471 if (mSource != NULL) { 472 inbandTracks = mSource->getTrackCount(); 473 } 474 size_t ccTracks = 0; 475 if (mCCDecoder != NULL) { 476 ccTracks = mCCDecoder->getTrackCount(); 477 } 478 479 if (trackIndex < inbandTracks) { 480 err = mSource->selectTrack(trackIndex, select); 481 482 if (!select && err == OK) { 483 int32_t type; 484 sp<AMessage> info = mSource->getTrackInfo(trackIndex); 485 if (info != NULL 486 && info->findInt32("type", &type) 487 && type == MEDIA_TRACK_TYPE_TIMEDTEXT) { 488 ++mTimedTextGeneration; 489 } 490 } 491 } else { 492 trackIndex -= inbandTracks; 493 494 if (trackIndex < ccTracks) { 495 err = mCCDecoder->selectTrack(trackIndex, select); 496 } 497 } 498 499 sp<AMessage> response = new AMessage; 500 response->setInt32("err", err); 501 502 response->postReply(replyID); 503 break; 504 } 505 506 case kWhatPollDuration: 507 { 508 int32_t generation; 509 CHECK(msg->findInt32("generation", &generation)); 510 511 if (generation != mPollDurationGeneration) { 512 // stale 513 break; 514 } 515 516 int64_t durationUs; 517 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) { 518 sp<NuPlayerDriver> driver = mDriver.promote(); 519 if (driver != NULL) { 520 driver->notifyDuration(durationUs); 521 } 522 } 523 524 msg->post(1000000ll); // poll again in a second. 525 break; 526 } 527 528 case kWhatSetVideoNativeWindow: 529 { 530 ALOGV("kWhatSetVideoNativeWindow"); 531 532 mDeferredActions.push_back( 533 new ShutdownDecoderAction( 534 false /* audio */, true /* video */)); 535 536 sp<RefBase> obj; 537 CHECK(msg->findObject("native-window", &obj)); 538 539 mDeferredActions.push_back( 540 new SetSurfaceAction( 541 static_cast<NativeWindowWrapper *>(obj.get()))); 542 543 if (obj != NULL) { 544 if (mStarted && mVideoDecoder != NULL) { 545 // Issue a seek to refresh the video screen only if started otherwise 546 // the extractor may not yet be started and will assert. 547 // If the video decoder is not set (perhaps audio only in this case) 548 // do not perform a seek as it is not needed. 549 mDeferredActions.push_back(new SeekAction(mCurrentPositionUs)); 550 } 551 552 // If there is a new surface texture, instantiate decoders 553 // again if possible. 554 mDeferredActions.push_back( 555 new SimpleAction(&NuPlayer::performScanSources)); 556 } 557 558 processDeferredActions(); 559 break; 560 } 561 562 case kWhatSetAudioSink: 563 { 564 ALOGV("kWhatSetAudioSink"); 565 566 sp<RefBase> obj; 567 CHECK(msg->findObject("sink", &obj)); 568 569 mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get()); 570 break; 571 } 572 573 case kWhatStart: 574 { 575 ALOGV("kWhatStart"); 576 577 mVideoIsAVC = false; 578 mOffloadAudio = false; 579 mAudioEOS = false; 580 mVideoEOS = false; 581 mSkipRenderingAudioUntilMediaTimeUs = -1; 582 mSkipRenderingVideoUntilMediaTimeUs = -1; 583 mVideoLateByUs = 0; 584 mNumFramesTotal = 0; 585 mNumFramesDropped = 0; 586 mStarted = true; 587 588 /* instantiate decoders now for secure playback */ 589 if (mSourceFlags & Source::FLAG_SECURE) { 590 if (mNativeWindow != NULL) { 591 instantiateDecoder(false, &mVideoDecoder); 592 } 593 594 if (mAudioSink != NULL) { 595 instantiateDecoder(true, &mAudioDecoder); 596 } 597 } 598 599 mSource->start(); 600 601 uint32_t flags = 0; 602 603 if (mSource->isRealTime()) { 604 flags |= Renderer::FLAG_REAL_TIME; 605 } 606 607 sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */); 608 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC; 609 if (mAudioSink != NULL) { 610 streamType = mAudioSink->getAudioStreamType(); 611 } 612 613 sp<AMessage> videoFormat = mSource->getFormat(false /* audio */); 614 615 mOffloadAudio = 616 canOffloadStream(audioMeta, (videoFormat != NULL), 617 true /* is_streaming */, streamType); 618 if (mOffloadAudio) { 619 flags |= Renderer::FLAG_OFFLOAD_AUDIO; 620 } 621 622 mRenderer = new Renderer( 623 mAudioSink, 624 new AMessage(kWhatRendererNotify, id()), 625 flags); 626 627 mRendererLooper = new ALooper; 628 mRendererLooper->setName("NuPlayerRenderer"); 629 mRendererLooper->start(false, false, ANDROID_PRIORITY_AUDIO); 630 mRendererLooper->registerHandler(mRenderer); 631 632 postScanSources(); 633 break; 634 } 635 636 case kWhatScanSources: 637 { 638 int32_t generation; 639 CHECK(msg->findInt32("generation", &generation)); 640 if (generation != mScanSourcesGeneration) { 641 // Drop obsolete msg. 642 break; 643 } 644 645 mScanSourcesPending = false; 646 647 ALOGV("scanning sources haveAudio=%d, haveVideo=%d", 648 mAudioDecoder != NULL, mVideoDecoder != NULL); 649 650 bool mHadAnySourcesBefore = 651 (mAudioDecoder != NULL) || (mVideoDecoder != NULL); 652 653 // initialize video before audio because successful initialization of 654 // video may change deep buffer mode of audio. 655 if (mNativeWindow != NULL) { 656 instantiateDecoder(false, &mVideoDecoder); 657 } 658 659 if (mAudioSink != NULL) { 660 if (mOffloadAudio) { 661 // open audio sink early under offload mode. 662 sp<AMessage> format = mSource->getFormat(true /*audio*/); 663 openAudioSink(format, true /*offloadOnly*/); 664 } 665 instantiateDecoder(true, &mAudioDecoder); 666 } 667 668 if (!mHadAnySourcesBefore 669 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) { 670 // This is the first time we've found anything playable. 671 672 if (mSourceFlags & Source::FLAG_DYNAMIC_DURATION) { 673 schedulePollDuration(); 674 } 675 } 676 677 status_t err; 678 if ((err = mSource->feedMoreTSData()) != OK) { 679 if (mAudioDecoder == NULL && mVideoDecoder == NULL) { 680 // We're not currently decoding anything (no audio or 681 // video tracks found) and we just ran out of input data. 682 683 if (err == ERROR_END_OF_STREAM) { 684 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); 685 } else { 686 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 687 } 688 } 689 break; 690 } 691 692 if ((mAudioDecoder == NULL && mAudioSink != NULL) 693 || (mVideoDecoder == NULL && mNativeWindow != NULL)) { 694 msg->post(100000ll); 695 mScanSourcesPending = true; 696 } 697 break; 698 } 699 700 case kWhatVideoNotify: 701 case kWhatAudioNotify: 702 { 703 bool audio = msg->what() == kWhatAudioNotify; 704 705 int32_t currentDecoderGeneration = 706 (audio? mAudioDecoderGeneration : mVideoDecoderGeneration); 707 int32_t requesterGeneration = currentDecoderGeneration - 1; 708 CHECK(msg->findInt32("generation", &requesterGeneration)); 709 710 if (requesterGeneration != currentDecoderGeneration) { 711 ALOGV("got message from old %s decoder, generation(%d:%d)", 712 audio ? "audio" : "video", requesterGeneration, 713 currentDecoderGeneration); 714 sp<AMessage> reply; 715 if (!(msg->findMessage("reply", &reply))) { 716 return; 717 } 718 719 reply->setInt32("err", INFO_DISCONTINUITY); 720 reply->post(); 721 return; 722 } 723 724 int32_t what; 725 CHECK(msg->findInt32("what", &what)); 726 727 if (what == Decoder::kWhatFillThisBuffer) { 728 status_t err = feedDecoderInputData( 729 audio, msg); 730 731 if (err == -EWOULDBLOCK) { 732 if (mSource->feedMoreTSData() == OK) { 733 msg->post(10000ll); 734 } 735 } 736 } else if (what == Decoder::kWhatEOS) { 737 int32_t err; 738 CHECK(msg->findInt32("err", &err)); 739 740 if (err == ERROR_END_OF_STREAM) { 741 ALOGV("got %s decoder EOS", audio ? "audio" : "video"); 742 } else { 743 ALOGV("got %s decoder EOS w/ error %d", 744 audio ? "audio" : "video", 745 err); 746 } 747 748 mRenderer->queueEOS(audio, err); 749 } else if (what == Decoder::kWhatFlushCompleted) { 750 bool needShutdown; 751 752 if (audio) { 753 CHECK(IsFlushingState(mFlushingAudio, &needShutdown)); 754 mFlushingAudio = FLUSHED; 755 } else { 756 CHECK(IsFlushingState(mFlushingVideo, &needShutdown)); 757 mFlushingVideo = FLUSHED; 758 759 mVideoLateByUs = 0; 760 } 761 762 ALOGV("decoder %s flush completed", audio ? "audio" : "video"); 763 764 if (needShutdown) { 765 ALOGV("initiating %s decoder shutdown", 766 audio ? "audio" : "video"); 767 768 getDecoder(audio)->initiateShutdown(); 769 770 if (audio) { 771 mFlushingAudio = SHUTTING_DOWN_DECODER; 772 } else { 773 mFlushingVideo = SHUTTING_DOWN_DECODER; 774 } 775 } 776 777 finishFlushIfPossible(); 778 } else if (what == Decoder::kWhatOutputFormatChanged) { 779 sp<AMessage> format; 780 CHECK(msg->findMessage("format", &format)); 781 782 if (audio) { 783 openAudioSink(format, false /*offloadOnly*/); 784 } else { 785 // video 786 sp<AMessage> inputFormat = 787 mSource->getFormat(false /* audio */); 788 789 updateVideoSize(inputFormat, format); 790 } 791 } else if (what == Decoder::kWhatShutdownCompleted) { 792 ALOGV("%s shutdown completed", audio ? "audio" : "video"); 793 if (audio) { 794 mAudioDecoder.clear(); 795 796 CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER); 797 mFlushingAudio = SHUT_DOWN; 798 } else { 799 mVideoDecoder.clear(); 800 801 CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER); 802 mFlushingVideo = SHUT_DOWN; 803 } 804 805 finishFlushIfPossible(); 806 } else if (what == Decoder::kWhatError) { 807 ALOGE("Received error from %s decoder, aborting playback.", 808 audio ? "audio" : "video"); 809 810 status_t err; 811 if (!msg->findInt32("err", &err)) { 812 err = UNKNOWN_ERROR; 813 } 814 mRenderer->queueEOS(audio, err); 815 if (audio && mFlushingAudio != NONE) { 816 mAudioDecoder.clear(); 817 mFlushingAudio = SHUT_DOWN; 818 } else if (!audio && mFlushingVideo != NONE){ 819 mVideoDecoder.clear(); 820 mFlushingVideo = SHUT_DOWN; 821 } 822 finishFlushIfPossible(); 823 } else if (what == Decoder::kWhatDrainThisBuffer) { 824 renderBuffer(audio, msg); 825 } else { 826 ALOGV("Unhandled decoder notification %d '%c%c%c%c'.", 827 what, 828 what >> 24, 829 (what >> 16) & 0xff, 830 (what >> 8) & 0xff, 831 what & 0xff); 832 } 833 834 break; 835 } 836 837 case kWhatRendererNotify: 838 { 839 int32_t what; 840 CHECK(msg->findInt32("what", &what)); 841 842 if (what == Renderer::kWhatEOS) { 843 int32_t audio; 844 CHECK(msg->findInt32("audio", &audio)); 845 846 int32_t finalResult; 847 CHECK(msg->findInt32("finalResult", &finalResult)); 848 849 if (audio) { 850 mAudioEOS = true; 851 } else { 852 mVideoEOS = true; 853 } 854 855 if (finalResult == ERROR_END_OF_STREAM) { 856 ALOGV("reached %s EOS", audio ? "audio" : "video"); 857 } else { 858 ALOGE("%s track encountered an error (%d)", 859 audio ? "audio" : "video", finalResult); 860 861 notifyListener( 862 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult); 863 } 864 865 if ((mAudioEOS || mAudioDecoder == NULL) 866 && (mVideoEOS || mVideoDecoder == NULL)) { 867 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); 868 } 869 } else if (what == Renderer::kWhatPosition) { 870 int64_t positionUs; 871 CHECK(msg->findInt64("positionUs", &positionUs)); 872 mCurrentPositionUs = positionUs; 873 874 CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs)); 875 876 if (mDriver != NULL) { 877 sp<NuPlayerDriver> driver = mDriver.promote(); 878 if (driver != NULL) { 879 driver->notifyPosition(positionUs); 880 881 driver->notifyFrameStats( 882 mNumFramesTotal, mNumFramesDropped); 883 } 884 } 885 } else if (what == Renderer::kWhatFlushComplete) { 886 int32_t audio; 887 CHECK(msg->findInt32("audio", &audio)); 888 889 ALOGV("renderer %s flush completed.", audio ? "audio" : "video"); 890 } else if (what == Renderer::kWhatVideoRenderingStart) { 891 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0); 892 } else if (what == Renderer::kWhatMediaRenderingStart) { 893 ALOGV("media rendering started"); 894 notifyListener(MEDIA_STARTED, 0, 0); 895 } else if (what == Renderer::kWhatAudioOffloadTearDown) { 896 ALOGV("Tear down audio offload, fall back to s/w path"); 897 int64_t positionUs; 898 CHECK(msg->findInt64("positionUs", &positionUs)); 899 closeAudioSink(); 900 mAudioDecoder.clear(); 901 mRenderer->flush(true /* audio */); 902 if (mVideoDecoder != NULL) { 903 mRenderer->flush(false /* audio */); 904 } 905 mRenderer->signalDisableOffloadAudio(); 906 mOffloadAudio = false; 907 908 performSeek(positionUs); 909 instantiateDecoder(true /* audio */, &mAudioDecoder); 910 } 911 break; 912 } 913 914 case kWhatMoreDataQueued: 915 { 916 break; 917 } 918 919 case kWhatReset: 920 { 921 ALOGV("kWhatReset"); 922 923 mDeferredActions.push_back( 924 new ShutdownDecoderAction( 925 true /* audio */, true /* video */)); 926 927 mDeferredActions.push_back( 928 new SimpleAction(&NuPlayer::performReset)); 929 930 processDeferredActions(); 931 break; 932 } 933 934 case kWhatSeek: 935 { 936 int64_t seekTimeUs; 937 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs)); 938 939 ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs); 940 941 mDeferredActions.push_back( 942 new SimpleAction(&NuPlayer::performDecoderFlush)); 943 944 mDeferredActions.push_back(new SeekAction(seekTimeUs)); 945 946 processDeferredActions(); 947 break; 948 } 949 950 case kWhatPause: 951 { 952 CHECK(mRenderer != NULL); 953 mSource->pause(); 954 mRenderer->pause(); 955 break; 956 } 957 958 case kWhatResume: 959 { 960 CHECK(mRenderer != NULL); 961 mSource->resume(); 962 mRenderer->resume(); 963 break; 964 } 965 966 case kWhatSourceNotify: 967 { 968 onSourceNotify(msg); 969 break; 970 } 971 972 case kWhatClosedCaptionNotify: 973 { 974 onClosedCaptionNotify(msg); 975 break; 976 } 977 978 default: 979 TRESPASS(); 980 break; 981 } 982} 983 984void NuPlayer::finishFlushIfPossible() { 985 if (mFlushingAudio != NONE && mFlushingAudio != FLUSHED 986 && mFlushingAudio != SHUT_DOWN) { 987 return; 988 } 989 990 if (mFlushingVideo != NONE && mFlushingVideo != FLUSHED 991 && mFlushingVideo != SHUT_DOWN) { 992 return; 993 } 994 995 ALOGV("both audio and video are flushed now."); 996 997 mPendingAudioAccessUnit.clear(); 998 999 if (mTimeDiscontinuityPending) { 1000 mRenderer->signalTimeDiscontinuity(); 1001 mTimeDiscontinuityPending = false; 1002 } 1003 1004 if (mAudioDecoder != NULL && mFlushingAudio == FLUSHED) { 1005 mAudioDecoder->signalResume(); 1006 } 1007 1008 if (mVideoDecoder != NULL && mFlushingVideo == FLUSHED) { 1009 mVideoDecoder->signalResume(); 1010 } 1011 1012 mFlushingAudio = NONE; 1013 mFlushingVideo = NONE; 1014 1015 processDeferredActions(); 1016} 1017 1018void NuPlayer::postScanSources() { 1019 if (mScanSourcesPending) { 1020 return; 1021 } 1022 1023 sp<AMessage> msg = new AMessage(kWhatScanSources, id()); 1024 msg->setInt32("generation", mScanSourcesGeneration); 1025 msg->post(); 1026 1027 mScanSourcesPending = true; 1028} 1029 1030void NuPlayer::openAudioSink(const sp<AMessage> &format, bool offloadOnly) { 1031 ALOGV("openAudioSink: offloadOnly(%d) mOffloadAudio(%d)", 1032 offloadOnly, mOffloadAudio); 1033 bool audioSinkChanged = false; 1034 1035 int32_t numChannels; 1036 CHECK(format->findInt32("channel-count", &numChannels)); 1037 1038 int32_t channelMask; 1039 if (!format->findInt32("channel-mask", &channelMask)) { 1040 // signal to the AudioSink to derive the mask from count. 1041 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER; 1042 } 1043 1044 int32_t sampleRate; 1045 CHECK(format->findInt32("sample-rate", &sampleRate)); 1046 1047 uint32_t flags; 1048 int64_t durationUs; 1049 // FIXME: we should handle the case where the video decoder 1050 // is created after we receive the format change indication. 1051 // Current code will just make that we select deep buffer 1052 // with video which should not be a problem as it should 1053 // not prevent from keeping A/V sync. 1054 if (mVideoDecoder == NULL && 1055 mSource->getDuration(&durationUs) == OK && 1056 durationUs 1057 > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) { 1058 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; 1059 } else { 1060 flags = AUDIO_OUTPUT_FLAG_NONE; 1061 } 1062 1063 if (mOffloadAudio) { 1064 audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT; 1065 AString mime; 1066 CHECK(format->findString("mime", &mime)); 1067 status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str()); 1068 1069 if (err != OK) { 1070 ALOGE("Couldn't map mime \"%s\" to a valid " 1071 "audio_format", mime.c_str()); 1072 mOffloadAudio = false; 1073 } else { 1074 ALOGV("Mime \"%s\" mapped to audio_format 0x%x", 1075 mime.c_str(), audioFormat); 1076 1077 int avgBitRate = -1; 1078 format->findInt32("bit-rate", &avgBitRate); 1079 1080 int32_t aacProfile = -1; 1081 if (audioFormat == AUDIO_FORMAT_AAC 1082 && format->findInt32("aac-profile", &aacProfile)) { 1083 // Redefine AAC format as per aac profile 1084 mapAACProfileToAudioFormat( 1085 audioFormat, 1086 aacProfile); 1087 } 1088 1089 audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER; 1090 offloadInfo.duration_us = -1; 1091 format->findInt64( 1092 "durationUs", &offloadInfo.duration_us); 1093 offloadInfo.sample_rate = sampleRate; 1094 offloadInfo.channel_mask = channelMask; 1095 offloadInfo.format = audioFormat; 1096 offloadInfo.stream_type = AUDIO_STREAM_MUSIC; 1097 offloadInfo.bit_rate = avgBitRate; 1098 offloadInfo.has_video = (mVideoDecoder != NULL); 1099 offloadInfo.is_streaming = true; 1100 1101 if (memcmp(&mCurrentOffloadInfo, &offloadInfo, sizeof(offloadInfo)) == 0) { 1102 ALOGV("openAudioSink: no change in offload mode"); 1103 return; // no change from previous configuration, everything ok. 1104 } 1105 ALOGV("openAudioSink: try to open AudioSink in offload mode"); 1106 flags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; 1107 flags &= ~AUDIO_OUTPUT_FLAG_DEEP_BUFFER; 1108 audioSinkChanged = true; 1109 mAudioSink->close(); 1110 err = mAudioSink->open( 1111 sampleRate, 1112 numChannels, 1113 (audio_channel_mask_t)channelMask, 1114 audioFormat, 1115 8 /* bufferCount */, 1116 &NuPlayer::Renderer::AudioSinkCallback, 1117 mRenderer.get(), 1118 (audio_output_flags_t)flags, 1119 &offloadInfo); 1120 1121 if (err == OK) { 1122 // If the playback is offloaded to h/w, we pass 1123 // the HAL some metadata information. 1124 // We don't want to do this for PCM because it 1125 // will be going through the AudioFlinger mixer 1126 // before reaching the hardware. 1127 sp<MetaData> audioMeta = 1128 mSource->getFormatMeta(true /* audio */); 1129 sendMetaDataToHal(mAudioSink, audioMeta); 1130 mCurrentOffloadInfo = offloadInfo; 1131 err = mAudioSink->start(); 1132 ALOGV_IF(err == OK, "openAudioSink: offload succeeded"); 1133 } 1134 if (err != OK) { 1135 // Clean up, fall back to non offload mode. 1136 mAudioSink->close(); 1137 mRenderer->signalDisableOffloadAudio(); 1138 mOffloadAudio = false; 1139 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER; 1140 ALOGV("openAudioSink: offload failed"); 1141 } 1142 } 1143 } 1144 if (!offloadOnly && !mOffloadAudio) { 1145 flags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; 1146 ALOGV("openAudioSink: open AudioSink in NON-offload mode"); 1147 1148 audioSinkChanged = true; 1149 mAudioSink->close(); 1150 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER; 1151 CHECK_EQ(mAudioSink->open( 1152 sampleRate, 1153 numChannels, 1154 (audio_channel_mask_t)channelMask, 1155 AUDIO_FORMAT_PCM_16_BIT, 1156 8 /* bufferCount */, 1157 NULL, 1158 NULL, 1159 (audio_output_flags_t)flags), 1160 (status_t)OK); 1161 mAudioSink->start(); 1162 } 1163 if (audioSinkChanged) { 1164 mRenderer->signalAudioSinkChanged(); 1165 } 1166} 1167 1168void NuPlayer::closeAudioSink() { 1169 mAudioSink->close(); 1170 mCurrentOffloadInfo = AUDIO_INFO_INITIALIZER; 1171} 1172 1173status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) { 1174 if (*decoder != NULL) { 1175 return OK; 1176 } 1177 1178 sp<AMessage> format = mSource->getFormat(audio); 1179 1180 if (format == NULL) { 1181 return -EWOULDBLOCK; 1182 } 1183 1184 if (!audio) { 1185 AString mime; 1186 CHECK(format->findString("mime", &mime)); 1187 mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str()); 1188 1189 sp<AMessage> ccNotify = new AMessage(kWhatClosedCaptionNotify, id()); 1190 mCCDecoder = new CCDecoder(ccNotify); 1191 1192 if (mSourceFlags & Source::FLAG_SECURE) { 1193 format->setInt32("secure", true); 1194 } 1195 } 1196 1197 if (audio) { 1198 sp<AMessage> notify = new AMessage(kWhatAudioNotify, id()); 1199 ++mAudioDecoderGeneration; 1200 notify->setInt32("generation", mAudioDecoderGeneration); 1201 1202 if (mOffloadAudio) { 1203 *decoder = new DecoderPassThrough(notify); 1204 } else { 1205 *decoder = new Decoder(notify); 1206 } 1207 } else { 1208 sp<AMessage> notify = new AMessage(kWhatVideoNotify, id()); 1209 ++mVideoDecoderGeneration; 1210 notify->setInt32("generation", mVideoDecoderGeneration); 1211 1212 *decoder = new Decoder(notify, mNativeWindow); 1213 } 1214 (*decoder)->init(); 1215 (*decoder)->configure(format); 1216 1217 // allocate buffers to decrypt widevine source buffers 1218 if (!audio && (mSourceFlags & Source::FLAG_SECURE)) { 1219 Vector<sp<ABuffer> > inputBufs; 1220 CHECK_EQ((*decoder)->getInputBuffers(&inputBufs), (status_t)OK); 1221 1222 Vector<MediaBuffer *> mediaBufs; 1223 for (size_t i = 0; i < inputBufs.size(); i++) { 1224 const sp<ABuffer> &buffer = inputBufs[i]; 1225 MediaBuffer *mbuf = new MediaBuffer(buffer->data(), buffer->size()); 1226 mediaBufs.push(mbuf); 1227 } 1228 1229 status_t err = mSource->setBuffers(audio, mediaBufs); 1230 if (err != OK) { 1231 for (size_t i = 0; i < mediaBufs.size(); ++i) { 1232 mediaBufs[i]->release(); 1233 } 1234 mediaBufs.clear(); 1235 ALOGE("Secure source didn't support secure mediaBufs."); 1236 return err; 1237 } 1238 } 1239 return OK; 1240} 1241 1242status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { 1243 sp<AMessage> reply; 1244 CHECK(msg->findMessage("reply", &reply)); 1245 1246 if ((audio && mFlushingAudio != NONE) 1247 || (!audio && mFlushingVideo != NONE) 1248 || mSource == NULL) { 1249 reply->setInt32("err", INFO_DISCONTINUITY); 1250 reply->post(); 1251 return OK; 1252 } 1253 1254 sp<ABuffer> accessUnit; 1255 1256 // Aggregate smaller buffers into a larger buffer. 1257 // The goal is to reduce power consumption. 1258 // Unfortunately this does not work with the software AAC decoder. 1259 // TODO optimize buffer size for power consumption 1260 // The offload read buffer size is 32 KB but 24 KB uses less power. 1261 const int kAudioBigBufferSizeBytes = 24 * 1024; 1262 bool doBufferAggregation = (audio && mOffloadAudio); 1263 sp<ABuffer> biggerBuffer; 1264 bool needMoreData = false; 1265 int numSmallBuffers = 0; 1266 bool gotTime = false; 1267 1268 bool dropAccessUnit; 1269 do { 1270 status_t err; 1271 // Did we save an accessUnit earlier because of a discontinuity? 1272 if (audio && (mPendingAudioAccessUnit != NULL)) { 1273 accessUnit = mPendingAudioAccessUnit; 1274 mPendingAudioAccessUnit.clear(); 1275 err = mPendingAudioErr; 1276 ALOGV("feedDecoderInputData() use mPendingAudioAccessUnit"); 1277 } else { 1278 err = mSource->dequeueAccessUnit(audio, &accessUnit); 1279 } 1280 1281 if (err == -EWOULDBLOCK) { 1282 ALOGD("feedDecoderInputData() got EWOULDBLOCK"); 1283 if (biggerBuffer == NULL) { 1284 return err; 1285 } else { 1286 break; // Reply with data that we already have. 1287 } 1288 } else if (err != OK) { 1289 if (err == INFO_DISCONTINUITY) { 1290 if (biggerBuffer != NULL) { 1291 // We already have some data so save this for later. 1292 mPendingAudioErr = err; 1293 mPendingAudioAccessUnit = accessUnit; 1294 accessUnit.clear(); 1295 ALOGD("feedDecoderInputData() save discontinuity for later"); 1296 break; 1297 } 1298 int32_t type; 1299 CHECK(accessUnit->meta()->findInt32("discontinuity", &type)); 1300 1301 bool formatChange = 1302 (audio && 1303 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT)) 1304 || (!audio && 1305 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT)); 1306 1307 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0; 1308 1309 ALOGI("%s discontinuity (formatChange=%d, time=%d)", 1310 audio ? "audio" : "video", formatChange, timeChange); 1311 1312 if (audio) { 1313 mSkipRenderingAudioUntilMediaTimeUs = -1; 1314 } else { 1315 mSkipRenderingVideoUntilMediaTimeUs = -1; 1316 } 1317 1318 if (timeChange) { 1319 sp<AMessage> extra; 1320 if (accessUnit->meta()->findMessage("extra", &extra) 1321 && extra != NULL) { 1322 int64_t resumeAtMediaTimeUs; 1323 if (extra->findInt64( 1324 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) { 1325 ALOGI("suppressing rendering of %s until %lld us", 1326 audio ? "audio" : "video", resumeAtMediaTimeUs); 1327 1328 if (audio) { 1329 mSkipRenderingAudioUntilMediaTimeUs = 1330 resumeAtMediaTimeUs; 1331 } else { 1332 mSkipRenderingVideoUntilMediaTimeUs = 1333 resumeAtMediaTimeUs; 1334 } 1335 } 1336 } 1337 } 1338 1339 mTimeDiscontinuityPending = 1340 mTimeDiscontinuityPending || timeChange; 1341 1342 bool seamlessFormatChange = false; 1343 sp<AMessage> newFormat = mSource->getFormat(audio); 1344 if (formatChange) { 1345 seamlessFormatChange = 1346 getDecoder(audio)->supportsSeamlessFormatChange(newFormat); 1347 // treat seamless format change separately 1348 formatChange = !seamlessFormatChange; 1349 } 1350 bool shutdownOrFlush = formatChange || timeChange; 1351 1352 // We want to queue up scan-sources only once per discontinuity. 1353 // We control this by doing it only if neither audio nor video are 1354 // flushing or shutting down. (After handling 1st discontinuity, one 1355 // of the flushing states will not be NONE.) 1356 // No need to scan sources if this discontinuity does not result 1357 // in a flush or shutdown, as the flushing state will stay NONE. 1358 if (mFlushingAudio == NONE && mFlushingVideo == NONE && 1359 shutdownOrFlush) { 1360 // And we'll resume scanning sources once we're done 1361 // flushing. 1362 mDeferredActions.push_front( 1363 new SimpleAction( 1364 &NuPlayer::performScanSources)); 1365 } 1366 1367 if (formatChange /* not seamless */) { 1368 // must change decoder 1369 flushDecoder(audio, /* needShutdown = */ true); 1370 } else if (timeChange) { 1371 // need to flush 1372 flushDecoder(audio, /* needShutdown = */ false, newFormat); 1373 err = OK; 1374 } else if (seamlessFormatChange) { 1375 // reuse existing decoder and don't flush 1376 updateDecoderFormatWithoutFlush(audio, newFormat); 1377 err = OK; 1378 } else { 1379 // This stream is unaffected by the discontinuity 1380 return -EWOULDBLOCK; 1381 } 1382 } 1383 1384 reply->setInt32("err", err); 1385 reply->post(); 1386 return OK; 1387 } 1388 1389 if (!audio) { 1390 ++mNumFramesTotal; 1391 } 1392 1393 dropAccessUnit = false; 1394 if (!audio 1395 && !(mSourceFlags & Source::FLAG_SECURE) 1396 && mVideoLateByUs > 100000ll 1397 && mVideoIsAVC 1398 && !IsAVCReferenceFrame(accessUnit)) { 1399 dropAccessUnit = true; 1400 ++mNumFramesDropped; 1401 } 1402 1403 size_t smallSize = accessUnit->size(); 1404 needMoreData = false; 1405 if (doBufferAggregation && (biggerBuffer == NULL) 1406 // Don't bother if only room for a few small buffers. 1407 && (smallSize < (kAudioBigBufferSizeBytes / 3))) { 1408 // Create a larger buffer for combining smaller buffers from the extractor. 1409 biggerBuffer = new ABuffer(kAudioBigBufferSizeBytes); 1410 biggerBuffer->setRange(0, 0); // start empty 1411 } 1412 1413 if (biggerBuffer != NULL) { 1414 int64_t timeUs; 1415 bool smallTimestampValid = accessUnit->meta()->findInt64("timeUs", &timeUs); 1416 // Will the smaller buffer fit? 1417 size_t bigSize = biggerBuffer->size(); 1418 size_t roomLeft = biggerBuffer->capacity() - bigSize; 1419 // Should we save this small buffer for the next big buffer? 1420 // If the first small buffer did not have a timestamp then save 1421 // any buffer that does have a timestamp until the next big buffer. 1422 if ((smallSize > roomLeft) 1423 || (!gotTime && (numSmallBuffers > 0) && smallTimestampValid)) { 1424 mPendingAudioErr = err; 1425 mPendingAudioAccessUnit = accessUnit; 1426 accessUnit.clear(); 1427 } else { 1428 // Append small buffer to the bigger buffer. 1429 memcpy(biggerBuffer->base() + bigSize, accessUnit->data(), smallSize); 1430 bigSize += smallSize; 1431 biggerBuffer->setRange(0, bigSize); 1432 1433 // Keep looping until we run out of room in the biggerBuffer. 1434 needMoreData = true; 1435 1436 // Grab time from first small buffer if available. 1437 if ((numSmallBuffers == 0) && smallTimestampValid) { 1438 biggerBuffer->meta()->setInt64("timeUs", timeUs); 1439 gotTime = true; 1440 } 1441 1442 ALOGV("feedDecoderInputData() #%d, smallSize = %zu, bigSize = %zu, capacity = %zu", 1443 numSmallBuffers, smallSize, bigSize, biggerBuffer->capacity()); 1444 numSmallBuffers++; 1445 } 1446 } 1447 } while (dropAccessUnit || needMoreData); 1448 1449 // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video"); 1450 1451#if 0 1452 int64_t mediaTimeUs; 1453 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs)); 1454 ALOGV("feeding %s input buffer at media time %.2f secs", 1455 audio ? "audio" : "video", 1456 mediaTimeUs / 1E6); 1457#endif 1458 1459 if (!audio) { 1460 mCCDecoder->decode(accessUnit); 1461 } 1462 1463 if (biggerBuffer != NULL) { 1464 ALOGV("feedDecoderInputData() reply with aggregated buffer, %d", numSmallBuffers); 1465 reply->setBuffer("buffer", biggerBuffer); 1466 } else { 1467 reply->setBuffer("buffer", accessUnit); 1468 } 1469 1470 reply->post(); 1471 1472 return OK; 1473} 1474 1475void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) { 1476 // ALOGV("renderBuffer %s", audio ? "audio" : "video"); 1477 1478 sp<AMessage> reply; 1479 CHECK(msg->findMessage("reply", &reply)); 1480 1481 if ((audio && mFlushingAudio != NONE) 1482 || (!audio && mFlushingVideo != NONE)) { 1483 // We're currently attempting to flush the decoder, in order 1484 // to complete this, the decoder wants all its buffers back, 1485 // so we don't want any output buffers it sent us (from before 1486 // we initiated the flush) to be stuck in the renderer's queue. 1487 1488 ALOGV("we're still flushing the %s decoder, sending its output buffer" 1489 " right back.", audio ? "audio" : "video"); 1490 1491 reply->post(); 1492 return; 1493 } 1494 1495 sp<ABuffer> buffer; 1496 CHECK(msg->findBuffer("buffer", &buffer)); 1497 1498 int64_t mediaTimeUs; 1499 CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs)); 1500 1501 int64_t &skipUntilMediaTimeUs = 1502 audio 1503 ? mSkipRenderingAudioUntilMediaTimeUs 1504 : mSkipRenderingVideoUntilMediaTimeUs; 1505 1506 if (skipUntilMediaTimeUs >= 0) { 1507 1508 if (mediaTimeUs < skipUntilMediaTimeUs) { 1509 ALOGV("dropping %s buffer at time %lld as requested.", 1510 audio ? "audio" : "video", 1511 mediaTimeUs); 1512 1513 reply->post(); 1514 return; 1515 } 1516 1517 skipUntilMediaTimeUs = -1; 1518 } 1519 1520 if (!audio && mCCDecoder->isSelected()) { 1521 mCCDecoder->display(mediaTimeUs); 1522 } 1523 1524 mRenderer->queueBuffer(audio, buffer, reply); 1525} 1526 1527void NuPlayer::updateVideoSize( 1528 const sp<AMessage> &inputFormat, 1529 const sp<AMessage> &outputFormat) { 1530 if (inputFormat == NULL) { 1531 ALOGW("Unknown video size, reporting 0x0!"); 1532 notifyListener(MEDIA_SET_VIDEO_SIZE, 0, 0); 1533 return; 1534 } 1535 1536 int32_t displayWidth, displayHeight; 1537 int32_t cropLeft, cropTop, cropRight, cropBottom; 1538 1539 if (outputFormat != NULL) { 1540 int32_t width, height; 1541 CHECK(outputFormat->findInt32("width", &width)); 1542 CHECK(outputFormat->findInt32("height", &height)); 1543 1544 int32_t cropLeft, cropTop, cropRight, cropBottom; 1545 CHECK(outputFormat->findRect( 1546 "crop", 1547 &cropLeft, &cropTop, &cropRight, &cropBottom)); 1548 1549 displayWidth = cropRight - cropLeft + 1; 1550 displayHeight = cropBottom - cropTop + 1; 1551 1552 ALOGV("Video output format changed to %d x %d " 1553 "(crop: %d x %d @ (%d, %d))", 1554 width, height, 1555 displayWidth, 1556 displayHeight, 1557 cropLeft, cropTop); 1558 } else { 1559 CHECK(inputFormat->findInt32("width", &displayWidth)); 1560 CHECK(inputFormat->findInt32("height", &displayHeight)); 1561 1562 ALOGV("Video input format %d x %d", displayWidth, displayHeight); 1563 } 1564 1565 // Take into account sample aspect ratio if necessary: 1566 int32_t sarWidth, sarHeight; 1567 if (inputFormat->findInt32("sar-width", &sarWidth) 1568 && inputFormat->findInt32("sar-height", &sarHeight)) { 1569 ALOGV("Sample aspect ratio %d : %d", sarWidth, sarHeight); 1570 1571 displayWidth = (displayWidth * sarWidth) / sarHeight; 1572 1573 ALOGV("display dimensions %d x %d", displayWidth, displayHeight); 1574 } 1575 1576 int32_t rotationDegrees; 1577 if (!inputFormat->findInt32("rotation-degrees", &rotationDegrees)) { 1578 rotationDegrees = 0; 1579 } 1580 1581 if (rotationDegrees == 90 || rotationDegrees == 270) { 1582 int32_t tmp = displayWidth; 1583 displayWidth = displayHeight; 1584 displayHeight = tmp; 1585 } 1586 1587 notifyListener( 1588 MEDIA_SET_VIDEO_SIZE, 1589 displayWidth, 1590 displayHeight); 1591} 1592 1593void NuPlayer::notifyListener(int msg, int ext1, int ext2, const Parcel *in) { 1594 if (mDriver == NULL) { 1595 return; 1596 } 1597 1598 sp<NuPlayerDriver> driver = mDriver.promote(); 1599 1600 if (driver == NULL) { 1601 return; 1602 } 1603 1604 driver->notifyListener(msg, ext1, ext2, in); 1605} 1606 1607void NuPlayer::flushDecoder( 1608 bool audio, bool needShutdown, const sp<AMessage> &newFormat) { 1609 ALOGV("[%s] flushDecoder needShutdown=%d", 1610 audio ? "audio" : "video", needShutdown); 1611 1612 const sp<Decoder> &decoder = getDecoder(audio); 1613 if (decoder == NULL) { 1614 ALOGI("flushDecoder %s without decoder present", 1615 audio ? "audio" : "video"); 1616 return; 1617 } 1618 1619 // Make sure we don't continue to scan sources until we finish flushing. 1620 ++mScanSourcesGeneration; 1621 mScanSourcesPending = false; 1622 1623 decoder->signalFlush(newFormat); 1624 mRenderer->flush(audio); 1625 1626 FlushStatus newStatus = 1627 needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER; 1628 1629 if (audio) { 1630 ALOGE_IF(mFlushingAudio != NONE, 1631 "audio flushDecoder() is called in state %d", mFlushingAudio); 1632 mFlushingAudio = newStatus; 1633 } else { 1634 ALOGE_IF(mFlushingVideo != NONE, 1635 "video flushDecoder() is called in state %d", mFlushingVideo); 1636 mFlushingVideo = newStatus; 1637 1638 if (mCCDecoder != NULL) { 1639 mCCDecoder->flush(); 1640 } 1641 } 1642} 1643 1644void NuPlayer::updateDecoderFormatWithoutFlush( 1645 bool audio, const sp<AMessage> &format) { 1646 ALOGV("[%s] updateDecoderFormatWithoutFlush", audio ? "audio" : "video"); 1647 1648 const sp<Decoder> &decoder = getDecoder(audio); 1649 if (decoder == NULL) { 1650 ALOGI("updateDecoderFormatWithoutFlush %s without decoder present", 1651 audio ? "audio" : "video"); 1652 return; 1653 } 1654 1655 decoder->signalUpdateFormat(format); 1656} 1657 1658void NuPlayer::queueDecoderShutdown( 1659 bool audio, bool video, const sp<AMessage> &reply) { 1660 ALOGI("queueDecoderShutdown audio=%d, video=%d", audio, video); 1661 1662 mDeferredActions.push_back( 1663 new ShutdownDecoderAction(audio, video)); 1664 1665 mDeferredActions.push_back( 1666 new SimpleAction(&NuPlayer::performScanSources)); 1667 1668 mDeferredActions.push_back(new PostMessageAction(reply)); 1669 1670 processDeferredActions(); 1671} 1672 1673status_t NuPlayer::setVideoScalingMode(int32_t mode) { 1674 mVideoScalingMode = mode; 1675 if (mNativeWindow != NULL) { 1676 status_t ret = native_window_set_scaling_mode( 1677 mNativeWindow->getNativeWindow().get(), mVideoScalingMode); 1678 if (ret != OK) { 1679 ALOGE("Failed to set scaling mode (%d): %s", 1680 -ret, strerror(-ret)); 1681 return ret; 1682 } 1683 } 1684 return OK; 1685} 1686 1687status_t NuPlayer::getTrackInfo(Parcel* reply) const { 1688 sp<AMessage> msg = new AMessage(kWhatGetTrackInfo, id()); 1689 msg->setPointer("reply", reply); 1690 1691 sp<AMessage> response; 1692 status_t err = msg->postAndAwaitResponse(&response); 1693 return err; 1694} 1695 1696status_t NuPlayer::getSelectedTrack(int32_t type, Parcel* reply) const { 1697 sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, id()); 1698 msg->setPointer("reply", reply); 1699 msg->setInt32("type", type); 1700 1701 sp<AMessage> response; 1702 status_t err = msg->postAndAwaitResponse(&response); 1703 if (err == OK && response != NULL) { 1704 CHECK(response->findInt32("err", &err)); 1705 } 1706 return err; 1707} 1708 1709status_t NuPlayer::selectTrack(size_t trackIndex, bool select) { 1710 sp<AMessage> msg = new AMessage(kWhatSelectTrack, id()); 1711 msg->setSize("trackIndex", trackIndex); 1712 msg->setInt32("select", select); 1713 1714 sp<AMessage> response; 1715 status_t err = msg->postAndAwaitResponse(&response); 1716 1717 if (err != OK) { 1718 return err; 1719 } 1720 1721 if (!response->findInt32("err", &err)) { 1722 err = OK; 1723 } 1724 1725 return err; 1726} 1727 1728void NuPlayer::schedulePollDuration() { 1729 sp<AMessage> msg = new AMessage(kWhatPollDuration, id()); 1730 msg->setInt32("generation", mPollDurationGeneration); 1731 msg->post(); 1732} 1733 1734void NuPlayer::cancelPollDuration() { 1735 ++mPollDurationGeneration; 1736} 1737 1738void NuPlayer::processDeferredActions() { 1739 while (!mDeferredActions.empty()) { 1740 // We won't execute any deferred actions until we're no longer in 1741 // an intermediate state, i.e. one more more decoders are currently 1742 // flushing or shutting down. 1743 1744 if (mFlushingAudio != NONE || mFlushingVideo != NONE) { 1745 // We're currently flushing, postpone the reset until that's 1746 // completed. 1747 1748 ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d", 1749 mFlushingAudio, mFlushingVideo); 1750 1751 break; 1752 } 1753 1754 sp<Action> action = *mDeferredActions.begin(); 1755 mDeferredActions.erase(mDeferredActions.begin()); 1756 1757 action->execute(this); 1758 } 1759} 1760 1761void NuPlayer::performSeek(int64_t seekTimeUs) { 1762 ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)", 1763 seekTimeUs, 1764 seekTimeUs / 1E6); 1765 1766 if (mSource == NULL) { 1767 // This happens when reset occurs right before the loop mode 1768 // asynchronously seeks to the start of the stream. 1769 LOG_ALWAYS_FATAL_IF(mAudioDecoder != NULL || mVideoDecoder != NULL, 1770 "mSource is NULL and decoders not NULL audio(%p) video(%p)", 1771 mAudioDecoder.get(), mVideoDecoder.get()); 1772 return; 1773 } 1774 mSource->seekTo(seekTimeUs); 1775 ++mTimedTextGeneration; 1776 1777 if (mDriver != NULL) { 1778 sp<NuPlayerDriver> driver = mDriver.promote(); 1779 if (driver != NULL) { 1780 driver->notifyPosition(seekTimeUs); 1781 driver->notifySeekComplete(); 1782 } 1783 } 1784 1785 // everything's flushed, continue playback. 1786} 1787 1788void NuPlayer::performDecoderFlush() { 1789 ALOGV("performDecoderFlush"); 1790 1791 if (mAudioDecoder == NULL && mVideoDecoder == NULL) { 1792 return; 1793 } 1794 1795 mTimeDiscontinuityPending = true; 1796 1797 if (mAudioDecoder != NULL) { 1798 flushDecoder(true /* audio */, false /* needShutdown */); 1799 } 1800 1801 if (mVideoDecoder != NULL) { 1802 flushDecoder(false /* audio */, false /* needShutdown */); 1803 } 1804} 1805 1806void NuPlayer::performDecoderShutdown(bool audio, bool video) { 1807 ALOGV("performDecoderShutdown audio=%d, video=%d", audio, video); 1808 1809 if ((!audio || mAudioDecoder == NULL) 1810 && (!video || mVideoDecoder == NULL)) { 1811 return; 1812 } 1813 1814 mTimeDiscontinuityPending = true; 1815 1816 if (audio && mAudioDecoder != NULL) { 1817 flushDecoder(true /* audio */, true /* needShutdown */); 1818 } 1819 1820 if (video && mVideoDecoder != NULL) { 1821 flushDecoder(false /* audio */, true /* needShutdown */); 1822 } 1823} 1824 1825void NuPlayer::performReset() { 1826 ALOGV("performReset"); 1827 1828 CHECK(mAudioDecoder == NULL); 1829 CHECK(mVideoDecoder == NULL); 1830 1831 cancelPollDuration(); 1832 1833 ++mScanSourcesGeneration; 1834 mScanSourcesPending = false; 1835 1836 ++mAudioDecoderGeneration; 1837 ++mVideoDecoderGeneration; 1838 1839 if (mRendererLooper != NULL) { 1840 if (mRenderer != NULL) { 1841 mRendererLooper->unregisterHandler(mRenderer->id()); 1842 } 1843 mRendererLooper->stop(); 1844 mRendererLooper.clear(); 1845 } 1846 mRenderer.clear(); 1847 1848 if (mSource != NULL) { 1849 mSource->stop(); 1850 1851 mSource.clear(); 1852 } 1853 1854 if (mDriver != NULL) { 1855 sp<NuPlayerDriver> driver = mDriver.promote(); 1856 if (driver != NULL) { 1857 driver->notifyResetComplete(); 1858 } 1859 } 1860 1861 mStarted = false; 1862} 1863 1864void NuPlayer::performScanSources() { 1865 ALOGV("performScanSources"); 1866 1867 if (!mStarted) { 1868 return; 1869 } 1870 1871 if (mAudioDecoder == NULL || mVideoDecoder == NULL) { 1872 postScanSources(); 1873 } 1874} 1875 1876void NuPlayer::performSetSurface(const sp<NativeWindowWrapper> &wrapper) { 1877 ALOGV("performSetSurface"); 1878 1879 mNativeWindow = wrapper; 1880 1881 // XXX - ignore error from setVideoScalingMode for now 1882 setVideoScalingMode(mVideoScalingMode); 1883 1884 if (mDriver != NULL) { 1885 sp<NuPlayerDriver> driver = mDriver.promote(); 1886 if (driver != NULL) { 1887 driver->notifySetSurfaceComplete(); 1888 } 1889 } 1890} 1891 1892void NuPlayer::onSourceNotify(const sp<AMessage> &msg) { 1893 int32_t what; 1894 CHECK(msg->findInt32("what", &what)); 1895 1896 switch (what) { 1897 case Source::kWhatPrepared: 1898 { 1899 if (mSource == NULL) { 1900 // This is a stale notification from a source that was 1901 // asynchronously preparing when the client called reset(). 1902 // We handled the reset, the source is gone. 1903 break; 1904 } 1905 1906 int32_t err; 1907 CHECK(msg->findInt32("err", &err)); 1908 1909 sp<NuPlayerDriver> driver = mDriver.promote(); 1910 if (driver != NULL) { 1911 // notify duration first, so that it's definitely set when 1912 // the app received the "prepare complete" callback. 1913 int64_t durationUs; 1914 if (mSource->getDuration(&durationUs) == OK) { 1915 driver->notifyDuration(durationUs); 1916 } 1917 driver->notifyPrepareCompleted(err); 1918 } 1919 1920 break; 1921 } 1922 1923 case Source::kWhatFlagsChanged: 1924 { 1925 uint32_t flags; 1926 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 1927 1928 sp<NuPlayerDriver> driver = mDriver.promote(); 1929 if (driver != NULL) { 1930 driver->notifyFlagsChanged(flags); 1931 } 1932 1933 if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION) 1934 && (!(flags & Source::FLAG_DYNAMIC_DURATION))) { 1935 cancelPollDuration(); 1936 } else if (!(mSourceFlags & Source::FLAG_DYNAMIC_DURATION) 1937 && (flags & Source::FLAG_DYNAMIC_DURATION) 1938 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) { 1939 schedulePollDuration(); 1940 } 1941 1942 mSourceFlags = flags; 1943 break; 1944 } 1945 1946 case Source::kWhatVideoSizeChanged: 1947 { 1948 sp<AMessage> format; 1949 CHECK(msg->findMessage("format", &format)); 1950 1951 updateVideoSize(format); 1952 break; 1953 } 1954 1955 case Source::kWhatBufferingUpdate: 1956 { 1957 int32_t percentage; 1958 CHECK(msg->findInt32("percentage", &percentage)); 1959 1960 notifyListener(MEDIA_BUFFERING_UPDATE, percentage, 0); 1961 break; 1962 } 1963 1964 case Source::kWhatBufferingStart: 1965 { 1966 notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0); 1967 break; 1968 } 1969 1970 case Source::kWhatBufferingEnd: 1971 { 1972 notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0); 1973 break; 1974 } 1975 1976 case Source::kWhatSubtitleData: 1977 { 1978 sp<ABuffer> buffer; 1979 CHECK(msg->findBuffer("buffer", &buffer)); 1980 1981 sendSubtitleData(buffer, 0 /* baseIndex */); 1982 break; 1983 } 1984 1985 case Source::kWhatTimedTextData: 1986 { 1987 int32_t generation; 1988 if (msg->findInt32("generation", &generation) 1989 && generation != mTimedTextGeneration) { 1990 break; 1991 } 1992 1993 sp<ABuffer> buffer; 1994 CHECK(msg->findBuffer("buffer", &buffer)); 1995 1996 sp<NuPlayerDriver> driver = mDriver.promote(); 1997 if (driver == NULL) { 1998 break; 1999 } 2000 2001 int posMs; 2002 int64_t timeUs, posUs; 2003 driver->getCurrentPosition(&posMs); 2004 posUs = posMs * 1000; 2005 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2006 2007 if (posUs < timeUs) { 2008 if (!msg->findInt32("generation", &generation)) { 2009 msg->setInt32("generation", mTimedTextGeneration); 2010 } 2011 msg->post(timeUs - posUs); 2012 } else { 2013 sendTimedTextData(buffer); 2014 } 2015 break; 2016 } 2017 2018 case Source::kWhatQueueDecoderShutdown: 2019 { 2020 int32_t audio, video; 2021 CHECK(msg->findInt32("audio", &audio)); 2022 CHECK(msg->findInt32("video", &video)); 2023 2024 sp<AMessage> reply; 2025 CHECK(msg->findMessage("reply", &reply)); 2026 2027 queueDecoderShutdown(audio, video, reply); 2028 break; 2029 } 2030 2031 case Source::kWhatDrmNoLicense: 2032 { 2033 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE); 2034 break; 2035 } 2036 2037 default: 2038 TRESPASS(); 2039 } 2040} 2041 2042void NuPlayer::onClosedCaptionNotify(const sp<AMessage> &msg) { 2043 int32_t what; 2044 CHECK(msg->findInt32("what", &what)); 2045 2046 switch (what) { 2047 case NuPlayer::CCDecoder::kWhatClosedCaptionData: 2048 { 2049 sp<ABuffer> buffer; 2050 CHECK(msg->findBuffer("buffer", &buffer)); 2051 2052 size_t inbandTracks = 0; 2053 if (mSource != NULL) { 2054 inbandTracks = mSource->getTrackCount(); 2055 } 2056 2057 sendSubtitleData(buffer, inbandTracks); 2058 break; 2059 } 2060 2061 case NuPlayer::CCDecoder::kWhatTrackAdded: 2062 { 2063 notifyListener(MEDIA_INFO, MEDIA_INFO_METADATA_UPDATE, 0); 2064 2065 break; 2066 } 2067 2068 default: 2069 TRESPASS(); 2070 } 2071 2072 2073} 2074 2075void NuPlayer::sendSubtitleData(const sp<ABuffer> &buffer, int32_t baseIndex) { 2076 int32_t trackIndex; 2077 int64_t timeUs, durationUs; 2078 CHECK(buffer->meta()->findInt32("trackIndex", &trackIndex)); 2079 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2080 CHECK(buffer->meta()->findInt64("durationUs", &durationUs)); 2081 2082 Parcel in; 2083 in.writeInt32(trackIndex + baseIndex); 2084 in.writeInt64(timeUs); 2085 in.writeInt64(durationUs); 2086 in.writeInt32(buffer->size()); 2087 in.writeInt32(buffer->size()); 2088 in.write(buffer->data(), buffer->size()); 2089 2090 notifyListener(MEDIA_SUBTITLE_DATA, 0, 0, &in); 2091} 2092 2093void NuPlayer::sendTimedTextData(const sp<ABuffer> &buffer) { 2094 const void *data; 2095 size_t size = 0; 2096 int64_t timeUs; 2097 int32_t flag = TextDescriptions::LOCAL_DESCRIPTIONS; 2098 2099 AString mime; 2100 CHECK(buffer->meta()->findString("mime", &mime)); 2101 CHECK(strcasecmp(mime.c_str(), MEDIA_MIMETYPE_TEXT_3GPP) == 0); 2102 2103 data = buffer->data(); 2104 size = buffer->size(); 2105 2106 Parcel parcel; 2107 if (size > 0) { 2108 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2109 flag |= TextDescriptions::IN_BAND_TEXT_3GPP; 2110 TextDescriptions::getParcelOfDescriptions( 2111 (const uint8_t *)data, size, flag, timeUs / 1000, &parcel); 2112 } 2113 2114 if ((parcel.dataSize() > 0)) { 2115 notifyListener(MEDIA_TIMED_TEXT, 0, 0, &parcel); 2116 } else { // send an empty timed text 2117 notifyListener(MEDIA_TIMED_TEXT, 0, 0); 2118 } 2119} 2120//////////////////////////////////////////////////////////////////////////////// 2121 2122sp<AMessage> NuPlayer::Source::getFormat(bool audio) { 2123 sp<MetaData> meta = getFormatMeta(audio); 2124 2125 if (meta == NULL) { 2126 return NULL; 2127 } 2128 2129 sp<AMessage> msg = new AMessage; 2130 2131 if(convertMetaDataToMessage(meta, &msg) == OK) { 2132 return msg; 2133 } 2134 return NULL; 2135} 2136 2137void NuPlayer::Source::notifyFlagsChanged(uint32_t flags) { 2138 sp<AMessage> notify = dupNotify(); 2139 notify->setInt32("what", kWhatFlagsChanged); 2140 notify->setInt32("flags", flags); 2141 notify->post(); 2142} 2143 2144void NuPlayer::Source::notifyVideoSizeChanged(const sp<AMessage> &format) { 2145 sp<AMessage> notify = dupNotify(); 2146 notify->setInt32("what", kWhatVideoSizeChanged); 2147 notify->setMessage("format", format); 2148 notify->post(); 2149} 2150 2151void NuPlayer::Source::notifyPrepared(status_t err) { 2152 sp<AMessage> notify = dupNotify(); 2153 notify->setInt32("what", kWhatPrepared); 2154 notify->setInt32("err", err); 2155 notify->post(); 2156} 2157 2158void NuPlayer::Source::onMessageReceived(const sp<AMessage> & /* msg */) { 2159 TRESPASS(); 2160} 2161 2162} // namespace android 2163