NuPlayer.cpp revision 57cea553cb19235553463412db5ad04c99835411
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 SurfaceTextureClient(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 mRenderer = new Renderer( 385 mAudioSink, 386 new AMessage(kWhatRendererNotify, id())); 387 388 looper()->registerHandler(mRenderer); 389 390 postScanSources(); 391 break; 392 } 393 394 case kWhatScanSources: 395 { 396 int32_t generation; 397 CHECK(msg->findInt32("generation", &generation)); 398 if (generation != mScanSourcesGeneration) { 399 // Drop obsolete msg. 400 break; 401 } 402 403 mScanSourcesPending = false; 404 405 ALOGV("scanning sources haveAudio=%d, haveVideo=%d", 406 mAudioDecoder != NULL, mVideoDecoder != NULL); 407 408 bool mHadAnySourcesBefore = 409 (mAudioDecoder != NULL) || (mVideoDecoder != NULL); 410 411 if (mNativeWindow != NULL) { 412 instantiateDecoder(false, &mVideoDecoder); 413 } 414 415 if (mAudioSink != NULL) { 416 instantiateDecoder(true, &mAudioDecoder); 417 } 418 419 if (!mHadAnySourcesBefore 420 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) { 421 // This is the first time we've found anything playable. 422 423 if (mSourceFlags & Source::FLAG_DYNAMIC_DURATION) { 424 schedulePollDuration(); 425 } 426 } 427 428 status_t err; 429 if ((err = mSource->feedMoreTSData()) != OK) { 430 if (mAudioDecoder == NULL && mVideoDecoder == NULL) { 431 // We're not currently decoding anything (no audio or 432 // video tracks found) and we just ran out of input data. 433 434 if (err == ERROR_END_OF_STREAM) { 435 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); 436 } else { 437 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 438 } 439 } 440 break; 441 } 442 443 if ((mAudioDecoder == NULL && mAudioSink != NULL) 444 || (mVideoDecoder == NULL && mNativeWindow != NULL)) { 445 msg->post(100000ll); 446 mScanSourcesPending = true; 447 } 448 break; 449 } 450 451 case kWhatVideoNotify: 452 case kWhatAudioNotify: 453 { 454 bool audio = msg->what() == kWhatAudioNotify; 455 456 sp<AMessage> codecRequest; 457 CHECK(msg->findMessage("codec-request", &codecRequest)); 458 459 int32_t what; 460 CHECK(codecRequest->findInt32("what", &what)); 461 462 if (what == ACodec::kWhatFillThisBuffer) { 463 status_t err = feedDecoderInputData( 464 audio, codecRequest); 465 466 if (err == -EWOULDBLOCK) { 467 if (mSource->feedMoreTSData() == OK) { 468 msg->post(10000ll); 469 } 470 } 471 } else if (what == ACodec::kWhatEOS) { 472 int32_t err; 473 CHECK(codecRequest->findInt32("err", &err)); 474 475 if (err == ERROR_END_OF_STREAM) { 476 ALOGV("got %s decoder EOS", audio ? "audio" : "video"); 477 } else { 478 ALOGV("got %s decoder EOS w/ error %d", 479 audio ? "audio" : "video", 480 err); 481 } 482 483 mRenderer->queueEOS(audio, err); 484 } else if (what == ACodec::kWhatFlushCompleted) { 485 bool needShutdown; 486 487 if (audio) { 488 CHECK(IsFlushingState(mFlushingAudio, &needShutdown)); 489 mFlushingAudio = FLUSHED; 490 } else { 491 CHECK(IsFlushingState(mFlushingVideo, &needShutdown)); 492 mFlushingVideo = FLUSHED; 493 494 mVideoLateByUs = 0; 495 } 496 497 ALOGV("decoder %s flush completed", audio ? "audio" : "video"); 498 499 if (needShutdown) { 500 ALOGV("initiating %s decoder shutdown", 501 audio ? "audio" : "video"); 502 503 (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown(); 504 505 if (audio) { 506 mFlushingAudio = SHUTTING_DOWN_DECODER; 507 } else { 508 mFlushingVideo = SHUTTING_DOWN_DECODER; 509 } 510 } 511 512 finishFlushIfPossible(); 513 } else if (what == ACodec::kWhatOutputFormatChanged) { 514 if (audio) { 515 int32_t numChannels; 516 CHECK(codecRequest->findInt32( 517 "channel-count", &numChannels)); 518 519 int32_t sampleRate; 520 CHECK(codecRequest->findInt32("sample-rate", &sampleRate)); 521 522 ALOGV("Audio output format changed to %d Hz, %d channels", 523 sampleRate, numChannels); 524 525 mAudioSink->close(); 526 527 audio_output_flags_t flags; 528 int64_t durationUs; 529 // FIXME: we should handle the case where the video decoder 530 // is created after we receive the format change indication. 531 // Current code will just make that we select deep buffer 532 // with video which should not be a problem as it should 533 // not prevent from keeping A/V sync. 534 if (mVideoDecoder == NULL && 535 mSource->getDuration(&durationUs) == OK && 536 durationUs 537 > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) { 538 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; 539 } else { 540 flags = AUDIO_OUTPUT_FLAG_NONE; 541 } 542 543 int32_t channelMask; 544 if (!codecRequest->findInt32("channel-mask", &channelMask)) { 545 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER; 546 } 547 548 CHECK_EQ(mAudioSink->open( 549 sampleRate, 550 numChannels, 551 (audio_channel_mask_t)channelMask, 552 AUDIO_FORMAT_PCM_16_BIT, 553 8 /* bufferCount */, 554 NULL, 555 NULL, 556 flags), 557 (status_t)OK); 558 mAudioSink->start(); 559 560 mRenderer->signalAudioSinkChanged(); 561 } else { 562 // video 563 564 int32_t width, height; 565 CHECK(codecRequest->findInt32("width", &width)); 566 CHECK(codecRequest->findInt32("height", &height)); 567 568 int32_t cropLeft, cropTop, cropRight, cropBottom; 569 CHECK(codecRequest->findRect( 570 "crop", 571 &cropLeft, &cropTop, &cropRight, &cropBottom)); 572 573 int32_t displayWidth = cropRight - cropLeft + 1; 574 int32_t displayHeight = cropBottom - cropTop + 1; 575 576 ALOGV("Video output format changed to %d x %d " 577 "(crop: %d x %d @ (%d, %d))", 578 width, height, 579 displayWidth, 580 displayHeight, 581 cropLeft, cropTop); 582 583 sp<AMessage> videoInputFormat = 584 mSource->getFormat(false /* audio */); 585 586 // Take into account sample aspect ratio if necessary: 587 int32_t sarWidth, sarHeight; 588 if (videoInputFormat->findInt32("sar-width", &sarWidth) 589 && videoInputFormat->findInt32( 590 "sar-height", &sarHeight)) { 591 ALOGV("Sample aspect ratio %d : %d", 592 sarWidth, sarHeight); 593 594 displayWidth = (displayWidth * sarWidth) / sarHeight; 595 596 ALOGV("display dimensions %d x %d", 597 displayWidth, displayHeight); 598 } 599 600 notifyListener( 601 MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight); 602 } 603 } else if (what == ACodec::kWhatShutdownCompleted) { 604 ALOGV("%s shutdown completed", audio ? "audio" : "video"); 605 if (audio) { 606 mAudioDecoder.clear(); 607 608 CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER); 609 mFlushingAudio = SHUT_DOWN; 610 } else { 611 mVideoDecoder.clear(); 612 613 CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER); 614 mFlushingVideo = SHUT_DOWN; 615 } 616 617 finishFlushIfPossible(); 618 } else if (what == ACodec::kWhatError) { 619 ALOGE("Received error from %s decoder, aborting playback.", 620 audio ? "audio" : "video"); 621 622 mRenderer->queueEOS(audio, UNKNOWN_ERROR); 623 } else if (what == ACodec::kWhatDrainThisBuffer) { 624 renderBuffer(audio, codecRequest); 625 } else if (what != ACodec::kWhatComponentAllocated 626 && what != ACodec::kWhatComponentConfigured 627 && what != ACodec::kWhatBuffersAllocated) { 628 ALOGV("Unhandled codec notification %d '%c%c%c%c'.", 629 what, 630 what >> 24, 631 (what >> 16) & 0xff, 632 (what >> 8) & 0xff, 633 what & 0xff); 634 } 635 636 break; 637 } 638 639 case kWhatRendererNotify: 640 { 641 int32_t what; 642 CHECK(msg->findInt32("what", &what)); 643 644 if (what == Renderer::kWhatEOS) { 645 int32_t audio; 646 CHECK(msg->findInt32("audio", &audio)); 647 648 int32_t finalResult; 649 CHECK(msg->findInt32("finalResult", &finalResult)); 650 651 if (audio) { 652 mAudioEOS = true; 653 } else { 654 mVideoEOS = true; 655 } 656 657 if (finalResult == ERROR_END_OF_STREAM) { 658 ALOGV("reached %s EOS", audio ? "audio" : "video"); 659 } else { 660 ALOGE("%s track encountered an error (%d)", 661 audio ? "audio" : "video", finalResult); 662 663 notifyListener( 664 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult); 665 } 666 667 if ((mAudioEOS || mAudioDecoder == NULL) 668 && (mVideoEOS || mVideoDecoder == NULL)) { 669 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); 670 } 671 } else if (what == Renderer::kWhatPosition) { 672 int64_t positionUs; 673 CHECK(msg->findInt64("positionUs", &positionUs)); 674 675 CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs)); 676 677 if (mDriver != NULL) { 678 sp<NuPlayerDriver> driver = mDriver.promote(); 679 if (driver != NULL) { 680 driver->notifyPosition(positionUs); 681 682 driver->notifyFrameStats( 683 mNumFramesTotal, mNumFramesDropped); 684 } 685 } 686 } else if (what == Renderer::kWhatFlushComplete) { 687 int32_t audio; 688 CHECK(msg->findInt32("audio", &audio)); 689 690 ALOGV("renderer %s flush completed.", audio ? "audio" : "video"); 691 } else if (what == Renderer::kWhatVideoRenderingStart) { 692 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0); 693 } 694 break; 695 } 696 697 case kWhatMoreDataQueued: 698 { 699 break; 700 } 701 702 case kWhatReset: 703 { 704 ALOGV("kWhatReset"); 705 706 mDeferredActions.push_back( 707 new SimpleAction(&NuPlayer::performDecoderShutdown)); 708 709 mDeferredActions.push_back( 710 new SimpleAction(&NuPlayer::performReset)); 711 712 processDeferredActions(); 713 break; 714 } 715 716 case kWhatSeek: 717 { 718 int64_t seekTimeUs; 719 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs)); 720 721 ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs); 722 723 mDeferredActions.push_back( 724 new SimpleAction(&NuPlayer::performDecoderFlush)); 725 726 mDeferredActions.push_back(new SeekAction(seekTimeUs)); 727 728 processDeferredActions(); 729 break; 730 } 731 732 case kWhatPause: 733 { 734 CHECK(mRenderer != NULL); 735 mRenderer->pause(); 736 break; 737 } 738 739 case kWhatResume: 740 { 741 CHECK(mRenderer != NULL); 742 mRenderer->resume(); 743 break; 744 } 745 746 case kWhatSourceNotify: 747 { 748 onSourceNotify(msg); 749 break; 750 } 751 752 default: 753 TRESPASS(); 754 break; 755 } 756} 757 758void NuPlayer::finishFlushIfPossible() { 759 if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) { 760 return; 761 } 762 763 if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) { 764 return; 765 } 766 767 ALOGV("both audio and video are flushed now."); 768 769 if (mTimeDiscontinuityPending) { 770 mRenderer->signalTimeDiscontinuity(); 771 mTimeDiscontinuityPending = false; 772 } 773 774 if (mAudioDecoder != NULL) { 775 mAudioDecoder->signalResume(); 776 } 777 778 if (mVideoDecoder != NULL) { 779 mVideoDecoder->signalResume(); 780 } 781 782 mFlushingAudio = NONE; 783 mFlushingVideo = NONE; 784 785 processDeferredActions(); 786} 787 788void NuPlayer::postScanSources() { 789 if (mScanSourcesPending) { 790 return; 791 } 792 793 sp<AMessage> msg = new AMessage(kWhatScanSources, id()); 794 msg->setInt32("generation", mScanSourcesGeneration); 795 msg->post(); 796 797 mScanSourcesPending = true; 798} 799 800status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) { 801 if (*decoder != NULL) { 802 return OK; 803 } 804 805 sp<AMessage> format = mSource->getFormat(audio); 806 807 if (format == NULL) { 808 return -EWOULDBLOCK; 809 } 810 811 if (!audio) { 812 AString mime; 813 CHECK(format->findString("mime", &mime)); 814 mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str()); 815 } 816 817 sp<AMessage> notify = 818 new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify, 819 id()); 820 821 *decoder = audio ? new Decoder(notify) : 822 new Decoder(notify, mNativeWindow); 823 looper()->registerHandler(*decoder); 824 825 (*decoder)->configure(format); 826 827 int64_t durationUs; 828 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) { 829 sp<NuPlayerDriver> driver = mDriver.promote(); 830 if (driver != NULL) { 831 driver->notifyDuration(durationUs); 832 } 833 } 834 835 return OK; 836} 837 838status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { 839 sp<AMessage> reply; 840 CHECK(msg->findMessage("reply", &reply)); 841 842 if ((audio && IsFlushingState(mFlushingAudio)) 843 || (!audio && IsFlushingState(mFlushingVideo))) { 844 reply->setInt32("err", INFO_DISCONTINUITY); 845 reply->post(); 846 return OK; 847 } 848 849 sp<ABuffer> accessUnit; 850 851 bool dropAccessUnit; 852 do { 853 status_t err = mSource->dequeueAccessUnit(audio, &accessUnit); 854 855 if (err == -EWOULDBLOCK) { 856 return err; 857 } else if (err != OK) { 858 if (err == INFO_DISCONTINUITY) { 859 int32_t type; 860 CHECK(accessUnit->meta()->findInt32("discontinuity", &type)); 861 862 bool formatChange = 863 (audio && 864 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT)) 865 || (!audio && 866 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT)); 867 868 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0; 869 870 ALOGI("%s discontinuity (formatChange=%d, time=%d)", 871 audio ? "audio" : "video", formatChange, timeChange); 872 873 if (audio) { 874 mSkipRenderingAudioUntilMediaTimeUs = -1; 875 } else { 876 mSkipRenderingVideoUntilMediaTimeUs = -1; 877 } 878 879 if (timeChange) { 880 sp<AMessage> extra; 881 if (accessUnit->meta()->findMessage("extra", &extra) 882 && extra != NULL) { 883 int64_t resumeAtMediaTimeUs; 884 if (extra->findInt64( 885 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) { 886 ALOGI("suppressing rendering of %s until %lld us", 887 audio ? "audio" : "video", resumeAtMediaTimeUs); 888 889 if (audio) { 890 mSkipRenderingAudioUntilMediaTimeUs = 891 resumeAtMediaTimeUs; 892 } else { 893 mSkipRenderingVideoUntilMediaTimeUs = 894 resumeAtMediaTimeUs; 895 } 896 } 897 } 898 } 899 900 mTimeDiscontinuityPending = 901 mTimeDiscontinuityPending || timeChange; 902 903 if (formatChange || timeChange) { 904 if (mFlushingAudio == NONE && mFlushingVideo == NONE) { 905 // And we'll resume scanning sources once we're done 906 // flushing. 907 mDeferredActions.push_front( 908 new SimpleAction( 909 &NuPlayer::performScanSources)); 910 } 911 912 flushDecoder(audio, formatChange); 913 } else { 914 // This stream is unaffected by the discontinuity 915 916 if (audio) { 917 mFlushingAudio = FLUSHED; 918 } else { 919 mFlushingVideo = FLUSHED; 920 } 921 922 finishFlushIfPossible(); 923 924 return -EWOULDBLOCK; 925 } 926 } 927 928 reply->setInt32("err", err); 929 reply->post(); 930 return OK; 931 } 932 933 if (!audio) { 934 ++mNumFramesTotal; 935 } 936 937 dropAccessUnit = false; 938 if (!audio 939 && mVideoLateByUs > 100000ll 940 && mVideoIsAVC 941 && !IsAVCReferenceFrame(accessUnit)) { 942 dropAccessUnit = true; 943 ++mNumFramesDropped; 944 } 945 } while (dropAccessUnit); 946 947 // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video"); 948 949#if 0 950 int64_t mediaTimeUs; 951 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs)); 952 ALOGV("feeding %s input buffer at media time %.2f secs", 953 audio ? "audio" : "video", 954 mediaTimeUs / 1E6); 955#endif 956 957 reply->setBuffer("buffer", accessUnit); 958 reply->post(); 959 960 return OK; 961} 962 963void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) { 964 // ALOGV("renderBuffer %s", audio ? "audio" : "video"); 965 966 sp<AMessage> reply; 967 CHECK(msg->findMessage("reply", &reply)); 968 969 if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) { 970 // We're currently attempting to flush the decoder, in order 971 // to complete this, the decoder wants all its buffers back, 972 // so we don't want any output buffers it sent us (from before 973 // we initiated the flush) to be stuck in the renderer's queue. 974 975 ALOGV("we're still flushing the %s decoder, sending its output buffer" 976 " right back.", audio ? "audio" : "video"); 977 978 reply->post(); 979 return; 980 } 981 982 sp<ABuffer> buffer; 983 CHECK(msg->findBuffer("buffer", &buffer)); 984 985 int64_t &skipUntilMediaTimeUs = 986 audio 987 ? mSkipRenderingAudioUntilMediaTimeUs 988 : mSkipRenderingVideoUntilMediaTimeUs; 989 990 if (skipUntilMediaTimeUs >= 0) { 991 int64_t mediaTimeUs; 992 CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs)); 993 994 if (mediaTimeUs < skipUntilMediaTimeUs) { 995 ALOGV("dropping %s buffer at time %lld as requested.", 996 audio ? "audio" : "video", 997 mediaTimeUs); 998 999 reply->post(); 1000 return; 1001 } 1002 1003 skipUntilMediaTimeUs = -1; 1004 } 1005 1006 mRenderer->queueBuffer(audio, buffer, reply); 1007} 1008 1009void NuPlayer::notifyListener(int msg, int ext1, int ext2) { 1010 if (mDriver == NULL) { 1011 return; 1012 } 1013 1014 sp<NuPlayerDriver> driver = mDriver.promote(); 1015 1016 if (driver == NULL) { 1017 return; 1018 } 1019 1020 driver->notifyListener(msg, ext1, ext2); 1021} 1022 1023void NuPlayer::flushDecoder(bool audio, bool needShutdown) { 1024 if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) { 1025 ALOGI("flushDecoder %s without decoder present", 1026 audio ? "audio" : "video"); 1027 } 1028 1029 // Make sure we don't continue to scan sources until we finish flushing. 1030 ++mScanSourcesGeneration; 1031 mScanSourcesPending = false; 1032 1033 (audio ? mAudioDecoder : mVideoDecoder)->signalFlush(); 1034 mRenderer->flush(audio); 1035 1036 FlushStatus newStatus = 1037 needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER; 1038 1039 if (audio) { 1040 CHECK(mFlushingAudio == NONE 1041 || mFlushingAudio == AWAITING_DISCONTINUITY); 1042 1043 mFlushingAudio = newStatus; 1044 1045 if (mFlushingVideo == NONE) { 1046 mFlushingVideo = (mVideoDecoder != NULL) 1047 ? AWAITING_DISCONTINUITY 1048 : FLUSHED; 1049 } 1050 } else { 1051 CHECK(mFlushingVideo == NONE 1052 || mFlushingVideo == AWAITING_DISCONTINUITY); 1053 1054 mFlushingVideo = newStatus; 1055 1056 if (mFlushingAudio == NONE) { 1057 mFlushingAudio = (mAudioDecoder != NULL) 1058 ? AWAITING_DISCONTINUITY 1059 : FLUSHED; 1060 } 1061 } 1062} 1063 1064sp<AMessage> NuPlayer::Source::getFormat(bool audio) { 1065 sp<MetaData> meta = getFormatMeta(audio); 1066 1067 if (meta == NULL) { 1068 return NULL; 1069 } 1070 1071 sp<AMessage> msg = new AMessage; 1072 1073 if(convertMetaDataToMessage(meta, &msg) == OK) { 1074 return msg; 1075 } 1076 return NULL; 1077} 1078 1079status_t NuPlayer::setVideoScalingMode(int32_t mode) { 1080 mVideoScalingMode = mode; 1081 if (mNativeWindow != NULL) { 1082 status_t ret = native_window_set_scaling_mode( 1083 mNativeWindow->getNativeWindow().get(), mVideoScalingMode); 1084 if (ret != OK) { 1085 ALOGE("Failed to set scaling mode (%d): %s", 1086 -ret, strerror(-ret)); 1087 return ret; 1088 } 1089 } 1090 return OK; 1091} 1092 1093void NuPlayer::schedulePollDuration() { 1094 sp<AMessage> msg = new AMessage(kWhatPollDuration, id()); 1095 msg->setInt32("generation", mPollDurationGeneration); 1096 msg->post(); 1097} 1098 1099void NuPlayer::cancelPollDuration() { 1100 ++mPollDurationGeneration; 1101} 1102 1103void NuPlayer::processDeferredActions() { 1104 while (!mDeferredActions.empty()) { 1105 // We won't execute any deferred actions until we're no longer in 1106 // an intermediate state, i.e. one more more decoders are currently 1107 // flushing or shutting down. 1108 1109 if (mRenderer != NULL) { 1110 // There's an edge case where the renderer owns all output 1111 // buffers and is paused, therefore the decoder will not read 1112 // more input data and will never encounter the matching 1113 // discontinuity. To avoid this, we resume the renderer. 1114 1115 if (mFlushingAudio == AWAITING_DISCONTINUITY 1116 || mFlushingVideo == AWAITING_DISCONTINUITY) { 1117 mRenderer->resume(); 1118 } 1119 } 1120 1121 if (mFlushingAudio != NONE || mFlushingVideo != NONE) { 1122 // We're currently flushing, postpone the reset until that's 1123 // completed. 1124 1125 ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d", 1126 mFlushingAudio, mFlushingVideo); 1127 1128 break; 1129 } 1130 1131 sp<Action> action = *mDeferredActions.begin(); 1132 mDeferredActions.erase(mDeferredActions.begin()); 1133 1134 action->execute(this); 1135 } 1136} 1137 1138void NuPlayer::performSeek(int64_t seekTimeUs) { 1139 ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)", 1140 seekTimeUs, 1141 seekTimeUs / 1E6); 1142 1143 mSource->seekTo(seekTimeUs); 1144 1145 if (mDriver != NULL) { 1146 sp<NuPlayerDriver> driver = mDriver.promote(); 1147 if (driver != NULL) { 1148 driver->notifyPosition(seekTimeUs); 1149 driver->notifySeekComplete(); 1150 } 1151 } 1152 1153 // everything's flushed, continue playback. 1154} 1155 1156void NuPlayer::performDecoderFlush() { 1157 ALOGV("performDecoderFlush"); 1158 1159 if (mAudioDecoder != NULL && mVideoDecoder == NULL) { 1160 return; 1161 } 1162 1163 mTimeDiscontinuityPending = true; 1164 1165 if (mAudioDecoder != NULL) { 1166 flushDecoder(true /* audio */, false /* needShutdown */); 1167 } 1168 1169 if (mVideoDecoder != NULL) { 1170 flushDecoder(false /* audio */, false /* needShutdown */); 1171 } 1172} 1173 1174void NuPlayer::performDecoderShutdown() { 1175 ALOGV("performDecoderShutdown"); 1176 1177 if (mAudioDecoder != NULL && mVideoDecoder == NULL) { 1178 return; 1179 } 1180 1181 mTimeDiscontinuityPending = true; 1182 1183 if (mAudioDecoder != NULL) { 1184 flushDecoder(true /* audio */, true /* needShutdown */); 1185 } 1186 1187 if (mVideoDecoder != NULL) { 1188 flushDecoder(false /* audio */, true /* needShutdown */); 1189 } 1190} 1191 1192void NuPlayer::performReset() { 1193 ALOGV("performReset"); 1194 1195 CHECK(mAudioDecoder == NULL); 1196 CHECK(mVideoDecoder == NULL); 1197 1198 cancelPollDuration(); 1199 1200 ++mScanSourcesGeneration; 1201 mScanSourcesPending = false; 1202 1203 mRenderer.clear(); 1204 1205 if (mSource != NULL) { 1206 mSource->stop(); 1207 1208 looper()->unregisterHandler(mSource->id()); 1209 1210 mSource.clear(); 1211 } 1212 1213 if (mDriver != NULL) { 1214 sp<NuPlayerDriver> driver = mDriver.promote(); 1215 if (driver != NULL) { 1216 driver->notifyResetComplete(); 1217 } 1218 } 1219 1220 mStarted = false; 1221} 1222 1223void NuPlayer::performScanSources() { 1224 ALOGV("performScanSources"); 1225 1226 if (!mStarted) { 1227 return; 1228 } 1229 1230 if (mAudioDecoder == NULL || mVideoDecoder == NULL) { 1231 postScanSources(); 1232 } 1233} 1234 1235void NuPlayer::performSetSurface(const sp<NativeWindowWrapper> &wrapper) { 1236 ALOGV("performSetSurface"); 1237 1238 mNativeWindow = wrapper; 1239 1240 // XXX - ignore error from setVideoScalingMode for now 1241 setVideoScalingMode(mVideoScalingMode); 1242 1243 if (mDriver != NULL) { 1244 sp<NuPlayerDriver> driver = mDriver.promote(); 1245 if (driver != NULL) { 1246 driver->notifySetSurfaceComplete(); 1247 } 1248 } 1249} 1250 1251void NuPlayer::onSourceNotify(const sp<AMessage> &msg) { 1252 int32_t what; 1253 CHECK(msg->findInt32("what", &what)); 1254 1255 switch (what) { 1256 case Source::kWhatPrepared: 1257 { 1258 sp<NuPlayerDriver> driver = mDriver.promote(); 1259 if (driver != NULL) { 1260 driver->notifyPrepareCompleted(OK); 1261 } 1262 break; 1263 } 1264 1265 case Source::kWhatFlagsChanged: 1266 { 1267 uint32_t flags; 1268 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 1269 1270 if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION) 1271 && (!(flags & Source::FLAG_DYNAMIC_DURATION))) { 1272 cancelPollDuration(); 1273 } else if (!(mSourceFlags & Source::FLAG_DYNAMIC_DURATION) 1274 && (flags & Source::FLAG_DYNAMIC_DURATION) 1275 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) { 1276 schedulePollDuration(); 1277 } 1278 1279 mSourceFlags = flags; 1280 break; 1281 } 1282 1283 case Source::kWhatVideoSizeChanged: 1284 { 1285 int32_t width, height; 1286 CHECK(msg->findInt32("width", &width)); 1287 CHECK(msg->findInt32("height", &height)); 1288 1289 notifyListener(MEDIA_SET_VIDEO_SIZE, width, height); 1290 break; 1291 } 1292 1293 default: 1294 TRESPASS(); 1295 } 1296} 1297 1298//////////////////////////////////////////////////////////////////////////////// 1299 1300void NuPlayer::Source::notifyFlagsChanged(uint32_t flags) { 1301 sp<AMessage> notify = dupNotify(); 1302 notify->setInt32("what", kWhatFlagsChanged); 1303 notify->setInt32("flags", flags); 1304 notify->post(); 1305} 1306 1307void NuPlayer::Source::notifyVideoSizeChanged(int32_t width, int32_t height) { 1308 sp<AMessage> notify = dupNotify(); 1309 notify->setInt32("what", kWhatVideoSizeChanged); 1310 notify->setInt32("width", width); 1311 notify->setInt32("height", height); 1312 notify->post(); 1313} 1314 1315void NuPlayer::Source::notifyPrepared() { 1316 sp<AMessage> notify = dupNotify(); 1317 notify->setInt32("what", kWhatPrepared); 1318 notify->post(); 1319} 1320 1321void NuPlayer::Source::onMessageReceived(const sp<AMessage> &msg) { 1322 TRESPASS(); 1323} 1324 1325} // namespace android 1326