blob: 607ec6a9261357f27ea15a6773d8a5d6cb66422d [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"
Andreas Huberf9334412010-12-15 15:17:42 -080024#include "NuPlayerDecoder.h"
Andreas Huber43c3e6c2011-01-05 12:17:08 -080025#include "NuPlayerDriver.h"
Andreas Huberf9334412010-12-15 15:17:42 -080026#include "NuPlayerRenderer.h"
Andreas Huber5bc087c2010-12-23 10:27:40 -080027#include "NuPlayerSource.h"
Andreas Huber2bfdd422011-10-11 15:24:07 -070028#include "RTSPSource.h"
Andreas Huber5bc087c2010-12-23 10:27:40 -080029#include "StreamingSource.h"
Andreas Huberafed0e12011-09-20 15:39:58 -070030#include "GenericSource.h"
Andreas Huber84066782011-08-16 09:34:26 -070031#include "mp4/MP4Source.h"
Andreas Huber5bc087c2010-12-23 10:27:40 -080032
33#include "ATSParser.h"
Andreas Huberf9334412010-12-15 15:17:42 -080034
Andreas Huber84066782011-08-16 09:34:26 -070035#include <cutils/properties.h> // for property_get
Andreas Huber3831a062010-12-21 10:22:33 -080036#include <media/stagefright/foundation/hexdump.h>
Andreas Huberf9334412010-12-15 15:17:42 -080037#include <media/stagefright/foundation/ABuffer.h>
38#include <media/stagefright/foundation/ADebug.h>
39#include <media/stagefright/foundation/AMessage.h>
40#include <media/stagefright/ACodec.h>
Andreas Huber3fe62152011-09-16 15:09:22 -070041#include <media/stagefright/MediaDefs.h>
Andreas Huberf9334412010-12-15 15:17:42 -080042#include <media/stagefright/MediaErrors.h>
43#include <media/stagefright/MetaData.h>
Andy McFadden8ba01022012-12-18 09:46:54 -080044#include <gui/IGraphicBufferProducer.h>
Andreas Huberf9334412010-12-15 15:17:42 -080045
Andreas Huber3fe62152011-09-16 15:09:22 -070046#include "avc_utils.h"
47
Andreas Huber84066782011-08-16 09:34:26 -070048#include "ESDS.h"
49#include <media/stagefright/Utils.h>
50
Andreas Huberf9334412010-12-15 15:17:42 -080051namespace android {
52
Andreas Hubera1f8ab02012-11-30 10:53:22 -080053struct NuPlayer::Action : public RefBase {
54 Action() {}
55
56 virtual void execute(NuPlayer *player) = 0;
57
58private:
59 DISALLOW_EVIL_CONSTRUCTORS(Action);
60};
61
62struct NuPlayer::SeekAction : public Action {
63 SeekAction(int64_t seekTimeUs)
64 : mSeekTimeUs(seekTimeUs) {
65 }
66
67 virtual void execute(NuPlayer *player) {
68 player->performSeek(mSeekTimeUs);
69 }
70
71private:
72 int64_t mSeekTimeUs;
73
74 DISALLOW_EVIL_CONSTRUCTORS(SeekAction);
75};
76
Andreas Huber57a339c2012-12-03 11:18:00 -080077struct NuPlayer::SetSurfaceAction : public Action {
78 SetSurfaceAction(const sp<NativeWindowWrapper> &wrapper)
79 : mWrapper(wrapper) {
80 }
81
82 virtual void execute(NuPlayer *player) {
83 player->performSetSurface(mWrapper);
84 }
85
86private:
87 sp<NativeWindowWrapper> mWrapper;
88
89 DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction);
90};
91
Andreas Hubera1f8ab02012-11-30 10:53:22 -080092// Use this if there's no state necessary to save in order to execute
93// the action.
94struct NuPlayer::SimpleAction : public Action {
95 typedef void (NuPlayer::*ActionFunc)();
96
97 SimpleAction(ActionFunc func)
98 : mFunc(func) {
99 }
100
101 virtual void execute(NuPlayer *player) {
102 (player->*mFunc)();
103 }
104
105private:
106 ActionFunc mFunc;
107
108 DISALLOW_EVIL_CONSTRUCTORS(SimpleAction);
109};
110
Andreas Huberf9334412010-12-15 15:17:42 -0800111////////////////////////////////////////////////////////////////////////////////
112
113NuPlayer::NuPlayer()
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700114 : mUIDValid(false),
Andreas Huber9575c962013-02-05 13:59:56 -0800115 mSourceFlags(0),
Andreas Huber3fe62152011-09-16 15:09:22 -0700116 mVideoIsAVC(false),
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700117 mAudioEOS(false),
Andreas Huberf9334412010-12-15 15:17:42 -0800118 mVideoEOS(false),
Andreas Huber5bc087c2010-12-23 10:27:40 -0800119 mScanSourcesPending(false),
Andreas Huber1aef2112011-01-04 14:01:29 -0800120 mScanSourcesGeneration(0),
Andreas Huberb7c8e912012-11-27 15:02:53 -0800121 mPollDurationGeneration(0),
Andreas Huber6e3d3112011-11-28 12:36:11 -0800122 mTimeDiscontinuityPending(false),
Andreas Huberf9334412010-12-15 15:17:42 -0800123 mFlushingAudio(NONE),
Andreas Huber1aef2112011-01-04 14:01:29 -0800124 mFlushingVideo(NONE),
Andreas Huber3fe62152011-09-16 15:09:22 -0700125 mSkipRenderingAudioUntilMediaTimeUs(-1ll),
126 mSkipRenderingVideoUntilMediaTimeUs(-1ll),
127 mVideoLateByUs(0ll),
128 mNumFramesTotal(0ll),
James Dong0d268a32012-08-31 12:18:27 -0700129 mNumFramesDropped(0ll),
Andreas Huber57a339c2012-12-03 11:18:00 -0800130 mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
131 mStarted(false) {
Andreas Huberf9334412010-12-15 15:17:42 -0800132}
133
134NuPlayer::~NuPlayer() {
135}
136
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700137void NuPlayer::setUID(uid_t uid) {
138 mUIDValid = true;
139 mUID = uid;
140}
141
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800142void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
143 mDriver = driver;
Andreas Huberf9334412010-12-15 15:17:42 -0800144}
145
Andreas Huber9575c962013-02-05 13:59:56 -0800146void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) {
Andreas Huberf9334412010-12-15 15:17:42 -0800147 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
148
Andreas Huberb5f25f02013-02-05 10:14:26 -0800149 sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
150
Andreas Huber84066782011-08-16 09:34:26 -0700151 char prop[PROPERTY_VALUE_MAX];
152 if (property_get("media.stagefright.use-mp4source", prop, NULL)
153 && (!strcmp(prop, "1") || !strcasecmp(prop, "true"))) {
Andreas Huberb5f25f02013-02-05 10:14:26 -0800154 msg->setObject("source", new MP4Source(notify, source));
Andreas Huber84066782011-08-16 09:34:26 -0700155 } else {
Andreas Huberb5f25f02013-02-05 10:14:26 -0800156 msg->setObject("source", new StreamingSource(notify, source));
Andreas Huber84066782011-08-16 09:34:26 -0700157 }
158
Andreas Huber5bc087c2010-12-23 10:27:40 -0800159 msg->post();
160}
Andreas Huberf9334412010-12-15 15:17:42 -0800161
Andreas Huberafed0e12011-09-20 15:39:58 -0700162static bool IsHTTPLiveURL(const char *url) {
163 if (!strncasecmp("http://", url, 7)
Andreas Huber99759402013-04-01 14:28:31 -0700164 || !strncasecmp("https://", url, 8)
165 || !strncasecmp("file://", url, 7)) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700166 size_t len = strlen(url);
167 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
168 return true;
169 }
170
171 if (strstr(url,"m3u8")) {
172 return true;
173 }
174 }
175
176 return false;
177}
178
Andreas Huber9575c962013-02-05 13:59:56 -0800179void NuPlayer::setDataSourceAsync(
Andreas Huber5bc087c2010-12-23 10:27:40 -0800180 const char *url, const KeyedVector<String8, String8> *headers) {
181 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
Oscar Rydhé7a33b772012-02-20 10:15:48 +0100182 size_t len = strlen(url);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800183
Andreas Huberb5f25f02013-02-05 10:14:26 -0800184 sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
185
Andreas Huberafed0e12011-09-20 15:39:58 -0700186 sp<Source> source;
187 if (IsHTTPLiveURL(url)) {
Andreas Huberb5f25f02013-02-05 10:14:26 -0800188 source = new HTTPLiveSource(notify, url, headers, mUIDValid, mUID);
Andreas Huberafed0e12011-09-20 15:39:58 -0700189 } else if (!strncasecmp(url, "rtsp://", 7)) {
Andreas Huberb5f25f02013-02-05 10:14:26 -0800190 source = new RTSPSource(notify, url, headers, mUIDValid, mUID);
Oscar Rydhé7a33b772012-02-20 10:15:48 +0100191 } else if ((!strncasecmp(url, "http://", 7)
192 || !strncasecmp(url, "https://", 8))
193 && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
194 || strstr(url, ".sdp?"))) {
195 source = new RTSPSource(notify, url, headers, mUIDValid, mUID, true);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700196 } else {
Andreas Huberb5f25f02013-02-05 10:14:26 -0800197 source = new GenericSource(notify, url, headers, mUIDValid, mUID);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700198 }
199
Andreas Huberafed0e12011-09-20 15:39:58 -0700200 msg->setObject("source", source);
201 msg->post();
202}
203
Andreas Huber9575c962013-02-05 13:59:56 -0800204void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700205 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
206
Andreas Huberb5f25f02013-02-05 10:14:26 -0800207 sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
208
209 sp<Source> source = new GenericSource(notify, fd, offset, length);
Andreas Huberafed0e12011-09-20 15:39:58 -0700210 msg->setObject("source", source);
Andreas Huberf9334412010-12-15 15:17:42 -0800211 msg->post();
212}
213
Andreas Huber9575c962013-02-05 13:59:56 -0800214void NuPlayer::prepareAsync() {
215 (new AMessage(kWhatPrepare, id()))->post();
216}
217
Andreas Huber57a339c2012-12-03 11:18:00 -0800218void NuPlayer::setVideoSurfaceTextureAsync(
Andy McFadden8ba01022012-12-18 09:46:54 -0800219 const sp<IGraphicBufferProducer> &bufferProducer) {
Glenn Kasten11731182011-02-08 17:26:17 -0800220 sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
Andreas Huber57a339c2012-12-03 11:18:00 -0800221
Andy McFadden8ba01022012-12-18 09:46:54 -0800222 if (bufferProducer == NULL) {
Andreas Huber57a339c2012-12-03 11:18:00 -0800223 msg->setObject("native-window", NULL);
224 } else {
225 msg->setObject(
226 "native-window",
227 new NativeWindowWrapper(
Mathias Agopian1a2952a2013-02-14 17:11:27 -0800228 new Surface(bufferProducer)));
Andreas Huber57a339c2012-12-03 11:18:00 -0800229 }
230
Andreas Huberf9334412010-12-15 15:17:42 -0800231 msg->post();
232}
233
234void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) {
235 sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id());
236 msg->setObject("sink", sink);
237 msg->post();
238}
239
240void NuPlayer::start() {
241 (new AMessage(kWhatStart, id()))->post();
242}
243
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800244void NuPlayer::pause() {
Andreas Huberb4082222011-01-20 15:23:04 -0800245 (new AMessage(kWhatPause, id()))->post();
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800246}
247
248void NuPlayer::resume() {
Andreas Huberb4082222011-01-20 15:23:04 -0800249 (new AMessage(kWhatResume, id()))->post();
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800250}
251
Andreas Huber1aef2112011-01-04 14:01:29 -0800252void NuPlayer::resetAsync() {
253 (new AMessage(kWhatReset, id()))->post();
254}
255
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800256void NuPlayer::seekToAsync(int64_t seekTimeUs) {
257 sp<AMessage> msg = new AMessage(kWhatSeek, id());
258 msg->setInt64("seekTimeUs", seekTimeUs);
259 msg->post();
260}
261
Andreas Huber53df1a42010-12-22 10:03:04 -0800262// static
Andreas Huber1aef2112011-01-04 14:01:29 -0800263bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
Andreas Huber53df1a42010-12-22 10:03:04 -0800264 switch (state) {
265 case FLUSHING_DECODER:
Andreas Huber1aef2112011-01-04 14:01:29 -0800266 if (needShutdown != NULL) {
267 *needShutdown = false;
Andreas Huber53df1a42010-12-22 10:03:04 -0800268 }
269 return true;
270
Andreas Huber1aef2112011-01-04 14:01:29 -0800271 case FLUSHING_DECODER_SHUTDOWN:
272 if (needShutdown != NULL) {
273 *needShutdown = true;
Andreas Huber53df1a42010-12-22 10:03:04 -0800274 }
275 return true;
276
277 default:
278 return false;
279 }
280}
281
Andreas Huberf9334412010-12-15 15:17:42 -0800282void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
283 switch (msg->what()) {
284 case kWhatSetDataSource:
285 {
Steve Block3856b092011-10-20 11:56:00 +0100286 ALOGV("kWhatSetDataSource");
Andreas Huberf9334412010-12-15 15:17:42 -0800287
288 CHECK(mSource == NULL);
289
Andreas Huber5bc087c2010-12-23 10:27:40 -0800290 sp<RefBase> obj;
291 CHECK(msg->findObject("source", &obj));
Andreas Huberf9334412010-12-15 15:17:42 -0800292
Andreas Huber5bc087c2010-12-23 10:27:40 -0800293 mSource = static_cast<Source *>(obj.get());
Andreas Huberb5f25f02013-02-05 10:14:26 -0800294
295 looper()->registerHandler(mSource);
Andreas Huber9575c962013-02-05 13:59:56 -0800296
297 CHECK(mDriver != NULL);
298 sp<NuPlayerDriver> driver = mDriver.promote();
299 if (driver != NULL) {
300 driver->notifySetDataSourceCompleted(OK);
301 }
302 break;
303 }
304
305 case kWhatPrepare:
306 {
307 mSource->prepareAsync();
Andreas Huberf9334412010-12-15 15:17:42 -0800308 break;
309 }
310
Andreas Huberb7c8e912012-11-27 15:02:53 -0800311 case kWhatPollDuration:
312 {
313 int32_t generation;
314 CHECK(msg->findInt32("generation", &generation));
315
316 if (generation != mPollDurationGeneration) {
317 // stale
318 break;
319 }
320
321 int64_t durationUs;
322 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
323 sp<NuPlayerDriver> driver = mDriver.promote();
324 if (driver != NULL) {
325 driver->notifyDuration(durationUs);
326 }
327 }
328
329 msg->post(1000000ll); // poll again in a second.
330 break;
331 }
332
Glenn Kasten11731182011-02-08 17:26:17 -0800333 case kWhatSetVideoNativeWindow:
Andreas Huberf9334412010-12-15 15:17:42 -0800334 {
Steve Block3856b092011-10-20 11:56:00 +0100335 ALOGV("kWhatSetVideoNativeWindow");
Andreas Huberf9334412010-12-15 15:17:42 -0800336
Andreas Huber57a339c2012-12-03 11:18:00 -0800337 mDeferredActions.push_back(
338 new SimpleAction(&NuPlayer::performDecoderShutdown));
339
Andreas Huberf9334412010-12-15 15:17:42 -0800340 sp<RefBase> obj;
Glenn Kasten11731182011-02-08 17:26:17 -0800341 CHECK(msg->findObject("native-window", &obj));
Andreas Huberf9334412010-12-15 15:17:42 -0800342
Andreas Huber57a339c2012-12-03 11:18:00 -0800343 mDeferredActions.push_back(
344 new SetSurfaceAction(
345 static_cast<NativeWindowWrapper *>(obj.get())));
James Dong0d268a32012-08-31 12:18:27 -0700346
Andreas Huber57a339c2012-12-03 11:18:00 -0800347 if (obj != NULL) {
348 // If there is a new surface texture, instantiate decoders
349 // again if possible.
350 mDeferredActions.push_back(
351 new SimpleAction(&NuPlayer::performScanSources));
352 }
353
354 processDeferredActions();
Andreas Huberf9334412010-12-15 15:17:42 -0800355 break;
356 }
357
358 case kWhatSetAudioSink:
359 {
Steve Block3856b092011-10-20 11:56:00 +0100360 ALOGV("kWhatSetAudioSink");
Andreas Huberf9334412010-12-15 15:17:42 -0800361
362 sp<RefBase> obj;
363 CHECK(msg->findObject("sink", &obj));
364
365 mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get());
366 break;
367 }
368
369 case kWhatStart:
370 {
Steve Block3856b092011-10-20 11:56:00 +0100371 ALOGV("kWhatStart");
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800372
Andreas Huber3fe62152011-09-16 15:09:22 -0700373 mVideoIsAVC = false;
Andreas Huber1aef2112011-01-04 14:01:29 -0800374 mAudioEOS = false;
375 mVideoEOS = false;
Andreas Huber32f3cef2011-03-02 15:34:46 -0800376 mSkipRenderingAudioUntilMediaTimeUs = -1;
377 mSkipRenderingVideoUntilMediaTimeUs = -1;
Andreas Huber3fe62152011-09-16 15:09:22 -0700378 mVideoLateByUs = 0;
379 mNumFramesTotal = 0;
380 mNumFramesDropped = 0;
Andreas Huber57a339c2012-12-03 11:18:00 -0800381 mStarted = true;
Andreas Huber1aef2112011-01-04 14:01:29 -0800382
Andreas Huber5bc087c2010-12-23 10:27:40 -0800383 mSource->start();
Andreas Huberf9334412010-12-15 15:17:42 -0800384
Andreas Huberd5e56232013-03-12 11:01:43 -0700385 uint32_t flags = 0;
386
387 if (mSource->isRealTime()) {
388 flags |= Renderer::FLAG_REAL_TIME;
389 }
390
Andreas Huberf9334412010-12-15 15:17:42 -0800391 mRenderer = new Renderer(
392 mAudioSink,
Andreas Huberd5e56232013-03-12 11:01:43 -0700393 new AMessage(kWhatRendererNotify, id()),
394 flags);
Andreas Huberf9334412010-12-15 15:17:42 -0800395
396 looper()->registerHandler(mRenderer);
397
Andreas Huber1aef2112011-01-04 14:01:29 -0800398 postScanSources();
Andreas Huberf9334412010-12-15 15:17:42 -0800399 break;
400 }
401
402 case kWhatScanSources:
403 {
Andreas Huber1aef2112011-01-04 14:01:29 -0800404 int32_t generation;
405 CHECK(msg->findInt32("generation", &generation));
406 if (generation != mScanSourcesGeneration) {
407 // Drop obsolete msg.
408 break;
409 }
410
Andreas Huber5bc087c2010-12-23 10:27:40 -0800411 mScanSourcesPending = false;
412
Steve Block3856b092011-10-20 11:56:00 +0100413 ALOGV("scanning sources haveAudio=%d, haveVideo=%d",
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800414 mAudioDecoder != NULL, mVideoDecoder != NULL);
415
Andreas Huberb7c8e912012-11-27 15:02:53 -0800416 bool mHadAnySourcesBefore =
417 (mAudioDecoder != NULL) || (mVideoDecoder != NULL);
418
Haynes Mathew George5d246ef2012-07-09 10:36:57 -0700419 if (mNativeWindow != NULL) {
420 instantiateDecoder(false, &mVideoDecoder);
421 }
Andreas Huberf9334412010-12-15 15:17:42 -0800422
423 if (mAudioSink != NULL) {
Andreas Huber5bc087c2010-12-23 10:27:40 -0800424 instantiateDecoder(true, &mAudioDecoder);
Andreas Huberf9334412010-12-15 15:17:42 -0800425 }
426
Andreas Huberb7c8e912012-11-27 15:02:53 -0800427 if (!mHadAnySourcesBefore
428 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
429 // This is the first time we've found anything playable.
430
Andreas Huber9575c962013-02-05 13:59:56 -0800431 if (mSourceFlags & Source::FLAG_DYNAMIC_DURATION) {
Andreas Huberb7c8e912012-11-27 15:02:53 -0800432 schedulePollDuration();
433 }
434 }
435
Andreas Hubereac68ba2011-09-27 12:12:25 -0700436 status_t err;
437 if ((err = mSource->feedMoreTSData()) != OK) {
Andreas Huber1aef2112011-01-04 14:01:29 -0800438 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
439 // We're not currently decoding anything (no audio or
440 // video tracks found) and we just ran out of input data.
Andreas Hubereac68ba2011-09-27 12:12:25 -0700441
442 if (err == ERROR_END_OF_STREAM) {
443 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
444 } else {
445 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
446 }
Andreas Huber1aef2112011-01-04 14:01:29 -0800447 }
Andreas Huberf9334412010-12-15 15:17:42 -0800448 break;
449 }
450
Andreas Huberfbe9d812012-08-31 14:05:27 -0700451 if ((mAudioDecoder == NULL && mAudioSink != NULL)
452 || (mVideoDecoder == NULL && mNativeWindow != NULL)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800453 msg->post(100000ll);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800454 mScanSourcesPending = true;
Andreas Huberf9334412010-12-15 15:17:42 -0800455 }
456 break;
457 }
458
459 case kWhatVideoNotify:
460 case kWhatAudioNotify:
461 {
462 bool audio = msg->what() == kWhatAudioNotify;
463
464 sp<AMessage> codecRequest;
465 CHECK(msg->findMessage("codec-request", &codecRequest));
466
467 int32_t what;
468 CHECK(codecRequest->findInt32("what", &what));
469
470 if (what == ACodec::kWhatFillThisBuffer) {
471 status_t err = feedDecoderInputData(
472 audio, codecRequest);
473
Andreas Huber5bc087c2010-12-23 10:27:40 -0800474 if (err == -EWOULDBLOCK) {
Andreas Hubereac68ba2011-09-27 12:12:25 -0700475 if (mSource->feedMoreTSData() == OK) {
Andreas Huber1183a4a2011-11-03 11:00:21 -0700476 msg->post(10000ll);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800477 }
Andreas Huberf9334412010-12-15 15:17:42 -0800478 }
479 } else if (what == ACodec::kWhatEOS) {
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700480 int32_t err;
481 CHECK(codecRequest->findInt32("err", &err));
482
483 if (err == ERROR_END_OF_STREAM) {
Steve Block3856b092011-10-20 11:56:00 +0100484 ALOGV("got %s decoder EOS", audio ? "audio" : "video");
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700485 } else {
Steve Block3856b092011-10-20 11:56:00 +0100486 ALOGV("got %s decoder EOS w/ error %d",
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700487 audio ? "audio" : "video",
488 err);
489 }
490
491 mRenderer->queueEOS(audio, err);
Andreas Huberf9334412010-12-15 15:17:42 -0800492 } else if (what == ACodec::kWhatFlushCompleted) {
Andreas Huber1aef2112011-01-04 14:01:29 -0800493 bool needShutdown;
Andreas Huber53df1a42010-12-22 10:03:04 -0800494
Andreas Huberf9334412010-12-15 15:17:42 -0800495 if (audio) {
Andreas Huber1aef2112011-01-04 14:01:29 -0800496 CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
Andreas Huberf9334412010-12-15 15:17:42 -0800497 mFlushingAudio = FLUSHED;
498 } else {
Andreas Huber1aef2112011-01-04 14:01:29 -0800499 CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
Andreas Huberf9334412010-12-15 15:17:42 -0800500 mFlushingVideo = FLUSHED;
Andreas Huber3fe62152011-09-16 15:09:22 -0700501
502 mVideoLateByUs = 0;
Andreas Huberf9334412010-12-15 15:17:42 -0800503 }
504
Steve Block3856b092011-10-20 11:56:00 +0100505 ALOGV("decoder %s flush completed", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800506
Andreas Huber1aef2112011-01-04 14:01:29 -0800507 if (needShutdown) {
Steve Block3856b092011-10-20 11:56:00 +0100508 ALOGV("initiating %s decoder shutdown",
Andreas Huber53df1a42010-12-22 10:03:04 -0800509 audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800510
Andreas Huber53df1a42010-12-22 10:03:04 -0800511 (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
Andreas Huberf9334412010-12-15 15:17:42 -0800512
Andreas Huber53df1a42010-12-22 10:03:04 -0800513 if (audio) {
514 mFlushingAudio = SHUTTING_DOWN_DECODER;
515 } else {
516 mFlushingVideo = SHUTTING_DOWN_DECODER;
517 }
Andreas Huberf9334412010-12-15 15:17:42 -0800518 }
Andreas Huber3831a062010-12-21 10:22:33 -0800519
520 finishFlushIfPossible();
Andreas Huber2c2814b2010-12-15 17:18:20 -0800521 } else if (what == ACodec::kWhatOutputFormatChanged) {
Andreas Huber31e25082011-01-10 10:38:31 -0800522 if (audio) {
523 int32_t numChannels;
Andreas Huber516dacf2012-12-03 15:20:40 -0800524 CHECK(codecRequest->findInt32(
525 "channel-count", &numChannels));
Andreas Huber2c2814b2010-12-15 17:18:20 -0800526
Andreas Huber31e25082011-01-10 10:38:31 -0800527 int32_t sampleRate;
528 CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
Andreas Huber2c2814b2010-12-15 17:18:20 -0800529
Steve Block3856b092011-10-20 11:56:00 +0100530 ALOGV("Audio output format changed to %d Hz, %d channels",
Andreas Huber31e25082011-01-10 10:38:31 -0800531 sampleRate, numChannels);
Andreas Huber2c2814b2010-12-15 17:18:20 -0800532
Andreas Huber31e25082011-01-10 10:38:31 -0800533 mAudioSink->close();
Eric Laurent1948eb32012-04-13 16:50:19 -0700534
535 audio_output_flags_t flags;
536 int64_t durationUs;
Andreas Huber516dacf2012-12-03 15:20:40 -0800537 // FIXME: we should handle the case where the video decoder
538 // is created after we receive the format change indication.
539 // Current code will just make that we select deep buffer
540 // with video which should not be a problem as it should
Eric Laurent1948eb32012-04-13 16:50:19 -0700541 // not prevent from keeping A/V sync.
542 if (mVideoDecoder == NULL &&
543 mSource->getDuration(&durationUs) == OK &&
Andreas Huber516dacf2012-12-03 15:20:40 -0800544 durationUs
545 > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
Eric Laurent1948eb32012-04-13 16:50:19 -0700546 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
547 } else {
548 flags = AUDIO_OUTPUT_FLAG_NONE;
549 }
550
Andreas Huber98065552012-05-03 11:33:01 -0700551 int32_t channelMask;
552 if (!codecRequest->findInt32("channel-mask", &channelMask)) {
553 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
554 }
555
Andreas Huber078cfcf2011-09-15 12:25:04 -0700556 CHECK_EQ(mAudioSink->open(
557 sampleRate,
558 numChannels,
Andreas Huber98065552012-05-03 11:33:01 -0700559 (audio_channel_mask_t)channelMask,
Andreas Huber078cfcf2011-09-15 12:25:04 -0700560 AUDIO_FORMAT_PCM_16_BIT,
Eric Laurent1948eb32012-04-13 16:50:19 -0700561 8 /* bufferCount */,
562 NULL,
563 NULL,
564 flags),
Andreas Huber078cfcf2011-09-15 12:25:04 -0700565 (status_t)OK);
Andreas Huber31e25082011-01-10 10:38:31 -0800566 mAudioSink->start();
Andreas Huber2c2814b2010-12-15 17:18:20 -0800567
Andreas Huber31e25082011-01-10 10:38:31 -0800568 mRenderer->signalAudioSinkChanged();
569 } else {
570 // video
Andreas Huber3831a062010-12-21 10:22:33 -0800571
Andreas Huber31e25082011-01-10 10:38:31 -0800572 int32_t width, height;
573 CHECK(codecRequest->findInt32("width", &width));
574 CHECK(codecRequest->findInt32("height", &height));
575
576 int32_t cropLeft, cropTop, cropRight, cropBottom;
577 CHECK(codecRequest->findRect(
578 "crop",
579 &cropLeft, &cropTop, &cropRight, &cropBottom));
580
Andreas Huber516dacf2012-12-03 15:20:40 -0800581 int32_t displayWidth = cropRight - cropLeft + 1;
582 int32_t displayHeight = cropBottom - cropTop + 1;
583
Steve Block3856b092011-10-20 11:56:00 +0100584 ALOGV("Video output format changed to %d x %d "
Andreas Hubercb67cd12011-08-26 16:02:19 -0700585 "(crop: %d x %d @ (%d, %d))",
Andreas Huber31e25082011-01-10 10:38:31 -0800586 width, height,
Andreas Huber516dacf2012-12-03 15:20:40 -0800587 displayWidth,
588 displayHeight,
Andreas Hubercb67cd12011-08-26 16:02:19 -0700589 cropLeft, cropTop);
Andreas Huber31e25082011-01-10 10:38:31 -0800590
Andreas Huber516dacf2012-12-03 15:20:40 -0800591 sp<AMessage> videoInputFormat =
592 mSource->getFormat(false /* audio */);
593
594 // Take into account sample aspect ratio if necessary:
595 int32_t sarWidth, sarHeight;
596 if (videoInputFormat->findInt32("sar-width", &sarWidth)
597 && videoInputFormat->findInt32(
598 "sar-height", &sarHeight)) {
599 ALOGV("Sample aspect ratio %d : %d",
600 sarWidth, sarHeight);
601
602 displayWidth = (displayWidth * sarWidth) / sarHeight;
603
604 ALOGV("display dimensions %d x %d",
605 displayWidth, displayHeight);
606 }
607
Andreas Huber31e25082011-01-10 10:38:31 -0800608 notifyListener(
Andreas Huber516dacf2012-12-03 15:20:40 -0800609 MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight);
Andreas Huber31e25082011-01-10 10:38:31 -0800610 }
Andreas Huber3831a062010-12-21 10:22:33 -0800611 } else if (what == ACodec::kWhatShutdownCompleted) {
Steve Block3856b092011-10-20 11:56:00 +0100612 ALOGV("%s shutdown completed", audio ? "audio" : "video");
Andreas Huber3831a062010-12-21 10:22:33 -0800613 if (audio) {
614 mAudioDecoder.clear();
615
616 CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
617 mFlushingAudio = SHUT_DOWN;
618 } else {
619 mVideoDecoder.clear();
620
621 CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
622 mFlushingVideo = SHUT_DOWN;
623 }
624
625 finishFlushIfPossible();
Andreas Huberc92fd242011-08-16 13:48:44 -0700626 } else if (what == ACodec::kWhatError) {
Steve Block29357bc2012-01-06 19:20:56 +0000627 ALOGE("Received error from %s decoder, aborting playback.",
Andreas Huberc92fd242011-08-16 13:48:44 -0700628 audio ? "audio" : "video");
629
630 mRenderer->queueEOS(audio, UNKNOWN_ERROR);
Andreas Huber57788222012-02-21 11:47:18 -0800631 } else if (what == ACodec::kWhatDrainThisBuffer) {
Andreas Huberf9334412010-12-15 15:17:42 -0800632 renderBuffer(audio, codecRequest);
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800633 } else if (what != ACodec::kWhatComponentAllocated
634 && what != ACodec::kWhatComponentConfigured
635 && what != ACodec::kWhatBuffersAllocated) {
636 ALOGV("Unhandled codec notification %d '%c%c%c%c'.",
637 what,
638 what >> 24,
639 (what >> 16) & 0xff,
640 (what >> 8) & 0xff,
641 what & 0xff);
Andreas Huberf9334412010-12-15 15:17:42 -0800642 }
643
644 break;
645 }
646
647 case kWhatRendererNotify:
648 {
649 int32_t what;
650 CHECK(msg->findInt32("what", &what));
651
652 if (what == Renderer::kWhatEOS) {
653 int32_t audio;
654 CHECK(msg->findInt32("audio", &audio));
655
Andreas Huberc92fd242011-08-16 13:48:44 -0700656 int32_t finalResult;
657 CHECK(msg->findInt32("finalResult", &finalResult));
658
Andreas Huberf9334412010-12-15 15:17:42 -0800659 if (audio) {
660 mAudioEOS = true;
661 } else {
662 mVideoEOS = true;
663 }
664
Andreas Huberc92fd242011-08-16 13:48:44 -0700665 if (finalResult == ERROR_END_OF_STREAM) {
Steve Block3856b092011-10-20 11:56:00 +0100666 ALOGV("reached %s EOS", audio ? "audio" : "video");
Andreas Huberc92fd242011-08-16 13:48:44 -0700667 } else {
Steve Block29357bc2012-01-06 19:20:56 +0000668 ALOGE("%s track encountered an error (%d)",
Andreas Huberc92fd242011-08-16 13:48:44 -0700669 audio ? "audio" : "video", finalResult);
670
671 notifyListener(
672 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult);
673 }
Andreas Huberf9334412010-12-15 15:17:42 -0800674
675 if ((mAudioEOS || mAudioDecoder == NULL)
676 && (mVideoEOS || mVideoDecoder == NULL)) {
677 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
678 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800679 } else if (what == Renderer::kWhatPosition) {
680 int64_t positionUs;
681 CHECK(msg->findInt64("positionUs", &positionUs));
682
Andreas Huber3fe62152011-09-16 15:09:22 -0700683 CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs));
684
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800685 if (mDriver != NULL) {
686 sp<NuPlayerDriver> driver = mDriver.promote();
687 if (driver != NULL) {
688 driver->notifyPosition(positionUs);
Andreas Huber3fe62152011-09-16 15:09:22 -0700689
690 driver->notifyFrameStats(
691 mNumFramesTotal, mNumFramesDropped);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800692 }
693 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700694 } else if (what == Renderer::kWhatFlushComplete) {
Andreas Huberf9334412010-12-15 15:17:42 -0800695 int32_t audio;
696 CHECK(msg->findInt32("audio", &audio));
697
Steve Block3856b092011-10-20 11:56:00 +0100698 ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
James Dongf57b4ea2012-07-20 13:38:36 -0700699 } else if (what == Renderer::kWhatVideoRenderingStart) {
700 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
Andreas Huberf9334412010-12-15 15:17:42 -0800701 }
702 break;
703 }
704
705 case kWhatMoreDataQueued:
706 {
707 break;
708 }
709
Andreas Huber1aef2112011-01-04 14:01:29 -0800710 case kWhatReset:
711 {
Steve Block3856b092011-10-20 11:56:00 +0100712 ALOGV("kWhatReset");
Andreas Huber1aef2112011-01-04 14:01:29 -0800713
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800714 mDeferredActions.push_back(
715 new SimpleAction(&NuPlayer::performDecoderShutdown));
Andreas Huberb7c8e912012-11-27 15:02:53 -0800716
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800717 mDeferredActions.push_back(
718 new SimpleAction(&NuPlayer::performReset));
Andreas Huberb58ce9f2011-11-28 16:27:35 -0800719
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800720 processDeferredActions();
Andreas Huber1aef2112011-01-04 14:01:29 -0800721 break;
722 }
723
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800724 case kWhatSeek:
725 {
726 int64_t seekTimeUs;
727 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
728
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800729 ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800730
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800731 mDeferredActions.push_back(
732 new SimpleAction(&NuPlayer::performDecoderFlush));
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800733
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800734 mDeferredActions.push_back(new SeekAction(seekTimeUs));
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800735
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800736 processDeferredActions();
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800737 break;
738 }
739
Andreas Huberb4082222011-01-20 15:23:04 -0800740 case kWhatPause:
741 {
742 CHECK(mRenderer != NULL);
Roger Jönssonfba60da2013-01-21 17:15:45 +0100743 mSource->pause();
Andreas Huberb4082222011-01-20 15:23:04 -0800744 mRenderer->pause();
745 break;
746 }
747
748 case kWhatResume:
749 {
750 CHECK(mRenderer != NULL);
Roger Jönssonfba60da2013-01-21 17:15:45 +0100751 mSource->resume();
Andreas Huberb4082222011-01-20 15:23:04 -0800752 mRenderer->resume();
753 break;
754 }
755
Andreas Huberb5f25f02013-02-05 10:14:26 -0800756 case kWhatSourceNotify:
757 {
Andreas Huber9575c962013-02-05 13:59:56 -0800758 onSourceNotify(msg);
Andreas Huberb5f25f02013-02-05 10:14:26 -0800759 break;
760 }
761
Andreas Huberf9334412010-12-15 15:17:42 -0800762 default:
763 TRESPASS();
764 break;
765 }
766}
767
Andreas Huber3831a062010-12-21 10:22:33 -0800768void NuPlayer::finishFlushIfPossible() {
769 if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
770 return;
771 }
772
773 if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
774 return;
775 }
776
Steve Block3856b092011-10-20 11:56:00 +0100777 ALOGV("both audio and video are flushed now.");
Andreas Huber3831a062010-12-21 10:22:33 -0800778
Andreas Huber6e3d3112011-11-28 12:36:11 -0800779 if (mTimeDiscontinuityPending) {
780 mRenderer->signalTimeDiscontinuity();
781 mTimeDiscontinuityPending = false;
782 }
Andreas Huber3831a062010-12-21 10:22:33 -0800783
Andreas Huber22fc52f2011-01-05 16:24:27 -0800784 if (mAudioDecoder != NULL) {
Andreas Huber3831a062010-12-21 10:22:33 -0800785 mAudioDecoder->signalResume();
786 }
787
Andreas Huber22fc52f2011-01-05 16:24:27 -0800788 if (mVideoDecoder != NULL) {
Andreas Huber3831a062010-12-21 10:22:33 -0800789 mVideoDecoder->signalResume();
790 }
791
792 mFlushingAudio = NONE;
793 mFlushingVideo = NONE;
Andreas Huber3831a062010-12-21 10:22:33 -0800794
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800795 processDeferredActions();
Andreas Huber1aef2112011-01-04 14:01:29 -0800796}
797
798void NuPlayer::postScanSources() {
799 if (mScanSourcesPending) {
800 return;
801 }
802
803 sp<AMessage> msg = new AMessage(kWhatScanSources, id());
804 msg->setInt32("generation", mScanSourcesGeneration);
805 msg->post();
806
807 mScanSourcesPending = true;
808}
809
Andreas Huber5bc087c2010-12-23 10:27:40 -0800810status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
Andreas Huberf9334412010-12-15 15:17:42 -0800811 if (*decoder != NULL) {
812 return OK;
813 }
814
Andreas Huber84066782011-08-16 09:34:26 -0700815 sp<AMessage> format = mSource->getFormat(audio);
Andreas Huberf9334412010-12-15 15:17:42 -0800816
Andreas Huber84066782011-08-16 09:34:26 -0700817 if (format == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -0800818 return -EWOULDBLOCK;
819 }
820
Andreas Huber3fe62152011-09-16 15:09:22 -0700821 if (!audio) {
Andreas Huber84066782011-08-16 09:34:26 -0700822 AString mime;
823 CHECK(format->findString("mime", &mime));
824 mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
Andreas Huber3fe62152011-09-16 15:09:22 -0700825 }
826
Andreas Huberf9334412010-12-15 15:17:42 -0800827 sp<AMessage> notify =
828 new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
829 id());
830
Glenn Kasten11731182011-02-08 17:26:17 -0800831 *decoder = audio ? new Decoder(notify) :
832 new Decoder(notify, mNativeWindow);
Andreas Huberf9334412010-12-15 15:17:42 -0800833 looper()->registerHandler(*decoder);
834
Andreas Huber84066782011-08-16 09:34:26 -0700835 (*decoder)->configure(format);
Andreas Huberf9334412010-12-15 15:17:42 -0800836
Andreas Huberf9334412010-12-15 15:17:42 -0800837 return OK;
838}
839
840status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
841 sp<AMessage> reply;
842 CHECK(msg->findMessage("reply", &reply));
843
Andreas Huber53df1a42010-12-22 10:03:04 -0800844 if ((audio && IsFlushingState(mFlushingAudio))
845 || (!audio && IsFlushingState(mFlushingVideo))) {
Andreas Huberf9334412010-12-15 15:17:42 -0800846 reply->setInt32("err", INFO_DISCONTINUITY);
847 reply->post();
848 return OK;
849 }
850
851 sp<ABuffer> accessUnit;
Andreas Huberf9334412010-12-15 15:17:42 -0800852
Andreas Huber3fe62152011-09-16 15:09:22 -0700853 bool dropAccessUnit;
854 do {
855 status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800856
Andreas Huber3fe62152011-09-16 15:09:22 -0700857 if (err == -EWOULDBLOCK) {
858 return err;
859 } else if (err != OK) {
860 if (err == INFO_DISCONTINUITY) {
861 int32_t type;
862 CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
Andreas Huber53df1a42010-12-22 10:03:04 -0800863
Andreas Huber3fe62152011-09-16 15:09:22 -0700864 bool formatChange =
Andreas Huber6e3d3112011-11-28 12:36:11 -0800865 (audio &&
866 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
867 || (!audio &&
868 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
Andreas Huber53df1a42010-12-22 10:03:04 -0800869
Andreas Huber6e3d3112011-11-28 12:36:11 -0800870 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
871
Steve Blockdf64d152012-01-04 20:05:49 +0000872 ALOGI("%s discontinuity (formatChange=%d, time=%d)",
Andreas Huber6e3d3112011-11-28 12:36:11 -0800873 audio ? "audio" : "video", formatChange, timeChange);
Andreas Huber32f3cef2011-03-02 15:34:46 -0800874
Andreas Huber3fe62152011-09-16 15:09:22 -0700875 if (audio) {
876 mSkipRenderingAudioUntilMediaTimeUs = -1;
877 } else {
878 mSkipRenderingVideoUntilMediaTimeUs = -1;
879 }
Andreas Huber32f3cef2011-03-02 15:34:46 -0800880
Andreas Huber6e3d3112011-11-28 12:36:11 -0800881 if (timeChange) {
882 sp<AMessage> extra;
883 if (accessUnit->meta()->findMessage("extra", &extra)
884 && extra != NULL) {
885 int64_t resumeAtMediaTimeUs;
886 if (extra->findInt64(
887 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
Steve Blockdf64d152012-01-04 20:05:49 +0000888 ALOGI("suppressing rendering of %s until %lld us",
Andreas Huber6e3d3112011-11-28 12:36:11 -0800889 audio ? "audio" : "video", resumeAtMediaTimeUs);
Andreas Huber3fe62152011-09-16 15:09:22 -0700890
Andreas Huber6e3d3112011-11-28 12:36:11 -0800891 if (audio) {
892 mSkipRenderingAudioUntilMediaTimeUs =
893 resumeAtMediaTimeUs;
894 } else {
895 mSkipRenderingVideoUntilMediaTimeUs =
896 resumeAtMediaTimeUs;
897 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700898 }
Andreas Huber32f3cef2011-03-02 15:34:46 -0800899 }
900 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700901
Andreas Huber6e3d3112011-11-28 12:36:11 -0800902 mTimeDiscontinuityPending =
903 mTimeDiscontinuityPending || timeChange;
904
905 if (formatChange || timeChange) {
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800906 if (mFlushingAudio == NONE && mFlushingVideo == NONE) {
907 // And we'll resume scanning sources once we're done
908 // flushing.
909 mDeferredActions.push_front(
910 new SimpleAction(
911 &NuPlayer::performScanSources));
912 }
913
Andreas Huber6e3d3112011-11-28 12:36:11 -0800914 flushDecoder(audio, formatChange);
915 } else {
916 // This stream is unaffected by the discontinuity
917
918 if (audio) {
919 mFlushingAudio = FLUSHED;
920 } else {
921 mFlushingVideo = FLUSHED;
922 }
923
924 finishFlushIfPossible();
925
926 return -EWOULDBLOCK;
927 }
Andreas Huber32f3cef2011-03-02 15:34:46 -0800928 }
929
Andreas Huber3fe62152011-09-16 15:09:22 -0700930 reply->setInt32("err", err);
931 reply->post();
932 return OK;
Andreas Huberf9334412010-12-15 15:17:42 -0800933 }
934
Andreas Huber3fe62152011-09-16 15:09:22 -0700935 if (!audio) {
936 ++mNumFramesTotal;
937 }
938
939 dropAccessUnit = false;
940 if (!audio
941 && mVideoLateByUs > 100000ll
942 && mVideoIsAVC
943 && !IsAVCReferenceFrame(accessUnit)) {
944 dropAccessUnit = true;
945 ++mNumFramesDropped;
946 }
947 } while (dropAccessUnit);
Andreas Huberf9334412010-12-15 15:17:42 -0800948
Steve Block3856b092011-10-20 11:56:00 +0100949 // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800950
951#if 0
952 int64_t mediaTimeUs;
953 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
Steve Block3856b092011-10-20 11:56:00 +0100954 ALOGV("feeding %s input buffer at media time %.2f secs",
Andreas Huberf9334412010-12-15 15:17:42 -0800955 audio ? "audio" : "video",
956 mediaTimeUs / 1E6);
957#endif
958
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800959 reply->setBuffer("buffer", accessUnit);
Andreas Huberf9334412010-12-15 15:17:42 -0800960 reply->post();
961
962 return OK;
963}
964
965void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
Steve Block3856b092011-10-20 11:56:00 +0100966 // ALOGV("renderBuffer %s", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800967
968 sp<AMessage> reply;
969 CHECK(msg->findMessage("reply", &reply));
970
Andreas Huber18ac5402011-08-31 15:04:25 -0700971 if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) {
972 // We're currently attempting to flush the decoder, in order
973 // to complete this, the decoder wants all its buffers back,
974 // so we don't want any output buffers it sent us (from before
975 // we initiated the flush) to be stuck in the renderer's queue.
976
Steve Block3856b092011-10-20 11:56:00 +0100977 ALOGV("we're still flushing the %s decoder, sending its output buffer"
Andreas Huber18ac5402011-08-31 15:04:25 -0700978 " right back.", audio ? "audio" : "video");
979
980 reply->post();
981 return;
982 }
983
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800984 sp<ABuffer> buffer;
985 CHECK(msg->findBuffer("buffer", &buffer));
Andreas Huberf9334412010-12-15 15:17:42 -0800986
Andreas Huber32f3cef2011-03-02 15:34:46 -0800987 int64_t &skipUntilMediaTimeUs =
988 audio
989 ? mSkipRenderingAudioUntilMediaTimeUs
990 : mSkipRenderingVideoUntilMediaTimeUs;
991
992 if (skipUntilMediaTimeUs >= 0) {
993 int64_t mediaTimeUs;
994 CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs));
995
996 if (mediaTimeUs < skipUntilMediaTimeUs) {
Steve Block3856b092011-10-20 11:56:00 +0100997 ALOGV("dropping %s buffer at time %lld as requested.",
Andreas Huber32f3cef2011-03-02 15:34:46 -0800998 audio ? "audio" : "video",
999 mediaTimeUs);
1000
1001 reply->post();
1002 return;
1003 }
1004
1005 skipUntilMediaTimeUs = -1;
1006 }
1007
Andreas Huberf9334412010-12-15 15:17:42 -08001008 mRenderer->queueBuffer(audio, buffer, reply);
1009}
1010
1011void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001012 if (mDriver == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -08001013 return;
1014 }
1015
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001016 sp<NuPlayerDriver> driver = mDriver.promote();
Andreas Huberf9334412010-12-15 15:17:42 -08001017
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001018 if (driver == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -08001019 return;
1020 }
1021
Andreas Hubera4af2142011-10-26 15:23:31 -07001022 driver->notifyListener(msg, ext1, ext2);
Andreas Huberf9334412010-12-15 15:17:42 -08001023}
1024
Andreas Huber1aef2112011-01-04 14:01:29 -08001025void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
Andreas Huber6e3d3112011-11-28 12:36:11 -08001026 if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
Steve Blockdf64d152012-01-04 20:05:49 +00001027 ALOGI("flushDecoder %s without decoder present",
Andreas Huber6e3d3112011-11-28 12:36:11 -08001028 audio ? "audio" : "video");
1029 }
1030
Andreas Huber1aef2112011-01-04 14:01:29 -08001031 // Make sure we don't continue to scan sources until we finish flushing.
1032 ++mScanSourcesGeneration;
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001033 mScanSourcesPending = false;
Andreas Huber1aef2112011-01-04 14:01:29 -08001034
1035 (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
1036 mRenderer->flush(audio);
1037
1038 FlushStatus newStatus =
1039 needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
1040
1041 if (audio) {
1042 CHECK(mFlushingAudio == NONE
1043 || mFlushingAudio == AWAITING_DISCONTINUITY);
1044
1045 mFlushingAudio = newStatus;
1046
1047 if (mFlushingVideo == NONE) {
1048 mFlushingVideo = (mVideoDecoder != NULL)
1049 ? AWAITING_DISCONTINUITY
1050 : FLUSHED;
1051 }
1052 } else {
1053 CHECK(mFlushingVideo == NONE
1054 || mFlushingVideo == AWAITING_DISCONTINUITY);
1055
1056 mFlushingVideo = newStatus;
1057
1058 if (mFlushingAudio == NONE) {
1059 mFlushingAudio = (mAudioDecoder != NULL)
1060 ? AWAITING_DISCONTINUITY
1061 : FLUSHED;
1062 }
1063 }
1064}
1065
Andreas Huber84066782011-08-16 09:34:26 -07001066sp<AMessage> NuPlayer::Source::getFormat(bool audio) {
1067 sp<MetaData> meta = getFormatMeta(audio);
1068
1069 if (meta == NULL) {
1070 return NULL;
1071 }
1072
1073 sp<AMessage> msg = new AMessage;
1074
1075 if(convertMetaDataToMessage(meta, &msg) == OK) {
1076 return msg;
1077 }
1078 return NULL;
1079}
1080
James Dong0d268a32012-08-31 12:18:27 -07001081status_t NuPlayer::setVideoScalingMode(int32_t mode) {
1082 mVideoScalingMode = mode;
Andreas Huber57a339c2012-12-03 11:18:00 -08001083 if (mNativeWindow != NULL) {
James Dong0d268a32012-08-31 12:18:27 -07001084 status_t ret = native_window_set_scaling_mode(
1085 mNativeWindow->getNativeWindow().get(), mVideoScalingMode);
1086 if (ret != OK) {
1087 ALOGE("Failed to set scaling mode (%d): %s",
1088 -ret, strerror(-ret));
1089 return ret;
1090 }
1091 }
1092 return OK;
1093}
1094
Andreas Huberb7c8e912012-11-27 15:02:53 -08001095void NuPlayer::schedulePollDuration() {
1096 sp<AMessage> msg = new AMessage(kWhatPollDuration, id());
1097 msg->setInt32("generation", mPollDurationGeneration);
1098 msg->post();
1099}
1100
1101void NuPlayer::cancelPollDuration() {
1102 ++mPollDurationGeneration;
1103}
1104
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001105void NuPlayer::processDeferredActions() {
1106 while (!mDeferredActions.empty()) {
1107 // We won't execute any deferred actions until we're no longer in
1108 // an intermediate state, i.e. one more more decoders are currently
1109 // flushing or shutting down.
1110
1111 if (mRenderer != NULL) {
1112 // There's an edge case where the renderer owns all output
1113 // buffers and is paused, therefore the decoder will not read
1114 // more input data and will never encounter the matching
1115 // discontinuity. To avoid this, we resume the renderer.
1116
1117 if (mFlushingAudio == AWAITING_DISCONTINUITY
1118 || mFlushingVideo == AWAITING_DISCONTINUITY) {
1119 mRenderer->resume();
1120 }
1121 }
1122
1123 if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
1124 // We're currently flushing, postpone the reset until that's
1125 // completed.
1126
1127 ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d",
1128 mFlushingAudio, mFlushingVideo);
1129
1130 break;
1131 }
1132
1133 sp<Action> action = *mDeferredActions.begin();
1134 mDeferredActions.erase(mDeferredActions.begin());
1135
1136 action->execute(this);
1137 }
1138}
1139
1140void NuPlayer::performSeek(int64_t seekTimeUs) {
1141 ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)",
1142 seekTimeUs,
1143 seekTimeUs / 1E6);
1144
1145 mSource->seekTo(seekTimeUs);
1146
1147 if (mDriver != NULL) {
1148 sp<NuPlayerDriver> driver = mDriver.promote();
1149 if (driver != NULL) {
1150 driver->notifyPosition(seekTimeUs);
1151 driver->notifySeekComplete();
1152 }
1153 }
1154
1155 // everything's flushed, continue playback.
1156}
1157
1158void NuPlayer::performDecoderFlush() {
1159 ALOGV("performDecoderFlush");
1160
Andreas Huberda9740e2013-04-16 10:54:03 -07001161 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001162 return;
1163 }
1164
1165 mTimeDiscontinuityPending = true;
1166
1167 if (mAudioDecoder != NULL) {
1168 flushDecoder(true /* audio */, false /* needShutdown */);
1169 }
1170
1171 if (mVideoDecoder != NULL) {
1172 flushDecoder(false /* audio */, false /* needShutdown */);
1173 }
1174}
1175
1176void NuPlayer::performDecoderShutdown() {
1177 ALOGV("performDecoderShutdown");
1178
Andreas Huberda9740e2013-04-16 10:54:03 -07001179 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001180 return;
1181 }
1182
1183 mTimeDiscontinuityPending = true;
1184
1185 if (mAudioDecoder != NULL) {
1186 flushDecoder(true /* audio */, true /* needShutdown */);
1187 }
1188
1189 if (mVideoDecoder != NULL) {
1190 flushDecoder(false /* audio */, true /* needShutdown */);
1191 }
1192}
1193
1194void NuPlayer::performReset() {
1195 ALOGV("performReset");
1196
1197 CHECK(mAudioDecoder == NULL);
1198 CHECK(mVideoDecoder == NULL);
1199
1200 cancelPollDuration();
1201
1202 ++mScanSourcesGeneration;
1203 mScanSourcesPending = false;
1204
1205 mRenderer.clear();
1206
1207 if (mSource != NULL) {
1208 mSource->stop();
Andreas Huberb5f25f02013-02-05 10:14:26 -08001209
1210 looper()->unregisterHandler(mSource->id());
1211
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001212 mSource.clear();
1213 }
1214
1215 if (mDriver != NULL) {
1216 sp<NuPlayerDriver> driver = mDriver.promote();
1217 if (driver != NULL) {
1218 driver->notifyResetComplete();
1219 }
1220 }
Andreas Huber57a339c2012-12-03 11:18:00 -08001221
1222 mStarted = false;
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001223}
1224
1225void NuPlayer::performScanSources() {
1226 ALOGV("performScanSources");
1227
Andreas Huber57a339c2012-12-03 11:18:00 -08001228 if (!mStarted) {
1229 return;
1230 }
1231
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001232 if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
1233 postScanSources();
1234 }
1235}
1236
Andreas Huber57a339c2012-12-03 11:18:00 -08001237void NuPlayer::performSetSurface(const sp<NativeWindowWrapper> &wrapper) {
1238 ALOGV("performSetSurface");
1239
1240 mNativeWindow = wrapper;
1241
1242 // XXX - ignore error from setVideoScalingMode for now
1243 setVideoScalingMode(mVideoScalingMode);
1244
1245 if (mDriver != NULL) {
1246 sp<NuPlayerDriver> driver = mDriver.promote();
1247 if (driver != NULL) {
1248 driver->notifySetSurfaceComplete();
1249 }
1250 }
1251}
1252
Andreas Huber9575c962013-02-05 13:59:56 -08001253void NuPlayer::onSourceNotify(const sp<AMessage> &msg) {
1254 int32_t what;
1255 CHECK(msg->findInt32("what", &what));
1256
1257 switch (what) {
1258 case Source::kWhatPrepared:
1259 {
Andreas Huberec0c5972013-02-05 14:47:13 -08001260 int32_t err;
1261 CHECK(msg->findInt32("err", &err));
1262
Andreas Huber9575c962013-02-05 13:59:56 -08001263 sp<NuPlayerDriver> driver = mDriver.promote();
1264 if (driver != NULL) {
Andreas Huberec0c5972013-02-05 14:47:13 -08001265 driver->notifyPrepareCompleted(err);
Andreas Huber9575c962013-02-05 13:59:56 -08001266 }
Andreas Huber99759402013-04-01 14:28:31 -07001267
1268 int64_t durationUs;
1269 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
1270 sp<NuPlayerDriver> driver = mDriver.promote();
1271 if (driver != NULL) {
1272 driver->notifyDuration(durationUs);
1273 }
1274 }
Andreas Huber9575c962013-02-05 13:59:56 -08001275 break;
1276 }
1277
1278 case Source::kWhatFlagsChanged:
1279 {
1280 uint32_t flags;
1281 CHECK(msg->findInt32("flags", (int32_t *)&flags));
1282
1283 if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
1284 && (!(flags & Source::FLAG_DYNAMIC_DURATION))) {
1285 cancelPollDuration();
1286 } else if (!(mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
1287 && (flags & Source::FLAG_DYNAMIC_DURATION)
1288 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
1289 schedulePollDuration();
1290 }
1291
1292 mSourceFlags = flags;
1293 break;
1294 }
1295
1296 case Source::kWhatVideoSizeChanged:
1297 {
1298 int32_t width, height;
1299 CHECK(msg->findInt32("width", &width));
1300 CHECK(msg->findInt32("height", &height));
1301
1302 notifyListener(MEDIA_SET_VIDEO_SIZE, width, height);
1303 break;
1304 }
1305
Roger Jönssonb50e83e2013-01-21 16:26:41 +01001306 case Source::kWhatBufferingStart:
1307 {
1308 notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0);
1309 break;
1310 }
1311
1312 case Source::kWhatBufferingEnd:
1313 {
1314 notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0);
1315 break;
1316 }
1317
Andreas Huber9575c962013-02-05 13:59:56 -08001318 default:
1319 TRESPASS();
1320 }
1321}
1322
Andreas Huberb5f25f02013-02-05 10:14:26 -08001323////////////////////////////////////////////////////////////////////////////////
1324
Andreas Huber9575c962013-02-05 13:59:56 -08001325void NuPlayer::Source::notifyFlagsChanged(uint32_t flags) {
1326 sp<AMessage> notify = dupNotify();
1327 notify->setInt32("what", kWhatFlagsChanged);
1328 notify->setInt32("flags", flags);
1329 notify->post();
1330}
1331
1332void NuPlayer::Source::notifyVideoSizeChanged(int32_t width, int32_t height) {
1333 sp<AMessage> notify = dupNotify();
1334 notify->setInt32("what", kWhatVideoSizeChanged);
1335 notify->setInt32("width", width);
1336 notify->setInt32("height", height);
1337 notify->post();
1338}
1339
Andreas Huberec0c5972013-02-05 14:47:13 -08001340void NuPlayer::Source::notifyPrepared(status_t err) {
Andreas Huber9575c962013-02-05 13:59:56 -08001341 sp<AMessage> notify = dupNotify();
1342 notify->setInt32("what", kWhatPrepared);
Andreas Huberec0c5972013-02-05 14:47:13 -08001343 notify->setInt32("err", err);
Andreas Huber9575c962013-02-05 13:59:56 -08001344 notify->post();
1345}
1346
Andreas Huberb5f25f02013-02-05 10:14:26 -08001347void NuPlayer::Source::onMessageReceived(const sp<AMessage> &msg) {
1348 TRESPASS();
1349}
1350
Andreas Huberf9334412010-12-15 15:17:42 -08001351} // namespace android