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