blob: f36356861a996730f314238a5e73b523a2069036 [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
77// Use this if there's no state necessary to save in order to execute
78// the action.
79struct NuPlayer::SimpleAction : public Action {
80 typedef void (NuPlayer::*ActionFunc)();
81
82 SimpleAction(ActionFunc func)
83 : mFunc(func) {
84 }
85
86 virtual void execute(NuPlayer *player) {
87 (player->*mFunc)();
88 }
89
90private:
91 ActionFunc mFunc;
92
93 DISALLOW_EVIL_CONSTRUCTORS(SimpleAction);
94};
95
Andreas Huberf9334412010-12-15 15:17:42 -080096////////////////////////////////////////////////////////////////////////////////
97
98NuPlayer::NuPlayer()
Andreas Huber9b80c2b2011-06-30 15:47:02 -070099 : mUIDValid(false),
Andreas Huber3fe62152011-09-16 15:09:22 -0700100 mVideoIsAVC(false),
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700101 mAudioEOS(false),
Andreas Huberf9334412010-12-15 15:17:42 -0800102 mVideoEOS(false),
Andreas Huber5bc087c2010-12-23 10:27:40 -0800103 mScanSourcesPending(false),
Andreas Huber1aef2112011-01-04 14:01:29 -0800104 mScanSourcesGeneration(0),
Andreas Huberb7c8e912012-11-27 15:02:53 -0800105 mPollDurationGeneration(0),
Andreas Huber6e3d3112011-11-28 12:36:11 -0800106 mTimeDiscontinuityPending(false),
Andreas Huberf9334412010-12-15 15:17:42 -0800107 mFlushingAudio(NONE),
Andreas Huber1aef2112011-01-04 14:01:29 -0800108 mFlushingVideo(NONE),
Andreas Huber3fe62152011-09-16 15:09:22 -0700109 mSkipRenderingAudioUntilMediaTimeUs(-1ll),
110 mSkipRenderingVideoUntilMediaTimeUs(-1ll),
111 mVideoLateByUs(0ll),
112 mNumFramesTotal(0ll),
James Dong0d268a32012-08-31 12:18:27 -0700113 mNumFramesDropped(0ll),
114 mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) {
Andreas Huberf9334412010-12-15 15:17:42 -0800115}
116
117NuPlayer::~NuPlayer() {
118}
119
Andreas Huber9b80c2b2011-06-30 15:47:02 -0700120void NuPlayer::setUID(uid_t uid) {
121 mUIDValid = true;
122 mUID = uid;
123}
124
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800125void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
126 mDriver = driver;
Andreas Huberf9334412010-12-15 15:17:42 -0800127}
128
129void NuPlayer::setDataSource(const sp<IStreamSource> &source) {
130 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
131
Andreas Huber84066782011-08-16 09:34:26 -0700132 char prop[PROPERTY_VALUE_MAX];
133 if (property_get("media.stagefright.use-mp4source", prop, NULL)
134 && (!strcmp(prop, "1") || !strcasecmp(prop, "true"))) {
135 msg->setObject("source", new MP4Source(source));
136 } else {
137 msg->setObject("source", new StreamingSource(source));
138 }
139
Andreas Huber5bc087c2010-12-23 10:27:40 -0800140 msg->post();
141}
Andreas Huberf9334412010-12-15 15:17:42 -0800142
Andreas Huberafed0e12011-09-20 15:39:58 -0700143static bool IsHTTPLiveURL(const char *url) {
144 if (!strncasecmp("http://", url, 7)
145 || !strncasecmp("https://", url, 8)) {
146 size_t len = strlen(url);
147 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
148 return true;
149 }
150
151 if (strstr(url,"m3u8")) {
152 return true;
153 }
154 }
155
156 return false;
157}
158
Andreas Huber5bc087c2010-12-23 10:27:40 -0800159void NuPlayer::setDataSource(
160 const char *url, const KeyedVector<String8, String8> *headers) {
161 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
162
Andreas Huberafed0e12011-09-20 15:39:58 -0700163 sp<Source> source;
164 if (IsHTTPLiveURL(url)) {
165 source = new HTTPLiveSource(url, headers, mUIDValid, mUID);
166 } else if (!strncasecmp(url, "rtsp://", 7)) {
167 source = new RTSPSource(url, headers, mUIDValid, mUID);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700168 } else {
Andreas Huberafed0e12011-09-20 15:39:58 -0700169 source = new GenericSource(url, headers, mUIDValid, mUID);
Andreas Huber2bfdd422011-10-11 15:24:07 -0700170 }
171
Andreas Huberafed0e12011-09-20 15:39:58 -0700172 msg->setObject("source", source);
173 msg->post();
174}
175
176void NuPlayer::setDataSource(int fd, int64_t offset, int64_t length) {
177 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
178
179 sp<Source> source = new GenericSource(fd, offset, length);
180 msg->setObject("source", source);
Andreas Huberf9334412010-12-15 15:17:42 -0800181 msg->post();
182}
183
Glenn Kasten11731182011-02-08 17:26:17 -0800184void NuPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
185 sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
186 sp<SurfaceTextureClient> surfaceTextureClient(surfaceTexture != NULL ?
187 new SurfaceTextureClient(surfaceTexture) : NULL);
188 msg->setObject("native-window", new NativeWindowWrapper(surfaceTextureClient));
Andreas Huberf9334412010-12-15 15:17:42 -0800189 msg->post();
190}
191
192void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) {
193 sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id());
194 msg->setObject("sink", sink);
195 msg->post();
196}
197
198void NuPlayer::start() {
199 (new AMessage(kWhatStart, id()))->post();
200}
201
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800202void NuPlayer::pause() {
Andreas Huberb4082222011-01-20 15:23:04 -0800203 (new AMessage(kWhatPause, id()))->post();
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800204}
205
206void NuPlayer::resume() {
Andreas Huberb4082222011-01-20 15:23:04 -0800207 (new AMessage(kWhatResume, id()))->post();
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800208}
209
Andreas Huber1aef2112011-01-04 14:01:29 -0800210void NuPlayer::resetAsync() {
211 (new AMessage(kWhatReset, id()))->post();
212}
213
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800214void NuPlayer::seekToAsync(int64_t seekTimeUs) {
215 sp<AMessage> msg = new AMessage(kWhatSeek, id());
216 msg->setInt64("seekTimeUs", seekTimeUs);
217 msg->post();
218}
219
Andreas Huber53df1a42010-12-22 10:03:04 -0800220// static
Andreas Huber1aef2112011-01-04 14:01:29 -0800221bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
Andreas Huber53df1a42010-12-22 10:03:04 -0800222 switch (state) {
223 case FLUSHING_DECODER:
Andreas Huber1aef2112011-01-04 14:01:29 -0800224 if (needShutdown != NULL) {
225 *needShutdown = false;
Andreas Huber53df1a42010-12-22 10:03:04 -0800226 }
227 return true;
228
Andreas Huber1aef2112011-01-04 14:01:29 -0800229 case FLUSHING_DECODER_SHUTDOWN:
230 if (needShutdown != NULL) {
231 *needShutdown = true;
Andreas Huber53df1a42010-12-22 10:03:04 -0800232 }
233 return true;
234
235 default:
236 return false;
237 }
238}
239
Andreas Huberf9334412010-12-15 15:17:42 -0800240void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
241 switch (msg->what()) {
242 case kWhatSetDataSource:
243 {
Steve Block3856b092011-10-20 11:56:00 +0100244 ALOGV("kWhatSetDataSource");
Andreas Huberf9334412010-12-15 15:17:42 -0800245
246 CHECK(mSource == NULL);
247
Andreas Huber5bc087c2010-12-23 10:27:40 -0800248 sp<RefBase> obj;
249 CHECK(msg->findObject("source", &obj));
Andreas Huberf9334412010-12-15 15:17:42 -0800250
Andreas Huber5bc087c2010-12-23 10:27:40 -0800251 mSource = static_cast<Source *>(obj.get());
Andreas Huberf9334412010-12-15 15:17:42 -0800252 break;
253 }
254
Andreas Huberb7c8e912012-11-27 15:02:53 -0800255 case kWhatPollDuration:
256 {
257 int32_t generation;
258 CHECK(msg->findInt32("generation", &generation));
259
260 if (generation != mPollDurationGeneration) {
261 // stale
262 break;
263 }
264
265 int64_t durationUs;
266 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
267 sp<NuPlayerDriver> driver = mDriver.promote();
268 if (driver != NULL) {
269 driver->notifyDuration(durationUs);
270 }
271 }
272
273 msg->post(1000000ll); // poll again in a second.
274 break;
275 }
276
Glenn Kasten11731182011-02-08 17:26:17 -0800277 case kWhatSetVideoNativeWindow:
Andreas Huberf9334412010-12-15 15:17:42 -0800278 {
Steve Block3856b092011-10-20 11:56:00 +0100279 ALOGV("kWhatSetVideoNativeWindow");
Andreas Huberf9334412010-12-15 15:17:42 -0800280
281 sp<RefBase> obj;
Glenn Kasten11731182011-02-08 17:26:17 -0800282 CHECK(msg->findObject("native-window", &obj));
Andreas Huberf9334412010-12-15 15:17:42 -0800283
Glenn Kasten11731182011-02-08 17:26:17 -0800284 mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get());
James Dong0d268a32012-08-31 12:18:27 -0700285
286 // XXX - ignore error from setVideoScalingMode for now
287 setVideoScalingMode(mVideoScalingMode);
Andreas Huberf9334412010-12-15 15:17:42 -0800288 break;
289 }
290
291 case kWhatSetAudioSink:
292 {
Steve Block3856b092011-10-20 11:56:00 +0100293 ALOGV("kWhatSetAudioSink");
Andreas Huberf9334412010-12-15 15:17:42 -0800294
295 sp<RefBase> obj;
296 CHECK(msg->findObject("sink", &obj));
297
298 mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get());
299 break;
300 }
301
302 case kWhatStart:
303 {
Steve Block3856b092011-10-20 11:56:00 +0100304 ALOGV("kWhatStart");
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800305
Andreas Huber3fe62152011-09-16 15:09:22 -0700306 mVideoIsAVC = false;
Andreas Huber1aef2112011-01-04 14:01:29 -0800307 mAudioEOS = false;
308 mVideoEOS = false;
Andreas Huber32f3cef2011-03-02 15:34:46 -0800309 mSkipRenderingAudioUntilMediaTimeUs = -1;
310 mSkipRenderingVideoUntilMediaTimeUs = -1;
Andreas Huber3fe62152011-09-16 15:09:22 -0700311 mVideoLateByUs = 0;
312 mNumFramesTotal = 0;
313 mNumFramesDropped = 0;
Andreas Huber1aef2112011-01-04 14:01:29 -0800314
Andreas Huber5bc087c2010-12-23 10:27:40 -0800315 mSource->start();
Andreas Huberf9334412010-12-15 15:17:42 -0800316
317 mRenderer = new Renderer(
318 mAudioSink,
319 new AMessage(kWhatRendererNotify, id()));
320
321 looper()->registerHandler(mRenderer);
322
Andreas Huber1aef2112011-01-04 14:01:29 -0800323 postScanSources();
Andreas Huberf9334412010-12-15 15:17:42 -0800324 break;
325 }
326
327 case kWhatScanSources:
328 {
Andreas Huber1aef2112011-01-04 14:01:29 -0800329 int32_t generation;
330 CHECK(msg->findInt32("generation", &generation));
331 if (generation != mScanSourcesGeneration) {
332 // Drop obsolete msg.
333 break;
334 }
335
Andreas Huber5bc087c2010-12-23 10:27:40 -0800336 mScanSourcesPending = false;
337
Steve Block3856b092011-10-20 11:56:00 +0100338 ALOGV("scanning sources haveAudio=%d, haveVideo=%d",
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800339 mAudioDecoder != NULL, mVideoDecoder != NULL);
340
Andreas Huberb7c8e912012-11-27 15:02:53 -0800341 bool mHadAnySourcesBefore =
342 (mAudioDecoder != NULL) || (mVideoDecoder != NULL);
343
Haynes Mathew George5d246ef2012-07-09 10:36:57 -0700344 if (mNativeWindow != NULL) {
345 instantiateDecoder(false, &mVideoDecoder);
346 }
Andreas Huberf9334412010-12-15 15:17:42 -0800347
348 if (mAudioSink != NULL) {
Andreas Huber5bc087c2010-12-23 10:27:40 -0800349 instantiateDecoder(true, &mAudioDecoder);
Andreas Huberf9334412010-12-15 15:17:42 -0800350 }
351
Andreas Huberb7c8e912012-11-27 15:02:53 -0800352 if (!mHadAnySourcesBefore
353 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
354 // This is the first time we've found anything playable.
355
356 uint32_t flags = mSource->flags();
357
358 if (flags & Source::FLAG_DYNAMIC_DURATION) {
359 schedulePollDuration();
360 }
361 }
362
Andreas Hubereac68ba2011-09-27 12:12:25 -0700363 status_t err;
364 if ((err = mSource->feedMoreTSData()) != OK) {
Andreas Huber1aef2112011-01-04 14:01:29 -0800365 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
366 // We're not currently decoding anything (no audio or
367 // video tracks found) and we just ran out of input data.
Andreas Hubereac68ba2011-09-27 12:12:25 -0700368
369 if (err == ERROR_END_OF_STREAM) {
370 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
371 } else {
372 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
373 }
Andreas Huber1aef2112011-01-04 14:01:29 -0800374 }
Andreas Huberf9334412010-12-15 15:17:42 -0800375 break;
376 }
377
Andreas Huberfbe9d812012-08-31 14:05:27 -0700378 if ((mAudioDecoder == NULL && mAudioSink != NULL)
379 || (mVideoDecoder == NULL && mNativeWindow != NULL)) {
Andreas Huberf9334412010-12-15 15:17:42 -0800380 msg->post(100000ll);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800381 mScanSourcesPending = true;
Andreas Huberf9334412010-12-15 15:17:42 -0800382 }
383 break;
384 }
385
386 case kWhatVideoNotify:
387 case kWhatAudioNotify:
388 {
389 bool audio = msg->what() == kWhatAudioNotify;
390
391 sp<AMessage> codecRequest;
392 CHECK(msg->findMessage("codec-request", &codecRequest));
393
394 int32_t what;
395 CHECK(codecRequest->findInt32("what", &what));
396
397 if (what == ACodec::kWhatFillThisBuffer) {
398 status_t err = feedDecoderInputData(
399 audio, codecRequest);
400
Andreas Huber5bc087c2010-12-23 10:27:40 -0800401 if (err == -EWOULDBLOCK) {
Andreas Hubereac68ba2011-09-27 12:12:25 -0700402 if (mSource->feedMoreTSData() == OK) {
Andreas Huber1183a4a2011-11-03 11:00:21 -0700403 msg->post(10000ll);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800404 }
Andreas Huberf9334412010-12-15 15:17:42 -0800405 }
406 } else if (what == ACodec::kWhatEOS) {
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700407 int32_t err;
408 CHECK(codecRequest->findInt32("err", &err));
409
410 if (err == ERROR_END_OF_STREAM) {
Steve Block3856b092011-10-20 11:56:00 +0100411 ALOGV("got %s decoder EOS", audio ? "audio" : "video");
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700412 } else {
Steve Block3856b092011-10-20 11:56:00 +0100413 ALOGV("got %s decoder EOS w/ error %d",
Andreas Huberdc9bacd2011-09-26 10:53:29 -0700414 audio ? "audio" : "video",
415 err);
416 }
417
418 mRenderer->queueEOS(audio, err);
Andreas Huberf9334412010-12-15 15:17:42 -0800419 } else if (what == ACodec::kWhatFlushCompleted) {
Andreas Huber1aef2112011-01-04 14:01:29 -0800420 bool needShutdown;
Andreas Huber53df1a42010-12-22 10:03:04 -0800421
Andreas Huberf9334412010-12-15 15:17:42 -0800422 if (audio) {
Andreas Huber1aef2112011-01-04 14:01:29 -0800423 CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
Andreas Huberf9334412010-12-15 15:17:42 -0800424 mFlushingAudio = FLUSHED;
425 } else {
Andreas Huber1aef2112011-01-04 14:01:29 -0800426 CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
Andreas Huberf9334412010-12-15 15:17:42 -0800427 mFlushingVideo = FLUSHED;
Andreas Huber3fe62152011-09-16 15:09:22 -0700428
429 mVideoLateByUs = 0;
Andreas Huberf9334412010-12-15 15:17:42 -0800430 }
431
Steve Block3856b092011-10-20 11:56:00 +0100432 ALOGV("decoder %s flush completed", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800433
Andreas Huber1aef2112011-01-04 14:01:29 -0800434 if (needShutdown) {
Steve Block3856b092011-10-20 11:56:00 +0100435 ALOGV("initiating %s decoder shutdown",
Andreas Huber53df1a42010-12-22 10:03:04 -0800436 audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800437
Andreas Huber53df1a42010-12-22 10:03:04 -0800438 (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
Andreas Huberf9334412010-12-15 15:17:42 -0800439
Andreas Huber53df1a42010-12-22 10:03:04 -0800440 if (audio) {
441 mFlushingAudio = SHUTTING_DOWN_DECODER;
442 } else {
443 mFlushingVideo = SHUTTING_DOWN_DECODER;
444 }
Andreas Huberf9334412010-12-15 15:17:42 -0800445 }
Andreas Huber3831a062010-12-21 10:22:33 -0800446
447 finishFlushIfPossible();
Andreas Huber2c2814b2010-12-15 17:18:20 -0800448 } else if (what == ACodec::kWhatOutputFormatChanged) {
Andreas Huber31e25082011-01-10 10:38:31 -0800449 if (audio) {
450 int32_t numChannels;
451 CHECK(codecRequest->findInt32("channel-count", &numChannels));
Andreas Huber2c2814b2010-12-15 17:18:20 -0800452
Andreas Huber31e25082011-01-10 10:38:31 -0800453 int32_t sampleRate;
454 CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
Andreas Huber2c2814b2010-12-15 17:18:20 -0800455
Steve Block3856b092011-10-20 11:56:00 +0100456 ALOGV("Audio output format changed to %d Hz, %d channels",
Andreas Huber31e25082011-01-10 10:38:31 -0800457 sampleRate, numChannels);
Andreas Huber2c2814b2010-12-15 17:18:20 -0800458
Andreas Huber31e25082011-01-10 10:38:31 -0800459 mAudioSink->close();
Eric Laurent1948eb32012-04-13 16:50:19 -0700460
461 audio_output_flags_t flags;
462 int64_t durationUs;
463 // FIXME: we should handle the case where the video decoder is created after
464 // we receive the format change indication. Current code will just make that
465 // we select deep buffer with video which should not be a problem as it should
466 // not prevent from keeping A/V sync.
467 if (mVideoDecoder == NULL &&
468 mSource->getDuration(&durationUs) == OK &&
469 durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
470 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
471 } else {
472 flags = AUDIO_OUTPUT_FLAG_NONE;
473 }
474
Andreas Huber98065552012-05-03 11:33:01 -0700475 int32_t channelMask;
476 if (!codecRequest->findInt32("channel-mask", &channelMask)) {
477 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
478 }
479
Andreas Huber078cfcf2011-09-15 12:25:04 -0700480 CHECK_EQ(mAudioSink->open(
481 sampleRate,
482 numChannels,
Andreas Huber98065552012-05-03 11:33:01 -0700483 (audio_channel_mask_t)channelMask,
Andreas Huber078cfcf2011-09-15 12:25:04 -0700484 AUDIO_FORMAT_PCM_16_BIT,
Eric Laurent1948eb32012-04-13 16:50:19 -0700485 8 /* bufferCount */,
486 NULL,
487 NULL,
488 flags),
Andreas Huber078cfcf2011-09-15 12:25:04 -0700489 (status_t)OK);
Andreas Huber31e25082011-01-10 10:38:31 -0800490 mAudioSink->start();
Andreas Huber2c2814b2010-12-15 17:18:20 -0800491
Andreas Huber31e25082011-01-10 10:38:31 -0800492 mRenderer->signalAudioSinkChanged();
493 } else {
494 // video
Andreas Huber3831a062010-12-21 10:22:33 -0800495
Andreas Huber31e25082011-01-10 10:38:31 -0800496 int32_t width, height;
497 CHECK(codecRequest->findInt32("width", &width));
498 CHECK(codecRequest->findInt32("height", &height));
499
500 int32_t cropLeft, cropTop, cropRight, cropBottom;
501 CHECK(codecRequest->findRect(
502 "crop",
503 &cropLeft, &cropTop, &cropRight, &cropBottom));
504
Steve Block3856b092011-10-20 11:56:00 +0100505 ALOGV("Video output format changed to %d x %d "
Andreas Hubercb67cd12011-08-26 16:02:19 -0700506 "(crop: %d x %d @ (%d, %d))",
Andreas Huber31e25082011-01-10 10:38:31 -0800507 width, height,
Andreas Hubercb67cd12011-08-26 16:02:19 -0700508 (cropRight - cropLeft + 1),
509 (cropBottom - cropTop + 1),
510 cropLeft, cropTop);
Andreas Huber31e25082011-01-10 10:38:31 -0800511
512 notifyListener(
513 MEDIA_SET_VIDEO_SIZE,
514 cropRight - cropLeft + 1,
515 cropBottom - cropTop + 1);
516 }
Andreas Huber3831a062010-12-21 10:22:33 -0800517 } else if (what == ACodec::kWhatShutdownCompleted) {
Steve Block3856b092011-10-20 11:56:00 +0100518 ALOGV("%s shutdown completed", audio ? "audio" : "video");
Andreas Huber3831a062010-12-21 10:22:33 -0800519 if (audio) {
520 mAudioDecoder.clear();
521
522 CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
523 mFlushingAudio = SHUT_DOWN;
524 } else {
525 mVideoDecoder.clear();
526
527 CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
528 mFlushingVideo = SHUT_DOWN;
529 }
530
531 finishFlushIfPossible();
Andreas Huberc92fd242011-08-16 13:48:44 -0700532 } else if (what == ACodec::kWhatError) {
Steve Block29357bc2012-01-06 19:20:56 +0000533 ALOGE("Received error from %s decoder, aborting playback.",
Andreas Huberc92fd242011-08-16 13:48:44 -0700534 audio ? "audio" : "video");
535
536 mRenderer->queueEOS(audio, UNKNOWN_ERROR);
Andreas Huber57788222012-02-21 11:47:18 -0800537 } else if (what == ACodec::kWhatDrainThisBuffer) {
Andreas Huberf9334412010-12-15 15:17:42 -0800538 renderBuffer(audio, codecRequest);
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800539 } else if (what != ACodec::kWhatComponentAllocated
540 && what != ACodec::kWhatComponentConfigured
541 && what != ACodec::kWhatBuffersAllocated) {
542 ALOGV("Unhandled codec notification %d '%c%c%c%c'.",
543 what,
544 what >> 24,
545 (what >> 16) & 0xff,
546 (what >> 8) & 0xff,
547 what & 0xff);
Andreas Huberf9334412010-12-15 15:17:42 -0800548 }
549
550 break;
551 }
552
553 case kWhatRendererNotify:
554 {
555 int32_t what;
556 CHECK(msg->findInt32("what", &what));
557
558 if (what == Renderer::kWhatEOS) {
559 int32_t audio;
560 CHECK(msg->findInt32("audio", &audio));
561
Andreas Huberc92fd242011-08-16 13:48:44 -0700562 int32_t finalResult;
563 CHECK(msg->findInt32("finalResult", &finalResult));
564
Andreas Huberf9334412010-12-15 15:17:42 -0800565 if (audio) {
566 mAudioEOS = true;
567 } else {
568 mVideoEOS = true;
569 }
570
Andreas Huberc92fd242011-08-16 13:48:44 -0700571 if (finalResult == ERROR_END_OF_STREAM) {
Steve Block3856b092011-10-20 11:56:00 +0100572 ALOGV("reached %s EOS", audio ? "audio" : "video");
Andreas Huberc92fd242011-08-16 13:48:44 -0700573 } else {
Steve Block29357bc2012-01-06 19:20:56 +0000574 ALOGE("%s track encountered an error (%d)",
Andreas Huberc92fd242011-08-16 13:48:44 -0700575 audio ? "audio" : "video", finalResult);
576
577 notifyListener(
578 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult);
579 }
Andreas Huberf9334412010-12-15 15:17:42 -0800580
581 if ((mAudioEOS || mAudioDecoder == NULL)
582 && (mVideoEOS || mVideoDecoder == NULL)) {
583 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
584 }
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800585 } else if (what == Renderer::kWhatPosition) {
586 int64_t positionUs;
587 CHECK(msg->findInt64("positionUs", &positionUs));
588
Andreas Huber3fe62152011-09-16 15:09:22 -0700589 CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs));
590
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800591 if (mDriver != NULL) {
592 sp<NuPlayerDriver> driver = mDriver.promote();
593 if (driver != NULL) {
594 driver->notifyPosition(positionUs);
Andreas Huber3fe62152011-09-16 15:09:22 -0700595
596 driver->notifyFrameStats(
597 mNumFramesTotal, mNumFramesDropped);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800598 }
599 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700600 } else if (what == Renderer::kWhatFlushComplete) {
Andreas Huberf9334412010-12-15 15:17:42 -0800601 int32_t audio;
602 CHECK(msg->findInt32("audio", &audio));
603
Steve Block3856b092011-10-20 11:56:00 +0100604 ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
James Dongf57b4ea2012-07-20 13:38:36 -0700605 } else if (what == Renderer::kWhatVideoRenderingStart) {
606 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
Andreas Huberf9334412010-12-15 15:17:42 -0800607 }
608 break;
609 }
610
611 case kWhatMoreDataQueued:
612 {
613 break;
614 }
615
Andreas Huber1aef2112011-01-04 14:01:29 -0800616 case kWhatReset:
617 {
Steve Block3856b092011-10-20 11:56:00 +0100618 ALOGV("kWhatReset");
Andreas Huber1aef2112011-01-04 14:01:29 -0800619
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800620 mDeferredActions.push_back(
621 new SimpleAction(&NuPlayer::performDecoderShutdown));
Andreas Huberb7c8e912012-11-27 15:02:53 -0800622
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800623 mDeferredActions.push_back(
624 new SimpleAction(&NuPlayer::performReset));
Andreas Huberb58ce9f2011-11-28 16:27:35 -0800625
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800626 processDeferredActions();
Andreas Huber1aef2112011-01-04 14:01:29 -0800627 break;
628 }
629
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800630 case kWhatSeek:
631 {
632 int64_t seekTimeUs;
633 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
634
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800635 ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs);
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800636
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800637 mDeferredActions.push_back(
638 new SimpleAction(&NuPlayer::performDecoderFlush));
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800639
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800640 mDeferredActions.push_back(new SeekAction(seekTimeUs));
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800641
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800642 processDeferredActions();
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800643 break;
644 }
645
Andreas Huberb4082222011-01-20 15:23:04 -0800646 case kWhatPause:
647 {
648 CHECK(mRenderer != NULL);
649 mRenderer->pause();
650 break;
651 }
652
653 case kWhatResume:
654 {
655 CHECK(mRenderer != NULL);
656 mRenderer->resume();
657 break;
658 }
659
Andreas Huberf9334412010-12-15 15:17:42 -0800660 default:
661 TRESPASS();
662 break;
663 }
664}
665
Andreas Huber3831a062010-12-21 10:22:33 -0800666void NuPlayer::finishFlushIfPossible() {
667 if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
668 return;
669 }
670
671 if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
672 return;
673 }
674
Steve Block3856b092011-10-20 11:56:00 +0100675 ALOGV("both audio and video are flushed now.");
Andreas Huber3831a062010-12-21 10:22:33 -0800676
Andreas Huber6e3d3112011-11-28 12:36:11 -0800677 if (mTimeDiscontinuityPending) {
678 mRenderer->signalTimeDiscontinuity();
679 mTimeDiscontinuityPending = false;
680 }
Andreas Huber3831a062010-12-21 10:22:33 -0800681
Andreas Huber22fc52f2011-01-05 16:24:27 -0800682 if (mAudioDecoder != NULL) {
Andreas Huber3831a062010-12-21 10:22:33 -0800683 mAudioDecoder->signalResume();
684 }
685
Andreas Huber22fc52f2011-01-05 16:24:27 -0800686 if (mVideoDecoder != NULL) {
Andreas Huber3831a062010-12-21 10:22:33 -0800687 mVideoDecoder->signalResume();
688 }
689
690 mFlushingAudio = NONE;
691 mFlushingVideo = NONE;
Andreas Huber3831a062010-12-21 10:22:33 -0800692
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800693 processDeferredActions();
Andreas Huber1aef2112011-01-04 14:01:29 -0800694}
695
696void NuPlayer::postScanSources() {
697 if (mScanSourcesPending) {
698 return;
699 }
700
701 sp<AMessage> msg = new AMessage(kWhatScanSources, id());
702 msg->setInt32("generation", mScanSourcesGeneration);
703 msg->post();
704
705 mScanSourcesPending = true;
706}
707
Andreas Huber5bc087c2010-12-23 10:27:40 -0800708status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
Andreas Huberf9334412010-12-15 15:17:42 -0800709 if (*decoder != NULL) {
710 return OK;
711 }
712
Andreas Huber84066782011-08-16 09:34:26 -0700713 sp<AMessage> format = mSource->getFormat(audio);
Andreas Huberf9334412010-12-15 15:17:42 -0800714
Andreas Huber84066782011-08-16 09:34:26 -0700715 if (format == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -0800716 return -EWOULDBLOCK;
717 }
718
Andreas Huber3fe62152011-09-16 15:09:22 -0700719 if (!audio) {
Andreas Huber84066782011-08-16 09:34:26 -0700720 AString mime;
721 CHECK(format->findString("mime", &mime));
722 mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
Andreas Huber3fe62152011-09-16 15:09:22 -0700723 }
724
Andreas Huberf9334412010-12-15 15:17:42 -0800725 sp<AMessage> notify =
726 new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
727 id());
728
Glenn Kasten11731182011-02-08 17:26:17 -0800729 *decoder = audio ? new Decoder(notify) :
730 new Decoder(notify, mNativeWindow);
Andreas Huberf9334412010-12-15 15:17:42 -0800731 looper()->registerHandler(*decoder);
732
Andreas Huber84066782011-08-16 09:34:26 -0700733 (*decoder)->configure(format);
Andreas Huberf9334412010-12-15 15:17:42 -0800734
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800735 int64_t durationUs;
736 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
737 sp<NuPlayerDriver> driver = mDriver.promote();
738 if (driver != NULL) {
739 driver->notifyDuration(durationUs);
740 }
741 }
742
Andreas Huberf9334412010-12-15 15:17:42 -0800743 return OK;
744}
745
746status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
747 sp<AMessage> reply;
748 CHECK(msg->findMessage("reply", &reply));
749
Andreas Huber53df1a42010-12-22 10:03:04 -0800750 if ((audio && IsFlushingState(mFlushingAudio))
751 || (!audio && IsFlushingState(mFlushingVideo))) {
Andreas Huberf9334412010-12-15 15:17:42 -0800752 reply->setInt32("err", INFO_DISCONTINUITY);
753 reply->post();
754 return OK;
755 }
756
757 sp<ABuffer> accessUnit;
Andreas Huberf9334412010-12-15 15:17:42 -0800758
Andreas Huber3fe62152011-09-16 15:09:22 -0700759 bool dropAccessUnit;
760 do {
761 status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
Andreas Huber5bc087c2010-12-23 10:27:40 -0800762
Andreas Huber3fe62152011-09-16 15:09:22 -0700763 if (err == -EWOULDBLOCK) {
764 return err;
765 } else if (err != OK) {
766 if (err == INFO_DISCONTINUITY) {
767 int32_t type;
768 CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
Andreas Huber53df1a42010-12-22 10:03:04 -0800769
Andreas Huber3fe62152011-09-16 15:09:22 -0700770 bool formatChange =
Andreas Huber6e3d3112011-11-28 12:36:11 -0800771 (audio &&
772 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
773 || (!audio &&
774 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
Andreas Huber53df1a42010-12-22 10:03:04 -0800775
Andreas Huber6e3d3112011-11-28 12:36:11 -0800776 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
777
Steve Blockdf64d152012-01-04 20:05:49 +0000778 ALOGI("%s discontinuity (formatChange=%d, time=%d)",
Andreas Huber6e3d3112011-11-28 12:36:11 -0800779 audio ? "audio" : "video", formatChange, timeChange);
Andreas Huber32f3cef2011-03-02 15:34:46 -0800780
Andreas Huber3fe62152011-09-16 15:09:22 -0700781 if (audio) {
782 mSkipRenderingAudioUntilMediaTimeUs = -1;
783 } else {
784 mSkipRenderingVideoUntilMediaTimeUs = -1;
785 }
Andreas Huber32f3cef2011-03-02 15:34:46 -0800786
Andreas Huber6e3d3112011-11-28 12:36:11 -0800787 if (timeChange) {
788 sp<AMessage> extra;
789 if (accessUnit->meta()->findMessage("extra", &extra)
790 && extra != NULL) {
791 int64_t resumeAtMediaTimeUs;
792 if (extra->findInt64(
793 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
Steve Blockdf64d152012-01-04 20:05:49 +0000794 ALOGI("suppressing rendering of %s until %lld us",
Andreas Huber6e3d3112011-11-28 12:36:11 -0800795 audio ? "audio" : "video", resumeAtMediaTimeUs);
Andreas Huber3fe62152011-09-16 15:09:22 -0700796
Andreas Huber6e3d3112011-11-28 12:36:11 -0800797 if (audio) {
798 mSkipRenderingAudioUntilMediaTimeUs =
799 resumeAtMediaTimeUs;
800 } else {
801 mSkipRenderingVideoUntilMediaTimeUs =
802 resumeAtMediaTimeUs;
803 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700804 }
Andreas Huber32f3cef2011-03-02 15:34:46 -0800805 }
806 }
Andreas Huber3fe62152011-09-16 15:09:22 -0700807
Andreas Huber6e3d3112011-11-28 12:36:11 -0800808 mTimeDiscontinuityPending =
809 mTimeDiscontinuityPending || timeChange;
810
811 if (formatChange || timeChange) {
Andreas Hubera1f8ab02012-11-30 10:53:22 -0800812 if (mFlushingAudio == NONE && mFlushingVideo == NONE) {
813 // And we'll resume scanning sources once we're done
814 // flushing.
815 mDeferredActions.push_front(
816 new SimpleAction(
817 &NuPlayer::performScanSources));
818 }
819
Andreas Huber6e3d3112011-11-28 12:36:11 -0800820 flushDecoder(audio, formatChange);
821 } else {
822 // This stream is unaffected by the discontinuity
823
824 if (audio) {
825 mFlushingAudio = FLUSHED;
826 } else {
827 mFlushingVideo = FLUSHED;
828 }
829
830 finishFlushIfPossible();
831
832 return -EWOULDBLOCK;
833 }
Andreas Huber32f3cef2011-03-02 15:34:46 -0800834 }
835
Andreas Huber3fe62152011-09-16 15:09:22 -0700836 reply->setInt32("err", err);
837 reply->post();
838 return OK;
Andreas Huberf9334412010-12-15 15:17:42 -0800839 }
840
Andreas Huber3fe62152011-09-16 15:09:22 -0700841 if (!audio) {
842 ++mNumFramesTotal;
843 }
844
845 dropAccessUnit = false;
846 if (!audio
847 && mVideoLateByUs > 100000ll
848 && mVideoIsAVC
849 && !IsAVCReferenceFrame(accessUnit)) {
850 dropAccessUnit = true;
851 ++mNumFramesDropped;
852 }
853 } while (dropAccessUnit);
Andreas Huberf9334412010-12-15 15:17:42 -0800854
Steve Block3856b092011-10-20 11:56:00 +0100855 // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800856
857#if 0
858 int64_t mediaTimeUs;
859 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
Steve Block3856b092011-10-20 11:56:00 +0100860 ALOGV("feeding %s input buffer at media time %.2f secs",
Andreas Huberf9334412010-12-15 15:17:42 -0800861 audio ? "audio" : "video",
862 mediaTimeUs / 1E6);
863#endif
864
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800865 reply->setBuffer("buffer", accessUnit);
Andreas Huberf9334412010-12-15 15:17:42 -0800866 reply->post();
867
868 return OK;
869}
870
871void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
Steve Block3856b092011-10-20 11:56:00 +0100872 // ALOGV("renderBuffer %s", audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800873
874 sp<AMessage> reply;
875 CHECK(msg->findMessage("reply", &reply));
876
Andreas Huber18ac5402011-08-31 15:04:25 -0700877 if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) {
878 // We're currently attempting to flush the decoder, in order
879 // to complete this, the decoder wants all its buffers back,
880 // so we don't want any output buffers it sent us (from before
881 // we initiated the flush) to be stuck in the renderer's queue.
882
Steve Block3856b092011-10-20 11:56:00 +0100883 ALOGV("we're still flushing the %s decoder, sending its output buffer"
Andreas Huber18ac5402011-08-31 15:04:25 -0700884 " right back.", audio ? "audio" : "video");
885
886 reply->post();
887 return;
888 }
889
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800890 sp<ABuffer> buffer;
891 CHECK(msg->findBuffer("buffer", &buffer));
Andreas Huberf9334412010-12-15 15:17:42 -0800892
Andreas Huber32f3cef2011-03-02 15:34:46 -0800893 int64_t &skipUntilMediaTimeUs =
894 audio
895 ? mSkipRenderingAudioUntilMediaTimeUs
896 : mSkipRenderingVideoUntilMediaTimeUs;
897
898 if (skipUntilMediaTimeUs >= 0) {
899 int64_t mediaTimeUs;
900 CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs));
901
902 if (mediaTimeUs < skipUntilMediaTimeUs) {
Steve Block3856b092011-10-20 11:56:00 +0100903 ALOGV("dropping %s buffer at time %lld as requested.",
Andreas Huber32f3cef2011-03-02 15:34:46 -0800904 audio ? "audio" : "video",
905 mediaTimeUs);
906
907 reply->post();
908 return;
909 }
910
911 skipUntilMediaTimeUs = -1;
912 }
913
Andreas Huberf9334412010-12-15 15:17:42 -0800914 mRenderer->queueBuffer(audio, buffer, reply);
915}
916
917void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800918 if (mDriver == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -0800919 return;
920 }
921
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800922 sp<NuPlayerDriver> driver = mDriver.promote();
Andreas Huberf9334412010-12-15 15:17:42 -0800923
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800924 if (driver == NULL) {
Andreas Huberf9334412010-12-15 15:17:42 -0800925 return;
926 }
927
Andreas Hubera4af2142011-10-26 15:23:31 -0700928 driver->notifyListener(msg, ext1, ext2);
Andreas Huberf9334412010-12-15 15:17:42 -0800929}
930
Andreas Huber1aef2112011-01-04 14:01:29 -0800931void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
Andreas Huber6e3d3112011-11-28 12:36:11 -0800932 if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
Steve Blockdf64d152012-01-04 20:05:49 +0000933 ALOGI("flushDecoder %s without decoder present",
Andreas Huber6e3d3112011-11-28 12:36:11 -0800934 audio ? "audio" : "video");
935 }
936
Andreas Huber1aef2112011-01-04 14:01:29 -0800937 // Make sure we don't continue to scan sources until we finish flushing.
938 ++mScanSourcesGeneration;
Andreas Huber43c3e6c2011-01-05 12:17:08 -0800939 mScanSourcesPending = false;
Andreas Huber1aef2112011-01-04 14:01:29 -0800940
941 (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
942 mRenderer->flush(audio);
943
944 FlushStatus newStatus =
945 needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
946
947 if (audio) {
948 CHECK(mFlushingAudio == NONE
949 || mFlushingAudio == AWAITING_DISCONTINUITY);
950
951 mFlushingAudio = newStatus;
952
953 if (mFlushingVideo == NONE) {
954 mFlushingVideo = (mVideoDecoder != NULL)
955 ? AWAITING_DISCONTINUITY
956 : FLUSHED;
957 }
958 } else {
959 CHECK(mFlushingVideo == NONE
960 || mFlushingVideo == AWAITING_DISCONTINUITY);
961
962 mFlushingVideo = newStatus;
963
964 if (mFlushingAudio == NONE) {
965 mFlushingAudio = (mAudioDecoder != NULL)
966 ? AWAITING_DISCONTINUITY
967 : FLUSHED;
968 }
969 }
970}
971
Andreas Huber84066782011-08-16 09:34:26 -0700972sp<AMessage> NuPlayer::Source::getFormat(bool audio) {
973 sp<MetaData> meta = getFormatMeta(audio);
974
975 if (meta == NULL) {
976 return NULL;
977 }
978
979 sp<AMessage> msg = new AMessage;
980
981 if(convertMetaDataToMessage(meta, &msg) == OK) {
982 return msg;
983 }
984 return NULL;
985}
986
James Dong0d268a32012-08-31 12:18:27 -0700987status_t NuPlayer::setVideoScalingMode(int32_t mode) {
988 mVideoScalingMode = mode;
James Dong376074e2012-09-14 15:34:35 -0700989 if (mNativeWindow != NULL
990 && mNativeWindow->getNativeWindow() != NULL) {
James Dong0d268a32012-08-31 12:18:27 -0700991 status_t ret = native_window_set_scaling_mode(
992 mNativeWindow->getNativeWindow().get(), mVideoScalingMode);
993 if (ret != OK) {
994 ALOGE("Failed to set scaling mode (%d): %s",
995 -ret, strerror(-ret));
996 return ret;
997 }
998 }
999 return OK;
1000}
1001
Andreas Huberb7c8e912012-11-27 15:02:53 -08001002void NuPlayer::schedulePollDuration() {
1003 sp<AMessage> msg = new AMessage(kWhatPollDuration, id());
1004 msg->setInt32("generation", mPollDurationGeneration);
1005 msg->post();
1006}
1007
1008void NuPlayer::cancelPollDuration() {
1009 ++mPollDurationGeneration;
1010}
1011
Andreas Hubera1f8ab02012-11-30 10:53:22 -08001012void NuPlayer::processDeferredActions() {
1013 while (!mDeferredActions.empty()) {
1014 // We won't execute any deferred actions until we're no longer in
1015 // an intermediate state, i.e. one more more decoders are currently
1016 // flushing or shutting down.
1017
1018 if (mRenderer != NULL) {
1019 // There's an edge case where the renderer owns all output
1020 // buffers and is paused, therefore the decoder will not read
1021 // more input data and will never encounter the matching
1022 // discontinuity. To avoid this, we resume the renderer.
1023
1024 if (mFlushingAudio == AWAITING_DISCONTINUITY
1025 || mFlushingVideo == AWAITING_DISCONTINUITY) {
1026 mRenderer->resume();
1027 }
1028 }
1029
1030 if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
1031 // We're currently flushing, postpone the reset until that's
1032 // completed.
1033
1034 ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d",
1035 mFlushingAudio, mFlushingVideo);
1036
1037 break;
1038 }
1039
1040 sp<Action> action = *mDeferredActions.begin();
1041 mDeferredActions.erase(mDeferredActions.begin());
1042
1043 action->execute(this);
1044 }
1045}
1046
1047void NuPlayer::performSeek(int64_t seekTimeUs) {
1048 ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)",
1049 seekTimeUs,
1050 seekTimeUs / 1E6);
1051
1052 mSource->seekTo(seekTimeUs);
1053
1054 if (mDriver != NULL) {
1055 sp<NuPlayerDriver> driver = mDriver.promote();
1056 if (driver != NULL) {
1057 driver->notifyPosition(seekTimeUs);
1058 driver->notifySeekComplete();
1059 }
1060 }
1061
1062 // everything's flushed, continue playback.
1063}
1064
1065void NuPlayer::performDecoderFlush() {
1066 ALOGV("performDecoderFlush");
1067
1068 if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
1069 return;
1070 }
1071
1072 mTimeDiscontinuityPending = true;
1073
1074 if (mAudioDecoder != NULL) {
1075 flushDecoder(true /* audio */, false /* needShutdown */);
1076 }
1077
1078 if (mVideoDecoder != NULL) {
1079 flushDecoder(false /* audio */, false /* needShutdown */);
1080 }
1081}
1082
1083void NuPlayer::performDecoderShutdown() {
1084 ALOGV("performDecoderShutdown");
1085
1086 if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
1087 return;
1088 }
1089
1090 mTimeDiscontinuityPending = true;
1091
1092 if (mAudioDecoder != NULL) {
1093 flushDecoder(true /* audio */, true /* needShutdown */);
1094 }
1095
1096 if (mVideoDecoder != NULL) {
1097 flushDecoder(false /* audio */, true /* needShutdown */);
1098 }
1099}
1100
1101void NuPlayer::performReset() {
1102 ALOGV("performReset");
1103
1104 CHECK(mAudioDecoder == NULL);
1105 CHECK(mVideoDecoder == NULL);
1106
1107 cancelPollDuration();
1108
1109 ++mScanSourcesGeneration;
1110 mScanSourcesPending = false;
1111
1112 mRenderer.clear();
1113
1114 if (mSource != NULL) {
1115 mSource->stop();
1116 mSource.clear();
1117 }
1118
1119 if (mDriver != NULL) {
1120 sp<NuPlayerDriver> driver = mDriver.promote();
1121 if (driver != NULL) {
1122 driver->notifyResetComplete();
1123 }
1124 }
1125}
1126
1127void NuPlayer::performScanSources() {
1128 ALOGV("performScanSources");
1129
1130 if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
1131 postScanSources();
1132 }
1133}
1134
Andreas Huberf9334412010-12-15 15:17:42 -08001135} // namespace android