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