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