xref: /aosp_15_r20/frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayer.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2010 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "NuPlayer"
19*ec779b8eSAndroid Build Coastguard Worker 
20*ec779b8eSAndroid Build Coastguard Worker #include <inttypes.h>
21*ec779b8eSAndroid Build Coastguard Worker 
22*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
23*ec779b8eSAndroid Build Coastguard Worker 
24*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayer.h"
25*ec779b8eSAndroid Build Coastguard Worker 
26*ec779b8eSAndroid Build Coastguard Worker #include "HTTPLiveSource.h"
27*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayerCCDecoder.h"
28*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayerDecoder.h"
29*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayerDecoderBase.h"
30*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayerDecoderPassThrough.h"
31*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayerDriver.h"
32*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayerRenderer.h"
33*ec779b8eSAndroid Build Coastguard Worker #include "NuPlayerSource.h"
34*ec779b8eSAndroid Build Coastguard Worker #include "RTPSource.h"
35*ec779b8eSAndroid Build Coastguard Worker #include "RTSPSource.h"
36*ec779b8eSAndroid Build Coastguard Worker #include "StreamingSource.h"
37*ec779b8eSAndroid Build Coastguard Worker #include "GenericSource.h"
38*ec779b8eSAndroid Build Coastguard Worker #include <timedtext/TextDescriptions.h>
39*ec779b8eSAndroid Build Coastguard Worker 
40*ec779b8eSAndroid Build Coastguard Worker #include <cutils/properties.h>
41*ec779b8eSAndroid Build Coastguard Worker 
42*ec779b8eSAndroid Build Coastguard Worker #include <media/AudioResamplerPublic.h>
43*ec779b8eSAndroid Build Coastguard Worker #include <media/AVSyncSettings.h>
44*ec779b8eSAndroid Build Coastguard Worker #include <media/MediaCodecBuffer.h>
45*ec779b8eSAndroid Build Coastguard Worker 
46*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/hexdump.h>
47*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ABuffer.h>
48*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
49*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/AMessage.h>
50*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/avc_utils.h>
51*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaBuffer.h>
52*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaClock.h>
53*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaDefs.h>
54*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaErrors.h>
55*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MetaData.h>
56*ec779b8eSAndroid Build Coastguard Worker 
57*ec779b8eSAndroid Build Coastguard Worker #include <mpeg2ts/ATSParser.h>
58*ec779b8eSAndroid Build Coastguard Worker 
59*ec779b8eSAndroid Build Coastguard Worker #include <gui/IGraphicBufferProducer.h>
60*ec779b8eSAndroid Build Coastguard Worker #include <gui/Surface.h>
61*ec779b8eSAndroid Build Coastguard Worker 
62*ec779b8eSAndroid Build Coastguard Worker 
63*ec779b8eSAndroid Build Coastguard Worker #include <media/esds/ESDS.h>
64*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/Utils.h>
65*ec779b8eSAndroid Build Coastguard Worker 
66*ec779b8eSAndroid Build Coastguard Worker namespace android {
67*ec779b8eSAndroid Build Coastguard Worker 
68*ec779b8eSAndroid Build Coastguard Worker struct NuPlayer::Action : public RefBase {
Actionandroid::NuPlayer::Action69*ec779b8eSAndroid Build Coastguard Worker     Action() {}
70*ec779b8eSAndroid Build Coastguard Worker 
71*ec779b8eSAndroid Build Coastguard Worker     virtual void execute(NuPlayer *player) = 0;
72*ec779b8eSAndroid Build Coastguard Worker 
73*ec779b8eSAndroid Build Coastguard Worker private:
74*ec779b8eSAndroid Build Coastguard Worker     DISALLOW_EVIL_CONSTRUCTORS(Action);
75*ec779b8eSAndroid Build Coastguard Worker };
76*ec779b8eSAndroid Build Coastguard Worker 
77*ec779b8eSAndroid Build Coastguard Worker struct NuPlayer::SeekAction : public Action {
SeekActionandroid::NuPlayer::SeekAction78*ec779b8eSAndroid Build Coastguard Worker     explicit SeekAction(int64_t seekTimeUs, MediaPlayerSeekMode mode)
79*ec779b8eSAndroid Build Coastguard Worker         : mSeekTimeUs(seekTimeUs),
80*ec779b8eSAndroid Build Coastguard Worker           mMode(mode) {
81*ec779b8eSAndroid Build Coastguard Worker     }
82*ec779b8eSAndroid Build Coastguard Worker 
executeandroid::NuPlayer::SeekAction83*ec779b8eSAndroid Build Coastguard Worker     virtual void execute(NuPlayer *player) {
84*ec779b8eSAndroid Build Coastguard Worker         player->performSeek(mSeekTimeUs, mMode);
85*ec779b8eSAndroid Build Coastguard Worker     }
86*ec779b8eSAndroid Build Coastguard Worker 
87*ec779b8eSAndroid Build Coastguard Worker private:
88*ec779b8eSAndroid Build Coastguard Worker     int64_t mSeekTimeUs;
89*ec779b8eSAndroid Build Coastguard Worker     MediaPlayerSeekMode mMode;
90*ec779b8eSAndroid Build Coastguard Worker 
91*ec779b8eSAndroid Build Coastguard Worker     DISALLOW_EVIL_CONSTRUCTORS(SeekAction);
92*ec779b8eSAndroid Build Coastguard Worker };
93*ec779b8eSAndroid Build Coastguard Worker 
94*ec779b8eSAndroid Build Coastguard Worker struct NuPlayer::ResumeDecoderAction : public Action {
ResumeDecoderActionandroid::NuPlayer::ResumeDecoderAction95*ec779b8eSAndroid Build Coastguard Worker     explicit ResumeDecoderAction(bool needNotify)
96*ec779b8eSAndroid Build Coastguard Worker         : mNeedNotify(needNotify) {
97*ec779b8eSAndroid Build Coastguard Worker     }
98*ec779b8eSAndroid Build Coastguard Worker 
executeandroid::NuPlayer::ResumeDecoderAction99*ec779b8eSAndroid Build Coastguard Worker     virtual void execute(NuPlayer *player) {
100*ec779b8eSAndroid Build Coastguard Worker         player->performResumeDecoders(mNeedNotify);
101*ec779b8eSAndroid Build Coastguard Worker     }
102*ec779b8eSAndroid Build Coastguard Worker 
103*ec779b8eSAndroid Build Coastguard Worker private:
104*ec779b8eSAndroid Build Coastguard Worker     bool mNeedNotify;
105*ec779b8eSAndroid Build Coastguard Worker 
106*ec779b8eSAndroid Build Coastguard Worker     DISALLOW_EVIL_CONSTRUCTORS(ResumeDecoderAction);
107*ec779b8eSAndroid Build Coastguard Worker };
108*ec779b8eSAndroid Build Coastguard Worker 
109*ec779b8eSAndroid Build Coastguard Worker struct NuPlayer::SetSurfaceAction : public Action {
SetSurfaceActionandroid::NuPlayer::SetSurfaceAction110*ec779b8eSAndroid Build Coastguard Worker     explicit SetSurfaceAction(const sp<Surface> &surface)
111*ec779b8eSAndroid Build Coastguard Worker         : mSurface(surface) {
112*ec779b8eSAndroid Build Coastguard Worker     }
113*ec779b8eSAndroid Build Coastguard Worker 
executeandroid::NuPlayer::SetSurfaceAction114*ec779b8eSAndroid Build Coastguard Worker     virtual void execute(NuPlayer *player) {
115*ec779b8eSAndroid Build Coastguard Worker         player->performSetSurface(mSurface);
116*ec779b8eSAndroid Build Coastguard Worker     }
117*ec779b8eSAndroid Build Coastguard Worker 
118*ec779b8eSAndroid Build Coastguard Worker private:
119*ec779b8eSAndroid Build Coastguard Worker     sp<Surface> mSurface;
120*ec779b8eSAndroid Build Coastguard Worker 
121*ec779b8eSAndroid Build Coastguard Worker     DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction);
122*ec779b8eSAndroid Build Coastguard Worker };
123*ec779b8eSAndroid Build Coastguard Worker 
124*ec779b8eSAndroid Build Coastguard Worker struct NuPlayer::FlushDecoderAction : public Action {
FlushDecoderActionandroid::NuPlayer::FlushDecoderAction125*ec779b8eSAndroid Build Coastguard Worker     FlushDecoderAction(FlushCommand audio, FlushCommand video)
126*ec779b8eSAndroid Build Coastguard Worker         : mAudio(audio),
127*ec779b8eSAndroid Build Coastguard Worker           mVideo(video) {
128*ec779b8eSAndroid Build Coastguard Worker     }
129*ec779b8eSAndroid Build Coastguard Worker 
executeandroid::NuPlayer::FlushDecoderAction130*ec779b8eSAndroid Build Coastguard Worker     virtual void execute(NuPlayer *player) {
131*ec779b8eSAndroid Build Coastguard Worker         player->performDecoderFlush(mAudio, mVideo);
132*ec779b8eSAndroid Build Coastguard Worker     }
133*ec779b8eSAndroid Build Coastguard Worker 
134*ec779b8eSAndroid Build Coastguard Worker private:
135*ec779b8eSAndroid Build Coastguard Worker     FlushCommand mAudio;
136*ec779b8eSAndroid Build Coastguard Worker     FlushCommand mVideo;
137*ec779b8eSAndroid Build Coastguard Worker 
138*ec779b8eSAndroid Build Coastguard Worker     DISALLOW_EVIL_CONSTRUCTORS(FlushDecoderAction);
139*ec779b8eSAndroid Build Coastguard Worker };
140*ec779b8eSAndroid Build Coastguard Worker 
141*ec779b8eSAndroid Build Coastguard Worker struct NuPlayer::PostMessageAction : public Action {
PostMessageActionandroid::NuPlayer::PostMessageAction142*ec779b8eSAndroid Build Coastguard Worker     explicit PostMessageAction(const sp<AMessage> &msg)
143*ec779b8eSAndroid Build Coastguard Worker         : mMessage(msg) {
144*ec779b8eSAndroid Build Coastguard Worker     }
145*ec779b8eSAndroid Build Coastguard Worker 
executeandroid::NuPlayer::PostMessageAction146*ec779b8eSAndroid Build Coastguard Worker     virtual void execute(NuPlayer *) {
147*ec779b8eSAndroid Build Coastguard Worker         mMessage->post();
148*ec779b8eSAndroid Build Coastguard Worker     }
149*ec779b8eSAndroid Build Coastguard Worker 
150*ec779b8eSAndroid Build Coastguard Worker private:
151*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> mMessage;
152*ec779b8eSAndroid Build Coastguard Worker 
153*ec779b8eSAndroid Build Coastguard Worker     DISALLOW_EVIL_CONSTRUCTORS(PostMessageAction);
154*ec779b8eSAndroid Build Coastguard Worker };
155*ec779b8eSAndroid Build Coastguard Worker 
156*ec779b8eSAndroid Build Coastguard Worker // Use this if there's no state necessary to save in order to execute
157*ec779b8eSAndroid Build Coastguard Worker // the action.
158*ec779b8eSAndroid Build Coastguard Worker struct NuPlayer::SimpleAction : public Action {
159*ec779b8eSAndroid Build Coastguard Worker     typedef void (NuPlayer::*ActionFunc)();
160*ec779b8eSAndroid Build Coastguard Worker 
SimpleActionandroid::NuPlayer::SimpleAction161*ec779b8eSAndroid Build Coastguard Worker     explicit SimpleAction(ActionFunc func)
162*ec779b8eSAndroid Build Coastguard Worker         : mFunc(func) {
163*ec779b8eSAndroid Build Coastguard Worker     }
164*ec779b8eSAndroid Build Coastguard Worker 
executeandroid::NuPlayer::SimpleAction165*ec779b8eSAndroid Build Coastguard Worker     virtual void execute(NuPlayer *player) {
166*ec779b8eSAndroid Build Coastguard Worker         (player->*mFunc)();
167*ec779b8eSAndroid Build Coastguard Worker     }
168*ec779b8eSAndroid Build Coastguard Worker 
169*ec779b8eSAndroid Build Coastguard Worker private:
170*ec779b8eSAndroid Build Coastguard Worker     ActionFunc mFunc;
171*ec779b8eSAndroid Build Coastguard Worker 
172*ec779b8eSAndroid Build Coastguard Worker     DISALLOW_EVIL_CONSTRUCTORS(SimpleAction);
173*ec779b8eSAndroid Build Coastguard Worker };
174*ec779b8eSAndroid Build Coastguard Worker 
175*ec779b8eSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
176*ec779b8eSAndroid Build Coastguard Worker 
NuPlayer(pid_t pid,const sp<MediaClock> & mediaClock)177*ec779b8eSAndroid Build Coastguard Worker NuPlayer::NuPlayer(pid_t pid, const sp<MediaClock> &mediaClock)
178*ec779b8eSAndroid Build Coastguard Worker     : mUIDValid(false),
179*ec779b8eSAndroid Build Coastguard Worker       mPID(pid),
180*ec779b8eSAndroid Build Coastguard Worker       mMediaClock(mediaClock),
181*ec779b8eSAndroid Build Coastguard Worker       mSourceFlags(0),
182*ec779b8eSAndroid Build Coastguard Worker       mOffloadAudio(false),
183*ec779b8eSAndroid Build Coastguard Worker       mAudioDecoderGeneration(0),
184*ec779b8eSAndroid Build Coastguard Worker       mVideoDecoderGeneration(0),
185*ec779b8eSAndroid Build Coastguard Worker       mRendererGeneration(0),
186*ec779b8eSAndroid Build Coastguard Worker       mLastStartedPlayingTimeNs(0),
187*ec779b8eSAndroid Build Coastguard Worker       mLastStartedRebufferingTimeNs(0),
188*ec779b8eSAndroid Build Coastguard Worker       mPreviousSeekTimeUs(0),
189*ec779b8eSAndroid Build Coastguard Worker       mAudioEOS(false),
190*ec779b8eSAndroid Build Coastguard Worker       mVideoEOS(false),
191*ec779b8eSAndroid Build Coastguard Worker       mScanSourcesPending(false),
192*ec779b8eSAndroid Build Coastguard Worker       mScanSourcesGeneration(0),
193*ec779b8eSAndroid Build Coastguard Worker       mPollDurationGeneration(0),
194*ec779b8eSAndroid Build Coastguard Worker       mTimedTextGeneration(0),
195*ec779b8eSAndroid Build Coastguard Worker       mFlushingAudio(NONE),
196*ec779b8eSAndroid Build Coastguard Worker       mFlushingVideo(NONE),
197*ec779b8eSAndroid Build Coastguard Worker       mResumePending(false),
198*ec779b8eSAndroid Build Coastguard Worker       mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
199*ec779b8eSAndroid Build Coastguard Worker       mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT),
200*ec779b8eSAndroid Build Coastguard Worker       mVideoFpsHint(-1.f),
201*ec779b8eSAndroid Build Coastguard Worker       mStarted(false),
202*ec779b8eSAndroid Build Coastguard Worker       mPrepared(false),
203*ec779b8eSAndroid Build Coastguard Worker       mResetting(false),
204*ec779b8eSAndroid Build Coastguard Worker       mSourceStarted(false),
205*ec779b8eSAndroid Build Coastguard Worker       mAudioDecoderError(false),
206*ec779b8eSAndroid Build Coastguard Worker       mVideoDecoderError(false),
207*ec779b8eSAndroid Build Coastguard Worker       mPaused(false),
208*ec779b8eSAndroid Build Coastguard Worker       mPausedByClient(true),
209*ec779b8eSAndroid Build Coastguard Worker       mPausedForBuffering(false),
210*ec779b8eSAndroid Build Coastguard Worker       mIsDrmProtected(false),
211*ec779b8eSAndroid Build Coastguard Worker       mDataSourceType(DATA_SOURCE_TYPE_NONE) {
212*ec779b8eSAndroid Build Coastguard Worker     CHECK(mediaClock != NULL);
213*ec779b8eSAndroid Build Coastguard Worker     clearFlushComplete();
214*ec779b8eSAndroid Build Coastguard Worker }
215*ec779b8eSAndroid Build Coastguard Worker 
~NuPlayer()216*ec779b8eSAndroid Build Coastguard Worker NuPlayer::~NuPlayer() {
217*ec779b8eSAndroid Build Coastguard Worker }
218*ec779b8eSAndroid Build Coastguard Worker 
setUID(uid_t uid)219*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::setUID(uid_t uid) {
220*ec779b8eSAndroid Build Coastguard Worker     mUIDValid = true;
221*ec779b8eSAndroid Build Coastguard Worker     mUID = uid;
222*ec779b8eSAndroid Build Coastguard Worker }
223*ec779b8eSAndroid Build Coastguard Worker 
init(const wp<NuPlayerDriver> & driver)224*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::init(const wp<NuPlayerDriver> &driver) {
225*ec779b8eSAndroid Build Coastguard Worker     mDriver = driver;
226*ec779b8eSAndroid Build Coastguard Worker 
227*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> notify = new AMessage(kWhatMediaClockNotify, this);
228*ec779b8eSAndroid Build Coastguard Worker     mMediaClock->setNotificationMessage(notify);
229*ec779b8eSAndroid Build Coastguard Worker }
230*ec779b8eSAndroid Build Coastguard Worker 
setDataSourceAsync(const sp<IStreamSource> & source)231*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) {
232*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
233*ec779b8eSAndroid Build Coastguard Worker 
234*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
235*ec779b8eSAndroid Build Coastguard Worker 
236*ec779b8eSAndroid Build Coastguard Worker     msg->setObject("source", new StreamingSource(notify, source));
237*ec779b8eSAndroid Build Coastguard Worker     msg->post();
238*ec779b8eSAndroid Build Coastguard Worker     mDataSourceType = DATA_SOURCE_TYPE_STREAM;
239*ec779b8eSAndroid Build Coastguard Worker }
240*ec779b8eSAndroid Build Coastguard Worker 
IsHTTPLiveURL(const char * url)241*ec779b8eSAndroid Build Coastguard Worker static bool IsHTTPLiveURL(const char *url) {
242*ec779b8eSAndroid Build Coastguard Worker     if (!strncasecmp("http://", url, 7)
243*ec779b8eSAndroid Build Coastguard Worker             || !strncasecmp("https://", url, 8)
244*ec779b8eSAndroid Build Coastguard Worker             || !strncasecmp("file://", url, 7)) {
245*ec779b8eSAndroid Build Coastguard Worker         size_t len = strlen(url);
246*ec779b8eSAndroid Build Coastguard Worker         if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
247*ec779b8eSAndroid Build Coastguard Worker             return true;
248*ec779b8eSAndroid Build Coastguard Worker         }
249*ec779b8eSAndroid Build Coastguard Worker 
250*ec779b8eSAndroid Build Coastguard Worker         if (strstr(url,"m3u8")) {
251*ec779b8eSAndroid Build Coastguard Worker             return true;
252*ec779b8eSAndroid Build Coastguard Worker         }
253*ec779b8eSAndroid Build Coastguard Worker     }
254*ec779b8eSAndroid Build Coastguard Worker 
255*ec779b8eSAndroid Build Coastguard Worker     return false;
256*ec779b8eSAndroid Build Coastguard Worker }
257*ec779b8eSAndroid Build Coastguard Worker 
setDataSourceAsync(const sp<IMediaHTTPService> & httpService,const char * url,const KeyedVector<String8,String8> * headers)258*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::setDataSourceAsync(
259*ec779b8eSAndroid Build Coastguard Worker         const sp<IMediaHTTPService> &httpService,
260*ec779b8eSAndroid Build Coastguard Worker         const char *url,
261*ec779b8eSAndroid Build Coastguard Worker         const KeyedVector<String8, String8> *headers) {
262*ec779b8eSAndroid Build Coastguard Worker 
263*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
264*ec779b8eSAndroid Build Coastguard Worker     size_t len = strlen(url);
265*ec779b8eSAndroid Build Coastguard Worker 
266*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
267*ec779b8eSAndroid Build Coastguard Worker 
268*ec779b8eSAndroid Build Coastguard Worker     sp<Source> source;
269*ec779b8eSAndroid Build Coastguard Worker     if (IsHTTPLiveURL(url)) {
270*ec779b8eSAndroid Build Coastguard Worker         source = new HTTPLiveSource(notify, httpService, url, headers);
271*ec779b8eSAndroid Build Coastguard Worker         ALOGV("setDataSourceAsync HTTPLiveSource %s", url);
272*ec779b8eSAndroid Build Coastguard Worker         mDataSourceType = DATA_SOURCE_TYPE_HTTP_LIVE;
273*ec779b8eSAndroid Build Coastguard Worker     } else if (!strncasecmp(url, "rtsp://", 7)) {
274*ec779b8eSAndroid Build Coastguard Worker         source = new RTSPSource(
275*ec779b8eSAndroid Build Coastguard Worker                 notify, httpService, url, headers, mUIDValid, mUID);
276*ec779b8eSAndroid Build Coastguard Worker         ALOGV("setDataSourceAsync RTSPSource %s", url);
277*ec779b8eSAndroid Build Coastguard Worker         mDataSourceType = DATA_SOURCE_TYPE_RTSP;
278*ec779b8eSAndroid Build Coastguard Worker     } else if ((!strncasecmp(url, "http://", 7)
279*ec779b8eSAndroid Build Coastguard Worker                 || !strncasecmp(url, "https://", 8))
280*ec779b8eSAndroid Build Coastguard Worker                     && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
281*ec779b8eSAndroid Build Coastguard Worker                     || strstr(url, ".sdp?"))) {
282*ec779b8eSAndroid Build Coastguard Worker         source = new RTSPSource(
283*ec779b8eSAndroid Build Coastguard Worker                 notify, httpService, url, headers, mUIDValid, mUID, true);
284*ec779b8eSAndroid Build Coastguard Worker         ALOGV("setDataSourceAsync RTSPSource http/https/.sdp %s", url);
285*ec779b8eSAndroid Build Coastguard Worker         mDataSourceType = DATA_SOURCE_TYPE_RTSP;
286*ec779b8eSAndroid Build Coastguard Worker     } else {
287*ec779b8eSAndroid Build Coastguard Worker         ALOGV("setDataSourceAsync GenericSource %s", url);
288*ec779b8eSAndroid Build Coastguard Worker 
289*ec779b8eSAndroid Build Coastguard Worker         sp<GenericSource> genericSource =
290*ec779b8eSAndroid Build Coastguard Worker                 new GenericSource(notify, mUIDValid, mUID, mMediaClock);
291*ec779b8eSAndroid Build Coastguard Worker 
292*ec779b8eSAndroid Build Coastguard Worker         status_t err = genericSource->setDataSource(httpService, url, headers);
293*ec779b8eSAndroid Build Coastguard Worker 
294*ec779b8eSAndroid Build Coastguard Worker         if (err == OK) {
295*ec779b8eSAndroid Build Coastguard Worker             source = genericSource;
296*ec779b8eSAndroid Build Coastguard Worker         } else {
297*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Failed to set data source!");
298*ec779b8eSAndroid Build Coastguard Worker         }
299*ec779b8eSAndroid Build Coastguard Worker 
300*ec779b8eSAndroid Build Coastguard Worker         // regardless of success/failure
301*ec779b8eSAndroid Build Coastguard Worker         mDataSourceType = DATA_SOURCE_TYPE_GENERIC_URL;
302*ec779b8eSAndroid Build Coastguard Worker     }
303*ec779b8eSAndroid Build Coastguard Worker     msg->setObject("source", source);
304*ec779b8eSAndroid Build Coastguard Worker     msg->post();
305*ec779b8eSAndroid Build Coastguard Worker }
306*ec779b8eSAndroid Build Coastguard Worker 
setDataSourceAsync(int fd,int64_t offset,int64_t length)307*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) {
308*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
309*ec779b8eSAndroid Build Coastguard Worker 
310*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
311*ec779b8eSAndroid Build Coastguard Worker 
312*ec779b8eSAndroid Build Coastguard Worker     sp<GenericSource> source =
313*ec779b8eSAndroid Build Coastguard Worker             new GenericSource(notify, mUIDValid, mUID, mMediaClock);
314*ec779b8eSAndroid Build Coastguard Worker 
315*ec779b8eSAndroid Build Coastguard Worker     ALOGV("setDataSourceAsync fd %d/%lld/%lld source: %p",
316*ec779b8eSAndroid Build Coastguard Worker             fd, (long long)offset, (long long)length, source.get());
317*ec779b8eSAndroid Build Coastguard Worker 
318*ec779b8eSAndroid Build Coastguard Worker     status_t err = source->setDataSource(fd, offset, length);
319*ec779b8eSAndroid Build Coastguard Worker 
320*ec779b8eSAndroid Build Coastguard Worker     if (err != OK) {
321*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Failed to set data source!");
322*ec779b8eSAndroid Build Coastguard Worker         source = NULL;
323*ec779b8eSAndroid Build Coastguard Worker     }
324*ec779b8eSAndroid Build Coastguard Worker 
325*ec779b8eSAndroid Build Coastguard Worker     msg->setObject("source", source);
326*ec779b8eSAndroid Build Coastguard Worker     msg->post();
327*ec779b8eSAndroid Build Coastguard Worker     mDataSourceType = DATA_SOURCE_TYPE_GENERIC_FD;
328*ec779b8eSAndroid Build Coastguard Worker }
329*ec779b8eSAndroid Build Coastguard Worker 
setDataSourceAsync(const sp<DataSource> & dataSource)330*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::setDataSourceAsync(const sp<DataSource> &dataSource) {
331*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
332*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
333*ec779b8eSAndroid Build Coastguard Worker 
334*ec779b8eSAndroid Build Coastguard Worker     sp<GenericSource> source = new GenericSource(notify, mUIDValid, mUID, mMediaClock);
335*ec779b8eSAndroid Build Coastguard Worker     status_t err = source->setDataSource(dataSource);
336*ec779b8eSAndroid Build Coastguard Worker 
337*ec779b8eSAndroid Build Coastguard Worker     if (err != OK) {
338*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Failed to set data source!");
339*ec779b8eSAndroid Build Coastguard Worker         source = NULL;
340*ec779b8eSAndroid Build Coastguard Worker     }
341*ec779b8eSAndroid Build Coastguard Worker 
342*ec779b8eSAndroid Build Coastguard Worker     msg->setObject("source", source);
343*ec779b8eSAndroid Build Coastguard Worker     msg->post();
344*ec779b8eSAndroid Build Coastguard Worker     mDataSourceType = DATA_SOURCE_TYPE_MEDIA;
345*ec779b8eSAndroid Build Coastguard Worker }
346*ec779b8eSAndroid Build Coastguard Worker 
getBufferingSettings(BufferingSettings * buffering)347*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::getBufferingSettings(
348*ec779b8eSAndroid Build Coastguard Worker         BufferingSettings *buffering /* nonnull */) {
349*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatGetBufferingSettings, this);
350*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> response;
351*ec779b8eSAndroid Build Coastguard Worker     status_t err = msg->postAndAwaitResponse(&response);
352*ec779b8eSAndroid Build Coastguard Worker     if (err == OK && response != NULL) {
353*ec779b8eSAndroid Build Coastguard Worker         CHECK(response->findInt32("err", &err));
354*ec779b8eSAndroid Build Coastguard Worker         if (err == OK) {
355*ec779b8eSAndroid Build Coastguard Worker             readFromAMessage(response, buffering);
356*ec779b8eSAndroid Build Coastguard Worker         }
357*ec779b8eSAndroid Build Coastguard Worker     }
358*ec779b8eSAndroid Build Coastguard Worker     return err;
359*ec779b8eSAndroid Build Coastguard Worker }
360*ec779b8eSAndroid Build Coastguard Worker 
setBufferingSettings(const BufferingSettings & buffering)361*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::setBufferingSettings(const BufferingSettings& buffering) {
362*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatSetBufferingSettings, this);
363*ec779b8eSAndroid Build Coastguard Worker     writeToAMessage(msg, buffering);
364*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> response;
365*ec779b8eSAndroid Build Coastguard Worker     status_t err = msg->postAndAwaitResponse(&response);
366*ec779b8eSAndroid Build Coastguard Worker     if (err == OK && response != NULL) {
367*ec779b8eSAndroid Build Coastguard Worker         CHECK(response->findInt32("err", &err));
368*ec779b8eSAndroid Build Coastguard Worker     }
369*ec779b8eSAndroid Build Coastguard Worker     return err;
370*ec779b8eSAndroid Build Coastguard Worker }
371*ec779b8eSAndroid Build Coastguard Worker 
setDataSourceAsync(const String8 & rtpParams)372*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::setDataSourceAsync(const String8& rtpParams) {
373*ec779b8eSAndroid Build Coastguard Worker     ALOGD("setDataSourceAsync for RTP = %s", rtpParams.c_str());
374*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
375*ec779b8eSAndroid Build Coastguard Worker 
376*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
377*ec779b8eSAndroid Build Coastguard Worker     sp<Source> source = new RTPSource(notify, rtpParams);
378*ec779b8eSAndroid Build Coastguard Worker 
379*ec779b8eSAndroid Build Coastguard Worker     msg->setObject("source", source);
380*ec779b8eSAndroid Build Coastguard Worker     msg->post();
381*ec779b8eSAndroid Build Coastguard Worker     mDataSourceType = DATA_SOURCE_TYPE_RTP;
382*ec779b8eSAndroid Build Coastguard Worker }
383*ec779b8eSAndroid Build Coastguard Worker 
prepareAsync()384*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::prepareAsync() {
385*ec779b8eSAndroid Build Coastguard Worker     ALOGV("prepareAsync");
386*ec779b8eSAndroid Build Coastguard Worker 
387*ec779b8eSAndroid Build Coastguard Worker     (new AMessage(kWhatPrepare, this))->post();
388*ec779b8eSAndroid Build Coastguard Worker }
389*ec779b8eSAndroid Build Coastguard Worker 
setVideoSurfaceTextureAsync(const sp<IGraphicBufferProducer> & bufferProducer)390*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::setVideoSurfaceTextureAsync(
391*ec779b8eSAndroid Build Coastguard Worker         const sp<IGraphicBufferProducer> &bufferProducer) {
392*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, this);
393*ec779b8eSAndroid Build Coastguard Worker 
394*ec779b8eSAndroid Build Coastguard Worker     if (bufferProducer == NULL) {
395*ec779b8eSAndroid Build Coastguard Worker         msg->setObject("surface", NULL);
396*ec779b8eSAndroid Build Coastguard Worker     } else {
397*ec779b8eSAndroid Build Coastguard Worker         msg->setObject("surface", new Surface(bufferProducer, true /* controlledByApp */));
398*ec779b8eSAndroid Build Coastguard Worker     }
399*ec779b8eSAndroid Build Coastguard Worker 
400*ec779b8eSAndroid Build Coastguard Worker     msg->post();
401*ec779b8eSAndroid Build Coastguard Worker }
402*ec779b8eSAndroid Build Coastguard Worker 
setAudioSink(const sp<MediaPlayerBase::AudioSink> & sink)403*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) {
404*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatSetAudioSink, this);
405*ec779b8eSAndroid Build Coastguard Worker     msg->setObject("sink", sink);
406*ec779b8eSAndroid Build Coastguard Worker     msg->post();
407*ec779b8eSAndroid Build Coastguard Worker }
408*ec779b8eSAndroid Build Coastguard Worker 
start()409*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::start() {
410*ec779b8eSAndroid Build Coastguard Worker     (new AMessage(kWhatStart, this))->post();
411*ec779b8eSAndroid Build Coastguard Worker }
412*ec779b8eSAndroid Build Coastguard Worker 
setPlaybackSettings(const AudioPlaybackRate & rate)413*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::setPlaybackSettings(const AudioPlaybackRate &rate) {
414*ec779b8eSAndroid Build Coastguard Worker     // do some cursory validation of the settings here. audio modes are
415*ec779b8eSAndroid Build Coastguard Worker     // only validated when set on the audiosink.
416*ec779b8eSAndroid Build Coastguard Worker      if ((rate.mSpeed != 0.f && rate.mSpeed < AUDIO_TIMESTRETCH_SPEED_MIN)
417*ec779b8eSAndroid Build Coastguard Worker             || rate.mSpeed > AUDIO_TIMESTRETCH_SPEED_MAX
418*ec779b8eSAndroid Build Coastguard Worker             || rate.mPitch < AUDIO_TIMESTRETCH_SPEED_MIN
419*ec779b8eSAndroid Build Coastguard Worker             || rate.mPitch > AUDIO_TIMESTRETCH_SPEED_MAX) {
420*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
421*ec779b8eSAndroid Build Coastguard Worker     }
422*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatConfigPlayback, this);
423*ec779b8eSAndroid Build Coastguard Worker     writeToAMessage(msg, rate);
424*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> response;
425*ec779b8eSAndroid Build Coastguard Worker     status_t err = msg->postAndAwaitResponse(&response);
426*ec779b8eSAndroid Build Coastguard Worker     if (err == OK && response != NULL) {
427*ec779b8eSAndroid Build Coastguard Worker         CHECK(response->findInt32("err", &err));
428*ec779b8eSAndroid Build Coastguard Worker     }
429*ec779b8eSAndroid Build Coastguard Worker     return err;
430*ec779b8eSAndroid Build Coastguard Worker }
431*ec779b8eSAndroid Build Coastguard Worker 
getPlaybackSettings(AudioPlaybackRate * rate)432*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::getPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
433*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatGetPlaybackSettings, this);
434*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> response;
435*ec779b8eSAndroid Build Coastguard Worker     status_t err = msg->postAndAwaitResponse(&response);
436*ec779b8eSAndroid Build Coastguard Worker     if (err == OK && response != NULL) {
437*ec779b8eSAndroid Build Coastguard Worker         CHECK(response->findInt32("err", &err));
438*ec779b8eSAndroid Build Coastguard Worker         if (err == OK) {
439*ec779b8eSAndroid Build Coastguard Worker             readFromAMessage(response, rate);
440*ec779b8eSAndroid Build Coastguard Worker         }
441*ec779b8eSAndroid Build Coastguard Worker     }
442*ec779b8eSAndroid Build Coastguard Worker     return err;
443*ec779b8eSAndroid Build Coastguard Worker }
444*ec779b8eSAndroid Build Coastguard Worker 
setSyncSettings(const AVSyncSettings & sync,float videoFpsHint)445*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::setSyncSettings(const AVSyncSettings &sync, float videoFpsHint) {
446*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatConfigSync, this);
447*ec779b8eSAndroid Build Coastguard Worker     writeToAMessage(msg, sync, videoFpsHint);
448*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> response;
449*ec779b8eSAndroid Build Coastguard Worker     status_t err = msg->postAndAwaitResponse(&response);
450*ec779b8eSAndroid Build Coastguard Worker     if (err == OK && response != NULL) {
451*ec779b8eSAndroid Build Coastguard Worker         CHECK(response->findInt32("err", &err));
452*ec779b8eSAndroid Build Coastguard Worker     }
453*ec779b8eSAndroid Build Coastguard Worker     return err;
454*ec779b8eSAndroid Build Coastguard Worker }
455*ec779b8eSAndroid Build Coastguard Worker 
getSyncSettings(AVSyncSettings * sync,float * videoFps)456*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::getSyncSettings(
457*ec779b8eSAndroid Build Coastguard Worker         AVSyncSettings *sync /* nonnull */, float *videoFps /* nonnull */) {
458*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatGetSyncSettings, this);
459*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> response;
460*ec779b8eSAndroid Build Coastguard Worker     status_t err = msg->postAndAwaitResponse(&response);
461*ec779b8eSAndroid Build Coastguard Worker     if (err == OK && response != NULL) {
462*ec779b8eSAndroid Build Coastguard Worker         CHECK(response->findInt32("err", &err));
463*ec779b8eSAndroid Build Coastguard Worker         if (err == OK) {
464*ec779b8eSAndroid Build Coastguard Worker             readFromAMessage(response, sync, videoFps);
465*ec779b8eSAndroid Build Coastguard Worker         }
466*ec779b8eSAndroid Build Coastguard Worker     }
467*ec779b8eSAndroid Build Coastguard Worker     return err;
468*ec779b8eSAndroid Build Coastguard Worker }
469*ec779b8eSAndroid Build Coastguard Worker 
pause()470*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::pause() {
471*ec779b8eSAndroid Build Coastguard Worker     (new AMessage(kWhatPause, this))->post();
472*ec779b8eSAndroid Build Coastguard Worker }
473*ec779b8eSAndroid Build Coastguard Worker 
resetAsync()474*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::resetAsync() {
475*ec779b8eSAndroid Build Coastguard Worker     sp<Source> source;
476*ec779b8eSAndroid Build Coastguard Worker     {
477*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock autoLock(mSourceLock);
478*ec779b8eSAndroid Build Coastguard Worker         source = mSource;
479*ec779b8eSAndroid Build Coastguard Worker     }
480*ec779b8eSAndroid Build Coastguard Worker 
481*ec779b8eSAndroid Build Coastguard Worker     if (source != NULL) {
482*ec779b8eSAndroid Build Coastguard Worker         // During a reset, the data source might be unresponsive already, we need to
483*ec779b8eSAndroid Build Coastguard Worker         // disconnect explicitly so that reads exit promptly.
484*ec779b8eSAndroid Build Coastguard Worker         // We can't queue the disconnect request to the looper, as it might be
485*ec779b8eSAndroid Build Coastguard Worker         // queued behind a stuck read and never gets processed.
486*ec779b8eSAndroid Build Coastguard Worker         // Doing a disconnect outside the looper to allows the pending reads to exit
487*ec779b8eSAndroid Build Coastguard Worker         // (either successfully or with error).
488*ec779b8eSAndroid Build Coastguard Worker         source->disconnect();
489*ec779b8eSAndroid Build Coastguard Worker     }
490*ec779b8eSAndroid Build Coastguard Worker 
491*ec779b8eSAndroid Build Coastguard Worker     (new AMessage(kWhatReset, this))->post();
492*ec779b8eSAndroid Build Coastguard Worker }
493*ec779b8eSAndroid Build Coastguard Worker 
notifyAt(int64_t mediaTimeUs)494*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::notifyAt(int64_t mediaTimeUs) {
495*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> notify = new AMessage(kWhatNotifyTime, this);
496*ec779b8eSAndroid Build Coastguard Worker     notify->setInt64("timerUs", mediaTimeUs);
497*ec779b8eSAndroid Build Coastguard Worker     mMediaClock->addTimer(notify, mediaTimeUs);
498*ec779b8eSAndroid Build Coastguard Worker     return OK;
499*ec779b8eSAndroid Build Coastguard Worker }
500*ec779b8eSAndroid Build Coastguard Worker 
seekToAsync(int64_t seekTimeUs,MediaPlayerSeekMode mode,bool needNotify)501*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::seekToAsync(int64_t seekTimeUs, MediaPlayerSeekMode mode, bool needNotify) {
502*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatSeek, this);
503*ec779b8eSAndroid Build Coastguard Worker     msg->setInt64("seekTimeUs", seekTimeUs);
504*ec779b8eSAndroid Build Coastguard Worker     msg->setInt32("mode", mode);
505*ec779b8eSAndroid Build Coastguard Worker     msg->setInt32("needNotify", needNotify);
506*ec779b8eSAndroid Build Coastguard Worker     msg->post();
507*ec779b8eSAndroid Build Coastguard Worker }
508*ec779b8eSAndroid Build Coastguard Worker 
509*ec779b8eSAndroid Build Coastguard Worker 
writeTrackInfo(Parcel * reply,const sp<AMessage> & format) const510*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::writeTrackInfo(
511*ec779b8eSAndroid Build Coastguard Worker         Parcel* reply, const sp<AMessage>& format) const {
512*ec779b8eSAndroid Build Coastguard Worker     if (format == NULL) {
513*ec779b8eSAndroid Build Coastguard Worker         ALOGE("NULL format");
514*ec779b8eSAndroid Build Coastguard Worker         return;
515*ec779b8eSAndroid Build Coastguard Worker     }
516*ec779b8eSAndroid Build Coastguard Worker     int32_t trackType;
517*ec779b8eSAndroid Build Coastguard Worker     if (!format->findInt32("type", &trackType)) {
518*ec779b8eSAndroid Build Coastguard Worker         ALOGE("no track type");
519*ec779b8eSAndroid Build Coastguard Worker         return;
520*ec779b8eSAndroid Build Coastguard Worker     }
521*ec779b8eSAndroid Build Coastguard Worker 
522*ec779b8eSAndroid Build Coastguard Worker     AString mime;
523*ec779b8eSAndroid Build Coastguard Worker     if (!format->findString("mime", &mime)) {
524*ec779b8eSAndroid Build Coastguard Worker         // Java MediaPlayer only uses mimetype for subtitle and timedtext tracks.
525*ec779b8eSAndroid Build Coastguard Worker         // If we can't find the mimetype here it means that we wouldn't be needing
526*ec779b8eSAndroid Build Coastguard Worker         // the mimetype on the Java end. We still write a placeholder mime to keep the
527*ec779b8eSAndroid Build Coastguard Worker         // (de)serialization logic simple.
528*ec779b8eSAndroid Build Coastguard Worker         if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
529*ec779b8eSAndroid Build Coastguard Worker             mime = "audio/";
530*ec779b8eSAndroid Build Coastguard Worker         } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
531*ec779b8eSAndroid Build Coastguard Worker             mime = "video/";
532*ec779b8eSAndroid Build Coastguard Worker         } else {
533*ec779b8eSAndroid Build Coastguard Worker             ALOGE("unknown track type: %d", trackType);
534*ec779b8eSAndroid Build Coastguard Worker             return;
535*ec779b8eSAndroid Build Coastguard Worker         }
536*ec779b8eSAndroid Build Coastguard Worker     }
537*ec779b8eSAndroid Build Coastguard Worker 
538*ec779b8eSAndroid Build Coastguard Worker     AString lang;
539*ec779b8eSAndroid Build Coastguard Worker     if (!format->findString("language", &lang)) {
540*ec779b8eSAndroid Build Coastguard Worker         ALOGE("no language");
541*ec779b8eSAndroid Build Coastguard Worker         return;
542*ec779b8eSAndroid Build Coastguard Worker     }
543*ec779b8eSAndroid Build Coastguard Worker 
544*ec779b8eSAndroid Build Coastguard Worker     reply->writeInt32(2); // write something non-zero
545*ec779b8eSAndroid Build Coastguard Worker     reply->writeInt32(trackType);
546*ec779b8eSAndroid Build Coastguard Worker     reply->writeString16(String16(mime.c_str()));
547*ec779b8eSAndroid Build Coastguard Worker     reply->writeString16(String16(lang.c_str()));
548*ec779b8eSAndroid Build Coastguard Worker 
549*ec779b8eSAndroid Build Coastguard Worker     if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
550*ec779b8eSAndroid Build Coastguard Worker         int32_t isAuto, isDefault, isForced;
551*ec779b8eSAndroid Build Coastguard Worker         CHECK(format->findInt32("auto", &isAuto));
552*ec779b8eSAndroid Build Coastguard Worker         CHECK(format->findInt32("default", &isDefault));
553*ec779b8eSAndroid Build Coastguard Worker         CHECK(format->findInt32("forced", &isForced));
554*ec779b8eSAndroid Build Coastguard Worker 
555*ec779b8eSAndroid Build Coastguard Worker         reply->writeInt32(isAuto);
556*ec779b8eSAndroid Build Coastguard Worker         reply->writeInt32(isDefault);
557*ec779b8eSAndroid Build Coastguard Worker         reply->writeInt32(isForced);
558*ec779b8eSAndroid Build Coastguard Worker     } else if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
559*ec779b8eSAndroid Build Coastguard Worker         int32_t hapticChannelCount;
560*ec779b8eSAndroid Build Coastguard Worker         bool hasHapticChannels = format->findInt32("haptic-channel-count", &hapticChannelCount);
561*ec779b8eSAndroid Build Coastguard Worker         reply->writeInt32(hasHapticChannels);
562*ec779b8eSAndroid Build Coastguard Worker         if (hasHapticChannels) {
563*ec779b8eSAndroid Build Coastguard Worker             reply->writeInt32(hapticChannelCount);
564*ec779b8eSAndroid Build Coastguard Worker         }
565*ec779b8eSAndroid Build Coastguard Worker     }
566*ec779b8eSAndroid Build Coastguard Worker }
567*ec779b8eSAndroid Build Coastguard Worker 
onMessageReceived(const sp<AMessage> & msg)568*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
569*ec779b8eSAndroid Build Coastguard Worker     switch (msg->what()) {
570*ec779b8eSAndroid Build Coastguard Worker         case kWhatSetDataSource:
571*ec779b8eSAndroid Build Coastguard Worker         {
572*ec779b8eSAndroid Build Coastguard Worker             ALOGV("kWhatSetDataSource");
573*ec779b8eSAndroid Build Coastguard Worker 
574*ec779b8eSAndroid Build Coastguard Worker             CHECK(mSource == NULL);
575*ec779b8eSAndroid Build Coastguard Worker 
576*ec779b8eSAndroid Build Coastguard Worker             status_t err = OK;
577*ec779b8eSAndroid Build Coastguard Worker             sp<RefBase> obj;
578*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findObject("source", &obj));
579*ec779b8eSAndroid Build Coastguard Worker             if (obj != NULL) {
580*ec779b8eSAndroid Build Coastguard Worker                 Mutex::Autolock autoLock(mSourceLock);
581*ec779b8eSAndroid Build Coastguard Worker                 mSource = static_cast<Source *>(obj.get());
582*ec779b8eSAndroid Build Coastguard Worker             } else {
583*ec779b8eSAndroid Build Coastguard Worker                 err = UNKNOWN_ERROR;
584*ec779b8eSAndroid Build Coastguard Worker             }
585*ec779b8eSAndroid Build Coastguard Worker 
586*ec779b8eSAndroid Build Coastguard Worker             CHECK(mDriver != NULL);
587*ec779b8eSAndroid Build Coastguard Worker             sp<NuPlayerDriver> driver = mDriver.promote();
588*ec779b8eSAndroid Build Coastguard Worker             if (driver != NULL) {
589*ec779b8eSAndroid Build Coastguard Worker                 driver->notifySetDataSourceCompleted(err);
590*ec779b8eSAndroid Build Coastguard Worker             }
591*ec779b8eSAndroid Build Coastguard Worker             break;
592*ec779b8eSAndroid Build Coastguard Worker         }
593*ec779b8eSAndroid Build Coastguard Worker 
594*ec779b8eSAndroid Build Coastguard Worker         case kWhatGetBufferingSettings:
595*ec779b8eSAndroid Build Coastguard Worker         {
596*ec779b8eSAndroid Build Coastguard Worker             sp<AReplyToken> replyID;
597*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->senderAwaitsResponse(&replyID));
598*ec779b8eSAndroid Build Coastguard Worker 
599*ec779b8eSAndroid Build Coastguard Worker             ALOGV("kWhatGetBufferingSettings");
600*ec779b8eSAndroid Build Coastguard Worker             BufferingSettings buffering;
601*ec779b8eSAndroid Build Coastguard Worker             status_t err = OK;
602*ec779b8eSAndroid Build Coastguard Worker             if (mSource != NULL) {
603*ec779b8eSAndroid Build Coastguard Worker                 err = mSource->getBufferingSettings(&buffering);
604*ec779b8eSAndroid Build Coastguard Worker             } else {
605*ec779b8eSAndroid Build Coastguard Worker                 err = INVALID_OPERATION;
606*ec779b8eSAndroid Build Coastguard Worker             }
607*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> response = new AMessage;
608*ec779b8eSAndroid Build Coastguard Worker             if (err == OK) {
609*ec779b8eSAndroid Build Coastguard Worker                 writeToAMessage(response, buffering);
610*ec779b8eSAndroid Build Coastguard Worker             }
611*ec779b8eSAndroid Build Coastguard Worker             response->setInt32("err", err);
612*ec779b8eSAndroid Build Coastguard Worker             response->postReply(replyID);
613*ec779b8eSAndroid Build Coastguard Worker             break;
614*ec779b8eSAndroid Build Coastguard Worker         }
615*ec779b8eSAndroid Build Coastguard Worker 
616*ec779b8eSAndroid Build Coastguard Worker         case kWhatSetBufferingSettings:
617*ec779b8eSAndroid Build Coastguard Worker         {
618*ec779b8eSAndroid Build Coastguard Worker             sp<AReplyToken> replyID;
619*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->senderAwaitsResponse(&replyID));
620*ec779b8eSAndroid Build Coastguard Worker 
621*ec779b8eSAndroid Build Coastguard Worker             ALOGV("kWhatSetBufferingSettings");
622*ec779b8eSAndroid Build Coastguard Worker             BufferingSettings buffering;
623*ec779b8eSAndroid Build Coastguard Worker             readFromAMessage(msg, &buffering);
624*ec779b8eSAndroid Build Coastguard Worker             status_t err = OK;
625*ec779b8eSAndroid Build Coastguard Worker             if (mSource != NULL) {
626*ec779b8eSAndroid Build Coastguard Worker                 err = mSource->setBufferingSettings(buffering);
627*ec779b8eSAndroid Build Coastguard Worker             } else {
628*ec779b8eSAndroid Build Coastguard Worker                 err = INVALID_OPERATION;
629*ec779b8eSAndroid Build Coastguard Worker             }
630*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> response = new AMessage;
631*ec779b8eSAndroid Build Coastguard Worker             response->setInt32("err", err);
632*ec779b8eSAndroid Build Coastguard Worker             response->postReply(replyID);
633*ec779b8eSAndroid Build Coastguard Worker             break;
634*ec779b8eSAndroid Build Coastguard Worker         }
635*ec779b8eSAndroid Build Coastguard Worker 
636*ec779b8eSAndroid Build Coastguard Worker         case kWhatPrepare:
637*ec779b8eSAndroid Build Coastguard Worker         {
638*ec779b8eSAndroid Build Coastguard Worker             ALOGV("onMessageReceived kWhatPrepare");
639*ec779b8eSAndroid Build Coastguard Worker 
640*ec779b8eSAndroid Build Coastguard Worker             mSource->prepareAsync();
641*ec779b8eSAndroid Build Coastguard Worker             break;
642*ec779b8eSAndroid Build Coastguard Worker         }
643*ec779b8eSAndroid Build Coastguard Worker 
644*ec779b8eSAndroid Build Coastguard Worker         case kWhatGetTrackInfo:
645*ec779b8eSAndroid Build Coastguard Worker         {
646*ec779b8eSAndroid Build Coastguard Worker             sp<AReplyToken> replyID;
647*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->senderAwaitsResponse(&replyID));
648*ec779b8eSAndroid Build Coastguard Worker 
649*ec779b8eSAndroid Build Coastguard Worker             Parcel* reply;
650*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findPointer("reply", (void**)&reply));
651*ec779b8eSAndroid Build Coastguard Worker 
652*ec779b8eSAndroid Build Coastguard Worker             size_t inbandTracks = 0;
653*ec779b8eSAndroid Build Coastguard Worker             if (mSource != NULL) {
654*ec779b8eSAndroid Build Coastguard Worker                 inbandTracks = mSource->getTrackCount();
655*ec779b8eSAndroid Build Coastguard Worker             }
656*ec779b8eSAndroid Build Coastguard Worker 
657*ec779b8eSAndroid Build Coastguard Worker             size_t ccTracks = 0;
658*ec779b8eSAndroid Build Coastguard Worker             if (mCCDecoder != NULL) {
659*ec779b8eSAndroid Build Coastguard Worker                 ccTracks = mCCDecoder->getTrackCount();
660*ec779b8eSAndroid Build Coastguard Worker             }
661*ec779b8eSAndroid Build Coastguard Worker 
662*ec779b8eSAndroid Build Coastguard Worker             // total track count
663*ec779b8eSAndroid Build Coastguard Worker             reply->writeInt32(inbandTracks + ccTracks);
664*ec779b8eSAndroid Build Coastguard Worker 
665*ec779b8eSAndroid Build Coastguard Worker             // write inband tracks
666*ec779b8eSAndroid Build Coastguard Worker             for (size_t i = 0; i < inbandTracks; ++i) {
667*ec779b8eSAndroid Build Coastguard Worker                 writeTrackInfo(reply, mSource->getTrackInfo(i));
668*ec779b8eSAndroid Build Coastguard Worker             }
669*ec779b8eSAndroid Build Coastguard Worker 
670*ec779b8eSAndroid Build Coastguard Worker             // write CC track
671*ec779b8eSAndroid Build Coastguard Worker             for (size_t i = 0; i < ccTracks; ++i) {
672*ec779b8eSAndroid Build Coastguard Worker                 writeTrackInfo(reply, mCCDecoder->getTrackInfo(i));
673*ec779b8eSAndroid Build Coastguard Worker             }
674*ec779b8eSAndroid Build Coastguard Worker 
675*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> response = new AMessage;
676*ec779b8eSAndroid Build Coastguard Worker             response->postReply(replyID);
677*ec779b8eSAndroid Build Coastguard Worker             break;
678*ec779b8eSAndroid Build Coastguard Worker         }
679*ec779b8eSAndroid Build Coastguard Worker 
680*ec779b8eSAndroid Build Coastguard Worker         case kWhatGetSelectedTrack:
681*ec779b8eSAndroid Build Coastguard Worker         {
682*ec779b8eSAndroid Build Coastguard Worker             int32_t type32;
683*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("type", (int32_t*)&type32));
684*ec779b8eSAndroid Build Coastguard Worker             media_track_type type = (media_track_type)type32;
685*ec779b8eSAndroid Build Coastguard Worker 
686*ec779b8eSAndroid Build Coastguard Worker             size_t inbandTracks = 0;
687*ec779b8eSAndroid Build Coastguard Worker             status_t err = INVALID_OPERATION;
688*ec779b8eSAndroid Build Coastguard Worker             ssize_t selectedTrack = -1;
689*ec779b8eSAndroid Build Coastguard Worker             if (mSource != NULL) {
690*ec779b8eSAndroid Build Coastguard Worker                 err = OK;
691*ec779b8eSAndroid Build Coastguard Worker                 inbandTracks = mSource->getTrackCount();
692*ec779b8eSAndroid Build Coastguard Worker                 selectedTrack = mSource->getSelectedTrack(type);
693*ec779b8eSAndroid Build Coastguard Worker             }
694*ec779b8eSAndroid Build Coastguard Worker 
695*ec779b8eSAndroid Build Coastguard Worker             if (selectedTrack == -1 && mCCDecoder != NULL) {
696*ec779b8eSAndroid Build Coastguard Worker                 err = OK;
697*ec779b8eSAndroid Build Coastguard Worker                 selectedTrack = mCCDecoder->getSelectedTrack(type);
698*ec779b8eSAndroid Build Coastguard Worker                 if (selectedTrack != -1) {
699*ec779b8eSAndroid Build Coastguard Worker                     selectedTrack += inbandTracks;
700*ec779b8eSAndroid Build Coastguard Worker                 }
701*ec779b8eSAndroid Build Coastguard Worker             }
702*ec779b8eSAndroid Build Coastguard Worker 
703*ec779b8eSAndroid Build Coastguard Worker             Parcel* reply;
704*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findPointer("reply", (void**)&reply));
705*ec779b8eSAndroid Build Coastguard Worker             reply->writeInt32(selectedTrack);
706*ec779b8eSAndroid Build Coastguard Worker 
707*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> response = new AMessage;
708*ec779b8eSAndroid Build Coastguard Worker             response->setInt32("err", err);
709*ec779b8eSAndroid Build Coastguard Worker 
710*ec779b8eSAndroid Build Coastguard Worker             sp<AReplyToken> replyID;
711*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->senderAwaitsResponse(&replyID));
712*ec779b8eSAndroid Build Coastguard Worker             response->postReply(replyID);
713*ec779b8eSAndroid Build Coastguard Worker             break;
714*ec779b8eSAndroid Build Coastguard Worker         }
715*ec779b8eSAndroid Build Coastguard Worker 
716*ec779b8eSAndroid Build Coastguard Worker         case kWhatSelectTrack:
717*ec779b8eSAndroid Build Coastguard Worker         {
718*ec779b8eSAndroid Build Coastguard Worker             sp<AReplyToken> replyID;
719*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->senderAwaitsResponse(&replyID));
720*ec779b8eSAndroid Build Coastguard Worker 
721*ec779b8eSAndroid Build Coastguard Worker             size_t trackIndex;
722*ec779b8eSAndroid Build Coastguard Worker             int32_t select;
723*ec779b8eSAndroid Build Coastguard Worker             int64_t timeUs;
724*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findSize("trackIndex", &trackIndex));
725*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("select", &select));
726*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt64("timeUs", &timeUs));
727*ec779b8eSAndroid Build Coastguard Worker 
728*ec779b8eSAndroid Build Coastguard Worker             status_t err = INVALID_OPERATION;
729*ec779b8eSAndroid Build Coastguard Worker 
730*ec779b8eSAndroid Build Coastguard Worker             size_t inbandTracks = 0;
731*ec779b8eSAndroid Build Coastguard Worker             if (mSource != NULL) {
732*ec779b8eSAndroid Build Coastguard Worker                 inbandTracks = mSource->getTrackCount();
733*ec779b8eSAndroid Build Coastguard Worker             }
734*ec779b8eSAndroid Build Coastguard Worker             size_t ccTracks = 0;
735*ec779b8eSAndroid Build Coastguard Worker             if (mCCDecoder != NULL) {
736*ec779b8eSAndroid Build Coastguard Worker                 ccTracks = mCCDecoder->getTrackCount();
737*ec779b8eSAndroid Build Coastguard Worker             }
738*ec779b8eSAndroid Build Coastguard Worker 
739*ec779b8eSAndroid Build Coastguard Worker             if (trackIndex < inbandTracks) {
740*ec779b8eSAndroid Build Coastguard Worker                 err = mSource->selectTrack(trackIndex, select, timeUs);
741*ec779b8eSAndroid Build Coastguard Worker 
742*ec779b8eSAndroid Build Coastguard Worker                 if (!select && err == OK) {
743*ec779b8eSAndroid Build Coastguard Worker                     int32_t type;
744*ec779b8eSAndroid Build Coastguard Worker                     sp<AMessage> info = mSource->getTrackInfo(trackIndex);
745*ec779b8eSAndroid Build Coastguard Worker                     if (info != NULL
746*ec779b8eSAndroid Build Coastguard Worker                             && info->findInt32("type", &type)
747*ec779b8eSAndroid Build Coastguard Worker                             && type == MEDIA_TRACK_TYPE_TIMEDTEXT) {
748*ec779b8eSAndroid Build Coastguard Worker                         ++mTimedTextGeneration;
749*ec779b8eSAndroid Build Coastguard Worker                     }
750*ec779b8eSAndroid Build Coastguard Worker                 }
751*ec779b8eSAndroid Build Coastguard Worker             } else {
752*ec779b8eSAndroid Build Coastguard Worker                 trackIndex -= inbandTracks;
753*ec779b8eSAndroid Build Coastguard Worker 
754*ec779b8eSAndroid Build Coastguard Worker                 if (trackIndex < ccTracks) {
755*ec779b8eSAndroid Build Coastguard Worker                     err = mCCDecoder->selectTrack(trackIndex, select);
756*ec779b8eSAndroid Build Coastguard Worker                 }
757*ec779b8eSAndroid Build Coastguard Worker             }
758*ec779b8eSAndroid Build Coastguard Worker 
759*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> response = new AMessage;
760*ec779b8eSAndroid Build Coastguard Worker             response->setInt32("err", err);
761*ec779b8eSAndroid Build Coastguard Worker 
762*ec779b8eSAndroid Build Coastguard Worker             response->postReply(replyID);
763*ec779b8eSAndroid Build Coastguard Worker             break;
764*ec779b8eSAndroid Build Coastguard Worker         }
765*ec779b8eSAndroid Build Coastguard Worker 
766*ec779b8eSAndroid Build Coastguard Worker         case kWhatPollDuration:
767*ec779b8eSAndroid Build Coastguard Worker         {
768*ec779b8eSAndroid Build Coastguard Worker             int32_t generation;
769*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("generation", &generation));
770*ec779b8eSAndroid Build Coastguard Worker 
771*ec779b8eSAndroid Build Coastguard Worker             if (generation != mPollDurationGeneration) {
772*ec779b8eSAndroid Build Coastguard Worker                 // stale
773*ec779b8eSAndroid Build Coastguard Worker                 break;
774*ec779b8eSAndroid Build Coastguard Worker             }
775*ec779b8eSAndroid Build Coastguard Worker 
776*ec779b8eSAndroid Build Coastguard Worker             int64_t durationUs;
777*ec779b8eSAndroid Build Coastguard Worker             if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
778*ec779b8eSAndroid Build Coastguard Worker                 sp<NuPlayerDriver> driver = mDriver.promote();
779*ec779b8eSAndroid Build Coastguard Worker                 if (driver != NULL) {
780*ec779b8eSAndroid Build Coastguard Worker                     driver->notifyDuration(durationUs);
781*ec779b8eSAndroid Build Coastguard Worker                 }
782*ec779b8eSAndroid Build Coastguard Worker             }
783*ec779b8eSAndroid Build Coastguard Worker 
784*ec779b8eSAndroid Build Coastguard Worker             msg->post(1000000LL);  // poll again in a second.
785*ec779b8eSAndroid Build Coastguard Worker             break;
786*ec779b8eSAndroid Build Coastguard Worker         }
787*ec779b8eSAndroid Build Coastguard Worker 
788*ec779b8eSAndroid Build Coastguard Worker         case kWhatSetVideoSurface:
789*ec779b8eSAndroid Build Coastguard Worker         {
790*ec779b8eSAndroid Build Coastguard Worker 
791*ec779b8eSAndroid Build Coastguard Worker             sp<RefBase> obj;
792*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findObject("surface", &obj));
793*ec779b8eSAndroid Build Coastguard Worker             sp<Surface> surface = static_cast<Surface *>(obj.get());
794*ec779b8eSAndroid Build Coastguard Worker 
795*ec779b8eSAndroid Build Coastguard Worker             ALOGD("onSetVideoSurface(%p, %s video decoder)",
796*ec779b8eSAndroid Build Coastguard Worker                     surface.get(),
797*ec779b8eSAndroid Build Coastguard Worker                     (mSource != NULL && mStarted && mSource->getFormat(false /* audio */) != NULL
798*ec779b8eSAndroid Build Coastguard Worker                             && mVideoDecoder != NULL) ? "have" : "no");
799*ec779b8eSAndroid Build Coastguard Worker 
800*ec779b8eSAndroid Build Coastguard Worker             // Need to check mStarted before calling mSource->getFormat because NuPlayer might
801*ec779b8eSAndroid Build Coastguard Worker             // be in preparing state and it could take long time.
802*ec779b8eSAndroid Build Coastguard Worker             // When mStarted is true, mSource must have been set.
803*ec779b8eSAndroid Build Coastguard Worker             if (mSource == NULL || !mStarted || mSource->getFormat(false /* audio */) == NULL
804*ec779b8eSAndroid Build Coastguard Worker                     // NOTE: mVideoDecoder's mSurface is always non-null
805*ec779b8eSAndroid Build Coastguard Worker                     || (mVideoDecoder != NULL && mVideoDecoder->setVideoSurface(surface) == OK)) {
806*ec779b8eSAndroid Build Coastguard Worker                 performSetSurface(surface);
807*ec779b8eSAndroid Build Coastguard Worker                 break;
808*ec779b8eSAndroid Build Coastguard Worker             }
809*ec779b8eSAndroid Build Coastguard Worker 
810*ec779b8eSAndroid Build Coastguard Worker             mDeferredActions.push_back(
811*ec779b8eSAndroid Build Coastguard Worker                     new FlushDecoderAction(
812*ec779b8eSAndroid Build Coastguard Worker                             (obj != NULL ? FLUSH_CMD_FLUSH : FLUSH_CMD_NONE) /* audio */,
813*ec779b8eSAndroid Build Coastguard Worker                                            FLUSH_CMD_SHUTDOWN /* video */));
814*ec779b8eSAndroid Build Coastguard Worker 
815*ec779b8eSAndroid Build Coastguard Worker             mDeferredActions.push_back(new SetSurfaceAction(surface));
816*ec779b8eSAndroid Build Coastguard Worker 
817*ec779b8eSAndroid Build Coastguard Worker             if (obj != NULL) {
818*ec779b8eSAndroid Build Coastguard Worker                 if (mStarted) {
819*ec779b8eSAndroid Build Coastguard Worker                     // Issue a seek to refresh the video screen only if started otherwise
820*ec779b8eSAndroid Build Coastguard Worker                     // the extractor may not yet be started and will assert.
821*ec779b8eSAndroid Build Coastguard Worker                     // If the video decoder is not set (perhaps audio only in this case)
822*ec779b8eSAndroid Build Coastguard Worker                     // do not perform a seek as it is not needed.
823*ec779b8eSAndroid Build Coastguard Worker                     int64_t currentPositionUs = 0;
824*ec779b8eSAndroid Build Coastguard Worker                     if (getCurrentPosition(&currentPositionUs) == OK) {
825*ec779b8eSAndroid Build Coastguard Worker                         mDeferredActions.push_back(
826*ec779b8eSAndroid Build Coastguard Worker                                 new SeekAction(currentPositionUs,
827*ec779b8eSAndroid Build Coastguard Worker                                         MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */));
828*ec779b8eSAndroid Build Coastguard Worker                     }
829*ec779b8eSAndroid Build Coastguard Worker                 }
830*ec779b8eSAndroid Build Coastguard Worker 
831*ec779b8eSAndroid Build Coastguard Worker                 // If there is a new surface texture, instantiate decoders
832*ec779b8eSAndroid Build Coastguard Worker                 // again if possible.
833*ec779b8eSAndroid Build Coastguard Worker                 mDeferredActions.push_back(
834*ec779b8eSAndroid Build Coastguard Worker                         new SimpleAction(&NuPlayer::performScanSources));
835*ec779b8eSAndroid Build Coastguard Worker 
836*ec779b8eSAndroid Build Coastguard Worker                 // After a flush without shutdown, decoder is paused.
837*ec779b8eSAndroid Build Coastguard Worker                 // Don't resume it until source seek is done, otherwise it could
838*ec779b8eSAndroid Build Coastguard Worker                 // start pulling stale data too soon.
839*ec779b8eSAndroid Build Coastguard Worker                 mDeferredActions.push_back(
840*ec779b8eSAndroid Build Coastguard Worker                         new ResumeDecoderAction(false /* needNotify */));
841*ec779b8eSAndroid Build Coastguard Worker             }
842*ec779b8eSAndroid Build Coastguard Worker 
843*ec779b8eSAndroid Build Coastguard Worker             processDeferredActions();
844*ec779b8eSAndroid Build Coastguard Worker             break;
845*ec779b8eSAndroid Build Coastguard Worker         }
846*ec779b8eSAndroid Build Coastguard Worker 
847*ec779b8eSAndroid Build Coastguard Worker         case kWhatSetAudioSink:
848*ec779b8eSAndroid Build Coastguard Worker         {
849*ec779b8eSAndroid Build Coastguard Worker             ALOGV("kWhatSetAudioSink");
850*ec779b8eSAndroid Build Coastguard Worker 
851*ec779b8eSAndroid Build Coastguard Worker             sp<RefBase> obj;
852*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findObject("sink", &obj));
853*ec779b8eSAndroid Build Coastguard Worker 
854*ec779b8eSAndroid Build Coastguard Worker             mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get());
855*ec779b8eSAndroid Build Coastguard Worker             break;
856*ec779b8eSAndroid Build Coastguard Worker         }
857*ec779b8eSAndroid Build Coastguard Worker 
858*ec779b8eSAndroid Build Coastguard Worker         case kWhatStart:
859*ec779b8eSAndroid Build Coastguard Worker         {
860*ec779b8eSAndroid Build Coastguard Worker             ALOGV("kWhatStart");
861*ec779b8eSAndroid Build Coastguard Worker             if (mStarted) {
862*ec779b8eSAndroid Build Coastguard Worker                 // do not resume yet if the source is still buffering
863*ec779b8eSAndroid Build Coastguard Worker                 if (!mPausedForBuffering) {
864*ec779b8eSAndroid Build Coastguard Worker                     onResume();
865*ec779b8eSAndroid Build Coastguard Worker                 }
866*ec779b8eSAndroid Build Coastguard Worker             } else {
867*ec779b8eSAndroid Build Coastguard Worker                 onStart();
868*ec779b8eSAndroid Build Coastguard Worker             }
869*ec779b8eSAndroid Build Coastguard Worker             mPausedByClient = false;
870*ec779b8eSAndroid Build Coastguard Worker             break;
871*ec779b8eSAndroid Build Coastguard Worker         }
872*ec779b8eSAndroid Build Coastguard Worker 
873*ec779b8eSAndroid Build Coastguard Worker         case kWhatConfigPlayback:
874*ec779b8eSAndroid Build Coastguard Worker         {
875*ec779b8eSAndroid Build Coastguard Worker             sp<AReplyToken> replyID;
876*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->senderAwaitsResponse(&replyID));
877*ec779b8eSAndroid Build Coastguard Worker             AudioPlaybackRate rate /* sanitized */;
878*ec779b8eSAndroid Build Coastguard Worker             readFromAMessage(msg, &rate);
879*ec779b8eSAndroid Build Coastguard Worker             status_t err = OK;
880*ec779b8eSAndroid Build Coastguard Worker             if (mRenderer != NULL) {
881*ec779b8eSAndroid Build Coastguard Worker                 // AudioSink allows only 1.f and 0.f for offload and direct modes.
882*ec779b8eSAndroid Build Coastguard Worker                 // For other speeds, restart audio to fallback to supported paths
883*ec779b8eSAndroid Build Coastguard Worker                 bool audioDirectOutput = (mAudioSink->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0;
884*ec779b8eSAndroid Build Coastguard Worker                 if ((mOffloadAudio || audioDirectOutput) &&
885*ec779b8eSAndroid Build Coastguard Worker                         ((rate.mSpeed != 0.f && rate.mSpeed != 1.f) || rate.mPitch != 1.f)) {
886*ec779b8eSAndroid Build Coastguard Worker 
887*ec779b8eSAndroid Build Coastguard Worker                     int64_t currentPositionUs;
888*ec779b8eSAndroid Build Coastguard Worker                     if (getCurrentPosition(&currentPositionUs) != OK) {
889*ec779b8eSAndroid Build Coastguard Worker                         currentPositionUs = mPreviousSeekTimeUs;
890*ec779b8eSAndroid Build Coastguard Worker                     }
891*ec779b8eSAndroid Build Coastguard Worker 
892*ec779b8eSAndroid Build Coastguard Worker                     // Set mPlaybackSettings so that the new audio decoder can
893*ec779b8eSAndroid Build Coastguard Worker                     // be created correctly.
894*ec779b8eSAndroid Build Coastguard Worker                     mPlaybackSettings = rate;
895*ec779b8eSAndroid Build Coastguard Worker                     if (!mPaused) {
896*ec779b8eSAndroid Build Coastguard Worker                         mRenderer->pause();
897*ec779b8eSAndroid Build Coastguard Worker                     }
898*ec779b8eSAndroid Build Coastguard Worker                     restartAudio(
899*ec779b8eSAndroid Build Coastguard Worker                             currentPositionUs, true /* forceNonOffload */,
900*ec779b8eSAndroid Build Coastguard Worker                             true /* needsToCreateAudioDecoder */);
901*ec779b8eSAndroid Build Coastguard Worker                     if (!mPaused) {
902*ec779b8eSAndroid Build Coastguard Worker                         mRenderer->resume();
903*ec779b8eSAndroid Build Coastguard Worker                     }
904*ec779b8eSAndroid Build Coastguard Worker                 }
905*ec779b8eSAndroid Build Coastguard Worker 
906*ec779b8eSAndroid Build Coastguard Worker                 err = mRenderer->setPlaybackSettings(rate);
907*ec779b8eSAndroid Build Coastguard Worker             }
908*ec779b8eSAndroid Build Coastguard Worker             if (err == OK) {
909*ec779b8eSAndroid Build Coastguard Worker                 if (rate.mSpeed == 0.f) {
910*ec779b8eSAndroid Build Coastguard Worker                     onPause();
911*ec779b8eSAndroid Build Coastguard Worker                     mPausedByClient = true;
912*ec779b8eSAndroid Build Coastguard Worker                     // save all other settings (using non-paused speed)
913*ec779b8eSAndroid Build Coastguard Worker                     // so we can restore them on start
914*ec779b8eSAndroid Build Coastguard Worker                     AudioPlaybackRate newRate = rate;
915*ec779b8eSAndroid Build Coastguard Worker                     newRate.mSpeed = mPlaybackSettings.mSpeed;
916*ec779b8eSAndroid Build Coastguard Worker                     mPlaybackSettings = newRate;
917*ec779b8eSAndroid Build Coastguard Worker                 } else { /* rate.mSpeed != 0.f */
918*ec779b8eSAndroid Build Coastguard Worker                     mPlaybackSettings = rate;
919*ec779b8eSAndroid Build Coastguard Worker                     if (mStarted) {
920*ec779b8eSAndroid Build Coastguard Worker                         // do not resume yet if the source is still buffering
921*ec779b8eSAndroid Build Coastguard Worker                         if (!mPausedForBuffering) {
922*ec779b8eSAndroid Build Coastguard Worker                             onResume();
923*ec779b8eSAndroid Build Coastguard Worker                         }
924*ec779b8eSAndroid Build Coastguard Worker                     } else if (mPrepared) {
925*ec779b8eSAndroid Build Coastguard Worker                         onStart();
926*ec779b8eSAndroid Build Coastguard Worker                     }
927*ec779b8eSAndroid Build Coastguard Worker 
928*ec779b8eSAndroid Build Coastguard Worker                     mPausedByClient = false;
929*ec779b8eSAndroid Build Coastguard Worker                 }
930*ec779b8eSAndroid Build Coastguard Worker             }
931*ec779b8eSAndroid Build Coastguard Worker 
932*ec779b8eSAndroid Build Coastguard Worker             if (mVideoDecoder != NULL) {
933*ec779b8eSAndroid Build Coastguard Worker                 sp<AMessage> params = new AMessage();
934*ec779b8eSAndroid Build Coastguard Worker                 params->setFloat("playback-speed", mPlaybackSettings.mSpeed);
935*ec779b8eSAndroid Build Coastguard Worker                 mVideoDecoder->setParameters(params);
936*ec779b8eSAndroid Build Coastguard Worker             }
937*ec779b8eSAndroid Build Coastguard Worker 
938*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> response = new AMessage;
939*ec779b8eSAndroid Build Coastguard Worker             response->setInt32("err", err);
940*ec779b8eSAndroid Build Coastguard Worker             response->postReply(replyID);
941*ec779b8eSAndroid Build Coastguard Worker             break;
942*ec779b8eSAndroid Build Coastguard Worker         }
943*ec779b8eSAndroid Build Coastguard Worker 
944*ec779b8eSAndroid Build Coastguard Worker         case kWhatGetPlaybackSettings:
945*ec779b8eSAndroid Build Coastguard Worker         {
946*ec779b8eSAndroid Build Coastguard Worker             sp<AReplyToken> replyID;
947*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->senderAwaitsResponse(&replyID));
948*ec779b8eSAndroid Build Coastguard Worker             AudioPlaybackRate rate = mPlaybackSettings;
949*ec779b8eSAndroid Build Coastguard Worker             status_t err = OK;
950*ec779b8eSAndroid Build Coastguard Worker             if (mRenderer != NULL) {
951*ec779b8eSAndroid Build Coastguard Worker                 err = mRenderer->getPlaybackSettings(&rate);
952*ec779b8eSAndroid Build Coastguard Worker             }
953*ec779b8eSAndroid Build Coastguard Worker             if (err == OK) {
954*ec779b8eSAndroid Build Coastguard Worker                 // get playback settings used by renderer, as it may be
955*ec779b8eSAndroid Build Coastguard Worker                 // slightly off due to audiosink not taking small changes.
956*ec779b8eSAndroid Build Coastguard Worker                 mPlaybackSettings = rate;
957*ec779b8eSAndroid Build Coastguard Worker                 if (mPaused) {
958*ec779b8eSAndroid Build Coastguard Worker                     rate.mSpeed = 0.f;
959*ec779b8eSAndroid Build Coastguard Worker                 }
960*ec779b8eSAndroid Build Coastguard Worker             }
961*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> response = new AMessage;
962*ec779b8eSAndroid Build Coastguard Worker             if (err == OK) {
963*ec779b8eSAndroid Build Coastguard Worker                 writeToAMessage(response, rate);
964*ec779b8eSAndroid Build Coastguard Worker             }
965*ec779b8eSAndroid Build Coastguard Worker             response->setInt32("err", err);
966*ec779b8eSAndroid Build Coastguard Worker             response->postReply(replyID);
967*ec779b8eSAndroid Build Coastguard Worker             break;
968*ec779b8eSAndroid Build Coastguard Worker         }
969*ec779b8eSAndroid Build Coastguard Worker 
970*ec779b8eSAndroid Build Coastguard Worker         case kWhatConfigSync:
971*ec779b8eSAndroid Build Coastguard Worker         {
972*ec779b8eSAndroid Build Coastguard Worker             sp<AReplyToken> replyID;
973*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->senderAwaitsResponse(&replyID));
974*ec779b8eSAndroid Build Coastguard Worker 
975*ec779b8eSAndroid Build Coastguard Worker             ALOGV("kWhatConfigSync");
976*ec779b8eSAndroid Build Coastguard Worker             AVSyncSettings sync;
977*ec779b8eSAndroid Build Coastguard Worker             float videoFpsHint;
978*ec779b8eSAndroid Build Coastguard Worker             readFromAMessage(msg, &sync, &videoFpsHint);
979*ec779b8eSAndroid Build Coastguard Worker             status_t err = OK;
980*ec779b8eSAndroid Build Coastguard Worker             if (mRenderer != NULL) {
981*ec779b8eSAndroid Build Coastguard Worker                 err = mRenderer->setSyncSettings(sync, videoFpsHint);
982*ec779b8eSAndroid Build Coastguard Worker             }
983*ec779b8eSAndroid Build Coastguard Worker             if (err == OK) {
984*ec779b8eSAndroid Build Coastguard Worker                 mSyncSettings = sync;
985*ec779b8eSAndroid Build Coastguard Worker                 mVideoFpsHint = videoFpsHint;
986*ec779b8eSAndroid Build Coastguard Worker             }
987*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> response = new AMessage;
988*ec779b8eSAndroid Build Coastguard Worker             response->setInt32("err", err);
989*ec779b8eSAndroid Build Coastguard Worker             response->postReply(replyID);
990*ec779b8eSAndroid Build Coastguard Worker             break;
991*ec779b8eSAndroid Build Coastguard Worker         }
992*ec779b8eSAndroid Build Coastguard Worker 
993*ec779b8eSAndroid Build Coastguard Worker         case kWhatGetSyncSettings:
994*ec779b8eSAndroid Build Coastguard Worker         {
995*ec779b8eSAndroid Build Coastguard Worker             sp<AReplyToken> replyID;
996*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->senderAwaitsResponse(&replyID));
997*ec779b8eSAndroid Build Coastguard Worker             AVSyncSettings sync = mSyncSettings;
998*ec779b8eSAndroid Build Coastguard Worker             float videoFps = mVideoFpsHint;
999*ec779b8eSAndroid Build Coastguard Worker             status_t err = OK;
1000*ec779b8eSAndroid Build Coastguard Worker             if (mRenderer != NULL) {
1001*ec779b8eSAndroid Build Coastguard Worker                 err = mRenderer->getSyncSettings(&sync, &videoFps);
1002*ec779b8eSAndroid Build Coastguard Worker                 if (err == OK) {
1003*ec779b8eSAndroid Build Coastguard Worker                     mSyncSettings = sync;
1004*ec779b8eSAndroid Build Coastguard Worker                     mVideoFpsHint = videoFps;
1005*ec779b8eSAndroid Build Coastguard Worker                 }
1006*ec779b8eSAndroid Build Coastguard Worker             }
1007*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> response = new AMessage;
1008*ec779b8eSAndroid Build Coastguard Worker             if (err == OK) {
1009*ec779b8eSAndroid Build Coastguard Worker                 writeToAMessage(response, sync, videoFps);
1010*ec779b8eSAndroid Build Coastguard Worker             }
1011*ec779b8eSAndroid Build Coastguard Worker             response->setInt32("err", err);
1012*ec779b8eSAndroid Build Coastguard Worker             response->postReply(replyID);
1013*ec779b8eSAndroid Build Coastguard Worker             break;
1014*ec779b8eSAndroid Build Coastguard Worker         }
1015*ec779b8eSAndroid Build Coastguard Worker 
1016*ec779b8eSAndroid Build Coastguard Worker         case kWhatScanSources:
1017*ec779b8eSAndroid Build Coastguard Worker         {
1018*ec779b8eSAndroid Build Coastguard Worker             int32_t generation;
1019*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("generation", &generation));
1020*ec779b8eSAndroid Build Coastguard Worker             if (generation != mScanSourcesGeneration) {
1021*ec779b8eSAndroid Build Coastguard Worker                 // Drop obsolete msg.
1022*ec779b8eSAndroid Build Coastguard Worker                 break;
1023*ec779b8eSAndroid Build Coastguard Worker             }
1024*ec779b8eSAndroid Build Coastguard Worker 
1025*ec779b8eSAndroid Build Coastguard Worker             mScanSourcesPending = false;
1026*ec779b8eSAndroid Build Coastguard Worker 
1027*ec779b8eSAndroid Build Coastguard Worker             ALOGV("scanning sources haveAudio=%d, haveVideo=%d",
1028*ec779b8eSAndroid Build Coastguard Worker                  mAudioDecoder != NULL, mVideoDecoder != NULL);
1029*ec779b8eSAndroid Build Coastguard Worker 
1030*ec779b8eSAndroid Build Coastguard Worker             bool mHadAnySourcesBefore =
1031*ec779b8eSAndroid Build Coastguard Worker                 (mAudioDecoder != NULL) || (mVideoDecoder != NULL);
1032*ec779b8eSAndroid Build Coastguard Worker             bool rescan = false;
1033*ec779b8eSAndroid Build Coastguard Worker 
1034*ec779b8eSAndroid Build Coastguard Worker             // initialize video before audio because successful initialization of
1035*ec779b8eSAndroid Build Coastguard Worker             // video may change deep buffer mode of audio.
1036*ec779b8eSAndroid Build Coastguard Worker             if (mSurface != NULL) {
1037*ec779b8eSAndroid Build Coastguard Worker                 if (instantiateDecoder(false, &mVideoDecoder) == -EWOULDBLOCK) {
1038*ec779b8eSAndroid Build Coastguard Worker                     rescan = true;
1039*ec779b8eSAndroid Build Coastguard Worker                 }
1040*ec779b8eSAndroid Build Coastguard Worker             }
1041*ec779b8eSAndroid Build Coastguard Worker 
1042*ec779b8eSAndroid Build Coastguard Worker             // Don't try to re-open audio sink if there's an existing decoder.
1043*ec779b8eSAndroid Build Coastguard Worker             if (mAudioSink != NULL && mAudioDecoder == NULL) {
1044*ec779b8eSAndroid Build Coastguard Worker                 if (instantiateDecoder(true, &mAudioDecoder) == -EWOULDBLOCK) {
1045*ec779b8eSAndroid Build Coastguard Worker                     rescan = true;
1046*ec779b8eSAndroid Build Coastguard Worker                 }
1047*ec779b8eSAndroid Build Coastguard Worker             }
1048*ec779b8eSAndroid Build Coastguard Worker 
1049*ec779b8eSAndroid Build Coastguard Worker             if (!mHadAnySourcesBefore
1050*ec779b8eSAndroid Build Coastguard Worker                     && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
1051*ec779b8eSAndroid Build Coastguard Worker                 // This is the first time we've found anything playable.
1052*ec779b8eSAndroid Build Coastguard Worker 
1053*ec779b8eSAndroid Build Coastguard Worker                 if (mSourceFlags & Source::FLAG_DYNAMIC_DURATION) {
1054*ec779b8eSAndroid Build Coastguard Worker                     schedulePollDuration();
1055*ec779b8eSAndroid Build Coastguard Worker                 }
1056*ec779b8eSAndroid Build Coastguard Worker             }
1057*ec779b8eSAndroid Build Coastguard Worker 
1058*ec779b8eSAndroid Build Coastguard Worker             status_t err;
1059*ec779b8eSAndroid Build Coastguard Worker             if ((err = mSource->feedMoreTSData()) != OK) {
1060*ec779b8eSAndroid Build Coastguard Worker                 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
1061*ec779b8eSAndroid Build Coastguard Worker                     // We're not currently decoding anything (no audio or
1062*ec779b8eSAndroid Build Coastguard Worker                     // video tracks found) and we just ran out of input data.
1063*ec779b8eSAndroid Build Coastguard Worker 
1064*ec779b8eSAndroid Build Coastguard Worker                     if (err == ERROR_END_OF_STREAM) {
1065*ec779b8eSAndroid Build Coastguard Worker                         notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
1066*ec779b8eSAndroid Build Coastguard Worker                     } else {
1067*ec779b8eSAndroid Build Coastguard Worker                         notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1068*ec779b8eSAndroid Build Coastguard Worker                     }
1069*ec779b8eSAndroid Build Coastguard Worker                 }
1070*ec779b8eSAndroid Build Coastguard Worker                 break;
1071*ec779b8eSAndroid Build Coastguard Worker             }
1072*ec779b8eSAndroid Build Coastguard Worker 
1073*ec779b8eSAndroid Build Coastguard Worker             if (rescan) {
1074*ec779b8eSAndroid Build Coastguard Worker                 msg->post(100000LL);
1075*ec779b8eSAndroid Build Coastguard Worker                 mScanSourcesPending = true;
1076*ec779b8eSAndroid Build Coastguard Worker             }
1077*ec779b8eSAndroid Build Coastguard Worker             break;
1078*ec779b8eSAndroid Build Coastguard Worker         }
1079*ec779b8eSAndroid Build Coastguard Worker 
1080*ec779b8eSAndroid Build Coastguard Worker         case kWhatVideoNotify:
1081*ec779b8eSAndroid Build Coastguard Worker         case kWhatAudioNotify:
1082*ec779b8eSAndroid Build Coastguard Worker         {
1083*ec779b8eSAndroid Build Coastguard Worker             bool audio = msg->what() == kWhatAudioNotify;
1084*ec779b8eSAndroid Build Coastguard Worker 
1085*ec779b8eSAndroid Build Coastguard Worker             int32_t currentDecoderGeneration =
1086*ec779b8eSAndroid Build Coastguard Worker                 (audio? mAudioDecoderGeneration : mVideoDecoderGeneration);
1087*ec779b8eSAndroid Build Coastguard Worker             int32_t requesterGeneration = currentDecoderGeneration - 1;
1088*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("generation", &requesterGeneration));
1089*ec779b8eSAndroid Build Coastguard Worker 
1090*ec779b8eSAndroid Build Coastguard Worker             if (requesterGeneration != currentDecoderGeneration) {
1091*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("got message from old %s decoder, generation(%d:%d)",
1092*ec779b8eSAndroid Build Coastguard Worker                         audio ? "audio" : "video", requesterGeneration,
1093*ec779b8eSAndroid Build Coastguard Worker                         currentDecoderGeneration);
1094*ec779b8eSAndroid Build Coastguard Worker                 sp<AMessage> reply;
1095*ec779b8eSAndroid Build Coastguard Worker                 if (!(msg->findMessage("reply", &reply))) {
1096*ec779b8eSAndroid Build Coastguard Worker                     return;
1097*ec779b8eSAndroid Build Coastguard Worker                 }
1098*ec779b8eSAndroid Build Coastguard Worker 
1099*ec779b8eSAndroid Build Coastguard Worker                 reply->setInt32("err", INFO_DISCONTINUITY);
1100*ec779b8eSAndroid Build Coastguard Worker                 reply->post();
1101*ec779b8eSAndroid Build Coastguard Worker                 return;
1102*ec779b8eSAndroid Build Coastguard Worker             }
1103*ec779b8eSAndroid Build Coastguard Worker 
1104*ec779b8eSAndroid Build Coastguard Worker             int32_t what;
1105*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("what", &what));
1106*ec779b8eSAndroid Build Coastguard Worker 
1107*ec779b8eSAndroid Build Coastguard Worker             if (what == DecoderBase::kWhatInputDiscontinuity) {
1108*ec779b8eSAndroid Build Coastguard Worker                 int32_t formatChange;
1109*ec779b8eSAndroid Build Coastguard Worker                 CHECK(msg->findInt32("formatChange", &formatChange));
1110*ec779b8eSAndroid Build Coastguard Worker 
1111*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("%s discontinuity: formatChange %d",
1112*ec779b8eSAndroid Build Coastguard Worker                         audio ? "audio" : "video", formatChange);
1113*ec779b8eSAndroid Build Coastguard Worker 
1114*ec779b8eSAndroid Build Coastguard Worker                 if (formatChange) {
1115*ec779b8eSAndroid Build Coastguard Worker                     mDeferredActions.push_back(
1116*ec779b8eSAndroid Build Coastguard Worker                             new FlushDecoderAction(
1117*ec779b8eSAndroid Build Coastguard Worker                                 audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE,
1118*ec779b8eSAndroid Build Coastguard Worker                                 audio ? FLUSH_CMD_NONE : FLUSH_CMD_SHUTDOWN));
1119*ec779b8eSAndroid Build Coastguard Worker                 }
1120*ec779b8eSAndroid Build Coastguard Worker 
1121*ec779b8eSAndroid Build Coastguard Worker                 mDeferredActions.push_back(
1122*ec779b8eSAndroid Build Coastguard Worker                         new SimpleAction(
1123*ec779b8eSAndroid Build Coastguard Worker                                 &NuPlayer::performScanSources));
1124*ec779b8eSAndroid Build Coastguard Worker 
1125*ec779b8eSAndroid Build Coastguard Worker                 processDeferredActions();
1126*ec779b8eSAndroid Build Coastguard Worker             } else if (what == DecoderBase::kWhatEOS) {
1127*ec779b8eSAndroid Build Coastguard Worker                 int32_t err;
1128*ec779b8eSAndroid Build Coastguard Worker                 CHECK(msg->findInt32("err", &err));
1129*ec779b8eSAndroid Build Coastguard Worker 
1130*ec779b8eSAndroid Build Coastguard Worker                 if (err == ERROR_END_OF_STREAM) {
1131*ec779b8eSAndroid Build Coastguard Worker                     ALOGV("got %s decoder EOS", audio ? "audio" : "video");
1132*ec779b8eSAndroid Build Coastguard Worker                 } else {
1133*ec779b8eSAndroid Build Coastguard Worker                     ALOGV("got %s decoder EOS w/ error %d",
1134*ec779b8eSAndroid Build Coastguard Worker                          audio ? "audio" : "video",
1135*ec779b8eSAndroid Build Coastguard Worker                          err);
1136*ec779b8eSAndroid Build Coastguard Worker                 }
1137*ec779b8eSAndroid Build Coastguard Worker 
1138*ec779b8eSAndroid Build Coastguard Worker                 mRenderer->queueEOS(audio, err);
1139*ec779b8eSAndroid Build Coastguard Worker             } else if (what == DecoderBase::kWhatFlushCompleted) {
1140*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("decoder %s flush completed", audio ? "audio" : "video");
1141*ec779b8eSAndroid Build Coastguard Worker 
1142*ec779b8eSAndroid Build Coastguard Worker                 handleFlushComplete(audio, true /* isDecoder */);
1143*ec779b8eSAndroid Build Coastguard Worker                 finishFlushIfPossible();
1144*ec779b8eSAndroid Build Coastguard Worker             } else if (what == DecoderBase::kWhatVideoSizeChanged) {
1145*ec779b8eSAndroid Build Coastguard Worker                 sp<AMessage> format;
1146*ec779b8eSAndroid Build Coastguard Worker                 CHECK(msg->findMessage("format", &format));
1147*ec779b8eSAndroid Build Coastguard Worker 
1148*ec779b8eSAndroid Build Coastguard Worker                 sp<AMessage> inputFormat =
1149*ec779b8eSAndroid Build Coastguard Worker                         mSource->getFormat(false /* audio */);
1150*ec779b8eSAndroid Build Coastguard Worker 
1151*ec779b8eSAndroid Build Coastguard Worker                 setVideoScalingMode(mVideoScalingMode);
1152*ec779b8eSAndroid Build Coastguard Worker                 updateVideoSize(inputFormat, format);
1153*ec779b8eSAndroid Build Coastguard Worker             } else if (what == DecoderBase::kWhatShutdownCompleted) {
1154*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("%s shutdown completed", audio ? "audio" : "video");
1155*ec779b8eSAndroid Build Coastguard Worker                 if (audio) {
1156*ec779b8eSAndroid Build Coastguard Worker                     Mutex::Autolock autoLock(mDecoderLock);
1157*ec779b8eSAndroid Build Coastguard Worker                     mAudioDecoder.clear();
1158*ec779b8eSAndroid Build Coastguard Worker                     mAudioDecoderError = false;
1159*ec779b8eSAndroid Build Coastguard Worker                     ++mAudioDecoderGeneration;
1160*ec779b8eSAndroid Build Coastguard Worker 
1161*ec779b8eSAndroid Build Coastguard Worker                     CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
1162*ec779b8eSAndroid Build Coastguard Worker                     mFlushingAudio = SHUT_DOWN;
1163*ec779b8eSAndroid Build Coastguard Worker                 } else {
1164*ec779b8eSAndroid Build Coastguard Worker                     Mutex::Autolock autoLock(mDecoderLock);
1165*ec779b8eSAndroid Build Coastguard Worker                     mVideoDecoder.clear();
1166*ec779b8eSAndroid Build Coastguard Worker                     mVideoDecoderError = false;
1167*ec779b8eSAndroid Build Coastguard Worker                     ++mVideoDecoderGeneration;
1168*ec779b8eSAndroid Build Coastguard Worker 
1169*ec779b8eSAndroid Build Coastguard Worker                     CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
1170*ec779b8eSAndroid Build Coastguard Worker                     mFlushingVideo = SHUT_DOWN;
1171*ec779b8eSAndroid Build Coastguard Worker                 }
1172*ec779b8eSAndroid Build Coastguard Worker 
1173*ec779b8eSAndroid Build Coastguard Worker                 finishFlushIfPossible();
1174*ec779b8eSAndroid Build Coastguard Worker             } else if (what == DecoderBase::kWhatResumeCompleted) {
1175*ec779b8eSAndroid Build Coastguard Worker                 finishResume();
1176*ec779b8eSAndroid Build Coastguard Worker             } else if (what == DecoderBase::kWhatError) {
1177*ec779b8eSAndroid Build Coastguard Worker                 status_t err;
1178*ec779b8eSAndroid Build Coastguard Worker                 if (!msg->findInt32("err", &err) || err == OK) {
1179*ec779b8eSAndroid Build Coastguard Worker                     err = UNKNOWN_ERROR;
1180*ec779b8eSAndroid Build Coastguard Worker                 }
1181*ec779b8eSAndroid Build Coastguard Worker 
1182*ec779b8eSAndroid Build Coastguard Worker                 // Decoder errors can be due to Source (e.g. from streaming),
1183*ec779b8eSAndroid Build Coastguard Worker                 // or from decoding corrupted bitstreams, or from other decoder
1184*ec779b8eSAndroid Build Coastguard Worker                 // MediaCodec operations (e.g. from an ongoing reset or seek).
1185*ec779b8eSAndroid Build Coastguard Worker                 // They may also be due to openAudioSink failure at
1186*ec779b8eSAndroid Build Coastguard Worker                 // decoder start or after a format change.
1187*ec779b8eSAndroid Build Coastguard Worker                 //
1188*ec779b8eSAndroid Build Coastguard Worker                 // We try to gracefully shut down the affected decoder if possible,
1189*ec779b8eSAndroid Build Coastguard Worker                 // rather than trying to force the shutdown with something
1190*ec779b8eSAndroid Build Coastguard Worker                 // similar to performReset(). This method can lead to a hang
1191*ec779b8eSAndroid Build Coastguard Worker                 // if MediaCodec functions block after an error, but they should
1192*ec779b8eSAndroid Build Coastguard Worker                 // typically return INVALID_OPERATION instead of blocking.
1193*ec779b8eSAndroid Build Coastguard Worker 
1194*ec779b8eSAndroid Build Coastguard Worker                 FlushStatus *flushing = audio ? &mFlushingAudio : &mFlushingVideo;
1195*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("received error(%#x) from %s decoder, flushing(%d), now shutting down",
1196*ec779b8eSAndroid Build Coastguard Worker                         err, audio ? "audio" : "video", *flushing);
1197*ec779b8eSAndroid Build Coastguard Worker 
1198*ec779b8eSAndroid Build Coastguard Worker                 switch (*flushing) {
1199*ec779b8eSAndroid Build Coastguard Worker                     case NONE:
1200*ec779b8eSAndroid Build Coastguard Worker                         mDeferredActions.push_back(
1201*ec779b8eSAndroid Build Coastguard Worker                                 new FlushDecoderAction(
1202*ec779b8eSAndroid Build Coastguard Worker                                     audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE,
1203*ec779b8eSAndroid Build Coastguard Worker                                     audio ? FLUSH_CMD_NONE : FLUSH_CMD_SHUTDOWN));
1204*ec779b8eSAndroid Build Coastguard Worker                         processDeferredActions();
1205*ec779b8eSAndroid Build Coastguard Worker                         break;
1206*ec779b8eSAndroid Build Coastguard Worker                     case FLUSHING_DECODER:
1207*ec779b8eSAndroid Build Coastguard Worker                         *flushing = FLUSHING_DECODER_SHUTDOWN; // initiate shutdown after flush.
1208*ec779b8eSAndroid Build Coastguard Worker                         break; // Wait for flush to complete.
1209*ec779b8eSAndroid Build Coastguard Worker                     case FLUSHING_DECODER_SHUTDOWN:
1210*ec779b8eSAndroid Build Coastguard Worker                         break; // Wait for flush to complete.
1211*ec779b8eSAndroid Build Coastguard Worker                     case SHUTTING_DOWN_DECODER:
1212*ec779b8eSAndroid Build Coastguard Worker                         break; // Wait for shutdown to complete.
1213*ec779b8eSAndroid Build Coastguard Worker                     case FLUSHED:
1214*ec779b8eSAndroid Build Coastguard Worker                         getDecoder(audio)->initiateShutdown(); // In the middle of a seek.
1215*ec779b8eSAndroid Build Coastguard Worker                         *flushing = SHUTTING_DOWN_DECODER;     // Shut down.
1216*ec779b8eSAndroid Build Coastguard Worker                         break;
1217*ec779b8eSAndroid Build Coastguard Worker                     case SHUT_DOWN:
1218*ec779b8eSAndroid Build Coastguard Worker                         finishFlushIfPossible();  // Should not occur.
1219*ec779b8eSAndroid Build Coastguard Worker                         break;                    // Finish anyways.
1220*ec779b8eSAndroid Build Coastguard Worker                 }
1221*ec779b8eSAndroid Build Coastguard Worker                 if (mSource != nullptr) {
1222*ec779b8eSAndroid Build Coastguard Worker                     if (audio) {
1223*ec779b8eSAndroid Build Coastguard Worker                         if (mVideoDecoderError || mSource->getFormat(false /* audio */) == NULL
1224*ec779b8eSAndroid Build Coastguard Worker                                 || mSurface == NULL || mVideoDecoder == NULL) {
1225*ec779b8eSAndroid Build Coastguard Worker                             // When both audio and video have error, or this stream has only audio
1226*ec779b8eSAndroid Build Coastguard Worker                             // which has error, notify client of error.
1227*ec779b8eSAndroid Build Coastguard Worker                             notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1228*ec779b8eSAndroid Build Coastguard Worker                         } else {
1229*ec779b8eSAndroid Build Coastguard Worker                             // Only audio track has error. Video track could be still good to play.
1230*ec779b8eSAndroid Build Coastguard Worker                             if (mVideoEOS) {
1231*ec779b8eSAndroid Build Coastguard Worker                                 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
1232*ec779b8eSAndroid Build Coastguard Worker                             } else {
1233*ec779b8eSAndroid Build Coastguard Worker                                 notifyListener(MEDIA_INFO, MEDIA_INFO_PLAY_AUDIO_ERROR, err);
1234*ec779b8eSAndroid Build Coastguard Worker                             }
1235*ec779b8eSAndroid Build Coastguard Worker                         }
1236*ec779b8eSAndroid Build Coastguard Worker                         mAudioDecoderError = true;
1237*ec779b8eSAndroid Build Coastguard Worker                     } else {
1238*ec779b8eSAndroid Build Coastguard Worker                         if (mAudioDecoderError || mSource->getFormat(true /* audio */) == NULL
1239*ec779b8eSAndroid Build Coastguard Worker                                 || mAudioSink == NULL || mAudioDecoder == NULL) {
1240*ec779b8eSAndroid Build Coastguard Worker                             // When both audio and video have error, or this stream has only video
1241*ec779b8eSAndroid Build Coastguard Worker                             // which has error, notify client of error.
1242*ec779b8eSAndroid Build Coastguard Worker                             notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1243*ec779b8eSAndroid Build Coastguard Worker                         } else {
1244*ec779b8eSAndroid Build Coastguard Worker                             // Only video track has error. Audio track could be still good to play.
1245*ec779b8eSAndroid Build Coastguard Worker                             if (mAudioEOS) {
1246*ec779b8eSAndroid Build Coastguard Worker                                 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
1247*ec779b8eSAndroid Build Coastguard Worker                             } else {
1248*ec779b8eSAndroid Build Coastguard Worker                                 notifyListener(MEDIA_INFO, MEDIA_INFO_PLAY_VIDEO_ERROR, err);
1249*ec779b8eSAndroid Build Coastguard Worker                             }
1250*ec779b8eSAndroid Build Coastguard Worker                         }
1251*ec779b8eSAndroid Build Coastguard Worker                         mVideoDecoderError = true;
1252*ec779b8eSAndroid Build Coastguard Worker                     }
1253*ec779b8eSAndroid Build Coastguard Worker                 }
1254*ec779b8eSAndroid Build Coastguard Worker             } else {
1255*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("Unhandled decoder notification %d '%c%c%c%c'.",
1256*ec779b8eSAndroid Build Coastguard Worker                       what,
1257*ec779b8eSAndroid Build Coastguard Worker                       what >> 24,
1258*ec779b8eSAndroid Build Coastguard Worker                       (what >> 16) & 0xff,
1259*ec779b8eSAndroid Build Coastguard Worker                       (what >> 8) & 0xff,
1260*ec779b8eSAndroid Build Coastguard Worker                       what & 0xff);
1261*ec779b8eSAndroid Build Coastguard Worker             }
1262*ec779b8eSAndroid Build Coastguard Worker 
1263*ec779b8eSAndroid Build Coastguard Worker             break;
1264*ec779b8eSAndroid Build Coastguard Worker         }
1265*ec779b8eSAndroid Build Coastguard Worker 
1266*ec779b8eSAndroid Build Coastguard Worker         case kWhatRendererNotify:
1267*ec779b8eSAndroid Build Coastguard Worker         {
1268*ec779b8eSAndroid Build Coastguard Worker             int32_t requesterGeneration = mRendererGeneration - 1;
1269*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("generation", &requesterGeneration));
1270*ec779b8eSAndroid Build Coastguard Worker             if (requesterGeneration != mRendererGeneration) {
1271*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("got message from old renderer, generation(%d:%d)",
1272*ec779b8eSAndroid Build Coastguard Worker                         requesterGeneration, mRendererGeneration);
1273*ec779b8eSAndroid Build Coastguard Worker                 return;
1274*ec779b8eSAndroid Build Coastguard Worker             }
1275*ec779b8eSAndroid Build Coastguard Worker 
1276*ec779b8eSAndroid Build Coastguard Worker             int32_t what;
1277*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("what", &what));
1278*ec779b8eSAndroid Build Coastguard Worker 
1279*ec779b8eSAndroid Build Coastguard Worker             if (what == Renderer::kWhatEOS) {
1280*ec779b8eSAndroid Build Coastguard Worker                 int32_t audio;
1281*ec779b8eSAndroid Build Coastguard Worker                 CHECK(msg->findInt32("audio", &audio));
1282*ec779b8eSAndroid Build Coastguard Worker 
1283*ec779b8eSAndroid Build Coastguard Worker                 int32_t finalResult;
1284*ec779b8eSAndroid Build Coastguard Worker                 CHECK(msg->findInt32("finalResult", &finalResult));
1285*ec779b8eSAndroid Build Coastguard Worker 
1286*ec779b8eSAndroid Build Coastguard Worker                 if (audio) {
1287*ec779b8eSAndroid Build Coastguard Worker                     mAudioEOS = true;
1288*ec779b8eSAndroid Build Coastguard Worker                 } else {
1289*ec779b8eSAndroid Build Coastguard Worker                     mVideoEOS = true;
1290*ec779b8eSAndroid Build Coastguard Worker                 }
1291*ec779b8eSAndroid Build Coastguard Worker 
1292*ec779b8eSAndroid Build Coastguard Worker                 if (finalResult == ERROR_END_OF_STREAM) {
1293*ec779b8eSAndroid Build Coastguard Worker                     ALOGV("reached %s EOS", audio ? "audio" : "video");
1294*ec779b8eSAndroid Build Coastguard Worker                 } else {
1295*ec779b8eSAndroid Build Coastguard Worker                     ALOGE("%s track encountered an error (%d)",
1296*ec779b8eSAndroid Build Coastguard Worker                          audio ? "audio" : "video", finalResult);
1297*ec779b8eSAndroid Build Coastguard Worker 
1298*ec779b8eSAndroid Build Coastguard Worker                     notifyListener(
1299*ec779b8eSAndroid Build Coastguard Worker                             MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult);
1300*ec779b8eSAndroid Build Coastguard Worker                 }
1301*ec779b8eSAndroid Build Coastguard Worker 
1302*ec779b8eSAndroid Build Coastguard Worker                 if ((mAudioEOS || mAudioDecoder == NULL)
1303*ec779b8eSAndroid Build Coastguard Worker                         && (mVideoEOS || mVideoDecoder == NULL)) {
1304*ec779b8eSAndroid Build Coastguard Worker                     notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
1305*ec779b8eSAndroid Build Coastguard Worker                 }
1306*ec779b8eSAndroid Build Coastguard Worker             } else if (what == Renderer::kWhatFlushComplete) {
1307*ec779b8eSAndroid Build Coastguard Worker                 int32_t audio;
1308*ec779b8eSAndroid Build Coastguard Worker                 CHECK(msg->findInt32("audio", &audio));
1309*ec779b8eSAndroid Build Coastguard Worker 
1310*ec779b8eSAndroid Build Coastguard Worker                 if (audio) {
1311*ec779b8eSAndroid Build Coastguard Worker                     mAudioEOS = false;
1312*ec779b8eSAndroid Build Coastguard Worker                 } else {
1313*ec779b8eSAndroid Build Coastguard Worker                     mVideoEOS = false;
1314*ec779b8eSAndroid Build Coastguard Worker                 }
1315*ec779b8eSAndroid Build Coastguard Worker 
1316*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
1317*ec779b8eSAndroid Build Coastguard Worker                 if (audio && (mFlushingAudio == NONE || mFlushingAudio == FLUSHED
1318*ec779b8eSAndroid Build Coastguard Worker                         || mFlushingAudio == SHUT_DOWN)) {
1319*ec779b8eSAndroid Build Coastguard Worker                     // Flush has been handled by tear down.
1320*ec779b8eSAndroid Build Coastguard Worker                     break;
1321*ec779b8eSAndroid Build Coastguard Worker                 }
1322*ec779b8eSAndroid Build Coastguard Worker                 handleFlushComplete(audio, false /* isDecoder */);
1323*ec779b8eSAndroid Build Coastguard Worker                 finishFlushIfPossible();
1324*ec779b8eSAndroid Build Coastguard Worker             } else if (what == Renderer::kWhatVideoRenderingStart) {
1325*ec779b8eSAndroid Build Coastguard Worker                 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
1326*ec779b8eSAndroid Build Coastguard Worker             } else if (what == Renderer::kWhatMediaRenderingStart) {
1327*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("media rendering started");
1328*ec779b8eSAndroid Build Coastguard Worker                 notifyListener(MEDIA_STARTED, 0, 0);
1329*ec779b8eSAndroid Build Coastguard Worker             } else if (what == Renderer::kWhatAudioTearDown) {
1330*ec779b8eSAndroid Build Coastguard Worker                 int32_t reason;
1331*ec779b8eSAndroid Build Coastguard Worker                 CHECK(msg->findInt32("reason", &reason));
1332*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("Tear down audio with reason %d.", reason);
1333*ec779b8eSAndroid Build Coastguard Worker                 if (reason == Renderer::kDueToTimeout && !(mPaused && mOffloadAudio)) {
1334*ec779b8eSAndroid Build Coastguard Worker                     // TimeoutWhenPaused is only for offload mode.
1335*ec779b8eSAndroid Build Coastguard Worker                     ALOGW("Received a stale message for teardown, mPaused(%d), mOffloadAudio(%d)",
1336*ec779b8eSAndroid Build Coastguard Worker                           mPaused, mOffloadAudio);
1337*ec779b8eSAndroid Build Coastguard Worker                     break;
1338*ec779b8eSAndroid Build Coastguard Worker                 }
1339*ec779b8eSAndroid Build Coastguard Worker                 int64_t positionUs;
1340*ec779b8eSAndroid Build Coastguard Worker                 if (!msg->findInt64("positionUs", &positionUs)) {
1341*ec779b8eSAndroid Build Coastguard Worker                     positionUs = mPreviousSeekTimeUs;
1342*ec779b8eSAndroid Build Coastguard Worker                 }
1343*ec779b8eSAndroid Build Coastguard Worker 
1344*ec779b8eSAndroid Build Coastguard Worker                 restartAudio(
1345*ec779b8eSAndroid Build Coastguard Worker                         positionUs, reason == Renderer::kForceNonOffload /* forceNonOffload */,
1346*ec779b8eSAndroid Build Coastguard Worker                         reason != Renderer::kDueToTimeout /* needsToCreateAudioDecoder */);
1347*ec779b8eSAndroid Build Coastguard Worker             }
1348*ec779b8eSAndroid Build Coastguard Worker             break;
1349*ec779b8eSAndroid Build Coastguard Worker         }
1350*ec779b8eSAndroid Build Coastguard Worker 
1351*ec779b8eSAndroid Build Coastguard Worker         case kWhatMoreDataQueued:
1352*ec779b8eSAndroid Build Coastguard Worker         {
1353*ec779b8eSAndroid Build Coastguard Worker             break;
1354*ec779b8eSAndroid Build Coastguard Worker         }
1355*ec779b8eSAndroid Build Coastguard Worker 
1356*ec779b8eSAndroid Build Coastguard Worker         case kWhatReset:
1357*ec779b8eSAndroid Build Coastguard Worker         {
1358*ec779b8eSAndroid Build Coastguard Worker             ALOGV("kWhatReset");
1359*ec779b8eSAndroid Build Coastguard Worker 
1360*ec779b8eSAndroid Build Coastguard Worker             mResetting = true;
1361*ec779b8eSAndroid Build Coastguard Worker             updatePlaybackTimer(true /* stopping */, "kWhatReset");
1362*ec779b8eSAndroid Build Coastguard Worker             updateRebufferingTimer(true /* stopping */, true /* exiting */);
1363*ec779b8eSAndroid Build Coastguard Worker 
1364*ec779b8eSAndroid Build Coastguard Worker             mDeferredActions.push_back(
1365*ec779b8eSAndroid Build Coastguard Worker                     new FlushDecoderAction(
1366*ec779b8eSAndroid Build Coastguard Worker                         FLUSH_CMD_SHUTDOWN /* audio */,
1367*ec779b8eSAndroid Build Coastguard Worker                         FLUSH_CMD_SHUTDOWN /* video */));
1368*ec779b8eSAndroid Build Coastguard Worker 
1369*ec779b8eSAndroid Build Coastguard Worker             mDeferredActions.push_back(
1370*ec779b8eSAndroid Build Coastguard Worker                     new SimpleAction(&NuPlayer::performReset));
1371*ec779b8eSAndroid Build Coastguard Worker 
1372*ec779b8eSAndroid Build Coastguard Worker             processDeferredActions();
1373*ec779b8eSAndroid Build Coastguard Worker             break;
1374*ec779b8eSAndroid Build Coastguard Worker         }
1375*ec779b8eSAndroid Build Coastguard Worker 
1376*ec779b8eSAndroid Build Coastguard Worker         case kWhatNotifyTime:
1377*ec779b8eSAndroid Build Coastguard Worker         {
1378*ec779b8eSAndroid Build Coastguard Worker             ALOGV("kWhatNotifyTime");
1379*ec779b8eSAndroid Build Coastguard Worker             int64_t timerUs;
1380*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt64("timerUs", &timerUs));
1381*ec779b8eSAndroid Build Coastguard Worker 
1382*ec779b8eSAndroid Build Coastguard Worker             notifyListener(MEDIA_NOTIFY_TIME, timerUs, 0);
1383*ec779b8eSAndroid Build Coastguard Worker             break;
1384*ec779b8eSAndroid Build Coastguard Worker         }
1385*ec779b8eSAndroid Build Coastguard Worker 
1386*ec779b8eSAndroid Build Coastguard Worker         case kWhatSeek:
1387*ec779b8eSAndroid Build Coastguard Worker         {
1388*ec779b8eSAndroid Build Coastguard Worker             int64_t seekTimeUs;
1389*ec779b8eSAndroid Build Coastguard Worker             int32_t mode;
1390*ec779b8eSAndroid Build Coastguard Worker             int32_t needNotify;
1391*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
1392*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("mode", &mode));
1393*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("needNotify", &needNotify));
1394*ec779b8eSAndroid Build Coastguard Worker 
1395*ec779b8eSAndroid Build Coastguard Worker             ALOGV("kWhatSeek seekTimeUs=%lld us, mode=%d, needNotify=%d",
1396*ec779b8eSAndroid Build Coastguard Worker                     (long long)seekTimeUs, mode, needNotify);
1397*ec779b8eSAndroid Build Coastguard Worker 
1398*ec779b8eSAndroid Build Coastguard Worker             if (!mStarted) {
1399*ec779b8eSAndroid Build Coastguard Worker                 // Seek before the player is started. In order to preview video,
1400*ec779b8eSAndroid Build Coastguard Worker                 // need to start the player and pause it. This branch is called
1401*ec779b8eSAndroid Build Coastguard Worker                 // only once if needed. After the player is started, any seek
1402*ec779b8eSAndroid Build Coastguard Worker                 // operation will go through normal path.
1403*ec779b8eSAndroid Build Coastguard Worker                 // Audio-only cases are handled separately.
1404*ec779b8eSAndroid Build Coastguard Worker                 onStart(seekTimeUs, (MediaPlayerSeekMode)mode);
1405*ec779b8eSAndroid Build Coastguard Worker                 if (mStarted) {
1406*ec779b8eSAndroid Build Coastguard Worker                     onPause();
1407*ec779b8eSAndroid Build Coastguard Worker                     mPausedByClient = true;
1408*ec779b8eSAndroid Build Coastguard Worker                 }
1409*ec779b8eSAndroid Build Coastguard Worker                 if (needNotify) {
1410*ec779b8eSAndroid Build Coastguard Worker                     notifyDriverSeekComplete();
1411*ec779b8eSAndroid Build Coastguard Worker                 }
1412*ec779b8eSAndroid Build Coastguard Worker                 break;
1413*ec779b8eSAndroid Build Coastguard Worker             }
1414*ec779b8eSAndroid Build Coastguard Worker 
1415*ec779b8eSAndroid Build Coastguard Worker             mDeferredActions.push_back(
1416*ec779b8eSAndroid Build Coastguard Worker                     new FlushDecoderAction(FLUSH_CMD_FLUSH /* audio */,
1417*ec779b8eSAndroid Build Coastguard Worker                                            FLUSH_CMD_FLUSH /* video */));
1418*ec779b8eSAndroid Build Coastguard Worker 
1419*ec779b8eSAndroid Build Coastguard Worker             mDeferredActions.push_back(
1420*ec779b8eSAndroid Build Coastguard Worker                     new SeekAction(seekTimeUs, (MediaPlayerSeekMode)mode));
1421*ec779b8eSAndroid Build Coastguard Worker 
1422*ec779b8eSAndroid Build Coastguard Worker             // After a flush without shutdown, decoder is paused.
1423*ec779b8eSAndroid Build Coastguard Worker             // Don't resume it until source seek is done, otherwise it could
1424*ec779b8eSAndroid Build Coastguard Worker             // start pulling stale data too soon.
1425*ec779b8eSAndroid Build Coastguard Worker             mDeferredActions.push_back(
1426*ec779b8eSAndroid Build Coastguard Worker                     new ResumeDecoderAction(needNotify));
1427*ec779b8eSAndroid Build Coastguard Worker 
1428*ec779b8eSAndroid Build Coastguard Worker             processDeferredActions();
1429*ec779b8eSAndroid Build Coastguard Worker             break;
1430*ec779b8eSAndroid Build Coastguard Worker         }
1431*ec779b8eSAndroid Build Coastguard Worker 
1432*ec779b8eSAndroid Build Coastguard Worker         case kWhatPause:
1433*ec779b8eSAndroid Build Coastguard Worker         {
1434*ec779b8eSAndroid Build Coastguard Worker             onPause();
1435*ec779b8eSAndroid Build Coastguard Worker             mPausedByClient = true;
1436*ec779b8eSAndroid Build Coastguard Worker             break;
1437*ec779b8eSAndroid Build Coastguard Worker         }
1438*ec779b8eSAndroid Build Coastguard Worker 
1439*ec779b8eSAndroid Build Coastguard Worker         case kWhatSourceNotify:
1440*ec779b8eSAndroid Build Coastguard Worker         {
1441*ec779b8eSAndroid Build Coastguard Worker             onSourceNotify(msg);
1442*ec779b8eSAndroid Build Coastguard Worker             break;
1443*ec779b8eSAndroid Build Coastguard Worker         }
1444*ec779b8eSAndroid Build Coastguard Worker 
1445*ec779b8eSAndroid Build Coastguard Worker         case kWhatClosedCaptionNotify:
1446*ec779b8eSAndroid Build Coastguard Worker         {
1447*ec779b8eSAndroid Build Coastguard Worker             onClosedCaptionNotify(msg);
1448*ec779b8eSAndroid Build Coastguard Worker             break;
1449*ec779b8eSAndroid Build Coastguard Worker         }
1450*ec779b8eSAndroid Build Coastguard Worker 
1451*ec779b8eSAndroid Build Coastguard Worker         case kWhatPrepareDrm:
1452*ec779b8eSAndroid Build Coastguard Worker         {
1453*ec779b8eSAndroid Build Coastguard Worker             status_t status = onPrepareDrm(msg);
1454*ec779b8eSAndroid Build Coastguard Worker 
1455*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> response = new AMessage;
1456*ec779b8eSAndroid Build Coastguard Worker             response->setInt32("status", status);
1457*ec779b8eSAndroid Build Coastguard Worker             sp<AReplyToken> replyID;
1458*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->senderAwaitsResponse(&replyID));
1459*ec779b8eSAndroid Build Coastguard Worker             response->postReply(replyID);
1460*ec779b8eSAndroid Build Coastguard Worker             break;
1461*ec779b8eSAndroid Build Coastguard Worker         }
1462*ec779b8eSAndroid Build Coastguard Worker 
1463*ec779b8eSAndroid Build Coastguard Worker         case kWhatReleaseDrm:
1464*ec779b8eSAndroid Build Coastguard Worker         {
1465*ec779b8eSAndroid Build Coastguard Worker             status_t status = onReleaseDrm();
1466*ec779b8eSAndroid Build Coastguard Worker 
1467*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> response = new AMessage;
1468*ec779b8eSAndroid Build Coastguard Worker             response->setInt32("status", status);
1469*ec779b8eSAndroid Build Coastguard Worker             sp<AReplyToken> replyID;
1470*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->senderAwaitsResponse(&replyID));
1471*ec779b8eSAndroid Build Coastguard Worker             response->postReply(replyID);
1472*ec779b8eSAndroid Build Coastguard Worker             break;
1473*ec779b8eSAndroid Build Coastguard Worker         }
1474*ec779b8eSAndroid Build Coastguard Worker 
1475*ec779b8eSAndroid Build Coastguard Worker         case kWhatMediaClockNotify:
1476*ec779b8eSAndroid Build Coastguard Worker         {
1477*ec779b8eSAndroid Build Coastguard Worker             ALOGV("kWhatMediaClockNotify");
1478*ec779b8eSAndroid Build Coastguard Worker             int64_t anchorMediaUs, anchorRealUs;
1479*ec779b8eSAndroid Build Coastguard Worker             float playbackRate;
1480*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt64("anchor-media-us", &anchorMediaUs));
1481*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt64("anchor-real-us", &anchorRealUs));
1482*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findFloat("playback-rate", &playbackRate));
1483*ec779b8eSAndroid Build Coastguard Worker 
1484*ec779b8eSAndroid Build Coastguard Worker             Parcel in;
1485*ec779b8eSAndroid Build Coastguard Worker             in.writeInt64(anchorMediaUs);
1486*ec779b8eSAndroid Build Coastguard Worker             in.writeInt64(anchorRealUs);
1487*ec779b8eSAndroid Build Coastguard Worker             in.writeFloat(playbackRate);
1488*ec779b8eSAndroid Build Coastguard Worker 
1489*ec779b8eSAndroid Build Coastguard Worker             notifyListener(MEDIA_TIME_DISCONTINUITY, 0, 0, &in);
1490*ec779b8eSAndroid Build Coastguard Worker             break;
1491*ec779b8eSAndroid Build Coastguard Worker         }
1492*ec779b8eSAndroid Build Coastguard Worker 
1493*ec779b8eSAndroid Build Coastguard Worker         default:
1494*ec779b8eSAndroid Build Coastguard Worker             TRESPASS();
1495*ec779b8eSAndroid Build Coastguard Worker             break;
1496*ec779b8eSAndroid Build Coastguard Worker     }
1497*ec779b8eSAndroid Build Coastguard Worker }
1498*ec779b8eSAndroid Build Coastguard Worker 
onResume()1499*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::onResume() {
1500*ec779b8eSAndroid Build Coastguard Worker     if (!mPaused || mResetting) {
1501*ec779b8eSAndroid Build Coastguard Worker         ALOGD_IF(mResetting, "resetting, onResume discarded");
1502*ec779b8eSAndroid Build Coastguard Worker         return;
1503*ec779b8eSAndroid Build Coastguard Worker     }
1504*ec779b8eSAndroid Build Coastguard Worker     mPaused = false;
1505*ec779b8eSAndroid Build Coastguard Worker     if (mSource != NULL) {
1506*ec779b8eSAndroid Build Coastguard Worker         mSource->resume();
1507*ec779b8eSAndroid Build Coastguard Worker     } else {
1508*ec779b8eSAndroid Build Coastguard Worker         ALOGW("resume called when source is gone or not set");
1509*ec779b8eSAndroid Build Coastguard Worker     }
1510*ec779b8eSAndroid Build Coastguard Worker     // |mAudioDecoder| may have been released due to the pause timeout, so re-create it if
1511*ec779b8eSAndroid Build Coastguard Worker     // needed.
1512*ec779b8eSAndroid Build Coastguard Worker     if (audioDecoderStillNeeded() && mAudioDecoder == NULL) {
1513*ec779b8eSAndroid Build Coastguard Worker         instantiateDecoder(true /* audio */, &mAudioDecoder);
1514*ec779b8eSAndroid Build Coastguard Worker     }
1515*ec779b8eSAndroid Build Coastguard Worker     if (mRenderer != NULL) {
1516*ec779b8eSAndroid Build Coastguard Worker         mRenderer->resume();
1517*ec779b8eSAndroid Build Coastguard Worker     } else {
1518*ec779b8eSAndroid Build Coastguard Worker         ALOGW("resume called when renderer is gone or not set");
1519*ec779b8eSAndroid Build Coastguard Worker     }
1520*ec779b8eSAndroid Build Coastguard Worker 
1521*ec779b8eSAndroid Build Coastguard Worker     startPlaybackTimer("onresume");
1522*ec779b8eSAndroid Build Coastguard Worker }
1523*ec779b8eSAndroid Build Coastguard Worker 
onInstantiateSecureDecoders()1524*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::onInstantiateSecureDecoders() {
1525*ec779b8eSAndroid Build Coastguard Worker     status_t err;
1526*ec779b8eSAndroid Build Coastguard Worker     if (!(mSourceFlags & Source::FLAG_SECURE)) {
1527*ec779b8eSAndroid Build Coastguard Worker         return BAD_TYPE;
1528*ec779b8eSAndroid Build Coastguard Worker     }
1529*ec779b8eSAndroid Build Coastguard Worker 
1530*ec779b8eSAndroid Build Coastguard Worker     if (mRenderer != NULL) {
1531*ec779b8eSAndroid Build Coastguard Worker         ALOGE("renderer should not be set when instantiating secure decoders");
1532*ec779b8eSAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
1533*ec779b8eSAndroid Build Coastguard Worker     }
1534*ec779b8eSAndroid Build Coastguard Worker 
1535*ec779b8eSAndroid Build Coastguard Worker     // TRICKY: We rely on mRenderer being null, so that decoder does not start requesting
1536*ec779b8eSAndroid Build Coastguard Worker     // data on instantiation.
1537*ec779b8eSAndroid Build Coastguard Worker     if (mSurface != NULL) {
1538*ec779b8eSAndroid Build Coastguard Worker         err = instantiateDecoder(false, &mVideoDecoder);
1539*ec779b8eSAndroid Build Coastguard Worker         if (err != OK) {
1540*ec779b8eSAndroid Build Coastguard Worker             return err;
1541*ec779b8eSAndroid Build Coastguard Worker         }
1542*ec779b8eSAndroid Build Coastguard Worker     }
1543*ec779b8eSAndroid Build Coastguard Worker 
1544*ec779b8eSAndroid Build Coastguard Worker     if (mAudioSink != NULL) {
1545*ec779b8eSAndroid Build Coastguard Worker         err = instantiateDecoder(true, &mAudioDecoder);
1546*ec779b8eSAndroid Build Coastguard Worker         if (err != OK) {
1547*ec779b8eSAndroid Build Coastguard Worker             return err;
1548*ec779b8eSAndroid Build Coastguard Worker         }
1549*ec779b8eSAndroid Build Coastguard Worker     }
1550*ec779b8eSAndroid Build Coastguard Worker     return OK;
1551*ec779b8eSAndroid Build Coastguard Worker }
1552*ec779b8eSAndroid Build Coastguard Worker 
onStart(int64_t startPositionUs,MediaPlayerSeekMode mode)1553*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::onStart(int64_t startPositionUs, MediaPlayerSeekMode mode) {
1554*ec779b8eSAndroid Build Coastguard Worker     ALOGV("onStart: mCrypto: %p (%d)", mCrypto.get(),
1555*ec779b8eSAndroid Build Coastguard Worker             (mCrypto != NULL ? mCrypto->getStrongCount() : 0));
1556*ec779b8eSAndroid Build Coastguard Worker 
1557*ec779b8eSAndroid Build Coastguard Worker     if (!mSourceStarted) {
1558*ec779b8eSAndroid Build Coastguard Worker         mSourceStarted = true;
1559*ec779b8eSAndroid Build Coastguard Worker         mSource->start();
1560*ec779b8eSAndroid Build Coastguard Worker     }
1561*ec779b8eSAndroid Build Coastguard Worker     if (startPositionUs > 0) {
1562*ec779b8eSAndroid Build Coastguard Worker         performSeek(startPositionUs, mode);
1563*ec779b8eSAndroid Build Coastguard Worker         if (mSource->getFormat(false /* audio */) == NULL) {
1564*ec779b8eSAndroid Build Coastguard Worker             return;
1565*ec779b8eSAndroid Build Coastguard Worker         }
1566*ec779b8eSAndroid Build Coastguard Worker     }
1567*ec779b8eSAndroid Build Coastguard Worker 
1568*ec779b8eSAndroid Build Coastguard Worker     mOffloadAudio = false;
1569*ec779b8eSAndroid Build Coastguard Worker     mAudioEOS = false;
1570*ec779b8eSAndroid Build Coastguard Worker     mVideoEOS = false;
1571*ec779b8eSAndroid Build Coastguard Worker     mStarted = true;
1572*ec779b8eSAndroid Build Coastguard Worker     mPaused = false;
1573*ec779b8eSAndroid Build Coastguard Worker 
1574*ec779b8eSAndroid Build Coastguard Worker     uint32_t flags = 0;
1575*ec779b8eSAndroid Build Coastguard Worker 
1576*ec779b8eSAndroid Build Coastguard Worker     if (mSource->isRealTime()) {
1577*ec779b8eSAndroid Build Coastguard Worker         flags |= Renderer::FLAG_REAL_TIME;
1578*ec779b8eSAndroid Build Coastguard Worker     }
1579*ec779b8eSAndroid Build Coastguard Worker 
1580*ec779b8eSAndroid Build Coastguard Worker     bool hasAudio = (mSource->getFormat(true /* audio */) != NULL);
1581*ec779b8eSAndroid Build Coastguard Worker     bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
1582*ec779b8eSAndroid Build Coastguard Worker     if (!hasAudio && !hasVideo) {
1583*ec779b8eSAndroid Build Coastguard Worker         ALOGE("no metadata for either audio or video source");
1584*ec779b8eSAndroid Build Coastguard Worker         mSource->stop();
1585*ec779b8eSAndroid Build Coastguard Worker         mSourceStarted = false;
1586*ec779b8eSAndroid Build Coastguard Worker         notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_MALFORMED);
1587*ec779b8eSAndroid Build Coastguard Worker         return;
1588*ec779b8eSAndroid Build Coastguard Worker     }
1589*ec779b8eSAndroid Build Coastguard Worker     ALOGV_IF(!hasAudio, "no metadata for audio source");  // video only stream
1590*ec779b8eSAndroid Build Coastguard Worker 
1591*ec779b8eSAndroid Build Coastguard Worker     sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
1592*ec779b8eSAndroid Build Coastguard Worker 
1593*ec779b8eSAndroid Build Coastguard Worker     audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
1594*ec779b8eSAndroid Build Coastguard Worker     if (mAudioSink != NULL) {
1595*ec779b8eSAndroid Build Coastguard Worker         streamType = mAudioSink->getAudioStreamType();
1596*ec779b8eSAndroid Build Coastguard Worker     }
1597*ec779b8eSAndroid Build Coastguard Worker 
1598*ec779b8eSAndroid Build Coastguard Worker     mOffloadAudio =
1599*ec779b8eSAndroid Build Coastguard Worker         canOffloadStream(audioMeta, hasVideo, mSource->isStreaming(), streamType)
1600*ec779b8eSAndroid Build Coastguard Worker                 && (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f);
1601*ec779b8eSAndroid Build Coastguard Worker 
1602*ec779b8eSAndroid Build Coastguard Worker     // Modular DRM: Disabling audio offload if the source is protected
1603*ec779b8eSAndroid Build Coastguard Worker     if (mOffloadAudio && mIsDrmProtected) {
1604*ec779b8eSAndroid Build Coastguard Worker         mOffloadAudio = false;
1605*ec779b8eSAndroid Build Coastguard Worker         ALOGV("onStart: Disabling mOffloadAudio now that the source is protected.");
1606*ec779b8eSAndroid Build Coastguard Worker     }
1607*ec779b8eSAndroid Build Coastguard Worker 
1608*ec779b8eSAndroid Build Coastguard Worker     if (mOffloadAudio) {
1609*ec779b8eSAndroid Build Coastguard Worker         flags |= Renderer::FLAG_OFFLOAD_AUDIO;
1610*ec779b8eSAndroid Build Coastguard Worker     }
1611*ec779b8eSAndroid Build Coastguard Worker 
1612*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> notify = new AMessage(kWhatRendererNotify, this);
1613*ec779b8eSAndroid Build Coastguard Worker     ++mRendererGeneration;
1614*ec779b8eSAndroid Build Coastguard Worker     notify->setInt32("generation", mRendererGeneration);
1615*ec779b8eSAndroid Build Coastguard Worker     mRenderer = new Renderer(mAudioSink, mMediaClock, notify, flags);
1616*ec779b8eSAndroid Build Coastguard Worker     mRendererLooper = new ALooper;
1617*ec779b8eSAndroid Build Coastguard Worker     mRendererLooper->setName("NuPlayerRenderer");
1618*ec779b8eSAndroid Build Coastguard Worker     mRendererLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
1619*ec779b8eSAndroid Build Coastguard Worker     mRendererLooper->registerHandler(mRenderer);
1620*ec779b8eSAndroid Build Coastguard Worker 
1621*ec779b8eSAndroid Build Coastguard Worker     status_t err = mRenderer->setPlaybackSettings(mPlaybackSettings);
1622*ec779b8eSAndroid Build Coastguard Worker     if (err != OK) {
1623*ec779b8eSAndroid Build Coastguard Worker         mSource->stop();
1624*ec779b8eSAndroid Build Coastguard Worker         mSourceStarted = false;
1625*ec779b8eSAndroid Build Coastguard Worker         notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
1626*ec779b8eSAndroid Build Coastguard Worker         return;
1627*ec779b8eSAndroid Build Coastguard Worker     }
1628*ec779b8eSAndroid Build Coastguard Worker 
1629*ec779b8eSAndroid Build Coastguard Worker     float rate = getFrameRate();
1630*ec779b8eSAndroid Build Coastguard Worker     if (rate > 0) {
1631*ec779b8eSAndroid Build Coastguard Worker         mRenderer->setVideoFrameRate(rate);
1632*ec779b8eSAndroid Build Coastguard Worker     }
1633*ec779b8eSAndroid Build Coastguard Worker 
1634*ec779b8eSAndroid Build Coastguard Worker     if (mVideoDecoder != NULL) {
1635*ec779b8eSAndroid Build Coastguard Worker         mVideoDecoder->setRenderer(mRenderer);
1636*ec779b8eSAndroid Build Coastguard Worker     }
1637*ec779b8eSAndroid Build Coastguard Worker     if (mAudioDecoder != NULL) {
1638*ec779b8eSAndroid Build Coastguard Worker         mAudioDecoder->setRenderer(mRenderer);
1639*ec779b8eSAndroid Build Coastguard Worker     }
1640*ec779b8eSAndroid Build Coastguard Worker 
1641*ec779b8eSAndroid Build Coastguard Worker     startPlaybackTimer("onstart");
1642*ec779b8eSAndroid Build Coastguard Worker 
1643*ec779b8eSAndroid Build Coastguard Worker     postScanSources();
1644*ec779b8eSAndroid Build Coastguard Worker }
1645*ec779b8eSAndroid Build Coastguard Worker 
startPlaybackTimer(const char * where)1646*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::startPlaybackTimer(const char *where) {
1647*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mPlayingTimeLock);
1648*ec779b8eSAndroid Build Coastguard Worker     if (mLastStartedPlayingTimeNs == 0) {
1649*ec779b8eSAndroid Build Coastguard Worker         mLastStartedPlayingTimeNs = systemTime();
1650*ec779b8eSAndroid Build Coastguard Worker         ALOGV("startPlaybackTimer() time %20" PRId64 " (%s)",  mLastStartedPlayingTimeNs, where);
1651*ec779b8eSAndroid Build Coastguard Worker     }
1652*ec779b8eSAndroid Build Coastguard Worker }
1653*ec779b8eSAndroid Build Coastguard Worker 
updatePlaybackTimer(bool stopping,const char * where)1654*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::updatePlaybackTimer(bool stopping, const char *where) {
1655*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mPlayingTimeLock);
1656*ec779b8eSAndroid Build Coastguard Worker 
1657*ec779b8eSAndroid Build Coastguard Worker     ALOGV("updatePlaybackTimer(%s)  time %20" PRId64 " (%s)",
1658*ec779b8eSAndroid Build Coastguard Worker 	  stopping ? "stop" : "snap", mLastStartedPlayingTimeNs, where);
1659*ec779b8eSAndroid Build Coastguard Worker 
1660*ec779b8eSAndroid Build Coastguard Worker     if (mLastStartedPlayingTimeNs != 0) {
1661*ec779b8eSAndroid Build Coastguard Worker         sp<NuPlayerDriver> driver = mDriver.promote();
1662*ec779b8eSAndroid Build Coastguard Worker         int64_t now = systemTime();
1663*ec779b8eSAndroid Build Coastguard Worker         if (driver != NULL) {
1664*ec779b8eSAndroid Build Coastguard Worker             int64_t played = now - mLastStartedPlayingTimeNs;
1665*ec779b8eSAndroid Build Coastguard Worker             ALOGV("updatePlaybackTimer()  log  %20" PRId64 "", played);
1666*ec779b8eSAndroid Build Coastguard Worker 
1667*ec779b8eSAndroid Build Coastguard Worker             if (played > 0) {
1668*ec779b8eSAndroid Build Coastguard Worker                 driver->notifyMorePlayingTimeUs((played+500)/1000);
1669*ec779b8eSAndroid Build Coastguard Worker             }
1670*ec779b8eSAndroid Build Coastguard Worker         }
1671*ec779b8eSAndroid Build Coastguard Worker 	if (stopping) {
1672*ec779b8eSAndroid Build Coastguard Worker             mLastStartedPlayingTimeNs = 0;
1673*ec779b8eSAndroid Build Coastguard Worker 	} else {
1674*ec779b8eSAndroid Build Coastguard Worker             mLastStartedPlayingTimeNs = now;
1675*ec779b8eSAndroid Build Coastguard Worker 	}
1676*ec779b8eSAndroid Build Coastguard Worker     }
1677*ec779b8eSAndroid Build Coastguard Worker }
1678*ec779b8eSAndroid Build Coastguard Worker 
startRebufferingTimer()1679*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::startRebufferingTimer() {
1680*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mPlayingTimeLock);
1681*ec779b8eSAndroid Build Coastguard Worker     if (mLastStartedRebufferingTimeNs == 0) {
1682*ec779b8eSAndroid Build Coastguard Worker         mLastStartedRebufferingTimeNs = systemTime();
1683*ec779b8eSAndroid Build Coastguard Worker         ALOGV("startRebufferingTimer() time %20" PRId64 "",  mLastStartedRebufferingTimeNs);
1684*ec779b8eSAndroid Build Coastguard Worker     }
1685*ec779b8eSAndroid Build Coastguard Worker }
1686*ec779b8eSAndroid Build Coastguard Worker 
updateRebufferingTimer(bool stopping,bool exitingPlayback)1687*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::updateRebufferingTimer(bool stopping, bool exitingPlayback) {
1688*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mPlayingTimeLock);
1689*ec779b8eSAndroid Build Coastguard Worker 
1690*ec779b8eSAndroid Build Coastguard Worker     ALOGV("updateRebufferingTimer(%s)  time %20" PRId64 " (exiting %d)",
1691*ec779b8eSAndroid Build Coastguard Worker 	  stopping ? "stop" : "snap", mLastStartedRebufferingTimeNs, exitingPlayback);
1692*ec779b8eSAndroid Build Coastguard Worker 
1693*ec779b8eSAndroid Build Coastguard Worker     if (mLastStartedRebufferingTimeNs != 0) {
1694*ec779b8eSAndroid Build Coastguard Worker         sp<NuPlayerDriver> driver = mDriver.promote();
1695*ec779b8eSAndroid Build Coastguard Worker         int64_t now = systemTime();
1696*ec779b8eSAndroid Build Coastguard Worker         if (driver != NULL) {
1697*ec779b8eSAndroid Build Coastguard Worker             int64_t rebuffered = now - mLastStartedRebufferingTimeNs;
1698*ec779b8eSAndroid Build Coastguard Worker             ALOGV("updateRebufferingTimer()  log  %20" PRId64 "", rebuffered);
1699*ec779b8eSAndroid Build Coastguard Worker 
1700*ec779b8eSAndroid Build Coastguard Worker             if (rebuffered > 0) {
1701*ec779b8eSAndroid Build Coastguard Worker                 driver->notifyMoreRebufferingTimeUs((rebuffered+500)/1000);
1702*ec779b8eSAndroid Build Coastguard Worker                 if (exitingPlayback) {
1703*ec779b8eSAndroid Build Coastguard Worker                     driver->notifyRebufferingWhenExit(true);
1704*ec779b8eSAndroid Build Coastguard Worker                 }
1705*ec779b8eSAndroid Build Coastguard Worker             }
1706*ec779b8eSAndroid Build Coastguard Worker         }
1707*ec779b8eSAndroid Build Coastguard Worker 	if (stopping) {
1708*ec779b8eSAndroid Build Coastguard Worker             mLastStartedRebufferingTimeNs = 0;
1709*ec779b8eSAndroid Build Coastguard Worker 	} else {
1710*ec779b8eSAndroid Build Coastguard Worker             mLastStartedRebufferingTimeNs = now;
1711*ec779b8eSAndroid Build Coastguard Worker 	}
1712*ec779b8eSAndroid Build Coastguard Worker     }
1713*ec779b8eSAndroid Build Coastguard Worker }
1714*ec779b8eSAndroid Build Coastguard Worker 
updateInternalTimers()1715*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::updateInternalTimers() {
1716*ec779b8eSAndroid Build Coastguard Worker     // update values, but ticking clocks keep ticking
1717*ec779b8eSAndroid Build Coastguard Worker     ALOGV("updateInternalTimers()");
1718*ec779b8eSAndroid Build Coastguard Worker     updatePlaybackTimer(false /* stopping */, "updateInternalTimers");
1719*ec779b8eSAndroid Build Coastguard Worker     updateRebufferingTimer(false /* stopping */, false /* exiting */);
1720*ec779b8eSAndroid Build Coastguard Worker }
1721*ec779b8eSAndroid Build Coastguard Worker 
setTargetBitrate(int bitrate)1722*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::setTargetBitrate(int bitrate) {
1723*ec779b8eSAndroid Build Coastguard Worker     if (mSource != NULL) {
1724*ec779b8eSAndroid Build Coastguard Worker         mSource->setTargetBitrate(bitrate);
1725*ec779b8eSAndroid Build Coastguard Worker     }
1726*ec779b8eSAndroid Build Coastguard Worker }
1727*ec779b8eSAndroid Build Coastguard Worker 
onPause()1728*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::onPause() {
1729*ec779b8eSAndroid Build Coastguard Worker 
1730*ec779b8eSAndroid Build Coastguard Worker     updatePlaybackTimer(true /* stopping */, "onPause");
1731*ec779b8eSAndroid Build Coastguard Worker 
1732*ec779b8eSAndroid Build Coastguard Worker     if (mPaused) {
1733*ec779b8eSAndroid Build Coastguard Worker         return;
1734*ec779b8eSAndroid Build Coastguard Worker     }
1735*ec779b8eSAndroid Build Coastguard Worker     mPaused = true;
1736*ec779b8eSAndroid Build Coastguard Worker     if (mSource != NULL) {
1737*ec779b8eSAndroid Build Coastguard Worker         mSource->pause();
1738*ec779b8eSAndroid Build Coastguard Worker     } else {
1739*ec779b8eSAndroid Build Coastguard Worker         ALOGW("pause called when source is gone or not set");
1740*ec779b8eSAndroid Build Coastguard Worker     }
1741*ec779b8eSAndroid Build Coastguard Worker     if (mRenderer != NULL) {
1742*ec779b8eSAndroid Build Coastguard Worker         mRenderer->pause();
1743*ec779b8eSAndroid Build Coastguard Worker     } else {
1744*ec779b8eSAndroid Build Coastguard Worker         ALOGW("pause called when renderer is gone or not set");
1745*ec779b8eSAndroid Build Coastguard Worker     }
1746*ec779b8eSAndroid Build Coastguard Worker 
1747*ec779b8eSAndroid Build Coastguard Worker }
1748*ec779b8eSAndroid Build Coastguard Worker 
audioDecoderStillNeeded()1749*ec779b8eSAndroid Build Coastguard Worker bool NuPlayer::audioDecoderStillNeeded() {
1750*ec779b8eSAndroid Build Coastguard Worker     // Audio decoder is no longer needed if it's in shut/shutting down status.
1751*ec779b8eSAndroid Build Coastguard Worker     return ((mFlushingAudio != SHUT_DOWN) && (mFlushingAudio != SHUTTING_DOWN_DECODER));
1752*ec779b8eSAndroid Build Coastguard Worker }
1753*ec779b8eSAndroid Build Coastguard Worker 
handleFlushComplete(bool audio,bool isDecoder)1754*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::handleFlushComplete(bool audio, bool isDecoder) {
1755*ec779b8eSAndroid Build Coastguard Worker     // We wait for both the decoder flush and the renderer flush to complete
1756*ec779b8eSAndroid Build Coastguard Worker     // before entering either the FLUSHED or the SHUTTING_DOWN_DECODER state.
1757*ec779b8eSAndroid Build Coastguard Worker 
1758*ec779b8eSAndroid Build Coastguard Worker     mFlushComplete[audio][isDecoder] = true;
1759*ec779b8eSAndroid Build Coastguard Worker     if (!mFlushComplete[audio][!isDecoder]) {
1760*ec779b8eSAndroid Build Coastguard Worker         return;
1761*ec779b8eSAndroid Build Coastguard Worker     }
1762*ec779b8eSAndroid Build Coastguard Worker 
1763*ec779b8eSAndroid Build Coastguard Worker     FlushStatus *state = audio ? &mFlushingAudio : &mFlushingVideo;
1764*ec779b8eSAndroid Build Coastguard Worker     switch (*state) {
1765*ec779b8eSAndroid Build Coastguard Worker         case FLUSHING_DECODER:
1766*ec779b8eSAndroid Build Coastguard Worker         {
1767*ec779b8eSAndroid Build Coastguard Worker             *state = FLUSHED;
1768*ec779b8eSAndroid Build Coastguard Worker             break;
1769*ec779b8eSAndroid Build Coastguard Worker         }
1770*ec779b8eSAndroid Build Coastguard Worker 
1771*ec779b8eSAndroid Build Coastguard Worker         case FLUSHING_DECODER_SHUTDOWN:
1772*ec779b8eSAndroid Build Coastguard Worker         {
1773*ec779b8eSAndroid Build Coastguard Worker             *state = SHUTTING_DOWN_DECODER;
1774*ec779b8eSAndroid Build Coastguard Worker 
1775*ec779b8eSAndroid Build Coastguard Worker             ALOGV("initiating %s decoder shutdown", audio ? "audio" : "video");
1776*ec779b8eSAndroid Build Coastguard Worker             getDecoder(audio)->initiateShutdown();
1777*ec779b8eSAndroid Build Coastguard Worker             break;
1778*ec779b8eSAndroid Build Coastguard Worker         }
1779*ec779b8eSAndroid Build Coastguard Worker 
1780*ec779b8eSAndroid Build Coastguard Worker         default:
1781*ec779b8eSAndroid Build Coastguard Worker             // decoder flush completes only occur in a flushing state.
1782*ec779b8eSAndroid Build Coastguard Worker             LOG_ALWAYS_FATAL_IF(isDecoder, "decoder flush in invalid state %d", *state);
1783*ec779b8eSAndroid Build Coastguard Worker             break;
1784*ec779b8eSAndroid Build Coastguard Worker     }
1785*ec779b8eSAndroid Build Coastguard Worker }
1786*ec779b8eSAndroid Build Coastguard Worker 
finishFlushIfPossible()1787*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::finishFlushIfPossible() {
1788*ec779b8eSAndroid Build Coastguard Worker     if (mFlushingAudio != NONE && mFlushingAudio != FLUSHED
1789*ec779b8eSAndroid Build Coastguard Worker             && mFlushingAudio != SHUT_DOWN) {
1790*ec779b8eSAndroid Build Coastguard Worker         return;
1791*ec779b8eSAndroid Build Coastguard Worker     }
1792*ec779b8eSAndroid Build Coastguard Worker 
1793*ec779b8eSAndroid Build Coastguard Worker     if (mFlushingVideo != NONE && mFlushingVideo != FLUSHED
1794*ec779b8eSAndroid Build Coastguard Worker             && mFlushingVideo != SHUT_DOWN) {
1795*ec779b8eSAndroid Build Coastguard Worker         return;
1796*ec779b8eSAndroid Build Coastguard Worker     }
1797*ec779b8eSAndroid Build Coastguard Worker 
1798*ec779b8eSAndroid Build Coastguard Worker     ALOGV("both audio and video are flushed now.");
1799*ec779b8eSAndroid Build Coastguard Worker 
1800*ec779b8eSAndroid Build Coastguard Worker     mFlushingAudio = NONE;
1801*ec779b8eSAndroid Build Coastguard Worker     mFlushingVideo = NONE;
1802*ec779b8eSAndroid Build Coastguard Worker 
1803*ec779b8eSAndroid Build Coastguard Worker     clearFlushComplete();
1804*ec779b8eSAndroid Build Coastguard Worker 
1805*ec779b8eSAndroid Build Coastguard Worker     processDeferredActions();
1806*ec779b8eSAndroid Build Coastguard Worker }
1807*ec779b8eSAndroid Build Coastguard Worker 
postScanSources()1808*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::postScanSources() {
1809*ec779b8eSAndroid Build Coastguard Worker     if (mScanSourcesPending) {
1810*ec779b8eSAndroid Build Coastguard Worker         return;
1811*ec779b8eSAndroid Build Coastguard Worker     }
1812*ec779b8eSAndroid Build Coastguard Worker 
1813*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatScanSources, this);
1814*ec779b8eSAndroid Build Coastguard Worker     msg->setInt32("generation", mScanSourcesGeneration);
1815*ec779b8eSAndroid Build Coastguard Worker     msg->post();
1816*ec779b8eSAndroid Build Coastguard Worker 
1817*ec779b8eSAndroid Build Coastguard Worker     mScanSourcesPending = true;
1818*ec779b8eSAndroid Build Coastguard Worker }
1819*ec779b8eSAndroid Build Coastguard Worker 
tryOpenAudioSinkForOffload(const sp<AMessage> & format,const sp<MetaData> & audioMeta,bool hasVideo)1820*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::tryOpenAudioSinkForOffload(
1821*ec779b8eSAndroid Build Coastguard Worker         const sp<AMessage> &format, const sp<MetaData> &audioMeta, bool hasVideo) {
1822*ec779b8eSAndroid Build Coastguard Worker     // Note: This is called early in NuPlayer to determine whether offloading
1823*ec779b8eSAndroid Build Coastguard Worker     // is possible; otherwise the decoders call the renderer openAudioSink directly.
1824*ec779b8eSAndroid Build Coastguard Worker 
1825*ec779b8eSAndroid Build Coastguard Worker     status_t err = mRenderer->openAudioSink(
1826*ec779b8eSAndroid Build Coastguard Worker             format, true /* offloadOnly */, hasVideo,
1827*ec779b8eSAndroid Build Coastguard Worker             AUDIO_OUTPUT_FLAG_NONE, &mOffloadAudio, mSource->isStreaming());
1828*ec779b8eSAndroid Build Coastguard Worker     if (err != OK) {
1829*ec779b8eSAndroid Build Coastguard Worker         // Any failure we turn off mOffloadAudio.
1830*ec779b8eSAndroid Build Coastguard Worker         mOffloadAudio = false;
1831*ec779b8eSAndroid Build Coastguard Worker     } else if (mOffloadAudio) {
1832*ec779b8eSAndroid Build Coastguard Worker         sendMetaDataToHal(mAudioSink, audioMeta);
1833*ec779b8eSAndroid Build Coastguard Worker     }
1834*ec779b8eSAndroid Build Coastguard Worker }
1835*ec779b8eSAndroid Build Coastguard Worker 
closeAudioSink()1836*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::closeAudioSink() {
1837*ec779b8eSAndroid Build Coastguard Worker     if (mRenderer != NULL) {
1838*ec779b8eSAndroid Build Coastguard Worker         mRenderer->closeAudioSink();
1839*ec779b8eSAndroid Build Coastguard Worker     }
1840*ec779b8eSAndroid Build Coastguard Worker }
1841*ec779b8eSAndroid Build Coastguard Worker 
restartAudio(int64_t currentPositionUs,bool forceNonOffload,bool needsToCreateAudioDecoder)1842*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::restartAudio(
1843*ec779b8eSAndroid Build Coastguard Worker         int64_t currentPositionUs, bool forceNonOffload, bool needsToCreateAudioDecoder) {
1844*ec779b8eSAndroid Build Coastguard Worker     ALOGD("restartAudio timeUs(%lld), dontOffload(%d), createDecoder(%d)",
1845*ec779b8eSAndroid Build Coastguard Worker           (long long)currentPositionUs, forceNonOffload, needsToCreateAudioDecoder);
1846*ec779b8eSAndroid Build Coastguard Worker     if (mAudioDecoder != NULL) {
1847*ec779b8eSAndroid Build Coastguard Worker         mAudioDecoder->pause();
1848*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock autoLock(mDecoderLock);
1849*ec779b8eSAndroid Build Coastguard Worker         mAudioDecoder.clear();
1850*ec779b8eSAndroid Build Coastguard Worker         mAudioDecoderError = false;
1851*ec779b8eSAndroid Build Coastguard Worker         ++mAudioDecoderGeneration;
1852*ec779b8eSAndroid Build Coastguard Worker     }
1853*ec779b8eSAndroid Build Coastguard Worker     if (mFlushingAudio == FLUSHING_DECODER) {
1854*ec779b8eSAndroid Build Coastguard Worker         mFlushComplete[1 /* audio */][1 /* isDecoder */] = true;
1855*ec779b8eSAndroid Build Coastguard Worker         mFlushingAudio = FLUSHED;
1856*ec779b8eSAndroid Build Coastguard Worker         finishFlushIfPossible();
1857*ec779b8eSAndroid Build Coastguard Worker     } else if (mFlushingAudio == FLUSHING_DECODER_SHUTDOWN
1858*ec779b8eSAndroid Build Coastguard Worker             || mFlushingAudio == SHUTTING_DOWN_DECODER) {
1859*ec779b8eSAndroid Build Coastguard Worker         mFlushComplete[1 /* audio */][1 /* isDecoder */] = true;
1860*ec779b8eSAndroid Build Coastguard Worker         mFlushingAudio = SHUT_DOWN;
1861*ec779b8eSAndroid Build Coastguard Worker         finishFlushIfPossible();
1862*ec779b8eSAndroid Build Coastguard Worker         needsToCreateAudioDecoder = false;
1863*ec779b8eSAndroid Build Coastguard Worker     }
1864*ec779b8eSAndroid Build Coastguard Worker     if (mRenderer == NULL) {
1865*ec779b8eSAndroid Build Coastguard Worker         return;
1866*ec779b8eSAndroid Build Coastguard Worker     }
1867*ec779b8eSAndroid Build Coastguard Worker     closeAudioSink();
1868*ec779b8eSAndroid Build Coastguard Worker     mRenderer->flush(true /* audio */, false /* notifyComplete */);
1869*ec779b8eSAndroid Build Coastguard Worker     if (mVideoDecoder != NULL) {
1870*ec779b8eSAndroid Build Coastguard Worker         mDeferredActions.push_back(
1871*ec779b8eSAndroid Build Coastguard Worker                 new FlushDecoderAction(FLUSH_CMD_NONE /* audio */,
1872*ec779b8eSAndroid Build Coastguard Worker                                        FLUSH_CMD_FLUSH /* video */));
1873*ec779b8eSAndroid Build Coastguard Worker         mDeferredActions.push_back(
1874*ec779b8eSAndroid Build Coastguard Worker                 new SeekAction(currentPositionUs,
1875*ec779b8eSAndroid Build Coastguard Worker                 MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */));
1876*ec779b8eSAndroid Build Coastguard Worker         // After a flush without shutdown, decoder is paused.
1877*ec779b8eSAndroid Build Coastguard Worker         // Don't resume it until source seek is done, otherwise it could
1878*ec779b8eSAndroid Build Coastguard Worker         // start pulling stale data too soon.
1879*ec779b8eSAndroid Build Coastguard Worker         mDeferredActions.push_back(new ResumeDecoderAction(false));
1880*ec779b8eSAndroid Build Coastguard Worker         processDeferredActions();
1881*ec779b8eSAndroid Build Coastguard Worker     } else {
1882*ec779b8eSAndroid Build Coastguard Worker         performSeek(currentPositionUs, MediaPlayerSeekMode::SEEK_PREVIOUS_SYNC /* mode */);
1883*ec779b8eSAndroid Build Coastguard Worker     }
1884*ec779b8eSAndroid Build Coastguard Worker 
1885*ec779b8eSAndroid Build Coastguard Worker     if (forceNonOffload) {
1886*ec779b8eSAndroid Build Coastguard Worker         mRenderer->signalDisableOffloadAudio();
1887*ec779b8eSAndroid Build Coastguard Worker         mOffloadAudio = false;
1888*ec779b8eSAndroid Build Coastguard Worker     }
1889*ec779b8eSAndroid Build Coastguard Worker     if (needsToCreateAudioDecoder) {
1890*ec779b8eSAndroid Build Coastguard Worker         instantiateDecoder(true /* audio */, &mAudioDecoder, !forceNonOffload);
1891*ec779b8eSAndroid Build Coastguard Worker     }
1892*ec779b8eSAndroid Build Coastguard Worker }
1893*ec779b8eSAndroid Build Coastguard Worker 
determineAudioModeChange(const sp<AMessage> & audioFormat)1894*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::determineAudioModeChange(const sp<AMessage> &audioFormat) {
1895*ec779b8eSAndroid Build Coastguard Worker     if (mSource == NULL || mAudioSink == NULL) {
1896*ec779b8eSAndroid Build Coastguard Worker         return;
1897*ec779b8eSAndroid Build Coastguard Worker     }
1898*ec779b8eSAndroid Build Coastguard Worker 
1899*ec779b8eSAndroid Build Coastguard Worker     if (mRenderer == NULL) {
1900*ec779b8eSAndroid Build Coastguard Worker         ALOGW("No renderer can be used to determine audio mode. Use non-offload for safety.");
1901*ec779b8eSAndroid Build Coastguard Worker         mOffloadAudio = false;
1902*ec779b8eSAndroid Build Coastguard Worker         return;
1903*ec779b8eSAndroid Build Coastguard Worker     }
1904*ec779b8eSAndroid Build Coastguard Worker 
1905*ec779b8eSAndroid Build Coastguard Worker     sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
1906*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> videoFormat = mSource->getFormat(false /* audio */);
1907*ec779b8eSAndroid Build Coastguard Worker     audio_stream_type_t streamType = mAudioSink->getAudioStreamType();
1908*ec779b8eSAndroid Build Coastguard Worker     const bool hasVideo = (videoFormat != NULL);
1909*ec779b8eSAndroid Build Coastguard Worker     bool canOffload = canOffloadStream(
1910*ec779b8eSAndroid Build Coastguard Worker             audioMeta, hasVideo, mSource->isStreaming(), streamType)
1911*ec779b8eSAndroid Build Coastguard Worker                     && (mPlaybackSettings.mSpeed == 1.f && mPlaybackSettings.mPitch == 1.f);
1912*ec779b8eSAndroid Build Coastguard Worker 
1913*ec779b8eSAndroid Build Coastguard Worker     // Modular DRM: Disabling audio offload if the source is protected
1914*ec779b8eSAndroid Build Coastguard Worker     if (canOffload && mIsDrmProtected) {
1915*ec779b8eSAndroid Build Coastguard Worker         canOffload = false;
1916*ec779b8eSAndroid Build Coastguard Worker         ALOGV("determineAudioModeChange: Disabling mOffloadAudio b/c the source is protected.");
1917*ec779b8eSAndroid Build Coastguard Worker     }
1918*ec779b8eSAndroid Build Coastguard Worker 
1919*ec779b8eSAndroid Build Coastguard Worker     if (canOffload) {
1920*ec779b8eSAndroid Build Coastguard Worker         if (!mOffloadAudio) {
1921*ec779b8eSAndroid Build Coastguard Worker             mRenderer->signalEnableOffloadAudio();
1922*ec779b8eSAndroid Build Coastguard Worker         }
1923*ec779b8eSAndroid Build Coastguard Worker         // open audio sink early under offload mode.
1924*ec779b8eSAndroid Build Coastguard Worker         tryOpenAudioSinkForOffload(audioFormat, audioMeta, hasVideo);
1925*ec779b8eSAndroid Build Coastguard Worker     } else {
1926*ec779b8eSAndroid Build Coastguard Worker         if (mOffloadAudio) {
1927*ec779b8eSAndroid Build Coastguard Worker             mRenderer->signalDisableOffloadAudio();
1928*ec779b8eSAndroid Build Coastguard Worker             mOffloadAudio = false;
1929*ec779b8eSAndroid Build Coastguard Worker         }
1930*ec779b8eSAndroid Build Coastguard Worker     }
1931*ec779b8eSAndroid Build Coastguard Worker }
1932*ec779b8eSAndroid Build Coastguard Worker 
instantiateDecoder(bool audio,sp<DecoderBase> * decoder,bool checkAudioModeChange)1933*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::instantiateDecoder(
1934*ec779b8eSAndroid Build Coastguard Worker         bool audio, sp<DecoderBase> *decoder, bool checkAudioModeChange) {
1935*ec779b8eSAndroid Build Coastguard Worker     // The audio decoder could be cleared by tear down. If still in shut down
1936*ec779b8eSAndroid Build Coastguard Worker     // process, no need to create a new audio decoder.
1937*ec779b8eSAndroid Build Coastguard Worker     if (*decoder != NULL || (audio && mFlushingAudio == SHUT_DOWN)) {
1938*ec779b8eSAndroid Build Coastguard Worker         return OK;
1939*ec779b8eSAndroid Build Coastguard Worker     }
1940*ec779b8eSAndroid Build Coastguard Worker 
1941*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> format = mSource->getFormat(audio);
1942*ec779b8eSAndroid Build Coastguard Worker 
1943*ec779b8eSAndroid Build Coastguard Worker     if (format == NULL) {
1944*ec779b8eSAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
1945*ec779b8eSAndroid Build Coastguard Worker     } else {
1946*ec779b8eSAndroid Build Coastguard Worker         status_t err;
1947*ec779b8eSAndroid Build Coastguard Worker         if (format->findInt32("err", &err) && err) {
1948*ec779b8eSAndroid Build Coastguard Worker             return err;
1949*ec779b8eSAndroid Build Coastguard Worker         }
1950*ec779b8eSAndroid Build Coastguard Worker     }
1951*ec779b8eSAndroid Build Coastguard Worker 
1952*ec779b8eSAndroid Build Coastguard Worker     format->setInt32("priority", 0 /* realtime */);
1953*ec779b8eSAndroid Build Coastguard Worker 
1954*ec779b8eSAndroid Build Coastguard Worker     if (mDataSourceType == DATA_SOURCE_TYPE_RTP) {
1955*ec779b8eSAndroid Build Coastguard Worker         ALOGV("instantiateDecoder: set decoder error free on stream corrupt.");
1956*ec779b8eSAndroid Build Coastguard Worker         format->setInt32("corrupt-free", true);
1957*ec779b8eSAndroid Build Coastguard Worker     }
1958*ec779b8eSAndroid Build Coastguard Worker 
1959*ec779b8eSAndroid Build Coastguard Worker     if (!audio) {
1960*ec779b8eSAndroid Build Coastguard Worker         AString mime;
1961*ec779b8eSAndroid Build Coastguard Worker         CHECK(format->findString("mime", &mime));
1962*ec779b8eSAndroid Build Coastguard Worker 
1963*ec779b8eSAndroid Build Coastguard Worker         sp<AMessage> ccNotify = new AMessage(kWhatClosedCaptionNotify, this);
1964*ec779b8eSAndroid Build Coastguard Worker         if (mCCDecoder == NULL) {
1965*ec779b8eSAndroid Build Coastguard Worker             mCCDecoder = new CCDecoder(ccNotify);
1966*ec779b8eSAndroid Build Coastguard Worker         }
1967*ec779b8eSAndroid Build Coastguard Worker 
1968*ec779b8eSAndroid Build Coastguard Worker         if (mSourceFlags & Source::FLAG_SECURE) {
1969*ec779b8eSAndroid Build Coastguard Worker             format->setInt32("secure", true);
1970*ec779b8eSAndroid Build Coastguard Worker         }
1971*ec779b8eSAndroid Build Coastguard Worker 
1972*ec779b8eSAndroid Build Coastguard Worker         if (mSourceFlags & Source::FLAG_PROTECTED) {
1973*ec779b8eSAndroid Build Coastguard Worker             format->setInt32("protected", true);
1974*ec779b8eSAndroid Build Coastguard Worker         }
1975*ec779b8eSAndroid Build Coastguard Worker 
1976*ec779b8eSAndroid Build Coastguard Worker         float rate = getFrameRate();
1977*ec779b8eSAndroid Build Coastguard Worker         if (rate > 0) {
1978*ec779b8eSAndroid Build Coastguard Worker             format->setFloat("operating-rate", rate * mPlaybackSettings.mSpeed);
1979*ec779b8eSAndroid Build Coastguard Worker         }
1980*ec779b8eSAndroid Build Coastguard Worker 
1981*ec779b8eSAndroid Build Coastguard Worker         format->setInt32("android._video-scaling", mVideoScalingMode);
1982*ec779b8eSAndroid Build Coastguard Worker     }
1983*ec779b8eSAndroid Build Coastguard Worker 
1984*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mDecoderLock);
1985*ec779b8eSAndroid Build Coastguard Worker 
1986*ec779b8eSAndroid Build Coastguard Worker     if (audio) {
1987*ec779b8eSAndroid Build Coastguard Worker         sp<AMessage> notify = new AMessage(kWhatAudioNotify, this);
1988*ec779b8eSAndroid Build Coastguard Worker         ++mAudioDecoderGeneration;
1989*ec779b8eSAndroid Build Coastguard Worker         notify->setInt32("generation", mAudioDecoderGeneration);
1990*ec779b8eSAndroid Build Coastguard Worker 
1991*ec779b8eSAndroid Build Coastguard Worker         if (checkAudioModeChange) {
1992*ec779b8eSAndroid Build Coastguard Worker             determineAudioModeChange(format);
1993*ec779b8eSAndroid Build Coastguard Worker         }
1994*ec779b8eSAndroid Build Coastguard Worker         if (mOffloadAudio) {
1995*ec779b8eSAndroid Build Coastguard Worker             mSource->setOffloadAudio(true /* offload */);
1996*ec779b8eSAndroid Build Coastguard Worker 
1997*ec779b8eSAndroid Build Coastguard Worker             const bool hasVideo = (mSource->getFormat(false /*audio */) != NULL);
1998*ec779b8eSAndroid Build Coastguard Worker             format->setInt32("has-video", hasVideo);
1999*ec779b8eSAndroid Build Coastguard Worker             *decoder = new DecoderPassThrough(notify, mSource, mRenderer);
2000*ec779b8eSAndroid Build Coastguard Worker             ALOGV("instantiateDecoder audio DecoderPassThrough  hasVideo: %d", hasVideo);
2001*ec779b8eSAndroid Build Coastguard Worker         } else {
2002*ec779b8eSAndroid Build Coastguard Worker             mSource->setOffloadAudio(false /* offload */);
2003*ec779b8eSAndroid Build Coastguard Worker 
2004*ec779b8eSAndroid Build Coastguard Worker             *decoder = new Decoder(notify, mSource, mPID, mUID, mRenderer);
2005*ec779b8eSAndroid Build Coastguard Worker             ALOGV("instantiateDecoder audio Decoder");
2006*ec779b8eSAndroid Build Coastguard Worker         }
2007*ec779b8eSAndroid Build Coastguard Worker         mAudioDecoderError = false;
2008*ec779b8eSAndroid Build Coastguard Worker     } else {
2009*ec779b8eSAndroid Build Coastguard Worker         sp<AMessage> notify = new AMessage(kWhatVideoNotify, this);
2010*ec779b8eSAndroid Build Coastguard Worker         ++mVideoDecoderGeneration;
2011*ec779b8eSAndroid Build Coastguard Worker         notify->setInt32("generation", mVideoDecoderGeneration);
2012*ec779b8eSAndroid Build Coastguard Worker 
2013*ec779b8eSAndroid Build Coastguard Worker         *decoder = new Decoder(
2014*ec779b8eSAndroid Build Coastguard Worker                 notify, mSource, mPID, mUID, mRenderer, mSurface, mCCDecoder);
2015*ec779b8eSAndroid Build Coastguard Worker         mVideoDecoderError = false;
2016*ec779b8eSAndroid Build Coastguard Worker 
2017*ec779b8eSAndroid Build Coastguard Worker         // enable FRC if high-quality AV sync is requested, even if not
2018*ec779b8eSAndroid Build Coastguard Worker         // directly queuing to display, as this will even improve textureview
2019*ec779b8eSAndroid Build Coastguard Worker         // playback.
2020*ec779b8eSAndroid Build Coastguard Worker         {
2021*ec779b8eSAndroid Build Coastguard Worker             if (property_get_bool("persist.sys.media.avsync", false)) {
2022*ec779b8eSAndroid Build Coastguard Worker                 format->setInt32("auto-frc", 1);
2023*ec779b8eSAndroid Build Coastguard Worker             }
2024*ec779b8eSAndroid Build Coastguard Worker         }
2025*ec779b8eSAndroid Build Coastguard Worker     }
2026*ec779b8eSAndroid Build Coastguard Worker     (*decoder)->init();
2027*ec779b8eSAndroid Build Coastguard Worker 
2028*ec779b8eSAndroid Build Coastguard Worker     // Modular DRM
2029*ec779b8eSAndroid Build Coastguard Worker     if (mIsDrmProtected) {
2030*ec779b8eSAndroid Build Coastguard Worker         format->setPointer("crypto", mCrypto.get());
2031*ec779b8eSAndroid Build Coastguard Worker         ALOGV("instantiateDecoder: mCrypto: %p (%d) isSecure: %d", mCrypto.get(),
2032*ec779b8eSAndroid Build Coastguard Worker                 (mCrypto != NULL ? mCrypto->getStrongCount() : 0),
2033*ec779b8eSAndroid Build Coastguard Worker                 (mSourceFlags & Source::FLAG_SECURE) != 0);
2034*ec779b8eSAndroid Build Coastguard Worker     }
2035*ec779b8eSAndroid Build Coastguard Worker 
2036*ec779b8eSAndroid Build Coastguard Worker     (*decoder)->configure(format);
2037*ec779b8eSAndroid Build Coastguard Worker 
2038*ec779b8eSAndroid Build Coastguard Worker     if (!audio) {
2039*ec779b8eSAndroid Build Coastguard Worker         sp<AMessage> params = new AMessage();
2040*ec779b8eSAndroid Build Coastguard Worker         float rate = getFrameRate();
2041*ec779b8eSAndroid Build Coastguard Worker         if (rate > 0) {
2042*ec779b8eSAndroid Build Coastguard Worker             params->setFloat("frame-rate-total", rate);
2043*ec779b8eSAndroid Build Coastguard Worker         }
2044*ec779b8eSAndroid Build Coastguard Worker 
2045*ec779b8eSAndroid Build Coastguard Worker         sp<MetaData> fileMeta = getFileMeta();
2046*ec779b8eSAndroid Build Coastguard Worker         if (fileMeta != NULL) {
2047*ec779b8eSAndroid Build Coastguard Worker             int32_t videoTemporalLayerCount;
2048*ec779b8eSAndroid Build Coastguard Worker             if (fileMeta->findInt32(kKeyTemporalLayerCount, &videoTemporalLayerCount)
2049*ec779b8eSAndroid Build Coastguard Worker                     && videoTemporalLayerCount > 0) {
2050*ec779b8eSAndroid Build Coastguard Worker                 params->setInt32("temporal-layer-count", videoTemporalLayerCount);
2051*ec779b8eSAndroid Build Coastguard Worker             }
2052*ec779b8eSAndroid Build Coastguard Worker         }
2053*ec779b8eSAndroid Build Coastguard Worker 
2054*ec779b8eSAndroid Build Coastguard Worker         if (params->countEntries() > 0) {
2055*ec779b8eSAndroid Build Coastguard Worker             (*decoder)->setParameters(params);
2056*ec779b8eSAndroid Build Coastguard Worker         }
2057*ec779b8eSAndroid Build Coastguard Worker     }
2058*ec779b8eSAndroid Build Coastguard Worker     return OK;
2059*ec779b8eSAndroid Build Coastguard Worker }
2060*ec779b8eSAndroid Build Coastguard Worker 
updateVideoSize(const sp<AMessage> & inputFormat,const sp<AMessage> & outputFormat)2061*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::updateVideoSize(
2062*ec779b8eSAndroid Build Coastguard Worker         const sp<AMessage> &inputFormat,
2063*ec779b8eSAndroid Build Coastguard Worker         const sp<AMessage> &outputFormat) {
2064*ec779b8eSAndroid Build Coastguard Worker     if (inputFormat == NULL) {
2065*ec779b8eSAndroid Build Coastguard Worker         ALOGW("Unknown video size, reporting 0x0!");
2066*ec779b8eSAndroid Build Coastguard Worker         notifyListener(MEDIA_SET_VIDEO_SIZE, 0, 0);
2067*ec779b8eSAndroid Build Coastguard Worker         return;
2068*ec779b8eSAndroid Build Coastguard Worker     }
2069*ec779b8eSAndroid Build Coastguard Worker     int32_t err = OK;
2070*ec779b8eSAndroid Build Coastguard Worker     inputFormat->findInt32("err", &err);
2071*ec779b8eSAndroid Build Coastguard Worker     if (err == -EWOULDBLOCK) {
2072*ec779b8eSAndroid Build Coastguard Worker         ALOGW("Video meta is not available yet!");
2073*ec779b8eSAndroid Build Coastguard Worker         return;
2074*ec779b8eSAndroid Build Coastguard Worker     }
2075*ec779b8eSAndroid Build Coastguard Worker     if (err != OK) {
2076*ec779b8eSAndroid Build Coastguard Worker         ALOGW("Something is wrong with video meta!");
2077*ec779b8eSAndroid Build Coastguard Worker         return;
2078*ec779b8eSAndroid Build Coastguard Worker     }
2079*ec779b8eSAndroid Build Coastguard Worker 
2080*ec779b8eSAndroid Build Coastguard Worker     int32_t displayWidth, displayHeight;
2081*ec779b8eSAndroid Build Coastguard Worker     if (outputFormat != NULL) {
2082*ec779b8eSAndroid Build Coastguard Worker         int32_t width, height;
2083*ec779b8eSAndroid Build Coastguard Worker         CHECK(outputFormat->findInt32("width", &width));
2084*ec779b8eSAndroid Build Coastguard Worker         CHECK(outputFormat->findInt32("height", &height));
2085*ec779b8eSAndroid Build Coastguard Worker 
2086*ec779b8eSAndroid Build Coastguard Worker         int32_t cropLeft, cropTop, cropRight, cropBottom;
2087*ec779b8eSAndroid Build Coastguard Worker         CHECK(outputFormat->findRect(
2088*ec779b8eSAndroid Build Coastguard Worker                     "crop",
2089*ec779b8eSAndroid Build Coastguard Worker                     &cropLeft, &cropTop, &cropRight, &cropBottom));
2090*ec779b8eSAndroid Build Coastguard Worker 
2091*ec779b8eSAndroid Build Coastguard Worker         displayWidth = cropRight - cropLeft + 1;
2092*ec779b8eSAndroid Build Coastguard Worker         displayHeight = cropBottom - cropTop + 1;
2093*ec779b8eSAndroid Build Coastguard Worker 
2094*ec779b8eSAndroid Build Coastguard Worker         ALOGV("Video output format changed to %d x %d "
2095*ec779b8eSAndroid Build Coastguard Worker              "(crop: %d x %d @ (%d, %d))",
2096*ec779b8eSAndroid Build Coastguard Worker              width, height,
2097*ec779b8eSAndroid Build Coastguard Worker              displayWidth,
2098*ec779b8eSAndroid Build Coastguard Worker              displayHeight,
2099*ec779b8eSAndroid Build Coastguard Worker              cropLeft, cropTop);
2100*ec779b8eSAndroid Build Coastguard Worker     } else {
2101*ec779b8eSAndroid Build Coastguard Worker         if (!inputFormat->findInt32("width", &displayWidth)
2102*ec779b8eSAndroid Build Coastguard Worker             || !inputFormat->findInt32("height", &displayHeight)) {
2103*ec779b8eSAndroid Build Coastguard Worker             ALOGW("Either video width or video height missing, reporting 0x0!");
2104*ec779b8eSAndroid Build Coastguard Worker             notifyListener(MEDIA_SET_VIDEO_SIZE, 0, 0);
2105*ec779b8eSAndroid Build Coastguard Worker             return;
2106*ec779b8eSAndroid Build Coastguard Worker         }
2107*ec779b8eSAndroid Build Coastguard Worker         ALOGV("Video input format %d x %d", displayWidth, displayHeight);
2108*ec779b8eSAndroid Build Coastguard Worker     }
2109*ec779b8eSAndroid Build Coastguard Worker 
2110*ec779b8eSAndroid Build Coastguard Worker     // Take into account sample aspect ratio if necessary:
2111*ec779b8eSAndroid Build Coastguard Worker     int32_t sarWidth, sarHeight;
2112*ec779b8eSAndroid Build Coastguard Worker     if (inputFormat->findInt32("sar-width", &sarWidth)
2113*ec779b8eSAndroid Build Coastguard Worker             && inputFormat->findInt32("sar-height", &sarHeight)
2114*ec779b8eSAndroid Build Coastguard Worker             && sarWidth > 0 && sarHeight > 0) {
2115*ec779b8eSAndroid Build Coastguard Worker         ALOGV("Sample aspect ratio %d : %d", sarWidth, sarHeight);
2116*ec779b8eSAndroid Build Coastguard Worker 
2117*ec779b8eSAndroid Build Coastguard Worker         displayWidth = (displayWidth * sarWidth) / sarHeight;
2118*ec779b8eSAndroid Build Coastguard Worker 
2119*ec779b8eSAndroid Build Coastguard Worker         ALOGV("display dimensions %d x %d", displayWidth, displayHeight);
2120*ec779b8eSAndroid Build Coastguard Worker     } else {
2121*ec779b8eSAndroid Build Coastguard Worker         int32_t width, height;
2122*ec779b8eSAndroid Build Coastguard Worker         if (inputFormat->findInt32("display-width", &width)
2123*ec779b8eSAndroid Build Coastguard Worker                 && inputFormat->findInt32("display-height", &height)
2124*ec779b8eSAndroid Build Coastguard Worker                 && width > 0 && height > 0
2125*ec779b8eSAndroid Build Coastguard Worker                 && displayWidth > 0 && displayHeight > 0) {
2126*ec779b8eSAndroid Build Coastguard Worker             if (displayHeight * (int64_t)width / height > (int64_t)displayWidth) {
2127*ec779b8eSAndroid Build Coastguard Worker                 displayHeight = (int32_t)(displayWidth * (int64_t)height / width);
2128*ec779b8eSAndroid Build Coastguard Worker             } else {
2129*ec779b8eSAndroid Build Coastguard Worker                 displayWidth = (int32_t)(displayHeight * (int64_t)width / height);
2130*ec779b8eSAndroid Build Coastguard Worker             }
2131*ec779b8eSAndroid Build Coastguard Worker             ALOGV("Video display width and height are overridden to %d x %d",
2132*ec779b8eSAndroid Build Coastguard Worker                  displayWidth, displayHeight);
2133*ec779b8eSAndroid Build Coastguard Worker         }
2134*ec779b8eSAndroid Build Coastguard Worker     }
2135*ec779b8eSAndroid Build Coastguard Worker 
2136*ec779b8eSAndroid Build Coastguard Worker     int32_t rotationDegrees;
2137*ec779b8eSAndroid Build Coastguard Worker     if (!inputFormat->findInt32("rotation-degrees", &rotationDegrees)) {
2138*ec779b8eSAndroid Build Coastguard Worker         rotationDegrees = 0;
2139*ec779b8eSAndroid Build Coastguard Worker     }
2140*ec779b8eSAndroid Build Coastguard Worker 
2141*ec779b8eSAndroid Build Coastguard Worker     if (rotationDegrees == 90 || rotationDegrees == 270) {
2142*ec779b8eSAndroid Build Coastguard Worker         int32_t tmp = displayWidth;
2143*ec779b8eSAndroid Build Coastguard Worker         displayWidth = displayHeight;
2144*ec779b8eSAndroid Build Coastguard Worker         displayHeight = tmp;
2145*ec779b8eSAndroid Build Coastguard Worker     }
2146*ec779b8eSAndroid Build Coastguard Worker 
2147*ec779b8eSAndroid Build Coastguard Worker     notifyListener(
2148*ec779b8eSAndroid Build Coastguard Worker             MEDIA_SET_VIDEO_SIZE,
2149*ec779b8eSAndroid Build Coastguard Worker             displayWidth,
2150*ec779b8eSAndroid Build Coastguard Worker             displayHeight);
2151*ec779b8eSAndroid Build Coastguard Worker }
2152*ec779b8eSAndroid Build Coastguard Worker 
notifyListener(int msg,int ext1,int ext2,const Parcel * in)2153*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::notifyListener(int msg, int ext1, int ext2, const Parcel *in) {
2154*ec779b8eSAndroid Build Coastguard Worker     if (mDriver == NULL) {
2155*ec779b8eSAndroid Build Coastguard Worker         return;
2156*ec779b8eSAndroid Build Coastguard Worker     }
2157*ec779b8eSAndroid Build Coastguard Worker 
2158*ec779b8eSAndroid Build Coastguard Worker     sp<NuPlayerDriver> driver = mDriver.promote();
2159*ec779b8eSAndroid Build Coastguard Worker 
2160*ec779b8eSAndroid Build Coastguard Worker     if (driver == NULL) {
2161*ec779b8eSAndroid Build Coastguard Worker         return;
2162*ec779b8eSAndroid Build Coastguard Worker     }
2163*ec779b8eSAndroid Build Coastguard Worker 
2164*ec779b8eSAndroid Build Coastguard Worker     driver->notifyListener(msg, ext1, ext2, in);
2165*ec779b8eSAndroid Build Coastguard Worker }
2166*ec779b8eSAndroid Build Coastguard Worker 
flushDecoder(bool audio,bool needShutdown)2167*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
2168*ec779b8eSAndroid Build Coastguard Worker     ALOGV("[%s] flushDecoder needShutdown=%d",
2169*ec779b8eSAndroid Build Coastguard Worker           audio ? "audio" : "video", needShutdown);
2170*ec779b8eSAndroid Build Coastguard Worker 
2171*ec779b8eSAndroid Build Coastguard Worker     const sp<DecoderBase> &decoder = getDecoder(audio);
2172*ec779b8eSAndroid Build Coastguard Worker     if (decoder == NULL) {
2173*ec779b8eSAndroid Build Coastguard Worker         ALOGI("flushDecoder %s without decoder present",
2174*ec779b8eSAndroid Build Coastguard Worker              audio ? "audio" : "video");
2175*ec779b8eSAndroid Build Coastguard Worker         return;
2176*ec779b8eSAndroid Build Coastguard Worker     }
2177*ec779b8eSAndroid Build Coastguard Worker 
2178*ec779b8eSAndroid Build Coastguard Worker     // Make sure we don't continue to scan sources until we finish flushing.
2179*ec779b8eSAndroid Build Coastguard Worker     ++mScanSourcesGeneration;
2180*ec779b8eSAndroid Build Coastguard Worker     if (mScanSourcesPending) {
2181*ec779b8eSAndroid Build Coastguard Worker         if (!needShutdown) {
2182*ec779b8eSAndroid Build Coastguard Worker             mDeferredActions.push_back(
2183*ec779b8eSAndroid Build Coastguard Worker                     new SimpleAction(&NuPlayer::performScanSources));
2184*ec779b8eSAndroid Build Coastguard Worker         }
2185*ec779b8eSAndroid Build Coastguard Worker         mScanSourcesPending = false;
2186*ec779b8eSAndroid Build Coastguard Worker     }
2187*ec779b8eSAndroid Build Coastguard Worker 
2188*ec779b8eSAndroid Build Coastguard Worker     decoder->signalFlush();
2189*ec779b8eSAndroid Build Coastguard Worker 
2190*ec779b8eSAndroid Build Coastguard Worker     FlushStatus newStatus =
2191*ec779b8eSAndroid Build Coastguard Worker         needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
2192*ec779b8eSAndroid Build Coastguard Worker 
2193*ec779b8eSAndroid Build Coastguard Worker     mFlushComplete[audio][false /* isDecoder */] = (mRenderer == NULL);
2194*ec779b8eSAndroid Build Coastguard Worker     mFlushComplete[audio][true /* isDecoder */] = false;
2195*ec779b8eSAndroid Build Coastguard Worker     if (audio) {
2196*ec779b8eSAndroid Build Coastguard Worker         ALOGE_IF(mFlushingAudio != NONE,
2197*ec779b8eSAndroid Build Coastguard Worker                 "audio flushDecoder() is called in state %d", mFlushingAudio);
2198*ec779b8eSAndroid Build Coastguard Worker         mFlushingAudio = newStatus;
2199*ec779b8eSAndroid Build Coastguard Worker     } else {
2200*ec779b8eSAndroid Build Coastguard Worker         ALOGE_IF(mFlushingVideo != NONE,
2201*ec779b8eSAndroid Build Coastguard Worker                 "video flushDecoder() is called in state %d", mFlushingVideo);
2202*ec779b8eSAndroid Build Coastguard Worker         mFlushingVideo = newStatus;
2203*ec779b8eSAndroid Build Coastguard Worker     }
2204*ec779b8eSAndroid Build Coastguard Worker }
2205*ec779b8eSAndroid Build Coastguard Worker 
queueDecoderShutdown(bool audio,bool video,const sp<AMessage> & reply)2206*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::queueDecoderShutdown(
2207*ec779b8eSAndroid Build Coastguard Worker         bool audio, bool video, const sp<AMessage> &reply) {
2208*ec779b8eSAndroid Build Coastguard Worker     ALOGI("queueDecoderShutdown audio=%d, video=%d", audio, video);
2209*ec779b8eSAndroid Build Coastguard Worker 
2210*ec779b8eSAndroid Build Coastguard Worker     mDeferredActions.push_back(
2211*ec779b8eSAndroid Build Coastguard Worker             new FlushDecoderAction(
2212*ec779b8eSAndroid Build Coastguard Worker                 audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE,
2213*ec779b8eSAndroid Build Coastguard Worker                 video ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE));
2214*ec779b8eSAndroid Build Coastguard Worker 
2215*ec779b8eSAndroid Build Coastguard Worker     mDeferredActions.push_back(
2216*ec779b8eSAndroid Build Coastguard Worker             new SimpleAction(&NuPlayer::performScanSources));
2217*ec779b8eSAndroid Build Coastguard Worker 
2218*ec779b8eSAndroid Build Coastguard Worker     mDeferredActions.push_back(new PostMessageAction(reply));
2219*ec779b8eSAndroid Build Coastguard Worker 
2220*ec779b8eSAndroid Build Coastguard Worker     processDeferredActions();
2221*ec779b8eSAndroid Build Coastguard Worker }
2222*ec779b8eSAndroid Build Coastguard Worker 
setVideoScalingMode(int32_t mode)2223*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::setVideoScalingMode(int32_t mode) {
2224*ec779b8eSAndroid Build Coastguard Worker     mVideoScalingMode = mode;
2225*ec779b8eSAndroid Build Coastguard Worker     if (mSurface != NULL) {
2226*ec779b8eSAndroid Build Coastguard Worker         status_t ret = native_window_set_scaling_mode(mSurface.get(), mVideoScalingMode);
2227*ec779b8eSAndroid Build Coastguard Worker         if (ret != OK) {
2228*ec779b8eSAndroid Build Coastguard Worker             ALOGE("Failed to set scaling mode (%d): %s",
2229*ec779b8eSAndroid Build Coastguard Worker                 -ret, strerror(-ret));
2230*ec779b8eSAndroid Build Coastguard Worker             return ret;
2231*ec779b8eSAndroid Build Coastguard Worker         }
2232*ec779b8eSAndroid Build Coastguard Worker         if (mVideoDecoder != NULL) {
2233*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> params = new AMessage();
2234*ec779b8eSAndroid Build Coastguard Worker             params->setInt32("android._video-scaling", mode);
2235*ec779b8eSAndroid Build Coastguard Worker             mVideoDecoder->setParameters(params);
2236*ec779b8eSAndroid Build Coastguard Worker         }
2237*ec779b8eSAndroid Build Coastguard Worker     }
2238*ec779b8eSAndroid Build Coastguard Worker     return OK;
2239*ec779b8eSAndroid Build Coastguard Worker }
2240*ec779b8eSAndroid Build Coastguard Worker 
getTrackInfo(Parcel * reply) const2241*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::getTrackInfo(Parcel* reply) const {
2242*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatGetTrackInfo, this);
2243*ec779b8eSAndroid Build Coastguard Worker     msg->setPointer("reply", reply);
2244*ec779b8eSAndroid Build Coastguard Worker 
2245*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> response;
2246*ec779b8eSAndroid Build Coastguard Worker     status_t err = msg->postAndAwaitResponse(&response);
2247*ec779b8eSAndroid Build Coastguard Worker     return err;
2248*ec779b8eSAndroid Build Coastguard Worker }
2249*ec779b8eSAndroid Build Coastguard Worker 
getSelectedTrack(int32_t type,Parcel * reply) const2250*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::getSelectedTrack(int32_t type, Parcel* reply) const {
2251*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, this);
2252*ec779b8eSAndroid Build Coastguard Worker     msg->setPointer("reply", reply);
2253*ec779b8eSAndroid Build Coastguard Worker     msg->setInt32("type", type);
2254*ec779b8eSAndroid Build Coastguard Worker 
2255*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> response;
2256*ec779b8eSAndroid Build Coastguard Worker     status_t err = msg->postAndAwaitResponse(&response);
2257*ec779b8eSAndroid Build Coastguard Worker     if (err == OK && response != NULL) {
2258*ec779b8eSAndroid Build Coastguard Worker         CHECK(response->findInt32("err", &err));
2259*ec779b8eSAndroid Build Coastguard Worker     }
2260*ec779b8eSAndroid Build Coastguard Worker     return err;
2261*ec779b8eSAndroid Build Coastguard Worker }
2262*ec779b8eSAndroid Build Coastguard Worker 
selectTrack(size_t trackIndex,bool select,int64_t timeUs)2263*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
2264*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatSelectTrack, this);
2265*ec779b8eSAndroid Build Coastguard Worker     msg->setSize("trackIndex", trackIndex);
2266*ec779b8eSAndroid Build Coastguard Worker     msg->setInt32("select", select);
2267*ec779b8eSAndroid Build Coastguard Worker     msg->setInt64("timeUs", timeUs);
2268*ec779b8eSAndroid Build Coastguard Worker 
2269*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> response;
2270*ec779b8eSAndroid Build Coastguard Worker     status_t err = msg->postAndAwaitResponse(&response);
2271*ec779b8eSAndroid Build Coastguard Worker 
2272*ec779b8eSAndroid Build Coastguard Worker     if (err != OK) {
2273*ec779b8eSAndroid Build Coastguard Worker         return err;
2274*ec779b8eSAndroid Build Coastguard Worker     }
2275*ec779b8eSAndroid Build Coastguard Worker 
2276*ec779b8eSAndroid Build Coastguard Worker     if (!response->findInt32("err", &err)) {
2277*ec779b8eSAndroid Build Coastguard Worker         err = OK;
2278*ec779b8eSAndroid Build Coastguard Worker     }
2279*ec779b8eSAndroid Build Coastguard Worker 
2280*ec779b8eSAndroid Build Coastguard Worker     return err;
2281*ec779b8eSAndroid Build Coastguard Worker }
2282*ec779b8eSAndroid Build Coastguard Worker 
getCurrentPosition(int64_t * mediaUs)2283*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::getCurrentPosition(int64_t *mediaUs) {
2284*ec779b8eSAndroid Build Coastguard Worker     sp<Renderer> renderer = mRenderer;
2285*ec779b8eSAndroid Build Coastguard Worker     if (renderer == NULL) {
2286*ec779b8eSAndroid Build Coastguard Worker         return NO_INIT;
2287*ec779b8eSAndroid Build Coastguard Worker     }
2288*ec779b8eSAndroid Build Coastguard Worker 
2289*ec779b8eSAndroid Build Coastguard Worker     return renderer->getCurrentPosition(mediaUs);
2290*ec779b8eSAndroid Build Coastguard Worker }
2291*ec779b8eSAndroid Build Coastguard Worker 
getStats(Vector<sp<AMessage>> * trackStats)2292*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::getStats(Vector<sp<AMessage> > *trackStats) {
2293*ec779b8eSAndroid Build Coastguard Worker     CHECK(trackStats != NULL);
2294*ec779b8eSAndroid Build Coastguard Worker 
2295*ec779b8eSAndroid Build Coastguard Worker     trackStats->clear();
2296*ec779b8eSAndroid Build Coastguard Worker 
2297*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock autoLock(mDecoderLock);
2298*ec779b8eSAndroid Build Coastguard Worker     if (mVideoDecoder != NULL) {
2299*ec779b8eSAndroid Build Coastguard Worker         trackStats->push_back(mVideoDecoder->getStats());
2300*ec779b8eSAndroid Build Coastguard Worker     }
2301*ec779b8eSAndroid Build Coastguard Worker     if (mAudioDecoder != NULL) {
2302*ec779b8eSAndroid Build Coastguard Worker         trackStats->push_back(mAudioDecoder->getStats());
2303*ec779b8eSAndroid Build Coastguard Worker     }
2304*ec779b8eSAndroid Build Coastguard Worker }
2305*ec779b8eSAndroid Build Coastguard Worker 
getFileMeta()2306*ec779b8eSAndroid Build Coastguard Worker sp<MetaData> NuPlayer::getFileMeta() {
2307*ec779b8eSAndroid Build Coastguard Worker     return mSource->getFileFormatMeta();
2308*ec779b8eSAndroid Build Coastguard Worker }
2309*ec779b8eSAndroid Build Coastguard Worker 
getFrameRate()2310*ec779b8eSAndroid Build Coastguard Worker float NuPlayer::getFrameRate() {
2311*ec779b8eSAndroid Build Coastguard Worker     sp<MetaData> meta = mSource->getFormatMeta(false /* audio */);
2312*ec779b8eSAndroid Build Coastguard Worker     if (meta == NULL) {
2313*ec779b8eSAndroid Build Coastguard Worker         return 0;
2314*ec779b8eSAndroid Build Coastguard Worker     }
2315*ec779b8eSAndroid Build Coastguard Worker     int32_t rate;
2316*ec779b8eSAndroid Build Coastguard Worker     if (!meta->findInt32(kKeyFrameRate, &rate)) {
2317*ec779b8eSAndroid Build Coastguard Worker         // fall back to try file meta
2318*ec779b8eSAndroid Build Coastguard Worker         sp<MetaData> fileMeta = getFileMeta();
2319*ec779b8eSAndroid Build Coastguard Worker         if (fileMeta == NULL) {
2320*ec779b8eSAndroid Build Coastguard Worker             ALOGW("source has video meta but not file meta");
2321*ec779b8eSAndroid Build Coastguard Worker             return -1;
2322*ec779b8eSAndroid Build Coastguard Worker         }
2323*ec779b8eSAndroid Build Coastguard Worker         int32_t fileMetaRate;
2324*ec779b8eSAndroid Build Coastguard Worker         if (!fileMeta->findInt32(kKeyFrameRate, &fileMetaRate)) {
2325*ec779b8eSAndroid Build Coastguard Worker             return -1;
2326*ec779b8eSAndroid Build Coastguard Worker         }
2327*ec779b8eSAndroid Build Coastguard Worker         return fileMetaRate;
2328*ec779b8eSAndroid Build Coastguard Worker     }
2329*ec779b8eSAndroid Build Coastguard Worker     return rate;
2330*ec779b8eSAndroid Build Coastguard Worker }
2331*ec779b8eSAndroid Build Coastguard Worker 
schedulePollDuration()2332*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::schedulePollDuration() {
2333*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatPollDuration, this);
2334*ec779b8eSAndroid Build Coastguard Worker     msg->setInt32("generation", mPollDurationGeneration);
2335*ec779b8eSAndroid Build Coastguard Worker     msg->post();
2336*ec779b8eSAndroid Build Coastguard Worker }
2337*ec779b8eSAndroid Build Coastguard Worker 
cancelPollDuration()2338*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::cancelPollDuration() {
2339*ec779b8eSAndroid Build Coastguard Worker     ++mPollDurationGeneration;
2340*ec779b8eSAndroid Build Coastguard Worker }
2341*ec779b8eSAndroid Build Coastguard Worker 
processDeferredActions()2342*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::processDeferredActions() {
2343*ec779b8eSAndroid Build Coastguard Worker     while (!mDeferredActions.empty()) {
2344*ec779b8eSAndroid Build Coastguard Worker         // We won't execute any deferred actions until we're no longer in
2345*ec779b8eSAndroid Build Coastguard Worker         // an intermediate state, i.e. one more more decoders are currently
2346*ec779b8eSAndroid Build Coastguard Worker         // flushing or shutting down.
2347*ec779b8eSAndroid Build Coastguard Worker 
2348*ec779b8eSAndroid Build Coastguard Worker         if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
2349*ec779b8eSAndroid Build Coastguard Worker             // We're currently flushing, postpone the reset until that's
2350*ec779b8eSAndroid Build Coastguard Worker             // completed.
2351*ec779b8eSAndroid Build Coastguard Worker 
2352*ec779b8eSAndroid Build Coastguard Worker             ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d",
2353*ec779b8eSAndroid Build Coastguard Worker                   mFlushingAudio, mFlushingVideo);
2354*ec779b8eSAndroid Build Coastguard Worker 
2355*ec779b8eSAndroid Build Coastguard Worker             break;
2356*ec779b8eSAndroid Build Coastguard Worker         }
2357*ec779b8eSAndroid Build Coastguard Worker 
2358*ec779b8eSAndroid Build Coastguard Worker         sp<Action> action = *mDeferredActions.begin();
2359*ec779b8eSAndroid Build Coastguard Worker         mDeferredActions.erase(mDeferredActions.begin());
2360*ec779b8eSAndroid Build Coastguard Worker 
2361*ec779b8eSAndroid Build Coastguard Worker         action->execute(this);
2362*ec779b8eSAndroid Build Coastguard Worker     }
2363*ec779b8eSAndroid Build Coastguard Worker }
2364*ec779b8eSAndroid Build Coastguard Worker 
performSeek(int64_t seekTimeUs,MediaPlayerSeekMode mode)2365*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::performSeek(int64_t seekTimeUs, MediaPlayerSeekMode mode) {
2366*ec779b8eSAndroid Build Coastguard Worker     ALOGV("performSeek seekTimeUs=%lld us (%.2f secs), mode=%d",
2367*ec779b8eSAndroid Build Coastguard Worker           (long long)seekTimeUs, seekTimeUs / 1E6, mode);
2368*ec779b8eSAndroid Build Coastguard Worker 
2369*ec779b8eSAndroid Build Coastguard Worker     if (mSource == NULL) {
2370*ec779b8eSAndroid Build Coastguard Worker         // This happens when reset occurs right before the loop mode
2371*ec779b8eSAndroid Build Coastguard Worker         // asynchronously seeks to the start of the stream.
2372*ec779b8eSAndroid Build Coastguard Worker         LOG_ALWAYS_FATAL_IF(mAudioDecoder != NULL || mVideoDecoder != NULL,
2373*ec779b8eSAndroid Build Coastguard Worker                 "mSource is NULL and decoders not NULL audio(%p) video(%p)",
2374*ec779b8eSAndroid Build Coastguard Worker                 mAudioDecoder.get(), mVideoDecoder.get());
2375*ec779b8eSAndroid Build Coastguard Worker         return;
2376*ec779b8eSAndroid Build Coastguard Worker     }
2377*ec779b8eSAndroid Build Coastguard Worker     mPreviousSeekTimeUs = seekTimeUs;
2378*ec779b8eSAndroid Build Coastguard Worker     mSource->seekTo(seekTimeUs, mode);
2379*ec779b8eSAndroid Build Coastguard Worker     ++mTimedTextGeneration;
2380*ec779b8eSAndroid Build Coastguard Worker 
2381*ec779b8eSAndroid Build Coastguard Worker     // everything's flushed, continue playback.
2382*ec779b8eSAndroid Build Coastguard Worker }
2383*ec779b8eSAndroid Build Coastguard Worker 
performDecoderFlush(FlushCommand audio,FlushCommand video)2384*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::performDecoderFlush(FlushCommand audio, FlushCommand video) {
2385*ec779b8eSAndroid Build Coastguard Worker     ALOGV("performDecoderFlush audio=%d, video=%d", audio, video);
2386*ec779b8eSAndroid Build Coastguard Worker 
2387*ec779b8eSAndroid Build Coastguard Worker     if ((audio == FLUSH_CMD_NONE || mAudioDecoder == NULL)
2388*ec779b8eSAndroid Build Coastguard Worker             && (video == FLUSH_CMD_NONE || mVideoDecoder == NULL)) {
2389*ec779b8eSAndroid Build Coastguard Worker         return;
2390*ec779b8eSAndroid Build Coastguard Worker     }
2391*ec779b8eSAndroid Build Coastguard Worker 
2392*ec779b8eSAndroid Build Coastguard Worker     if (audio != FLUSH_CMD_NONE && mAudioDecoder != NULL) {
2393*ec779b8eSAndroid Build Coastguard Worker         flushDecoder(true /* audio */, (audio == FLUSH_CMD_SHUTDOWN));
2394*ec779b8eSAndroid Build Coastguard Worker     }
2395*ec779b8eSAndroid Build Coastguard Worker 
2396*ec779b8eSAndroid Build Coastguard Worker     if (video != FLUSH_CMD_NONE && mVideoDecoder != NULL) {
2397*ec779b8eSAndroid Build Coastguard Worker         flushDecoder(false /* audio */, (video == FLUSH_CMD_SHUTDOWN));
2398*ec779b8eSAndroid Build Coastguard Worker     }
2399*ec779b8eSAndroid Build Coastguard Worker }
2400*ec779b8eSAndroid Build Coastguard Worker 
performReset()2401*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::performReset() {
2402*ec779b8eSAndroid Build Coastguard Worker     ALOGV("performReset");
2403*ec779b8eSAndroid Build Coastguard Worker 
2404*ec779b8eSAndroid Build Coastguard Worker     CHECK(mAudioDecoder == NULL);
2405*ec779b8eSAndroid Build Coastguard Worker     CHECK(mVideoDecoder == NULL);
2406*ec779b8eSAndroid Build Coastguard Worker 
2407*ec779b8eSAndroid Build Coastguard Worker     updatePlaybackTimer(true /* stopping */, "performReset");
2408*ec779b8eSAndroid Build Coastguard Worker     updateRebufferingTimer(true /* stopping */, true /* exiting */);
2409*ec779b8eSAndroid Build Coastguard Worker 
2410*ec779b8eSAndroid Build Coastguard Worker     cancelPollDuration();
2411*ec779b8eSAndroid Build Coastguard Worker 
2412*ec779b8eSAndroid Build Coastguard Worker     ++mScanSourcesGeneration;
2413*ec779b8eSAndroid Build Coastguard Worker     mScanSourcesPending = false;
2414*ec779b8eSAndroid Build Coastguard Worker 
2415*ec779b8eSAndroid Build Coastguard Worker     if (mRendererLooper != NULL) {
2416*ec779b8eSAndroid Build Coastguard Worker         if (mRenderer != NULL) {
2417*ec779b8eSAndroid Build Coastguard Worker             mRendererLooper->unregisterHandler(mRenderer->id());
2418*ec779b8eSAndroid Build Coastguard Worker         }
2419*ec779b8eSAndroid Build Coastguard Worker         mRendererLooper->stop();
2420*ec779b8eSAndroid Build Coastguard Worker         mRendererLooper.clear();
2421*ec779b8eSAndroid Build Coastguard Worker     }
2422*ec779b8eSAndroid Build Coastguard Worker     mRenderer.clear();
2423*ec779b8eSAndroid Build Coastguard Worker     ++mRendererGeneration;
2424*ec779b8eSAndroid Build Coastguard Worker 
2425*ec779b8eSAndroid Build Coastguard Worker     if (mSource != NULL) {
2426*ec779b8eSAndroid Build Coastguard Worker         mSource->stop();
2427*ec779b8eSAndroid Build Coastguard Worker 
2428*ec779b8eSAndroid Build Coastguard Worker         Mutex::Autolock autoLock(mSourceLock);
2429*ec779b8eSAndroid Build Coastguard Worker         mSource.clear();
2430*ec779b8eSAndroid Build Coastguard Worker     }
2431*ec779b8eSAndroid Build Coastguard Worker 
2432*ec779b8eSAndroid Build Coastguard Worker     if (mDriver != NULL) {
2433*ec779b8eSAndroid Build Coastguard Worker         sp<NuPlayerDriver> driver = mDriver.promote();
2434*ec779b8eSAndroid Build Coastguard Worker         if (driver != NULL) {
2435*ec779b8eSAndroid Build Coastguard Worker             driver->notifyResetComplete();
2436*ec779b8eSAndroid Build Coastguard Worker         }
2437*ec779b8eSAndroid Build Coastguard Worker     }
2438*ec779b8eSAndroid Build Coastguard Worker 
2439*ec779b8eSAndroid Build Coastguard Worker     mStarted = false;
2440*ec779b8eSAndroid Build Coastguard Worker     mPrepared = false;
2441*ec779b8eSAndroid Build Coastguard Worker     mResetting = false;
2442*ec779b8eSAndroid Build Coastguard Worker     mSourceStarted = false;
2443*ec779b8eSAndroid Build Coastguard Worker 
2444*ec779b8eSAndroid Build Coastguard Worker     // Modular DRM
2445*ec779b8eSAndroid Build Coastguard Worker     if (mCrypto != NULL) {
2446*ec779b8eSAndroid Build Coastguard Worker         // decoders will be flushed before this so their mCrypto would go away on their own
2447*ec779b8eSAndroid Build Coastguard Worker         // TODO change to ALOGV
2448*ec779b8eSAndroid Build Coastguard Worker         ALOGD("performReset mCrypto: %p (%d)", mCrypto.get(),
2449*ec779b8eSAndroid Build Coastguard Worker                 (mCrypto != NULL ? mCrypto->getStrongCount() : 0));
2450*ec779b8eSAndroid Build Coastguard Worker         mCrypto.clear();
2451*ec779b8eSAndroid Build Coastguard Worker     }
2452*ec779b8eSAndroid Build Coastguard Worker     mIsDrmProtected = false;
2453*ec779b8eSAndroid Build Coastguard Worker }
2454*ec779b8eSAndroid Build Coastguard Worker 
performScanSources()2455*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::performScanSources() {
2456*ec779b8eSAndroid Build Coastguard Worker     ALOGV("performScanSources");
2457*ec779b8eSAndroid Build Coastguard Worker 
2458*ec779b8eSAndroid Build Coastguard Worker     if (!mStarted) {
2459*ec779b8eSAndroid Build Coastguard Worker         return;
2460*ec779b8eSAndroid Build Coastguard Worker     }
2461*ec779b8eSAndroid Build Coastguard Worker 
2462*ec779b8eSAndroid Build Coastguard Worker     if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
2463*ec779b8eSAndroid Build Coastguard Worker         postScanSources();
2464*ec779b8eSAndroid Build Coastguard Worker     }
2465*ec779b8eSAndroid Build Coastguard Worker }
2466*ec779b8eSAndroid Build Coastguard Worker 
performSetSurface(const sp<Surface> & surface)2467*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::performSetSurface(const sp<Surface> &surface) {
2468*ec779b8eSAndroid Build Coastguard Worker     ALOGV("performSetSurface");
2469*ec779b8eSAndroid Build Coastguard Worker 
2470*ec779b8eSAndroid Build Coastguard Worker     mSurface = surface;
2471*ec779b8eSAndroid Build Coastguard Worker 
2472*ec779b8eSAndroid Build Coastguard Worker     // XXX - ignore error from setVideoScalingMode for now
2473*ec779b8eSAndroid Build Coastguard Worker     setVideoScalingMode(mVideoScalingMode);
2474*ec779b8eSAndroid Build Coastguard Worker 
2475*ec779b8eSAndroid Build Coastguard Worker     if (mDriver != NULL) {
2476*ec779b8eSAndroid Build Coastguard Worker         sp<NuPlayerDriver> driver = mDriver.promote();
2477*ec779b8eSAndroid Build Coastguard Worker         if (driver != NULL) {
2478*ec779b8eSAndroid Build Coastguard Worker             driver->notifySetSurfaceComplete();
2479*ec779b8eSAndroid Build Coastguard Worker         }
2480*ec779b8eSAndroid Build Coastguard Worker     }
2481*ec779b8eSAndroid Build Coastguard Worker }
2482*ec779b8eSAndroid Build Coastguard Worker 
performResumeDecoders(bool needNotify)2483*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::performResumeDecoders(bool needNotify) {
2484*ec779b8eSAndroid Build Coastguard Worker     if (needNotify) {
2485*ec779b8eSAndroid Build Coastguard Worker         mResumePending = true;
2486*ec779b8eSAndroid Build Coastguard Worker         if (mVideoDecoder == NULL) {
2487*ec779b8eSAndroid Build Coastguard Worker             // if audio-only, we can notify seek complete now,
2488*ec779b8eSAndroid Build Coastguard Worker             // as the resume operation will be relatively fast.
2489*ec779b8eSAndroid Build Coastguard Worker             finishResume();
2490*ec779b8eSAndroid Build Coastguard Worker         }
2491*ec779b8eSAndroid Build Coastguard Worker     }
2492*ec779b8eSAndroid Build Coastguard Worker 
2493*ec779b8eSAndroid Build Coastguard Worker     if (mVideoDecoder != NULL) {
2494*ec779b8eSAndroid Build Coastguard Worker         // When there is continuous seek, MediaPlayer will cache the seek
2495*ec779b8eSAndroid Build Coastguard Worker         // position, and send down new seek request when previous seek is
2496*ec779b8eSAndroid Build Coastguard Worker         // complete. Let's wait for at least one video output frame before
2497*ec779b8eSAndroid Build Coastguard Worker         // notifying seek complete, so that the video thumbnail gets updated
2498*ec779b8eSAndroid Build Coastguard Worker         // when seekbar is dragged.
2499*ec779b8eSAndroid Build Coastguard Worker         mVideoDecoder->signalResume(needNotify);
2500*ec779b8eSAndroid Build Coastguard Worker     }
2501*ec779b8eSAndroid Build Coastguard Worker 
2502*ec779b8eSAndroid Build Coastguard Worker     if (mAudioDecoder != NULL) {
2503*ec779b8eSAndroid Build Coastguard Worker         mAudioDecoder->signalResume(false /* needNotify */);
2504*ec779b8eSAndroid Build Coastguard Worker     }
2505*ec779b8eSAndroid Build Coastguard Worker }
2506*ec779b8eSAndroid Build Coastguard Worker 
finishResume()2507*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::finishResume() {
2508*ec779b8eSAndroid Build Coastguard Worker     if (mResumePending) {
2509*ec779b8eSAndroid Build Coastguard Worker         mResumePending = false;
2510*ec779b8eSAndroid Build Coastguard Worker         notifyDriverSeekComplete();
2511*ec779b8eSAndroid Build Coastguard Worker     }
2512*ec779b8eSAndroid Build Coastguard Worker }
2513*ec779b8eSAndroid Build Coastguard Worker 
notifyDriverSeekComplete()2514*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::notifyDriverSeekComplete() {
2515*ec779b8eSAndroid Build Coastguard Worker     if (mDriver != NULL) {
2516*ec779b8eSAndroid Build Coastguard Worker         sp<NuPlayerDriver> driver = mDriver.promote();
2517*ec779b8eSAndroid Build Coastguard Worker         if (driver != NULL) {
2518*ec779b8eSAndroid Build Coastguard Worker             driver->notifySeekComplete();
2519*ec779b8eSAndroid Build Coastguard Worker         }
2520*ec779b8eSAndroid Build Coastguard Worker     }
2521*ec779b8eSAndroid Build Coastguard Worker }
2522*ec779b8eSAndroid Build Coastguard Worker 
onSourceNotify(const sp<AMessage> & msg)2523*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::onSourceNotify(const sp<AMessage> &msg) {
2524*ec779b8eSAndroid Build Coastguard Worker     int32_t what;
2525*ec779b8eSAndroid Build Coastguard Worker     CHECK(msg->findInt32("what", &what));
2526*ec779b8eSAndroid Build Coastguard Worker 
2527*ec779b8eSAndroid Build Coastguard Worker     switch (what) {
2528*ec779b8eSAndroid Build Coastguard Worker         case Source::kWhatInstantiateSecureDecoders:
2529*ec779b8eSAndroid Build Coastguard Worker         {
2530*ec779b8eSAndroid Build Coastguard Worker             if (mSource == NULL) {
2531*ec779b8eSAndroid Build Coastguard Worker                 // This is a stale notification from a source that was
2532*ec779b8eSAndroid Build Coastguard Worker                 // asynchronously preparing when the client called reset().
2533*ec779b8eSAndroid Build Coastguard Worker                 // We handled the reset, the source is gone.
2534*ec779b8eSAndroid Build Coastguard Worker                 break;
2535*ec779b8eSAndroid Build Coastguard Worker             }
2536*ec779b8eSAndroid Build Coastguard Worker 
2537*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> reply;
2538*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findMessage("reply", &reply));
2539*ec779b8eSAndroid Build Coastguard Worker             status_t err = onInstantiateSecureDecoders();
2540*ec779b8eSAndroid Build Coastguard Worker             reply->setInt32("err", err);
2541*ec779b8eSAndroid Build Coastguard Worker             reply->post();
2542*ec779b8eSAndroid Build Coastguard Worker             break;
2543*ec779b8eSAndroid Build Coastguard Worker         }
2544*ec779b8eSAndroid Build Coastguard Worker 
2545*ec779b8eSAndroid Build Coastguard Worker         case Source::kWhatPrepared:
2546*ec779b8eSAndroid Build Coastguard Worker         {
2547*ec779b8eSAndroid Build Coastguard Worker             ALOGV("NuPlayer::onSourceNotify Source::kWhatPrepared source: %p", mSource.get());
2548*ec779b8eSAndroid Build Coastguard Worker             if (mSource == NULL) {
2549*ec779b8eSAndroid Build Coastguard Worker                 // This is a stale notification from a source that was
2550*ec779b8eSAndroid Build Coastguard Worker                 // asynchronously preparing when the client called reset().
2551*ec779b8eSAndroid Build Coastguard Worker                 // We handled the reset, the source is gone.
2552*ec779b8eSAndroid Build Coastguard Worker                 break;
2553*ec779b8eSAndroid Build Coastguard Worker             }
2554*ec779b8eSAndroid Build Coastguard Worker 
2555*ec779b8eSAndroid Build Coastguard Worker             int32_t err;
2556*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("err", &err));
2557*ec779b8eSAndroid Build Coastguard Worker 
2558*ec779b8eSAndroid Build Coastguard Worker             if (err != OK) {
2559*ec779b8eSAndroid Build Coastguard Worker                 // shut down potential secure codecs in case client never calls reset
2560*ec779b8eSAndroid Build Coastguard Worker                 mDeferredActions.push_back(
2561*ec779b8eSAndroid Build Coastguard Worker                         new FlushDecoderAction(FLUSH_CMD_SHUTDOWN /* audio */,
2562*ec779b8eSAndroid Build Coastguard Worker                                                FLUSH_CMD_SHUTDOWN /* video */));
2563*ec779b8eSAndroid Build Coastguard Worker                 processDeferredActions();
2564*ec779b8eSAndroid Build Coastguard Worker             } else {
2565*ec779b8eSAndroid Build Coastguard Worker                 mPrepared = true;
2566*ec779b8eSAndroid Build Coastguard Worker             }
2567*ec779b8eSAndroid Build Coastguard Worker 
2568*ec779b8eSAndroid Build Coastguard Worker             sp<NuPlayerDriver> driver = mDriver.promote();
2569*ec779b8eSAndroid Build Coastguard Worker             if (driver != NULL) {
2570*ec779b8eSAndroid Build Coastguard Worker                 // notify duration first, so that it's definitely set when
2571*ec779b8eSAndroid Build Coastguard Worker                 // the app received the "prepare complete" callback.
2572*ec779b8eSAndroid Build Coastguard Worker                 int64_t durationUs;
2573*ec779b8eSAndroid Build Coastguard Worker                 if (mSource->getDuration(&durationUs) == OK) {
2574*ec779b8eSAndroid Build Coastguard Worker                     driver->notifyDuration(durationUs);
2575*ec779b8eSAndroid Build Coastguard Worker                 }
2576*ec779b8eSAndroid Build Coastguard Worker                 driver->notifyPrepareCompleted(err);
2577*ec779b8eSAndroid Build Coastguard Worker             }
2578*ec779b8eSAndroid Build Coastguard Worker 
2579*ec779b8eSAndroid Build Coastguard Worker             break;
2580*ec779b8eSAndroid Build Coastguard Worker         }
2581*ec779b8eSAndroid Build Coastguard Worker 
2582*ec779b8eSAndroid Build Coastguard Worker         // Modular DRM
2583*ec779b8eSAndroid Build Coastguard Worker         case Source::kWhatDrmInfo:
2584*ec779b8eSAndroid Build Coastguard Worker         {
2585*ec779b8eSAndroid Build Coastguard Worker             Parcel parcel;
2586*ec779b8eSAndroid Build Coastguard Worker             sp<ABuffer> drmInfo;
2587*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findBuffer("drmInfo", &drmInfo));
2588*ec779b8eSAndroid Build Coastguard Worker             parcel.setData(drmInfo->data(), drmInfo->size());
2589*ec779b8eSAndroid Build Coastguard Worker 
2590*ec779b8eSAndroid Build Coastguard Worker             ALOGV("onSourceNotify() kWhatDrmInfo MEDIA_DRM_INFO drmInfo: %p  parcel size: %zu",
2591*ec779b8eSAndroid Build Coastguard Worker                     drmInfo.get(), parcel.dataSize());
2592*ec779b8eSAndroid Build Coastguard Worker 
2593*ec779b8eSAndroid Build Coastguard Worker             notifyListener(MEDIA_DRM_INFO, 0 /* ext1 */, 0 /* ext2 */, &parcel);
2594*ec779b8eSAndroid Build Coastguard Worker 
2595*ec779b8eSAndroid Build Coastguard Worker             break;
2596*ec779b8eSAndroid Build Coastguard Worker         }
2597*ec779b8eSAndroid Build Coastguard Worker 
2598*ec779b8eSAndroid Build Coastguard Worker         case Source::kWhatFlagsChanged:
2599*ec779b8eSAndroid Build Coastguard Worker         {
2600*ec779b8eSAndroid Build Coastguard Worker             uint32_t flags;
2601*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("flags", (int32_t *)&flags));
2602*ec779b8eSAndroid Build Coastguard Worker 
2603*ec779b8eSAndroid Build Coastguard Worker             sp<NuPlayerDriver> driver = mDriver.promote();
2604*ec779b8eSAndroid Build Coastguard Worker             if (driver != NULL) {
2605*ec779b8eSAndroid Build Coastguard Worker 
2606*ec779b8eSAndroid Build Coastguard Worker                 ALOGV("onSourceNotify() kWhatFlagsChanged  FLAG_CAN_PAUSE: %d  "
2607*ec779b8eSAndroid Build Coastguard Worker                         "FLAG_CAN_SEEK_BACKWARD: %d \n\t\t\t\t FLAG_CAN_SEEK_FORWARD: %d  "
2608*ec779b8eSAndroid Build Coastguard Worker                         "FLAG_CAN_SEEK: %d  FLAG_DYNAMIC_DURATION: %d \n"
2609*ec779b8eSAndroid Build Coastguard Worker                         "\t\t\t\t FLAG_SECURE: %d  FLAG_PROTECTED: %d",
2610*ec779b8eSAndroid Build Coastguard Worker                         (flags & Source::FLAG_CAN_PAUSE) != 0,
2611*ec779b8eSAndroid Build Coastguard Worker                         (flags & Source::FLAG_CAN_SEEK_BACKWARD) != 0,
2612*ec779b8eSAndroid Build Coastguard Worker                         (flags & Source::FLAG_CAN_SEEK_FORWARD) != 0,
2613*ec779b8eSAndroid Build Coastguard Worker                         (flags & Source::FLAG_CAN_SEEK) != 0,
2614*ec779b8eSAndroid Build Coastguard Worker                         (flags & Source::FLAG_DYNAMIC_DURATION) != 0,
2615*ec779b8eSAndroid Build Coastguard Worker                         (flags & Source::FLAG_SECURE) != 0,
2616*ec779b8eSAndroid Build Coastguard Worker                         (flags & Source::FLAG_PROTECTED) != 0);
2617*ec779b8eSAndroid Build Coastguard Worker 
2618*ec779b8eSAndroid Build Coastguard Worker                 if ((flags & NuPlayer::Source::FLAG_CAN_SEEK) == 0) {
2619*ec779b8eSAndroid Build Coastguard Worker                     driver->notifyListener(
2620*ec779b8eSAndroid Build Coastguard Worker                             MEDIA_INFO, MEDIA_INFO_NOT_SEEKABLE, 0);
2621*ec779b8eSAndroid Build Coastguard Worker                 }
2622*ec779b8eSAndroid Build Coastguard Worker                 driver->notifyFlagsChanged(flags);
2623*ec779b8eSAndroid Build Coastguard Worker             }
2624*ec779b8eSAndroid Build Coastguard Worker 
2625*ec779b8eSAndroid Build Coastguard Worker             if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
2626*ec779b8eSAndroid Build Coastguard Worker                     && (!(flags & Source::FLAG_DYNAMIC_DURATION))) {
2627*ec779b8eSAndroid Build Coastguard Worker                 cancelPollDuration();
2628*ec779b8eSAndroid Build Coastguard Worker             } else if (!(mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
2629*ec779b8eSAndroid Build Coastguard Worker                     && (flags & Source::FLAG_DYNAMIC_DURATION)
2630*ec779b8eSAndroid Build Coastguard Worker                     && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
2631*ec779b8eSAndroid Build Coastguard Worker                 schedulePollDuration();
2632*ec779b8eSAndroid Build Coastguard Worker             }
2633*ec779b8eSAndroid Build Coastguard Worker 
2634*ec779b8eSAndroid Build Coastguard Worker             mSourceFlags = flags;
2635*ec779b8eSAndroid Build Coastguard Worker             break;
2636*ec779b8eSAndroid Build Coastguard Worker         }
2637*ec779b8eSAndroid Build Coastguard Worker 
2638*ec779b8eSAndroid Build Coastguard Worker         case Source::kWhatVideoSizeChanged:
2639*ec779b8eSAndroid Build Coastguard Worker         {
2640*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> format;
2641*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findMessage("format", &format));
2642*ec779b8eSAndroid Build Coastguard Worker 
2643*ec779b8eSAndroid Build Coastguard Worker             updateVideoSize(format);
2644*ec779b8eSAndroid Build Coastguard Worker             break;
2645*ec779b8eSAndroid Build Coastguard Worker         }
2646*ec779b8eSAndroid Build Coastguard Worker 
2647*ec779b8eSAndroid Build Coastguard Worker         case Source::kWhatBufferingUpdate:
2648*ec779b8eSAndroid Build Coastguard Worker         {
2649*ec779b8eSAndroid Build Coastguard Worker             int32_t percentage;
2650*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("percentage", &percentage));
2651*ec779b8eSAndroid Build Coastguard Worker 
2652*ec779b8eSAndroid Build Coastguard Worker             notifyListener(MEDIA_BUFFERING_UPDATE, percentage, 0);
2653*ec779b8eSAndroid Build Coastguard Worker             break;
2654*ec779b8eSAndroid Build Coastguard Worker         }
2655*ec779b8eSAndroid Build Coastguard Worker 
2656*ec779b8eSAndroid Build Coastguard Worker         case Source::kWhatPauseOnBufferingStart:
2657*ec779b8eSAndroid Build Coastguard Worker         {
2658*ec779b8eSAndroid Build Coastguard Worker             // ignore if not playing
2659*ec779b8eSAndroid Build Coastguard Worker             if (mStarted) {
2660*ec779b8eSAndroid Build Coastguard Worker                 ALOGI("buffer low, pausing...");
2661*ec779b8eSAndroid Build Coastguard Worker 
2662*ec779b8eSAndroid Build Coastguard Worker                 startRebufferingTimer();
2663*ec779b8eSAndroid Build Coastguard Worker                 mPausedForBuffering = true;
2664*ec779b8eSAndroid Build Coastguard Worker                 onPause();
2665*ec779b8eSAndroid Build Coastguard Worker             }
2666*ec779b8eSAndroid Build Coastguard Worker             notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0);
2667*ec779b8eSAndroid Build Coastguard Worker             break;
2668*ec779b8eSAndroid Build Coastguard Worker         }
2669*ec779b8eSAndroid Build Coastguard Worker 
2670*ec779b8eSAndroid Build Coastguard Worker         case Source::kWhatResumeOnBufferingEnd:
2671*ec779b8eSAndroid Build Coastguard Worker         {
2672*ec779b8eSAndroid Build Coastguard Worker             // ignore if not playing
2673*ec779b8eSAndroid Build Coastguard Worker             if (mStarted) {
2674*ec779b8eSAndroid Build Coastguard Worker                 ALOGI("buffer ready, resuming...");
2675*ec779b8eSAndroid Build Coastguard Worker 
2676*ec779b8eSAndroid Build Coastguard Worker                 updateRebufferingTimer(true /* stopping */, false /* exiting */);
2677*ec779b8eSAndroid Build Coastguard Worker                 mPausedForBuffering = false;
2678*ec779b8eSAndroid Build Coastguard Worker 
2679*ec779b8eSAndroid Build Coastguard Worker                 // do not resume yet if client didn't unpause
2680*ec779b8eSAndroid Build Coastguard Worker                 if (!mPausedByClient) {
2681*ec779b8eSAndroid Build Coastguard Worker                     onResume();
2682*ec779b8eSAndroid Build Coastguard Worker                 }
2683*ec779b8eSAndroid Build Coastguard Worker             }
2684*ec779b8eSAndroid Build Coastguard Worker             notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0);
2685*ec779b8eSAndroid Build Coastguard Worker             break;
2686*ec779b8eSAndroid Build Coastguard Worker         }
2687*ec779b8eSAndroid Build Coastguard Worker 
2688*ec779b8eSAndroid Build Coastguard Worker         case Source::kWhatCacheStats:
2689*ec779b8eSAndroid Build Coastguard Worker         {
2690*ec779b8eSAndroid Build Coastguard Worker             int32_t kbps;
2691*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("bandwidth", &kbps));
2692*ec779b8eSAndroid Build Coastguard Worker 
2693*ec779b8eSAndroid Build Coastguard Worker             notifyListener(MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
2694*ec779b8eSAndroid Build Coastguard Worker             break;
2695*ec779b8eSAndroid Build Coastguard Worker         }
2696*ec779b8eSAndroid Build Coastguard Worker 
2697*ec779b8eSAndroid Build Coastguard Worker         case Source::kWhatSubtitleData:
2698*ec779b8eSAndroid Build Coastguard Worker         {
2699*ec779b8eSAndroid Build Coastguard Worker             sp<ABuffer> buffer;
2700*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findBuffer("buffer", &buffer));
2701*ec779b8eSAndroid Build Coastguard Worker 
2702*ec779b8eSAndroid Build Coastguard Worker             sendSubtitleData(buffer, 0 /* baseIndex */);
2703*ec779b8eSAndroid Build Coastguard Worker             break;
2704*ec779b8eSAndroid Build Coastguard Worker         }
2705*ec779b8eSAndroid Build Coastguard Worker 
2706*ec779b8eSAndroid Build Coastguard Worker         case Source::kWhatTimedMetaData:
2707*ec779b8eSAndroid Build Coastguard Worker         {
2708*ec779b8eSAndroid Build Coastguard Worker             sp<ABuffer> buffer;
2709*ec779b8eSAndroid Build Coastguard Worker             if (!msg->findBuffer("buffer", &buffer)) {
2710*ec779b8eSAndroid Build Coastguard Worker                 notifyListener(MEDIA_INFO, MEDIA_INFO_METADATA_UPDATE, 0);
2711*ec779b8eSAndroid Build Coastguard Worker             } else {
2712*ec779b8eSAndroid Build Coastguard Worker                 sendTimedMetaData(buffer);
2713*ec779b8eSAndroid Build Coastguard Worker             }
2714*ec779b8eSAndroid Build Coastguard Worker             break;
2715*ec779b8eSAndroid Build Coastguard Worker         }
2716*ec779b8eSAndroid Build Coastguard Worker 
2717*ec779b8eSAndroid Build Coastguard Worker         case Source::kWhatTimedTextData:
2718*ec779b8eSAndroid Build Coastguard Worker         {
2719*ec779b8eSAndroid Build Coastguard Worker             int32_t generation;
2720*ec779b8eSAndroid Build Coastguard Worker             if (msg->findInt32("generation", &generation)
2721*ec779b8eSAndroid Build Coastguard Worker                     && generation != mTimedTextGeneration) {
2722*ec779b8eSAndroid Build Coastguard Worker                 break;
2723*ec779b8eSAndroid Build Coastguard Worker             }
2724*ec779b8eSAndroid Build Coastguard Worker 
2725*ec779b8eSAndroid Build Coastguard Worker             sp<ABuffer> buffer;
2726*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findBuffer("buffer", &buffer));
2727*ec779b8eSAndroid Build Coastguard Worker 
2728*ec779b8eSAndroid Build Coastguard Worker             sp<NuPlayerDriver> driver = mDriver.promote();
2729*ec779b8eSAndroid Build Coastguard Worker             if (driver == NULL) {
2730*ec779b8eSAndroid Build Coastguard Worker                 break;
2731*ec779b8eSAndroid Build Coastguard Worker             }
2732*ec779b8eSAndroid Build Coastguard Worker 
2733*ec779b8eSAndroid Build Coastguard Worker             int posMs;
2734*ec779b8eSAndroid Build Coastguard Worker             int64_t timeUs, posUs;
2735*ec779b8eSAndroid Build Coastguard Worker             driver->getCurrentPosition(&posMs);
2736*ec779b8eSAndroid Build Coastguard Worker             posUs = (int64_t) posMs * 1000LL;
2737*ec779b8eSAndroid Build Coastguard Worker             CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2738*ec779b8eSAndroid Build Coastguard Worker 
2739*ec779b8eSAndroid Build Coastguard Worker             if (posUs < timeUs) {
2740*ec779b8eSAndroid Build Coastguard Worker                 if (!msg->findInt32("generation", &generation)) {
2741*ec779b8eSAndroid Build Coastguard Worker                     msg->setInt32("generation", mTimedTextGeneration);
2742*ec779b8eSAndroid Build Coastguard Worker                 }
2743*ec779b8eSAndroid Build Coastguard Worker                 msg->post(timeUs - posUs);
2744*ec779b8eSAndroid Build Coastguard Worker             } else {
2745*ec779b8eSAndroid Build Coastguard Worker                 sendTimedTextData(buffer);
2746*ec779b8eSAndroid Build Coastguard Worker             }
2747*ec779b8eSAndroid Build Coastguard Worker             break;
2748*ec779b8eSAndroid Build Coastguard Worker         }
2749*ec779b8eSAndroid Build Coastguard Worker 
2750*ec779b8eSAndroid Build Coastguard Worker         case Source::kWhatQueueDecoderShutdown:
2751*ec779b8eSAndroid Build Coastguard Worker         {
2752*ec779b8eSAndroid Build Coastguard Worker             int32_t audio, video;
2753*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("audio", &audio));
2754*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("video", &video));
2755*ec779b8eSAndroid Build Coastguard Worker 
2756*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> reply;
2757*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findMessage("reply", &reply));
2758*ec779b8eSAndroid Build Coastguard Worker 
2759*ec779b8eSAndroid Build Coastguard Worker             queueDecoderShutdown(audio, video, reply);
2760*ec779b8eSAndroid Build Coastguard Worker             break;
2761*ec779b8eSAndroid Build Coastguard Worker         }
2762*ec779b8eSAndroid Build Coastguard Worker 
2763*ec779b8eSAndroid Build Coastguard Worker         case Source::kWhatDrmNoLicense:
2764*ec779b8eSAndroid Build Coastguard Worker         {
2765*ec779b8eSAndroid Build Coastguard Worker             notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
2766*ec779b8eSAndroid Build Coastguard Worker             break;
2767*ec779b8eSAndroid Build Coastguard Worker         }
2768*ec779b8eSAndroid Build Coastguard Worker 
2769*ec779b8eSAndroid Build Coastguard Worker         case Source::kWhatIMSRxNotice:
2770*ec779b8eSAndroid Build Coastguard Worker         {
2771*ec779b8eSAndroid Build Coastguard Worker             sp<AMessage> IMSRxNotice;
2772*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findMessage("message", &IMSRxNotice));
2773*ec779b8eSAndroid Build Coastguard Worker             sendIMSRxNotice(IMSRxNotice);
2774*ec779b8eSAndroid Build Coastguard Worker             break;
2775*ec779b8eSAndroid Build Coastguard Worker         }
2776*ec779b8eSAndroid Build Coastguard Worker 
2777*ec779b8eSAndroid Build Coastguard Worker         default:
2778*ec779b8eSAndroid Build Coastguard Worker             TRESPASS();
2779*ec779b8eSAndroid Build Coastguard Worker     }
2780*ec779b8eSAndroid Build Coastguard Worker }
2781*ec779b8eSAndroid Build Coastguard Worker 
onClosedCaptionNotify(const sp<AMessage> & msg)2782*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::onClosedCaptionNotify(const sp<AMessage> &msg) {
2783*ec779b8eSAndroid Build Coastguard Worker     int32_t what;
2784*ec779b8eSAndroid Build Coastguard Worker     CHECK(msg->findInt32("what", &what));
2785*ec779b8eSAndroid Build Coastguard Worker 
2786*ec779b8eSAndroid Build Coastguard Worker     switch (what) {
2787*ec779b8eSAndroid Build Coastguard Worker         case NuPlayer::CCDecoder::kWhatClosedCaptionData:
2788*ec779b8eSAndroid Build Coastguard Worker         {
2789*ec779b8eSAndroid Build Coastguard Worker             sp<ABuffer> buffer;
2790*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findBuffer("buffer", &buffer));
2791*ec779b8eSAndroid Build Coastguard Worker 
2792*ec779b8eSAndroid Build Coastguard Worker             size_t inbandTracks = 0;
2793*ec779b8eSAndroid Build Coastguard Worker             if (mSource != NULL) {
2794*ec779b8eSAndroid Build Coastguard Worker                 inbandTracks = mSource->getTrackCount();
2795*ec779b8eSAndroid Build Coastguard Worker             }
2796*ec779b8eSAndroid Build Coastguard Worker 
2797*ec779b8eSAndroid Build Coastguard Worker             sendSubtitleData(buffer, inbandTracks);
2798*ec779b8eSAndroid Build Coastguard Worker             break;
2799*ec779b8eSAndroid Build Coastguard Worker         }
2800*ec779b8eSAndroid Build Coastguard Worker 
2801*ec779b8eSAndroid Build Coastguard Worker         case NuPlayer::CCDecoder::kWhatTrackAdded:
2802*ec779b8eSAndroid Build Coastguard Worker         {
2803*ec779b8eSAndroid Build Coastguard Worker             notifyListener(MEDIA_INFO, MEDIA_INFO_METADATA_UPDATE, 0);
2804*ec779b8eSAndroid Build Coastguard Worker 
2805*ec779b8eSAndroid Build Coastguard Worker             break;
2806*ec779b8eSAndroid Build Coastguard Worker         }
2807*ec779b8eSAndroid Build Coastguard Worker 
2808*ec779b8eSAndroid Build Coastguard Worker         default:
2809*ec779b8eSAndroid Build Coastguard Worker             TRESPASS();
2810*ec779b8eSAndroid Build Coastguard Worker     }
2811*ec779b8eSAndroid Build Coastguard Worker 
2812*ec779b8eSAndroid Build Coastguard Worker 
2813*ec779b8eSAndroid Build Coastguard Worker }
2814*ec779b8eSAndroid Build Coastguard Worker 
sendSubtitleData(const sp<ABuffer> & buffer,int32_t baseIndex)2815*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::sendSubtitleData(const sp<ABuffer> &buffer, int32_t baseIndex) {
2816*ec779b8eSAndroid Build Coastguard Worker     int32_t trackIndex;
2817*ec779b8eSAndroid Build Coastguard Worker     int64_t timeUs, durationUs;
2818*ec779b8eSAndroid Build Coastguard Worker     CHECK(buffer->meta()->findInt32("track-index", &trackIndex));
2819*ec779b8eSAndroid Build Coastguard Worker     CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2820*ec779b8eSAndroid Build Coastguard Worker     CHECK(buffer->meta()->findInt64("durationUs", &durationUs));
2821*ec779b8eSAndroid Build Coastguard Worker 
2822*ec779b8eSAndroid Build Coastguard Worker     Parcel in;
2823*ec779b8eSAndroid Build Coastguard Worker     in.writeInt32(trackIndex + baseIndex);
2824*ec779b8eSAndroid Build Coastguard Worker     in.writeInt64(timeUs);
2825*ec779b8eSAndroid Build Coastguard Worker     in.writeInt64(durationUs);
2826*ec779b8eSAndroid Build Coastguard Worker     in.writeInt32(buffer->size());
2827*ec779b8eSAndroid Build Coastguard Worker     in.writeInt32(buffer->size());
2828*ec779b8eSAndroid Build Coastguard Worker     in.write(buffer->data(), buffer->size());
2829*ec779b8eSAndroid Build Coastguard Worker 
2830*ec779b8eSAndroid Build Coastguard Worker     notifyListener(MEDIA_SUBTITLE_DATA, 0, 0, &in);
2831*ec779b8eSAndroid Build Coastguard Worker }
2832*ec779b8eSAndroid Build Coastguard Worker 
sendTimedMetaData(const sp<ABuffer> & buffer)2833*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::sendTimedMetaData(const sp<ABuffer> &buffer) {
2834*ec779b8eSAndroid Build Coastguard Worker     int64_t timeUs;
2835*ec779b8eSAndroid Build Coastguard Worker     CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2836*ec779b8eSAndroid Build Coastguard Worker 
2837*ec779b8eSAndroid Build Coastguard Worker     Parcel in;
2838*ec779b8eSAndroid Build Coastguard Worker     in.writeInt64(timeUs);
2839*ec779b8eSAndroid Build Coastguard Worker     in.writeInt32(buffer->size());
2840*ec779b8eSAndroid Build Coastguard Worker     in.writeInt32(buffer->size());
2841*ec779b8eSAndroid Build Coastguard Worker     in.write(buffer->data(), buffer->size());
2842*ec779b8eSAndroid Build Coastguard Worker 
2843*ec779b8eSAndroid Build Coastguard Worker     notifyListener(MEDIA_META_DATA, 0, 0, &in);
2844*ec779b8eSAndroid Build Coastguard Worker }
2845*ec779b8eSAndroid Build Coastguard Worker 
sendTimedTextData(const sp<ABuffer> & buffer)2846*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::sendTimedTextData(const sp<ABuffer> &buffer) {
2847*ec779b8eSAndroid Build Coastguard Worker     const void *data;
2848*ec779b8eSAndroid Build Coastguard Worker     size_t size = 0;
2849*ec779b8eSAndroid Build Coastguard Worker     int64_t timeUs;
2850*ec779b8eSAndroid Build Coastguard Worker     int32_t flag = TextDescriptions::IN_BAND_TEXT_3GPP;
2851*ec779b8eSAndroid Build Coastguard Worker 
2852*ec779b8eSAndroid Build Coastguard Worker     AString mime;
2853*ec779b8eSAndroid Build Coastguard Worker     CHECK(buffer->meta()->findString("mime", &mime));
2854*ec779b8eSAndroid Build Coastguard Worker     CHECK(strcasecmp(mime.c_str(), MEDIA_MIMETYPE_TEXT_3GPP) == 0);
2855*ec779b8eSAndroid Build Coastguard Worker 
2856*ec779b8eSAndroid Build Coastguard Worker     data = buffer->data();
2857*ec779b8eSAndroid Build Coastguard Worker     size = buffer->size();
2858*ec779b8eSAndroid Build Coastguard Worker 
2859*ec779b8eSAndroid Build Coastguard Worker     Parcel parcel;
2860*ec779b8eSAndroid Build Coastguard Worker     if (size > 0) {
2861*ec779b8eSAndroid Build Coastguard Worker         CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2862*ec779b8eSAndroid Build Coastguard Worker         int32_t global = 0;
2863*ec779b8eSAndroid Build Coastguard Worker         if (buffer->meta()->findInt32("global", &global) && global) {
2864*ec779b8eSAndroid Build Coastguard Worker             flag |= TextDescriptions::GLOBAL_DESCRIPTIONS;
2865*ec779b8eSAndroid Build Coastguard Worker         } else {
2866*ec779b8eSAndroid Build Coastguard Worker             flag |= TextDescriptions::LOCAL_DESCRIPTIONS;
2867*ec779b8eSAndroid Build Coastguard Worker         }
2868*ec779b8eSAndroid Build Coastguard Worker         TextDescriptions::getParcelOfDescriptions(
2869*ec779b8eSAndroid Build Coastguard Worker                 (const uint8_t *)data, size, flag, timeUs / 1000, &parcel);
2870*ec779b8eSAndroid Build Coastguard Worker     }
2871*ec779b8eSAndroid Build Coastguard Worker 
2872*ec779b8eSAndroid Build Coastguard Worker     if ((parcel.dataSize() > 0)) {
2873*ec779b8eSAndroid Build Coastguard Worker         notifyListener(MEDIA_TIMED_TEXT, 0, 0, &parcel);
2874*ec779b8eSAndroid Build Coastguard Worker     } else {  // send an empty timed text
2875*ec779b8eSAndroid Build Coastguard Worker         notifyListener(MEDIA_TIMED_TEXT, 0, 0);
2876*ec779b8eSAndroid Build Coastguard Worker     }
2877*ec779b8eSAndroid Build Coastguard Worker }
2878*ec779b8eSAndroid Build Coastguard Worker 
sendIMSRxNotice(const sp<AMessage> & msg)2879*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::sendIMSRxNotice(const sp<AMessage> &msg) {
2880*ec779b8eSAndroid Build Coastguard Worker     int32_t payloadType;
2881*ec779b8eSAndroid Build Coastguard Worker 
2882*ec779b8eSAndroid Build Coastguard Worker     CHECK(msg->findInt32("payload-type", &payloadType));
2883*ec779b8eSAndroid Build Coastguard Worker 
2884*ec779b8eSAndroid Build Coastguard Worker     int32_t rtpSeq = 0, rtpTime = 0;
2885*ec779b8eSAndroid Build Coastguard Worker     int64_t ntpTime = 0, recvTimeUs = 0;
2886*ec779b8eSAndroid Build Coastguard Worker 
2887*ec779b8eSAndroid Build Coastguard Worker     Parcel in;
2888*ec779b8eSAndroid Build Coastguard Worker     in.writeInt32(payloadType);
2889*ec779b8eSAndroid Build Coastguard Worker 
2890*ec779b8eSAndroid Build Coastguard Worker     switch (payloadType) {
2891*ec779b8eSAndroid Build Coastguard Worker         case ARTPSource::RTP_FIRST_PACKET:
2892*ec779b8eSAndroid Build Coastguard Worker         {
2893*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("rtp-time", &rtpTime));
2894*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("rtp-seq-num", &rtpSeq));
2895*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt64("recv-time-us", &recvTimeUs));
2896*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(rtpTime);
2897*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(rtpSeq);
2898*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(recvTimeUs >> 32);
2899*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(recvTimeUs & 0xFFFFFFFF);
2900*ec779b8eSAndroid Build Coastguard Worker             break;
2901*ec779b8eSAndroid Build Coastguard Worker         }
2902*ec779b8eSAndroid Build Coastguard Worker         case ARTPSource::RTCP_FIRST_PACKET:
2903*ec779b8eSAndroid Build Coastguard Worker         {
2904*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt64("recv-time-us", &recvTimeUs));
2905*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(recvTimeUs >> 32);
2906*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(recvTimeUs & 0xFFFFFFFF);
2907*ec779b8eSAndroid Build Coastguard Worker             break;
2908*ec779b8eSAndroid Build Coastguard Worker         }
2909*ec779b8eSAndroid Build Coastguard Worker         case ARTPSource::RTCP_SR:
2910*ec779b8eSAndroid Build Coastguard Worker         {
2911*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("rtp-time", &rtpTime));
2912*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt64("ntp-time", &ntpTime));
2913*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt64("recv-time-us", &recvTimeUs));
2914*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(rtpTime);
2915*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(ntpTime >> 32);
2916*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(ntpTime & 0xFFFFFFFF);
2917*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(recvTimeUs >> 32);
2918*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(recvTimeUs & 0xFFFFFFFF);
2919*ec779b8eSAndroid Build Coastguard Worker             break;
2920*ec779b8eSAndroid Build Coastguard Worker         }
2921*ec779b8eSAndroid Build Coastguard Worker         case ARTPSource::RTCP_RR:
2922*ec779b8eSAndroid Build Coastguard Worker         {
2923*ec779b8eSAndroid Build Coastguard Worker             int64_t recvTimeUs;
2924*ec779b8eSAndroid Build Coastguard Worker             int32_t senderId;
2925*ec779b8eSAndroid Build Coastguard Worker             int32_t ssrc;
2926*ec779b8eSAndroid Build Coastguard Worker             int32_t fraction;
2927*ec779b8eSAndroid Build Coastguard Worker             int32_t lost;
2928*ec779b8eSAndroid Build Coastguard Worker             int32_t lastSeq;
2929*ec779b8eSAndroid Build Coastguard Worker             int32_t jitter;
2930*ec779b8eSAndroid Build Coastguard Worker             int32_t lsr;
2931*ec779b8eSAndroid Build Coastguard Worker             int32_t dlsr;
2932*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt64("recv-time-us", &recvTimeUs));
2933*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("rtcp-rr-ssrc", &senderId));
2934*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("rtcp-rrb-ssrc", &ssrc));
2935*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("rtcp-rrb-fraction", &fraction));
2936*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("rtcp-rrb-lost", &lost));
2937*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("rtcp-rrb-lastSeq", &lastSeq));
2938*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("rtcp-rrb-jitter", &jitter));
2939*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("rtcp-rrb-lsr", &lsr));
2940*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("rtcp-rrb-dlsr", &dlsr));
2941*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(recvTimeUs >> 32);
2942*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(recvTimeUs & 0xFFFFFFFF);
2943*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(senderId);
2944*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(ssrc);
2945*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(fraction);
2946*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(lost);
2947*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(lastSeq);
2948*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(jitter);
2949*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(lsr);
2950*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(dlsr);
2951*ec779b8eSAndroid Build Coastguard Worker             break;
2952*ec779b8eSAndroid Build Coastguard Worker         }
2953*ec779b8eSAndroid Build Coastguard Worker         case ARTPSource::RTCP_TSFB:   // RTCP TSFB
2954*ec779b8eSAndroid Build Coastguard Worker         case ARTPSource::RTCP_PSFB:   // RTCP PSFB
2955*ec779b8eSAndroid Build Coastguard Worker         case ARTPSource::RTP_AUTODOWN:
2956*ec779b8eSAndroid Build Coastguard Worker         {
2957*ec779b8eSAndroid Build Coastguard Worker             int32_t feedbackType, id;
2958*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("feedback-type", &feedbackType));
2959*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("sender", &id));
2960*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(feedbackType);
2961*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(id);
2962*ec779b8eSAndroid Build Coastguard Worker             if (payloadType == ARTPSource::RTCP_TSFB) {
2963*ec779b8eSAndroid Build Coastguard Worker                 int32_t bitrate;
2964*ec779b8eSAndroid Build Coastguard Worker                 CHECK(msg->findInt32("bit-rate", &bitrate));
2965*ec779b8eSAndroid Build Coastguard Worker                 in.writeInt32(bitrate);
2966*ec779b8eSAndroid Build Coastguard Worker             }
2967*ec779b8eSAndroid Build Coastguard Worker             break;
2968*ec779b8eSAndroid Build Coastguard Worker         }
2969*ec779b8eSAndroid Build Coastguard Worker         case ARTPSource::RTP_QUALITY:
2970*ec779b8eSAndroid Build Coastguard Worker         case ARTPSource::RTP_QUALITY_EMC:
2971*ec779b8eSAndroid Build Coastguard Worker         {
2972*ec779b8eSAndroid Build Coastguard Worker             int32_t feedbackType, bitrate;
2973*ec779b8eSAndroid Build Coastguard Worker             int32_t highestSeqNum, baseSeqNum, prevExpected;
2974*ec779b8eSAndroid Build Coastguard Worker             int32_t numBufRecv, prevNumBufRecv;
2975*ec779b8eSAndroid Build Coastguard Worker             int32_t latestRtpTime, jbTimeMs, rtpRtcpSrTimeGapMs;
2976*ec779b8eSAndroid Build Coastguard Worker             int64_t recvTimeUs;
2977*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("feedback-type", &feedbackType));
2978*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("bit-rate", &bitrate));
2979*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("highest-seq-num", &highestSeqNum));
2980*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("base-seq-num", &baseSeqNum));
2981*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("prev-expected", &prevExpected));
2982*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("num-buf-recv", &numBufRecv));
2983*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("prev-num-buf-recv", &prevNumBufRecv));
2984*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("latest-rtp-time", &latestRtpTime));
2985*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt64("recv-time-us", &recvTimeUs));
2986*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("rtp-jitter-time-ms", &jbTimeMs));
2987*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("rtp-rtcpsr-time-gap-ms", &rtpRtcpSrTimeGapMs));
2988*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(feedbackType);
2989*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(bitrate);
2990*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(highestSeqNum);
2991*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(baseSeqNum);
2992*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(prevExpected);
2993*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(numBufRecv);
2994*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(prevNumBufRecv);
2995*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(latestRtpTime);
2996*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(recvTimeUs >> 32);
2997*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(recvTimeUs & 0xFFFFFFFF);
2998*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(jbTimeMs);
2999*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(rtpRtcpSrTimeGapMs);
3000*ec779b8eSAndroid Build Coastguard Worker             break;
3001*ec779b8eSAndroid Build Coastguard Worker         }
3002*ec779b8eSAndroid Build Coastguard Worker         case ARTPSource::RTP_CVO:
3003*ec779b8eSAndroid Build Coastguard Worker         {
3004*ec779b8eSAndroid Build Coastguard Worker             int32_t cvo;
3005*ec779b8eSAndroid Build Coastguard Worker             CHECK(msg->findInt32("cvo", &cvo));
3006*ec779b8eSAndroid Build Coastguard Worker             in.writeInt32(cvo);
3007*ec779b8eSAndroid Build Coastguard Worker             break;
3008*ec779b8eSAndroid Build Coastguard Worker         }
3009*ec779b8eSAndroid Build Coastguard Worker         default:
3010*ec779b8eSAndroid Build Coastguard Worker         break;
3011*ec779b8eSAndroid Build Coastguard Worker     }
3012*ec779b8eSAndroid Build Coastguard Worker 
3013*ec779b8eSAndroid Build Coastguard Worker     notifyListener(MEDIA_IMS_RX_NOTICE, 0, 0, &in);
3014*ec779b8eSAndroid Build Coastguard Worker }
3015*ec779b8eSAndroid Build Coastguard Worker 
getDataSourceType()3016*ec779b8eSAndroid Build Coastguard Worker const char *NuPlayer::getDataSourceType() {
3017*ec779b8eSAndroid Build Coastguard Worker     switch (mDataSourceType) {
3018*ec779b8eSAndroid Build Coastguard Worker         case DATA_SOURCE_TYPE_HTTP_LIVE:
3019*ec779b8eSAndroid Build Coastguard Worker             return "HTTPLive";
3020*ec779b8eSAndroid Build Coastguard Worker 
3021*ec779b8eSAndroid Build Coastguard Worker         case DATA_SOURCE_TYPE_RTP:
3022*ec779b8eSAndroid Build Coastguard Worker             return "RTP";
3023*ec779b8eSAndroid Build Coastguard Worker 
3024*ec779b8eSAndroid Build Coastguard Worker         case DATA_SOURCE_TYPE_RTSP:
3025*ec779b8eSAndroid Build Coastguard Worker             return "RTSP";
3026*ec779b8eSAndroid Build Coastguard Worker 
3027*ec779b8eSAndroid Build Coastguard Worker         case DATA_SOURCE_TYPE_GENERIC_URL:
3028*ec779b8eSAndroid Build Coastguard Worker             return "GenURL";
3029*ec779b8eSAndroid Build Coastguard Worker 
3030*ec779b8eSAndroid Build Coastguard Worker         case DATA_SOURCE_TYPE_GENERIC_FD:
3031*ec779b8eSAndroid Build Coastguard Worker             return "GenFD";
3032*ec779b8eSAndroid Build Coastguard Worker 
3033*ec779b8eSAndroid Build Coastguard Worker         case DATA_SOURCE_TYPE_MEDIA:
3034*ec779b8eSAndroid Build Coastguard Worker             return "Media";
3035*ec779b8eSAndroid Build Coastguard Worker 
3036*ec779b8eSAndroid Build Coastguard Worker         case DATA_SOURCE_TYPE_STREAM:
3037*ec779b8eSAndroid Build Coastguard Worker             return "Stream";
3038*ec779b8eSAndroid Build Coastguard Worker 
3039*ec779b8eSAndroid Build Coastguard Worker         case DATA_SOURCE_TYPE_NONE:
3040*ec779b8eSAndroid Build Coastguard Worker         default:
3041*ec779b8eSAndroid Build Coastguard Worker             return "None";
3042*ec779b8eSAndroid Build Coastguard Worker     }
3043*ec779b8eSAndroid Build Coastguard Worker  }
3044*ec779b8eSAndroid Build Coastguard Worker 
dump(AString & logString)3045*ec779b8eSAndroid Build Coastguard Worker  void NuPlayer::dump(AString& logString) {
3046*ec779b8eSAndroid Build Coastguard Worker     logString.append("renderer(");
3047*ec779b8eSAndroid Build Coastguard Worker     if (mRenderer != nullptr) {
3048*ec779b8eSAndroid Build Coastguard Worker         mRenderer->dump(logString);
3049*ec779b8eSAndroid Build Coastguard Worker     } else {
3050*ec779b8eSAndroid Build Coastguard Worker         logString.append("null");
3051*ec779b8eSAndroid Build Coastguard Worker     }
3052*ec779b8eSAndroid Build Coastguard Worker     logString.append(")");
3053*ec779b8eSAndroid Build Coastguard Worker  }
3054*ec779b8eSAndroid Build Coastguard Worker 
3055*ec779b8eSAndroid Build Coastguard Worker // Modular DRM begin
prepareDrm(const uint8_t uuid[16],const Vector<uint8_t> & drmSessionId)3056*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t> &drmSessionId)
3057*ec779b8eSAndroid Build Coastguard Worker {
3058*ec779b8eSAndroid Build Coastguard Worker     ALOGV("prepareDrm ");
3059*ec779b8eSAndroid Build Coastguard Worker 
3060*ec779b8eSAndroid Build Coastguard Worker     // Passing to the looper anyway; called in a pre-config prepared state so no race on mCrypto
3061*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatPrepareDrm, this);
3062*ec779b8eSAndroid Build Coastguard Worker     // synchronous call so just passing the address but with local copies of "const" args
3063*ec779b8eSAndroid Build Coastguard Worker     uint8_t UUID[16];
3064*ec779b8eSAndroid Build Coastguard Worker     memcpy(UUID, uuid, sizeof(UUID));
3065*ec779b8eSAndroid Build Coastguard Worker     Vector<uint8_t> sessionId = drmSessionId;
3066*ec779b8eSAndroid Build Coastguard Worker     msg->setPointer("uuid", (void*)UUID);
3067*ec779b8eSAndroid Build Coastguard Worker     msg->setPointer("drmSessionId", (void*)&sessionId);
3068*ec779b8eSAndroid Build Coastguard Worker 
3069*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> response;
3070*ec779b8eSAndroid Build Coastguard Worker     status_t status = msg->postAndAwaitResponse(&response);
3071*ec779b8eSAndroid Build Coastguard Worker 
3072*ec779b8eSAndroid Build Coastguard Worker     if (status == OK && response != NULL) {
3073*ec779b8eSAndroid Build Coastguard Worker         CHECK(response->findInt32("status", &status));
3074*ec779b8eSAndroid Build Coastguard Worker         ALOGV("prepareDrm ret: %d ", status);
3075*ec779b8eSAndroid Build Coastguard Worker     } else {
3076*ec779b8eSAndroid Build Coastguard Worker         ALOGE("prepareDrm err: %d", status);
3077*ec779b8eSAndroid Build Coastguard Worker     }
3078*ec779b8eSAndroid Build Coastguard Worker 
3079*ec779b8eSAndroid Build Coastguard Worker     return status;
3080*ec779b8eSAndroid Build Coastguard Worker }
3081*ec779b8eSAndroid Build Coastguard Worker 
releaseDrm()3082*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::releaseDrm()
3083*ec779b8eSAndroid Build Coastguard Worker {
3084*ec779b8eSAndroid Build Coastguard Worker     ALOGV("releaseDrm ");
3085*ec779b8eSAndroid Build Coastguard Worker 
3086*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage(kWhatReleaseDrm, this);
3087*ec779b8eSAndroid Build Coastguard Worker 
3088*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> response;
3089*ec779b8eSAndroid Build Coastguard Worker     status_t status = msg->postAndAwaitResponse(&response);
3090*ec779b8eSAndroid Build Coastguard Worker 
3091*ec779b8eSAndroid Build Coastguard Worker     if (status == OK && response != NULL) {
3092*ec779b8eSAndroid Build Coastguard Worker         CHECK(response->findInt32("status", &status));
3093*ec779b8eSAndroid Build Coastguard Worker         ALOGV("releaseDrm ret: %d ", status);
3094*ec779b8eSAndroid Build Coastguard Worker     } else {
3095*ec779b8eSAndroid Build Coastguard Worker         ALOGE("releaseDrm err: %d", status);
3096*ec779b8eSAndroid Build Coastguard Worker     }
3097*ec779b8eSAndroid Build Coastguard Worker 
3098*ec779b8eSAndroid Build Coastguard Worker     return status;
3099*ec779b8eSAndroid Build Coastguard Worker }
3100*ec779b8eSAndroid Build Coastguard Worker 
onPrepareDrm(const sp<AMessage> & msg)3101*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::onPrepareDrm(const sp<AMessage> &msg)
3102*ec779b8eSAndroid Build Coastguard Worker {
3103*ec779b8eSAndroid Build Coastguard Worker     // TODO change to ALOGV
3104*ec779b8eSAndroid Build Coastguard Worker     ALOGD("onPrepareDrm ");
3105*ec779b8eSAndroid Build Coastguard Worker 
3106*ec779b8eSAndroid Build Coastguard Worker     status_t status = INVALID_OPERATION;
3107*ec779b8eSAndroid Build Coastguard Worker     if (mSource == NULL) {
3108*ec779b8eSAndroid Build Coastguard Worker         ALOGE("onPrepareDrm: No source. onPrepareDrm failed with %d.", status);
3109*ec779b8eSAndroid Build Coastguard Worker         return status;
3110*ec779b8eSAndroid Build Coastguard Worker     }
3111*ec779b8eSAndroid Build Coastguard Worker 
3112*ec779b8eSAndroid Build Coastguard Worker     uint8_t *uuid;
3113*ec779b8eSAndroid Build Coastguard Worker     Vector<uint8_t> *drmSessionId;
3114*ec779b8eSAndroid Build Coastguard Worker     CHECK(msg->findPointer("uuid", (void**)&uuid));
3115*ec779b8eSAndroid Build Coastguard Worker     CHECK(msg->findPointer("drmSessionId", (void**)&drmSessionId));
3116*ec779b8eSAndroid Build Coastguard Worker 
3117*ec779b8eSAndroid Build Coastguard Worker     status = OK;
3118*ec779b8eSAndroid Build Coastguard Worker     sp<ICrypto> crypto = NULL;
3119*ec779b8eSAndroid Build Coastguard Worker 
3120*ec779b8eSAndroid Build Coastguard Worker     status = mSource->prepareDrm(uuid, *drmSessionId, &crypto);
3121*ec779b8eSAndroid Build Coastguard Worker     if (crypto == NULL) {
3122*ec779b8eSAndroid Build Coastguard Worker         ALOGE("onPrepareDrm: mSource->prepareDrm failed. status: %d", status);
3123*ec779b8eSAndroid Build Coastguard Worker         return status;
3124*ec779b8eSAndroid Build Coastguard Worker     }
3125*ec779b8eSAndroid Build Coastguard Worker     ALOGV("onPrepareDrm: mSource->prepareDrm succeeded");
3126*ec779b8eSAndroid Build Coastguard Worker 
3127*ec779b8eSAndroid Build Coastguard Worker     if (mCrypto != NULL) {
3128*ec779b8eSAndroid Build Coastguard Worker         ALOGE("onPrepareDrm: Unexpected. Already having mCrypto: %p (%d)",
3129*ec779b8eSAndroid Build Coastguard Worker                 mCrypto.get(), mCrypto->getStrongCount());
3130*ec779b8eSAndroid Build Coastguard Worker         mCrypto.clear();
3131*ec779b8eSAndroid Build Coastguard Worker     }
3132*ec779b8eSAndroid Build Coastguard Worker 
3133*ec779b8eSAndroid Build Coastguard Worker     mCrypto = crypto;
3134*ec779b8eSAndroid Build Coastguard Worker     mIsDrmProtected = true;
3135*ec779b8eSAndroid Build Coastguard Worker     // TODO change to ALOGV
3136*ec779b8eSAndroid Build Coastguard Worker     ALOGD("onPrepareDrm: mCrypto: %p (%d)", mCrypto.get(),
3137*ec779b8eSAndroid Build Coastguard Worker             (mCrypto != NULL ? mCrypto->getStrongCount() : 0));
3138*ec779b8eSAndroid Build Coastguard Worker 
3139*ec779b8eSAndroid Build Coastguard Worker     return status;
3140*ec779b8eSAndroid Build Coastguard Worker }
3141*ec779b8eSAndroid Build Coastguard Worker 
onReleaseDrm()3142*ec779b8eSAndroid Build Coastguard Worker status_t NuPlayer::onReleaseDrm()
3143*ec779b8eSAndroid Build Coastguard Worker {
3144*ec779b8eSAndroid Build Coastguard Worker     // TODO change to ALOGV
3145*ec779b8eSAndroid Build Coastguard Worker     ALOGD("onReleaseDrm ");
3146*ec779b8eSAndroid Build Coastguard Worker 
3147*ec779b8eSAndroid Build Coastguard Worker     if (!mIsDrmProtected) {
3148*ec779b8eSAndroid Build Coastguard Worker         ALOGW("onReleaseDrm: Unexpected. mIsDrmProtected is already false.");
3149*ec779b8eSAndroid Build Coastguard Worker     }
3150*ec779b8eSAndroid Build Coastguard Worker 
3151*ec779b8eSAndroid Build Coastguard Worker     mIsDrmProtected = false;
3152*ec779b8eSAndroid Build Coastguard Worker 
3153*ec779b8eSAndroid Build Coastguard Worker     status_t status;
3154*ec779b8eSAndroid Build Coastguard Worker     if (mCrypto != NULL) {
3155*ec779b8eSAndroid Build Coastguard Worker         // notifying the source first before removing crypto from codec
3156*ec779b8eSAndroid Build Coastguard Worker         if (mSource != NULL) {
3157*ec779b8eSAndroid Build Coastguard Worker             mSource->releaseDrm();
3158*ec779b8eSAndroid Build Coastguard Worker         }
3159*ec779b8eSAndroid Build Coastguard Worker 
3160*ec779b8eSAndroid Build Coastguard Worker         status=OK;
3161*ec779b8eSAndroid Build Coastguard Worker         // first making sure the codecs have released their crypto reference
3162*ec779b8eSAndroid Build Coastguard Worker         const sp<DecoderBase> &videoDecoder = getDecoder(false/*audio*/);
3163*ec779b8eSAndroid Build Coastguard Worker         if (videoDecoder != NULL) {
3164*ec779b8eSAndroid Build Coastguard Worker             status = videoDecoder->releaseCrypto();
3165*ec779b8eSAndroid Build Coastguard Worker             ALOGV("onReleaseDrm: video decoder ret: %d", status);
3166*ec779b8eSAndroid Build Coastguard Worker         }
3167*ec779b8eSAndroid Build Coastguard Worker 
3168*ec779b8eSAndroid Build Coastguard Worker         const sp<DecoderBase> &audioDecoder = getDecoder(true/*audio*/);
3169*ec779b8eSAndroid Build Coastguard Worker         if (audioDecoder != NULL) {
3170*ec779b8eSAndroid Build Coastguard Worker             status_t status_audio = audioDecoder->releaseCrypto();
3171*ec779b8eSAndroid Build Coastguard Worker             if (status == OK) {   // otherwise, returning the first error
3172*ec779b8eSAndroid Build Coastguard Worker                 status = status_audio;
3173*ec779b8eSAndroid Build Coastguard Worker             }
3174*ec779b8eSAndroid Build Coastguard Worker             ALOGV("onReleaseDrm: audio decoder ret: %d", status_audio);
3175*ec779b8eSAndroid Build Coastguard Worker         }
3176*ec779b8eSAndroid Build Coastguard Worker 
3177*ec779b8eSAndroid Build Coastguard Worker         // TODO change to ALOGV
3178*ec779b8eSAndroid Build Coastguard Worker         ALOGD("onReleaseDrm: mCrypto: %p (%d)", mCrypto.get(),
3179*ec779b8eSAndroid Build Coastguard Worker                 (mCrypto != NULL ? mCrypto->getStrongCount() : 0));
3180*ec779b8eSAndroid Build Coastguard Worker         mCrypto.clear();
3181*ec779b8eSAndroid Build Coastguard Worker     } else {   // mCrypto == NULL
3182*ec779b8eSAndroid Build Coastguard Worker         ALOGE("onReleaseDrm: Unexpected. There is no crypto.");
3183*ec779b8eSAndroid Build Coastguard Worker         status = INVALID_OPERATION;
3184*ec779b8eSAndroid Build Coastguard Worker     }
3185*ec779b8eSAndroid Build Coastguard Worker 
3186*ec779b8eSAndroid Build Coastguard Worker     return status;
3187*ec779b8eSAndroid Build Coastguard Worker }
3188*ec779b8eSAndroid Build Coastguard Worker // Modular DRM end
3189*ec779b8eSAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////////////
3190*ec779b8eSAndroid Build Coastguard Worker 
getFormat(bool audio)3191*ec779b8eSAndroid Build Coastguard Worker sp<AMessage> NuPlayer::Source::getFormat(bool audio) {
3192*ec779b8eSAndroid Build Coastguard Worker     sp<MetaData> meta = getFormatMeta(audio);
3193*ec779b8eSAndroid Build Coastguard Worker 
3194*ec779b8eSAndroid Build Coastguard Worker     if (meta == NULL) {
3195*ec779b8eSAndroid Build Coastguard Worker         return NULL;
3196*ec779b8eSAndroid Build Coastguard Worker     }
3197*ec779b8eSAndroid Build Coastguard Worker 
3198*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> msg = new AMessage;
3199*ec779b8eSAndroid Build Coastguard Worker 
3200*ec779b8eSAndroid Build Coastguard Worker     if(convertMetaDataToMessage(meta, &msg) == OK) {
3201*ec779b8eSAndroid Build Coastguard Worker         return msg;
3202*ec779b8eSAndroid Build Coastguard Worker     }
3203*ec779b8eSAndroid Build Coastguard Worker     return NULL;
3204*ec779b8eSAndroid Build Coastguard Worker }
3205*ec779b8eSAndroid Build Coastguard Worker 
notifyFlagsChanged(uint32_t flags)3206*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::Source::notifyFlagsChanged(uint32_t flags) {
3207*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> notify = dupNotify();
3208*ec779b8eSAndroid Build Coastguard Worker     notify->setInt32("what", kWhatFlagsChanged);
3209*ec779b8eSAndroid Build Coastguard Worker     notify->setInt32("flags", flags);
3210*ec779b8eSAndroid Build Coastguard Worker     notify->post();
3211*ec779b8eSAndroid Build Coastguard Worker }
3212*ec779b8eSAndroid Build Coastguard Worker 
notifyVideoSizeChanged(const sp<AMessage> & format)3213*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::Source::notifyVideoSizeChanged(const sp<AMessage> &format) {
3214*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> notify = dupNotify();
3215*ec779b8eSAndroid Build Coastguard Worker     notify->setInt32("what", kWhatVideoSizeChanged);
3216*ec779b8eSAndroid Build Coastguard Worker     notify->setMessage("format", format);
3217*ec779b8eSAndroid Build Coastguard Worker     notify->post();
3218*ec779b8eSAndroid Build Coastguard Worker }
3219*ec779b8eSAndroid Build Coastguard Worker 
notifyPrepared(status_t err)3220*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::Source::notifyPrepared(status_t err) {
3221*ec779b8eSAndroid Build Coastguard Worker     ALOGV("Source::notifyPrepared %d", err);
3222*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> notify = dupNotify();
3223*ec779b8eSAndroid Build Coastguard Worker     notify->setInt32("what", kWhatPrepared);
3224*ec779b8eSAndroid Build Coastguard Worker     notify->setInt32("err", err);
3225*ec779b8eSAndroid Build Coastguard Worker     notify->post();
3226*ec779b8eSAndroid Build Coastguard Worker }
3227*ec779b8eSAndroid Build Coastguard Worker 
notifyDrmInfo(const sp<ABuffer> & drmInfoBuffer)3228*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::Source::notifyDrmInfo(const sp<ABuffer> &drmInfoBuffer)
3229*ec779b8eSAndroid Build Coastguard Worker {
3230*ec779b8eSAndroid Build Coastguard Worker     ALOGV("Source::notifyDrmInfo");
3231*ec779b8eSAndroid Build Coastguard Worker 
3232*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> notify = dupNotify();
3233*ec779b8eSAndroid Build Coastguard Worker     notify->setInt32("what", kWhatDrmInfo);
3234*ec779b8eSAndroid Build Coastguard Worker     notify->setBuffer("drmInfo", drmInfoBuffer);
3235*ec779b8eSAndroid Build Coastguard Worker 
3236*ec779b8eSAndroid Build Coastguard Worker     notify->post();
3237*ec779b8eSAndroid Build Coastguard Worker }
3238*ec779b8eSAndroid Build Coastguard Worker 
notifyInstantiateSecureDecoders(const sp<AMessage> & reply)3239*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::Source::notifyInstantiateSecureDecoders(const sp<AMessage> &reply) {
3240*ec779b8eSAndroid Build Coastguard Worker     sp<AMessage> notify = dupNotify();
3241*ec779b8eSAndroid Build Coastguard Worker     notify->setInt32("what", kWhatInstantiateSecureDecoders);
3242*ec779b8eSAndroid Build Coastguard Worker     notify->setMessage("reply", reply);
3243*ec779b8eSAndroid Build Coastguard Worker     notify->post();
3244*ec779b8eSAndroid Build Coastguard Worker }
3245*ec779b8eSAndroid Build Coastguard Worker 
onMessageReceived(const sp<AMessage> &)3246*ec779b8eSAndroid Build Coastguard Worker void NuPlayer::Source::onMessageReceived(const sp<AMessage> & /* msg */) {
3247*ec779b8eSAndroid Build Coastguard Worker     TRESPASS();
3248*ec779b8eSAndroid Build Coastguard Worker }
3249*ec779b8eSAndroid Build Coastguard Worker 
3250*ec779b8eSAndroid Build Coastguard Worker }  // namespace android
3251