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