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