blob: 9ef9237995c8e775a4d755e25fa57a9712e8c8c2 [file] [log] [blame]
Andreas Hubera1587462010-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 Huber54e66492010-12-23 10:27:40 -080022
23#include "HTTPLiveSource.h"
Andreas Hubera1587462010-12-15 15:17:42 -080024#include "NuPlayerDecoder.h"
Andreas Huber08e10cb2011-01-05 12:17:08 -080025#include "NuPlayerDriver.h"
Andreas Hubera1587462010-12-15 15:17:42 -080026#include "NuPlayerRenderer.h"
Andreas Huber54e66492010-12-23 10:27:40 -080027#include "NuPlayerSource.h"
Andreas Hubera6be6dc2011-10-11 15:24:07 -070028#include "RTSPSource.h"
Andreas Huber54e66492010-12-23 10:27:40 -080029#include "StreamingSource.h"
30
31#include "ATSParser.h"
Andreas Hubera1587462010-12-15 15:17:42 -080032
Andreas Huber41c3f742010-12-21 10:22:33 -080033#include <media/stagefright/foundation/hexdump.h>
Andreas Hubera1587462010-12-15 15:17:42 -080034#include <media/stagefright/foundation/ABuffer.h>
35#include <media/stagefright/foundation/ADebug.h>
36#include <media/stagefright/foundation/AMessage.h>
37#include <media/stagefright/ACodec.h>
Andreas Huber950fc9d2011-09-16 15:09:22 -070038#include <media/stagefright/MediaDefs.h>
Andreas Hubera1587462010-12-15 15:17:42 -080039#include <media/stagefright/MediaErrors.h>
40#include <media/stagefright/MetaData.h>
41#include <surfaceflinger/Surface.h>
Glenn Kastencc562a32011-02-08 17:26:17 -080042#include <gui/ISurfaceTexture.h>
Andreas Hubera1587462010-12-15 15:17:42 -080043
Andreas Huber950fc9d2011-09-16 15:09:22 -070044#include "avc_utils.h"
45
Andreas Hubera1587462010-12-15 15:17:42 -080046namespace android {
47
48////////////////////////////////////////////////////////////////////////////////
49
50NuPlayer::NuPlayer()
Andreas Huber603d7392011-06-30 15:47:02 -070051 : mUIDValid(false),
Andreas Huber950fc9d2011-09-16 15:09:22 -070052 mVideoIsAVC(false),
Andreas Huber603d7392011-06-30 15:47:02 -070053 mAudioEOS(false),
Andreas Hubera1587462010-12-15 15:17:42 -080054 mVideoEOS(false),
Andreas Huber54e66492010-12-23 10:27:40 -080055 mScanSourcesPending(false),
Andreas Hubercbeaca72011-01-04 14:01:29 -080056 mScanSourcesGeneration(0),
Andreas Huber66a051a2011-11-28 12:36:11 -080057 mTimeDiscontinuityPending(false),
Andreas Hubera1587462010-12-15 15:17:42 -080058 mFlushingAudio(NONE),
Andreas Hubercbeaca72011-01-04 14:01:29 -080059 mFlushingVideo(NONE),
60 mResetInProgress(false),
Andreas Huber950fc9d2011-09-16 15:09:22 -070061 mResetPostponed(false),
62 mSkipRenderingAudioUntilMediaTimeUs(-1ll),
63 mSkipRenderingVideoUntilMediaTimeUs(-1ll),
64 mVideoLateByUs(0ll),
65 mNumFramesTotal(0ll),
66 mNumFramesDropped(0ll) {
Andreas Hubera1587462010-12-15 15:17:42 -080067}
68
69NuPlayer::~NuPlayer() {
70}
71
Andreas Huber603d7392011-06-30 15:47:02 -070072void NuPlayer::setUID(uid_t uid) {
73 mUIDValid = true;
74 mUID = uid;
75}
76
Andreas Huber08e10cb2011-01-05 12:17:08 -080077void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
78 mDriver = driver;
Andreas Hubera1587462010-12-15 15:17:42 -080079}
80
81void NuPlayer::setDataSource(const sp<IStreamSource> &source) {
82 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
83
Andreas Huber54e66492010-12-23 10:27:40 -080084 msg->setObject("source", new StreamingSource(source));
85 msg->post();
86}
Andreas Hubera1587462010-12-15 15:17:42 -080087
Andreas Huber54e66492010-12-23 10:27:40 -080088void NuPlayer::setDataSource(
89 const char *url, const KeyedVector<String8, String8> *headers) {
90 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
91
Andreas Hubera6be6dc2011-10-11 15:24:07 -070092 if (!strncasecmp(url, "rtsp://", 7)) {
93 msg->setObject(
94 "source", new RTSPSource(url, headers, mUIDValid, mUID));
95 } else {
96 msg->setObject(
97 "source", new HTTPLiveSource(url, headers, mUIDValid, mUID));
98 }
99
Andreas Hubera1587462010-12-15 15:17:42 -0800100 msg->post();
101}
102
Glenn Kastencc562a32011-02-08 17:26:17 -0800103void NuPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
104 sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
105 sp<SurfaceTextureClient> surfaceTextureClient(surfaceTexture != NULL ?
106 new SurfaceTextureClient(surfaceTexture) : NULL);
107 msg->setObject("native-window", new NativeWindowWrapper(surfaceTextureClient));
Andreas Hubera1587462010-12-15 15:17:42 -0800108 msg->post();
109}
110
111void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) {
112 sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id());
113 msg->setObject("sink", sink);
114 msg->post();
115}
116
117void NuPlayer::start() {
118 (new AMessage(kWhatStart, id()))->post();
119}
120
Andreas Huber08e10cb2011-01-05 12:17:08 -0800121void NuPlayer::pause() {
Andreas Huber601fe0e2011-01-20 15:23:04 -0800122 (new AMessage(kWhatPause, id()))->post();
Andreas Huber08e10cb2011-01-05 12:17:08 -0800123}
124
125void NuPlayer::resume() {
Andreas Huber601fe0e2011-01-20 15:23:04 -0800126 (new AMessage(kWhatResume, id()))->post();
Andreas Huber08e10cb2011-01-05 12:17:08 -0800127}
128
Andreas Hubercbeaca72011-01-04 14:01:29 -0800129void NuPlayer::resetAsync() {
130 (new AMessage(kWhatReset, id()))->post();
131}
132
Andreas Huber08e10cb2011-01-05 12:17:08 -0800133void NuPlayer::seekToAsync(int64_t seekTimeUs) {
134 sp<AMessage> msg = new AMessage(kWhatSeek, id());
135 msg->setInt64("seekTimeUs", seekTimeUs);
136 msg->post();
137}
138
Andreas Huber222e6892010-12-22 10:03:04 -0800139// static
Andreas Hubercbeaca72011-01-04 14:01:29 -0800140bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
Andreas Huber222e6892010-12-22 10:03:04 -0800141 switch (state) {
142 case FLUSHING_DECODER:
Andreas Hubercbeaca72011-01-04 14:01:29 -0800143 if (needShutdown != NULL) {
144 *needShutdown = false;
Andreas Huber222e6892010-12-22 10:03:04 -0800145 }
146 return true;
147
Andreas Hubercbeaca72011-01-04 14:01:29 -0800148 case FLUSHING_DECODER_SHUTDOWN:
149 if (needShutdown != NULL) {
150 *needShutdown = true;
Andreas Huber222e6892010-12-22 10:03:04 -0800151 }
152 return true;
153
154 default:
155 return false;
156 }
157}
158
Andreas Hubera1587462010-12-15 15:17:42 -0800159void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
160 switch (msg->what()) {
161 case kWhatSetDataSource:
162 {
Steve Block71f2cf12011-10-20 11:56:00 +0100163 ALOGV("kWhatSetDataSource");
Andreas Hubera1587462010-12-15 15:17:42 -0800164
165 CHECK(mSource == NULL);
166
Andreas Huber54e66492010-12-23 10:27:40 -0800167 sp<RefBase> obj;
168 CHECK(msg->findObject("source", &obj));
Andreas Hubera1587462010-12-15 15:17:42 -0800169
Andreas Huber54e66492010-12-23 10:27:40 -0800170 mSource = static_cast<Source *>(obj.get());
Andreas Hubera1587462010-12-15 15:17:42 -0800171 break;
172 }
173
Glenn Kastencc562a32011-02-08 17:26:17 -0800174 case kWhatSetVideoNativeWindow:
Andreas Hubera1587462010-12-15 15:17:42 -0800175 {
Steve Block71f2cf12011-10-20 11:56:00 +0100176 ALOGV("kWhatSetVideoNativeWindow");
Andreas Hubera1587462010-12-15 15:17:42 -0800177
178 sp<RefBase> obj;
Glenn Kastencc562a32011-02-08 17:26:17 -0800179 CHECK(msg->findObject("native-window", &obj));
Andreas Hubera1587462010-12-15 15:17:42 -0800180
Glenn Kastencc562a32011-02-08 17:26:17 -0800181 mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get());
Andreas Hubera1587462010-12-15 15:17:42 -0800182 break;
183 }
184
185 case kWhatSetAudioSink:
186 {
Steve Block71f2cf12011-10-20 11:56:00 +0100187 ALOGV("kWhatSetAudioSink");
Andreas Hubera1587462010-12-15 15:17:42 -0800188
189 sp<RefBase> obj;
190 CHECK(msg->findObject("sink", &obj));
191
192 mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get());
193 break;
194 }
195
196 case kWhatStart:
197 {
Steve Block71f2cf12011-10-20 11:56:00 +0100198 ALOGV("kWhatStart");
Andreas Huber08e10cb2011-01-05 12:17:08 -0800199
Andreas Huber950fc9d2011-09-16 15:09:22 -0700200 mVideoIsAVC = false;
Andreas Hubercbeaca72011-01-04 14:01:29 -0800201 mAudioEOS = false;
202 mVideoEOS = false;
Andreas Huber669ad132011-03-02 15:34:46 -0800203 mSkipRenderingAudioUntilMediaTimeUs = -1;
204 mSkipRenderingVideoUntilMediaTimeUs = -1;
Andreas Huber950fc9d2011-09-16 15:09:22 -0700205 mVideoLateByUs = 0;
206 mNumFramesTotal = 0;
207 mNumFramesDropped = 0;
Andreas Hubercbeaca72011-01-04 14:01:29 -0800208
Andreas Huber54e66492010-12-23 10:27:40 -0800209 mSource->start();
Andreas Hubera1587462010-12-15 15:17:42 -0800210
211 mRenderer = new Renderer(
212 mAudioSink,
213 new AMessage(kWhatRendererNotify, id()));
214
215 looper()->registerHandler(mRenderer);
216
Andreas Hubercbeaca72011-01-04 14:01:29 -0800217 postScanSources();
Andreas Hubera1587462010-12-15 15:17:42 -0800218 break;
219 }
220
221 case kWhatScanSources:
222 {
Andreas Hubercbeaca72011-01-04 14:01:29 -0800223 int32_t generation;
224 CHECK(msg->findInt32("generation", &generation));
225 if (generation != mScanSourcesGeneration) {
226 // Drop obsolete msg.
227 break;
228 }
229
Andreas Huber54e66492010-12-23 10:27:40 -0800230 mScanSourcesPending = false;
231
Steve Block71f2cf12011-10-20 11:56:00 +0100232 ALOGV("scanning sources haveAudio=%d, haveVideo=%d",
Andreas Huber08e10cb2011-01-05 12:17:08 -0800233 mAudioDecoder != NULL, mVideoDecoder != NULL);
234
Andreas Huber54e66492010-12-23 10:27:40 -0800235 instantiateDecoder(false, &mVideoDecoder);
Andreas Hubera1587462010-12-15 15:17:42 -0800236
237 if (mAudioSink != NULL) {
Andreas Huber54e66492010-12-23 10:27:40 -0800238 instantiateDecoder(true, &mAudioDecoder);
Andreas Hubera1587462010-12-15 15:17:42 -0800239 }
240
Andreas Huber79226192011-09-27 12:12:25 -0700241 status_t err;
242 if ((err = mSource->feedMoreTSData()) != OK) {
Andreas Hubercbeaca72011-01-04 14:01:29 -0800243 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
244 // We're not currently decoding anything (no audio or
245 // video tracks found) and we just ran out of input data.
Andreas Huber79226192011-09-27 12:12:25 -0700246
247 if (err == ERROR_END_OF_STREAM) {
248 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
249 } else {
250 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
251 }
Andreas Hubercbeaca72011-01-04 14:01:29 -0800252 }
Andreas Hubera1587462010-12-15 15:17:42 -0800253 break;
254 }
255
Andreas Hubera1587462010-12-15 15:17:42 -0800256 if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
257 msg->post(100000ll);
Andreas Huber54e66492010-12-23 10:27:40 -0800258 mScanSourcesPending = true;
Andreas Hubera1587462010-12-15 15:17:42 -0800259 }
260 break;
261 }
262
263 case kWhatVideoNotify:
264 case kWhatAudioNotify:
265 {
266 bool audio = msg->what() == kWhatAudioNotify;
267
268 sp<AMessage> codecRequest;
269 CHECK(msg->findMessage("codec-request", &codecRequest));
270
271 int32_t what;
272 CHECK(codecRequest->findInt32("what", &what));
273
274 if (what == ACodec::kWhatFillThisBuffer) {
275 status_t err = feedDecoderInputData(
276 audio, codecRequest);
277
Andreas Huber54e66492010-12-23 10:27:40 -0800278 if (err == -EWOULDBLOCK) {
Andreas Huber79226192011-09-27 12:12:25 -0700279 if (mSource->feedMoreTSData() == OK) {
Andreas Hubere395f642011-11-03 11:00:21 -0700280 msg->post(10000ll);
Andreas Huber54e66492010-12-23 10:27:40 -0800281 }
Andreas Hubera1587462010-12-15 15:17:42 -0800282 }
283 } else if (what == ACodec::kWhatEOS) {
Andreas Huber928baf12011-09-26 10:53:29 -0700284 int32_t err;
285 CHECK(codecRequest->findInt32("err", &err));
286
287 if (err == ERROR_END_OF_STREAM) {
Steve Block71f2cf12011-10-20 11:56:00 +0100288 ALOGV("got %s decoder EOS", audio ? "audio" : "video");
Andreas Huber928baf12011-09-26 10:53:29 -0700289 } else {
Steve Block71f2cf12011-10-20 11:56:00 +0100290 ALOGV("got %s decoder EOS w/ error %d",
Andreas Huber928baf12011-09-26 10:53:29 -0700291 audio ? "audio" : "video",
292 err);
293 }
294
295 mRenderer->queueEOS(audio, err);
Andreas Hubera1587462010-12-15 15:17:42 -0800296 } else if (what == ACodec::kWhatFlushCompleted) {
Andreas Hubercbeaca72011-01-04 14:01:29 -0800297 bool needShutdown;
Andreas Huber222e6892010-12-22 10:03:04 -0800298
Andreas Hubera1587462010-12-15 15:17:42 -0800299 if (audio) {
Andreas Hubercbeaca72011-01-04 14:01:29 -0800300 CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
Andreas Hubera1587462010-12-15 15:17:42 -0800301 mFlushingAudio = FLUSHED;
302 } else {
Andreas Hubercbeaca72011-01-04 14:01:29 -0800303 CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
Andreas Hubera1587462010-12-15 15:17:42 -0800304 mFlushingVideo = FLUSHED;
Andreas Huber950fc9d2011-09-16 15:09:22 -0700305
306 mVideoLateByUs = 0;
Andreas Hubera1587462010-12-15 15:17:42 -0800307 }
308
Steve Block71f2cf12011-10-20 11:56:00 +0100309 ALOGV("decoder %s flush completed", audio ? "audio" : "video");
Andreas Hubera1587462010-12-15 15:17:42 -0800310
Andreas Hubercbeaca72011-01-04 14:01:29 -0800311 if (needShutdown) {
Steve Block71f2cf12011-10-20 11:56:00 +0100312 ALOGV("initiating %s decoder shutdown",
Andreas Huber222e6892010-12-22 10:03:04 -0800313 audio ? "audio" : "video");
Andreas Hubera1587462010-12-15 15:17:42 -0800314
Andreas Huber222e6892010-12-22 10:03:04 -0800315 (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
Andreas Hubera1587462010-12-15 15:17:42 -0800316
Andreas Huber222e6892010-12-22 10:03:04 -0800317 if (audio) {
318 mFlushingAudio = SHUTTING_DOWN_DECODER;
319 } else {
320 mFlushingVideo = SHUTTING_DOWN_DECODER;
321 }
Andreas Hubera1587462010-12-15 15:17:42 -0800322 }
Andreas Huber41c3f742010-12-21 10:22:33 -0800323
324 finishFlushIfPossible();
Andreas Huber687b32d2010-12-15 17:18:20 -0800325 } else if (what == ACodec::kWhatOutputFormatChanged) {
Andreas Huber7caa1302011-01-10 10:38:31 -0800326 if (audio) {
327 int32_t numChannels;
328 CHECK(codecRequest->findInt32("channel-count", &numChannels));
Andreas Huber687b32d2010-12-15 17:18:20 -0800329
Andreas Huber7caa1302011-01-10 10:38:31 -0800330 int32_t sampleRate;
331 CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
Andreas Huber687b32d2010-12-15 17:18:20 -0800332
Steve Block71f2cf12011-10-20 11:56:00 +0100333 ALOGV("Audio output format changed to %d Hz, %d channels",
Andreas Huber7caa1302011-01-10 10:38:31 -0800334 sampleRate, numChannels);
Andreas Huber687b32d2010-12-15 17:18:20 -0800335
Andreas Huber7caa1302011-01-10 10:38:31 -0800336 mAudioSink->close();
Andreas Huber115cac82011-09-15 12:25:04 -0700337 CHECK_EQ(mAudioSink->open(
338 sampleRate,
339 numChannels,
340 AUDIO_FORMAT_PCM_16_BIT,
341 8 /* bufferCount */),
342 (status_t)OK);
Andreas Huber7caa1302011-01-10 10:38:31 -0800343 mAudioSink->start();
Andreas Huber687b32d2010-12-15 17:18:20 -0800344
Andreas Huber7caa1302011-01-10 10:38:31 -0800345 mRenderer->signalAudioSinkChanged();
346 } else {
347 // video
Andreas Huber41c3f742010-12-21 10:22:33 -0800348
Andreas Huber7caa1302011-01-10 10:38:31 -0800349 int32_t width, height;
350 CHECK(codecRequest->findInt32("width", &width));
351 CHECK(codecRequest->findInt32("height", &height));
352
353 int32_t cropLeft, cropTop, cropRight, cropBottom;
354 CHECK(codecRequest->findRect(
355 "crop",
356 &cropLeft, &cropTop, &cropRight, &cropBottom));
357
Steve Block71f2cf12011-10-20 11:56:00 +0100358 ALOGV("Video output format changed to %d x %d "
Andreas Huber6032a602011-08-26 16:02:19 -0700359 "(crop: %d x %d @ (%d, %d))",
Andreas Huber7caa1302011-01-10 10:38:31 -0800360 width, height,
Andreas Huber6032a602011-08-26 16:02:19 -0700361 (cropRight - cropLeft + 1),
362 (cropBottom - cropTop + 1),
363 cropLeft, cropTop);
Andreas Huber7caa1302011-01-10 10:38:31 -0800364
365 notifyListener(
366 MEDIA_SET_VIDEO_SIZE,
367 cropRight - cropLeft + 1,
368 cropBottom - cropTop + 1);
369 }
Andreas Huber41c3f742010-12-21 10:22:33 -0800370 } else if (what == ACodec::kWhatShutdownCompleted) {
Steve Block71f2cf12011-10-20 11:56:00 +0100371 ALOGV("%s shutdown completed", audio ? "audio" : "video");
Andreas Huber41c3f742010-12-21 10:22:33 -0800372 if (audio) {
373 mAudioDecoder.clear();
374
375 CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
376 mFlushingAudio = SHUT_DOWN;
377 } else {
378 mVideoDecoder.clear();
379
380 CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
381 mFlushingVideo = SHUT_DOWN;
382 }
383
384 finishFlushIfPossible();
Andreas Huberd84fd792011-08-16 13:48:44 -0700385 } else if (what == ACodec::kWhatError) {
386 LOGE("Received error from %s decoder, aborting playback.",
387 audio ? "audio" : "video");
388
389 mRenderer->queueEOS(audio, UNKNOWN_ERROR);
Andreas Hubera1587462010-12-15 15:17:42 -0800390 } else {
391 CHECK_EQ((int)what, (int)ACodec::kWhatDrainThisBuffer);
392
393 renderBuffer(audio, codecRequest);
394 }
395
396 break;
397 }
398
399 case kWhatRendererNotify:
400 {
401 int32_t what;
402 CHECK(msg->findInt32("what", &what));
403
404 if (what == Renderer::kWhatEOS) {
405 int32_t audio;
406 CHECK(msg->findInt32("audio", &audio));
407
Andreas Huberd84fd792011-08-16 13:48:44 -0700408 int32_t finalResult;
409 CHECK(msg->findInt32("finalResult", &finalResult));
410
Andreas Hubera1587462010-12-15 15:17:42 -0800411 if (audio) {
412 mAudioEOS = true;
413 } else {
414 mVideoEOS = true;
415 }
416
Andreas Huberd84fd792011-08-16 13:48:44 -0700417 if (finalResult == ERROR_END_OF_STREAM) {
Steve Block71f2cf12011-10-20 11:56:00 +0100418 ALOGV("reached %s EOS", audio ? "audio" : "video");
Andreas Huberd84fd792011-08-16 13:48:44 -0700419 } else {
Andreas Huber928baf12011-09-26 10:53:29 -0700420 LOGE("%s track encountered an error (%d)",
Andreas Huberd84fd792011-08-16 13:48:44 -0700421 audio ? "audio" : "video", finalResult);
422
423 notifyListener(
424 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult);
425 }
Andreas Hubera1587462010-12-15 15:17:42 -0800426
427 if ((mAudioEOS || mAudioDecoder == NULL)
428 && (mVideoEOS || mVideoDecoder == NULL)) {
429 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
430 }
Andreas Huber08e10cb2011-01-05 12:17:08 -0800431 } else if (what == Renderer::kWhatPosition) {
432 int64_t positionUs;
433 CHECK(msg->findInt64("positionUs", &positionUs));
434
Andreas Huber950fc9d2011-09-16 15:09:22 -0700435 CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs));
436
Andreas Huber08e10cb2011-01-05 12:17:08 -0800437 if (mDriver != NULL) {
438 sp<NuPlayerDriver> driver = mDriver.promote();
439 if (driver != NULL) {
440 driver->notifyPosition(positionUs);
Andreas Huber950fc9d2011-09-16 15:09:22 -0700441
442 driver->notifyFrameStats(
443 mNumFramesTotal, mNumFramesDropped);
Andreas Huber08e10cb2011-01-05 12:17:08 -0800444 }
445 }
Andreas Huber950fc9d2011-09-16 15:09:22 -0700446 } else if (what == Renderer::kWhatFlushComplete) {
Andreas Hubera1587462010-12-15 15:17:42 -0800447 CHECK_EQ(what, (int32_t)Renderer::kWhatFlushComplete);
448
449 int32_t audio;
450 CHECK(msg->findInt32("audio", &audio));
451
Steve Block71f2cf12011-10-20 11:56:00 +0100452 ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
Andreas Hubera1587462010-12-15 15:17:42 -0800453 }
454 break;
455 }
456
457 case kWhatMoreDataQueued:
458 {
459 break;
460 }
461
Andreas Hubercbeaca72011-01-04 14:01:29 -0800462 case kWhatReset:
463 {
Steve Block71f2cf12011-10-20 11:56:00 +0100464 ALOGV("kWhatReset");
Andreas Hubercbeaca72011-01-04 14:01:29 -0800465
Andreas Huber551aeac2011-11-28 16:27:35 -0800466 if (mRenderer != NULL) {
467 // There's an edge case where the renderer owns all output
468 // buffers and is paused, therefore the decoder will not read
469 // more input data and will never encounter the matching
470 // discontinuity. To avoid this, we resume the renderer.
471
472 if (mFlushingAudio == AWAITING_DISCONTINUITY
473 || mFlushingVideo == AWAITING_DISCONTINUITY) {
474 mRenderer->resume();
475 }
476 }
477
Andreas Hubercbeaca72011-01-04 14:01:29 -0800478 if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
479 // We're currently flushing, postpone the reset until that's
480 // completed.
481
Andreas Huberdb85b542011-11-30 09:53:40 -0800482 ALOGV("postponing reset mFlushingAudio=%d, mFlushingVideo=%d",
483 mFlushingAudio, mFlushingVideo);
Andreas Hubercbeaca72011-01-04 14:01:29 -0800484
485 mResetPostponed = true;
486 break;
487 }
488
489 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
490 finishReset();
491 break;
492 }
493
Andreas Huber66a051a2011-11-28 12:36:11 -0800494 mTimeDiscontinuityPending = true;
495
Andreas Hubercbeaca72011-01-04 14:01:29 -0800496 if (mAudioDecoder != NULL) {
497 flushDecoder(true /* audio */, true /* needShutdown */);
498 }
499
500 if (mVideoDecoder != NULL) {
501 flushDecoder(false /* audio */, true /* needShutdown */);
502 }
503
504 mResetInProgress = true;
505 break;
506 }
507
Andreas Huber08e10cb2011-01-05 12:17:08 -0800508 case kWhatSeek:
509 {
510 int64_t seekTimeUs;
511 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
512
Steve Block71f2cf12011-10-20 11:56:00 +0100513 ALOGV("kWhatSeek seekTimeUs=%lld us (%.2f secs)",
Andreas Huber08e10cb2011-01-05 12:17:08 -0800514 seekTimeUs, seekTimeUs / 1E6);
515
516 mSource->seekTo(seekTimeUs);
517
518 if (mDriver != NULL) {
519 sp<NuPlayerDriver> driver = mDriver.promote();
520 if (driver != NULL) {
521 driver->notifySeekComplete();
522 }
523 }
524
525 break;
526 }
527
Andreas Huber601fe0e2011-01-20 15:23:04 -0800528 case kWhatPause:
529 {
530 CHECK(mRenderer != NULL);
531 mRenderer->pause();
532 break;
533 }
534
535 case kWhatResume:
536 {
537 CHECK(mRenderer != NULL);
538 mRenderer->resume();
539 break;
540 }
541
Andreas Hubera1587462010-12-15 15:17:42 -0800542 default:
543 TRESPASS();
544 break;
545 }
546}
547
Andreas Huber41c3f742010-12-21 10:22:33 -0800548void NuPlayer::finishFlushIfPossible() {
549 if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
550 return;
551 }
552
553 if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
554 return;
555 }
556
Steve Block71f2cf12011-10-20 11:56:00 +0100557 ALOGV("both audio and video are flushed now.");
Andreas Huber41c3f742010-12-21 10:22:33 -0800558
Andreas Huber66a051a2011-11-28 12:36:11 -0800559 if (mTimeDiscontinuityPending) {
560 mRenderer->signalTimeDiscontinuity();
561 mTimeDiscontinuityPending = false;
562 }
Andreas Huber41c3f742010-12-21 10:22:33 -0800563
Andreas Huber847551c2011-01-05 16:24:27 -0800564 if (mAudioDecoder != NULL) {
Andreas Huber41c3f742010-12-21 10:22:33 -0800565 mAudioDecoder->signalResume();
566 }
567
Andreas Huber847551c2011-01-05 16:24:27 -0800568 if (mVideoDecoder != NULL) {
Andreas Huber41c3f742010-12-21 10:22:33 -0800569 mVideoDecoder->signalResume();
570 }
571
572 mFlushingAudio = NONE;
573 mFlushingVideo = NONE;
Andreas Huber41c3f742010-12-21 10:22:33 -0800574
Andreas Hubercbeaca72011-01-04 14:01:29 -0800575 if (mResetInProgress) {
Steve Block71f2cf12011-10-20 11:56:00 +0100576 ALOGV("reset completed");
Andreas Hubercbeaca72011-01-04 14:01:29 -0800577
578 mResetInProgress = false;
579 finishReset();
580 } else if (mResetPostponed) {
581 (new AMessage(kWhatReset, id()))->post();
582 mResetPostponed = false;
Andreas Huber847551c2011-01-05 16:24:27 -0800583 } else if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
Andreas Hubercbeaca72011-01-04 14:01:29 -0800584 postScanSources();
Andreas Hubera1587462010-12-15 15:17:42 -0800585 }
586}
587
Andreas Hubercbeaca72011-01-04 14:01:29 -0800588void NuPlayer::finishReset() {
589 CHECK(mAudioDecoder == NULL);
590 CHECK(mVideoDecoder == NULL);
591
Andreas Hubera6be6dc2011-10-11 15:24:07 -0700592 ++mScanSourcesGeneration;
593 mScanSourcesPending = false;
594
Andreas Hubercbeaca72011-01-04 14:01:29 -0800595 mRenderer.clear();
Andreas Hubera6be6dc2011-10-11 15:24:07 -0700596
597 if (mSource != NULL) {
598 mSource->stop();
599 mSource.clear();
600 }
Andreas Hubercbeaca72011-01-04 14:01:29 -0800601
Andreas Huber08e10cb2011-01-05 12:17:08 -0800602 if (mDriver != NULL) {
603 sp<NuPlayerDriver> driver = mDriver.promote();
604 if (driver != NULL) {
605 driver->notifyResetComplete();
606 }
607 }
Andreas Hubercbeaca72011-01-04 14:01:29 -0800608}
609
610void NuPlayer::postScanSources() {
611 if (mScanSourcesPending) {
612 return;
613 }
614
615 sp<AMessage> msg = new AMessage(kWhatScanSources, id());
616 msg->setInt32("generation", mScanSourcesGeneration);
617 msg->post();
618
619 mScanSourcesPending = true;
620}
621
Andreas Huber54e66492010-12-23 10:27:40 -0800622status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
Andreas Hubera1587462010-12-15 15:17:42 -0800623 if (*decoder != NULL) {
624 return OK;
625 }
626
Andreas Huber54e66492010-12-23 10:27:40 -0800627 sp<MetaData> meta = mSource->getFormat(audio);
Andreas Hubera1587462010-12-15 15:17:42 -0800628
Andreas Huber54e66492010-12-23 10:27:40 -0800629 if (meta == NULL) {
Andreas Hubera1587462010-12-15 15:17:42 -0800630 return -EWOULDBLOCK;
631 }
632
Andreas Huber950fc9d2011-09-16 15:09:22 -0700633 if (!audio) {
634 const char *mime;
635 CHECK(meta->findCString(kKeyMIMEType, &mime));
636 mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime);
637 }
638
Andreas Hubera1587462010-12-15 15:17:42 -0800639 sp<AMessage> notify =
640 new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
641 id());
642
Glenn Kastencc562a32011-02-08 17:26:17 -0800643 *decoder = audio ? new Decoder(notify) :
644 new Decoder(notify, mNativeWindow);
Andreas Hubera1587462010-12-15 15:17:42 -0800645 looper()->registerHandler(*decoder);
646
Andreas Huber54e66492010-12-23 10:27:40 -0800647 (*decoder)->configure(meta);
Andreas Hubera1587462010-12-15 15:17:42 -0800648
Andreas Huber08e10cb2011-01-05 12:17:08 -0800649 int64_t durationUs;
650 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
651 sp<NuPlayerDriver> driver = mDriver.promote();
652 if (driver != NULL) {
653 driver->notifyDuration(durationUs);
654 }
655 }
656
Andreas Hubera1587462010-12-15 15:17:42 -0800657 return OK;
658}
659
660status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
661 sp<AMessage> reply;
662 CHECK(msg->findMessage("reply", &reply));
663
Andreas Huber222e6892010-12-22 10:03:04 -0800664 if ((audio && IsFlushingState(mFlushingAudio))
665 || (!audio && IsFlushingState(mFlushingVideo))) {
Andreas Hubera1587462010-12-15 15:17:42 -0800666 reply->setInt32("err", INFO_DISCONTINUITY);
667 reply->post();
668 return OK;
669 }
670
671 sp<ABuffer> accessUnit;
Andreas Hubera1587462010-12-15 15:17:42 -0800672
Andreas Huber950fc9d2011-09-16 15:09:22 -0700673 bool dropAccessUnit;
674 do {
675 status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
Andreas Huber54e66492010-12-23 10:27:40 -0800676
Andreas Huber950fc9d2011-09-16 15:09:22 -0700677 if (err == -EWOULDBLOCK) {
678 return err;
679 } else if (err != OK) {
680 if (err == INFO_DISCONTINUITY) {
681 int32_t type;
682 CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
Andreas Huber222e6892010-12-22 10:03:04 -0800683
Andreas Huber950fc9d2011-09-16 15:09:22 -0700684 bool formatChange =
Andreas Huber66a051a2011-11-28 12:36:11 -0800685 (audio &&
686 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
687 || (!audio &&
688 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
Andreas Huber222e6892010-12-22 10:03:04 -0800689
Andreas Huber66a051a2011-11-28 12:36:11 -0800690 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
691
Steve Block6215d3f2012-01-04 20:05:49 +0000692 ALOGI("%s discontinuity (formatChange=%d, time=%d)",
Andreas Huber66a051a2011-11-28 12:36:11 -0800693 audio ? "audio" : "video", formatChange, timeChange);
Andreas Huber669ad132011-03-02 15:34:46 -0800694
Andreas Huber950fc9d2011-09-16 15:09:22 -0700695 if (audio) {
696 mSkipRenderingAudioUntilMediaTimeUs = -1;
697 } else {
698 mSkipRenderingVideoUntilMediaTimeUs = -1;
699 }
Andreas Huber669ad132011-03-02 15:34:46 -0800700
Andreas Huber66a051a2011-11-28 12:36:11 -0800701 if (timeChange) {
702 sp<AMessage> extra;
703 if (accessUnit->meta()->findMessage("extra", &extra)
704 && extra != NULL) {
705 int64_t resumeAtMediaTimeUs;
706 if (extra->findInt64(
707 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
Steve Block6215d3f2012-01-04 20:05:49 +0000708 ALOGI("suppressing rendering of %s until %lld us",
Andreas Huber66a051a2011-11-28 12:36:11 -0800709 audio ? "audio" : "video", resumeAtMediaTimeUs);
Andreas Huber950fc9d2011-09-16 15:09:22 -0700710
Andreas Huber66a051a2011-11-28 12:36:11 -0800711 if (audio) {
712 mSkipRenderingAudioUntilMediaTimeUs =
713 resumeAtMediaTimeUs;
714 } else {
715 mSkipRenderingVideoUntilMediaTimeUs =
716 resumeAtMediaTimeUs;
717 }
Andreas Huber950fc9d2011-09-16 15:09:22 -0700718 }
Andreas Huber669ad132011-03-02 15:34:46 -0800719 }
720 }
Andreas Huber950fc9d2011-09-16 15:09:22 -0700721
Andreas Huber66a051a2011-11-28 12:36:11 -0800722 mTimeDiscontinuityPending =
723 mTimeDiscontinuityPending || timeChange;
724
725 if (formatChange || timeChange) {
726 flushDecoder(audio, formatChange);
727 } else {
728 // This stream is unaffected by the discontinuity
729
730 if (audio) {
731 mFlushingAudio = FLUSHED;
732 } else {
733 mFlushingVideo = FLUSHED;
734 }
735
736 finishFlushIfPossible();
737
738 return -EWOULDBLOCK;
739 }
Andreas Huber669ad132011-03-02 15:34:46 -0800740 }
741
Andreas Huber950fc9d2011-09-16 15:09:22 -0700742 reply->setInt32("err", err);
743 reply->post();
744 return OK;
Andreas Hubera1587462010-12-15 15:17:42 -0800745 }
746
Andreas Huber950fc9d2011-09-16 15:09:22 -0700747 if (!audio) {
748 ++mNumFramesTotal;
749 }
750
751 dropAccessUnit = false;
752 if (!audio
753 && mVideoLateByUs > 100000ll
754 && mVideoIsAVC
755 && !IsAVCReferenceFrame(accessUnit)) {
756 dropAccessUnit = true;
757 ++mNumFramesDropped;
758 }
759 } while (dropAccessUnit);
Andreas Hubera1587462010-12-15 15:17:42 -0800760
Steve Block71f2cf12011-10-20 11:56:00 +0100761 // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
Andreas Hubera1587462010-12-15 15:17:42 -0800762
763#if 0
764 int64_t mediaTimeUs;
765 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
Steve Block71f2cf12011-10-20 11:56:00 +0100766 ALOGV("feeding %s input buffer at media time %.2f secs",
Andreas Hubera1587462010-12-15 15:17:42 -0800767 audio ? "audio" : "video",
768 mediaTimeUs / 1E6);
769#endif
770
771 reply->setObject("buffer", accessUnit);
772 reply->post();
773
774 return OK;
775}
776
777void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
Steve Block71f2cf12011-10-20 11:56:00 +0100778 // ALOGV("renderBuffer %s", audio ? "audio" : "video");
Andreas Hubera1587462010-12-15 15:17:42 -0800779
780 sp<AMessage> reply;
781 CHECK(msg->findMessage("reply", &reply));
782
Andreas Huberea8c9b12011-08-31 15:04:25 -0700783 if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) {
784 // We're currently attempting to flush the decoder, in order
785 // to complete this, the decoder wants all its buffers back,
786 // so we don't want any output buffers it sent us (from before
787 // we initiated the flush) to be stuck in the renderer's queue.
788
Steve Block71f2cf12011-10-20 11:56:00 +0100789 ALOGV("we're still flushing the %s decoder, sending its output buffer"
Andreas Huberea8c9b12011-08-31 15:04:25 -0700790 " right back.", audio ? "audio" : "video");
791
792 reply->post();
793 return;
794 }
795
Andreas Hubera1587462010-12-15 15:17:42 -0800796 sp<RefBase> obj;
797 CHECK(msg->findObject("buffer", &obj));
798
799 sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
800
Andreas Huber669ad132011-03-02 15:34:46 -0800801 int64_t &skipUntilMediaTimeUs =
802 audio
803 ? mSkipRenderingAudioUntilMediaTimeUs
804 : mSkipRenderingVideoUntilMediaTimeUs;
805
806 if (skipUntilMediaTimeUs >= 0) {
807 int64_t mediaTimeUs;
808 CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs));
809
810 if (mediaTimeUs < skipUntilMediaTimeUs) {
Steve Block71f2cf12011-10-20 11:56:00 +0100811 ALOGV("dropping %s buffer at time %lld as requested.",
Andreas Huber669ad132011-03-02 15:34:46 -0800812 audio ? "audio" : "video",
813 mediaTimeUs);
814
815 reply->post();
816 return;
817 }
818
819 skipUntilMediaTimeUs = -1;
820 }
821
Andreas Hubera1587462010-12-15 15:17:42 -0800822 mRenderer->queueBuffer(audio, buffer, reply);
823}
824
825void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
Andreas Huber08e10cb2011-01-05 12:17:08 -0800826 if (mDriver == NULL) {
Andreas Hubera1587462010-12-15 15:17:42 -0800827 return;
828 }
829
Andreas Huber08e10cb2011-01-05 12:17:08 -0800830 sp<NuPlayerDriver> driver = mDriver.promote();
Andreas Hubera1587462010-12-15 15:17:42 -0800831
Andreas Huber08e10cb2011-01-05 12:17:08 -0800832 if (driver == NULL) {
Andreas Hubera1587462010-12-15 15:17:42 -0800833 return;
834 }
835
Andreas Hubere96e84b2011-10-26 15:23:31 -0700836 driver->notifyListener(msg, ext1, ext2);
Andreas Hubera1587462010-12-15 15:17:42 -0800837}
838
Andreas Hubercbeaca72011-01-04 14:01:29 -0800839void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
Andreas Huber66a051a2011-11-28 12:36:11 -0800840 if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
Steve Block6215d3f2012-01-04 20:05:49 +0000841 ALOGI("flushDecoder %s without decoder present",
Andreas Huber66a051a2011-11-28 12:36:11 -0800842 audio ? "audio" : "video");
843 }
844
Andreas Hubercbeaca72011-01-04 14:01:29 -0800845 // Make sure we don't continue to scan sources until we finish flushing.
846 ++mScanSourcesGeneration;
Andreas Huber08e10cb2011-01-05 12:17:08 -0800847 mScanSourcesPending = false;
Andreas Hubercbeaca72011-01-04 14:01:29 -0800848
849 (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
850 mRenderer->flush(audio);
851
852 FlushStatus newStatus =
853 needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
854
855 if (audio) {
856 CHECK(mFlushingAudio == NONE
857 || mFlushingAudio == AWAITING_DISCONTINUITY);
858
859 mFlushingAudio = newStatus;
860
861 if (mFlushingVideo == NONE) {
862 mFlushingVideo = (mVideoDecoder != NULL)
863 ? AWAITING_DISCONTINUITY
864 : FLUSHED;
865 }
866 } else {
867 CHECK(mFlushingVideo == NONE
868 || mFlushingVideo == AWAITING_DISCONTINUITY);
869
870 mFlushingVideo = newStatus;
871
872 if (mFlushingAudio == NONE) {
873 mFlushingAudio = (mAudioDecoder != NULL)
874 ? AWAITING_DISCONTINUITY
875 : FLUSHED;
876 }
877 }
878}
879
Andreas Hubera1587462010-12-15 15:17:42 -0800880} // namespace android