1 /*
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
23 #include "HTTPLiveSource.h"
24 #include "NuPlayerDecoder.h"
25 #include "NuPlayerDriver.h"
26 #include "NuPlayerRenderer.h"
27 #include "NuPlayerSource.h"
28 #include "RTSPSource.h"
29 #include "StreamingSource.h"
30 #include "GenericSource.h"
31 #include "mp4/MP4Source.h"
32
33 #include "ATSParser.h"
34
35 #include <cutils/properties.h> // for property_get
36 #include <media/stagefright/foundation/hexdump.h>
37 #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>
41 #include <media/stagefright/MediaDefs.h>
42 #include <media/stagefright/MediaErrors.h>
43 #include <media/stagefright/MetaData.h>
44 #include <gui/IGraphicBufferProducer.h>
45
46 #include "avc_utils.h"
47
48 #include "ESDS.h"
49 #include <media/stagefright/Utils.h>
50
51 namespace android {
52
53 struct NuPlayer::Action : public RefBase {
Actionandroid::NuPlayer::Action54 Action() {}
55
56 virtual void execute(NuPlayer *player) = 0;
57
58 private:
59 DISALLOW_EVIL_CONSTRUCTORS(Action);
60 };
61
62 struct NuPlayer::SeekAction : public Action {
SeekActionandroid::NuPlayer::SeekAction63 SeekAction(int64_t seekTimeUs)
64 : mSeekTimeUs(seekTimeUs) {
65 }
66
executeandroid::NuPlayer::SeekAction67 virtual void execute(NuPlayer *player) {
68 player->performSeek(mSeekTimeUs);
69 }
70
71 private:
72 int64_t mSeekTimeUs;
73
74 DISALLOW_EVIL_CONSTRUCTORS(SeekAction);
75 };
76
77 struct NuPlayer::SetSurfaceAction : public Action {
SetSurfaceActionandroid::NuPlayer::SetSurfaceAction78 SetSurfaceAction(const sp<NativeWindowWrapper> &wrapper)
79 : mWrapper(wrapper) {
80 }
81
executeandroid::NuPlayer::SetSurfaceAction82 virtual void execute(NuPlayer *player) {
83 player->performSetSurface(mWrapper);
84 }
85
86 private:
87 sp<NativeWindowWrapper> mWrapper;
88
89 DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction);
90 };
91
92 // Use this if there's no state necessary to save in order to execute
93 // the action.
94 struct NuPlayer::SimpleAction : public Action {
95 typedef void (NuPlayer::*ActionFunc)();
96
SimpleActionandroid::NuPlayer::SimpleAction97 SimpleAction(ActionFunc func)
98 : mFunc(func) {
99 }
100
executeandroid::NuPlayer::SimpleAction101 virtual void execute(NuPlayer *player) {
102 (player->*mFunc)();
103 }
104
105 private:
106 ActionFunc mFunc;
107
108 DISALLOW_EVIL_CONSTRUCTORS(SimpleAction);
109 };
110
111 ////////////////////////////////////////////////////////////////////////////////
112
NuPlayer()113 NuPlayer::NuPlayer()
114 : mUIDValid(false),
115 mSourceFlags(0),
116 mVideoIsAVC(false),
117 mAudioEOS(false),
118 mVideoEOS(false),
119 mScanSourcesPending(false),
120 mScanSourcesGeneration(0),
121 mPollDurationGeneration(0),
122 mTimeDiscontinuityPending(false),
123 mFlushingAudio(NONE),
124 mFlushingVideo(NONE),
125 mSkipRenderingAudioUntilMediaTimeUs(-1ll),
126 mSkipRenderingVideoUntilMediaTimeUs(-1ll),
127 mVideoLateByUs(0ll),
128 mNumFramesTotal(0ll),
129 mNumFramesDropped(0ll),
130 mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
131 mStarted(false) {
132 }
133
~NuPlayer()134 NuPlayer::~NuPlayer() {
135 }
136
setUID(uid_t uid)137 void NuPlayer::setUID(uid_t uid) {
138 mUIDValid = true;
139 mUID = uid;
140 }
141
setDriver(const wp<NuPlayerDriver> & driver)142 void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
143 mDriver = driver;
144 }
145
setDataSourceAsync(const sp<IStreamSource> & source)146 void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) {
147 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
148
149 sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
150
151 char prop[PROPERTY_VALUE_MAX];
152 if (property_get("media.stagefright.use-mp4source", prop, NULL)
153 && (!strcmp(prop, "1") || !strcasecmp(prop, "true"))) {
154 msg->setObject("source", new MP4Source(notify, source));
155 } else {
156 msg->setObject("source", new StreamingSource(notify, source));
157 }
158
159 msg->post();
160 }
161
IsHTTPLiveURL(const char * url)162 static bool IsHTTPLiveURL(const char *url) {
163 if (!strncasecmp("http://", url, 7)
164 || !strncasecmp("https://", url, 8)
165 || !strncasecmp("file://", url, 7)) {
166 size_t len = strlen(url);
167 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
168 return true;
169 }
170
171 if (strstr(url,"m3u8")) {
172 return true;
173 }
174 }
175
176 return false;
177 }
178
setDataSourceAsync(const char * url,const KeyedVector<String8,String8> * headers)179 void NuPlayer::setDataSourceAsync(
180 const char *url, const KeyedVector<String8, String8> *headers) {
181 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
182 size_t len = strlen(url);
183
184 sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
185
186 sp<Source> source;
187 if (IsHTTPLiveURL(url)) {
188 source = new HTTPLiveSource(notify, url, headers, mUIDValid, mUID);
189 } else if (!strncasecmp(url, "rtsp://", 7)) {
190 source = new RTSPSource(notify, url, headers, mUIDValid, mUID);
191 } else if ((!strncasecmp(url, "http://", 7)
192 || !strncasecmp(url, "https://", 8))
193 && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
194 || strstr(url, ".sdp?"))) {
195 source = new RTSPSource(notify, url, headers, mUIDValid, mUID, true);
196 } else {
197 source = new GenericSource(notify, url, headers, mUIDValid, mUID);
198 }
199
200 msg->setObject("source", source);
201 msg->post();
202 }
203
setDataSourceAsync(int fd,int64_t offset,int64_t length)204 void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) {
205 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
206
207 sp<AMessage> notify = new AMessage(kWhatSourceNotify, id());
208
209 sp<Source> source = new GenericSource(notify, fd, offset, length);
210 msg->setObject("source", source);
211 msg->post();
212 }
213
prepareAsync()214 void NuPlayer::prepareAsync() {
215 (new AMessage(kWhatPrepare, id()))->post();
216 }
217
setVideoSurfaceTextureAsync(const sp<IGraphicBufferProducer> & bufferProducer)218 void NuPlayer::setVideoSurfaceTextureAsync(
219 const sp<IGraphicBufferProducer> &bufferProducer) {
220 sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id());
221
222 if (bufferProducer == NULL) {
223 msg->setObject("native-window", NULL);
224 } else {
225 msg->setObject(
226 "native-window",
227 new NativeWindowWrapper(
228 new Surface(bufferProducer)));
229 }
230
231 msg->post();
232 }
233
setAudioSink(const sp<MediaPlayerBase::AudioSink> & sink)234 void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) {
235 sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id());
236 msg->setObject("sink", sink);
237 msg->post();
238 }
239
start()240 void NuPlayer::start() {
241 (new AMessage(kWhatStart, id()))->post();
242 }
243
pause()244 void NuPlayer::pause() {
245 (new AMessage(kWhatPause, id()))->post();
246 }
247
resume()248 void NuPlayer::resume() {
249 (new AMessage(kWhatResume, id()))->post();
250 }
251
resetAsync()252 void NuPlayer::resetAsync() {
253 (new AMessage(kWhatReset, id()))->post();
254 }
255
seekToAsync(int64_t seekTimeUs)256 void NuPlayer::seekToAsync(int64_t seekTimeUs) {
257 sp<AMessage> msg = new AMessage(kWhatSeek, id());
258 msg->setInt64("seekTimeUs", seekTimeUs);
259 msg->post();
260 }
261
262 // static
IsFlushingState(FlushStatus state,bool * needShutdown)263 bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
264 switch (state) {
265 case FLUSHING_DECODER:
266 if (needShutdown != NULL) {
267 *needShutdown = false;
268 }
269 return true;
270
271 case FLUSHING_DECODER_SHUTDOWN:
272 if (needShutdown != NULL) {
273 *needShutdown = true;
274 }
275 return true;
276
277 default:
278 return false;
279 }
280 }
281
onMessageReceived(const sp<AMessage> & msg)282 void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
283 switch (msg->what()) {
284 case kWhatSetDataSource:
285 {
286 ALOGV("kWhatSetDataSource");
287
288 CHECK(mSource == NULL);
289
290 sp<RefBase> obj;
291 CHECK(msg->findObject("source", &obj));
292
293 mSource = static_cast<Source *>(obj.get());
294
295 looper()->registerHandler(mSource);
296
297 CHECK(mDriver != NULL);
298 sp<NuPlayerDriver> driver = mDriver.promote();
299 if (driver != NULL) {
300 driver->notifySetDataSourceCompleted(OK);
301 }
302 break;
303 }
304
305 case kWhatPrepare:
306 {
307 mSource->prepareAsync();
308 break;
309 }
310
311 case kWhatPollDuration:
312 {
313 int32_t generation;
314 CHECK(msg->findInt32("generation", &generation));
315
316 if (generation != mPollDurationGeneration) {
317 // stale
318 break;
319 }
320
321 int64_t durationUs;
322 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
323 sp<NuPlayerDriver> driver = mDriver.promote();
324 if (driver != NULL) {
325 driver->notifyDuration(durationUs);
326 }
327 }
328
329 msg->post(1000000ll); // poll again in a second.
330 break;
331 }
332
333 case kWhatSetVideoNativeWindow:
334 {
335 ALOGV("kWhatSetVideoNativeWindow");
336
337 mDeferredActions.push_back(
338 new SimpleAction(&NuPlayer::performDecoderShutdown));
339
340 sp<RefBase> obj;
341 CHECK(msg->findObject("native-window", &obj));
342
343 mDeferredActions.push_back(
344 new SetSurfaceAction(
345 static_cast<NativeWindowWrapper *>(obj.get())));
346
347 if (obj != NULL) {
348 // If there is a new surface texture, instantiate decoders
349 // again if possible.
350 mDeferredActions.push_back(
351 new SimpleAction(&NuPlayer::performScanSources));
352 }
353
354 processDeferredActions();
355 break;
356 }
357
358 case kWhatSetAudioSink:
359 {
360 ALOGV("kWhatSetAudioSink");
361
362 sp<RefBase> obj;
363 CHECK(msg->findObject("sink", &obj));
364
365 mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get());
366 break;
367 }
368
369 case kWhatStart:
370 {
371 ALOGV("kWhatStart");
372
373 mVideoIsAVC = false;
374 mAudioEOS = false;
375 mVideoEOS = false;
376 mSkipRenderingAudioUntilMediaTimeUs = -1;
377 mSkipRenderingVideoUntilMediaTimeUs = -1;
378 mVideoLateByUs = 0;
379 mNumFramesTotal = 0;
380 mNumFramesDropped = 0;
381 mStarted = true;
382
383 mSource->start();
384
385 uint32_t flags = 0;
386
387 if (mSource->isRealTime()) {
388 flags |= Renderer::FLAG_REAL_TIME;
389 }
390
391 mRenderer = new Renderer(
392 mAudioSink,
393 new AMessage(kWhatRendererNotify, id()),
394 flags);
395
396 looper()->registerHandler(mRenderer);
397
398 postScanSources();
399 break;
400 }
401
402 case kWhatScanSources:
403 {
404 int32_t generation;
405 CHECK(msg->findInt32("generation", &generation));
406 if (generation != mScanSourcesGeneration) {
407 // Drop obsolete msg.
408 break;
409 }
410
411 mScanSourcesPending = false;
412
413 ALOGV("scanning sources haveAudio=%d, haveVideo=%d",
414 mAudioDecoder != NULL, mVideoDecoder != NULL);
415
416 bool mHadAnySourcesBefore =
417 (mAudioDecoder != NULL) || (mVideoDecoder != NULL);
418
419 if (mNativeWindow != NULL) {
420 instantiateDecoder(false, &mVideoDecoder);
421 }
422
423 if (mAudioSink != NULL) {
424 instantiateDecoder(true, &mAudioDecoder);
425 }
426
427 if (!mHadAnySourcesBefore
428 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
429 // This is the first time we've found anything playable.
430
431 if (mSourceFlags & Source::FLAG_DYNAMIC_DURATION) {
432 schedulePollDuration();
433 }
434 }
435
436 status_t err;
437 if ((err = mSource->feedMoreTSData()) != OK) {
438 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
439 // We're not currently decoding anything (no audio or
440 // video tracks found) and we just ran out of input data.
441
442 if (err == ERROR_END_OF_STREAM) {
443 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
444 } else {
445 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
446 }
447 }
448 break;
449 }
450
451 if ((mAudioDecoder == NULL && mAudioSink != NULL)
452 || (mVideoDecoder == NULL && mNativeWindow != NULL)) {
453 msg->post(100000ll);
454 mScanSourcesPending = true;
455 }
456 break;
457 }
458
459 case kWhatVideoNotify:
460 case kWhatAudioNotify:
461 {
462 bool audio = msg->what() == kWhatAudioNotify;
463
464 sp<AMessage> codecRequest;
465 CHECK(msg->findMessage("codec-request", &codecRequest));
466
467 int32_t what;
468 CHECK(codecRequest->findInt32("what", &what));
469
470 if (what == ACodec::kWhatFillThisBuffer) {
471 status_t err = feedDecoderInputData(
472 audio, codecRequest);
473
474 if (err == -EWOULDBLOCK) {
475 if (mSource->feedMoreTSData() == OK) {
476 msg->post(10000ll);
477 }
478 }
479 } else if (what == ACodec::kWhatEOS) {
480 int32_t err;
481 CHECK(codecRequest->findInt32("err", &err));
482
483 if (err == ERROR_END_OF_STREAM) {
484 ALOGV("got %s decoder EOS", audio ? "audio" : "video");
485 } else {
486 ALOGV("got %s decoder EOS w/ error %d",
487 audio ? "audio" : "video",
488 err);
489 }
490
491 mRenderer->queueEOS(audio, err);
492 } else if (what == ACodec::kWhatFlushCompleted) {
493 bool needShutdown;
494
495 if (audio) {
496 CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
497 mFlushingAudio = FLUSHED;
498 } else {
499 CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
500 mFlushingVideo = FLUSHED;
501
502 mVideoLateByUs = 0;
503 }
504
505 ALOGV("decoder %s flush completed", audio ? "audio" : "video");
506
507 if (needShutdown) {
508 ALOGV("initiating %s decoder shutdown",
509 audio ? "audio" : "video");
510
511 (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
512
513 if (audio) {
514 mFlushingAudio = SHUTTING_DOWN_DECODER;
515 } else {
516 mFlushingVideo = SHUTTING_DOWN_DECODER;
517 }
518 }
519
520 finishFlushIfPossible();
521 } else if (what == ACodec::kWhatOutputFormatChanged) {
522 if (audio) {
523 int32_t numChannels;
524 CHECK(codecRequest->findInt32(
525 "channel-count", &numChannels));
526
527 int32_t sampleRate;
528 CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
529
530 ALOGV("Audio output format changed to %d Hz, %d channels",
531 sampleRate, numChannels);
532
533 mAudioSink->close();
534
535 audio_output_flags_t flags;
536 int64_t durationUs;
537 // FIXME: we should handle the case where the video decoder
538 // is created after we receive the format change indication.
539 // Current code will just make that we select deep buffer
540 // with video which should not be a problem as it should
541 // not prevent from keeping A/V sync.
542 if (mVideoDecoder == NULL &&
543 mSource->getDuration(&durationUs) == OK &&
544 durationUs
545 > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
546 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
547 } else {
548 flags = AUDIO_OUTPUT_FLAG_NONE;
549 }
550
551 int32_t channelMask;
552 if (!codecRequest->findInt32("channel-mask", &channelMask)) {
553 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
554 }
555
556 CHECK_EQ(mAudioSink->open(
557 sampleRate,
558 numChannels,
559 (audio_channel_mask_t)channelMask,
560 AUDIO_FORMAT_PCM_16_BIT,
561 8 /* bufferCount */,
562 NULL,
563 NULL,
564 flags),
565 (status_t)OK);
566 mAudioSink->start();
567
568 mRenderer->signalAudioSinkChanged();
569 } else {
570 // video
571
572 int32_t width, height;
573 CHECK(codecRequest->findInt32("width", &width));
574 CHECK(codecRequest->findInt32("height", &height));
575
576 int32_t cropLeft, cropTop, cropRight, cropBottom;
577 CHECK(codecRequest->findRect(
578 "crop",
579 &cropLeft, &cropTop, &cropRight, &cropBottom));
580
581 int32_t displayWidth = cropRight - cropLeft + 1;
582 int32_t displayHeight = cropBottom - cropTop + 1;
583
584 ALOGV("Video output format changed to %d x %d "
585 "(crop: %d x %d @ (%d, %d))",
586 width, height,
587 displayWidth,
588 displayHeight,
589 cropLeft, cropTop);
590
591 sp<AMessage> videoInputFormat =
592 mSource->getFormat(false /* audio */);
593
594 // Take into account sample aspect ratio if necessary:
595 int32_t sarWidth, sarHeight;
596 if (videoInputFormat->findInt32("sar-width", &sarWidth)
597 && videoInputFormat->findInt32(
598 "sar-height", &sarHeight)) {
599 ALOGV("Sample aspect ratio %d : %d",
600 sarWidth, sarHeight);
601
602 displayWidth = (displayWidth * sarWidth) / sarHeight;
603
604 ALOGV("display dimensions %d x %d",
605 displayWidth, displayHeight);
606 }
607
608 notifyListener(
609 MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight);
610 }
611 } else if (what == ACodec::kWhatShutdownCompleted) {
612 ALOGV("%s shutdown completed", audio ? "audio" : "video");
613 if (audio) {
614 mAudioDecoder.clear();
615
616 CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
617 mFlushingAudio = SHUT_DOWN;
618 } else {
619 mVideoDecoder.clear();
620
621 CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
622 mFlushingVideo = SHUT_DOWN;
623 }
624
625 finishFlushIfPossible();
626 } else if (what == ACodec::kWhatError) {
627 ALOGE("Received error from %s decoder, aborting playback.",
628 audio ? "audio" : "video");
629
630 mRenderer->queueEOS(audio, UNKNOWN_ERROR);
631 } else if (what == ACodec::kWhatDrainThisBuffer) {
632 renderBuffer(audio, codecRequest);
633 } else if (what != ACodec::kWhatComponentAllocated
634 && what != ACodec::kWhatComponentConfigured
635 && what != ACodec::kWhatBuffersAllocated) {
636 ALOGV("Unhandled codec notification %d '%c%c%c%c'.",
637 what,
638 what >> 24,
639 (what >> 16) & 0xff,
640 (what >> 8) & 0xff,
641 what & 0xff);
642 }
643
644 break;
645 }
646
647 case kWhatRendererNotify:
648 {
649 int32_t what;
650 CHECK(msg->findInt32("what", &what));
651
652 if (what == Renderer::kWhatEOS) {
653 int32_t audio;
654 CHECK(msg->findInt32("audio", &audio));
655
656 int32_t finalResult;
657 CHECK(msg->findInt32("finalResult", &finalResult));
658
659 if (audio) {
660 mAudioEOS = true;
661 } else {
662 mVideoEOS = true;
663 }
664
665 if (finalResult == ERROR_END_OF_STREAM) {
666 ALOGV("reached %s EOS", audio ? "audio" : "video");
667 } else {
668 ALOGE("%s track encountered an error (%d)",
669 audio ? "audio" : "video", finalResult);
670
671 notifyListener(
672 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult);
673 }
674
675 if ((mAudioEOS || mAudioDecoder == NULL)
676 && (mVideoEOS || mVideoDecoder == NULL)) {
677 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
678 }
679 } else if (what == Renderer::kWhatPosition) {
680 int64_t positionUs;
681 CHECK(msg->findInt64("positionUs", &positionUs));
682
683 CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs));
684
685 if (mDriver != NULL) {
686 sp<NuPlayerDriver> driver = mDriver.promote();
687 if (driver != NULL) {
688 driver->notifyPosition(positionUs);
689
690 driver->notifyFrameStats(
691 mNumFramesTotal, mNumFramesDropped);
692 }
693 }
694 } else if (what == Renderer::kWhatFlushComplete) {
695 int32_t audio;
696 CHECK(msg->findInt32("audio", &audio));
697
698 ALOGV("renderer %s flush completed.", audio ? "audio" : "video");
699 } else if (what == Renderer::kWhatVideoRenderingStart) {
700 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0);
701 }
702 break;
703 }
704
705 case kWhatMoreDataQueued:
706 {
707 break;
708 }
709
710 case kWhatReset:
711 {
712 ALOGV("kWhatReset");
713
714 mDeferredActions.push_back(
715 new SimpleAction(&NuPlayer::performDecoderShutdown));
716
717 mDeferredActions.push_back(
718 new SimpleAction(&NuPlayer::performReset));
719
720 processDeferredActions();
721 break;
722 }
723
724 case kWhatSeek:
725 {
726 int64_t seekTimeUs;
727 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
728
729 ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs);
730
731 mDeferredActions.push_back(
732 new SimpleAction(&NuPlayer::performDecoderFlush));
733
734 mDeferredActions.push_back(new SeekAction(seekTimeUs));
735
736 processDeferredActions();
737 break;
738 }
739
740 case kWhatPause:
741 {
742 CHECK(mRenderer != NULL);
743 mSource->pause();
744 mRenderer->pause();
745 break;
746 }
747
748 case kWhatResume:
749 {
750 CHECK(mRenderer != NULL);
751 mSource->resume();
752 mRenderer->resume();
753 break;
754 }
755
756 case kWhatSourceNotify:
757 {
758 onSourceNotify(msg);
759 break;
760 }
761
762 default:
763 TRESPASS();
764 break;
765 }
766 }
767
finishFlushIfPossible()768 void NuPlayer::finishFlushIfPossible() {
769 if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
770 return;
771 }
772
773 if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
774 return;
775 }
776
777 ALOGV("both audio and video are flushed now.");
778
779 if (mTimeDiscontinuityPending) {
780 mRenderer->signalTimeDiscontinuity();
781 mTimeDiscontinuityPending = false;
782 }
783
784 if (mAudioDecoder != NULL) {
785 mAudioDecoder->signalResume();
786 }
787
788 if (mVideoDecoder != NULL) {
789 mVideoDecoder->signalResume();
790 }
791
792 mFlushingAudio = NONE;
793 mFlushingVideo = NONE;
794
795 processDeferredActions();
796 }
797
postScanSources()798 void NuPlayer::postScanSources() {
799 if (mScanSourcesPending) {
800 return;
801 }
802
803 sp<AMessage> msg = new AMessage(kWhatScanSources, id());
804 msg->setInt32("generation", mScanSourcesGeneration);
805 msg->post();
806
807 mScanSourcesPending = true;
808 }
809
instantiateDecoder(bool audio,sp<Decoder> * decoder)810 status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
811 if (*decoder != NULL) {
812 return OK;
813 }
814
815 sp<AMessage> format = mSource->getFormat(audio);
816
817 if (format == NULL) {
818 return -EWOULDBLOCK;
819 }
820
821 if (!audio) {
822 AString mime;
823 CHECK(format->findString("mime", &mime));
824 mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str());
825 }
826
827 sp<AMessage> notify =
828 new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify,
829 id());
830
831 *decoder = audio ? new Decoder(notify) :
832 new Decoder(notify, mNativeWindow);
833 looper()->registerHandler(*decoder);
834
835 (*decoder)->configure(format);
836
837 return OK;
838 }
839
feedDecoderInputData(bool audio,const sp<AMessage> & msg)840 status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
841 sp<AMessage> reply;
842 CHECK(msg->findMessage("reply", &reply));
843
844 if ((audio && IsFlushingState(mFlushingAudio))
845 || (!audio && IsFlushingState(mFlushingVideo))) {
846 reply->setInt32("err", INFO_DISCONTINUITY);
847 reply->post();
848 return OK;
849 }
850
851 sp<ABuffer> accessUnit;
852
853 bool dropAccessUnit;
854 do {
855 status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
856
857 if (err == -EWOULDBLOCK) {
858 return err;
859 } else if (err != OK) {
860 if (err == INFO_DISCONTINUITY) {
861 int32_t type;
862 CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
863
864 bool formatChange =
865 (audio &&
866 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
867 || (!audio &&
868 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
869
870 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
871
872 ALOGI("%s discontinuity (formatChange=%d, time=%d)",
873 audio ? "audio" : "video", formatChange, timeChange);
874
875 if (audio) {
876 mSkipRenderingAudioUntilMediaTimeUs = -1;
877 } else {
878 mSkipRenderingVideoUntilMediaTimeUs = -1;
879 }
880
881 if (timeChange) {
882 sp<AMessage> extra;
883 if (accessUnit->meta()->findMessage("extra", &extra)
884 && extra != NULL) {
885 int64_t resumeAtMediaTimeUs;
886 if (extra->findInt64(
887 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
888 ALOGI("suppressing rendering of %s until %lld us",
889 audio ? "audio" : "video", resumeAtMediaTimeUs);
890
891 if (audio) {
892 mSkipRenderingAudioUntilMediaTimeUs =
893 resumeAtMediaTimeUs;
894 } else {
895 mSkipRenderingVideoUntilMediaTimeUs =
896 resumeAtMediaTimeUs;
897 }
898 }
899 }
900 }
901
902 mTimeDiscontinuityPending =
903 mTimeDiscontinuityPending || timeChange;
904
905 if (formatChange || timeChange) {
906 if (mFlushingAudio == NONE && mFlushingVideo == NONE) {
907 // And we'll resume scanning sources once we're done
908 // flushing.
909 mDeferredActions.push_front(
910 new SimpleAction(
911 &NuPlayer::performScanSources));
912 }
913
914 flushDecoder(audio, formatChange);
915 } else {
916 // This stream is unaffected by the discontinuity
917
918 if (audio) {
919 mFlushingAudio = FLUSHED;
920 } else {
921 mFlushingVideo = FLUSHED;
922 }
923
924 finishFlushIfPossible();
925
926 return -EWOULDBLOCK;
927 }
928 }
929
930 reply->setInt32("err", err);
931 reply->post();
932 return OK;
933 }
934
935 if (!audio) {
936 ++mNumFramesTotal;
937 }
938
939 dropAccessUnit = false;
940 if (!audio
941 && mVideoLateByUs > 100000ll
942 && mVideoIsAVC
943 && !IsAVCReferenceFrame(accessUnit)) {
944 dropAccessUnit = true;
945 ++mNumFramesDropped;
946 }
947 } while (dropAccessUnit);
948
949 // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
950
951 #if 0
952 int64_t mediaTimeUs;
953 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
954 ALOGV("feeding %s input buffer at media time %.2f secs",
955 audio ? "audio" : "video",
956 mediaTimeUs / 1E6);
957 #endif
958
959 reply->setBuffer("buffer", accessUnit);
960 reply->post();
961
962 return OK;
963 }
964
renderBuffer(bool audio,const sp<AMessage> & msg)965 void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
966 // ALOGV("renderBuffer %s", audio ? "audio" : "video");
967
968 sp<AMessage> reply;
969 CHECK(msg->findMessage("reply", &reply));
970
971 if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) {
972 // We're currently attempting to flush the decoder, in order
973 // to complete this, the decoder wants all its buffers back,
974 // so we don't want any output buffers it sent us (from before
975 // we initiated the flush) to be stuck in the renderer's queue.
976
977 ALOGV("we're still flushing the %s decoder, sending its output buffer"
978 " right back.", audio ? "audio" : "video");
979
980 reply->post();
981 return;
982 }
983
984 sp<ABuffer> buffer;
985 CHECK(msg->findBuffer("buffer", &buffer));
986
987 int64_t &skipUntilMediaTimeUs =
988 audio
989 ? mSkipRenderingAudioUntilMediaTimeUs
990 : mSkipRenderingVideoUntilMediaTimeUs;
991
992 if (skipUntilMediaTimeUs >= 0) {
993 int64_t mediaTimeUs;
994 CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs));
995
996 if (mediaTimeUs < skipUntilMediaTimeUs) {
997 ALOGV("dropping %s buffer at time %lld as requested.",
998 audio ? "audio" : "video",
999 mediaTimeUs);
1000
1001 reply->post();
1002 return;
1003 }
1004
1005 skipUntilMediaTimeUs = -1;
1006 }
1007
1008 mRenderer->queueBuffer(audio, buffer, reply);
1009 }
1010
notifyListener(int msg,int ext1,int ext2)1011 void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
1012 if (mDriver == NULL) {
1013 return;
1014 }
1015
1016 sp<NuPlayerDriver> driver = mDriver.promote();
1017
1018 if (driver == NULL) {
1019 return;
1020 }
1021
1022 driver->notifyListener(msg, ext1, ext2);
1023 }
1024
flushDecoder(bool audio,bool needShutdown)1025 void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
1026 if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
1027 ALOGI("flushDecoder %s without decoder present",
1028 audio ? "audio" : "video");
1029 }
1030
1031 // Make sure we don't continue to scan sources until we finish flushing.
1032 ++mScanSourcesGeneration;
1033 mScanSourcesPending = false;
1034
1035 (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
1036 mRenderer->flush(audio);
1037
1038 FlushStatus newStatus =
1039 needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;
1040
1041 if (audio) {
1042 CHECK(mFlushingAudio == NONE
1043 || mFlushingAudio == AWAITING_DISCONTINUITY);
1044
1045 mFlushingAudio = newStatus;
1046
1047 if (mFlushingVideo == NONE) {
1048 mFlushingVideo = (mVideoDecoder != NULL)
1049 ? AWAITING_DISCONTINUITY
1050 : FLUSHED;
1051 }
1052 } else {
1053 CHECK(mFlushingVideo == NONE
1054 || mFlushingVideo == AWAITING_DISCONTINUITY);
1055
1056 mFlushingVideo = newStatus;
1057
1058 if (mFlushingAudio == NONE) {
1059 mFlushingAudio = (mAudioDecoder != NULL)
1060 ? AWAITING_DISCONTINUITY
1061 : FLUSHED;
1062 }
1063 }
1064 }
1065
getFormat(bool audio)1066 sp<AMessage> NuPlayer::Source::getFormat(bool audio) {
1067 sp<MetaData> meta = getFormatMeta(audio);
1068
1069 if (meta == NULL) {
1070 return NULL;
1071 }
1072
1073 sp<AMessage> msg = new AMessage;
1074
1075 if(convertMetaDataToMessage(meta, &msg) == OK) {
1076 return msg;
1077 }
1078 return NULL;
1079 }
1080
setVideoScalingMode(int32_t mode)1081 status_t NuPlayer::setVideoScalingMode(int32_t mode) {
1082 mVideoScalingMode = mode;
1083 if (mNativeWindow != NULL) {
1084 status_t ret = native_window_set_scaling_mode(
1085 mNativeWindow->getNativeWindow().get(), mVideoScalingMode);
1086 if (ret != OK) {
1087 ALOGE("Failed to set scaling mode (%d): %s",
1088 -ret, strerror(-ret));
1089 return ret;
1090 }
1091 }
1092 return OK;
1093 }
1094
schedulePollDuration()1095 void NuPlayer::schedulePollDuration() {
1096 sp<AMessage> msg = new AMessage(kWhatPollDuration, id());
1097 msg->setInt32("generation", mPollDurationGeneration);
1098 msg->post();
1099 }
1100
cancelPollDuration()1101 void NuPlayer::cancelPollDuration() {
1102 ++mPollDurationGeneration;
1103 }
1104
processDeferredActions()1105 void NuPlayer::processDeferredActions() {
1106 while (!mDeferredActions.empty()) {
1107 // We won't execute any deferred actions until we're no longer in
1108 // an intermediate state, i.e. one more more decoders are currently
1109 // flushing or shutting down.
1110
1111 if (mRenderer != NULL) {
1112 // There's an edge case where the renderer owns all output
1113 // buffers and is paused, therefore the decoder will not read
1114 // more input data and will never encounter the matching
1115 // discontinuity. To avoid this, we resume the renderer.
1116
1117 if (mFlushingAudio == AWAITING_DISCONTINUITY
1118 || mFlushingVideo == AWAITING_DISCONTINUITY) {
1119 mRenderer->resume();
1120 }
1121 }
1122
1123 if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
1124 // We're currently flushing, postpone the reset until that's
1125 // completed.
1126
1127 ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d",
1128 mFlushingAudio, mFlushingVideo);
1129
1130 break;
1131 }
1132
1133 sp<Action> action = *mDeferredActions.begin();
1134 mDeferredActions.erase(mDeferredActions.begin());
1135
1136 action->execute(this);
1137 }
1138 }
1139
performSeek(int64_t seekTimeUs)1140 void NuPlayer::performSeek(int64_t seekTimeUs) {
1141 ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)",
1142 seekTimeUs,
1143 seekTimeUs / 1E6);
1144
1145 mSource->seekTo(seekTimeUs);
1146
1147 if (mDriver != NULL) {
1148 sp<NuPlayerDriver> driver = mDriver.promote();
1149 if (driver != NULL) {
1150 driver->notifyPosition(seekTimeUs);
1151 driver->notifySeekComplete();
1152 }
1153 }
1154
1155 // everything's flushed, continue playback.
1156 }
1157
performDecoderFlush()1158 void NuPlayer::performDecoderFlush() {
1159 ALOGV("performDecoderFlush");
1160
1161 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
1162 return;
1163 }
1164
1165 mTimeDiscontinuityPending = true;
1166
1167 if (mAudioDecoder != NULL) {
1168 flushDecoder(true /* audio */, false /* needShutdown */);
1169 }
1170
1171 if (mVideoDecoder != NULL) {
1172 flushDecoder(false /* audio */, false /* needShutdown */);
1173 }
1174 }
1175
performDecoderShutdown()1176 void NuPlayer::performDecoderShutdown() {
1177 ALOGV("performDecoderShutdown");
1178
1179 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
1180 return;
1181 }
1182
1183 mTimeDiscontinuityPending = true;
1184
1185 if (mAudioDecoder != NULL) {
1186 flushDecoder(true /* audio */, true /* needShutdown */);
1187 }
1188
1189 if (mVideoDecoder != NULL) {
1190 flushDecoder(false /* audio */, true /* needShutdown */);
1191 }
1192 }
1193
performReset()1194 void NuPlayer::performReset() {
1195 ALOGV("performReset");
1196
1197 CHECK(mAudioDecoder == NULL);
1198 CHECK(mVideoDecoder == NULL);
1199
1200 cancelPollDuration();
1201
1202 ++mScanSourcesGeneration;
1203 mScanSourcesPending = false;
1204
1205 mRenderer.clear();
1206
1207 if (mSource != NULL) {
1208 mSource->stop();
1209
1210 looper()->unregisterHandler(mSource->id());
1211
1212 mSource.clear();
1213 }
1214
1215 if (mDriver != NULL) {
1216 sp<NuPlayerDriver> driver = mDriver.promote();
1217 if (driver != NULL) {
1218 driver->notifyResetComplete();
1219 }
1220 }
1221
1222 mStarted = false;
1223 }
1224
performScanSources()1225 void NuPlayer::performScanSources() {
1226 ALOGV("performScanSources");
1227
1228 if (!mStarted) {
1229 return;
1230 }
1231
1232 if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
1233 postScanSources();
1234 }
1235 }
1236
performSetSurface(const sp<NativeWindowWrapper> & wrapper)1237 void NuPlayer::performSetSurface(const sp<NativeWindowWrapper> &wrapper) {
1238 ALOGV("performSetSurface");
1239
1240 mNativeWindow = wrapper;
1241
1242 // XXX - ignore error from setVideoScalingMode for now
1243 setVideoScalingMode(mVideoScalingMode);
1244
1245 if (mDriver != NULL) {
1246 sp<NuPlayerDriver> driver = mDriver.promote();
1247 if (driver != NULL) {
1248 driver->notifySetSurfaceComplete();
1249 }
1250 }
1251 }
1252
onSourceNotify(const sp<AMessage> & msg)1253 void NuPlayer::onSourceNotify(const sp<AMessage> &msg) {
1254 int32_t what;
1255 CHECK(msg->findInt32("what", &what));
1256
1257 switch (what) {
1258 case Source::kWhatPrepared:
1259 {
1260 if (mSource == NULL) {
1261 // This is a stale notification from a source that was
1262 // asynchronously preparing when the client called reset().
1263 // We handled the reset, the source is gone.
1264 break;
1265 }
1266
1267 int32_t err;
1268 CHECK(msg->findInt32("err", &err));
1269
1270 sp<NuPlayerDriver> driver = mDriver.promote();
1271 if (driver != NULL) {
1272 driver->notifyPrepareCompleted(err);
1273 }
1274
1275 int64_t durationUs;
1276 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
1277 sp<NuPlayerDriver> driver = mDriver.promote();
1278 if (driver != NULL) {
1279 driver->notifyDuration(durationUs);
1280 }
1281 }
1282 break;
1283 }
1284
1285 case Source::kWhatFlagsChanged:
1286 {
1287 uint32_t flags;
1288 CHECK(msg->findInt32("flags", (int32_t *)&flags));
1289
1290 if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
1291 && (!(flags & Source::FLAG_DYNAMIC_DURATION))) {
1292 cancelPollDuration();
1293 } else if (!(mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
1294 && (flags & Source::FLAG_DYNAMIC_DURATION)
1295 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) {
1296 schedulePollDuration();
1297 }
1298
1299 mSourceFlags = flags;
1300 break;
1301 }
1302
1303 case Source::kWhatVideoSizeChanged:
1304 {
1305 int32_t width, height;
1306 CHECK(msg->findInt32("width", &width));
1307 CHECK(msg->findInt32("height", &height));
1308
1309 notifyListener(MEDIA_SET_VIDEO_SIZE, width, height);
1310 break;
1311 }
1312
1313 case Source::kWhatBufferingStart:
1314 {
1315 notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0);
1316 break;
1317 }
1318
1319 case Source::kWhatBufferingEnd:
1320 {
1321 notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0);
1322 break;
1323 }
1324
1325 default:
1326 TRESPASS();
1327 }
1328 }
1329
1330 ////////////////////////////////////////////////////////////////////////////////
1331
notifyFlagsChanged(uint32_t flags)1332 void NuPlayer::Source::notifyFlagsChanged(uint32_t flags) {
1333 sp<AMessage> notify = dupNotify();
1334 notify->setInt32("what", kWhatFlagsChanged);
1335 notify->setInt32("flags", flags);
1336 notify->post();
1337 }
1338
notifyVideoSizeChanged(int32_t width,int32_t height)1339 void NuPlayer::Source::notifyVideoSizeChanged(int32_t width, int32_t height) {
1340 sp<AMessage> notify = dupNotify();
1341 notify->setInt32("what", kWhatVideoSizeChanged);
1342 notify->setInt32("width", width);
1343 notify->setInt32("height", height);
1344 notify->post();
1345 }
1346
notifyPrepared(status_t err)1347 void NuPlayer::Source::notifyPrepared(status_t err) {
1348 sp<AMessage> notify = dupNotify();
1349 notify->setInt32("what", kWhatPrepared);
1350 notify->setInt32("err", err);
1351 notify->post();
1352 }
1353
onMessageReceived(const sp<AMessage> & msg)1354 void NuPlayer::Source::onMessageReceived(const sp<AMessage> &msg) {
1355 TRESPASS();
1356 }
1357
1358 } // namespace android
1359