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