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