blob: f9c328332084621495d35c9d00a556209bf4a394 [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>
Glenn Kasten11731182011-02-08 17:26:17 -080044#include <gui/ISurfaceTexture.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 Huber3fe62152011-09-16 15:09:22 -0700115 mVideoIsAVC(false),
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700116 mAudioEOS(false),
Andreas Huberf9334412010-12-15 15:17:42 -0800117 mVideoEOS(false),
Andreas Huber5bc087c2010-12-23 10:27:40 -0800118 mScanSourcesPending(false),
Andreas Huber1aef2112011-01-04 14:01:29 -0800119 mScanSourcesGeneration(0),
Andreas Huberb7c8e912012-11-27 15:02:53 -0800120 mPollDurationGeneration(0),
Andreas Huber6e3d3112011-11-28 12:36:11 -0800121 mTimeDiscontinuityPending(false),
Andreas Huberf9334412010-12-15 15:17:42 -0800122 mFlushingAudio(NONE),
Andreas Huber1aef2112011-01-04 14:01:29 -0800123 mFlushingVideo(NONE),
Andreas Huber3fe62152011-09-16 15:09:22 -0700124 mSkipRenderingAudioUntilMediaTimeUs(-1ll),
125 mSkipRenderingVideoUntilMediaTimeUs(-1ll),
126 mVideoLateByUs(0ll),
127 mNumFramesTotal(0ll),
James Dong0d268a32012-08-31 12:18:27 -0700128 mNumFramesDropped(0ll),
Andreas Huber57a339c2012-12-03 11:18:00 -0800129 mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
130 mStarted(false) {
Andreas Huberf9334412010-12-15 15:17:42 -0800131}
132
133NuPlayer::~NuPlayer() {
134}
135
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700136void NuPlayer::setUID(uid_t uid) {
137 mUIDValid = true;
138 mUID = uid;
139}
140
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800141void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
142 mDriver = driver;
Andreas Huberf9334412010-12-15 15:17:42 -0800143}
144
145void NuPlayer::setDataSource(const sp<IStreamSource> &source) {
146 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
147
Andreas Huber84066782011-08-16 09:34:26 -0700148 char prop[PROPERTY_VALUE_MAX];
149 if (property_get("media.stagefright.use-mp4source", prop, NULL)
150 && (!strcmp(prop, "1") || !strcasecmp(prop, "true"))) {
151 msg->setObject("source", new MP4Source(source));
152 } else {
153 msg->setObject("source", new StreamingSource(source));
154 }
155
Andreas Huber5bc087c2010-12-23 10:27:40 -0800156 msg->post();
157}
Andreas Huberf9334412010-12-15 15:17:42 -0800158
Andreas Huberafed0e12011-09-20 15:39:58 -0700159static bool IsHTTPLiveURL(const char *url) {
160 if (!strncasecmp("http://", url, 7)
161 || !strncasecmp("https://", url, 8)) {
162 size_t len = strlen(url);
163 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
164 return true;
165 }
166
167 if (strstr(url,"m3u8")) {
168 return true;
169 }
170 }
171
172 return false;
173}
174
Andreas Huber5bc087c2010-12-23 10:27:40 -0800175void NuPlayer::setDataSource(
176 const char *url, const KeyedVector<String8, String8> *headers) {
177 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
178
Andreas Huberafed0e12011-09-20 15:39:58 -0700179 sp<Source> source;
180 if (IsHTTPLiveURL(url)) {
181 source = new HTTPLiveSource(url, headers, mUIDValid, mUID);
182 } else if (!strncasecmp(url, "rtsp://", 7)) {
183 source = new RTSPSource(url, headers, mUIDValid, mUID);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700184 } else {
Andreas Huberafed0e12011-09-20 15:39:58 -0700185 source = new GenericSource(url, headers, mUIDValid, mUID);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700186 }
187
Andreas Huberafed0e12011-09-20 15:39:58 -0700188 msg->setObject("source", source);
189 msg->post();
190}
191
192void NuPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
193 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
194
195 sp<Source> source = new GenericSource(fd, offset, length);
196 msg->setObject("source", source);
Andreas Huberf9334412010-12-15 15:17:42 -0800197 msg->post();
198}
199
Andreas Huber57a339c2012-12-03 11:18:00 -0800200void NuPlayer::setVideoSurfaceTextureAsync(
201 const sp<ISurfaceTexture> &surfaceTexture) {
Glenn Kasten11731182011-02-08 17:26:17 -0800202 sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
Andreas Huber57a339c2012-12-03 11:18:00 -0800203
204 if (surfaceTexture == NULL) {
205 msg->setObject("native-window", NULL);
206 } else {
207 msg->setObject(
208 "native-window",
209 new NativeWindowWrapper(
210 new SurfaceTextureClient(surfaceTexture)));
211 }
212
Andreas Huberf9334412010-12-15 15:17:42 -0800213 msg->post();
214}
215
216void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) {
217 sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id());
218 msg->setObject("sink", sink);
219 msg->post();
220}
221
222void NuPlayer::start() {
223 (new AMessage(kWhatStart, id()))->post();
224}
225
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800226void NuPlayer::pause() {
Andreas Huberb4082222011-01-20 15:23:04 -0800227 (new AMessage(kWhatPause, id()))->post();
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800228}
229
230void NuPlayer::resume() {
Andreas Huberb4082222011-01-20 15:23:04 -0800231 (new AMessage(kWhatResume, id()))->post();
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800232}
233
Andreas Huber1aef2112011-01-04 14:01:29 -0800234void NuPlayer::resetAsync() {
235 (new AMessage(kWhatReset, id()))->post();
236}
237
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800238void NuPlayer::seekToAsync(int64_t seekTimeUs) {
239 sp<AMessage> msg = new AMessage(kWhatSeek, id());
240 msg->setInt64("seekTimeUs", seekTimeUs);
241 msg->post();
242}
243
Andreas Huber53df1a42010-12-22 10:03:04 -0800244// static
Andreas Huber1aef2112011-01-04 14:01:29 -0800245bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
Andreas Huber53df1a42010-12-22 10:03:04 -0800246 switch (state) {
247 case FLUSHING_DECODER:
Andreas Huber1aef2112011-01-04 14:01:29 -0800248 if (needShutdown != NULL) {
249 *needShutdown = false;
Andreas Huber53df1a42010-12-22 10:03:04 -0800250 }
251 return true;
252
Andreas Huber1aef2112011-01-04 14:01:29 -0800253 case FLUSHING_DECODER_SHUTDOWN:
254 if (needShutdown != NULL) {
255 *needShutdown = true;
Andreas Huber53df1a42010-12-22 10:03:04 -0800256 }
257 return true;
258
259 default:
260 return false;
261 }
262}
263
Andreas Huberf9334412010-12-15 15:17:42 -0800264void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
265 switch (msg->what()) {
266 case kWhatSetDataSource:
267 {
Steve Block3856b092011-10-20 11:56:00 +0100268 ALOGV("kWhatSetDataSource");
Andreas Huberf9334412010-12-15 15:17:42 -0800269
270 CHECK(mSource == NULL);
271
Andreas Huber5bc087c2010-12-23 10:27:40 -0800272 sp<RefBase> obj;
273 CHECK(msg->findObject("source", &obj));
Andreas Huberf9334412010-12-15 15:17:42 -0800274
Andreas Huber5bc087c2010-12-23 10:27:40 -0800275 mSource = static_cast<Source *>(obj.get());
Andreas Huberf9334412010-12-15 15:17:42 -0800276 break;
277 }
278
Andreas Huberb7c8e912012-11-27 15:02:53 -0800279 case kWhatPollDuration:
280 {
281 int32_t generation;
282 CHECK(msg->findInt32("generation", &generation));
283
284 if (generation != mPollDurationGeneration) {
285 // stale
286 break;
287 }
288
289 int64_t durationUs;
290 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
291 sp<NuPlayerDriver> driver = mDriver.promote();
292 if (driver != NULL) {
293 driver->notifyDuration(durationUs);
294 }
295 }
296
297 msg->post(1000000ll); // poll again in a second.
298 break;
299 }
300
Glenn Kasten11731182011-02-08 17:26:17 -0800301 case kWhatSetVideoNativeWindow:
Andreas Huberf9334412010-12-15 15:17:42 -0800302 {
Steve Block3856b092011-10-20 11:56:00 +0100303 ALOGV("kWhatSetVideoNativeWindow");
Andreas Huberf9334412010-12-15 15:17:42 -0800304
Andreas Huber57a339c2012-12-03 11:18:00 -0800305 mDeferredActions.push_back(
306 new SimpleAction(&NuPlayer::performDecoderShutdown));
307
Andreas Huberf9334412010-12-15 15:17:42 -0800308 sp<RefBase> obj;
Glenn Kasten11731182011-02-08 17:26:17 -0800309 CHECK(msg->findObject("native-window", &obj));
Andreas Huberf9334412010-12-15 15:17:42 -0800310
Andreas Huber57a339c2012-12-03 11:18:00 -0800311 mDeferredActions.push_back(
312 new SetSurfaceAction(
313 static_cast<NativeWindowWrapper *>(obj.get())));
James Dong0d268a32012-08-31 12:18:27 -0700314
Andreas Huber57a339c2012-12-03 11:18:00 -0800315 if (obj != NULL) {
316 // If there is a new surface texture, instantiate decoders
317 // again if possible.
318 mDeferredActions.push_back(
319 new SimpleAction(&NuPlayer::performScanSources));
320 }
321
322 processDeferredActions();
Andreas Huberf9334412010-12-15 15:17:42 -0800323 break;
324 }
325
326 case kWhatSetAudioSink:
327 {
Steve Block3856b092011-10-20 11:56:00 +0100328 ALOGV("kWhatSetAudioSink");
Andreas Huberf9334412010-12-15 15:17:42 -0800329
330 sp<RefBase> obj;
331 CHECK(msg->findObject("sink", &obj));
332
333 mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get());
334 break;
335 }
336
337 case kWhatStart:
338 {
Steve Block3856b092011-10-20 11:56:00 +0100339 ALOGV("kWhatStart");
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800340
Andreas Huber3fe62152011-09-16 15:09:22 -0700341 mVideoIsAVC = false;
Andreas Huber1aef2112011-01-04 14:01:29 -0800342 mAudioEOS = false;
343 mVideoEOS = false;
Andreas Huber32f3cef2011-03-02 15:34:46 -0800344 mSkipRenderingAudioUntilMediaTimeUs = -1;
345 mSkipRenderingVideoUntilMediaTimeUs = -1;
Andreas Huber3fe62152011-09-16 15:09:22 -0700346 mVideoLateByUs = 0;
347 mNumFramesTotal = 0;
348 mNumFramesDropped = 0;
Andreas Huber57a339c2012-12-03 11:18:00 -0800349 mStarted = true;
Andreas Huber1aef2112011-01-04 14:01:29 -0800350
Andreas Huber5bc087c2010-12-23 10:27:40 -0800351 mSource->start();
Andreas Huberf9334412010-12-15 15:17:42 -0800352
353 mRenderer = new Renderer(
354 mAudioSink,
355 new AMessage(kWhatRendererNotify, id()));
356
357 looper()->registerHandler(mRenderer);
358
Andreas Huber1aef2112011-01-04 14:01:29 -0800359 postScanSources();
Andreas Huberf9334412010-12-15 15:17:42 -0800360 break;
361 }
362
363 case kWhatScanSources:
364 {
Andreas Huber1aef2112011-01-04 14:01:29 -0800365 int32_t generation;
366 CHECK(msg->findInt32("generation", &generation));
367 if (generation != mScanSourcesGeneration) {
368 // Drop obsolete msg.
369 break;
370 }
371
Andreas Huber5bc087c2010-12-23 10:27:40 -0800372 mScanSourcesPending = false;
373
Steve Block3856b092011-10-20 11:56:00 +0100374 ALOGV("scanning sources haveAudio=%d, haveVideo=%d",
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800375 mAudioDecoder != NULL, mVideoDecoder != NULL);
376
Andreas Huberb7c8e912012-11-27 15:02:53 -0800377 bool mHadAnySourcesBefore =
378 (mAudioDecoder != NULL) || (mVideoDecoder != NULL);
379
Haynes Mathew George5d246ef2012-07-09 10:36:57 -0700380 if (mNativeWindow != NULL) {
381 instantiateDecoder(false, &mVideoDecoder);
382 }
Andreas Huberf9334412010-12-15 15:17:42 -0800383
384 if (mAudioSink != NULL) {
Andreas Huber5bc087c2010-12-23 10:27:40 -0800385 instantiateDecoder(true, &mAudioDecoder);
Andreas Huberf9334412010-12-15 15:17:42 -0800386 }
387
Andreas Huberb7c8e912012-11-27 15:02:53 -0800388 if (!mHadAnySourcesBefore
389 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
390 // This is the first time we've found anything playable.
391
392 uint32_t flags = mSource->flags();
393
394 if (flags & Source::FLAG_DYNAMIC_DURATION) {
395 schedulePollDuration();
396 }
397 }
398
Andreas Hubereac68ba2011-09-27 12:12:25 -0700399 status_t err;
400 if ((err = mSource->feedMoreTSData()) != OK) {
Andreas Huber1aef2112011-01-04 14:01:29 -0800401 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
402 // We're not currently decoding anything (no audio or
403 // video tracks found) and we just ran out of input data.
Andreas Hubereac68ba2011-09-27 12:12:25 -0700404
405 if (err == ERROR_END_OF_STREAM) {
406 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
407 } else {
408 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
409 }
Andreas Huber1aef2112011-01-04 14:01:29 -0800410 }
Andreas Huberf9334412010-12-15 15:17:42 -0800411 break;
412 }
413
Andreas Huberfbe9d812012-08-31 14:05:27 -0700414 if ((mAudioDecoder == NULL && mAudioSink != NULL)
415 || (mVideoDecoder == NULL && mNativeWindow != NULL)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800416 msg->post(100000ll);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800417 mScanSourcesPending = true;
Andreas Huberf9334412010-12-15 15:17:42 -0800418 }
419 break;
420 }
421
422 case kWhatVideoNotify:
423 case kWhatAudioNotify:
424 {
425 bool audio = msg->what() == kWhatAudioNotify;
426
427 sp<AMessage> codecRequest;
428 CHECK(msg->findMessage("codec-request", &codecRequest));
429
430 int32_t what;
431 CHECK(codecRequest->findInt32("what", &what));
432
433 if (what == ACodec::kWhatFillThisBuffer) {
434 status_t err = feedDecoderInputData(
435 audio, codecRequest);
436
Andreas Huber5bc087c2010-12-23 10:27:40 -0800437 if (err == -EWOULDBLOCK) {
Andreas Hubereac68ba2011-09-27 12:12:25 -0700438 if (mSource->feedMoreTSData() == OK) {
Andreas Huber1183a4a2011-11-03 11:00:21 -0700439 msg->post(10000ll);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800440 }
Andreas Huberf9334412010-12-15 15:17:42 -0800441 }
442 } else if (what == ACodec::kWhatEOS) {
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700443 int32_t err;
444 CHECK(codecRequest->findInt32("err", &err));
445
446 if (err == ERROR_END_OF_STREAM) {
Steve Block3856b092011-10-20 11:56:00 +0100447 ALOGV("got %s decoder EOS", audio ? "audio" : "video");
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700448 } else {
Steve Block3856b092011-10-20 11:56:00 +0100449 ALOGV("got %s decoder EOS w/ error %d",
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700450 audio ? "audio" : "video",
451 err);
452 }
453
454 mRenderer->queueEOS(audio, err);
Andreas Huberf9334412010-12-15 15:17:42 -0800455 } else if (what == ACodec::kWhatFlushCompleted) {
Andreas Huber1aef2112011-01-04 14:01:29 -0800456 bool needShutdown;
Andreas Huber53df1a42010-12-22 10:03:04 -0800457
Andreas Huberf9334412010-12-15 15:17:42 -0800458 if (audio) {
Andreas Huber1aef2112011-01-04 14:01:29 -0800459 CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
Andreas Huberf9334412010-12-15 15:17:42 -0800460 mFlushingAudio = FLUSHED;
461 } else {
Andreas Huber1aef2112011-01-04 14:01:29 -0800462 CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
Andreas Huberf9334412010-12-15 15:17:42 -0800463 mFlushingVideo = FLUSHED;
Andreas Huber3fe62152011-09-16 15:09:22 -0700464
465 mVideoLateByUs = 0;
Andreas Huberf9334412010-12-15 15:17:42 -0800466 }
467
Steve Block3856b092011-10-20 11:56:00 +0100468 ALOGV("decoder %s flush completed", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800469
Andreas Huber1aef2112011-01-04 14:01:29 -0800470 if (needShutdown) {
Steve Block3856b092011-10-20 11:56:00 +0100471 ALOGV("initiating %s decoder shutdown",
Andreas Huber53df1a42010-12-22 10:03:04 -0800472 audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800473
Andreas Huber53df1a42010-12-22 10:03:04 -0800474 (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
Andreas Huberf9334412010-12-15 15:17:42 -0800475
Andreas Huber53df1a42010-12-22 10:03:04 -0800476 if (audio) {
477 mFlushingAudio = SHUTTING_DOWN_DECODER;
478 } else {
479 mFlushingVideo = SHUTTING_DOWN_DECODER;
480 }
Andreas Huberf9334412010-12-15 15:17:42 -0800481 }
Andreas Huber3831a062010-12-21 10:22:33 -0800482
483 finishFlushIfPossible();
Andreas Huber2c2814b2010-12-15 17:18:20 -0800484 } else if (what == ACodec::kWhatOutputFormatChanged) {
Andreas Huber31e25082011-01-10 10:38:31 -0800485 if (audio) {
486 int32_t numChannels;
487 CHECK(codecRequest->findInt32("channel-count", &numChannels));
Andreas Huber2c2814b2010-12-15 17:18:20 -0800488
Andreas Huber31e25082011-01-10 10:38:31 -0800489 int32_t sampleRate;
490 CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
Andreas Huber2c2814b2010-12-15 17:18:20 -0800491
Steve Block3856b092011-10-20 11:56:00 +0100492 ALOGV("Audio output format changed to %d Hz, %d channels",
Andreas Huber31e25082011-01-10 10:38:31 -0800493 sampleRate, numChannels);
Andreas Huber2c2814b2010-12-15 17:18:20 -0800494
Andreas Huber31e25082011-01-10 10:38:31 -0800495 mAudioSink->close();
Eric Laurent1948eb32012-04-13 16:50:19 -0700496
497 audio_output_flags_t flags;
498 int64_t durationUs;
499 // FIXME: we should handle the case where the video decoder is created after
500 // we receive the format change indication. Current code will just make that
501 // we select deep buffer with video which should not be a problem as it should
502 // not prevent from keeping A/V sync.
503 if (mVideoDecoder == NULL &&
504 mSource->getDuration(&durationUs) == OK &&
505 durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
506 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
507 } else {
508 flags = AUDIO_OUTPUT_FLAG_NONE;
509 }
510
Andreas Huber98065552012-05-03 11:33:01 -0700511 int32_t channelMask;
512 if (!codecRequest->findInt32("channel-mask", &channelMask)) {
513 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
514 }
515
Andreas Huber078cfcf2011-09-15 12:25:04 -0700516 CHECK_EQ(mAudioSink->open(
517 sampleRate,
518 numChannels,
Andreas Huber98065552012-05-03 11:33:01 -0700519 (audio_channel_mask_t)channelMask,
Andreas Huber078cfcf2011-09-15 12:25:04 -0700520 AUDIO_FORMAT_PCM_16_BIT,
Eric Laurent1948eb32012-04-13 16:50:19 -0700521 8 /* bufferCount */,
522 NULL,
523 NULL,
524 flags),
Andreas Huber078cfcf2011-09-15 12:25:04 -0700525 (status_t)OK);
Andreas Huber31e25082011-01-10 10:38:31 -0800526 mAudioSink->start();
Andreas Huber2c2814b2010-12-15 17:18:20 -0800527
Andreas Huber31e25082011-01-10 10:38:31 -0800528 mRenderer->signalAudioSinkChanged();
529 } else {
530 // video
Andreas Huber3831a062010-12-21 10:22:33 -0800531
Andreas Huber31e25082011-01-10 10:38:31 -0800532 int32_t width, height;
533 CHECK(codecRequest->findInt32("width", &width));
534 CHECK(codecRequest->findInt32("height", &height));
535
536 int32_t cropLeft, cropTop, cropRight, cropBottom;
537 CHECK(codecRequest->findRect(
538 "crop",
539 &cropLeft, &cropTop, &cropRight, &cropBottom));
540
Steve Block3856b092011-10-20 11:56:00 +0100541 ALOGV("Video output format changed to %d x %d "
Andreas Hubercb67cd12011-08-26 16:02:19 -0700542 "(crop: %d x %d @ (%d, %d))",
Andreas Huber31e25082011-01-10 10:38:31 -0800543 width, height,
Andreas Hubercb67cd12011-08-26 16:02:19 -0700544 (cropRight - cropLeft + 1),
545 (cropBottom - cropTop + 1),
546 cropLeft, cropTop);
Andreas Huber31e25082011-01-10 10:38:31 -0800547
548 notifyListener(
549 MEDIA_SET_VIDEO_SIZE,
550 cropRight - cropLeft + 1,
551 cropBottom - cropTop + 1);
552 }
Andreas Huber3831a062010-12-21 10:22:33 -0800553 } else if (what == ACodec::kWhatShutdownCompleted) {
Steve Block3856b092011-10-20 11:56:00 +0100554 ALOGV("%s shutdown completed", audio ? "audio" : "video");
Andreas Huber3831a062010-12-21 10:22:33 -0800555 if (audio) {
556 mAudioDecoder.clear();
557
558 CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
559 mFlushingAudio = SHUT_DOWN;
560 } else {
561 mVideoDecoder.clear();
562
563 CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
564 mFlushingVideo = SHUT_DOWN;
565 }
566
567 finishFlushIfPossible();
Andreas Huberc92fd242011-08-16 13:48:44 -0700568 } else if (what == ACodec::kWhatError) {
Steve Block29357bc2012-01-06 19:20:56 +0000569 ALOGE("Received error from %s decoder, aborting playback.",
Andreas Huberc92fd242011-08-16 13:48:44 -0700570 audio ? "audio" : "video");
571
572 mRenderer->queueEOS(audio, UNKNOWN_ERROR);
Andreas Huber57788222012-02-21 11:47:18 -0800573 } else if (what == ACodec::kWhatDrainThisBuffer) {
Andreas Huberf9334412010-12-15 15:17:42 -0800574 renderBuffer(audio, codecRequest);
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800575 } else if (what != ACodec::kWhatComponentAllocated
576 && what != ACodec::kWhatComponentConfigured
577 && what != ACodec::kWhatBuffersAllocated) {
578 ALOGV("Unhandled codec notification %d '%c%c%c%c'.",
579 what,
580 what >> 24,
581 (what >> 16) & 0xff,
582 (what >> 8) & 0xff,
583 what & 0xff);
Andreas Huberf9334412010-12-15 15:17:42 -0800584 }
585
586 break;
587 }
588
589 case kWhatRendererNotify:
590 {
591 int32_t what;
592 CHECK(msg->findInt32("what", &what));
593
594 if (what == Renderer::kWhatEOS) {
595 int32_t audio;
596 CHECK(msg->findInt32("audio", &audio));
597
Andreas Huberc92fd242011-08-16 13:48:44 -0700598 int32_t finalResult;
599 CHECK(msg->findInt32("finalResult", &finalResult));
600
Andreas Huberf9334412010-12-15 15:17:42 -0800601 if (audio) {
602 mAudioEOS = true;
603 } else {
604 mVideoEOS = true;
605 }
606
Andreas Huberc92fd242011-08-16 13:48:44 -0700607 if (finalResult == ERROR_END_OF_STREAM) {
Steve Block3856b092011-10-20 11:56:00 +0100608 ALOGV("reached %s EOS", audio ? "audio" : "video");
Andreas Huberc92fd242011-08-16 13:48:44 -0700609 } else {
Steve Block29357bc2012-01-06 19:20:56 +0000610 ALOGE("%s track encountered an error (%d)",
Andreas Huberc92fd242011-08-16 13:48:44 -0700611 audio ? "audio" : "video", finalResult);
612
613 notifyListener(
614 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult);
615 }
Andreas Huberf9334412010-12-15 15:17:42 -0800616
617 if ((mAudioEOS || mAudioDecoder == NULL)
618 && (mVideoEOS || mVideoDecoder == NULL)) {
619 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
620 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800621 } else if (what == Renderer::kWhatPosition) {
622 int64_t positionUs;
623 CHECK(msg->findInt64("positionUs", &positionUs));
624
Andreas Huber3fe62152011-09-16 15:09:22 -0700625 CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs));
626
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800627 if (mDriver != NULL) {
628 sp<NuPlayerDriver> driver = mDriver.promote();
629 if (driver != NULL) {
630 driver->notifyPosition(positionUs);
Andreas Huber3fe62152011-09-16 15:09:22 -0700631
632 driver->notifyFrameStats(
633 mNumFramesTotal, mNumFramesDropped);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800634 }
635 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700636 } else if (what == Renderer::kWhatFlushComplete) {
Andreas Huberf9334412010-12-15 15:17:42 -0800637 int32_t audio;
638 CHECK(msg->findInt32("audio", &audio));
639
Steve Block3856b092011-10-20 11:56:00 +0100640 ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
James Dongf57b4ea2012-07-20 13:38:36 -0700641 } else if (what == Renderer::kWhatVideoRenderingStart) {
642 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
Andreas Huberf9334412010-12-15 15:17:42 -0800643 }
644 break;
645 }
646
647 case kWhatMoreDataQueued:
648 {
649 break;
650 }
651
Andreas Huber1aef2112011-01-04 14:01:29 -0800652 case kWhatReset:
653 {
Steve Block3856b092011-10-20 11:56:00 +0100654 ALOGV("kWhatReset");
Andreas Huber1aef2112011-01-04 14:01:29 -0800655
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800656 mDeferredActions.push_back(
657 new SimpleAction(&NuPlayer::performDecoderShutdown));
Andreas Huberb7c8e912012-11-27 15:02:53 -0800658
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800659 mDeferredActions.push_back(
660 new SimpleAction(&NuPlayer::performReset));
Andreas Huberb58ce9f2011-11-28 16:27:35 -0800661
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800662 processDeferredActions();
Andreas Huber1aef2112011-01-04 14:01:29 -0800663 break;
664 }
665
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800666 case kWhatSeek:
667 {
668 int64_t seekTimeUs;
669 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
670
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800671 ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800672
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800673 mDeferredActions.push_back(
674 new SimpleAction(&NuPlayer::performDecoderFlush));
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800675
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800676 mDeferredActions.push_back(new SeekAction(seekTimeUs));
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800677
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800678 processDeferredActions();
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800679 break;
680 }
681
Andreas Huberb4082222011-01-20 15:23:04 -0800682 case kWhatPause:
683 {
684 CHECK(mRenderer != NULL);
685 mRenderer->pause();
686 break;
687 }
688
689 case kWhatResume:
690 {
691 CHECK(mRenderer != NULL);
692 mRenderer->resume();
693 break;
694 }
695
Andreas Huberf9334412010-12-15 15:17:42 -0800696 default:
697 TRESPASS();
698 break;
699 }
700}
701
Andreas Huber3831a062010-12-21 10:22:33 -0800702void NuPlayer::finishFlushIfPossible() {
703 if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
704 return;
705 }
706
707 if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
708 return;
709 }
710
Steve Block3856b092011-10-20 11:56:00 +0100711 ALOGV("both audio and video are flushed now.");
Andreas Huber3831a062010-12-21 10:22:33 -0800712
Andreas Huber6e3d3112011-11-28 12:36:11 -0800713 if (mTimeDiscontinuityPending) {
714 mRenderer->signalTimeDiscontinuity();
715 mTimeDiscontinuityPending = false;
716 }
Andreas Huber3831a062010-12-21 10:22:33 -0800717
Andreas Huber22fc52f2011-01-05 16:24:27 -0800718 if (mAudioDecoder != NULL) {
Andreas Huber3831a062010-12-21 10:22:33 -0800719 mAudioDecoder->signalResume();
720 }
721
Andreas Huber22fc52f2011-01-05 16:24:27 -0800722 if (mVideoDecoder != NULL) {
Andreas Huber3831a062010-12-21 10:22:33 -0800723 mVideoDecoder->signalResume();
724 }
725
726 mFlushingAudio = NONE;
727 mFlushingVideo = NONE;
Andreas Huber3831a062010-12-21 10:22:33 -0800728
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800729 processDeferredActions();
Andreas Huber1aef2112011-01-04 14:01:29 -0800730}
731
732void NuPlayer::postScanSources() {
733 if (mScanSourcesPending) {
734 return;
735 }
736
737 sp<AMessage> msg = new AMessage(kWhatScanSources, id());
738 msg->setInt32("generation", mScanSourcesGeneration);
739 msg->post();
740
741 mScanSourcesPending = true;
742}
743
Andreas Huber5bc087c2010-12-23 10:27:40 -0800744status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
Andreas Huberf9334412010-12-15 15:17:42 -0800745 if (*decoder != NULL) {
746 return OK;
747 }
748
Andreas Huber84066782011-08-16 09:34:26 -0700749 sp<AMessage> format = mSource->getFormat(audio);
Andreas Huberf9334412010-12-15 15:17:42 -0800750
Andreas Huber84066782011-08-16 09:34:26 -0700751 if (format == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -0800752 return -EWOULDBLOCK;
753 }
754
Andreas Huber3fe62152011-09-16 15:09:22 -0700755 if (!audio) {
Andreas Huber84066782011-08-16 09:34:26 -0700756 AString mime;
757 CHECK(format->findString("mime", &mime));
758 mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
Andreas Huber3fe62152011-09-16 15:09:22 -0700759 }
760
Andreas Huberf9334412010-12-15 15:17:42 -0800761 sp<AMessage> notify =
762 new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
763 id());
764
Glenn Kasten11731182011-02-08 17:26:17 -0800765 *decoder = audio ? new Decoder(notify) :
766 new Decoder(notify, mNativeWindow);
Andreas Huberf9334412010-12-15 15:17:42 -0800767 looper()->registerHandler(*decoder);
768
Andreas Huber84066782011-08-16 09:34:26 -0700769 (*decoder)->configure(format);
Andreas Huberf9334412010-12-15 15:17:42 -0800770
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800771 int64_t durationUs;
772 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
773 sp<NuPlayerDriver> driver = mDriver.promote();
774 if (driver != NULL) {
775 driver->notifyDuration(durationUs);
776 }
777 }
778
Andreas Huberf9334412010-12-15 15:17:42 -0800779 return OK;
780}
781
782status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
783 sp<AMessage> reply;
784 CHECK(msg->findMessage("reply", &reply));
785
Andreas Huber53df1a42010-12-22 10:03:04 -0800786 if ((audio && IsFlushingState(mFlushingAudio))
787 || (!audio && IsFlushingState(mFlushingVideo))) {
Andreas Huberf9334412010-12-15 15:17:42 -0800788 reply->setInt32("err", INFO_DISCONTINUITY);
789 reply->post();
790 return OK;
791 }
792
793 sp<ABuffer> accessUnit;
Andreas Huberf9334412010-12-15 15:17:42 -0800794
Andreas Huber3fe62152011-09-16 15:09:22 -0700795 bool dropAccessUnit;
796 do {
797 status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800798
Andreas Huber3fe62152011-09-16 15:09:22 -0700799 if (err == -EWOULDBLOCK) {
800 return err;
801 } else if (err != OK) {
802 if (err == INFO_DISCONTINUITY) {
803 int32_t type;
804 CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
Andreas Huber53df1a42010-12-22 10:03:04 -0800805
Andreas Huber3fe62152011-09-16 15:09:22 -0700806 bool formatChange =
Andreas Huber6e3d3112011-11-28 12:36:11 -0800807 (audio &&
808 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
809 || (!audio &&
810 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
Andreas Huber53df1a42010-12-22 10:03:04 -0800811
Andreas Huber6e3d3112011-11-28 12:36:11 -0800812 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
813
Steve Blockdf64d152012-01-04 20:05:49 +0000814 ALOGI("%s discontinuity (formatChange=%d, time=%d)",
Andreas Huber6e3d3112011-11-28 12:36:11 -0800815 audio ? "audio" : "video", formatChange, timeChange);
Andreas Huber32f3cef2011-03-02 15:34:46 -0800816
Andreas Huber3fe62152011-09-16 15:09:22 -0700817 if (audio) {
818 mSkipRenderingAudioUntilMediaTimeUs = -1;
819 } else {
820 mSkipRenderingVideoUntilMediaTimeUs = -1;
821 }
Andreas Huber32f3cef2011-03-02 15:34:46 -0800822
Andreas Huber6e3d3112011-11-28 12:36:11 -0800823 if (timeChange) {
824 sp<AMessage> extra;
825 if (accessUnit->meta()->findMessage("extra", &extra)
826 && extra != NULL) {
827 int64_t resumeAtMediaTimeUs;
828 if (extra->findInt64(
829 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
Steve Blockdf64d152012-01-04 20:05:49 +0000830 ALOGI("suppressing rendering of %s until %lld us",
Andreas Huber6e3d3112011-11-28 12:36:11 -0800831 audio ? "audio" : "video", resumeAtMediaTimeUs);
Andreas Huber3fe62152011-09-16 15:09:22 -0700832
Andreas Huber6e3d3112011-11-28 12:36:11 -0800833 if (audio) {
834 mSkipRenderingAudioUntilMediaTimeUs =
835 resumeAtMediaTimeUs;
836 } else {
837 mSkipRenderingVideoUntilMediaTimeUs =
838 resumeAtMediaTimeUs;
839 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700840 }
Andreas Huber32f3cef2011-03-02 15:34:46 -0800841 }
842 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700843
Andreas Huber6e3d3112011-11-28 12:36:11 -0800844 mTimeDiscontinuityPending =
845 mTimeDiscontinuityPending || timeChange;
846
847 if (formatChange || timeChange) {
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800848 if (mFlushingAudio == NONE && mFlushingVideo == NONE) {
849 // And we'll resume scanning sources once we're done
850 // flushing.
851 mDeferredActions.push_front(
852 new SimpleAction(
853 &NuPlayer::performScanSources));
854 }
855
Andreas Huber6e3d3112011-11-28 12:36:11 -0800856 flushDecoder(audio, formatChange);
857 } else {
858 // This stream is unaffected by the discontinuity
859
860 if (audio) {
861 mFlushingAudio = FLUSHED;
862 } else {
863 mFlushingVideo = FLUSHED;
864 }
865
866 finishFlushIfPossible();
867
868 return -EWOULDBLOCK;
869 }
Andreas Huber32f3cef2011-03-02 15:34:46 -0800870 }
871
Andreas Huber3fe62152011-09-16 15:09:22 -0700872 reply->setInt32("err", err);
873 reply->post();
874 return OK;
Andreas Huberf9334412010-12-15 15:17:42 -0800875 }
876
Andreas Huber3fe62152011-09-16 15:09:22 -0700877 if (!audio) {
878 ++mNumFramesTotal;
879 }
880
881 dropAccessUnit = false;
882 if (!audio
883 && mVideoLateByUs > 100000ll
884 && mVideoIsAVC
885 && !IsAVCReferenceFrame(accessUnit)) {
886 dropAccessUnit = true;
887 ++mNumFramesDropped;
888 }
889 } while (dropAccessUnit);
Andreas Huberf9334412010-12-15 15:17:42 -0800890
Steve Block3856b092011-10-20 11:56:00 +0100891 // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800892
893#if 0
894 int64_t mediaTimeUs;
895 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
Steve Block3856b092011-10-20 11:56:00 +0100896 ALOGV("feeding %s input buffer at media time %.2f secs",
Andreas Huberf9334412010-12-15 15:17:42 -0800897 audio ? "audio" : "video",
898 mediaTimeUs / 1E6);
899#endif
900
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800901 reply->setBuffer("buffer", accessUnit);
Andreas Huberf9334412010-12-15 15:17:42 -0800902 reply->post();
903
904 return OK;
905}
906
907void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
Steve Block3856b092011-10-20 11:56:00 +0100908 // ALOGV("renderBuffer %s", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800909
910 sp<AMessage> reply;
911 CHECK(msg->findMessage("reply", &reply));
912
Andreas Huber18ac5402011-08-31 15:04:25 -0700913 if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) {
914 // We're currently attempting to flush the decoder, in order
915 // to complete this, the decoder wants all its buffers back,
916 // so we don't want any output buffers it sent us (from before
917 // we initiated the flush) to be stuck in the renderer's queue.
918
Steve Block3856b092011-10-20 11:56:00 +0100919 ALOGV("we're still flushing the %s decoder, sending its output buffer"
Andreas Huber18ac5402011-08-31 15:04:25 -0700920 " right back.", audio ? "audio" : "video");
921
922 reply->post();
923 return;
924 }
925
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800926 sp<ABuffer> buffer;
927 CHECK(msg->findBuffer("buffer", &buffer));
Andreas Huberf9334412010-12-15 15:17:42 -0800928
Andreas Huber32f3cef2011-03-02 15:34:46 -0800929 int64_t &skipUntilMediaTimeUs =
930 audio
931 ? mSkipRenderingAudioUntilMediaTimeUs
932 : mSkipRenderingVideoUntilMediaTimeUs;
933
934 if (skipUntilMediaTimeUs >= 0) {
935 int64_t mediaTimeUs;
936 CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs));
937
938 if (mediaTimeUs < skipUntilMediaTimeUs) {
Steve Block3856b092011-10-20 11:56:00 +0100939 ALOGV("dropping %s buffer at time %lld as requested.",
Andreas Huber32f3cef2011-03-02 15:34:46 -0800940 audio ? "audio" : "video",
941 mediaTimeUs);
942
943 reply->post();
944 return;
945 }
946
947 skipUntilMediaTimeUs = -1;
948 }
949
Andreas Huberf9334412010-12-15 15:17:42 -0800950 mRenderer->queueBuffer(audio, buffer, reply);
951}
952
953void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800954 if (mDriver == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -0800955 return;
956 }
957
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800958 sp<NuPlayerDriver> driver = mDriver.promote();
Andreas Huberf9334412010-12-15 15:17:42 -0800959
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800960 if (driver == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -0800961 return;
962 }
963
Andreas Hubera4af2142011-10-26 15:23:31 -0700964 driver->notifyListener(msg, ext1, ext2);
Andreas Huberf9334412010-12-15 15:17:42 -0800965}
966
Andreas Huber1aef2112011-01-04 14:01:29 -0800967void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
Andreas Huber6e3d3112011-11-28 12:36:11 -0800968 if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
Steve Blockdf64d152012-01-04 20:05:49 +0000969 ALOGI("flushDecoder %s without decoder present",
Andreas Huber6e3d3112011-11-28 12:36:11 -0800970 audio ? "audio" : "video");
971 }
972
Andreas Huber1aef2112011-01-04 14:01:29 -0800973 // Make sure we don't continue to scan sources until we finish flushing.
974 ++mScanSourcesGeneration;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800975 mScanSourcesPending = false;
Andreas Huber1aef2112011-01-04 14:01:29 -0800976
977 (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
978 mRenderer->flush(audio);
979
980 FlushStatus newStatus =
981 needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
982
983 if (audio) {
984 CHECK(mFlushingAudio == NONE
985 || mFlushingAudio == AWAITING_DISCONTINUITY);
986
987 mFlushingAudio = newStatus;
988
989 if (mFlushingVideo == NONE) {
990 mFlushingVideo = (mVideoDecoder != NULL)
991 ? AWAITING_DISCONTINUITY
992 : FLUSHED;
993 }
994 } else {
995 CHECK(mFlushingVideo == NONE
996 || mFlushingVideo == AWAITING_DISCONTINUITY);
997
998 mFlushingVideo = newStatus;
999
1000 if (mFlushingAudio == NONE) {
1001 mFlushingAudio = (mAudioDecoder != NULL)
1002 ? AWAITING_DISCONTINUITY
1003 : FLUSHED;
1004 }
1005 }
1006}
1007
Andreas Huber84066782011-08-16 09:34:26 -07001008sp<AMessage> NuPlayer::Source::getFormat(bool audio) {
1009 sp<MetaData> meta = getFormatMeta(audio);
1010
1011 if (meta == NULL) {
1012 return NULL;
1013 }
1014
1015 sp<AMessage> msg = new AMessage;
1016
1017 if(convertMetaDataToMessage(meta, &msg) == OK) {
1018 return msg;
1019 }
1020 return NULL;
1021}
1022
James Dong0d268a32012-08-31 12:18:27 -07001023status_t NuPlayer::setVideoScalingMode(int32_t mode) {
1024 mVideoScalingMode = mode;
Andreas Huber57a339c2012-12-03 11:18:00 -08001025 if (mNativeWindow != NULL) {
James Dong0d268a32012-08-31 12:18:27 -07001026 status_t ret = native_window_set_scaling_mode(
1027 mNativeWindow->getNativeWindow().get(), mVideoScalingMode);
1028 if (ret != OK) {
1029 ALOGE("Failed to set scaling mode (%d): %s",
1030 -ret, strerror(-ret));
1031 return ret;
1032 }
1033 }
1034 return OK;
1035}
1036
Andreas Huberb7c8e912012-11-27 15:02:53 -08001037void NuPlayer::schedulePollDuration() {
1038 sp<AMessage> msg = new AMessage(kWhatPollDuration, id());
1039 msg->setInt32("generation", mPollDurationGeneration);
1040 msg->post();
1041}
1042
1043void NuPlayer::cancelPollDuration() {
1044 ++mPollDurationGeneration;
1045}
1046
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001047void NuPlayer::processDeferredActions() {
1048 while (!mDeferredActions.empty()) {
1049 // We won't execute any deferred actions until we're no longer in
1050 // an intermediate state, i.e. one more more decoders are currently
1051 // flushing or shutting down.
1052
1053 if (mRenderer != NULL) {
1054 // There's an edge case where the renderer owns all output
1055 // buffers and is paused, therefore the decoder will not read
1056 // more input data and will never encounter the matching
1057 // discontinuity. To avoid this, we resume the renderer.
1058
1059 if (mFlushingAudio == AWAITING_DISCONTINUITY
1060 || mFlushingVideo == AWAITING_DISCONTINUITY) {
1061 mRenderer->resume();
1062 }
1063 }
1064
1065 if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
1066 // We're currently flushing, postpone the reset until that's
1067 // completed.
1068
1069 ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d",
1070 mFlushingAudio, mFlushingVideo);
1071
1072 break;
1073 }
1074
1075 sp<Action> action = *mDeferredActions.begin();
1076 mDeferredActions.erase(mDeferredActions.begin());
1077
1078 action->execute(this);
1079 }
1080}
1081
1082void NuPlayer::performSeek(int64_t seekTimeUs) {
1083 ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)",
1084 seekTimeUs,
1085 seekTimeUs / 1E6);
1086
1087 mSource->seekTo(seekTimeUs);
1088
1089 if (mDriver != NULL) {
1090 sp<NuPlayerDriver> driver = mDriver.promote();
1091 if (driver != NULL) {
1092 driver->notifyPosition(seekTimeUs);
1093 driver->notifySeekComplete();
1094 }
1095 }
1096
1097 // everything's flushed, continue playback.
1098}
1099
1100void NuPlayer::performDecoderFlush() {
1101 ALOGV("performDecoderFlush");
1102
1103 if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
1104 return;
1105 }
1106
1107 mTimeDiscontinuityPending = true;
1108
1109 if (mAudioDecoder != NULL) {
1110 flushDecoder(true /* audio */, false /* needShutdown */);
1111 }
1112
1113 if (mVideoDecoder != NULL) {
1114 flushDecoder(false /* audio */, false /* needShutdown */);
1115 }
1116}
1117
1118void NuPlayer::performDecoderShutdown() {
1119 ALOGV("performDecoderShutdown");
1120
1121 if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
1122 return;
1123 }
1124
1125 mTimeDiscontinuityPending = true;
1126
1127 if (mAudioDecoder != NULL) {
1128 flushDecoder(true /* audio */, true /* needShutdown */);
1129 }
1130
1131 if (mVideoDecoder != NULL) {
1132 flushDecoder(false /* audio */, true /* needShutdown */);
1133 }
1134}
1135
1136void NuPlayer::performReset() {
1137 ALOGV("performReset");
1138
1139 CHECK(mAudioDecoder == NULL);
1140 CHECK(mVideoDecoder == NULL);
1141
1142 cancelPollDuration();
1143
1144 ++mScanSourcesGeneration;
1145 mScanSourcesPending = false;
1146
1147 mRenderer.clear();
1148
1149 if (mSource != NULL) {
1150 mSource->stop();
1151 mSource.clear();
1152 }
1153
1154 if (mDriver != NULL) {
1155 sp<NuPlayerDriver> driver = mDriver.promote();
1156 if (driver != NULL) {
1157 driver->notifyResetComplete();
1158 }
1159 }
Andreas Huber57a339c2012-12-03 11:18:00 -08001160
1161 mStarted = false;
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001162}
1163
1164void NuPlayer::performScanSources() {
1165 ALOGV("performScanSources");
1166
Andreas Huber57a339c2012-12-03 11:18:00 -08001167 if (!mStarted) {
1168 return;
1169 }
1170
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001171 if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
1172 postScanSources();
1173 }
1174}
1175
Andreas Huber57a339c2012-12-03 11:18:00 -08001176void NuPlayer::performSetSurface(const sp<NativeWindowWrapper> &wrapper) {
1177 ALOGV("performSetSurface");
1178
1179 mNativeWindow = wrapper;
1180
1181 // XXX - ignore error from setVideoScalingMode for now
1182 setVideoScalingMode(mVideoScalingMode);
1183
1184 if (mDriver != NULL) {
1185 sp<NuPlayerDriver> driver = mDriver.promote();
1186 if (driver != NULL) {
1187 driver->notifySetSurfaceComplete();
1188 }
1189 }
1190}
1191
Andreas Huberf9334412010-12-15 15:17:42 -08001192} // namespace android