NuPlayer.cpp revision 1a447be0cf1abc7564ae2afe7b4d2240c875de54
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/ISurfaceTexture.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<ISurfaceTexture> &surfaceTexture) { 202 sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id()); 203 204 if (surfaceTexture == NULL) { 205 msg->setObject("native-window", NULL); 206 } else { 207 msg->setObject( 208 "native-window", 209 new NativeWindowWrapper( 210 new SurfaceTextureClient(surfaceTexture))); 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("channel-count", &numChannels)); 488 489 int32_t sampleRate; 490 CHECK(codecRequest->findInt32("sample-rate", &sampleRate)); 491 492 ALOGV("Audio output format changed to %d Hz, %d channels", 493 sampleRate, numChannels); 494 495 mAudioSink->close(); 496 497 audio_output_flags_t flags; 498 int64_t durationUs; 499 // FIXME: we should handle the case where the video decoder is created after 500 // we receive the format change indication. Current code will just make that 501 // we select deep buffer with video which should not be a problem as it should 502 // not prevent from keeping A/V sync. 503 if (mVideoDecoder == NULL && 504 mSource->getDuration(&durationUs) == OK && 505 durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) { 506 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; 507 } else { 508 flags = AUDIO_OUTPUT_FLAG_NONE; 509 } 510 511 int32_t channelMask; 512 if (!codecRequest->findInt32("channel-mask", &channelMask)) { 513 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER; 514 } 515 516 CHECK_EQ(mAudioSink->open( 517 sampleRate, 518 numChannels, 519 (audio_channel_mask_t)channelMask, 520 AUDIO_FORMAT_PCM_16_BIT, 521 8 /* bufferCount */, 522 NULL, 523 NULL, 524 flags), 525 (status_t)OK); 526 mAudioSink->start(); 527 528 mRenderer->signalAudioSinkChanged(); 529 } else { 530 // video 531 532 int32_t width, height; 533 CHECK(codecRequest->findInt32("width", &width)); 534 CHECK(codecRequest->findInt32("height", &height)); 535 536 int32_t cropLeft, cropTop, cropRight, cropBottom; 537 CHECK(codecRequest->findRect( 538 "crop", 539 &cropLeft, &cropTop, &cropRight, &cropBottom)); 540 541 ALOGV("Video output format changed to %d x %d " 542 "(crop: %d x %d @ (%d, %d))", 543 width, height, 544 (cropRight - cropLeft + 1), 545 (cropBottom - cropTop + 1), 546 cropLeft, cropTop); 547 548 notifyListener( 549 MEDIA_SET_VIDEO_SIZE, 550 cropRight - cropLeft + 1, 551 cropBottom - cropTop + 1); 552 } 553 } else if (what == ACodec::kWhatShutdownCompleted) { 554 ALOGV("%s shutdown completed", audio ? "audio" : "video"); 555 if (audio) { 556 mAudioDecoder.clear(); 557 558 CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER); 559 mFlushingAudio = SHUT_DOWN; 560 } else { 561 mVideoDecoder.clear(); 562 563 CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER); 564 mFlushingVideo = SHUT_DOWN; 565 } 566 567 finishFlushIfPossible(); 568 } else if (what == ACodec::kWhatError) { 569 ALOGE("Received error from %s decoder, aborting playback.", 570 audio ? "audio" : "video"); 571 572 mRenderer->queueEOS(audio, UNKNOWN_ERROR); 573 } else if (what == ACodec::kWhatDrainThisBuffer) { 574 renderBuffer(audio, codecRequest); 575 } else if (what != ACodec::kWhatComponentAllocated 576 && what != ACodec::kWhatComponentConfigured 577 && what != ACodec::kWhatBuffersAllocated) { 578 ALOGV("Unhandled codec notification %d '%c%c%c%c'.", 579 what, 580 what >> 24, 581 (what >> 16) & 0xff, 582 (what >> 8) & 0xff, 583 what & 0xff); 584 } 585 586 break; 587 } 588 589 case kWhatRendererNotify: 590 { 591 int32_t what; 592 CHECK(msg->findInt32("what", &what)); 593 594 if (what == Renderer::kWhatEOS) { 595 int32_t audio; 596 CHECK(msg->findInt32("audio", &audio)); 597 598 int32_t finalResult; 599 CHECK(msg->findInt32("finalResult", &finalResult)); 600 601 if (audio) { 602 mAudioEOS = true; 603 } else { 604 mVideoEOS = true; 605 } 606 607 if (finalResult == ERROR_END_OF_STREAM) { 608 ALOGV("reached %s EOS", audio ? "audio" : "video"); 609 } else { 610 ALOGE("%s track encountered an error (%d)", 611 audio ? "audio" : "video", finalResult); 612 613 notifyListener( 614 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult); 615 } 616 617 if ((mAudioEOS || mAudioDecoder == NULL) 618 && (mVideoEOS || mVideoDecoder == NULL)) { 619 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); 620 } 621 } else if (what == Renderer::kWhatPosition) { 622 int64_t positionUs; 623 CHECK(msg->findInt64("positionUs", &positionUs)); 624 625 CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs)); 626 627 if (mDriver != NULL) { 628 sp<NuPlayerDriver> driver = mDriver.promote(); 629 if (driver != NULL) { 630 driver->notifyPosition(positionUs); 631 632 driver->notifyFrameStats( 633 mNumFramesTotal, mNumFramesDropped); 634 } 635 } 636 } else if (what == Renderer::kWhatFlushComplete) { 637 int32_t audio; 638 CHECK(msg->findInt32("audio", &audio)); 639 640 ALOGV("renderer %s flush completed.", audio ? "audio" : "video"); 641 } else if (what == Renderer::kWhatVideoRenderingStart) { 642 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0); 643 } 644 break; 645 } 646 647 case kWhatMoreDataQueued: 648 { 649 break; 650 } 651 652 case kWhatReset: 653 { 654 ALOGV("kWhatReset"); 655 656 mDeferredActions.push_back( 657 new SimpleAction(&NuPlayer::performDecoderShutdown)); 658 659 mDeferredActions.push_back( 660 new SimpleAction(&NuPlayer::performReset)); 661 662 processDeferredActions(); 663 break; 664 } 665 666 case kWhatSeek: 667 { 668 int64_t seekTimeUs; 669 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs)); 670 671 ALOGV("kWhatSeek seekTimeUs=%lld us", seekTimeUs); 672 673 mDeferredActions.push_back( 674 new SimpleAction(&NuPlayer::performDecoderFlush)); 675 676 mDeferredActions.push_back(new SeekAction(seekTimeUs)); 677 678 processDeferredActions(); 679 break; 680 } 681 682 case kWhatPause: 683 { 684 CHECK(mRenderer != NULL); 685 mRenderer->pause(); 686 break; 687 } 688 689 case kWhatResume: 690 { 691 CHECK(mRenderer != NULL); 692 mRenderer->resume(); 693 break; 694 } 695 696 default: 697 TRESPASS(); 698 break; 699 } 700} 701 702void NuPlayer::finishFlushIfPossible() { 703 if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) { 704 return; 705 } 706 707 if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) { 708 return; 709 } 710 711 ALOGV("both audio and video are flushed now."); 712 713 if (mTimeDiscontinuityPending) { 714 mRenderer->signalTimeDiscontinuity(); 715 mTimeDiscontinuityPending = false; 716 } 717 718 if (mAudioDecoder != NULL) { 719 mAudioDecoder->signalResume(); 720 } 721 722 if (mVideoDecoder != NULL) { 723 mVideoDecoder->signalResume(); 724 } 725 726 mFlushingAudio = NONE; 727 mFlushingVideo = NONE; 728 729 processDeferredActions(); 730} 731 732void NuPlayer::postScanSources() { 733 if (mScanSourcesPending) { 734 return; 735 } 736 737 sp<AMessage> msg = new AMessage(kWhatScanSources, id()); 738 msg->setInt32("generation", mScanSourcesGeneration); 739 msg->post(); 740 741 mScanSourcesPending = true; 742} 743 744status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) { 745 if (*decoder != NULL) { 746 return OK; 747 } 748 749 sp<AMessage> format = mSource->getFormat(audio); 750 751 if (format == NULL) { 752 return -EWOULDBLOCK; 753 } 754 755 if (!audio) { 756 AString mime; 757 CHECK(format->findString("mime", &mime)); 758 mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str()); 759 } 760 761 sp<AMessage> notify = 762 new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify, 763 id()); 764 765 *decoder = audio ? new Decoder(notify) : 766 new Decoder(notify, mNativeWindow); 767 looper()->registerHandler(*decoder); 768 769 (*decoder)->configure(format); 770 771 int64_t durationUs; 772 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) { 773 sp<NuPlayerDriver> driver = mDriver.promote(); 774 if (driver != NULL) { 775 driver->notifyDuration(durationUs); 776 } 777 } 778 779 return OK; 780} 781 782status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { 783 sp<AMessage> reply; 784 CHECK(msg->findMessage("reply", &reply)); 785 786 if ((audio && IsFlushingState(mFlushingAudio)) 787 || (!audio && IsFlushingState(mFlushingVideo))) { 788 reply->setInt32("err", INFO_DISCONTINUITY); 789 reply->post(); 790 return OK; 791 } 792 793 sp<ABuffer> accessUnit; 794 795 bool dropAccessUnit; 796 do { 797 status_t err = mSource->dequeueAccessUnit(audio, &accessUnit); 798 799 if (err == -EWOULDBLOCK) { 800 return err; 801 } else if (err != OK) { 802 if (err == INFO_DISCONTINUITY) { 803 int32_t type; 804 CHECK(accessUnit->meta()->findInt32("discontinuity", &type)); 805 806 bool formatChange = 807 (audio && 808 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT)) 809 || (!audio && 810 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT)); 811 812 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0; 813 814 ALOGI("%s discontinuity (formatChange=%d, time=%d)", 815 audio ? "audio" : "video", formatChange, timeChange); 816 817 if (audio) { 818 mSkipRenderingAudioUntilMediaTimeUs = -1; 819 } else { 820 mSkipRenderingVideoUntilMediaTimeUs = -1; 821 } 822 823 if (timeChange) { 824 sp<AMessage> extra; 825 if (accessUnit->meta()->findMessage("extra", &extra) 826 && extra != NULL) { 827 int64_t resumeAtMediaTimeUs; 828 if (extra->findInt64( 829 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) { 830 ALOGI("suppressing rendering of %s until %lld us", 831 audio ? "audio" : "video", resumeAtMediaTimeUs); 832 833 if (audio) { 834 mSkipRenderingAudioUntilMediaTimeUs = 835 resumeAtMediaTimeUs; 836 } else { 837 mSkipRenderingVideoUntilMediaTimeUs = 838 resumeAtMediaTimeUs; 839 } 840 } 841 } 842 } 843 844 mTimeDiscontinuityPending = 845 mTimeDiscontinuityPending || timeChange; 846 847 if (formatChange || timeChange) { 848 if (mFlushingAudio == NONE && mFlushingVideo == NONE) { 849 // And we'll resume scanning sources once we're done 850 // flushing. 851 mDeferredActions.push_front( 852 new SimpleAction( 853 &NuPlayer::performScanSources)); 854 } 855 856 flushDecoder(audio, formatChange); 857 } else { 858 // This stream is unaffected by the discontinuity 859 860 if (audio) { 861 mFlushingAudio = FLUSHED; 862 } else { 863 mFlushingVideo = FLUSHED; 864 } 865 866 finishFlushIfPossible(); 867 868 return -EWOULDBLOCK; 869 } 870 } 871 872 reply->setInt32("err", err); 873 reply->post(); 874 return OK; 875 } 876 877 if (!audio) { 878 ++mNumFramesTotal; 879 } 880 881 dropAccessUnit = false; 882 if (!audio 883 && mVideoLateByUs > 100000ll 884 && mVideoIsAVC 885 && !IsAVCReferenceFrame(accessUnit)) { 886 dropAccessUnit = true; 887 ++mNumFramesDropped; 888 } 889 } while (dropAccessUnit); 890 891 // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video"); 892 893#if 0 894 int64_t mediaTimeUs; 895 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs)); 896 ALOGV("feeding %s input buffer at media time %.2f secs", 897 audio ? "audio" : "video", 898 mediaTimeUs / 1E6); 899#endif 900 901 reply->setBuffer("buffer", accessUnit); 902 reply->post(); 903 904 return OK; 905} 906 907void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) { 908 // ALOGV("renderBuffer %s", audio ? "audio" : "video"); 909 910 sp<AMessage> reply; 911 CHECK(msg->findMessage("reply", &reply)); 912 913 if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) { 914 // We're currently attempting to flush the decoder, in order 915 // to complete this, the decoder wants all its buffers back, 916 // so we don't want any output buffers it sent us (from before 917 // we initiated the flush) to be stuck in the renderer's queue. 918 919 ALOGV("we're still flushing the %s decoder, sending its output buffer" 920 " right back.", audio ? "audio" : "video"); 921 922 reply->post(); 923 return; 924 } 925 926 sp<ABuffer> buffer; 927 CHECK(msg->findBuffer("buffer", &buffer)); 928 929 int64_t &skipUntilMediaTimeUs = 930 audio 931 ? mSkipRenderingAudioUntilMediaTimeUs 932 : mSkipRenderingVideoUntilMediaTimeUs; 933 934 if (skipUntilMediaTimeUs >= 0) { 935 int64_t mediaTimeUs; 936 CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs)); 937 938 if (mediaTimeUs < skipUntilMediaTimeUs) { 939 ALOGV("dropping %s buffer at time %lld as requested.", 940 audio ? "audio" : "video", 941 mediaTimeUs); 942 943 reply->post(); 944 return; 945 } 946 947 skipUntilMediaTimeUs = -1; 948 } 949 950 mRenderer->queueBuffer(audio, buffer, reply); 951} 952 953void NuPlayer::notifyListener(int msg, int ext1, int ext2) { 954 if (mDriver == NULL) { 955 return; 956 } 957 958 sp<NuPlayerDriver> driver = mDriver.promote(); 959 960 if (driver == NULL) { 961 return; 962 } 963 964 driver->notifyListener(msg, ext1, ext2); 965} 966 967void NuPlayer::flushDecoder(bool audio, bool needShutdown) { 968 if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) { 969 ALOGI("flushDecoder %s without decoder present", 970 audio ? "audio" : "video"); 971 } 972 973 // Make sure we don't continue to scan sources until we finish flushing. 974 ++mScanSourcesGeneration; 975 mScanSourcesPending = false; 976 977 (audio ? mAudioDecoder : mVideoDecoder)->signalFlush(); 978 mRenderer->flush(audio); 979 980 FlushStatus newStatus = 981 needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER; 982 983 if (audio) { 984 CHECK(mFlushingAudio == NONE 985 || mFlushingAudio == AWAITING_DISCONTINUITY); 986 987 mFlushingAudio = newStatus; 988 989 if (mFlushingVideo == NONE) { 990 mFlushingVideo = (mVideoDecoder != NULL) 991 ? AWAITING_DISCONTINUITY 992 : FLUSHED; 993 } 994 } else { 995 CHECK(mFlushingVideo == NONE 996 || mFlushingVideo == AWAITING_DISCONTINUITY); 997 998 mFlushingVideo = newStatus; 999 1000 if (mFlushingAudio == NONE) { 1001 mFlushingAudio = (mAudioDecoder != NULL) 1002 ? AWAITING_DISCONTINUITY 1003 : FLUSHED; 1004 } 1005 } 1006} 1007 1008sp<AMessage> NuPlayer::Source::getFormat(bool audio) { 1009 sp<MetaData> meta = getFormatMeta(audio); 1010 1011 if (meta == NULL) { 1012 return NULL; 1013 } 1014 1015 sp<AMessage> msg = new AMessage; 1016 1017 if(convertMetaDataToMessage(meta, &msg) == OK) { 1018 return msg; 1019 } 1020 return NULL; 1021} 1022 1023status_t NuPlayer::setVideoScalingMode(int32_t mode) { 1024 mVideoScalingMode = mode; 1025 if (mNativeWindow != NULL) { 1026 status_t ret = native_window_set_scaling_mode( 1027 mNativeWindow->getNativeWindow().get(), mVideoScalingMode); 1028 if (ret != OK) { 1029 ALOGE("Failed to set scaling mode (%d): %s", 1030 -ret, strerror(-ret)); 1031 return ret; 1032 } 1033 } 1034 return OK; 1035} 1036 1037void NuPlayer::schedulePollDuration() { 1038 sp<AMessage> msg = new AMessage(kWhatPollDuration, id()); 1039 msg->setInt32("generation", mPollDurationGeneration); 1040 msg->post(); 1041} 1042 1043void NuPlayer::cancelPollDuration() { 1044 ++mPollDurationGeneration; 1045} 1046 1047void NuPlayer::processDeferredActions() { 1048 while (!mDeferredActions.empty()) { 1049 // We won't execute any deferred actions until we're no longer in 1050 // an intermediate state, i.e. one more more decoders are currently 1051 // flushing or shutting down. 1052 1053 if (mRenderer != NULL) { 1054 // There's an edge case where the renderer owns all output 1055 // buffers and is paused, therefore the decoder will not read 1056 // more input data and will never encounter the matching 1057 // discontinuity. To avoid this, we resume the renderer. 1058 1059 if (mFlushingAudio == AWAITING_DISCONTINUITY 1060 || mFlushingVideo == AWAITING_DISCONTINUITY) { 1061 mRenderer->resume(); 1062 } 1063 } 1064 1065 if (mFlushingAudio != NONE || mFlushingVideo != NONE) { 1066 // We're currently flushing, postpone the reset until that's 1067 // completed. 1068 1069 ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d", 1070 mFlushingAudio, mFlushingVideo); 1071 1072 break; 1073 } 1074 1075 sp<Action> action = *mDeferredActions.begin(); 1076 mDeferredActions.erase(mDeferredActions.begin()); 1077 1078 action->execute(this); 1079 } 1080} 1081 1082void NuPlayer::performSeek(int64_t seekTimeUs) { 1083 ALOGV("performSeek seekTimeUs=%lld us (%.2f secs)", 1084 seekTimeUs, 1085 seekTimeUs / 1E6); 1086 1087 mSource->seekTo(seekTimeUs); 1088 1089 if (mDriver != NULL) { 1090 sp<NuPlayerDriver> driver = mDriver.promote(); 1091 if (driver != NULL) { 1092 driver->notifyPosition(seekTimeUs); 1093 driver->notifySeekComplete(); 1094 } 1095 } 1096 1097 // everything's flushed, continue playback. 1098} 1099 1100void NuPlayer::performDecoderFlush() { 1101 ALOGV("performDecoderFlush"); 1102 1103 if (mAudioDecoder != NULL && mVideoDecoder == NULL) { 1104 return; 1105 } 1106 1107 mTimeDiscontinuityPending = true; 1108 1109 if (mAudioDecoder != NULL) { 1110 flushDecoder(true /* audio */, false /* needShutdown */); 1111 } 1112 1113 if (mVideoDecoder != NULL) { 1114 flushDecoder(false /* audio */, false /* needShutdown */); 1115 } 1116} 1117 1118void NuPlayer::performDecoderShutdown() { 1119 ALOGV("performDecoderShutdown"); 1120 1121 if (mAudioDecoder != NULL && mVideoDecoder == NULL) { 1122 return; 1123 } 1124 1125 mTimeDiscontinuityPending = true; 1126 1127 if (mAudioDecoder != NULL) { 1128 flushDecoder(true /* audio */, true /* needShutdown */); 1129 } 1130 1131 if (mVideoDecoder != NULL) { 1132 flushDecoder(false /* audio */, true /* needShutdown */); 1133 } 1134} 1135 1136void NuPlayer::performReset() { 1137 ALOGV("performReset"); 1138 1139 CHECK(mAudioDecoder == NULL); 1140 CHECK(mVideoDecoder == NULL); 1141 1142 cancelPollDuration(); 1143 1144 ++mScanSourcesGeneration; 1145 mScanSourcesPending = false; 1146 1147 mRenderer.clear(); 1148 1149 if (mSource != NULL) { 1150 mSource->stop(); 1151 mSource.clear(); 1152 } 1153 1154 if (mDriver != NULL) { 1155 sp<NuPlayerDriver> driver = mDriver.promote(); 1156 if (driver != NULL) { 1157 driver->notifyResetComplete(); 1158 } 1159 } 1160 1161 mStarted = false; 1162} 1163 1164void NuPlayer::performScanSources() { 1165 ALOGV("performScanSources"); 1166 1167 if (!mStarted) { 1168 return; 1169 } 1170 1171 if (mAudioDecoder == NULL || mVideoDecoder == NULL) { 1172 postScanSources(); 1173 } 1174} 1175 1176void NuPlayer::performSetSurface(const sp<NativeWindowWrapper> &wrapper) { 1177 ALOGV("performSetSurface"); 1178 1179 mNativeWindow = wrapper; 1180 1181 // XXX - ignore error from setVideoScalingMode for now 1182 setVideoScalingMode(mVideoScalingMode); 1183 1184 if (mDriver != NULL) { 1185 sp<NuPlayerDriver> driver = mDriver.promote(); 1186 if (driver != NULL) { 1187 driver->notifySetSurfaceComplete(); 1188 } 1189 } 1190} 1191 1192} // namespace android 1193