blob: 6d95a41fa58df8dc772fbee755d001dc66a2d767 [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
Martin Storsjoda38df52013-09-25 16:05:36 +030035#include "SoftwareRenderer.h"
36
Andreas Huber84066782011-08-16 09:34:26 -070037#include <cutils/properties.h> // for property_get
Andreas Huber3831a062010-12-21 10:22:33 -080038#include <media/stagefright/foundation/hexdump.h>
Andreas Huberf9334412010-12-15 15:17:42 -080039#include <media/stagefright/foundation/ABuffer.h>
40#include <media/stagefright/foundation/ADebug.h>
41#include <media/stagefright/foundation/AMessage.h>
42#include <media/stagefright/ACodec.h>
Andreas Huber3fe62152011-09-16 15:09:22 -070043#include <media/stagefright/MediaDefs.h>
Andreas Huberf9334412010-12-15 15:17:42 -080044#include <media/stagefright/MediaErrors.h>
45#include <media/stagefright/MetaData.h>
Andy McFadden484566c2012-12-18 09:46:54 -080046#include <gui/IGraphicBufferProducer.h>
Andreas Huberf9334412010-12-15 15:17:42 -080047
Andreas Huber3fe62152011-09-16 15:09:22 -070048#include "avc_utils.h"
49
Andreas Huber84066782011-08-16 09:34:26 -070050#include "ESDS.h"
51#include <media/stagefright/Utils.h>
52
Andreas Huberf9334412010-12-15 15:17:42 -080053namespace android {
54
Andreas Huber457ec422012-11-30 10:53:22 -080055struct NuPlayer::Action : public RefBase {
56 Action() {}
57
58 virtual void execute(NuPlayer *player) = 0;
59
60private:
61 DISALLOW_EVIL_CONSTRUCTORS(Action);
62};
63
64struct NuPlayer::SeekAction : public Action {
65 SeekAction(int64_t seekTimeUs)
66 : mSeekTimeUs(seekTimeUs) {
67 }
68
69 virtual void execute(NuPlayer *player) {
70 player->performSeek(mSeekTimeUs);
71 }
72
73private:
74 int64_t mSeekTimeUs;
75
76 DISALLOW_EVIL_CONSTRUCTORS(SeekAction);
77};
78
Andreas Huber1a447be2012-12-03 11:18:00 -080079struct NuPlayer::SetSurfaceAction : public Action {
80 SetSurfaceAction(const sp<NativeWindowWrapper> &wrapper)
81 : mWrapper(wrapper) {
82 }
83
84 virtual void execute(NuPlayer *player) {
85 player->performSetSurface(mWrapper);
86 }
87
88private:
89 sp<NativeWindowWrapper> mWrapper;
90
91 DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction);
92};
93
Andreas Huber457ec422012-11-30 10:53:22 -080094// Use this if there's no state necessary to save in order to execute
95// the action.
96struct NuPlayer::SimpleAction : public Action {
97 typedef void (NuPlayer::*ActionFunc)();
98
99 SimpleAction(ActionFunc func)
100 : mFunc(func) {
101 }
102
103 virtual void execute(NuPlayer *player) {
104 (player->*mFunc)();
105 }
106
107private:
108 ActionFunc mFunc;
109
110 DISALLOW_EVIL_CONSTRUCTORS(SimpleAction);
111};
112
Andreas Huberf9334412010-12-15 15:17:42 -0800113////////////////////////////////////////////////////////////////////////////////
114
115NuPlayer::NuPlayer()
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700116 : mUIDValid(false),
Andreas Huber57cea552013-02-05 13:59:56 -0800117 mSourceFlags(0),
Andreas Huber3fe62152011-09-16 15:09:22 -0700118 mVideoIsAVC(false),
Martin Storsjoda38df52013-09-25 16:05:36 +0300119 mNeedsSwRenderer(false),
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700120 mAudioEOS(false),
Andreas Huberf9334412010-12-15 15:17:42 -0800121 mVideoEOS(false),
Andreas Huber5bc087c2010-12-23 10:27:40 -0800122 mScanSourcesPending(false),
Andreas Huber1aef2112011-01-04 14:01:29 -0800123 mScanSourcesGeneration(0),
Andreas Hubera4c5bc02012-11-27 15:02:53 -0800124 mPollDurationGeneration(0),
Andreas Huber6e3d3112011-11-28 12:36:11 -0800125 mTimeDiscontinuityPending(false),
Andreas Huberf9334412010-12-15 15:17:42 -0800126 mFlushingAudio(NONE),
Andreas Huber1aef2112011-01-04 14:01:29 -0800127 mFlushingVideo(NONE),
Andreas Huber3fe62152011-09-16 15:09:22 -0700128 mSkipRenderingAudioUntilMediaTimeUs(-1ll),
129 mSkipRenderingVideoUntilMediaTimeUs(-1ll),
130 mVideoLateByUs(0ll),
131 mNumFramesTotal(0ll),
James Dong53a2d132012-08-31 12:18:27 -0700132 mNumFramesDropped(0ll),
Andreas Huber1a447be2012-12-03 11:18:00 -0800133 mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
134 mStarted(false) {
Andreas Huberf9334412010-12-15 15:17:42 -0800135}
136
137NuPlayer::~NuPlayer() {
138}
139
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700140void NuPlayer::setUID(uid_t uid) {
141 mUIDValid = true;
142 mUID = uid;
143}
144
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800145void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
146 mDriver = driver;
Andreas Huberf9334412010-12-15 15:17:42 -0800147}
148
Andreas Huber57cea552013-02-05 13:59:56 -0800149void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) {
Andreas Huberf9334412010-12-15 15:17:42 -0800150 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
151
Andreas Huber5ab368a2013-02-05 10:14:26 -0800152 sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
153
Andreas Huber84066782011-08-16 09:34:26 -0700154 char prop[PROPERTY_VALUE_MAX];
155 if (property_get("media.stagefright.use-mp4source", prop, NULL)
156 && (!strcmp(prop, "1") || !strcasecmp(prop, "true"))) {
Andreas Huber5ab368a2013-02-05 10:14:26 -0800157 msg->setObject("source", new MP4Source(notify, source));
Andreas Huber84066782011-08-16 09:34:26 -0700158 } else {
Andreas Huber5ab368a2013-02-05 10:14:26 -0800159 msg->setObject("source", new StreamingSource(notify, source));
Andreas Huber84066782011-08-16 09:34:26 -0700160 }
161
Andreas Huber5bc087c2010-12-23 10:27:40 -0800162 msg->post();
163}
Andreas Huberf9334412010-12-15 15:17:42 -0800164
Andreas Huberafed0e12011-09-20 15:39:58 -0700165static bool IsHTTPLiveURL(const char *url) {
166 if (!strncasecmp("http://", url, 7)
Andreas Huber7069bdf2013-04-01 14:28:31 -0700167 || !strncasecmp("https://", url, 8)
168 || !strncasecmp("file://", url, 7)) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700169 size_t len = strlen(url);
170 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
171 return true;
172 }
173
174 if (strstr(url,"m3u8")) {
175 return true;
176 }
177 }
178
179 return false;
180}
181
Andreas Huber57cea552013-02-05 13:59:56 -0800182void NuPlayer::setDataSourceAsync(
Andreas Huber5bc087c2010-12-23 10:27:40 -0800183 const char *url, const KeyedVector<String8, String8> *headers) {
184 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100185 size_t len = strlen(url);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800186
Andreas Huber5ab368a2013-02-05 10:14:26 -0800187 sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
188
Andreas Huberafed0e12011-09-20 15:39:58 -0700189 sp<Source> source;
190 if (IsHTTPLiveURL(url)) {
Andreas Huber5ab368a2013-02-05 10:14:26 -0800191 source = new HTTPLiveSource(notify, url, headers, mUIDValid, mUID);
Andreas Huberafed0e12011-09-20 15:39:58 -0700192 } else if (!strncasecmp(url, "rtsp://", 7)) {
Andreas Huber5ab368a2013-02-05 10:14:26 -0800193 source = new RTSPSource(notify, url, headers, mUIDValid, mUID);
Oscar Rydhé81dd60e2012-02-20 10:15:48 +0100194 } else if ((!strncasecmp(url, "http://", 7)
195 || !strncasecmp(url, "https://", 8))
196 && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
197 || strstr(url, ".sdp?"))) {
198 source = new RTSPSource(notify, url, headers, mUIDValid, mUID, true);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700199 } else {
Andreas Huber5ab368a2013-02-05 10:14:26 -0800200 source = new GenericSource(notify, url, headers, mUIDValid, mUID);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700201 }
202
Andreas Huberafed0e12011-09-20 15:39:58 -0700203 msg->setObject("source", source);
204 msg->post();
205}
206
Andreas Huber57cea552013-02-05 13:59:56 -0800207void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) {
Andreas Huberafed0e12011-09-20 15:39:58 -0700208 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
209
Andreas Huber5ab368a2013-02-05 10:14:26 -0800210 sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
211
212 sp<Source> source = new GenericSource(notify, fd, offset, length);
Andreas Huberafed0e12011-09-20 15:39:58 -0700213 msg->setObject("source", source);
Andreas Huberf9334412010-12-15 15:17:42 -0800214 msg->post();
215}
216
Andreas Huber57cea552013-02-05 13:59:56 -0800217void NuPlayer::prepareAsync() {
218 (new AMessage(kWhatPrepare, id()))->post();
219}
220
Andreas Huber1a447be2012-12-03 11:18:00 -0800221void NuPlayer::setVideoSurfaceTextureAsync(
Andy McFadden484566c2012-12-18 09:46:54 -0800222 const sp<IGraphicBufferProducer> &bufferProducer) {
Glenn Kasten11731182011-02-08 17:26:17 -0800223 sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
Andreas Huber1a447be2012-12-03 11:18:00 -0800224
Andy McFadden484566c2012-12-18 09:46:54 -0800225 if (bufferProducer == NULL) {
Andreas Huber1a447be2012-12-03 11:18:00 -0800226 msg->setObject("native-window", NULL);
227 } else {
228 msg->setObject(
229 "native-window",
230 new NativeWindowWrapper(
Mathias Agopianb1e7cd12013-02-14 17:11:27 -0800231 new Surface(bufferProducer)));
Andreas Huber1a447be2012-12-03 11:18:00 -0800232 }
233
Andreas Huberf9334412010-12-15 15:17:42 -0800234 msg->post();
235}
236
237void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) {
238 sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id());
239 msg->setObject("sink", sink);
240 msg->post();
241}
242
243void NuPlayer::start() {
244 (new AMessage(kWhatStart, id()))->post();
245}
246
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800247void NuPlayer::pause() {
Andreas Huberb4082222011-01-20 15:23:04 -0800248 (new AMessage(kWhatPause, id()))->post();
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800249}
250
251void NuPlayer::resume() {
Andreas Huberb4082222011-01-20 15:23:04 -0800252 (new AMessage(kWhatResume, id()))->post();
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800253}
254
Andreas Huber1aef2112011-01-04 14:01:29 -0800255void NuPlayer::resetAsync() {
256 (new AMessage(kWhatReset, id()))->post();
257}
258
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800259void NuPlayer::seekToAsync(int64_t seekTimeUs) {
260 sp<AMessage> msg = new AMessage(kWhatSeek, id());
261 msg->setInt64("seekTimeUs", seekTimeUs);
262 msg->post();
263}
264
Andreas Huber53df1a42010-12-22 10:03:04 -0800265// static
Andreas Huber1aef2112011-01-04 14:01:29 -0800266bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
Andreas Huber53df1a42010-12-22 10:03:04 -0800267 switch (state) {
268 case FLUSHING_DECODER:
Andreas Huber1aef2112011-01-04 14:01:29 -0800269 if (needShutdown != NULL) {
270 *needShutdown = false;
Andreas Huber53df1a42010-12-22 10:03:04 -0800271 }
272 return true;
273
Andreas Huber1aef2112011-01-04 14:01:29 -0800274 case FLUSHING_DECODER_SHUTDOWN:
275 if (needShutdown != NULL) {
276 *needShutdown = true;
Andreas Huber53df1a42010-12-22 10:03:04 -0800277 }
278 return true;
279
280 default:
281 return false;
282 }
283}
284
Andreas Huberf9334412010-12-15 15:17:42 -0800285void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
286 switch (msg->what()) {
287 case kWhatSetDataSource:
288 {
Steve Block3856b092011-10-20 11:56:00 +0100289 ALOGV("kWhatSetDataSource");
Andreas Huberf9334412010-12-15 15:17:42 -0800290
291 CHECK(mSource == NULL);
292
Andreas Huber5bc087c2010-12-23 10:27:40 -0800293 sp<RefBase> obj;
294 CHECK(msg->findObject("source", &obj));
Andreas Huberf9334412010-12-15 15:17:42 -0800295
Andreas Huber5bc087c2010-12-23 10:27:40 -0800296 mSource = static_cast<Source *>(obj.get());
Andreas Huber5ab368a2013-02-05 10:14:26 -0800297
298 looper()->registerHandler(mSource);
Andreas Huber57cea552013-02-05 13:59:56 -0800299
300 CHECK(mDriver != NULL);
301 sp<NuPlayerDriver> driver = mDriver.promote();
302 if (driver != NULL) {
303 driver->notifySetDataSourceCompleted(OK);
304 }
305 break;
306 }
307
308 case kWhatPrepare:
309 {
310 mSource->prepareAsync();
Andreas Huberf9334412010-12-15 15:17:42 -0800311 break;
312 }
313
Andreas Hubera4c5bc02012-11-27 15:02:53 -0800314 case kWhatPollDuration:
315 {
316 int32_t generation;
317 CHECK(msg->findInt32("generation", &generation));
318
319 if (generation != mPollDurationGeneration) {
320 // stale
321 break;
322 }
323
324 int64_t durationUs;
325 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
326 sp<NuPlayerDriver> driver = mDriver.promote();
327 if (driver != NULL) {
328 driver->notifyDuration(durationUs);
329 }
330 }
331
332 msg->post(1000000ll); // poll again in a second.
333 break;
334 }
335
Glenn Kasten11731182011-02-08 17:26:17 -0800336 case kWhatSetVideoNativeWindow:
Andreas Huberf9334412010-12-15 15:17:42 -0800337 {
Steve Block3856b092011-10-20 11:56:00 +0100338 ALOGV("kWhatSetVideoNativeWindow");
Andreas Huberf9334412010-12-15 15:17:42 -0800339
Andreas Huber1a447be2012-12-03 11:18:00 -0800340 mDeferredActions.push_back(
341 new SimpleAction(&NuPlayer::performDecoderShutdown));
342
Andreas Huberf9334412010-12-15 15:17:42 -0800343 sp<RefBase> obj;
Glenn Kasten11731182011-02-08 17:26:17 -0800344 CHECK(msg->findObject("native-window", &obj));
Andreas Huberf9334412010-12-15 15:17:42 -0800345
Andreas Huber1a447be2012-12-03 11:18:00 -0800346 mDeferredActions.push_back(
347 new SetSurfaceAction(
348 static_cast<NativeWindowWrapper *>(obj.get())));
James Dong53a2d132012-08-31 12:18:27 -0700349
Andreas Huber1a447be2012-12-03 11:18:00 -0800350 if (obj != NULL) {
351 // If there is a new surface texture, instantiate decoders
352 // again if possible.
353 mDeferredActions.push_back(
354 new SimpleAction(&NuPlayer::performScanSources));
355 }
356
357 processDeferredActions();
Andreas Huberf9334412010-12-15 15:17:42 -0800358 break;
359 }
360
361 case kWhatSetAudioSink:
362 {
Steve Block3856b092011-10-20 11:56:00 +0100363 ALOGV("kWhatSetAudioSink");
Andreas Huberf9334412010-12-15 15:17:42 -0800364
365 sp<RefBase> obj;
366 CHECK(msg->findObject("sink", &obj));
367
368 mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get());
369 break;
370 }
371
372 case kWhatStart:
373 {
Steve Block3856b092011-10-20 11:56:00 +0100374 ALOGV("kWhatStart");
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800375
Andreas Huber3fe62152011-09-16 15:09:22 -0700376 mVideoIsAVC = false;
Martin Storsjoda38df52013-09-25 16:05:36 +0300377 mNeedsSwRenderer = false;
Andreas Huber1aef2112011-01-04 14:01:29 -0800378 mAudioEOS = false;
379 mVideoEOS = false;
Andreas Huber32f3cef2011-03-02 15:34:46 -0800380 mSkipRenderingAudioUntilMediaTimeUs = -1;
381 mSkipRenderingVideoUntilMediaTimeUs = -1;
Andreas Huber3fe62152011-09-16 15:09:22 -0700382 mVideoLateByUs = 0;
383 mNumFramesTotal = 0;
384 mNumFramesDropped = 0;
Andreas Huber1a447be2012-12-03 11:18:00 -0800385 mStarted = true;
Andreas Huber1aef2112011-01-04 14:01:29 -0800386
Andreas Huber5bc087c2010-12-23 10:27:40 -0800387 mSource->start();
Andreas Huberf9334412010-12-15 15:17:42 -0800388
Andreas Huber9dffd242013-03-12 11:01:43 -0700389 uint32_t flags = 0;
390
391 if (mSource->isRealTime()) {
392 flags |= Renderer::FLAG_REAL_TIME;
393 }
394
Andreas Huberf9334412010-12-15 15:17:42 -0800395 mRenderer = new Renderer(
396 mAudioSink,
Andreas Huber9dffd242013-03-12 11:01:43 -0700397 new AMessage(kWhatRendererNotify, id()),
398 flags);
Andreas Huberf9334412010-12-15 15:17:42 -0800399
400 looper()->registerHandler(mRenderer);
401
Andreas Huber1aef2112011-01-04 14:01:29 -0800402 postScanSources();
Andreas Huberf9334412010-12-15 15:17:42 -0800403 break;
404 }
405
406 case kWhatScanSources:
407 {
Andreas Huber1aef2112011-01-04 14:01:29 -0800408 int32_t generation;
409 CHECK(msg->findInt32("generation", &generation));
410 if (generation != mScanSourcesGeneration) {
411 // Drop obsolete msg.
412 break;
413 }
414
Andreas Huber5bc087c2010-12-23 10:27:40 -0800415 mScanSourcesPending = false;
416
Steve Block3856b092011-10-20 11:56:00 +0100417 ALOGV("scanning sources haveAudio=%d, haveVideo=%d",
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800418 mAudioDecoder != NULL, mVideoDecoder != NULL);
419
Andreas Hubera4c5bc02012-11-27 15:02:53 -0800420 bool mHadAnySourcesBefore =
421 (mAudioDecoder != NULL) || (mVideoDecoder != NULL);
422
Haynes Mathew George5d246ef2012-07-09 10:36:57 -0700423 if (mNativeWindow != NULL) {
424 instantiateDecoder(false, &mVideoDecoder);
425 }
Andreas Huberf9334412010-12-15 15:17:42 -0800426
427 if (mAudioSink != NULL) {
Andreas Huber5bc087c2010-12-23 10:27:40 -0800428 instantiateDecoder(true, &mAudioDecoder);
Andreas Huberf9334412010-12-15 15:17:42 -0800429 }
430
Andreas Hubera4c5bc02012-11-27 15:02:53 -0800431 if (!mHadAnySourcesBefore
432 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
433 // This is the first time we've found anything playable.
434
Andreas Huber57cea552013-02-05 13:59:56 -0800435 if (mSourceFlags & Source::FLAG_DYNAMIC_DURATION) {
Andreas Hubera4c5bc02012-11-27 15:02:53 -0800436 schedulePollDuration();
437 }
438 }
439
Andreas Hubereac68ba2011-09-27 12:12:25 -0700440 status_t err;
441 if ((err = mSource->feedMoreTSData()) != OK) {
Andreas Huber1aef2112011-01-04 14:01:29 -0800442 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
443 // We're not currently decoding anything (no audio or
444 // video tracks found) and we just ran out of input data.
Andreas Hubereac68ba2011-09-27 12:12:25 -0700445
446 if (err == ERROR_END_OF_STREAM) {
447 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
448 } else {
449 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
450 }
Andreas Huber1aef2112011-01-04 14:01:29 -0800451 }
Andreas Huberf9334412010-12-15 15:17:42 -0800452 break;
453 }
454
Andreas Huber8a61c222012-08-31 14:05:27 -0700455 if ((mAudioDecoder == NULL && mAudioSink != NULL)
456 || (mVideoDecoder == NULL && mNativeWindow != NULL)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800457 msg->post(100000ll);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800458 mScanSourcesPending = true;
Andreas Huberf9334412010-12-15 15:17:42 -0800459 }
460 break;
461 }
462
463 case kWhatVideoNotify:
464 case kWhatAudioNotify:
465 {
466 bool audio = msg->what() == kWhatAudioNotify;
467
468 sp<AMessage> codecRequest;
469 CHECK(msg->findMessage("codec-request", &codecRequest));
470
471 int32_t what;
472 CHECK(codecRequest->findInt32("what", &what));
473
474 if (what == ACodec::kWhatFillThisBuffer) {
475 status_t err = feedDecoderInputData(
476 audio, codecRequest);
477
Andreas Huber5bc087c2010-12-23 10:27:40 -0800478 if (err == -EWOULDBLOCK) {
Andreas Hubereac68ba2011-09-27 12:12:25 -0700479 if (mSource->feedMoreTSData() == OK) {
Andreas Huber1183a4a2011-11-03 11:00:21 -0700480 msg->post(10000ll);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800481 }
Andreas Huberf9334412010-12-15 15:17:42 -0800482 }
483 } else if (what == ACodec::kWhatEOS) {
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700484 int32_t err;
485 CHECK(codecRequest->findInt32("err", &err));
486
487 if (err == ERROR_END_OF_STREAM) {
Steve Block3856b092011-10-20 11:56:00 +0100488 ALOGV("got %s decoder EOS", audio ? "audio" : "video");
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700489 } else {
Steve Block3856b092011-10-20 11:56:00 +0100490 ALOGV("got %s decoder EOS w/ error %d",
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700491 audio ? "audio" : "video",
492 err);
493 }
494
495 mRenderer->queueEOS(audio, err);
Andreas Huberf9334412010-12-15 15:17:42 -0800496 } else if (what == ACodec::kWhatFlushCompleted) {
Andreas Huber1aef2112011-01-04 14:01:29 -0800497 bool needShutdown;
Andreas Huber53df1a42010-12-22 10:03:04 -0800498
Andreas Huberf9334412010-12-15 15:17:42 -0800499 if (audio) {
Andreas Huber1aef2112011-01-04 14:01:29 -0800500 CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
Andreas Huberf9334412010-12-15 15:17:42 -0800501 mFlushingAudio = FLUSHED;
502 } else {
Andreas Huber1aef2112011-01-04 14:01:29 -0800503 CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
Andreas Huberf9334412010-12-15 15:17:42 -0800504 mFlushingVideo = FLUSHED;
Andreas Huber3fe62152011-09-16 15:09:22 -0700505
506 mVideoLateByUs = 0;
Andreas Huberf9334412010-12-15 15:17:42 -0800507 }
508
Steve Block3856b092011-10-20 11:56:00 +0100509 ALOGV("decoder %s flush completed", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800510
Andreas Huber1aef2112011-01-04 14:01:29 -0800511 if (needShutdown) {
Steve Block3856b092011-10-20 11:56:00 +0100512 ALOGV("initiating %s decoder shutdown",
Andreas Huber53df1a42010-12-22 10:03:04 -0800513 audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800514
Andreas Huber53df1a42010-12-22 10:03:04 -0800515 (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
Andreas Huberf9334412010-12-15 15:17:42 -0800516
Andreas Huber53df1a42010-12-22 10:03:04 -0800517 if (audio) {
518 mFlushingAudio = SHUTTING_DOWN_DECODER;
519 } else {
520 mFlushingVideo = SHUTTING_DOWN_DECODER;
521 }
Andreas Huberf9334412010-12-15 15:17:42 -0800522 }
Andreas Huber3831a062010-12-21 10:22:33 -0800523
524 finishFlushIfPossible();
Andreas Huber2c2814b2010-12-15 17:18:20 -0800525 } else if (what == ACodec::kWhatOutputFormatChanged) {
Andreas Huber31e25082011-01-10 10:38:31 -0800526 if (audio) {
527 int32_t numChannels;
Andreas Hubere9810fa2012-12-03 15:20:40 -0800528 CHECK(codecRequest->findInt32(
529 "channel-count", &numChannels));
Andreas Huber2c2814b2010-12-15 17:18:20 -0800530
Andreas Huber31e25082011-01-10 10:38:31 -0800531 int32_t sampleRate;
532 CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
Andreas Huber2c2814b2010-12-15 17:18:20 -0800533
Steve Block3856b092011-10-20 11:56:00 +0100534 ALOGV("Audio output format changed to %d Hz, %d channels",
Andreas Huber31e25082011-01-10 10:38:31 -0800535 sampleRate, numChannels);
Andreas Huber2c2814b2010-12-15 17:18:20 -0800536
Andreas Huber31e25082011-01-10 10:38:31 -0800537 mAudioSink->close();
Eric Laurent1948eb32012-04-13 16:50:19 -0700538
539 audio_output_flags_t flags;
540 int64_t durationUs;
Andreas Hubere9810fa2012-12-03 15:20:40 -0800541 // FIXME: we should handle the case where the video decoder
542 // is created after we receive the format change indication.
543 // Current code will just make that we select deep buffer
544 // with video which should not be a problem as it should
Eric Laurent1948eb32012-04-13 16:50:19 -0700545 // not prevent from keeping A/V sync.
546 if (mVideoDecoder == NULL &&
547 mSource->getDuration(&durationUs) == OK &&
Andreas Hubere9810fa2012-12-03 15:20:40 -0800548 durationUs
549 > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
Eric Laurent1948eb32012-04-13 16:50:19 -0700550 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
551 } else {
552 flags = AUDIO_OUTPUT_FLAG_NONE;
553 }
554
Andreas Huber98065552012-05-03 11:33:01 -0700555 int32_t channelMask;
556 if (!codecRequest->findInt32("channel-mask", &channelMask)) {
557 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
558 }
559
Andreas Huber078cfcf2011-09-15 12:25:04 -0700560 CHECK_EQ(mAudioSink->open(
561 sampleRate,
562 numChannels,
Andreas Huber98065552012-05-03 11:33:01 -0700563 (audio_channel_mask_t)channelMask,
Andreas Huber078cfcf2011-09-15 12:25:04 -0700564 AUDIO_FORMAT_PCM_16_BIT,
Eric Laurent1948eb32012-04-13 16:50:19 -0700565 8 /* bufferCount */,
566 NULL,
567 NULL,
568 flags),
Andreas Huber078cfcf2011-09-15 12:25:04 -0700569 (status_t)OK);
Andreas Huber31e25082011-01-10 10:38:31 -0800570 mAudioSink->start();
Andreas Huber2c2814b2010-12-15 17:18:20 -0800571
Andreas Huber31e25082011-01-10 10:38:31 -0800572 mRenderer->signalAudioSinkChanged();
573 } else {
574 // video
Andreas Huber3831a062010-12-21 10:22:33 -0800575
Andreas Huber31e25082011-01-10 10:38:31 -0800576 int32_t width, height;
577 CHECK(codecRequest->findInt32("width", &width));
578 CHECK(codecRequest->findInt32("height", &height));
579
580 int32_t cropLeft, cropTop, cropRight, cropBottom;
581 CHECK(codecRequest->findRect(
582 "crop",
583 &cropLeft, &cropTop, &cropRight, &cropBottom));
584
Andreas Hubere9810fa2012-12-03 15:20:40 -0800585 int32_t displayWidth = cropRight - cropLeft + 1;
586 int32_t displayHeight = cropBottom - cropTop + 1;
587
Steve Block3856b092011-10-20 11:56:00 +0100588 ALOGV("Video output format changed to %d x %d "
Andreas Hubercb67cd12011-08-26 16:02:19 -0700589 "(crop: %d x %d @ (%d, %d))",
Andreas Huber31e25082011-01-10 10:38:31 -0800590 width, height,
Andreas Hubere9810fa2012-12-03 15:20:40 -0800591 displayWidth,
592 displayHeight,
Andreas Hubercb67cd12011-08-26 16:02:19 -0700593 cropLeft, cropTop);
Andreas Huber31e25082011-01-10 10:38:31 -0800594
Andreas Hubere9810fa2012-12-03 15:20:40 -0800595 sp<AMessage> videoInputFormat =
596 mSource->getFormat(false /* audio */);
597
598 // Take into account sample aspect ratio if necessary:
599 int32_t sarWidth, sarHeight;
600 if (videoInputFormat->findInt32("sar-width", &sarWidth)
601 && videoInputFormat->findInt32(
602 "sar-height", &sarHeight)) {
603 ALOGV("Sample aspect ratio %d : %d",
604 sarWidth, sarHeight);
605
606 displayWidth = (displayWidth * sarWidth) / sarHeight;
607
608 ALOGV("display dimensions %d x %d",
609 displayWidth, displayHeight);
610 }
611
Andreas Huber31e25082011-01-10 10:38:31 -0800612 notifyListener(
Andreas Hubere9810fa2012-12-03 15:20:40 -0800613 MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight);
Martin Storsjoda38df52013-09-25 16:05:36 +0300614
615 if (mNeedsSwRenderer && mNativeWindow != NULL) {
616 int32_t colorFormat;
617 CHECK(codecRequest->findInt32("color-format", &colorFormat));
618
619 sp<MetaData> meta = new MetaData;
620 meta->setInt32(kKeyWidth, width);
621 meta->setInt32(kKeyHeight, height);
622 meta->setRect(kKeyCropRect, cropLeft, cropTop, cropRight, cropBottom);
623 meta->setInt32(kKeyColorFormat, colorFormat);
624
625 mRenderer->setSoftRenderer(
626 new SoftwareRenderer(mNativeWindow->getNativeWindow(), meta));
627 }
Andreas Huber31e25082011-01-10 10:38:31 -0800628 }
Andreas Huber3831a062010-12-21 10:22:33 -0800629 } else if (what == ACodec::kWhatShutdownCompleted) {
Steve Block3856b092011-10-20 11:56:00 +0100630 ALOGV("%s shutdown completed", audio ? "audio" : "video");
Andreas Huber3831a062010-12-21 10:22:33 -0800631 if (audio) {
632 mAudioDecoder.clear();
633
634 CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
635 mFlushingAudio = SHUT_DOWN;
636 } else {
637 mVideoDecoder.clear();
638
639 CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
640 mFlushingVideo = SHUT_DOWN;
641 }
642
643 finishFlushIfPossible();
Andreas Huberc92fd242011-08-16 13:48:44 -0700644 } else if (what == ACodec::kWhatError) {
Steve Block29357bc2012-01-06 19:20:56 +0000645 ALOGE("Received error from %s decoder, aborting playback.",
Andreas Huberc92fd242011-08-16 13:48:44 -0700646 audio ? "audio" : "video");
647
648 mRenderer->queueEOS(audio, UNKNOWN_ERROR);
Andreas Huber57788222012-02-21 11:47:18 -0800649 } else if (what == ACodec::kWhatDrainThisBuffer) {
Andreas Huberf9334412010-12-15 15:17:42 -0800650 renderBuffer(audio, codecRequest);
Martin Storsjoda38df52013-09-25 16:05:36 +0300651 } else if (what == ACodec::kWhatComponentAllocated) {
652 if (!audio) {
653 AString name;
654 CHECK(codecRequest->findString("componentName", &name));
655 mNeedsSwRenderer = name.startsWith("OMX.google.");
656 }
657 } else if (what != ACodec::kWhatComponentConfigured
Andreas Huber457ec422012-11-30 10:53:22 -0800658 && what != ACodec::kWhatBuffersAllocated) {
659 ALOGV("Unhandled codec notification %d '%c%c%c%c'.",
660 what,
661 what >> 24,
662 (what >> 16) & 0xff,
663 (what >> 8) & 0xff,
664 what & 0xff);
Andreas Huberf9334412010-12-15 15:17:42 -0800665 }
666
667 break;
668 }
669
670 case kWhatRendererNotify:
671 {
672 int32_t what;
673 CHECK(msg->findInt32("what", &what));
674
675 if (what == Renderer::kWhatEOS) {
676 int32_t audio;
677 CHECK(msg->findInt32("audio", &audio));
678
Andreas Huberc92fd242011-08-16 13:48:44 -0700679 int32_t finalResult;
680 CHECK(msg->findInt32("finalResult", &finalResult));
681
Andreas Huberf9334412010-12-15 15:17:42 -0800682 if (audio) {
683 mAudioEOS = true;
684 } else {
685 mVideoEOS = true;
686 }
687
Andreas Huberc92fd242011-08-16 13:48:44 -0700688 if (finalResult == ERROR_END_OF_STREAM) {
Steve Block3856b092011-10-20 11:56:00 +0100689 ALOGV("reached %s EOS", audio ? "audio" : "video");
Andreas Huberc92fd242011-08-16 13:48:44 -0700690 } else {
Steve Block29357bc2012-01-06 19:20:56 +0000691 ALOGE("%s track encountered an error (%d)",
Andreas Huberc92fd242011-08-16 13:48:44 -0700692 audio ? "audio" : "video", finalResult);
693
694 notifyListener(
695 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult);
696 }
Andreas Huberf9334412010-12-15 15:17:42 -0800697
698 if ((mAudioEOS || mAudioDecoder == NULL)
699 && (mVideoEOS || mVideoDecoder == NULL)) {
700 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
701 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800702 } else if (what == Renderer::kWhatPosition) {
703 int64_t positionUs;
704 CHECK(msg->findInt64("positionUs", &positionUs));
705
Andreas Huber3fe62152011-09-16 15:09:22 -0700706 CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs));
707
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800708 if (mDriver != NULL) {
709 sp<NuPlayerDriver> driver = mDriver.promote();
710 if (driver != NULL) {
711 driver->notifyPosition(positionUs);
Andreas Huber3fe62152011-09-16 15:09:22 -0700712
713 driver->notifyFrameStats(
714 mNumFramesTotal, mNumFramesDropped);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800715 }
716 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700717 } else if (what == Renderer::kWhatFlushComplete) {
Andreas Huberf9334412010-12-15 15:17:42 -0800718 int32_t audio;
719 CHECK(msg->findInt32("audio", &audio));
720
Steve Block3856b092011-10-20 11:56:00 +0100721 ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
James Dongf57b4ea2012-07-20 13:38:36 -0700722 } else if (what == Renderer::kWhatVideoRenderingStart) {
723 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
Andreas Huberf9334412010-12-15 15:17:42 -0800724 }
725 break;
726 }
727
728 case kWhatMoreDataQueued:
729 {
730 break;
731 }
732
Andreas Huber1aef2112011-01-04 14:01:29 -0800733 case kWhatReset:
734 {
Steve Block3856b092011-10-20 11:56:00 +0100735 ALOGV("kWhatReset");
Andreas Huber1aef2112011-01-04 14:01:29 -0800736
Andreas Huber457ec422012-11-30 10:53:22 -0800737 mDeferredActions.push_back(
738 new SimpleAction(&NuPlayer::performDecoderShutdown));
Andreas Hubera4c5bc02012-11-27 15:02:53 -0800739
Andreas Huber457ec422012-11-30 10:53:22 -0800740 mDeferredActions.push_back(
741 new SimpleAction(&NuPlayer::performReset));
Andreas Huberb58ce9f2011-11-28 16:27:35 -0800742
Andreas Huber457ec422012-11-30 10:53:22 -0800743 processDeferredActions();
Andreas Huber1aef2112011-01-04 14:01:29 -0800744 break;
745 }
746
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800747 case kWhatSeek:
748 {
749 int64_t seekTimeUs;
750 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
751
Andreas Huber457ec422012-11-30 10:53:22 -0800752 ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800753
Andreas Huber457ec422012-11-30 10:53:22 -0800754 mDeferredActions.push_back(
755 new SimpleAction(&NuPlayer::performDecoderFlush));
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800756
Andreas Huber457ec422012-11-30 10:53:22 -0800757 mDeferredActions.push_back(new SeekAction(seekTimeUs));
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800758
Andreas Huber457ec422012-11-30 10:53:22 -0800759 processDeferredActions();
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800760 break;
761 }
762
Andreas Huberb4082222011-01-20 15:23:04 -0800763 case kWhatPause:
764 {
765 CHECK(mRenderer != NULL);
Roger Jönsson46d13e32013-01-21 17:15:45 +0100766 mSource->pause();
Andreas Huberb4082222011-01-20 15:23:04 -0800767 mRenderer->pause();
768 break;
769 }
770
771 case kWhatResume:
772 {
773 CHECK(mRenderer != NULL);
Roger Jönsson46d13e32013-01-21 17:15:45 +0100774 mSource->resume();
Andreas Huberb4082222011-01-20 15:23:04 -0800775 mRenderer->resume();
776 break;
777 }
778
Andreas Huber5ab368a2013-02-05 10:14:26 -0800779 case kWhatSourceNotify:
780 {
Andreas Huber57cea552013-02-05 13:59:56 -0800781 onSourceNotify(msg);
Andreas Huber5ab368a2013-02-05 10:14:26 -0800782 break;
783 }
784
Andreas Huberf9334412010-12-15 15:17:42 -0800785 default:
786 TRESPASS();
787 break;
788 }
789}
790
Andreas Huber3831a062010-12-21 10:22:33 -0800791void NuPlayer::finishFlushIfPossible() {
792 if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
793 return;
794 }
795
796 if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
797 return;
798 }
799
Steve Block3856b092011-10-20 11:56:00 +0100800 ALOGV("both audio and video are flushed now.");
Andreas Huber3831a062010-12-21 10:22:33 -0800801
Andreas Huber6e3d3112011-11-28 12:36:11 -0800802 if (mTimeDiscontinuityPending) {
803 mRenderer->signalTimeDiscontinuity();
804 mTimeDiscontinuityPending = false;
805 }
Andreas Huber3831a062010-12-21 10:22:33 -0800806
Andreas Huber22fc52f2011-01-05 16:24:27 -0800807 if (mAudioDecoder != NULL) {
Andreas Huber3831a062010-12-21 10:22:33 -0800808 mAudioDecoder->signalResume();
809 }
810
Andreas Huber22fc52f2011-01-05 16:24:27 -0800811 if (mVideoDecoder != NULL) {
Andreas Huber3831a062010-12-21 10:22:33 -0800812 mVideoDecoder->signalResume();
813 }
814
815 mFlushingAudio = NONE;
816 mFlushingVideo = NONE;
Andreas Huber3831a062010-12-21 10:22:33 -0800817
Andreas Huber457ec422012-11-30 10:53:22 -0800818 processDeferredActions();
Andreas Huber1aef2112011-01-04 14:01:29 -0800819}
820
821void NuPlayer::postScanSources() {
822 if (mScanSourcesPending) {
823 return;
824 }
825
826 sp<AMessage> msg = new AMessage(kWhatScanSources, id());
827 msg->setInt32("generation", mScanSourcesGeneration);
828 msg->post();
829
830 mScanSourcesPending = true;
831}
832
Andreas Huber5bc087c2010-12-23 10:27:40 -0800833status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
Andreas Huberf9334412010-12-15 15:17:42 -0800834 if (*decoder != NULL) {
835 return OK;
836 }
837
Andreas Huber84066782011-08-16 09:34:26 -0700838 sp<AMessage> format = mSource->getFormat(audio);
Andreas Huberf9334412010-12-15 15:17:42 -0800839
Andreas Huber84066782011-08-16 09:34:26 -0700840 if (format == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -0800841 return -EWOULDBLOCK;
842 }
843
Andreas Huber3fe62152011-09-16 15:09:22 -0700844 if (!audio) {
Andreas Huber84066782011-08-16 09:34:26 -0700845 AString mime;
846 CHECK(format->findString("mime", &mime));
847 mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
Andreas Huber3fe62152011-09-16 15:09:22 -0700848 }
849
Andreas Huberf9334412010-12-15 15:17:42 -0800850 sp<AMessage> notify =
851 new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
852 id());
853
Glenn Kasten11731182011-02-08 17:26:17 -0800854 *decoder = audio ? new Decoder(notify) :
855 new Decoder(notify, mNativeWindow);
Andreas Huberf9334412010-12-15 15:17:42 -0800856 looper()->registerHandler(*decoder);
857
Andreas Huber84066782011-08-16 09:34:26 -0700858 (*decoder)->configure(format);
Andreas Huberf9334412010-12-15 15:17:42 -0800859
Andreas Huberf9334412010-12-15 15:17:42 -0800860 return OK;
861}
862
863status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
864 sp<AMessage> reply;
865 CHECK(msg->findMessage("reply", &reply));
866
Andreas Huber53df1a42010-12-22 10:03:04 -0800867 if ((audio && IsFlushingState(mFlushingAudio))
868 || (!audio && IsFlushingState(mFlushingVideo))) {
Andreas Huberf9334412010-12-15 15:17:42 -0800869 reply->setInt32("err", INFO_DISCONTINUITY);
870 reply->post();
871 return OK;
872 }
873
874 sp<ABuffer> accessUnit;
Andreas Huberf9334412010-12-15 15:17:42 -0800875
Andreas Huber3fe62152011-09-16 15:09:22 -0700876 bool dropAccessUnit;
877 do {
878 status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800879
Andreas Huber3fe62152011-09-16 15:09:22 -0700880 if (err == -EWOULDBLOCK) {
881 return err;
882 } else if (err != OK) {
883 if (err == INFO_DISCONTINUITY) {
884 int32_t type;
885 CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
Andreas Huber53df1a42010-12-22 10:03:04 -0800886
Andreas Huber3fe62152011-09-16 15:09:22 -0700887 bool formatChange =
Andreas Huber6e3d3112011-11-28 12:36:11 -0800888 (audio &&
889 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
890 || (!audio &&
891 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
Andreas Huber53df1a42010-12-22 10:03:04 -0800892
Andreas Huber6e3d3112011-11-28 12:36:11 -0800893 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
894
Steve Blockdf64d152012-01-04 20:05:49 +0000895 ALOGI("%s discontinuity (formatChange=%d, time=%d)",
Andreas Huber6e3d3112011-11-28 12:36:11 -0800896 audio ? "audio" : "video", formatChange, timeChange);
Andreas Huber32f3cef2011-03-02 15:34:46 -0800897
Andreas Huber3fe62152011-09-16 15:09:22 -0700898 if (audio) {
899 mSkipRenderingAudioUntilMediaTimeUs = -1;
900 } else {
901 mSkipRenderingVideoUntilMediaTimeUs = -1;
902 }
Andreas Huber32f3cef2011-03-02 15:34:46 -0800903
Andreas Huber6e3d3112011-11-28 12:36:11 -0800904 if (timeChange) {
905 sp<AMessage> extra;
906 if (accessUnit->meta()->findMessage("extra", &extra)
907 && extra != NULL) {
908 int64_t resumeAtMediaTimeUs;
909 if (extra->findInt64(
910 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
Steve Blockdf64d152012-01-04 20:05:49 +0000911 ALOGI("suppressing rendering of %s until %lld us",
Andreas Huber6e3d3112011-11-28 12:36:11 -0800912 audio ? "audio" : "video", resumeAtMediaTimeUs);
Andreas Huber3fe62152011-09-16 15:09:22 -0700913
Andreas Huber6e3d3112011-11-28 12:36:11 -0800914 if (audio) {
915 mSkipRenderingAudioUntilMediaTimeUs =
916 resumeAtMediaTimeUs;
917 } else {
918 mSkipRenderingVideoUntilMediaTimeUs =
919 resumeAtMediaTimeUs;
920 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700921 }
Andreas Huber32f3cef2011-03-02 15:34:46 -0800922 }
923 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700924
Andreas Huber6e3d3112011-11-28 12:36:11 -0800925 mTimeDiscontinuityPending =
926 mTimeDiscontinuityPending || timeChange;
927
928 if (formatChange || timeChange) {
Andreas Huber457ec422012-11-30 10:53:22 -0800929 if (mFlushingAudio == NONE && mFlushingVideo == NONE) {
930 // And we'll resume scanning sources once we're done
931 // flushing.
932 mDeferredActions.push_front(
933 new SimpleAction(
934 &NuPlayer::performScanSources));
935 }
936
Andreas Huber6e3d3112011-11-28 12:36:11 -0800937 flushDecoder(audio, formatChange);
938 } else {
939 // This stream is unaffected by the discontinuity
940
941 if (audio) {
942 mFlushingAudio = FLUSHED;
943 } else {
944 mFlushingVideo = FLUSHED;
945 }
946
947 finishFlushIfPossible();
948
949 return -EWOULDBLOCK;
950 }
Andreas Huber32f3cef2011-03-02 15:34:46 -0800951 }
952
Andreas Huber3fe62152011-09-16 15:09:22 -0700953 reply->setInt32("err", err);
954 reply->post();
955 return OK;
Andreas Huberf9334412010-12-15 15:17:42 -0800956 }
957
Andreas Huber3fe62152011-09-16 15:09:22 -0700958 if (!audio) {
959 ++mNumFramesTotal;
960 }
961
962 dropAccessUnit = false;
963 if (!audio
964 && mVideoLateByUs > 100000ll
965 && mVideoIsAVC
966 && !IsAVCReferenceFrame(accessUnit)) {
967 dropAccessUnit = true;
968 ++mNumFramesDropped;
969 }
970 } while (dropAccessUnit);
Andreas Huberf9334412010-12-15 15:17:42 -0800971
Steve Block3856b092011-10-20 11:56:00 +0100972 // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800973
974#if 0
975 int64_t mediaTimeUs;
976 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
Steve Block3856b092011-10-20 11:56:00 +0100977 ALOGV("feeding %s input buffer at media time %.2f secs",
Andreas Huberf9334412010-12-15 15:17:42 -0800978 audio ? "audio" : "video",
979 mediaTimeUs / 1E6);
980#endif
981
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800982 reply->setBuffer("buffer", accessUnit);
Andreas Huberf9334412010-12-15 15:17:42 -0800983 reply->post();
984
985 return OK;
986}
987
988void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
Steve Block3856b092011-10-20 11:56:00 +0100989 // ALOGV("renderBuffer %s", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800990
991 sp<AMessage> reply;
992 CHECK(msg->findMessage("reply", &reply));
993
Andreas Huber18ac5402011-08-31 15:04:25 -0700994 if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) {
995 // We're currently attempting to flush the decoder, in order
996 // to complete this, the decoder wants all its buffers back,
997 // so we don't want any output buffers it sent us (from before
998 // we initiated the flush) to be stuck in the renderer's queue.
999
Steve Block3856b092011-10-20 11:56:00 +01001000 ALOGV("we're still flushing the %s decoder, sending its output buffer"
Andreas Huber18ac5402011-08-31 15:04:25 -07001001 " right back.", audio ? "audio" : "video");
1002
1003 reply->post();
1004 return;
1005 }
1006
Andreas Huber2d8bedd2012-02-21 14:38:23 -08001007 sp<ABuffer> buffer;
1008 CHECK(msg->findBuffer("buffer", &buffer));
Andreas Huberf9334412010-12-15 15:17:42 -08001009
Andreas Huber32f3cef2011-03-02 15:34:46 -08001010 int64_t &skipUntilMediaTimeUs =
1011 audio
1012 ? mSkipRenderingAudioUntilMediaTimeUs
1013 : mSkipRenderingVideoUntilMediaTimeUs;
1014
1015 if (skipUntilMediaTimeUs >= 0) {
1016 int64_t mediaTimeUs;
1017 CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs));
1018
1019 if (mediaTimeUs < skipUntilMediaTimeUs) {
Steve Block3856b092011-10-20 11:56:00 +01001020 ALOGV("dropping %s buffer at time %lld as requested.",
Andreas Huber32f3cef2011-03-02 15:34:46 -08001021 audio ? "audio" : "video",
1022 mediaTimeUs);
1023
1024 reply->post();
1025 return;
1026 }
1027
1028 skipUntilMediaTimeUs = -1;
1029 }
1030
Andreas Huberf9334412010-12-15 15:17:42 -08001031 mRenderer->queueBuffer(audio, buffer, reply);
1032}
1033
1034void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001035 if (mDriver == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -08001036 return;
1037 }
1038
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001039 sp<NuPlayerDriver> driver = mDriver.promote();
Andreas Huberf9334412010-12-15 15:17:42 -08001040
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001041 if (driver == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -08001042 return;
1043 }
1044
Andreas Hubera4af2142011-10-26 15:23:31 -07001045 driver->notifyListener(msg, ext1, ext2);
Andreas Huberf9334412010-12-15 15:17:42 -08001046}
1047
Andreas Huber1aef2112011-01-04 14:01:29 -08001048void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
Andreas Huber6e3d3112011-11-28 12:36:11 -08001049 if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
Steve Blockdf64d152012-01-04 20:05:49 +00001050 ALOGI("flushDecoder %s without decoder present",
Andreas Huber6e3d3112011-11-28 12:36:11 -08001051 audio ? "audio" : "video");
1052 }
1053
Andreas Huber1aef2112011-01-04 14:01:29 -08001054 // Make sure we don't continue to scan sources until we finish flushing.
1055 ++mScanSourcesGeneration;
Andreas Huber43c3e6c2011-01-05 12:17:08 -08001056 mScanSourcesPending = false;
Andreas Huber1aef2112011-01-04 14:01:29 -08001057
1058 (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
1059 mRenderer->flush(audio);
1060
1061 FlushStatus newStatus =
1062 needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
1063
1064 if (audio) {
1065 CHECK(mFlushingAudio == NONE
1066 || mFlushingAudio == AWAITING_DISCONTINUITY);
1067
1068 mFlushingAudio = newStatus;
1069
1070 if (mFlushingVideo == NONE) {
1071 mFlushingVideo = (mVideoDecoder != NULL)
1072 ? AWAITING_DISCONTINUITY
1073 : FLUSHED;
1074 }
1075 } else {
1076 CHECK(mFlushingVideo == NONE
1077 || mFlushingVideo == AWAITING_DISCONTINUITY);
1078
1079 mFlushingVideo = newStatus;
1080
1081 if (mFlushingAudio == NONE) {
1082 mFlushingAudio = (mAudioDecoder != NULL)
1083 ? AWAITING_DISCONTINUITY
1084 : FLUSHED;
1085 }
1086 }
1087}
1088
Andreas Huber84066782011-08-16 09:34:26 -07001089sp<AMessage> NuPlayer::Source::getFormat(bool audio) {
1090 sp<MetaData> meta = getFormatMeta(audio);
1091
1092 if (meta == NULL) {
1093 return NULL;
1094 }
1095
1096 sp<AMessage> msg = new AMessage;
1097
1098 if(convertMetaDataToMessage(meta, &msg) == OK) {
1099 return msg;
1100 }
1101 return NULL;
1102}
1103
James Dong53a2d132012-08-31 12:18:27 -07001104status_t NuPlayer::setVideoScalingMode(int32_t mode) {
1105 mVideoScalingMode = mode;
Andreas Huber1a447be2012-12-03 11:18:00 -08001106 if (mNativeWindow != NULL) {
James Dong53a2d132012-08-31 12:18:27 -07001107 status_t ret = native_window_set_scaling_mode(
1108 mNativeWindow->getNativeWindow().get(), mVideoScalingMode);
1109 if (ret != OK) {
1110 ALOGE("Failed to set scaling mode (%d): %s",
1111 -ret, strerror(-ret));
1112 return ret;
1113 }
1114 }
1115 return OK;
1116}
1117
Andreas Hubera4c5bc02012-11-27 15:02:53 -08001118void NuPlayer::schedulePollDuration() {
1119 sp<AMessage> msg = new AMessage(kWhatPollDuration, id());
1120 msg->setInt32("generation", mPollDurationGeneration);
1121 msg->post();
1122}
1123
1124void NuPlayer::cancelPollDuration() {
1125 ++mPollDurationGeneration;
1126}
1127
Andreas Huber457ec422012-11-30 10:53:22 -08001128void NuPlayer::processDeferredActions() {
1129 while (!mDeferredActions.empty()) {
1130 // We won't execute any deferred actions until we're no longer in
1131 // an intermediate state, i.e. one more more decoders are currently
1132 // flushing or shutting down.
1133
1134 if (mRenderer != NULL) {
1135 // There's an edge case where the renderer owns all output
1136 // buffers and is paused, therefore the decoder will not read
1137 // more input data and will never encounter the matching
1138 // discontinuity. To avoid this, we resume the renderer.
1139
1140 if (mFlushingAudio == AWAITING_DISCONTINUITY
1141 || mFlushingVideo == AWAITING_DISCONTINUITY) {
1142 mRenderer->resume();
1143 }
1144 }
1145
1146 if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
1147 // We're currently flushing, postpone the reset until that's
1148 // completed.
1149
1150 ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d",
1151 mFlushingAudio, mFlushingVideo);
1152
1153 break;
1154 }
1155
1156 sp<Action> action = *mDeferredActions.begin();
1157 mDeferredActions.erase(mDeferredActions.begin());
1158
1159 action->execute(this);
1160 }
1161}
1162
1163void NuPlayer::performSeek(int64_t seekTimeUs) {
1164 ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)",
1165 seekTimeUs,
1166 seekTimeUs / 1E6);
1167
1168 mSource->seekTo(seekTimeUs);
1169
1170 if (mDriver != NULL) {
1171 sp<NuPlayerDriver> driver = mDriver.promote();
1172 if (driver != NULL) {
1173 driver->notifyPosition(seekTimeUs);
1174 driver->notifySeekComplete();
1175 }
1176 }
1177
1178 // everything's flushed, continue playback.
1179}
1180
1181void NuPlayer::performDecoderFlush() {
1182 ALOGV("performDecoderFlush");
1183
Andreas Huberca6867f2013-04-16 10:54:03 -07001184 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
Andreas Huber457ec422012-11-30 10:53:22 -08001185 return;
1186 }
1187
1188 mTimeDiscontinuityPending = true;
1189
1190 if (mAudioDecoder != NULL) {
1191 flushDecoder(true /* audio */, false /* needShutdown */);
1192 }
1193
1194 if (mVideoDecoder != NULL) {
1195 flushDecoder(false /* audio */, false /* needShutdown */);
1196 }
1197}
1198
1199void NuPlayer::performDecoderShutdown() {
1200 ALOGV("performDecoderShutdown");
1201
Andreas Huberca6867f2013-04-16 10:54:03 -07001202 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
Andreas Huber457ec422012-11-30 10:53:22 -08001203 return;
1204 }
1205
1206 mTimeDiscontinuityPending = true;
1207
1208 if (mAudioDecoder != NULL) {
1209 flushDecoder(true /* audio */, true /* needShutdown */);
1210 }
1211
1212 if (mVideoDecoder != NULL) {
1213 flushDecoder(false /* audio */, true /* needShutdown */);
1214 }
1215}
1216
1217void NuPlayer::performReset() {
1218 ALOGV("performReset");
1219
1220 CHECK(mAudioDecoder == NULL);
1221 CHECK(mVideoDecoder == NULL);
1222
1223 cancelPollDuration();
1224
1225 ++mScanSourcesGeneration;
1226 mScanSourcesPending = false;
1227
1228 mRenderer.clear();
1229
1230 if (mSource != NULL) {
1231 mSource->stop();
Andreas Huber5ab368a2013-02-05 10:14:26 -08001232
1233 looper()->unregisterHandler(mSource->id());
1234
Andreas Huber457ec422012-11-30 10:53:22 -08001235 mSource.clear();
1236 }
1237
1238 if (mDriver != NULL) {
1239 sp<NuPlayerDriver> driver = mDriver.promote();
1240 if (driver != NULL) {
1241 driver->notifyResetComplete();
1242 }
1243 }
Andreas Huber1a447be2012-12-03 11:18:00 -08001244
1245 mStarted = false;
Andreas Huber457ec422012-11-30 10:53:22 -08001246}
1247
1248void NuPlayer::performScanSources() {
1249 ALOGV("performScanSources");
1250
Andreas Huber1a447be2012-12-03 11:18:00 -08001251 if (!mStarted) {
1252 return;
1253 }
1254
Andreas Huber457ec422012-11-30 10:53:22 -08001255 if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
1256 postScanSources();
1257 }
1258}
1259
Andreas Huber1a447be2012-12-03 11:18:00 -08001260void NuPlayer::performSetSurface(const sp<NativeWindowWrapper> &wrapper) {
1261 ALOGV("performSetSurface");
1262
1263 mNativeWindow = wrapper;
1264
1265 // XXX - ignore error from setVideoScalingMode for now
1266 setVideoScalingMode(mVideoScalingMode);
1267
1268 if (mDriver != NULL) {
1269 sp<NuPlayerDriver> driver = mDriver.promote();
1270 if (driver != NULL) {
1271 driver->notifySetSurfaceComplete();
1272 }
1273 }
1274}
1275
Andreas Huber57cea552013-02-05 13:59:56 -08001276void NuPlayer::onSourceNotify(const sp<AMessage> &msg) {
1277 int32_t what;
1278 CHECK(msg->findInt32("what", &what));
1279
1280 switch (what) {
1281 case Source::kWhatPrepared:
1282 {
Andreas Huber5a750132013-04-25 15:11:19 -07001283 if (mSource == NULL) {
1284 // This is a stale notification from a source that was
1285 // asynchronously preparing when the client called reset().
1286 // We handled the reset, the source is gone.
1287 break;
1288 }
1289
Andreas Huber7f475c32013-02-05 14:47:13 -08001290 int32_t err;
1291 CHECK(msg->findInt32("err", &err));
1292
Andreas Huber57cea552013-02-05 13:59:56 -08001293 sp<NuPlayerDriver> driver = mDriver.promote();
1294 if (driver != NULL) {
Andreas Huber7f475c32013-02-05 14:47:13 -08001295 driver->notifyPrepareCompleted(err);
Andreas Huber57cea552013-02-05 13:59:56 -08001296 }
Andreas Huber7069bdf2013-04-01 14:28:31 -07001297
1298 int64_t durationUs;
1299 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
1300 sp<NuPlayerDriver> driver = mDriver.promote();
1301 if (driver != NULL) {
1302 driver->notifyDuration(durationUs);
1303 }
1304 }
Andreas Huber57cea552013-02-05 13:59:56 -08001305 break;
1306 }
1307
1308 case Source::kWhatFlagsChanged:
1309 {
1310 uint32_t flags;
1311 CHECK(msg->findInt32("flags", (int32_t *)&flags));
1312
1313 if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
1314 && (!(flags & Source::FLAG_DYNAMIC_DURATION))) {
1315 cancelPollDuration();
1316 } else if (!(mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
1317 && (flags & Source::FLAG_DYNAMIC_DURATION)
1318 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
1319 schedulePollDuration();
1320 }
1321
1322 mSourceFlags = flags;
1323 break;
1324 }
1325
1326 case Source::kWhatVideoSizeChanged:
1327 {
1328 int32_t width, height;
1329 CHECK(msg->findInt32("width", &width));
1330 CHECK(msg->findInt32("height", &height));
1331
1332 notifyListener(MEDIA_SET_VIDEO_SIZE, width, height);
1333 break;
1334 }
1335
Roger Jönssoncfc30832013-01-21 16:26:41 +01001336 case Source::kWhatBufferingStart:
1337 {
1338 notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0);
1339 break;
1340 }
1341
1342 case Source::kWhatBufferingEnd:
1343 {
1344 notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0);
1345 break;
1346 }
1347
Andreas Huber57cea552013-02-05 13:59:56 -08001348 default:
1349 TRESPASS();
1350 }
1351}
1352
Andreas Huber5ab368a2013-02-05 10:14:26 -08001353////////////////////////////////////////////////////////////////////////////////
1354
Andreas Huber57cea552013-02-05 13:59:56 -08001355void NuPlayer::Source::notifyFlagsChanged(uint32_t flags) {
1356 sp<AMessage> notify = dupNotify();
1357 notify->setInt32("what", kWhatFlagsChanged);
1358 notify->setInt32("flags", flags);
1359 notify->post();
1360}
1361
1362void NuPlayer::Source::notifyVideoSizeChanged(int32_t width, int32_t height) {
1363 sp<AMessage> notify = dupNotify();
1364 notify->setInt32("what", kWhatVideoSizeChanged);
1365 notify->setInt32("width", width);
1366 notify->setInt32("height", height);
1367 notify->post();
1368}
1369
Andreas Huber7f475c32013-02-05 14:47:13 -08001370void NuPlayer::Source::notifyPrepared(status_t err) {
Andreas Huber57cea552013-02-05 13:59:56 -08001371 sp<AMessage> notify = dupNotify();
1372 notify->setInt32("what", kWhatPrepared);
Andreas Huber7f475c32013-02-05 14:47:13 -08001373 notify->setInt32("err", err);
Andreas Huber57cea552013-02-05 13:59:56 -08001374 notify->post();
1375}
1376
Andreas Huber5ab368a2013-02-05 10:14:26 -08001377void NuPlayer::Source::onMessageReceived(const sp<AMessage> &msg) {
1378 TRESPASS();
1379}
1380
Andreas Huberf9334412010-12-15 15:17:42 -08001381} // namespace android