blob: 967fa495ed0b9339b83ae73c8987fd330fec75bd [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"
22#include "NuPlayerDecoder.h"
23#include "NuPlayerRenderer.h"
24#include "NuPlayerStreamListener.h"
25
Andreas Huber3831a062010-12-21 10:22:33 -080026#include <media/stagefright/foundation/hexdump.h>
Andreas Huberf9334412010-12-15 15:17:42 -080027#include <media/stagefright/foundation/ABuffer.h>
28#include <media/stagefright/foundation/ADebug.h>
29#include <media/stagefright/foundation/AMessage.h>
30#include <media/stagefright/ACodec.h>
31#include <media/stagefright/MediaErrors.h>
32#include <media/stagefright/MetaData.h>
33#include <surfaceflinger/Surface.h>
34
35namespace android {
36
37////////////////////////////////////////////////////////////////////////////////
38
39NuPlayer::NuPlayer()
40 : mEOS(false),
41 mAudioEOS(false),
42 mVideoEOS(false),
43 mFlushingAudio(NONE),
44 mFlushingVideo(NONE) {
45}
46
47NuPlayer::~NuPlayer() {
48}
49
50void NuPlayer::setListener(const wp<MediaPlayerBase> &listener) {
51 mListener = listener;
52}
53
54void NuPlayer::setDataSource(const sp<IStreamSource> &source) {
55 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
56
57 source->incStrong(this);
58 msg->setPointer("source", source.get()); // XXX unsafe.
59
60 msg->post();
61}
62
63void NuPlayer::setVideoSurface(const sp<Surface> &surface) {
64 sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, id());
65 msg->setObject("surface", surface);
66 msg->post();
67}
68
69void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) {
70 sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id());
71 msg->setObject("sink", sink);
72 msg->post();
73}
74
75void NuPlayer::start() {
76 (new AMessage(kWhatStart, id()))->post();
77}
78
Andreas Huber53df1a42010-12-22 10:03:04 -080079// static
80bool NuPlayer::IsFlushingState(FlushStatus state, bool *formatChange) {
81 switch (state) {
82 case FLUSHING_DECODER:
83 if (formatChange != NULL) {
84 *formatChange = false;
85 }
86 return true;
87
88 case FLUSHING_DECODER_FORMATCHANGE:
89 if (formatChange != NULL) {
90 *formatChange = true;
91 }
92 return true;
93
94 default:
95 return false;
96 }
97}
98
Andreas Huberf9334412010-12-15 15:17:42 -080099void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
100 switch (msg->what()) {
101 case kWhatSetDataSource:
102 {
103 LOGI("kWhatSetDataSource");
104
105 CHECK(mSource == NULL);
106
107 void *ptr;
108 CHECK(msg->findPointer("source", &ptr));
109
110 mSource = static_cast<IStreamSource *>(ptr);
111 mSource->decStrong(this);
112
113 mStreamListener = new NuPlayerStreamListener(mSource, id());
114 mTSParser = new ATSParser;
115 break;
116 }
117
118 case kWhatSetVideoSurface:
119 {
120 LOGI("kWhatSetVideoSurface");
121
122 sp<RefBase> obj;
123 CHECK(msg->findObject("surface", &obj));
124
125 mSurface = static_cast<Surface *>(obj.get());
126 break;
127 }
128
129 case kWhatSetAudioSink:
130 {
131 LOGI("kWhatSetAudioSink");
132
133 sp<RefBase> obj;
134 CHECK(msg->findObject("sink", &obj));
135
136 mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get());
137 break;
138 }
139
140 case kWhatStart:
141 {
142 mStreamListener->start();
143
144 mRenderer = new Renderer(
145 mAudioSink,
146 new AMessage(kWhatRendererNotify, id()));
147
148 looper()->registerHandler(mRenderer);
149
150 (new AMessage(kWhatScanSources, id()))->post();
151 break;
152 }
153
154 case kWhatScanSources:
155 {
Andreas Huber3831a062010-12-21 10:22:33 -0800156 instantiateDecoder(
157 false,
158 &mVideoDecoder,
159 false /* ignoreCodecSpecificData */);
Andreas Huberf9334412010-12-15 15:17:42 -0800160
161 if (mAudioSink != NULL) {
Andreas Huber3831a062010-12-21 10:22:33 -0800162 instantiateDecoder(
163 true,
164 &mAudioDecoder,
165 false /* ignoreCodecSpecificData */);
Andreas Huberf9334412010-12-15 15:17:42 -0800166 }
167
168 if (mEOS) {
169 break;
170 }
171
172 feedMoreTSData();
173
174 if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
175 msg->post(100000ll);
176 }
177 break;
178 }
179
180 case kWhatVideoNotify:
181 case kWhatAudioNotify:
182 {
183 bool audio = msg->what() == kWhatAudioNotify;
184
185 sp<AMessage> codecRequest;
186 CHECK(msg->findMessage("codec-request", &codecRequest));
187
188 int32_t what;
189 CHECK(codecRequest->findInt32("what", &what));
190
191 if (what == ACodec::kWhatFillThisBuffer) {
192 status_t err = feedDecoderInputData(
193 audio, codecRequest);
194
195 if (err == -EWOULDBLOCK && !mEOS) {
196 feedMoreTSData();
197 msg->post();
198 }
199 } else if (what == ACodec::kWhatEOS) {
200 mRenderer->queueEOS(audio, ERROR_END_OF_STREAM);
201 } else if (what == ACodec::kWhatFlushCompleted) {
Andreas Huber53df1a42010-12-22 10:03:04 -0800202 bool formatChange;
203
Andreas Huberf9334412010-12-15 15:17:42 -0800204 if (audio) {
Andreas Huber53df1a42010-12-22 10:03:04 -0800205 CHECK(IsFlushingState(mFlushingAudio, &formatChange));
Andreas Huberf9334412010-12-15 15:17:42 -0800206 mFlushingAudio = FLUSHED;
207 } else {
Andreas Huber53df1a42010-12-22 10:03:04 -0800208 CHECK(IsFlushingState(mFlushingVideo, &formatChange));
Andreas Huberf9334412010-12-15 15:17:42 -0800209 mFlushingVideo = FLUSHED;
210 }
211
212 LOGI("decoder %s flush completed", audio ? "audio" : "video");
213
Andreas Huber53df1a42010-12-22 10:03:04 -0800214 if (formatChange) {
215 LOGI("initiating %s decoder shutdown",
216 audio ? "audio" : "video");
Andreas Huberf9334412010-12-15 15:17:42 -0800217
Andreas Huber53df1a42010-12-22 10:03:04 -0800218 (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
Andreas Huberf9334412010-12-15 15:17:42 -0800219
Andreas Huber53df1a42010-12-22 10:03:04 -0800220 if (audio) {
221 mFlushingAudio = SHUTTING_DOWN_DECODER;
222 } else {
223 mFlushingVideo = SHUTTING_DOWN_DECODER;
224 }
Andreas Huberf9334412010-12-15 15:17:42 -0800225 }
Andreas Huber3831a062010-12-21 10:22:33 -0800226
227 finishFlushIfPossible();
Andreas Huber2c2814b2010-12-15 17:18:20 -0800228 } else if (what == ACodec::kWhatOutputFormatChanged) {
229 CHECK(audio);
230
231 int32_t numChannels;
232 CHECK(codecRequest->findInt32("channel-count", &numChannels));
233
234 int32_t sampleRate;
235 CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
236
237 LOGI("Audio output format changed to %d Hz, %d channels",
238 sampleRate, numChannels);
239
240 mAudioSink->close();
241 CHECK_EQ(mAudioSink->open(sampleRate, numChannels), (status_t)OK);
242 mAudioSink->start();
Andreas Huber3831a062010-12-21 10:22:33 -0800243
244 mRenderer->signalAudioSinkChanged();
245 } else if (what == ACodec::kWhatShutdownCompleted) {
246 LOGI("%s shutdown completed", audio ? "audio" : "video");
247 if (audio) {
248 mAudioDecoder.clear();
249
250 CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
251 mFlushingAudio = SHUT_DOWN;
252 } else {
253 mVideoDecoder.clear();
254
255 CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
256 mFlushingVideo = SHUT_DOWN;
257 }
258
259 finishFlushIfPossible();
Andreas Huberf9334412010-12-15 15:17:42 -0800260 } else {
261 CHECK_EQ((int)what, (int)ACodec::kWhatDrainThisBuffer);
262
263 renderBuffer(audio, codecRequest);
264 }
265
266 break;
267 }
268
269 case kWhatRendererNotify:
270 {
271 int32_t what;
272 CHECK(msg->findInt32("what", &what));
273
274 if (what == Renderer::kWhatEOS) {
275 int32_t audio;
276 CHECK(msg->findInt32("audio", &audio));
277
278 if (audio) {
279 mAudioEOS = true;
280 } else {
281 mVideoEOS = true;
282 }
283
284 LOGI("reached %s EOS", audio ? "audio" : "video");
285
286 if ((mAudioEOS || mAudioDecoder == NULL)
287 && (mVideoEOS || mVideoDecoder == NULL)) {
288 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
289 }
290 } else {
291 CHECK_EQ(what, (int32_t)Renderer::kWhatFlushComplete);
292
293 int32_t audio;
294 CHECK(msg->findInt32("audio", &audio));
295
296 LOGI("renderer %s flush completed.", audio ? "audio" : "video");
297 }
298 break;
299 }
300
301 case kWhatMoreDataQueued:
302 {
303 break;
304 }
305
306 default:
307 TRESPASS();
308 break;
309 }
310}
311
Andreas Huber3831a062010-12-21 10:22:33 -0800312void NuPlayer::finishFlushIfPossible() {
313 if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
314 return;
315 }
316
317 if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
318 return;
319 }
320
321 LOGI("both audio and video are flushed now.");
322
323 mRenderer->signalTimeDiscontinuity();
324
325 if (mFlushingAudio == SHUT_DOWN) {
326 instantiateDecoder(
327 true,
328 &mAudioDecoder,
329 true /* ignoreCodecSpecificData */);
330 CHECK(mAudioDecoder != NULL);
331 } else if (mAudioDecoder != NULL) {
332 mAudioDecoder->signalResume();
333 }
334
335 if (mFlushingVideo == SHUT_DOWN) {
336 instantiateDecoder(
337 false,
338 &mVideoDecoder,
339 true /* ignoreCodecSpecificData */);
340 CHECK(mVideoDecoder != NULL);
341 } else if (mVideoDecoder != NULL) {
342 mVideoDecoder->signalResume();
343 }
344
345 mFlushingAudio = NONE;
346 mFlushingVideo = NONE;
347}
348
Andreas Huberf9334412010-12-15 15:17:42 -0800349void NuPlayer::feedMoreTSData() {
350 CHECK(!mEOS);
351
352 for (int32_t i = 0; i < 10; ++i) {
353 char buffer[188];
354 ssize_t n = mStreamListener->read(buffer, sizeof(buffer));
355
356 if (n == 0) {
357 LOGI("input data EOS reached.");
358 mTSParser->signalEOS(ERROR_END_OF_STREAM);
359 mEOS = true;
360 break;
361 } else if (n == INFO_DISCONTINUITY) {
362 mTSParser->signalDiscontinuity(ATSParser::DISCONTINUITY_SEEK);
363 } else if (n < 0) {
364 CHECK_EQ(n, -EWOULDBLOCK);
365 break;
366 } else {
367 if (buffer[0] == 0x00) {
368 // XXX legacy
Andreas Huber3831a062010-12-21 10:22:33 -0800369 mTSParser->signalDiscontinuity(
370 buffer[1] == 0x00
371 ? ATSParser::DISCONTINUITY_SEEK
372 : ATSParser::DISCONTINUITY_FORMATCHANGE);
Andreas Huberf9334412010-12-15 15:17:42 -0800373 } else {
374 mTSParser->feedTSPacket(buffer, sizeof(buffer));
375 }
376 }
377 }
378}
379
380status_t NuPlayer::dequeueNextAccessUnit(
381 ATSParser::SourceType *type, sp<ABuffer> *accessUnit) {
382 accessUnit->clear();
383
384 status_t audioErr = -EWOULDBLOCK;
385 int64_t audioTimeUs;
386
387 sp<AnotherPacketSource> audioSource =
388 static_cast<AnotherPacketSource *>(
389 mTSParser->getSource(ATSParser::MPEG2ADTS_AUDIO).get());
390
391 if (audioSource != NULL) {
392 audioErr = audioSource->nextBufferTime(&audioTimeUs);
393 }
394
395 status_t videoErr = -EWOULDBLOCK;
396 int64_t videoTimeUs;
397
398 sp<AnotherPacketSource> videoSource =
399 static_cast<AnotherPacketSource *>(
400 mTSParser->getSource(ATSParser::AVC_VIDEO).get());
401
402 if (videoSource != NULL) {
403 videoErr = videoSource->nextBufferTime(&videoTimeUs);
404 }
405
406 if (audioErr == -EWOULDBLOCK || videoErr == -EWOULDBLOCK) {
407 return -EWOULDBLOCK;
408 }
409
410 if (audioErr != OK && videoErr != OK) {
411 return audioErr;
412 }
413
414 if (videoErr != OK || (audioErr == OK && audioTimeUs < videoTimeUs)) {
415 *type = ATSParser::MPEG2ADTS_AUDIO;
416 return audioSource->dequeueAccessUnit(accessUnit);
417 } else {
418 *type = ATSParser::AVC_VIDEO;
419 return videoSource->dequeueAccessUnit(accessUnit);
420 }
421}
422
423status_t NuPlayer::dequeueAccessUnit(
424 ATSParser::SourceType type, sp<ABuffer> *accessUnit) {
425 sp<AnotherPacketSource> source =
426 static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
427
428 if (source == NULL) {
429 return -EWOULDBLOCK;
430 }
431
432 status_t finalResult;
433 if (!source->hasBufferAvailable(&finalResult)) {
434 return finalResult == OK ? -EWOULDBLOCK : finalResult;
435 }
436
437 return source->dequeueAccessUnit(accessUnit);
438}
439
440status_t NuPlayer::instantiateDecoder(
Andreas Huber3831a062010-12-21 10:22:33 -0800441 bool audio, sp<Decoder> *decoder, bool ignoreCodecSpecificData) {
Andreas Huberf9334412010-12-15 15:17:42 -0800442 if (*decoder != NULL) {
443 return OK;
444 }
445
446 ATSParser::SourceType type =
447 audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO;
448
449 sp<AnotherPacketSource> source =
450 static_cast<AnotherPacketSource *>(
451 mTSParser->getSource(type).get());
452
453 if (source == NULL) {
454 return -EWOULDBLOCK;
455 }
456
457 sp<AMessage> notify =
458 new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
459 id());
460
461 *decoder = new Decoder(notify, audio ? NULL : mSurface);
462 looper()->registerHandler(*decoder);
463
464 const sp<MetaData> &meta = source->getFormat();
Andreas Huber3831a062010-12-21 10:22:33 -0800465 (*decoder)->configure(meta, ignoreCodecSpecificData);
Andreas Huberf9334412010-12-15 15:17:42 -0800466
Andreas Huberf9334412010-12-15 15:17:42 -0800467 return OK;
468}
469
470status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
471 sp<AMessage> reply;
472 CHECK(msg->findMessage("reply", &reply));
473
Andreas Huber53df1a42010-12-22 10:03:04 -0800474 if ((audio && IsFlushingState(mFlushingAudio))
475 || (!audio && IsFlushingState(mFlushingVideo))) {
Andreas Huberf9334412010-12-15 15:17:42 -0800476 reply->setInt32("err", INFO_DISCONTINUITY);
477 reply->post();
478 return OK;
479 }
480
481 sp<ABuffer> accessUnit;
482 status_t err = dequeueAccessUnit(
483 audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO,
484 &accessUnit);
485
486 if (err == -EWOULDBLOCK) {
487 return err;
488 } else if (err != OK) {
489 if (err == INFO_DISCONTINUITY) {
Andreas Huber53df1a42010-12-22 10:03:04 -0800490 int32_t formatChange;
491 if (!accessUnit->meta()->findInt32(
492 "format-change", &formatChange)) {
493 formatChange = 0;
494 }
495
496 LOGI("%s discontinuity (formatChange=%d)",
497 audio ? "audio" : "video", formatChange);
498
Andreas Huberf9334412010-12-15 15:17:42 -0800499 (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
500 mRenderer->flush(audio);
501
502 if (audio) {
503 CHECK(mFlushingAudio == NONE
504 || mFlushingAudio == AWAITING_DISCONTINUITY);
Andreas Huber53df1a42010-12-22 10:03:04 -0800505
506 mFlushingAudio = formatChange
507 ? FLUSHING_DECODER_FORMATCHANGE : FLUSHING_DECODER;
508
Andreas Huberf9334412010-12-15 15:17:42 -0800509 if (mFlushingVideo == NONE) {
510 mFlushingVideo = (mVideoDecoder != NULL)
511 ? AWAITING_DISCONTINUITY
512 : FLUSHED;
513 }
514 } else {
515 CHECK(mFlushingVideo == NONE
516 || mFlushingVideo == AWAITING_DISCONTINUITY);
Andreas Huber53df1a42010-12-22 10:03:04 -0800517
518 mFlushingVideo = formatChange
519 ? FLUSHING_DECODER_FORMATCHANGE : FLUSHING_DECODER;
520
Andreas Huberf9334412010-12-15 15:17:42 -0800521 if (mFlushingAudio == NONE) {
522 mFlushingAudio = (mAudioDecoder != NULL)
523 ? AWAITING_DISCONTINUITY
524 : FLUSHED;
525 }
526 }
527 }
528
529 reply->setInt32("err", err);
530 reply->post();
531 return OK;
532 }
533
534 LOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
535
536#if 0
537 int64_t mediaTimeUs;
538 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
539 LOGI("feeding %s input buffer at media time %.2f secs",
540 audio ? "audio" : "video",
541 mediaTimeUs / 1E6);
542#endif
543
544 reply->setObject("buffer", accessUnit);
545 reply->post();
546
547 return OK;
548}
549
550void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
551 LOGV("renderBuffer %s", audio ? "audio" : "video");
552
553 sp<AMessage> reply;
554 CHECK(msg->findMessage("reply", &reply));
555
556 sp<RefBase> obj;
557 CHECK(msg->findObject("buffer", &obj));
558
559 sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
560
561 mRenderer->queueBuffer(audio, buffer, reply);
562}
563
564void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
565 if (mListener == NULL) {
566 return;
567 }
568
569 sp<MediaPlayerBase> listener = mListener.promote();
570
571 if (listener == NULL) {
572 return;
573 }
574
575 listener->sendEvent(msg, ext1, ext2);
576}
577
578} // namespace android