blob: 517fb34ef62cf9c32aebefe2a4c6c2c31f1648b0 [file] [log] [blame]
Andreas Huberf9334412010-12-15 15:17:42 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "NuPlayer"
19#include <utils/Log.h>
20
21#include "NuPlayer.h"
Andreas Huber5bc087c2010-12-23 10:27:40 -080022
23#include "HTTPLiveSource.h"
Andreas Huberf9334412010-12-15 15:17:42 -080024#include "NuPlayerDecoder.h"
Andreas Huber43c3e6c2011-01-05 12:17:08 -080025#include "NuPlayerDriver.h"
Andreas Huberf9334412010-12-15 15:17:42 -080026#include "NuPlayerRenderer.h"
Andreas Huber5bc087c2010-12-23 10:27:40 -080027#include "NuPlayerSource.h"
Andreas Huber2bfdd422011-10-11 15:24:07 -070028#include "RTSPSource.h"
Andreas Huber5bc087c2010-12-23 10:27:40 -080029#include "StreamingSource.h"
Andreas Huberafed0e12011-09-20 15:39:58 -070030#include "GenericSource.h"
Andreas Huber84066782011-08-16 09:34:26 -070031#include "mp4/MP4Source.h"
Andreas Huber5bc087c2010-12-23 10:27:40 -080032
33#include "ATSParser.h"
Andreas Huberf9334412010-12-15 15:17:42 -080034
Andreas Huber84066782011-08-16 09:34:26 -070035#include <cutils/properties.h> // for property_get
Andreas Huber3831a062010-12-21 10:22:33 -080036#include <media/stagefright/foundation/hexdump.h>
Andreas Huberf9334412010-12-15 15:17:42 -080037#include <media/stagefright/foundation/ABuffer.h>
38#include <media/stagefright/foundation/ADebug.h>
39#include <media/stagefright/foundation/AMessage.h>
40#include <media/stagefright/ACodec.h>
Andreas Huber3fe62152011-09-16 15:09:22 -070041#include <media/stagefright/MediaDefs.h>
Andreas Huberf9334412010-12-15 15:17:42 -080042#include <media/stagefright/MediaErrors.h>
43#include <media/stagefright/MetaData.h>
Andy McFadden8ba01022012-12-18 09:46:54 -080044#include <gui/IGraphicBufferProducer.h>
Andreas Huberf9334412010-12-15 15:17:42 -080045
Andreas Huber3fe62152011-09-16 15:09:22 -070046#include "avc_utils.h"
47
Andreas Huber84066782011-08-16 09:34:26 -070048#include "ESDS.h"
49#include <media/stagefright/Utils.h>
50
Andreas Huberf9334412010-12-15 15:17:42 -080051namespace android {
52
Andreas Hubera1f8ab02012-11-30 10:53:22 -080053struct NuPlayer::Action : public RefBase {
54 Action() {}
55
56 virtual void execute(NuPlayer *player) = 0;
57
58private:
59 DISALLOW_EVIL_CONSTRUCTORS(Action);
60};
61
62struct NuPlayer::SeekAction : public Action {
63 SeekAction(int64_t seekTimeUs)
64 : mSeekTimeUs(seekTimeUs) {
65 }
66
67 virtual void execute(NuPlayer *player) {
68 player->performSeek(mSeekTimeUs);
69 }
70
71private:
72 int64_t mSeekTimeUs;
73
74 DISALLOW_EVIL_CONSTRUCTORS(SeekAction);
75};
76
Andreas Huber57a339c2012-12-03 11:18:00 -080077struct NuPlayer::SetSurfaceAction : public Action {
78 SetSurfaceAction(const sp<NativeWindowWrapper> &wrapper)
79 : mWrapper(wrapper) {
80 }
81
82 virtual void execute(NuPlayer *player) {
83 player->performSetSurface(mWrapper);
84 }
85
86private:
87 sp<NativeWindowWrapper> mWrapper;
88
89 DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction);
90};
91
Andreas Hubera1f8ab02012-11-30 10:53:22 -080092// Use this if there's no state necessary to save in order to execute
93// the action.
94struct NuPlayer::SimpleAction : public Action {
95 typedef void (NuPlayer::*ActionFunc)();
96
97 SimpleAction(ActionFunc func)
98 : mFunc(func) {
99 }
100
101 virtual void execute(NuPlayer *player) {
102 (player->*mFunc)();
103 }
104
105private:
106 ActionFunc mFunc;
107
108 DISALLOW_EVIL_CONSTRUCTORS(SimpleAction);
109};
110
Andreas Huberf9334412010-12-15 15:17:42 -0800111////////////////////////////////////////////////////////////////////////////////
112
113NuPlayer::NuPlayer()
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700114 : mUIDValid(false),
Andreas 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(
Andy McFadden8ba01022012-12-18 09:46:54 -0800201 const sp<IGraphicBufferProducer> &bufferProducer) {
Glenn Kasten11731182011-02-08 17:26:17 -0800202 sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
Andreas Huber57a339c2012-12-03 11:18:00 -0800203
Andy McFadden8ba01022012-12-18 09:46:54 -0800204 if (bufferProducer == NULL) {
Andreas Huber57a339c2012-12-03 11:18:00 -0800205 msg->setObject("native-window", NULL);
206 } else {
207 msg->setObject(
208 "native-window",
209 new NativeWindowWrapper(
Andy McFadden8ba01022012-12-18 09:46:54 -0800210 new SurfaceTextureClient(bufferProducer)));
Andreas Huber57a339c2012-12-03 11:18:00 -0800211 }
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;
Andreas Huber516dacf2012-12-03 15:20:40 -0800487 CHECK(codecRequest->findInt32(
488 "channel-count", &numChannels));
Andreas Huber2c2814b2010-12-15 17:18:20 -0800489
Andreas Huber31e25082011-01-10 10:38:31 -0800490 int32_t sampleRate;
491 CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
Andreas Huber2c2814b2010-12-15 17:18:20 -0800492
Steve Block3856b092011-10-20 11:56:00 +0100493 ALOGV("Audio output format changed to %d Hz, %d channels",
Andreas Huber31e25082011-01-10 10:38:31 -0800494 sampleRate, numChannels);
Andreas Huber2c2814b2010-12-15 17:18:20 -0800495
Andreas Huber31e25082011-01-10 10:38:31 -0800496 mAudioSink->close();
Eric Laurent1948eb32012-04-13 16:50:19 -0700497
498 audio_output_flags_t flags;
499 int64_t durationUs;
Andreas Huber516dacf2012-12-03 15:20:40 -0800500 // FIXME: we should handle the case where the video decoder
501 // is created after we receive the format change indication.
502 // Current code will just make that we select deep buffer
503 // with video which should not be a problem as it should
Eric Laurent1948eb32012-04-13 16:50:19 -0700504 // not prevent from keeping A/V sync.
505 if (mVideoDecoder == NULL &&
506 mSource->getDuration(&durationUs) == OK &&
Andreas Huber516dacf2012-12-03 15:20:40 -0800507 durationUs
508 > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
Eric Laurent1948eb32012-04-13 16:50:19 -0700509 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
510 } else {
511 flags = AUDIO_OUTPUT_FLAG_NONE;
512 }
513
Andreas Huber98065552012-05-03 11:33:01 -0700514 int32_t channelMask;
515 if (!codecRequest->findInt32("channel-mask", &channelMask)) {
516 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
517 }
518
Andreas Huber078cfcf2011-09-15 12:25:04 -0700519 CHECK_EQ(mAudioSink->open(
520 sampleRate,
521 numChannels,
Andreas Huber98065552012-05-03 11:33:01 -0700522 (audio_channel_mask_t)channelMask,
Andreas Huber078cfcf2011-09-15 12:25:04 -0700523 AUDIO_FORMAT_PCM_16_BIT,
Eric Laurent1948eb32012-04-13 16:50:19 -0700524 8 /* bufferCount */,
525 NULL,
526 NULL,
527 flags),
Andreas Huber078cfcf2011-09-15 12:25:04 -0700528 (status_t)OK);
Andreas Huber31e25082011-01-10 10:38:31 -0800529 mAudioSink->start();
Andreas Huber2c2814b2010-12-15 17:18:20 -0800530
Andreas Huber31e25082011-01-10 10:38:31 -0800531 mRenderer->signalAudioSinkChanged();
532 } else {
533 // video
Andreas Huber3831a062010-12-21 10:22:33 -0800534
Andreas Huber31e25082011-01-10 10:38:31 -0800535 int32_t width, height;
536 CHECK(codecRequest->findInt32("width", &width));
537 CHECK(codecRequest->findInt32("height", &height));
538
539 int32_t cropLeft, cropTop, cropRight, cropBottom;
540 CHECK(codecRequest->findRect(
541 "crop",
542 &cropLeft, &cropTop, &cropRight, &cropBottom));
543
Andreas Huber516dacf2012-12-03 15:20:40 -0800544 int32_t displayWidth = cropRight - cropLeft + 1;
545 int32_t displayHeight = cropBottom - cropTop + 1;
546
Steve Block3856b092011-10-20 11:56:00 +0100547 ALOGV("Video output format changed to %d x %d "
Andreas Hubercb67cd12011-08-26 16:02:19 -0700548 "(crop: %d x %d @ (%d, %d))",
Andreas Huber31e25082011-01-10 10:38:31 -0800549 width, height,
Andreas Huber516dacf2012-12-03 15:20:40 -0800550 displayWidth,
551 displayHeight,
Andreas Hubercb67cd12011-08-26 16:02:19 -0700552 cropLeft, cropTop);
Andreas Huber31e25082011-01-10 10:38:31 -0800553
Andreas Huber516dacf2012-12-03 15:20:40 -0800554 sp<AMessage> videoInputFormat =
555 mSource->getFormat(false /* audio */);
556
557 // Take into account sample aspect ratio if necessary:
558 int32_t sarWidth, sarHeight;
559 if (videoInputFormat->findInt32("sar-width", &sarWidth)
560 && videoInputFormat->findInt32(
561 "sar-height", &sarHeight)) {
562 ALOGV("Sample aspect ratio %d : %d",
563 sarWidth, sarHeight);
564
565 displayWidth = (displayWidth * sarWidth) / sarHeight;
566
567 ALOGV("display dimensions %d x %d",
568 displayWidth, displayHeight);
569 }
570
Andreas Huber31e25082011-01-10 10:38:31 -0800571 notifyListener(
Andreas Huber516dacf2012-12-03 15:20:40 -0800572 MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight);
Andreas Huber31e25082011-01-10 10:38:31 -0800573 }
Andreas Huber3831a062010-12-21 10:22:33 -0800574 } else if (what == ACodec::kWhatShutdownCompleted) {
Steve Block3856b092011-10-20 11:56:00 +0100575 ALOGV("%s shutdown completed", audio ? "audio" : "video");
Andreas Huber3831a062010-12-21 10:22:33 -0800576 if (audio) {
577 mAudioDecoder.clear();
578
579 CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
580 mFlushingAudio = SHUT_DOWN;
581 } else {
582 mVideoDecoder.clear();
583
584 CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
585 mFlushingVideo = SHUT_DOWN;
586 }
587
588 finishFlushIfPossible();
Andreas Huberc92fd242011-08-16 13:48:44 -0700589 } else if (what == ACodec::kWhatError) {
Steve Block29357bc2012-01-06 19:20:56 +0000590 ALOGE("Received error from %s decoder, aborting playback.",
Andreas Huberc92fd242011-08-16 13:48:44 -0700591 audio ? "audio" : "video");
592
593 mRenderer->queueEOS(audio, UNKNOWN_ERROR);
Andreas Huber57788222012-02-21 11:47:18 -0800594 } else if (what == ACodec::kWhatDrainThisBuffer) {
Andreas Huberf9334412010-12-15 15:17:42 -0800595 renderBuffer(audio, codecRequest);
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800596 } else if (what != ACodec::kWhatComponentAllocated
597 && what != ACodec::kWhatComponentConfigured
598 && what != ACodec::kWhatBuffersAllocated) {
599 ALOGV("Unhandled codec notification %d '%c%c%c%c'.",
600 what,
601 what >> 24,
602 (what >> 16) & 0xff,
603 (what >> 8) & 0xff,
604 what & 0xff);
Andreas Huberf9334412010-12-15 15:17:42 -0800605 }
606
607 break;
608 }
609
610 case kWhatRendererNotify:
611 {
612 int32_t what;
613 CHECK(msg->findInt32("what", &what));
614
615 if (what == Renderer::kWhatEOS) {
616 int32_t audio;
617 CHECK(msg->findInt32("audio", &audio));
618
Andreas Huberc92fd242011-08-16 13:48:44 -0700619 int32_t finalResult;
620 CHECK(msg->findInt32("finalResult", &finalResult));
621
Andreas Huberf9334412010-12-15 15:17:42 -0800622 if (audio) {
623 mAudioEOS = true;
624 } else {
625 mVideoEOS = true;
626 }
627
Andreas Huberc92fd242011-08-16 13:48:44 -0700628 if (finalResult == ERROR_END_OF_STREAM) {
Steve Block3856b092011-10-20 11:56:00 +0100629 ALOGV("reached %s EOS", audio ? "audio" : "video");
Andreas Huberc92fd242011-08-16 13:48:44 -0700630 } else {
Steve Block29357bc2012-01-06 19:20:56 +0000631 ALOGE("%s track encountered an error (%d)",
Andreas Huberc92fd242011-08-16 13:48:44 -0700632 audio ? "audio" : "video", finalResult);
633
634 notifyListener(
635 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult);
636 }
Andreas Huberf9334412010-12-15 15:17:42 -0800637
638 if ((mAudioEOS || mAudioDecoder == NULL)
639 && (mVideoEOS || mVideoDecoder == NULL)) {
640 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
641 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800642 } else if (what == Renderer::kWhatPosition) {
643 int64_t positionUs;
644 CHECK(msg->findInt64("positionUs", &positionUs));
645
Andreas Huber3fe62152011-09-16 15:09:22 -0700646 CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs));
647
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800648 if (mDriver != NULL) {
649 sp<NuPlayerDriver> driver = mDriver.promote();
650 if (driver != NULL) {
651 driver->notifyPosition(positionUs);
Andreas Huber3fe62152011-09-16 15:09:22 -0700652
653 driver->notifyFrameStats(
654 mNumFramesTotal, mNumFramesDropped);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800655 }
656 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700657 } else if (what == Renderer::kWhatFlushComplete) {
Andreas Huberf9334412010-12-15 15:17:42 -0800658 int32_t audio;
659 CHECK(msg->findInt32("audio", &audio));
660
Steve Block3856b092011-10-20 11:56:00 +0100661 ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
James Dongf57b4ea2012-07-20 13:38:36 -0700662 } else if (what == Renderer::kWhatVideoRenderingStart) {
663 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
Andreas Huberf9334412010-12-15 15:17:42 -0800664 }
665 break;
666 }
667
668 case kWhatMoreDataQueued:
669 {
670 break;
671 }
672
Andreas Huber1aef2112011-01-04 14:01:29 -0800673 case kWhatReset:
674 {
Steve Block3856b092011-10-20 11:56:00 +0100675 ALOGV("kWhatReset");
Andreas Huber1aef2112011-01-04 14:01:29 -0800676
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800677 mDeferredActions.push_back(
678 new SimpleAction(&NuPlayer::performDecoderShutdown));
Andreas Huberb7c8e912012-11-27 15:02:53 -0800679
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800680 mDeferredActions.push_back(
681 new SimpleAction(&NuPlayer::performReset));
Andreas Huberb58ce9f2011-11-28 16:27:35 -0800682
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800683 processDeferredActions();
Andreas Huber1aef2112011-01-04 14:01:29 -0800684 break;
685 }
686
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800687 case kWhatSeek:
688 {
689 int64_t seekTimeUs;
690 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
691
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800692 ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800693
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800694 mDeferredActions.push_back(
695 new SimpleAction(&NuPlayer::performDecoderFlush));
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800696
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800697 mDeferredActions.push_back(new SeekAction(seekTimeUs));
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800698
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800699 processDeferredActions();
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800700 break;
701 }
702
Andreas Huberb4082222011-01-20 15:23:04 -0800703 case kWhatPause:
704 {
705 CHECK(mRenderer != NULL);
706 mRenderer->pause();
707 break;
708 }
709
710 case kWhatResume:
711 {
712 CHECK(mRenderer != NULL);
713 mRenderer->resume();
714 break;
715 }
716
Andreas Huberf9334412010-12-15 15:17:42 -0800717 default:
718 TRESPASS();
719 break;
720 }
721}
722
Andreas Huber3831a062010-12-21 10:22:33 -0800723void NuPlayer::finishFlushIfPossible() {
724 if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
725 return;
726 }
727
728 if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
729 return;
730 }
731
Steve Block3856b092011-10-20 11:56:00 +0100732 ALOGV("both audio and video are flushed now.");
Andreas Huber3831a062010-12-21 10:22:33 -0800733
Andreas Huber6e3d3112011-11-28 12:36:11 -0800734 if (mTimeDiscontinuityPending) {
735 mRenderer->signalTimeDiscontinuity();
736 mTimeDiscontinuityPending = false;
737 }
Andreas Huber3831a062010-12-21 10:22:33 -0800738
Andreas Huber22fc52f2011-01-05 16:24:27 -0800739 if (mAudioDecoder != NULL) {
Andreas Huber3831a062010-12-21 10:22:33 -0800740 mAudioDecoder->signalResume();
741 }
742
Andreas Huber22fc52f2011-01-05 16:24:27 -0800743 if (mVideoDecoder != NULL) {
Andreas Huber3831a062010-12-21 10:22:33 -0800744 mVideoDecoder->signalResume();
745 }
746
747 mFlushingAudio = NONE;
748 mFlushingVideo = NONE;
Andreas Huber3831a062010-12-21 10:22:33 -0800749
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800750 processDeferredActions();
Andreas Huber1aef2112011-01-04 14:01:29 -0800751}
752
753void NuPlayer::postScanSources() {
754 if (mScanSourcesPending) {
755 return;
756 }
757
758 sp<AMessage> msg = new AMessage(kWhatScanSources, id());
759 msg->setInt32("generation", mScanSourcesGeneration);
760 msg->post();
761
762 mScanSourcesPending = true;
763}
764
Andreas Huber5bc087c2010-12-23 10:27:40 -0800765status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
Andreas Huberf9334412010-12-15 15:17:42 -0800766 if (*decoder != NULL) {
767 return OK;
768 }
769
Andreas Huber84066782011-08-16 09:34:26 -0700770 sp<AMessage> format = mSource->getFormat(audio);
Andreas Huberf9334412010-12-15 15:17:42 -0800771
Andreas Huber84066782011-08-16 09:34:26 -0700772 if (format == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -0800773 return -EWOULDBLOCK;
774 }
775
Andreas Huber3fe62152011-09-16 15:09:22 -0700776 if (!audio) {
Andreas Huber84066782011-08-16 09:34:26 -0700777 AString mime;
778 CHECK(format->findString("mime", &mime));
779 mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
Andreas Huber3fe62152011-09-16 15:09:22 -0700780 }
781
Andreas Huberf9334412010-12-15 15:17:42 -0800782 sp<AMessage> notify =
783 new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
784 id());
785
Glenn Kasten11731182011-02-08 17:26:17 -0800786 *decoder = audio ? new Decoder(notify) :
787 new Decoder(notify, mNativeWindow);
Andreas Huberf9334412010-12-15 15:17:42 -0800788 looper()->registerHandler(*decoder);
789
Andreas Huber84066782011-08-16 09:34:26 -0700790 (*decoder)->configure(format);
Andreas Huberf9334412010-12-15 15:17:42 -0800791
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800792 int64_t durationUs;
793 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
794 sp<NuPlayerDriver> driver = mDriver.promote();
795 if (driver != NULL) {
796 driver->notifyDuration(durationUs);
797 }
798 }
799
Andreas Huberf9334412010-12-15 15:17:42 -0800800 return OK;
801}
802
803status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
804 sp<AMessage> reply;
805 CHECK(msg->findMessage("reply", &reply));
806
Andreas Huber53df1a42010-12-22 10:03:04 -0800807 if ((audio && IsFlushingState(mFlushingAudio))
808 || (!audio && IsFlushingState(mFlushingVideo))) {
Andreas Huberf9334412010-12-15 15:17:42 -0800809 reply->setInt32("err", INFO_DISCONTINUITY);
810 reply->post();
811 return OK;
812 }
813
814 sp<ABuffer> accessUnit;
Andreas Huberf9334412010-12-15 15:17:42 -0800815
Andreas Huber3fe62152011-09-16 15:09:22 -0700816 bool dropAccessUnit;
817 do {
818 status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800819
Andreas Huber3fe62152011-09-16 15:09:22 -0700820 if (err == -EWOULDBLOCK) {
821 return err;
822 } else if (err != OK) {
823 if (err == INFO_DISCONTINUITY) {
824 int32_t type;
825 CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
Andreas Huber53df1a42010-12-22 10:03:04 -0800826
Andreas Huber3fe62152011-09-16 15:09:22 -0700827 bool formatChange =
Andreas Huber6e3d3112011-11-28 12:36:11 -0800828 (audio &&
829 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
830 || (!audio &&
831 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
Andreas Huber53df1a42010-12-22 10:03:04 -0800832
Andreas Huber6e3d3112011-11-28 12:36:11 -0800833 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
834
Steve Blockdf64d152012-01-04 20:05:49 +0000835 ALOGI("%s discontinuity (formatChange=%d, time=%d)",
Andreas Huber6e3d3112011-11-28 12:36:11 -0800836 audio ? "audio" : "video", formatChange, timeChange);
Andreas Huber32f3cef2011-03-02 15:34:46 -0800837
Andreas Huber3fe62152011-09-16 15:09:22 -0700838 if (audio) {
839 mSkipRenderingAudioUntilMediaTimeUs = -1;
840 } else {
841 mSkipRenderingVideoUntilMediaTimeUs = -1;
842 }
Andreas Huber32f3cef2011-03-02 15:34:46 -0800843
Andreas Huber6e3d3112011-11-28 12:36:11 -0800844 if (timeChange) {
845 sp<AMessage> extra;
846 if (accessUnit->meta()->findMessage("extra", &extra)
847 && extra != NULL) {
848 int64_t resumeAtMediaTimeUs;
849 if (extra->findInt64(
850 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
Steve Blockdf64d152012-01-04 20:05:49 +0000851 ALOGI("suppressing rendering of %s until %lld us",
Andreas Huber6e3d3112011-11-28 12:36:11 -0800852 audio ? "audio" : "video", resumeAtMediaTimeUs);
Andreas Huber3fe62152011-09-16 15:09:22 -0700853
Andreas Huber6e3d3112011-11-28 12:36:11 -0800854 if (audio) {
855 mSkipRenderingAudioUntilMediaTimeUs =
856 resumeAtMediaTimeUs;
857 } else {
858 mSkipRenderingVideoUntilMediaTimeUs =
859 resumeAtMediaTimeUs;
860 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700861 }
Andreas Huber32f3cef2011-03-02 15:34:46 -0800862 }
863 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700864
Andreas Huber6e3d3112011-11-28 12:36:11 -0800865 mTimeDiscontinuityPending =
866 mTimeDiscontinuityPending || timeChange;
867
868 if (formatChange || timeChange) {
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800869 if (mFlushingAudio == NONE && mFlushingVideo == NONE) {
870 // And we'll resume scanning sources once we're done
871 // flushing.
872 mDeferredActions.push_front(
873 new SimpleAction(
874 &NuPlayer::performScanSources));
875 }
876
Andreas Huber6e3d3112011-11-28 12:36:11 -0800877 flushDecoder(audio, formatChange);
878 } else {
879 // This stream is unaffected by the discontinuity
880
881 if (audio) {
882 mFlushingAudio = FLUSHED;
883 } else {
884 mFlushingVideo = FLUSHED;
885 }
886
887 finishFlushIfPossible();
888
889 return -EWOULDBLOCK;
890 }
Andreas Huber32f3cef2011-03-02 15:34:46 -0800891 }
892
Andreas Huber3fe62152011-09-16 15:09:22 -0700893 reply->setInt32("err", err);
894 reply->post();
895 return OK;
Andreas Huberf9334412010-12-15 15:17:42 -0800896 }
897
Andreas Huber3fe62152011-09-16 15:09:22 -0700898 if (!audio) {
899 ++mNumFramesTotal;
900 }
901
902 dropAccessUnit = false;
903 if (!audio
904 && mVideoLateByUs > 100000ll
905 && mVideoIsAVC
906 && !IsAVCReferenceFrame(accessUnit)) {
907 dropAccessUnit = true;
908 ++mNumFramesDropped;
909 }
910 } while (dropAccessUnit);
Andreas Huberf9334412010-12-15 15:17:42 -0800911
Steve Block3856b092011-10-20 11:56:00 +0100912 // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800913
914#if 0
915 int64_t mediaTimeUs;
916 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
Steve Block3856b092011-10-20 11:56:00 +0100917 ALOGV("feeding %s input buffer at media time %.2f secs",
Andreas Huberf9334412010-12-15 15:17:42 -0800918 audio ? "audio" : "video",
919 mediaTimeUs / 1E6);
920#endif
921
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800922 reply->setBuffer("buffer", accessUnit);
Andreas Huberf9334412010-12-15 15:17:42 -0800923 reply->post();
924
925 return OK;
926}
927
928void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
Steve Block3856b092011-10-20 11:56:00 +0100929 // ALOGV("renderBuffer %s", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800930
931 sp<AMessage> reply;
932 CHECK(msg->findMessage("reply", &reply));
933
Andreas Huber18ac5402011-08-31 15:04:25 -0700934 if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) {
935 // We're currently attempting to flush the decoder, in order
936 // to complete this, the decoder wants all its buffers back,
937 // so we don't want any output buffers it sent us (from before
938 // we initiated the flush) to be stuck in the renderer's queue.
939
Steve Block3856b092011-10-20 11:56:00 +0100940 ALOGV("we're still flushing the %s decoder, sending its output buffer"
Andreas Huber18ac5402011-08-31 15:04:25 -0700941 " right back.", audio ? "audio" : "video");
942
943 reply->post();
944 return;
945 }
946
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800947 sp<ABuffer> buffer;
948 CHECK(msg->findBuffer("buffer", &buffer));
Andreas Huberf9334412010-12-15 15:17:42 -0800949
Andreas Huber32f3cef2011-03-02 15:34:46 -0800950 int64_t &skipUntilMediaTimeUs =
951 audio
952 ? mSkipRenderingAudioUntilMediaTimeUs
953 : mSkipRenderingVideoUntilMediaTimeUs;
954
955 if (skipUntilMediaTimeUs >= 0) {
956 int64_t mediaTimeUs;
957 CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs));
958
959 if (mediaTimeUs < skipUntilMediaTimeUs) {
Steve Block3856b092011-10-20 11:56:00 +0100960 ALOGV("dropping %s buffer at time %lld as requested.",
Andreas Huber32f3cef2011-03-02 15:34:46 -0800961 audio ? "audio" : "video",
962 mediaTimeUs);
963
964 reply->post();
965 return;
966 }
967
968 skipUntilMediaTimeUs = -1;
969 }
970
Andreas Huberf9334412010-12-15 15:17:42 -0800971 mRenderer->queueBuffer(audio, buffer, reply);
972}
973
974void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800975 if (mDriver == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -0800976 return;
977 }
978
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800979 sp<NuPlayerDriver> driver = mDriver.promote();
Andreas Huberf9334412010-12-15 15:17:42 -0800980
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800981 if (driver == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -0800982 return;
983 }
984
Andreas Hubera4af2142011-10-26 15:23:31 -0700985 driver->notifyListener(msg, ext1, ext2);
Andreas Huberf9334412010-12-15 15:17:42 -0800986}
987
Andreas Huber1aef2112011-01-04 14:01:29 -0800988void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
Andreas Huber6e3d3112011-11-28 12:36:11 -0800989 if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
Steve Blockdf64d152012-01-04 20:05:49 +0000990 ALOGI("flushDecoder %s without decoder present",
Andreas Huber6e3d3112011-11-28 12:36:11 -0800991 audio ? "audio" : "video");
992 }
993
Andreas Huber1aef2112011-01-04 14:01:29 -0800994 // Make sure we don't continue to scan sources until we finish flushing.
995 ++mScanSourcesGeneration;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800996 mScanSourcesPending = false;
Andreas Huber1aef2112011-01-04 14:01:29 -0800997
998 (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
999 mRenderer->flush(audio);
1000
1001 FlushStatus newStatus =
1002 needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
1003
1004 if (audio) {
1005 CHECK(mFlushingAudio == NONE
1006 || mFlushingAudio == AWAITING_DISCONTINUITY);
1007
1008 mFlushingAudio = newStatus;
1009
1010 if (mFlushingVideo == NONE) {
1011 mFlushingVideo = (mVideoDecoder != NULL)
1012 ? AWAITING_DISCONTINUITY
1013 : FLUSHED;
1014 }
1015 } else {
1016 CHECK(mFlushingVideo == NONE
1017 || mFlushingVideo == AWAITING_DISCONTINUITY);
1018
1019 mFlushingVideo = newStatus;
1020
1021 if (mFlushingAudio == NONE) {
1022 mFlushingAudio = (mAudioDecoder != NULL)
1023 ? AWAITING_DISCONTINUITY
1024 : FLUSHED;
1025 }
1026 }
1027}
1028
Andreas Huber84066782011-08-16 09:34:26 -07001029sp<AMessage> NuPlayer::Source::getFormat(bool audio) {
1030 sp<MetaData> meta = getFormatMeta(audio);
1031
1032 if (meta == NULL) {
1033 return NULL;
1034 }
1035
1036 sp<AMessage> msg = new AMessage;
1037
1038 if(convertMetaDataToMessage(meta, &msg) == OK) {
1039 return msg;
1040 }
1041 return NULL;
1042}
1043
James Dong0d268a32012-08-31 12:18:27 -07001044status_t NuPlayer::setVideoScalingMode(int32_t mode) {
1045 mVideoScalingMode = mode;
Andreas Huber57a339c2012-12-03 11:18:00 -08001046 if (mNativeWindow != NULL) {
James Dong0d268a32012-08-31 12:18:27 -07001047 status_t ret = native_window_set_scaling_mode(
1048 mNativeWindow->getNativeWindow().get(), mVideoScalingMode);
1049 if (ret != OK) {
1050 ALOGE("Failed to set scaling mode (%d): %s",
1051 -ret, strerror(-ret));
1052 return ret;
1053 }
1054 }
1055 return OK;
1056}
1057
Andreas Huberb7c8e912012-11-27 15:02:53 -08001058void NuPlayer::schedulePollDuration() {
1059 sp<AMessage> msg = new AMessage(kWhatPollDuration, id());
1060 msg->setInt32("generation", mPollDurationGeneration);
1061 msg->post();
1062}
1063
1064void NuPlayer::cancelPollDuration() {
1065 ++mPollDurationGeneration;
1066}
1067
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001068void NuPlayer::processDeferredActions() {
1069 while (!mDeferredActions.empty()) {
1070 // We won't execute any deferred actions until we're no longer in
1071 // an intermediate state, i.e. one more more decoders are currently
1072 // flushing or shutting down.
1073
1074 if (mRenderer != NULL) {
1075 // There's an edge case where the renderer owns all output
1076 // buffers and is paused, therefore the decoder will not read
1077 // more input data and will never encounter the matching
1078 // discontinuity. To avoid this, we resume the renderer.
1079
1080 if (mFlushingAudio == AWAITING_DISCONTINUITY
1081 || mFlushingVideo == AWAITING_DISCONTINUITY) {
1082 mRenderer->resume();
1083 }
1084 }
1085
1086 if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
1087 // We're currently flushing, postpone the reset until that's
1088 // completed.
1089
1090 ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d",
1091 mFlushingAudio, mFlushingVideo);
1092
1093 break;
1094 }
1095
1096 sp<Action> action = *mDeferredActions.begin();
1097 mDeferredActions.erase(mDeferredActions.begin());
1098
1099 action->execute(this);
1100 }
1101}
1102
1103void NuPlayer::performSeek(int64_t seekTimeUs) {
1104 ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)",
1105 seekTimeUs,
1106 seekTimeUs / 1E6);
1107
1108 mSource->seekTo(seekTimeUs);
1109
1110 if (mDriver != NULL) {
1111 sp<NuPlayerDriver> driver = mDriver.promote();
1112 if (driver != NULL) {
1113 driver->notifyPosition(seekTimeUs);
1114 driver->notifySeekComplete();
1115 }
1116 }
1117
1118 // everything's flushed, continue playback.
1119}
1120
1121void NuPlayer::performDecoderFlush() {
1122 ALOGV("performDecoderFlush");
1123
1124 if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
1125 return;
1126 }
1127
1128 mTimeDiscontinuityPending = true;
1129
1130 if (mAudioDecoder != NULL) {
1131 flushDecoder(true /* audio */, false /* needShutdown */);
1132 }
1133
1134 if (mVideoDecoder != NULL) {
1135 flushDecoder(false /* audio */, false /* needShutdown */);
1136 }
1137}
1138
1139void NuPlayer::performDecoderShutdown() {
1140 ALOGV("performDecoderShutdown");
1141
1142 if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
1143 return;
1144 }
1145
1146 mTimeDiscontinuityPending = true;
1147
1148 if (mAudioDecoder != NULL) {
1149 flushDecoder(true /* audio */, true /* needShutdown */);
1150 }
1151
1152 if (mVideoDecoder != NULL) {
1153 flushDecoder(false /* audio */, true /* needShutdown */);
1154 }
1155}
1156
1157void NuPlayer::performReset() {
1158 ALOGV("performReset");
1159
1160 CHECK(mAudioDecoder == NULL);
1161 CHECK(mVideoDecoder == NULL);
1162
1163 cancelPollDuration();
1164
1165 ++mScanSourcesGeneration;
1166 mScanSourcesPending = false;
1167
1168 mRenderer.clear();
1169
1170 if (mSource != NULL) {
1171 mSource->stop();
1172 mSource.clear();
1173 }
1174
1175 if (mDriver != NULL) {
1176 sp<NuPlayerDriver> driver = mDriver.promote();
1177 if (driver != NULL) {
1178 driver->notifyResetComplete();
1179 }
1180 }
Andreas Huber57a339c2012-12-03 11:18:00 -08001181
1182 mStarted = false;
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001183}
1184
1185void NuPlayer::performScanSources() {
1186 ALOGV("performScanSources");
1187
Andreas Huber57a339c2012-12-03 11:18:00 -08001188 if (!mStarted) {
1189 return;
1190 }
1191
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001192 if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
1193 postScanSources();
1194 }
1195}
1196
Andreas Huber57a339c2012-12-03 11:18:00 -08001197void NuPlayer::performSetSurface(const sp<NativeWindowWrapper> &wrapper) {
1198 ALOGV("performSetSurface");
1199
1200 mNativeWindow = wrapper;
1201
1202 // XXX - ignore error from setVideoScalingMode for now
1203 setVideoScalingMode(mVideoScalingMode);
1204
1205 if (mDriver != NULL) {
1206 sp<NuPlayerDriver> driver = mDriver.promote();
1207 if (driver != NULL) {
1208 driver->notifySetSurfaceComplete();
1209 }
1210 }
1211}
1212
Andreas Huberf9334412010-12-15 15:17:42 -08001213} // namespace android