blob: f4d379411f596c1549cc7f53b0a1e8a046f958e2 [file] [log] [blame]
Andreas Huberf9334412010-12-15 15:17:42 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "NuPlayer"
19#include <utils/Log.h>
20
21#include "NuPlayer.h"
Andreas Huber5bc087c2010-12-23 10:27:40 -080022
23#include "HTTPLiveSource.h"
Chong Zhang7137ec72014-11-12 16:41:05 -080024#include "NuPlayerCCDecoder.h"
Andreas Huberf9334412010-12-15 15:17:42 -080025#include "NuPlayerDecoder.h"
Chong Zhang7137ec72014-11-12 16:41:05 -080026#include "NuPlayerDecoderBase.h"
Wei Jiabc2fb722014-07-08 16:37:57 -070027#include "NuPlayerDecoderPassThrough.h"
Andreas Huber43c3e6c2011-01-05 12:17:08 -080028#include "NuPlayerDriver.h"
Andreas Huberf9334412010-12-15 15:17:42 -080029#include "NuPlayerRenderer.h"
Andreas Huber5bc087c2010-12-23 10:27:40 -080030#include "NuPlayerSource.h"
Andreas Huber2bfdd422011-10-11 15:24:07 -070031#include "RTSPSource.h"
Andreas Huber5bc087c2010-12-23 10:27:40 -080032#include "StreamingSource.h"
Andreas Huberafed0e12011-09-20 15:39:58 -070033#include "GenericSource.h"
Robert Shihd3b0bbb2014-07-23 15:00:25 -070034#include "TextDescriptions.h"
Andreas Huber5bc087c2010-12-23 10:27:40 -080035
36#include "ATSParser.h"
Andreas Huberf9334412010-12-15 15:17:42 -080037
Lajos Molnard9fd6312014-11-06 11:00:00 -080038#include <cutils/properties.h>
39
Andreas Huber3831a062010-12-21 10:22:33 -080040#include <media/stagefright/foundation/hexdump.h>
Andreas Huberf9334412010-12-15 15:17:42 -080041#include <media/stagefright/foundation/ABuffer.h>
42#include <media/stagefright/foundation/ADebug.h>
43#include <media/stagefright/foundation/AMessage.h>
Lajos Molnar09524832014-07-17 14:29:51 -070044#include <media/stagefright/MediaBuffer.h>
Andreas Huber3fe62152011-09-16 15:09:22 -070045#include <media/stagefright/MediaDefs.h>
Andreas Huberf9334412010-12-15 15:17:42 -080046#include <media/stagefright/MediaErrors.h>
47#include <media/stagefright/MetaData.h>
Andy McFadden8ba01022012-12-18 09:46:54 -080048#include <gui/IGraphicBufferProducer.h>
Andreas Huberf9334412010-12-15 15:17:42 -080049
Andreas Huber3fe62152011-09-16 15:09:22 -070050#include "avc_utils.h"
51
Andreas Huber84066782011-08-16 09:34:26 -070052#include "ESDS.h"
53#include <media/stagefright/Utils.h>
54
Andreas Huberf9334412010-12-15 15:17:42 -080055namespace android {
56
Andreas Hubera1f8ab02012-11-30 10:53:22 -080057struct NuPlayer::Action : public RefBase {
58 Action() {}
59
60 virtual void execute(NuPlayer *player) = 0;
61
62private:
63 DISALLOW_EVIL_CONSTRUCTORS(Action);
64};
65
66struct NuPlayer::SeekAction : public Action {
Wei Jiae427abf2014-09-22 15:21:11 -070067 SeekAction(int64_t seekTimeUs, bool needNotify)
68 : mSeekTimeUs(seekTimeUs),
69 mNeedNotify(needNotify) {
Andreas Hubera1f8ab02012-11-30 10:53:22 -080070 }
71
72 virtual void execute(NuPlayer *player) {
Wei Jiae427abf2014-09-22 15:21:11 -070073 player->performSeek(mSeekTimeUs, mNeedNotify);
Andreas Hubera1f8ab02012-11-30 10:53:22 -080074 }
75
76private:
77 int64_t mSeekTimeUs;
Wei Jiae427abf2014-09-22 15:21:11 -070078 bool mNeedNotify;
Andreas Hubera1f8ab02012-11-30 10:53:22 -080079
80 DISALLOW_EVIL_CONSTRUCTORS(SeekAction);
81};
82
Chong Zhangf8d71772014-11-26 15:08:34 -080083struct NuPlayer::ResumeDecoderAction : public Action {
84 ResumeDecoderAction(bool needNotify)
85 : mNeedNotify(needNotify) {
86 }
87
88 virtual void execute(NuPlayer *player) {
89 player->performResumeDecoders(mNeedNotify);
90 }
91
92private:
93 bool mNeedNotify;
94
95 DISALLOW_EVIL_CONSTRUCTORS(ResumeDecoderAction);
96};
97
Andreas Huber57a339c2012-12-03 11:18:00 -080098struct NuPlayer::SetSurfaceAction : public Action {
99 SetSurfaceAction(const sp<NativeWindowWrapper> &wrapper)
100 : mWrapper(wrapper) {
101 }
102
103 virtual void execute(NuPlayer *player) {
104 player->performSetSurface(mWrapper);
105 }
106
107private:
108 sp<NativeWindowWrapper> mWrapper;
109
110 DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction);
111};
112
Wei Jiafef808d2014-10-31 17:57:05 -0700113struct NuPlayer::FlushDecoderAction : public Action {
114 FlushDecoderAction(FlushCommand audio, FlushCommand video)
Andreas Huber14f76722013-01-15 09:04:18 -0800115 : mAudio(audio),
116 mVideo(video) {
117 }
118
119 virtual void execute(NuPlayer *player) {
Wei Jiafef808d2014-10-31 17:57:05 -0700120 player->performDecoderFlush(mAudio, mVideo);
Andreas Huber14f76722013-01-15 09:04:18 -0800121 }
122
123private:
Wei Jiafef808d2014-10-31 17:57:05 -0700124 FlushCommand mAudio;
125 FlushCommand mVideo;
Andreas Huber14f76722013-01-15 09:04:18 -0800126
Wei Jiafef808d2014-10-31 17:57:05 -0700127 DISALLOW_EVIL_CONSTRUCTORS(FlushDecoderAction);
Andreas Huber14f76722013-01-15 09:04:18 -0800128};
129
130struct NuPlayer::PostMessageAction : public Action {
131 PostMessageAction(const sp<AMessage> &msg)
132 : mMessage(msg) {
133 }
134
135 virtual void execute(NuPlayer *) {
136 mMessage->post();
137 }
138
139private:
140 sp<AMessage> mMessage;
141
142 DISALLOW_EVIL_CONSTRUCTORS(PostMessageAction);
143};
144
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800145// Use this if there's no state necessary to save in order to execute
146// the action.
147struct NuPlayer::SimpleAction : public Action {
148 typedef void (NuPlayer::*ActionFunc)();
149
150 SimpleAction(ActionFunc func)
151 : mFunc(func) {
152 }
153
154 virtual void execute(NuPlayer *player) {
155 (player->*mFunc)();
156 }
157
158private:
159 ActionFunc mFunc;
160
161 DISALLOW_EVIL_CONSTRUCTORS(SimpleAction);
162};
163
Andreas Huberf9334412010-12-15 15:17:42 -0800164////////////////////////////////////////////////////////////////////////////////
165
166NuPlayer::NuPlayer()
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700167 : mUIDValid(false),
Andreas Huber9575c962013-02-05 13:59:56 -0800168 mSourceFlags(0),
Wei Jiabc2fb722014-07-08 16:37:57 -0700169 mOffloadAudio(false),
Wei Jia88703c32014-08-06 11:24:07 -0700170 mAudioDecoderGeneration(0),
171 mVideoDecoderGeneration(0),
Wei Jia57568df2014-09-22 10:16:29 -0700172 mRendererGeneration(0),
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700173 mAudioEOS(false),
Andreas Huberf9334412010-12-15 15:17:42 -0800174 mVideoEOS(false),
Andreas Huber5bc087c2010-12-23 10:27:40 -0800175 mScanSourcesPending(false),
Andreas Huber1aef2112011-01-04 14:01:29 -0800176 mScanSourcesGeneration(0),
Andreas Huberb7c8e912012-11-27 15:02:53 -0800177 mPollDurationGeneration(0),
Robert Shihd3b0bbb2014-07-23 15:00:25 -0700178 mTimedTextGeneration(0),
Andreas Huberf9334412010-12-15 15:17:42 -0800179 mFlushingAudio(NONE),
Andreas Huber1aef2112011-01-04 14:01:29 -0800180 mFlushingVideo(NONE),
Chong Zhangf8d71772014-11-26 15:08:34 -0800181 mResumePending(false),
Andreas Huber57a339c2012-12-03 11:18:00 -0800182 mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
Wei Jia98160162015-02-04 17:01:11 -0800183 mPlaybackRate(1.0),
Chong Zhangefbb6192015-01-30 17:13:27 -0800184 mStarted(false),
185 mPaused(false),
186 mPausedByClient(false) {
Andy Hung8d121d42014-10-03 09:53:53 -0700187 clearFlushComplete();
Andreas Huberf9334412010-12-15 15:17:42 -0800188}
189
190NuPlayer::~NuPlayer() {
191}
192
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700193void NuPlayer::setUID(uid_t uid) {
194 mUIDValid = true;
195 mUID = uid;
196}
197
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800198void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
199 mDriver = driver;
Andreas Huberf9334412010-12-15 15:17:42 -0800200}
201
Andreas Huber9575c962013-02-05 13:59:56 -0800202void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800203 sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
Andreas Huberf9334412010-12-15 15:17:42 -0800204
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800205 sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
Andreas Huberb5f25f02013-02-05 10:14:26 -0800206
Andreas Huber240abcc2014-02-13 13:32:37 -0800207 msg->setObject("source", new StreamingSource(notify, source));
Andreas Huber5bc087c2010-12-23 10:27:40 -0800208 msg->post();
209}
Andreas Huberf9334412010-12-15 15:17:42 -0800210
Andreas Huberafed0e12011-09-20 15:39:58 -0700211static bool IsHTTPLiveURL(const char *url) {
212 if (!strncasecmp("http://", url, 7)
Andreas Huber99759402013-04-01 14:28:31 -0700213 || !strncasecmp("https://", url, 8)
214 || !strncasecmp("file://", url, 7)) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700215 size_t len = strlen(url);
216 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
217 return true;
218 }
219
220 if (strstr(url,"m3u8")) {
221 return true;
222 }
223 }
224
225 return false;
226}
227
Andreas Huber9575c962013-02-05 13:59:56 -0800228void NuPlayer::setDataSourceAsync(
Andreas Huber1b86fe02014-01-29 11:13:26 -0800229 const sp<IMediaHTTPService> &httpService,
230 const char *url,
231 const KeyedVector<String8, String8> *headers) {
Chong Zhang3de157d2014-08-05 20:54:44 -0700232
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800233 sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
Oscar Rydhé7a33b772012-02-20 10:15:48 +0100234 size_t len = strlen(url);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800235
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800236 sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
Andreas Huberb5f25f02013-02-05 10:14:26 -0800237
Andreas Huberafed0e12011-09-20 15:39:58 -0700238 sp<Source> source;
239 if (IsHTTPLiveURL(url)) {
Andreas Huber81e68442014-02-05 11:52:33 -0800240 source = new HTTPLiveSource(notify, httpService, url, headers);
Andreas Huberafed0e12011-09-20 15:39:58 -0700241 } else if (!strncasecmp(url, "rtsp://", 7)) {
Andreas Huber1b86fe02014-01-29 11:13:26 -0800242 source = new RTSPSource(
243 notify, httpService, url, headers, mUIDValid, mUID);
Oscar Rydhé7a33b772012-02-20 10:15:48 +0100244 } else if ((!strncasecmp(url, "http://", 7)
245 || !strncasecmp(url, "https://", 8))
246 && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
247 || strstr(url, ".sdp?"))) {
Andreas Huber1b86fe02014-01-29 11:13:26 -0800248 source = new RTSPSource(
249 notify, httpService, url, headers, mUIDValid, mUID, true);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700250 } else {
Chong Zhang3de157d2014-08-05 20:54:44 -0700251 sp<GenericSource> genericSource =
252 new GenericSource(notify, mUIDValid, mUID);
253 // Don't set FLAG_SECURE on mSourceFlags here for widevine.
254 // The correct flags will be updated in Source::kWhatFlagsChanged
255 // handler when GenericSource is prepared.
Andreas Huber2bfdd422011-10-11 15:24:07 -0700256
Chong Zhanga19f33e2014-08-07 15:35:07 -0700257 status_t err = genericSource->setDataSource(httpService, url, headers);
Chong Zhang3de157d2014-08-05 20:54:44 -0700258
259 if (err == OK) {
260 source = genericSource;
261 } else {
Chong Zhanga19f33e2014-08-07 15:35:07 -0700262 ALOGE("Failed to set data source!");
Chong Zhang3de157d2014-08-05 20:54:44 -0700263 }
264 }
Andreas Huberafed0e12011-09-20 15:39:58 -0700265 msg->setObject("source", source);
266 msg->post();
267}
268
Andreas Huber9575c962013-02-05 13:59:56 -0800269void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800270 sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
Andreas Huberafed0e12011-09-20 15:39:58 -0700271
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800272 sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
Andreas Huberb5f25f02013-02-05 10:14:26 -0800273
Chong Zhang3de157d2014-08-05 20:54:44 -0700274 sp<GenericSource> source =
275 new GenericSource(notify, mUIDValid, mUID);
276
Chong Zhanga19f33e2014-08-07 15:35:07 -0700277 status_t err = source->setDataSource(fd, offset, length);
Chong Zhang3de157d2014-08-05 20:54:44 -0700278
279 if (err != OK) {
Chong Zhanga19f33e2014-08-07 15:35:07 -0700280 ALOGE("Failed to set data source!");
Chong Zhang3de157d2014-08-05 20:54:44 -0700281 source = NULL;
282 }
283
Andreas Huberafed0e12011-09-20 15:39:58 -0700284 msg->setObject("source", source);
Andreas Huberf9334412010-12-15 15:17:42 -0800285 msg->post();
286}
287
Andreas Huber9575c962013-02-05 13:59:56 -0800288void NuPlayer::prepareAsync() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800289 (new AMessage(kWhatPrepare, this))->post();
Andreas Huber9575c962013-02-05 13:59:56 -0800290}
291
Andreas Huber57a339c2012-12-03 11:18:00 -0800292void NuPlayer::setVideoSurfaceTextureAsync(
Andy McFadden8ba01022012-12-18 09:46:54 -0800293 const sp<IGraphicBufferProducer> &bufferProducer) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800294 sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, this);
Andreas Huber57a339c2012-12-03 11:18:00 -0800295
Andy McFadden8ba01022012-12-18 09:46:54 -0800296 if (bufferProducer == NULL) {
Andreas Huber57a339c2012-12-03 11:18:00 -0800297 msg->setObject("native-window", NULL);
298 } else {
299 msg->setObject(
300 "native-window",
301 new NativeWindowWrapper(
Wei Jia9c03a402014-08-26 15:24:43 -0700302 new Surface(bufferProducer, true /* controlledByApp */)));
Andreas Huber57a339c2012-12-03 11:18:00 -0800303 }
304
Andreas Huberf9334412010-12-15 15:17:42 -0800305 msg->post();
306}
307
308void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800309 sp<AMessage> msg = new AMessage(kWhatSetAudioSink, this);
Andreas Huberf9334412010-12-15 15:17:42 -0800310 msg->setObject("sink", sink);
311 msg->post();
312}
313
314void NuPlayer::start() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800315 (new AMessage(kWhatStart, this))->post();
Andreas Huberf9334412010-12-15 15:17:42 -0800316}
317
Wei Jia98160162015-02-04 17:01:11 -0800318void NuPlayer::setPlaybackRate(float rate) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800319 sp<AMessage> msg = new AMessage(kWhatSetRate, this);
Wei Jia98160162015-02-04 17:01:11 -0800320 msg->setFloat("rate", rate);
321 msg->post();
322}
323
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800324void NuPlayer::pause() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800325 (new AMessage(kWhatPause, this))->post();
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800326}
327
Andreas Huber1aef2112011-01-04 14:01:29 -0800328void NuPlayer::resetAsync() {
Chong Zhang48296b72014-09-14 14:28:45 -0700329 if (mSource != NULL) {
330 // During a reset, the data source might be unresponsive already, we need to
331 // disconnect explicitly so that reads exit promptly.
332 // We can't queue the disconnect request to the looper, as it might be
333 // queued behind a stuck read and never gets processed.
334 // Doing a disconnect outside the looper to allows the pending reads to exit
335 // (either successfully or with error).
336 mSource->disconnect();
337 }
338
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800339 (new AMessage(kWhatReset, this))->post();
Andreas Huber1aef2112011-01-04 14:01:29 -0800340}
341
Wei Jiae427abf2014-09-22 15:21:11 -0700342void NuPlayer::seekToAsync(int64_t seekTimeUs, bool needNotify) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800343 sp<AMessage> msg = new AMessage(kWhatSeek, this);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800344 msg->setInt64("seekTimeUs", seekTimeUs);
Wei Jiae427abf2014-09-22 15:21:11 -0700345 msg->setInt32("needNotify", needNotify);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800346 msg->post();
347}
348
Andreas Huber53df1a42010-12-22 10:03:04 -0800349
Chong Zhang404fced2014-06-11 14:45:31 -0700350void NuPlayer::writeTrackInfo(
351 Parcel* reply, const sp<AMessage> format) const {
352 int32_t trackType;
353 CHECK(format->findInt32("type", &trackType));
354
355 AString lang;
356 CHECK(format->findString("language", &lang));
357
358 reply->writeInt32(2); // write something non-zero
359 reply->writeInt32(trackType);
360 reply->writeString16(String16(lang.c_str()));
361
362 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
363 AString mime;
364 CHECK(format->findString("mime", &mime));
365
366 int32_t isAuto, isDefault, isForced;
367 CHECK(format->findInt32("auto", &isAuto));
368 CHECK(format->findInt32("default", &isDefault));
369 CHECK(format->findInt32("forced", &isForced));
370
371 reply->writeString16(String16(mime.c_str()));
372 reply->writeInt32(isAuto);
373 reply->writeInt32(isDefault);
374 reply->writeInt32(isForced);
375 }
376}
377
Andreas Huberf9334412010-12-15 15:17:42 -0800378void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
379 switch (msg->what()) {
380 case kWhatSetDataSource:
381 {
Steve Block3856b092011-10-20 11:56:00 +0100382 ALOGV("kWhatSetDataSource");
Andreas Huberf9334412010-12-15 15:17:42 -0800383
384 CHECK(mSource == NULL);
385
Chong Zhang3de157d2014-08-05 20:54:44 -0700386 status_t err = OK;
Andreas Huber5bc087c2010-12-23 10:27:40 -0800387 sp<RefBase> obj;
388 CHECK(msg->findObject("source", &obj));
Chong Zhang3de157d2014-08-05 20:54:44 -0700389 if (obj != NULL) {
390 mSource = static_cast<Source *>(obj.get());
Chong Zhang3de157d2014-08-05 20:54:44 -0700391 } else {
392 err = UNKNOWN_ERROR;
393 }
Andreas Huber9575c962013-02-05 13:59:56 -0800394
395 CHECK(mDriver != NULL);
396 sp<NuPlayerDriver> driver = mDriver.promote();
397 if (driver != NULL) {
Chong Zhang3de157d2014-08-05 20:54:44 -0700398 driver->notifySetDataSourceCompleted(err);
Andreas Huber9575c962013-02-05 13:59:56 -0800399 }
400 break;
401 }
402
403 case kWhatPrepare:
404 {
405 mSource->prepareAsync();
Andreas Huberf9334412010-12-15 15:17:42 -0800406 break;
407 }
408
Chong Zhangdcb89b32013-08-06 09:44:47 -0700409 case kWhatGetTrackInfo:
410 {
Lajos Molnar3f274362015-03-05 14:35:41 -0800411 sp<AReplyToken> replyID;
Chong Zhangdcb89b32013-08-06 09:44:47 -0700412 CHECK(msg->senderAwaitsResponse(&replyID));
413
Chong Zhang404fced2014-06-11 14:45:31 -0700414 Parcel* reply;
415 CHECK(msg->findPointer("reply", (void**)&reply));
416
417 size_t inbandTracks = 0;
Chong Zhangdcb89b32013-08-06 09:44:47 -0700418 if (mSource != NULL) {
Chong Zhang404fced2014-06-11 14:45:31 -0700419 inbandTracks = mSource->getTrackCount();
420 }
421
Chong Zhanga7fa1d92014-06-11 14:49:23 -0700422 size_t ccTracks = 0;
423 if (mCCDecoder != NULL) {
424 ccTracks = mCCDecoder->getTrackCount();
425 }
426
Chong Zhang404fced2014-06-11 14:45:31 -0700427 // total track count
Chong Zhanga7fa1d92014-06-11 14:49:23 -0700428 reply->writeInt32(inbandTracks + ccTracks);
Chong Zhang404fced2014-06-11 14:45:31 -0700429
430 // write inband tracks
431 for (size_t i = 0; i < inbandTracks; ++i) {
432 writeTrackInfo(reply, mSource->getTrackInfo(i));
Chong Zhangdcb89b32013-08-06 09:44:47 -0700433 }
434
Chong Zhanga7fa1d92014-06-11 14:49:23 -0700435 // write CC track
436 for (size_t i = 0; i < ccTracks; ++i) {
437 writeTrackInfo(reply, mCCDecoder->getTrackInfo(i));
438 }
439
Chong Zhangdcb89b32013-08-06 09:44:47 -0700440 sp<AMessage> response = new AMessage;
Chong Zhangdcb89b32013-08-06 09:44:47 -0700441 response->postReply(replyID);
442 break;
443 }
444
Robert Shih7c4f0d72014-07-09 18:53:31 -0700445 case kWhatGetSelectedTrack:
446 {
447 status_t err = INVALID_OPERATION;
448 if (mSource != NULL) {
449 err = OK;
450
451 int32_t type32;
452 CHECK(msg->findInt32("type", (int32_t*)&type32));
453 media_track_type type = (media_track_type)type32;
454 ssize_t selectedTrack = mSource->getSelectedTrack(type);
455
456 Parcel* reply;
457 CHECK(msg->findPointer("reply", (void**)&reply));
458 reply->writeInt32(selectedTrack);
459 }
460
461 sp<AMessage> response = new AMessage;
462 response->setInt32("err", err);
463
Lajos Molnar3f274362015-03-05 14:35:41 -0800464 sp<AReplyToken> replyID;
Robert Shih7c4f0d72014-07-09 18:53:31 -0700465 CHECK(msg->senderAwaitsResponse(&replyID));
466 response->postReply(replyID);
467 break;
468 }
469
Chong Zhangdcb89b32013-08-06 09:44:47 -0700470 case kWhatSelectTrack:
471 {
Lajos Molnar3f274362015-03-05 14:35:41 -0800472 sp<AReplyToken> replyID;
Chong Zhangdcb89b32013-08-06 09:44:47 -0700473 CHECK(msg->senderAwaitsResponse(&replyID));
474
Chong Zhang404fced2014-06-11 14:45:31 -0700475 size_t trackIndex;
476 int32_t select;
Robert Shih6ffb1fd2014-10-29 16:24:32 -0700477 int64_t timeUs;
Chong Zhang404fced2014-06-11 14:45:31 -0700478 CHECK(msg->findSize("trackIndex", &trackIndex));
479 CHECK(msg->findInt32("select", &select));
Robert Shih6ffb1fd2014-10-29 16:24:32 -0700480 CHECK(msg->findInt64("timeUs", &timeUs));
Chong Zhang404fced2014-06-11 14:45:31 -0700481
Chong Zhangdcb89b32013-08-06 09:44:47 -0700482 status_t err = INVALID_OPERATION;
Chong Zhang404fced2014-06-11 14:45:31 -0700483
484 size_t inbandTracks = 0;
Chong Zhangdcb89b32013-08-06 09:44:47 -0700485 if (mSource != NULL) {
Chong Zhang404fced2014-06-11 14:45:31 -0700486 inbandTracks = mSource->getTrackCount();
487 }
Chong Zhanga7fa1d92014-06-11 14:49:23 -0700488 size_t ccTracks = 0;
489 if (mCCDecoder != NULL) {
490 ccTracks = mCCDecoder->getTrackCount();
491 }
Chong Zhang404fced2014-06-11 14:45:31 -0700492
493 if (trackIndex < inbandTracks) {
Robert Shih6ffb1fd2014-10-29 16:24:32 -0700494 err = mSource->selectTrack(trackIndex, select, timeUs);
Robert Shihd3b0bbb2014-07-23 15:00:25 -0700495
496 if (!select && err == OK) {
497 int32_t type;
498 sp<AMessage> info = mSource->getTrackInfo(trackIndex);
499 if (info != NULL
500 && info->findInt32("type", &type)
501 && type == MEDIA_TRACK_TYPE_TIMEDTEXT) {
502 ++mTimedTextGeneration;
503 }
504 }
Chong Zhanga7fa1d92014-06-11 14:49:23 -0700505 } else {
506 trackIndex -= inbandTracks;
507
508 if (trackIndex < ccTracks) {
509 err = mCCDecoder->selectTrack(trackIndex, select);
510 }
Chong Zhangdcb89b32013-08-06 09:44:47 -0700511 }
512
513 sp<AMessage> response = new AMessage;
514 response->setInt32("err", err);
515
516 response->postReply(replyID);
517 break;
518 }
519
Andreas Huberb7c8e912012-11-27 15:02:53 -0800520 case kWhatPollDuration:
521 {
522 int32_t generation;
523 CHECK(msg->findInt32("generation", &generation));
524
525 if (generation != mPollDurationGeneration) {
526 // stale
527 break;
528 }
529
530 int64_t durationUs;
531 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
532 sp<NuPlayerDriver> driver = mDriver.promote();
533 if (driver != NULL) {
534 driver->notifyDuration(durationUs);
535 }
536 }
537
538 msg->post(1000000ll); // poll again in a second.
539 break;
540 }
541
Glenn Kasten11731182011-02-08 17:26:17 -0800542 case kWhatSetVideoNativeWindow:
Andreas Huberf9334412010-12-15 15:17:42 -0800543 {
Steve Block3856b092011-10-20 11:56:00 +0100544 ALOGV("kWhatSetVideoNativeWindow");
Andreas Huberf9334412010-12-15 15:17:42 -0800545
546 sp<RefBase> obj;
Glenn Kasten11731182011-02-08 17:26:17 -0800547 CHECK(msg->findObject("native-window", &obj));
Andreas Huberf9334412010-12-15 15:17:42 -0800548
Lajos Molnarf4849522014-12-10 16:58:57 -0800549 if (mSource == NULL || mSource->getFormat(false /* audio */) == NULL) {
Wei Jiafef808d2014-10-31 17:57:05 -0700550 performSetSurface(static_cast<NativeWindowWrapper *>(obj.get()));
551 break;
552 }
553
554 mDeferredActions.push_back(
555 new FlushDecoderAction(FLUSH_CMD_FLUSH /* audio */,
556 FLUSH_CMD_SHUTDOWN /* video */));
557
Andreas Huber57a339c2012-12-03 11:18:00 -0800558 mDeferredActions.push_back(
559 new SetSurfaceAction(
560 static_cast<NativeWindowWrapper *>(obj.get())));
James Dong0d268a32012-08-31 12:18:27 -0700561
Andreas Huber57a339c2012-12-03 11:18:00 -0800562 if (obj != NULL) {
Wei Jiafef808d2014-10-31 17:57:05 -0700563 if (mStarted) {
Andy Hung73535852014-09-05 11:42:58 -0700564 // Issue a seek to refresh the video screen only if started otherwise
565 // the extractor may not yet be started and will assert.
566 // If the video decoder is not set (perhaps audio only in this case)
567 // do not perform a seek as it is not needed.
Ronghua Wua73d9e02014-10-08 15:13:29 -0700568 int64_t currentPositionUs = 0;
569 if (getCurrentPosition(&currentPositionUs) == OK) {
570 mDeferredActions.push_back(
571 new SeekAction(currentPositionUs, false /* needNotify */));
572 }
Andy Hung73535852014-09-05 11:42:58 -0700573 }
Wei Jiaac428aa2014-09-02 19:01:34 -0700574
Andreas Huber57a339c2012-12-03 11:18:00 -0800575 // If there is a new surface texture, instantiate decoders
576 // again if possible.
577 mDeferredActions.push_back(
578 new SimpleAction(&NuPlayer::performScanSources));
579 }
580
Chong Zhangf8d71772014-11-26 15:08:34 -0800581 // After a flush without shutdown, decoder is paused.
582 // Don't resume it until source seek is done, otherwise it could
Chong Zhang7137ec72014-11-12 16:41:05 -0800583 // start pulling stale data too soon.
584 mDeferredActions.push_back(
Chong Zhangf8d71772014-11-26 15:08:34 -0800585 new ResumeDecoderAction(false /* needNotify */));
Chong Zhang7137ec72014-11-12 16:41:05 -0800586
Andreas Huber57a339c2012-12-03 11:18:00 -0800587 processDeferredActions();
Andreas Huberf9334412010-12-15 15:17:42 -0800588 break;
589 }
590
591 case kWhatSetAudioSink:
592 {
Steve Block3856b092011-10-20 11:56:00 +0100593 ALOGV("kWhatSetAudioSink");
Andreas Huberf9334412010-12-15 15:17:42 -0800594
595 sp<RefBase> obj;
596 CHECK(msg->findObject("sink", &obj));
597
598 mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get());
599 break;
600 }
601
602 case kWhatStart:
603 {
Steve Block3856b092011-10-20 11:56:00 +0100604 ALOGV("kWhatStart");
Wei Jia94211742014-10-28 17:09:06 -0700605 if (mStarted) {
606 onResume();
607 } else {
608 onStart();
Lajos Molnar09524832014-07-17 14:29:51 -0700609 }
Chong Zhangefbb6192015-01-30 17:13:27 -0800610 mPausedByClient = false;
Andreas Huberf9334412010-12-15 15:17:42 -0800611 break;
612 }
613
Wei Jia98160162015-02-04 17:01:11 -0800614 case kWhatSetRate:
615 {
616 ALOGV("kWhatSetRate");
617 CHECK(msg->findFloat("rate", &mPlaybackRate));
618 if (mRenderer != NULL) {
619 mRenderer->setPlaybackRate(mPlaybackRate);
620 }
621 break;
622 }
623
Andreas Huberf9334412010-12-15 15:17:42 -0800624 case kWhatScanSources:
625 {
Andreas Huber1aef2112011-01-04 14:01:29 -0800626 int32_t generation;
627 CHECK(msg->findInt32("generation", &generation));
628 if (generation != mScanSourcesGeneration) {
629 // Drop obsolete msg.
630 break;
631 }
632
Andreas Huber5bc087c2010-12-23 10:27:40 -0800633 mScanSourcesPending = false;
634
Steve Block3856b092011-10-20 11:56:00 +0100635 ALOGV("scanning sources haveAudio=%d, haveVideo=%d",
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800636 mAudioDecoder != NULL, mVideoDecoder != NULL);
637
Andreas Huberb7c8e912012-11-27 15:02:53 -0800638 bool mHadAnySourcesBefore =
639 (mAudioDecoder != NULL) || (mVideoDecoder != NULL);
640
Andy Hung282a7e32014-08-14 15:56:34 -0700641 // initialize video before audio because successful initialization of
642 // video may change deep buffer mode of audio.
Haynes Mathew George5d246ef2012-07-09 10:36:57 -0700643 if (mNativeWindow != NULL) {
644 instantiateDecoder(false, &mVideoDecoder);
645 }
Andreas Huberf9334412010-12-15 15:17:42 -0800646
Ronghua Wua10fd232014-11-06 16:15:20 -0800647 // Don't try to re-open audio sink if there's an existing decoder.
648 if (mAudioSink != NULL && mAudioDecoder == NULL) {
649 sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
650 sp<AMessage> videoFormat = mSource->getFormat(false /* audio */);
651 audio_stream_type_t streamType = mAudioSink->getAudioStreamType();
Andy Hung202bce12014-12-03 11:47:36 -0800652 const bool hasVideo = (videoFormat != NULL);
653 const bool canOffload = canOffloadStream(
654 audioMeta, hasVideo, true /* is_streaming */, streamType);
Ronghua Wua10fd232014-11-06 16:15:20 -0800655 if (canOffload) {
656 if (!mOffloadAudio) {
657 mRenderer->signalEnableOffloadAudio();
658 }
Andy Hung282a7e32014-08-14 15:56:34 -0700659 // open audio sink early under offload mode.
660 sp<AMessage> format = mSource->getFormat(true /*audio*/);
Andy Hung202bce12014-12-03 11:47:36 -0800661 tryOpenAudioSinkForOffload(format, hasVideo);
Andy Hung282a7e32014-08-14 15:56:34 -0700662 }
Andreas Huber5bc087c2010-12-23 10:27:40 -0800663 instantiateDecoder(true, &mAudioDecoder);
Andreas Huberf9334412010-12-15 15:17:42 -0800664 }
665
Andreas Huberb7c8e912012-11-27 15:02:53 -0800666 if (!mHadAnySourcesBefore
667 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
668 // This is the first time we've found anything playable.
669
Andreas Huber9575c962013-02-05 13:59:56 -0800670 if (mSourceFlags & Source::FLAG_DYNAMIC_DURATION) {
Andreas Huberb7c8e912012-11-27 15:02:53 -0800671 schedulePollDuration();
672 }
673 }
674
Andreas Hubereac68ba2011-09-27 12:12:25 -0700675 status_t err;
676 if ((err = mSource->feedMoreTSData()) != OK) {
Andreas Huber1aef2112011-01-04 14:01:29 -0800677 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
678 // We're not currently decoding anything (no audio or
679 // video tracks found) and we just ran out of input data.
Andreas Hubereac68ba2011-09-27 12:12:25 -0700680
681 if (err == ERROR_END_OF_STREAM) {
682 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
683 } else {
684 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
685 }
Andreas Huber1aef2112011-01-04 14:01:29 -0800686 }
Andreas Huberf9334412010-12-15 15:17:42 -0800687 break;
688 }
689
Andreas Huberfbe9d812012-08-31 14:05:27 -0700690 if ((mAudioDecoder == NULL && mAudioSink != NULL)
691 || (mVideoDecoder == NULL && mNativeWindow != NULL)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800692 msg->post(100000ll);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800693 mScanSourcesPending = true;
Andreas Huberf9334412010-12-15 15:17:42 -0800694 }
695 break;
696 }
697
698 case kWhatVideoNotify:
699 case kWhatAudioNotify:
700 {
701 bool audio = msg->what() == kWhatAudioNotify;
702
Wei Jia88703c32014-08-06 11:24:07 -0700703 int32_t currentDecoderGeneration =
704 (audio? mAudioDecoderGeneration : mVideoDecoderGeneration);
705 int32_t requesterGeneration = currentDecoderGeneration - 1;
706 CHECK(msg->findInt32("generation", &requesterGeneration));
707
708 if (requesterGeneration != currentDecoderGeneration) {
709 ALOGV("got message from old %s decoder, generation(%d:%d)",
710 audio ? "audio" : "video", requesterGeneration,
711 currentDecoderGeneration);
712 sp<AMessage> reply;
713 if (!(msg->findMessage("reply", &reply))) {
714 return;
715 }
716
717 reply->setInt32("err", INFO_DISCONTINUITY);
718 reply->post();
719 return;
720 }
721
Andreas Huberf9334412010-12-15 15:17:42 -0800722 int32_t what;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800723 CHECK(msg->findInt32("what", &what));
Andreas Huberf9334412010-12-15 15:17:42 -0800724
Chong Zhang7137ec72014-11-12 16:41:05 -0800725 if (what == DecoderBase::kWhatInputDiscontinuity) {
726 int32_t formatChange;
727 CHECK(msg->findInt32("formatChange", &formatChange));
Andreas Huberf9334412010-12-15 15:17:42 -0800728
Chong Zhang7137ec72014-11-12 16:41:05 -0800729 ALOGV("%s discontinuity: formatChange %d",
730 audio ? "audio" : "video", formatChange);
731
732 if (formatChange) {
733 mDeferredActions.push_back(
734 new FlushDecoderAction(
735 audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE,
736 audio ? FLUSH_CMD_NONE : FLUSH_CMD_SHUTDOWN));
Andreas Huberf9334412010-12-15 15:17:42 -0800737 }
Chong Zhang7137ec72014-11-12 16:41:05 -0800738
739 mDeferredActions.push_back(
740 new SimpleAction(
741 &NuPlayer::performScanSources));
742
743 processDeferredActions();
744 } else if (what == DecoderBase::kWhatEOS) {
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700745 int32_t err;
Lajos Molnar1cd13982014-01-17 15:12:51 -0800746 CHECK(msg->findInt32("err", &err));
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700747
748 if (err == ERROR_END_OF_STREAM) {
Steve Block3856b092011-10-20 11:56:00 +0100749 ALOGV("got %s decoder EOS", audio ? "audio" : "video");
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700750 } else {
Steve Block3856b092011-10-20 11:56:00 +0100751 ALOGV("got %s decoder EOS w/ error %d",
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700752 audio ? "audio" : "video",
753 err);
754 }
755
756 mRenderer->queueEOS(audio, err);
Chong Zhang7137ec72014-11-12 16:41:05 -0800757 } else if (what == DecoderBase::kWhatFlushCompleted) {
Steve Block3856b092011-10-20 11:56:00 +0100758 ALOGV("decoder %s flush completed", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800759
Andy Hung8d121d42014-10-03 09:53:53 -0700760 handleFlushComplete(audio, true /* isDecoder */);
Andreas Huber3831a062010-12-21 10:22:33 -0800761 finishFlushIfPossible();
Chong Zhang7137ec72014-11-12 16:41:05 -0800762 } else if (what == DecoderBase::kWhatVideoSizeChanged) {
Lajos Molnar1cd13982014-01-17 15:12:51 -0800763 sp<AMessage> format;
764 CHECK(msg->findMessage("format", &format));
765
Wei Jiac6cfd702014-11-11 16:33:20 -0800766 sp<AMessage> inputFormat =
767 mSource->getFormat(false /* audio */);
Andreas Huber3831a062010-12-21 10:22:33 -0800768
Wei Jiac6cfd702014-11-11 16:33:20 -0800769 updateVideoSize(inputFormat, format);
Chong Zhang7137ec72014-11-12 16:41:05 -0800770 } else if (what == DecoderBase::kWhatShutdownCompleted) {
Steve Block3856b092011-10-20 11:56:00 +0100771 ALOGV("%s shutdown completed", audio ? "audio" : "video");
Andreas Huber3831a062010-12-21 10:22:33 -0800772 if (audio) {
773 mAudioDecoder.clear();
Wei Jia57568df2014-09-22 10:16:29 -0700774 ++mAudioDecoderGeneration;
Andreas Huber3831a062010-12-21 10:22:33 -0800775
776 CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
777 mFlushingAudio = SHUT_DOWN;
778 } else {
779 mVideoDecoder.clear();
Wei Jia57568df2014-09-22 10:16:29 -0700780 ++mVideoDecoderGeneration;
Andreas Huber3831a062010-12-21 10:22:33 -0800781
782 CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
783 mFlushingVideo = SHUT_DOWN;
784 }
785
786 finishFlushIfPossible();
Chong Zhangf8d71772014-11-26 15:08:34 -0800787 } else if (what == DecoderBase::kWhatResumeCompleted) {
788 finishResume();
Chong Zhang7137ec72014-11-12 16:41:05 -0800789 } else if (what == DecoderBase::kWhatError) {
Chong Zhangf4c0a942014-08-11 15:14:10 -0700790 status_t err;
Andy Hung2abde2c2014-09-30 14:40:32 -0700791 if (!msg->findInt32("err", &err) || err == OK) {
Chong Zhangf4c0a942014-08-11 15:14:10 -0700792 err = UNKNOWN_ERROR;
793 }
Andy Hungcf31f1e2014-09-23 14:59:01 -0700794
Andy Hung2abde2c2014-09-30 14:40:32 -0700795 // Decoder errors can be due to Source (e.g. from streaming),
796 // or from decoding corrupted bitstreams, or from other decoder
797 // MediaCodec operations (e.g. from an ongoing reset or seek).
Andy Hung202bce12014-12-03 11:47:36 -0800798 // They may also be due to openAudioSink failure at
799 // decoder start or after a format change.
Andy Hung2abde2c2014-09-30 14:40:32 -0700800 //
801 // We try to gracefully shut down the affected decoder if possible,
802 // rather than trying to force the shutdown with something
803 // similar to performReset(). This method can lead to a hang
804 // if MediaCodec functions block after an error, but they should
805 // typically return INVALID_OPERATION instead of blocking.
806
807 FlushStatus *flushing = audio ? &mFlushingAudio : &mFlushingVideo;
808 ALOGE("received error(%#x) from %s decoder, flushing(%d), now shutting down",
809 err, audio ? "audio" : "video", *flushing);
810
811 switch (*flushing) {
812 case NONE:
813 mDeferredActions.push_back(
Wei Jiafef808d2014-10-31 17:57:05 -0700814 new FlushDecoderAction(
815 audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE,
816 audio ? FLUSH_CMD_NONE : FLUSH_CMD_SHUTDOWN));
Andy Hung2abde2c2014-09-30 14:40:32 -0700817 processDeferredActions();
818 break;
819 case FLUSHING_DECODER:
820 *flushing = FLUSHING_DECODER_SHUTDOWN; // initiate shutdown after flush.
821 break; // Wait for flush to complete.
822 case FLUSHING_DECODER_SHUTDOWN:
823 break; // Wait for flush to complete.
824 case SHUTTING_DOWN_DECODER:
825 break; // Wait for shutdown to complete.
826 case FLUSHED:
827 // Widevine source reads must stop before releasing the video decoder.
828 if (!audio && mSource != NULL && mSourceFlags & Source::FLAG_SECURE) {
829 mSource->stop();
830 }
831 getDecoder(audio)->initiateShutdown(); // In the middle of a seek.
832 *flushing = SHUTTING_DOWN_DECODER; // Shut down.
833 break;
834 case SHUT_DOWN:
835 finishFlushIfPossible(); // Should not occur.
836 break; // Finish anyways.
Marco Nelissen9e2b7912014-08-18 16:13:03 -0700837 }
Andy Hung2abde2c2014-09-30 14:40:32 -0700838 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
Lajos Molnar1cd13982014-01-17 15:12:51 -0800839 } else {
840 ALOGV("Unhandled decoder notification %d '%c%c%c%c'.",
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800841 what,
842 what >> 24,
843 (what >> 16) & 0xff,
844 (what >> 8) & 0xff,
845 what & 0xff);
Andreas Huberf9334412010-12-15 15:17:42 -0800846 }
847
848 break;
849 }
850
851 case kWhatRendererNotify:
852 {
Wei Jia57568df2014-09-22 10:16:29 -0700853 int32_t requesterGeneration = mRendererGeneration - 1;
854 CHECK(msg->findInt32("generation", &requesterGeneration));
855 if (requesterGeneration != mRendererGeneration) {
856 ALOGV("got message from old renderer, generation(%d:%d)",
857 requesterGeneration, mRendererGeneration);
858 return;
859 }
860
Andreas Huberf9334412010-12-15 15:17:42 -0800861 int32_t what;
862 CHECK(msg->findInt32("what", &what));
863
864 if (what == Renderer::kWhatEOS) {
865 int32_t audio;
866 CHECK(msg->findInt32("audio", &audio));
867
Andreas Huberc92fd242011-08-16 13:48:44 -0700868 int32_t finalResult;
869 CHECK(msg->findInt32("finalResult", &finalResult));
870
Andreas Huberf9334412010-12-15 15:17:42 -0800871 if (audio) {
872 mAudioEOS = true;
873 } else {
874 mVideoEOS = true;
875 }
876
Andreas Huberc92fd242011-08-16 13:48:44 -0700877 if (finalResult == ERROR_END_OF_STREAM) {
Steve Block3856b092011-10-20 11:56:00 +0100878 ALOGV("reached %s EOS", audio ? "audio" : "video");
Andreas Huberc92fd242011-08-16 13:48:44 -0700879 } else {
Steve Block29357bc2012-01-06 19:20:56 +0000880 ALOGE("%s track encountered an error (%d)",
Andreas Huberc92fd242011-08-16 13:48:44 -0700881 audio ? "audio" : "video", finalResult);
882
883 notifyListener(
884 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult);
885 }
Andreas Huberf9334412010-12-15 15:17:42 -0800886
887 if ((mAudioEOS || mAudioDecoder == NULL)
888 && (mVideoEOS || mVideoDecoder == NULL)) {
889 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
890 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700891 } else if (what == Renderer::kWhatFlushComplete) {
Andreas Huberf9334412010-12-15 15:17:42 -0800892 int32_t audio;
893 CHECK(msg->findInt32("audio", &audio));
894
Steve Block3856b092011-10-20 11:56:00 +0100895 ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
Andy Hung8d121d42014-10-03 09:53:53 -0700896 handleFlushComplete(audio, false /* isDecoder */);
897 finishFlushIfPossible();
James Dongf57b4ea2012-07-20 13:38:36 -0700898 } else if (what == Renderer::kWhatVideoRenderingStart) {
899 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
Lajos Molnarcbaffcf2013-08-14 18:30:38 -0700900 } else if (what == Renderer::kWhatMediaRenderingStart) {
901 ALOGV("media rendering started");
902 notifyListener(MEDIA_STARTED, 0, 0);
Wei Jia3a2956d2014-07-22 16:01:33 -0700903 } else if (what == Renderer::kWhatAudioOffloadTearDown) {
Ronghua Wua10fd232014-11-06 16:15:20 -0800904 ALOGV("Tear down audio offload, fall back to s/w path if due to error.");
Wei Jia3a2956d2014-07-22 16:01:33 -0700905 int64_t positionUs;
906 CHECK(msg->findInt64("positionUs", &positionUs));
Ronghua Wu08529172014-10-02 16:55:52 -0700907 int32_t reason;
908 CHECK(msg->findInt32("reason", &reason));
Andy Hung282a7e32014-08-14 15:56:34 -0700909 closeAudioSink();
Wei Jia3a2956d2014-07-22 16:01:33 -0700910 mAudioDecoder.clear();
Wei Jia57568df2014-09-22 10:16:29 -0700911 ++mAudioDecoderGeneration;
Chong Zhang7137ec72014-11-12 16:41:05 -0800912 mRenderer->flush(
913 true /* audio */, false /* notifyComplete */);
Wei Jia3a2956d2014-07-22 16:01:33 -0700914 if (mVideoDecoder != NULL) {
Chong Zhang7137ec72014-11-12 16:41:05 -0800915 mRenderer->flush(
916 false /* audio */, false /* notifyComplete */);
Wei Jia3a2956d2014-07-22 16:01:33 -0700917 }
Wei Jia3a2956d2014-07-22 16:01:33 -0700918
Wei Jiae427abf2014-09-22 15:21:11 -0700919 performSeek(positionUs, false /* needNotify */);
Ronghua Wu08529172014-10-02 16:55:52 -0700920 if (reason == Renderer::kDueToError) {
Ronghua Wua10fd232014-11-06 16:15:20 -0800921 mRenderer->signalDisableOffloadAudio();
922 mOffloadAudio = false;
Ronghua Wu08529172014-10-02 16:55:52 -0700923 instantiateDecoder(true /* audio */, &mAudioDecoder);
924 }
Andreas Huberf9334412010-12-15 15:17:42 -0800925 }
926 break;
927 }
928
929 case kWhatMoreDataQueued:
930 {
931 break;
932 }
933
Andreas Huber1aef2112011-01-04 14:01:29 -0800934 case kWhatReset:
935 {
Steve Block3856b092011-10-20 11:56:00 +0100936 ALOGV("kWhatReset");
Andreas Huber1aef2112011-01-04 14:01:29 -0800937
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800938 mDeferredActions.push_back(
Wei Jiafef808d2014-10-31 17:57:05 -0700939 new FlushDecoderAction(
940 FLUSH_CMD_SHUTDOWN /* audio */,
941 FLUSH_CMD_SHUTDOWN /* video */));
Andreas Huberb7c8e912012-11-27 15:02:53 -0800942
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800943 mDeferredActions.push_back(
944 new SimpleAction(&NuPlayer::performReset));
Andreas Huberb58ce9f2011-11-28 16:27:35 -0800945
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800946 processDeferredActions();
Andreas Huber1aef2112011-01-04 14:01:29 -0800947 break;
948 }
949
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800950 case kWhatSeek:
951 {
952 int64_t seekTimeUs;
Wei Jiae427abf2014-09-22 15:21:11 -0700953 int32_t needNotify;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800954 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
Wei Jiae427abf2014-09-22 15:21:11 -0700955 CHECK(msg->findInt32("needNotify", &needNotify));
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800956
Wei Jiae427abf2014-09-22 15:21:11 -0700957 ALOGV("kWhatSeek seekTimeUs=%lld us, needNotify=%d",
958 seekTimeUs, needNotify);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800959
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800960 mDeferredActions.push_back(
Wei Jiafef808d2014-10-31 17:57:05 -0700961 new FlushDecoderAction(FLUSH_CMD_FLUSH /* audio */,
962 FLUSH_CMD_FLUSH /* video */));
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800963
Wei Jiae427abf2014-09-22 15:21:11 -0700964 mDeferredActions.push_back(
965 new SeekAction(seekTimeUs, needNotify));
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800966
Chong Zhangf8d71772014-11-26 15:08:34 -0800967 // After a flush without shutdown, decoder is paused.
968 // Don't resume it until source seek is done, otherwise it could
Chong Zhang7137ec72014-11-12 16:41:05 -0800969 // start pulling stale data too soon.
970 mDeferredActions.push_back(
Chong Zhangf8d71772014-11-26 15:08:34 -0800971 new ResumeDecoderAction(needNotify));
Chong Zhang7137ec72014-11-12 16:41:05 -0800972
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800973 processDeferredActions();
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800974 break;
975 }
976
Andreas Huberb4082222011-01-20 15:23:04 -0800977 case kWhatPause:
978 {
Chong Zhangefbb6192015-01-30 17:13:27 -0800979 onPause();
980 mPausedByClient = true;
Andreas Huberb4082222011-01-20 15:23:04 -0800981 break;
982 }
983
Andreas Huberb5f25f02013-02-05 10:14:26 -0800984 case kWhatSourceNotify:
985 {
Andreas Huber9575c962013-02-05 13:59:56 -0800986 onSourceNotify(msg);
Andreas Huberb5f25f02013-02-05 10:14:26 -0800987 break;
988 }
989
Chong Zhanga7fa1d92014-06-11 14:49:23 -0700990 case kWhatClosedCaptionNotify:
991 {
992 onClosedCaptionNotify(msg);
993 break;
994 }
995
Andreas Huberf9334412010-12-15 15:17:42 -0800996 default:
997 TRESPASS();
998 break;
999 }
1000}
1001
Wei Jia94211742014-10-28 17:09:06 -07001002void NuPlayer::onResume() {
Chong Zhangefbb6192015-01-30 17:13:27 -08001003 if (!mPaused) {
1004 return;
1005 }
1006 mPaused = false;
Wei Jia94211742014-10-28 17:09:06 -07001007 if (mSource != NULL) {
1008 mSource->resume();
1009 } else {
1010 ALOGW("resume called when source is gone or not set");
1011 }
1012 // |mAudioDecoder| may have been released due to the pause timeout, so re-create it if
1013 // needed.
1014 if (audioDecoderStillNeeded() && mAudioDecoder == NULL) {
1015 instantiateDecoder(true /* audio */, &mAudioDecoder);
1016 }
1017 if (mRenderer != NULL) {
1018 mRenderer->resume();
1019 } else {
1020 ALOGW("resume called when renderer is gone or not set");
1021 }
1022}
1023
1024void NuPlayer::onStart() {
Wei Jia94211742014-10-28 17:09:06 -07001025 mOffloadAudio = false;
1026 mAudioEOS = false;
1027 mVideoEOS = false;
Wei Jia94211742014-10-28 17:09:06 -07001028 mStarted = true;
1029
1030 /* instantiate decoders now for secure playback */
1031 if (mSourceFlags & Source::FLAG_SECURE) {
1032 if (mNativeWindow != NULL) {
1033 instantiateDecoder(false, &mVideoDecoder);
1034 }
1035
1036 if (mAudioSink != NULL) {
1037 instantiateDecoder(true, &mAudioDecoder);
1038 }
1039 }
1040
1041 mSource->start();
1042
1043 uint32_t flags = 0;
1044
1045 if (mSource->isRealTime()) {
1046 flags |= Renderer::FLAG_REAL_TIME;
1047 }
1048
1049 sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
1050 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
1051 if (mAudioSink != NULL) {
1052 streamType = mAudioSink->getAudioStreamType();
1053 }
1054
1055 sp<AMessage> videoFormat = mSource->getFormat(false /* audio */);
1056
1057 mOffloadAudio =
1058 canOffloadStream(audioMeta, (videoFormat != NULL),
1059 true /* is_streaming */, streamType);
1060 if (mOffloadAudio) {
1061 flags |= Renderer::FLAG_OFFLOAD_AUDIO;
1062 }
1063
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001064 sp<AMessage> notify = new AMessage(kWhatRendererNotify, this);
Wei Jia94211742014-10-28 17:09:06 -07001065 ++mRendererGeneration;
1066 notify->setInt32("generation", mRendererGeneration);
1067 mRenderer = new Renderer(mAudioSink, notify, flags);
Wei Jia94211742014-10-28 17:09:06 -07001068 mRendererLooper = new ALooper;
1069 mRendererLooper->setName("NuPlayerRenderer");
1070 mRendererLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
1071 mRendererLooper->registerHandler(mRenderer);
Wei Jiac8206ff2015-03-04 13:59:37 -08001072 if (mPlaybackRate != 1.0) {
1073 mRenderer->setPlaybackRate(mPlaybackRate);
1074 }
Wei Jia94211742014-10-28 17:09:06 -07001075
1076 sp<MetaData> meta = getFileMeta();
1077 int32_t rate;
1078 if (meta != NULL
1079 && meta->findInt32(kKeyFrameRate, &rate) && rate > 0) {
1080 mRenderer->setVideoFrameRate(rate);
1081 }
1082
Wei Jiac6cfd702014-11-11 16:33:20 -08001083 if (mVideoDecoder != NULL) {
1084 mVideoDecoder->setRenderer(mRenderer);
1085 }
1086 if (mAudioDecoder != NULL) {
1087 mAudioDecoder->setRenderer(mRenderer);
1088 }
1089
Wei Jia94211742014-10-28 17:09:06 -07001090 postScanSources();
1091}
1092
Chong Zhangefbb6192015-01-30 17:13:27 -08001093void NuPlayer::onPause() {
1094 if (mPaused) {
1095 return;
1096 }
1097 mPaused = true;
1098 if (mSource != NULL) {
1099 mSource->pause();
1100 } else {
1101 ALOGW("pause called when source is gone or not set");
1102 }
1103 if (mRenderer != NULL) {
1104 mRenderer->pause();
1105 } else {
1106 ALOGW("pause called when renderer is gone or not set");
1107 }
1108}
1109
Ronghua Wud7988b12014-10-03 15:19:10 -07001110bool NuPlayer::audioDecoderStillNeeded() {
1111 // Audio decoder is no longer needed if it's in shut/shutting down status.
1112 return ((mFlushingAudio != SHUT_DOWN) && (mFlushingAudio != SHUTTING_DOWN_DECODER));
1113}
1114
Andy Hung8d121d42014-10-03 09:53:53 -07001115void NuPlayer::handleFlushComplete(bool audio, bool isDecoder) {
1116 // We wait for both the decoder flush and the renderer flush to complete
1117 // before entering either the FLUSHED or the SHUTTING_DOWN_DECODER state.
1118
1119 mFlushComplete[audio][isDecoder] = true;
1120 if (!mFlushComplete[audio][!isDecoder]) {
1121 return;
1122 }
1123
1124 FlushStatus *state = audio ? &mFlushingAudio : &mFlushingVideo;
1125 switch (*state) {
1126 case FLUSHING_DECODER:
1127 {
1128 *state = FLUSHED;
Andy Hung8d121d42014-10-03 09:53:53 -07001129 break;
1130 }
1131
1132 case FLUSHING_DECODER_SHUTDOWN:
1133 {
1134 *state = SHUTTING_DOWN_DECODER;
1135
1136 ALOGV("initiating %s decoder shutdown", audio ? "audio" : "video");
1137 if (!audio) {
Andy Hung8d121d42014-10-03 09:53:53 -07001138 // Widevine source reads must stop before releasing the video decoder.
1139 if (mSource != NULL && mSourceFlags & Source::FLAG_SECURE) {
1140 mSource->stop();
1141 }
1142 }
1143 getDecoder(audio)->initiateShutdown();
1144 break;
1145 }
1146
1147 default:
1148 // decoder flush completes only occur in a flushing state.
1149 LOG_ALWAYS_FATAL_IF(isDecoder, "decoder flush in invalid state %d", *state);
1150 break;
1151 }
1152}
1153
Andreas Huber3831a062010-12-21 10:22:33 -08001154void NuPlayer::finishFlushIfPossible() {
Wei Jia53904f32014-07-29 10:22:53 -07001155 if (mFlushingAudio != NONE && mFlushingAudio != FLUSHED
1156 && mFlushingAudio != SHUT_DOWN) {
Andreas Huber3831a062010-12-21 10:22:33 -08001157 return;
1158 }
1159
Wei Jia53904f32014-07-29 10:22:53 -07001160 if (mFlushingVideo != NONE && mFlushingVideo != FLUSHED
1161 && mFlushingVideo != SHUT_DOWN) {
Andreas Huber3831a062010-12-21 10:22:33 -08001162 return;
1163 }
1164
Steve Block3856b092011-10-20 11:56:00 +01001165 ALOGV("both audio and video are flushed now.");
Andreas Huber3831a062010-12-21 10:22:33 -08001166
Andreas Huber3831a062010-12-21 10:22:33 -08001167 mFlushingAudio = NONE;
1168 mFlushingVideo = NONE;
Andreas Huber3831a062010-12-21 10:22:33 -08001169
Andy Hung8d121d42014-10-03 09:53:53 -07001170 clearFlushComplete();
1171
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001172 processDeferredActions();
Andreas Huber1aef2112011-01-04 14:01:29 -08001173}
1174
1175void NuPlayer::postScanSources() {
1176 if (mScanSourcesPending) {
1177 return;
1178 }
1179
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001180 sp<AMessage> msg = new AMessage(kWhatScanSources, this);
Andreas Huber1aef2112011-01-04 14:01:29 -08001181 msg->setInt32("generation", mScanSourcesGeneration);
1182 msg->post();
1183
1184 mScanSourcesPending = true;
1185}
1186
Andy Hung202bce12014-12-03 11:47:36 -08001187void NuPlayer::tryOpenAudioSinkForOffload(const sp<AMessage> &format, bool hasVideo) {
1188 // Note: This is called early in NuPlayer to determine whether offloading
1189 // is possible; otherwise the decoders call the renderer openAudioSink directly.
Andy Hung282a7e32014-08-14 15:56:34 -07001190
Andy Hung202bce12014-12-03 11:47:36 -08001191 status_t err = mRenderer->openAudioSink(
1192 format, true /* offloadOnly */, hasVideo, AUDIO_OUTPUT_FLAG_NONE, &mOffloadAudio);
1193 if (err != OK) {
1194 // Any failure we turn off mOffloadAudio.
1195 mOffloadAudio = false;
1196 } else if (mOffloadAudio) {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001197 sp<MetaData> audioMeta =
1198 mSource->getFormatMeta(true /* audio */);
1199 sendMetaDataToHal(mAudioSink, audioMeta);
Andy Hung282a7e32014-08-14 15:56:34 -07001200 }
1201}
1202
1203void NuPlayer::closeAudioSink() {
Chong Zhang3b9eb1f2014-10-15 17:05:08 -07001204 mRenderer->closeAudioSink();
Andy Hung282a7e32014-08-14 15:56:34 -07001205}
1206
Chong Zhang7137ec72014-11-12 16:41:05 -08001207status_t NuPlayer::instantiateDecoder(bool audio, sp<DecoderBase> *decoder) {
Andreas Huberf9334412010-12-15 15:17:42 -08001208 if (*decoder != NULL) {
1209 return OK;
1210 }
1211
Andreas Huber84066782011-08-16 09:34:26 -07001212 sp<AMessage> format = mSource->getFormat(audio);
Andreas Huberf9334412010-12-15 15:17:42 -08001213
Andreas Huber84066782011-08-16 09:34:26 -07001214 if (format == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -08001215 return -EWOULDBLOCK;
1216 }
1217
Andreas Huber3fe62152011-09-16 15:09:22 -07001218 if (!audio) {
Andreas Huber84066782011-08-16 09:34:26 -07001219 AString mime;
1220 CHECK(format->findString("mime", &mime));
Chong Zhanga7fa1d92014-06-11 14:49:23 -07001221
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001222 sp<AMessage> ccNotify = new AMessage(kWhatClosedCaptionNotify, this);
Chong Zhang341ab6e2015-02-04 13:37:18 -08001223 if (mCCDecoder == NULL) {
1224 mCCDecoder = new CCDecoder(ccNotify);
1225 }
Lajos Molnar09524832014-07-17 14:29:51 -07001226
1227 if (mSourceFlags & Source::FLAG_SECURE) {
1228 format->setInt32("secure", true);
1229 }
Chong Zhang17134602015-01-07 16:14:34 -08001230
1231 if (mSourceFlags & Source::FLAG_PROTECTED) {
1232 format->setInt32("protected", true);
1233 }
Andreas Huber3fe62152011-09-16 15:09:22 -07001234 }
1235
Wei Jiabc2fb722014-07-08 16:37:57 -07001236 if (audio) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001237 sp<AMessage> notify = new AMessage(kWhatAudioNotify, this);
Wei Jia88703c32014-08-06 11:24:07 -07001238 ++mAudioDecoderGeneration;
1239 notify->setInt32("generation", mAudioDecoderGeneration);
1240
Wei Jiabc2fb722014-07-08 16:37:57 -07001241 if (mOffloadAudio) {
Wei Jiac6cfd702014-11-11 16:33:20 -08001242 *decoder = new DecoderPassThrough(notify, mSource, mRenderer);
Wei Jiabc2fb722014-07-08 16:37:57 -07001243 } else {
Wei Jiac6cfd702014-11-11 16:33:20 -08001244 *decoder = new Decoder(notify, mSource, mRenderer);
Wei Jiabc2fb722014-07-08 16:37:57 -07001245 }
1246 } else {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001247 sp<AMessage> notify = new AMessage(kWhatVideoNotify, this);
Wei Jia88703c32014-08-06 11:24:07 -07001248 ++mVideoDecoderGeneration;
1249 notify->setInt32("generation", mVideoDecoderGeneration);
1250
Chong Zhang7137ec72014-11-12 16:41:05 -08001251 *decoder = new Decoder(
1252 notify, mSource, mRenderer, mNativeWindow, mCCDecoder);
Lajos Molnard9fd6312014-11-06 11:00:00 -08001253
1254 // enable FRC if high-quality AV sync is requested, even if not
1255 // queuing to native window, as this will even improve textureview
1256 // playback.
1257 {
1258 char value[PROPERTY_VALUE_MAX];
1259 if (property_get("persist.sys.media.avsync", value, NULL) &&
1260 (!strcmp("1", value) || !strcasecmp("true", value))) {
1261 format->setInt32("auto-frc", 1);
1262 }
1263 }
Wei Jiabc2fb722014-07-08 16:37:57 -07001264 }
Lajos Molnar1cd13982014-01-17 15:12:51 -08001265 (*decoder)->init();
Andreas Huber84066782011-08-16 09:34:26 -07001266 (*decoder)->configure(format);
Andreas Huberf9334412010-12-15 15:17:42 -08001267
Lajos Molnar09524832014-07-17 14:29:51 -07001268 // allocate buffers to decrypt widevine source buffers
1269 if (!audio && (mSourceFlags & Source::FLAG_SECURE)) {
1270 Vector<sp<ABuffer> > inputBufs;
1271 CHECK_EQ((*decoder)->getInputBuffers(&inputBufs), (status_t)OK);
1272
1273 Vector<MediaBuffer *> mediaBufs;
1274 for (size_t i = 0; i < inputBufs.size(); i++) {
1275 const sp<ABuffer> &buffer = inputBufs[i];
1276 MediaBuffer *mbuf = new MediaBuffer(buffer->data(), buffer->size());
1277 mediaBufs.push(mbuf);
1278 }
1279
1280 status_t err = mSource->setBuffers(audio, mediaBufs);
1281 if (err != OK) {
1282 for (size_t i = 0; i < mediaBufs.size(); ++i) {
1283 mediaBufs[i]->release();
1284 }
1285 mediaBufs.clear();
1286 ALOGE("Secure source didn't support secure mediaBufs.");
1287 return err;
1288 }
1289 }
Andreas Huberf9334412010-12-15 15:17:42 -08001290 return OK;
1291}
1292
Chong Zhangced1c2f2014-08-08 15:22:35 -07001293void NuPlayer::updateVideoSize(
1294 const sp<AMessage> &inputFormat,
1295 const sp<AMessage> &outputFormat) {
1296 if (inputFormat == NULL) {
1297 ALOGW("Unknown video size, reporting 0x0!");
1298 notifyListener(MEDIA_SET_VIDEO_SIZE, 0, 0);
1299 return;
1300 }
1301
1302 int32_t displayWidth, displayHeight;
1303 int32_t cropLeft, cropTop, cropRight, cropBottom;
1304
1305 if (outputFormat != NULL) {
1306 int32_t width, height;
1307 CHECK(outputFormat->findInt32("width", &width));
1308 CHECK(outputFormat->findInt32("height", &height));
1309
1310 int32_t cropLeft, cropTop, cropRight, cropBottom;
1311 CHECK(outputFormat->findRect(
1312 "crop",
1313 &cropLeft, &cropTop, &cropRight, &cropBottom));
1314
1315 displayWidth = cropRight - cropLeft + 1;
1316 displayHeight = cropBottom - cropTop + 1;
1317
1318 ALOGV("Video output format changed to %d x %d "
1319 "(crop: %d x %d @ (%d, %d))",
1320 width, height,
1321 displayWidth,
1322 displayHeight,
1323 cropLeft, cropTop);
1324 } else {
1325 CHECK(inputFormat->findInt32("width", &displayWidth));
1326 CHECK(inputFormat->findInt32("height", &displayHeight));
1327
1328 ALOGV("Video input format %d x %d", displayWidth, displayHeight);
1329 }
1330
1331 // Take into account sample aspect ratio if necessary:
1332 int32_t sarWidth, sarHeight;
1333 if (inputFormat->findInt32("sar-width", &sarWidth)
1334 && inputFormat->findInt32("sar-height", &sarHeight)) {
1335 ALOGV("Sample aspect ratio %d : %d", sarWidth, sarHeight);
1336
1337 displayWidth = (displayWidth * sarWidth) / sarHeight;
1338
1339 ALOGV("display dimensions %d x %d", displayWidth, displayHeight);
1340 }
1341
1342 int32_t rotationDegrees;
1343 if (!inputFormat->findInt32("rotation-degrees", &rotationDegrees)) {
1344 rotationDegrees = 0;
1345 }
1346
1347 if (rotationDegrees == 90 || rotationDegrees == 270) {
1348 int32_t tmp = displayWidth;
1349 displayWidth = displayHeight;
1350 displayHeight = tmp;
1351 }
1352
1353 notifyListener(
1354 MEDIA_SET_VIDEO_SIZE,
1355 displayWidth,
1356 displayHeight);
1357}
1358
Chong Zhangdcb89b32013-08-06 09:44:47 -07001359void NuPlayer::notifyListener(int msg, int ext1, int ext2, const Parcel *in) {
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001360 if (mDriver == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -08001361 return;
1362 }
1363
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001364 sp<NuPlayerDriver> driver = mDriver.promote();
Andreas Huberf9334412010-12-15 15:17:42 -08001365
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001366 if (driver == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -08001367 return;
1368 }
1369
Chong Zhangdcb89b32013-08-06 09:44:47 -07001370 driver->notifyListener(msg, ext1, ext2, in);
Andreas Huberf9334412010-12-15 15:17:42 -08001371}
1372
Chong Zhang7137ec72014-11-12 16:41:05 -08001373void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
Andreas Huber14f76722013-01-15 09:04:18 -08001374 ALOGV("[%s] flushDecoder needShutdown=%d",
1375 audio ? "audio" : "video", needShutdown);
1376
Chong Zhang7137ec72014-11-12 16:41:05 -08001377 const sp<DecoderBase> &decoder = getDecoder(audio);
Lajos Molnar87603c02014-08-20 19:25:30 -07001378 if (decoder == NULL) {
Steve Blockdf64d152012-01-04 20:05:49 +00001379 ALOGI("flushDecoder %s without decoder present",
Andreas Huber6e3d3112011-11-28 12:36:11 -08001380 audio ? "audio" : "video");
Lajos Molnar87603c02014-08-20 19:25:30 -07001381 return;
Andreas Huber6e3d3112011-11-28 12:36:11 -08001382 }
1383
Andreas Huber1aef2112011-01-04 14:01:29 -08001384 // Make sure we don't continue to scan sources until we finish flushing.
1385 ++mScanSourcesGeneration;
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001386 mScanSourcesPending = false;
Andreas Huber1aef2112011-01-04 14:01:29 -08001387
Chong Zhang7137ec72014-11-12 16:41:05 -08001388 decoder->signalFlush();
Andreas Huber1aef2112011-01-04 14:01:29 -08001389
1390 FlushStatus newStatus =
1391 needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
1392
Andy Hung8d121d42014-10-03 09:53:53 -07001393 mFlushComplete[audio][false /* isDecoder */] = false;
1394 mFlushComplete[audio][true /* isDecoder */] = false;
Andreas Huber1aef2112011-01-04 14:01:29 -08001395 if (audio) {
Wei Jia53904f32014-07-29 10:22:53 -07001396 ALOGE_IF(mFlushingAudio != NONE,
1397 "audio flushDecoder() is called in state %d", mFlushingAudio);
Andreas Huber1aef2112011-01-04 14:01:29 -08001398 mFlushingAudio = newStatus;
Andreas Huber1aef2112011-01-04 14:01:29 -08001399 } else {
Wei Jia53904f32014-07-29 10:22:53 -07001400 ALOGE_IF(mFlushingVideo != NONE,
1401 "video flushDecoder() is called in state %d", mFlushingVideo);
Andreas Huber1aef2112011-01-04 14:01:29 -08001402 mFlushingVideo = newStatus;
Andreas Huber1aef2112011-01-04 14:01:29 -08001403 }
1404}
1405
Chong Zhangced1c2f2014-08-08 15:22:35 -07001406void NuPlayer::queueDecoderShutdown(
1407 bool audio, bool video, const sp<AMessage> &reply) {
1408 ALOGI("queueDecoderShutdown audio=%d, video=%d", audio, video);
Andreas Huber84066782011-08-16 09:34:26 -07001409
Chong Zhangced1c2f2014-08-08 15:22:35 -07001410 mDeferredActions.push_back(
Wei Jiafef808d2014-10-31 17:57:05 -07001411 new FlushDecoderAction(
1412 audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE,
1413 video ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE));
Andreas Huber84066782011-08-16 09:34:26 -07001414
Chong Zhangced1c2f2014-08-08 15:22:35 -07001415 mDeferredActions.push_back(
1416 new SimpleAction(&NuPlayer::performScanSources));
Andreas Huber84066782011-08-16 09:34:26 -07001417
Chong Zhangced1c2f2014-08-08 15:22:35 -07001418 mDeferredActions.push_back(new PostMessageAction(reply));
1419
1420 processDeferredActions();
Andreas Huber84066782011-08-16 09:34:26 -07001421}
1422
James Dong0d268a32012-08-31 12:18:27 -07001423status_t NuPlayer::setVideoScalingMode(int32_t mode) {
1424 mVideoScalingMode = mode;
Andreas Huber57a339c2012-12-03 11:18:00 -08001425 if (mNativeWindow != NULL) {
James Dong0d268a32012-08-31 12:18:27 -07001426 status_t ret = native_window_set_scaling_mode(
1427 mNativeWindow->getNativeWindow().get(), mVideoScalingMode);
1428 if (ret != OK) {
1429 ALOGE("Failed to set scaling mode (%d): %s",
1430 -ret, strerror(-ret));
1431 return ret;
1432 }
1433 }
1434 return OK;
1435}
1436
Chong Zhangdcb89b32013-08-06 09:44:47 -07001437status_t NuPlayer::getTrackInfo(Parcel* reply) const {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001438 sp<AMessage> msg = new AMessage(kWhatGetTrackInfo, this);
Chong Zhangdcb89b32013-08-06 09:44:47 -07001439 msg->setPointer("reply", reply);
1440
1441 sp<AMessage> response;
1442 status_t err = msg->postAndAwaitResponse(&response);
1443 return err;
1444}
1445
Robert Shih7c4f0d72014-07-09 18:53:31 -07001446status_t NuPlayer::getSelectedTrack(int32_t type, Parcel* reply) const {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001447 sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, this);
Robert Shih7c4f0d72014-07-09 18:53:31 -07001448 msg->setPointer("reply", reply);
1449 msg->setInt32("type", type);
1450
1451 sp<AMessage> response;
1452 status_t err = msg->postAndAwaitResponse(&response);
1453 if (err == OK && response != NULL) {
1454 CHECK(response->findInt32("err", &err));
1455 }
1456 return err;
1457}
1458
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001459status_t NuPlayer::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001460 sp<AMessage> msg = new AMessage(kWhatSelectTrack, this);
Chong Zhangdcb89b32013-08-06 09:44:47 -07001461 msg->setSize("trackIndex", trackIndex);
1462 msg->setInt32("select", select);
Robert Shih6ffb1fd2014-10-29 16:24:32 -07001463 msg->setInt64("timeUs", timeUs);
Chong Zhangdcb89b32013-08-06 09:44:47 -07001464
1465 sp<AMessage> response;
1466 status_t err = msg->postAndAwaitResponse(&response);
1467
Chong Zhang404fced2014-06-11 14:45:31 -07001468 if (err != OK) {
1469 return err;
1470 }
1471
1472 if (!response->findInt32("err", &err)) {
1473 err = OK;
1474 }
1475
Chong Zhangdcb89b32013-08-06 09:44:47 -07001476 return err;
1477}
1478
Ronghua Wua73d9e02014-10-08 15:13:29 -07001479status_t NuPlayer::getCurrentPosition(int64_t *mediaUs) {
1480 sp<Renderer> renderer = mRenderer;
1481 if (renderer == NULL) {
1482 return NO_INIT;
1483 }
1484
1485 return renderer->getCurrentPosition(mediaUs);
1486}
1487
1488void NuPlayer::getStats(int64_t *numFramesTotal, int64_t *numFramesDropped) {
Chong Zhang7137ec72014-11-12 16:41:05 -08001489 sp<DecoderBase> decoder = getDecoder(false /* audio */);
1490 if (decoder != NULL) {
1491 decoder->getStats(numFramesTotal, numFramesDropped);
1492 } else {
1493 *numFramesTotal = 0;
1494 *numFramesDropped = 0;
1495 }
Ronghua Wua73d9e02014-10-08 15:13:29 -07001496}
1497
Marco Nelissenf0b72b52014-09-16 15:43:44 -07001498sp<MetaData> NuPlayer::getFileMeta() {
1499 return mSource->getFileFormatMeta();
1500}
1501
Andreas Huberb7c8e912012-11-27 15:02:53 -08001502void NuPlayer::schedulePollDuration() {
Lajos Molnar1d15ab52015-03-04 16:46:34 -08001503 sp<AMessage> msg = new AMessage(kWhatPollDuration, this);
Andreas Huberb7c8e912012-11-27 15:02:53 -08001504 msg->setInt32("generation", mPollDurationGeneration);
1505 msg->post();
1506}
1507
1508void NuPlayer::cancelPollDuration() {
1509 ++mPollDurationGeneration;
1510}
1511
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001512void NuPlayer::processDeferredActions() {
1513 while (!mDeferredActions.empty()) {
1514 // We won't execute any deferred actions until we're no longer in
1515 // an intermediate state, i.e. one more more decoders are currently
1516 // flushing or shutting down.
1517
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001518 if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
1519 // We're currently flushing, postpone the reset until that's
1520 // completed.
1521
1522 ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d",
1523 mFlushingAudio, mFlushingVideo);
1524
1525 break;
1526 }
1527
1528 sp<Action> action = *mDeferredActions.begin();
1529 mDeferredActions.erase(mDeferredActions.begin());
1530
1531 action->execute(this);
1532 }
1533}
1534
Wei Jiae427abf2014-09-22 15:21:11 -07001535void NuPlayer::performSeek(int64_t seekTimeUs, bool needNotify) {
1536 ALOGV("performSeek seekTimeUs=%lld us (%.2f secs), needNotify(%d)",
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001537 seekTimeUs,
Wei Jiae427abf2014-09-22 15:21:11 -07001538 seekTimeUs / 1E6,
1539 needNotify);
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001540
Andy Hungadf34bf2014-09-03 18:22:22 -07001541 if (mSource == NULL) {
1542 // This happens when reset occurs right before the loop mode
1543 // asynchronously seeks to the start of the stream.
1544 LOG_ALWAYS_FATAL_IF(mAudioDecoder != NULL || mVideoDecoder != NULL,
1545 "mSource is NULL and decoders not NULL audio(%p) video(%p)",
1546 mAudioDecoder.get(), mVideoDecoder.get());
1547 return;
1548 }
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001549 mSource->seekTo(seekTimeUs);
Robert Shihd3b0bbb2014-07-23 15:00:25 -07001550 ++mTimedTextGeneration;
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001551
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001552 // everything's flushed, continue playback.
1553}
1554
Wei Jiafef808d2014-10-31 17:57:05 -07001555void NuPlayer::performDecoderFlush(FlushCommand audio, FlushCommand video) {
1556 ALOGV("performDecoderFlush audio=%d, video=%d", audio, video);
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001557
Wei Jiafef808d2014-10-31 17:57:05 -07001558 if ((audio == FLUSH_CMD_NONE || mAudioDecoder == NULL)
1559 && (video == FLUSH_CMD_NONE || mVideoDecoder == NULL)) {
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001560 return;
1561 }
1562
Wei Jiafef808d2014-10-31 17:57:05 -07001563 if (audio != FLUSH_CMD_NONE && mAudioDecoder != NULL) {
1564 flushDecoder(true /* audio */, (audio == FLUSH_CMD_SHUTDOWN));
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001565 }
1566
Wei Jiafef808d2014-10-31 17:57:05 -07001567 if (video != FLUSH_CMD_NONE && mVideoDecoder != NULL) {
1568 flushDecoder(false /* audio */, (video == FLUSH_CMD_SHUTDOWN));
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001569 }
1570}
1571
1572void NuPlayer::performReset() {
1573 ALOGV("performReset");
1574
1575 CHECK(mAudioDecoder == NULL);
1576 CHECK(mVideoDecoder == NULL);
1577
1578 cancelPollDuration();
1579
1580 ++mScanSourcesGeneration;
1581 mScanSourcesPending = false;
1582
Lajos Molnar09524832014-07-17 14:29:51 -07001583 if (mRendererLooper != NULL) {
1584 if (mRenderer != NULL) {
1585 mRendererLooper->unregisterHandler(mRenderer->id());
1586 }
1587 mRendererLooper->stop();
1588 mRendererLooper.clear();
1589 }
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001590 mRenderer.clear();
Wei Jia57568df2014-09-22 10:16:29 -07001591 ++mRendererGeneration;
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001592
1593 if (mSource != NULL) {
1594 mSource->stop();
Andreas Huberb5f25f02013-02-05 10:14:26 -08001595
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001596 mSource.clear();
1597 }
1598
1599 if (mDriver != NULL) {
1600 sp<NuPlayerDriver> driver = mDriver.promote();
1601 if (driver != NULL) {
1602 driver->notifyResetComplete();
1603 }
1604 }
Andreas Huber57a339c2012-12-03 11:18:00 -08001605
1606 mStarted = false;
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001607}
1608
1609void NuPlayer::performScanSources() {
1610 ALOGV("performScanSources");
1611
Andreas Huber57a339c2012-12-03 11:18:00 -08001612 if (!mStarted) {
1613 return;
1614 }
1615
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001616 if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
1617 postScanSources();
1618 }
1619}
1620
Andreas Huber57a339c2012-12-03 11:18:00 -08001621void NuPlayer::performSetSurface(const sp<NativeWindowWrapper> &wrapper) {
1622 ALOGV("performSetSurface");
1623
1624 mNativeWindow = wrapper;
1625
1626 // XXX - ignore error from setVideoScalingMode for now
1627 setVideoScalingMode(mVideoScalingMode);
Chong Zhang13d6faa2014-08-22 15:35:28 -07001628
1629 if (mDriver != NULL) {
1630 sp<NuPlayerDriver> driver = mDriver.promote();
1631 if (driver != NULL) {
1632 driver->notifySetSurfaceComplete();
1633 }
1634 }
Andreas Huber57a339c2012-12-03 11:18:00 -08001635}
1636
Chong Zhangf8d71772014-11-26 15:08:34 -08001637void NuPlayer::performResumeDecoders(bool needNotify) {
1638 if (needNotify) {
1639 mResumePending = true;
1640 if (mVideoDecoder == NULL) {
1641 // if audio-only, we can notify seek complete now,
1642 // as the resume operation will be relatively fast.
1643 finishResume();
1644 }
1645 }
1646
Chong Zhang7137ec72014-11-12 16:41:05 -08001647 if (mVideoDecoder != NULL) {
Chong Zhangf8d71772014-11-26 15:08:34 -08001648 // When there is continuous seek, MediaPlayer will cache the seek
1649 // position, and send down new seek request when previous seek is
1650 // complete. Let's wait for at least one video output frame before
1651 // notifying seek complete, so that the video thumbnail gets updated
1652 // when seekbar is dragged.
1653 mVideoDecoder->signalResume(needNotify);
Chong Zhang7137ec72014-11-12 16:41:05 -08001654 }
1655
1656 if (mAudioDecoder != NULL) {
Chong Zhangf8d71772014-11-26 15:08:34 -08001657 mAudioDecoder->signalResume(false /* needNotify */);
1658 }
1659}
1660
1661void NuPlayer::finishResume() {
1662 if (mResumePending) {
1663 mResumePending = false;
1664 if (mDriver != NULL) {
1665 sp<NuPlayerDriver> driver = mDriver.promote();
1666 if (driver != NULL) {
1667 driver->notifySeekComplete();
1668 }
1669 }
Chong Zhang7137ec72014-11-12 16:41:05 -08001670 }
1671}
1672
Andreas Huber9575c962013-02-05 13:59:56 -08001673void NuPlayer::onSourceNotify(const sp<AMessage> &msg) {
1674 int32_t what;
1675 CHECK(msg->findInt32("what", &what));
1676
1677 switch (what) {
1678 case Source::kWhatPrepared:
1679 {
Andreas Huberb5f28d42013-04-25 15:11:19 -07001680 if (mSource == NULL) {
1681 // This is a stale notification from a source that was
1682 // asynchronously preparing when the client called reset().
1683 // We handled the reset, the source is gone.
1684 break;
1685 }
1686
Andreas Huberec0c5972013-02-05 14:47:13 -08001687 int32_t err;
1688 CHECK(msg->findInt32("err", &err));
1689
Andreas Huber9575c962013-02-05 13:59:56 -08001690 sp<NuPlayerDriver> driver = mDriver.promote();
1691 if (driver != NULL) {
Marco Nelissendd114d12014-05-28 15:23:14 -07001692 // notify duration first, so that it's definitely set when
1693 // the app received the "prepare complete" callback.
1694 int64_t durationUs;
1695 if (mSource->getDuration(&durationUs) == OK) {
1696 driver->notifyDuration(durationUs);
1697 }
Andreas Huberec0c5972013-02-05 14:47:13 -08001698 driver->notifyPrepareCompleted(err);
Andreas Huber9575c962013-02-05 13:59:56 -08001699 }
Andreas Huber99759402013-04-01 14:28:31 -07001700
Andreas Huber9575c962013-02-05 13:59:56 -08001701 break;
1702 }
1703
1704 case Source::kWhatFlagsChanged:
1705 {
1706 uint32_t flags;
1707 CHECK(msg->findInt32("flags", (int32_t *)&flags));
1708
Chong Zhang4b7069d2013-09-11 12:52:43 -07001709 sp<NuPlayerDriver> driver = mDriver.promote();
1710 if (driver != NULL) {
Wei Jia895651b2014-12-10 17:31:52 -08001711 if ((flags & NuPlayer::Source::FLAG_CAN_SEEK) == 0) {
1712 driver->notifyListener(
1713 MEDIA_INFO, MEDIA_INFO_NOT_SEEKABLE, 0);
1714 }
Chong Zhang4b7069d2013-09-11 12:52:43 -07001715 driver->notifyFlagsChanged(flags);
1716 }
1717
Andreas Huber9575c962013-02-05 13:59:56 -08001718 if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
1719 && (!(flags & Source::FLAG_DYNAMIC_DURATION))) {
1720 cancelPollDuration();
1721 } else if (!(mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
1722 && (flags & Source::FLAG_DYNAMIC_DURATION)
1723 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
1724 schedulePollDuration();
1725 }
1726
1727 mSourceFlags = flags;
1728 break;
1729 }
1730
1731 case Source::kWhatVideoSizeChanged:
1732 {
Chong Zhangced1c2f2014-08-08 15:22:35 -07001733 sp<AMessage> format;
1734 CHECK(msg->findMessage("format", &format));
Andreas Huber9575c962013-02-05 13:59:56 -08001735
Chong Zhangced1c2f2014-08-08 15:22:35 -07001736 updateVideoSize(format);
Andreas Huber9575c962013-02-05 13:59:56 -08001737 break;
1738 }
1739
Chong Zhang2a3cc9a2014-08-21 17:48:26 -07001740 case Source::kWhatBufferingUpdate:
1741 {
1742 int32_t percentage;
1743 CHECK(msg->findInt32("percentage", &percentage));
1744
1745 notifyListener(MEDIA_BUFFERING_UPDATE, percentage, 0);
1746 break;
1747 }
1748
Chong Zhangefbb6192015-01-30 17:13:27 -08001749 case Source::kWhatPauseOnBufferingStart:
1750 {
1751 // ignore if not playing
1752 if (mStarted && !mPausedByClient) {
1753 ALOGI("buffer low, pausing...");
1754
1755 onPause();
1756 }
1757 // fall-thru
1758 }
1759
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001760 case Source::kWhatBufferingStart:
1761 {
1762 notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0);
1763 break;
1764 }
1765
Chong Zhangefbb6192015-01-30 17:13:27 -08001766 case Source::kWhatResumeOnBufferingEnd:
1767 {
1768 // ignore if not playing
1769 if (mStarted && !mPausedByClient) {
1770 ALOGI("buffer ready, resuming...");
1771
1772 onResume();
1773 }
1774 // fall-thru
1775 }
1776
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001777 case Source::kWhatBufferingEnd:
1778 {
1779 notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0);
1780 break;
1781 }
1782
Chong Zhangefbb6192015-01-30 17:13:27 -08001783 case Source::kWhatCacheStats:
1784 {
1785 int32_t kbps;
1786 CHECK(msg->findInt32("bandwidth", &kbps));
1787
1788 notifyListener(MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
1789 break;
1790 }
1791
Chong Zhangdcb89b32013-08-06 09:44:47 -07001792 case Source::kWhatSubtitleData:
1793 {
1794 sp<ABuffer> buffer;
1795 CHECK(msg->findBuffer("buffer", &buffer));
1796
Chong Zhang404fced2014-06-11 14:45:31 -07001797 sendSubtitleData(buffer, 0 /* baseIndex */);
Chong Zhangdcb89b32013-08-06 09:44:47 -07001798 break;
1799 }
1800
Robert Shihd3b0bbb2014-07-23 15:00:25 -07001801 case Source::kWhatTimedTextData:
1802 {
1803 int32_t generation;
1804 if (msg->findInt32("generation", &generation)
1805 && generation != mTimedTextGeneration) {
1806 break;
1807 }
1808
1809 sp<ABuffer> buffer;
1810 CHECK(msg->findBuffer("buffer", &buffer));
1811
1812 sp<NuPlayerDriver> driver = mDriver.promote();
1813 if (driver == NULL) {
1814 break;
1815 }
1816
1817 int posMs;
1818 int64_t timeUs, posUs;
1819 driver->getCurrentPosition(&posMs);
1820 posUs = posMs * 1000;
1821 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1822
1823 if (posUs < timeUs) {
1824 if (!msg->findInt32("generation", &generation)) {
1825 msg->setInt32("generation", mTimedTextGeneration);
1826 }
1827 msg->post(timeUs - posUs);
1828 } else {
1829 sendTimedTextData(buffer);
1830 }
1831 break;
1832 }
1833
Andreas Huber14f76722013-01-15 09:04:18 -08001834 case Source::kWhatQueueDecoderShutdown:
1835 {
1836 int32_t audio, video;
1837 CHECK(msg->findInt32("audio", &audio));
1838 CHECK(msg->findInt32("video", &video));
1839
1840 sp<AMessage> reply;
1841 CHECK(msg->findMessage("reply", &reply));
1842
1843 queueDecoderShutdown(audio, video, reply);
1844 break;
1845 }
1846
Ronghua Wu80276872014-08-28 15:50:29 -07001847 case Source::kWhatDrmNoLicense:
1848 {
1849 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE);
1850 break;
1851 }
1852
Andreas Huber9575c962013-02-05 13:59:56 -08001853 default:
1854 TRESPASS();
1855 }
1856}
1857
Chong Zhanga7fa1d92014-06-11 14:49:23 -07001858void NuPlayer::onClosedCaptionNotify(const sp<AMessage> &msg) {
1859 int32_t what;
1860 CHECK(msg->findInt32("what", &what));
1861
1862 switch (what) {
1863 case NuPlayer::CCDecoder::kWhatClosedCaptionData:
1864 {
1865 sp<ABuffer> buffer;
1866 CHECK(msg->findBuffer("buffer", &buffer));
1867
1868 size_t inbandTracks = 0;
1869 if (mSource != NULL) {
1870 inbandTracks = mSource->getTrackCount();
1871 }
1872
1873 sendSubtitleData(buffer, inbandTracks);
1874 break;
1875 }
1876
1877 case NuPlayer::CCDecoder::kWhatTrackAdded:
1878 {
1879 notifyListener(MEDIA_INFO, MEDIA_INFO_METADATA_UPDATE, 0);
1880
1881 break;
1882 }
1883
1884 default:
1885 TRESPASS();
1886 }
1887
1888
1889}
1890
Chong Zhang404fced2014-06-11 14:45:31 -07001891void NuPlayer::sendSubtitleData(const sp<ABuffer> &buffer, int32_t baseIndex) {
1892 int32_t trackIndex;
1893 int64_t timeUs, durationUs;
1894 CHECK(buffer->meta()->findInt32("trackIndex", &trackIndex));
1895 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1896 CHECK(buffer->meta()->findInt64("durationUs", &durationUs));
1897
1898 Parcel in;
1899 in.writeInt32(trackIndex + baseIndex);
1900 in.writeInt64(timeUs);
1901 in.writeInt64(durationUs);
1902 in.writeInt32(buffer->size());
1903 in.writeInt32(buffer->size());
1904 in.write(buffer->data(), buffer->size());
1905
1906 notifyListener(MEDIA_SUBTITLE_DATA, 0, 0, &in);
1907}
Robert Shihd3b0bbb2014-07-23 15:00:25 -07001908
1909void NuPlayer::sendTimedTextData(const sp<ABuffer> &buffer) {
1910 const void *data;
1911 size_t size = 0;
1912 int64_t timeUs;
1913 int32_t flag = TextDescriptions::LOCAL_DESCRIPTIONS;
1914
1915 AString mime;
1916 CHECK(buffer->meta()->findString("mime", &mime));
1917 CHECK(strcasecmp(mime.c_str(), MEDIA_MIMETYPE_TEXT_3GPP) == 0);
1918
1919 data = buffer->data();
1920 size = buffer->size();
1921
1922 Parcel parcel;
1923 if (size > 0) {
1924 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1925 flag |= TextDescriptions::IN_BAND_TEXT_3GPP;
1926 TextDescriptions::getParcelOfDescriptions(
1927 (const uint8_t *)data, size, flag, timeUs / 1000, &parcel);
1928 }
1929
1930 if ((parcel.dataSize() > 0)) {
1931 notifyListener(MEDIA_TIMED_TEXT, 0, 0, &parcel);
1932 } else { // send an empty timed text
1933 notifyListener(MEDIA_TIMED_TEXT, 0, 0);
1934 }
1935}
Andreas Huberb5f25f02013-02-05 10:14:26 -08001936////////////////////////////////////////////////////////////////////////////////
1937
Chong Zhangced1c2f2014-08-08 15:22:35 -07001938sp<AMessage> NuPlayer::Source::getFormat(bool audio) {
1939 sp<MetaData> meta = getFormatMeta(audio);
1940
1941 if (meta == NULL) {
1942 return NULL;
1943 }
1944
1945 sp<AMessage> msg = new AMessage;
1946
1947 if(convertMetaDataToMessage(meta, &msg) == OK) {
1948 return msg;
1949 }
1950 return NULL;
1951}
1952
Andreas Huber9575c962013-02-05 13:59:56 -08001953void NuPlayer::Source::notifyFlagsChanged(uint32_t flags) {
1954 sp<AMessage> notify = dupNotify();
1955 notify->setInt32("what", kWhatFlagsChanged);
1956 notify->setInt32("flags", flags);
1957 notify->post();
1958}
1959
Chong Zhangced1c2f2014-08-08 15:22:35 -07001960void NuPlayer::Source::notifyVideoSizeChanged(const sp<AMessage> &format) {
Andreas Huber9575c962013-02-05 13:59:56 -08001961 sp<AMessage> notify = dupNotify();
1962 notify->setInt32("what", kWhatVideoSizeChanged);
Chong Zhangced1c2f2014-08-08 15:22:35 -07001963 notify->setMessage("format", format);
Andreas Huber9575c962013-02-05 13:59:56 -08001964 notify->post();
1965}
1966
Andreas Huberec0c5972013-02-05 14:47:13 -08001967void NuPlayer::Source::notifyPrepared(status_t err) {
Andreas Huber9575c962013-02-05 13:59:56 -08001968 sp<AMessage> notify = dupNotify();
1969 notify->setInt32("what", kWhatPrepared);
Andreas Huberec0c5972013-02-05 14:47:13 -08001970 notify->setInt32("err", err);
Andreas Huber9575c962013-02-05 13:59:56 -08001971 notify->post();
1972}
1973
Andreas Huber84333e02014-02-07 15:36:10 -08001974void NuPlayer::Source::onMessageReceived(const sp<AMessage> & /* msg */) {
Andreas Huberb5f25f02013-02-05 10:14:26 -08001975 TRESPASS();
1976}
1977
Andreas Huberf9334412010-12-15 15:17:42 -08001978} // namespace android