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 #include "TextDescriptions.h" 33 34 #include "ATSParser.h" 35 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/MediaBuffer.h> 41 #include <media/stagefright/MediaDefs.h> 42 #include <media/stagefright/MediaErrors.h> 43 #include <media/stagefright/MetaData.h> 44 #include <gui/IGraphicBufferProducer.h> 45 46 #include "avc_utils.h" 47 48 #include "ESDS.h" 49 #include <media/stagefright/Utils.h> 50 51 namespace android { 52 53 // TODO optimize buffer size for power consumption 54 // The offload read buffer size is 32 KB but 24 KB uses less power. 55 const size_t NuPlayer::kAggregateBufferSizeBytes = 24 * 1024; 56 57 struct NuPlayer::Action : public RefBase { 58 Action() {} 59 60 virtual void execute(NuPlayer *player) = 0; 61 62 private: 63 DISALLOW_EVIL_CONSTRUCTORS(Action); 64 }; 65 66 struct NuPlayer::SeekAction : public Action { 67 SeekAction(int64_t seekTimeUs, bool needNotify) 68 : mSeekTimeUs(seekTimeUs), 69 mNeedNotify(needNotify) { 70 } 71 72 virtual void execute(NuPlayer *player) { 73 player->performSeek(mSeekTimeUs, mNeedNotify); 74 } 75 76 private: 77 int64_t mSeekTimeUs; 78 bool mNeedNotify; 79 80 DISALLOW_EVIL_CONSTRUCTORS(SeekAction); 81 }; 82 83 struct NuPlayer::SetSurfaceAction : public Action { 84 SetSurfaceAction(const sp<NativeWindowWrapper> &wrapper) 85 : mWrapper(wrapper) { 86 } 87 88 virtual void execute(NuPlayer *player) { 89 player->performSetSurface(mWrapper); 90 } 91 92 private: 93 sp<NativeWindowWrapper> mWrapper; 94 95 DISALLOW_EVIL_CONSTRUCTORS(SetSurfaceAction); 96 }; 97 98 struct NuPlayer::ShutdownDecoderAction : public Action { 99 ShutdownDecoderAction(bool audio, bool video) 100 : mAudio(audio), 101 mVideo(video) { 102 } 103 104 virtual void execute(NuPlayer *player) { 105 player->performDecoderShutdown(mAudio, mVideo); 106 } 107 108 private: 109 bool mAudio; 110 bool mVideo; 111 112 DISALLOW_EVIL_CONSTRUCTORS(ShutdownDecoderAction); 113 }; 114 115 struct NuPlayer::PostMessageAction : public Action { 116 PostMessageAction(const sp<AMessage> &msg) 117 : mMessage(msg) { 118 } 119 120 virtual void execute(NuPlayer *) { 121 mMessage->post(); 122 } 123 124 private: 125 sp<AMessage> mMessage; 126 127 DISALLOW_EVIL_CONSTRUCTORS(PostMessageAction); 128 }; 129 130 // Use this if there's no state necessary to save in order to execute 131 // the action. 132 struct NuPlayer::SimpleAction : public Action { 133 typedef void (NuPlayer::*ActionFunc)(); 134 135 SimpleAction(ActionFunc func) 136 : mFunc(func) { 137 } 138 139 virtual void execute(NuPlayer *player) { 140 (player->*mFunc)(); 141 } 142 143 private: 144 ActionFunc mFunc; 145 146 DISALLOW_EVIL_CONSTRUCTORS(SimpleAction); 147 }; 148 149 //////////////////////////////////////////////////////////////////////////////// 150 151 NuPlayer::NuPlayer() 152 : mUIDValid(false), 153 mSourceFlags(0), 154 mVideoIsAVC(false), 155 mOffloadAudio(false), 156 mAudioDecoderGeneration(0), 157 mVideoDecoderGeneration(0), 158 mRendererGeneration(0), 159 mAudioEOS(false), 160 mVideoEOS(false), 161 mScanSourcesPending(false), 162 mScanSourcesGeneration(0), 163 mPollDurationGeneration(0), 164 mTimedTextGeneration(0), 165 mTimeDiscontinuityPending(false), 166 mFlushingAudio(NONE), 167 mFlushingVideo(NONE), 168 mSkipRenderingAudioUntilMediaTimeUs(-1ll), 169 mSkipRenderingVideoUntilMediaTimeUs(-1ll), 170 mNumFramesTotal(0ll), 171 mNumFramesDropped(0ll), 172 mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW), 173 mStarted(false) { 174 clearFlushComplete(); 175 } 176 177 NuPlayer::~NuPlayer() { 178 } 179 180 void NuPlayer::setUID(uid_t uid) { 181 mUIDValid = true; 182 mUID = uid; 183 } 184 185 void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) { 186 mDriver = driver; 187 } 188 189 void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) { 190 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); 191 192 sp<AMessage> notify = new AMessage(kWhatSourceNotify, id()); 193 194 msg->setObject("source", new StreamingSource(notify, source)); 195 msg->post(); 196 } 197 198 static bool IsHTTPLiveURL(const char *url) { 199 if (!strncasecmp("http://", url, 7) 200 || !strncasecmp("https://", url, 8) 201 || !strncasecmp("file://", url, 7)) { 202 size_t len = strlen(url); 203 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) { 204 return true; 205 } 206 207 if (strstr(url,"m3u8")) { 208 return true; 209 } 210 } 211 212 return false; 213 } 214 215 void NuPlayer::setDataSourceAsync( 216 const sp<IMediaHTTPService> &httpService, 217 const char *url, 218 const KeyedVector<String8, String8> *headers) { 219 220 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); 221 size_t len = strlen(url); 222 223 sp<AMessage> notify = new AMessage(kWhatSourceNotify, id()); 224 225 sp<Source> source; 226 if (IsHTTPLiveURL(url)) { 227 source = new HTTPLiveSource(notify, httpService, url, headers); 228 } else if (!strncasecmp(url, "rtsp://", 7)) { 229 source = new RTSPSource( 230 notify, httpService, url, headers, mUIDValid, mUID); 231 } else if ((!strncasecmp(url, "http://", 7) 232 || !strncasecmp(url, "https://", 8)) 233 && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) 234 || strstr(url, ".sdp?"))) { 235 source = new RTSPSource( 236 notify, httpService, url, headers, mUIDValid, mUID, true); 237 } else { 238 sp<GenericSource> genericSource = 239 new GenericSource(notify, mUIDValid, mUID); 240 // Don't set FLAG_SECURE on mSourceFlags here for widevine. 241 // The correct flags will be updated in Source::kWhatFlagsChanged 242 // handler when GenericSource is prepared. 243 244 status_t err = genericSource->setDataSource(httpService, url, headers); 245 246 if (err == OK) { 247 source = genericSource; 248 } else { 249 ALOGE("Failed to set data source!"); 250 } 251 } 252 msg->setObject("source", source); 253 msg->post(); 254 } 255 256 void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) { 257 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); 258 259 sp<AMessage> notify = new AMessage(kWhatSourceNotify, id()); 260 261 sp<GenericSource> source = 262 new GenericSource(notify, mUIDValid, mUID); 263 264 status_t err = source->setDataSource(fd, offset, length); 265 266 if (err != OK) { 267 ALOGE("Failed to set data source!"); 268 source = NULL; 269 } 270 271 msg->setObject("source", source); 272 msg->post(); 273 } 274 275 void NuPlayer::prepareAsync() { 276 (new AMessage(kWhatPrepare, id()))->post(); 277 } 278 279 void NuPlayer::setVideoSurfaceTextureAsync( 280 const sp<IGraphicBufferProducer> &bufferProducer) { 281 sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id()); 282 283 if (bufferProducer == NULL) { 284 msg->setObject("native-window", NULL); 285 } else { 286 msg->setObject( 287 "native-window", 288 new NativeWindowWrapper( 289 new Surface(bufferProducer, true /* controlledByApp */))); 290 } 291 292 msg->post(); 293 } 294 295 void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) { 296 sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id()); 297 msg->setObject("sink", sink); 298 msg->post(); 299 } 300 301 void NuPlayer::start() { 302 (new AMessage(kWhatStart, id()))->post(); 303 } 304 305 void NuPlayer::pause() { 306 (new AMessage(kWhatPause, id()))->post(); 307 } 308 309 void NuPlayer::resume() { 310 (new AMessage(kWhatResume, id()))->post(); 311 } 312 313 void NuPlayer::resetAsync() { 314 if (mSource != NULL) { 315 // During a reset, the data source might be unresponsive already, we need to 316 // disconnect explicitly so that reads exit promptly. 317 // We can't queue the disconnect request to the looper, as it might be 318 // queued behind a stuck read and never gets processed. 319 // Doing a disconnect outside the looper to allows the pending reads to exit 320 // (either successfully or with error). 321 mSource->disconnect(); 322 } 323 324 (new AMessage(kWhatReset, id()))->post(); 325 } 326 327 void NuPlayer::seekToAsync(int64_t seekTimeUs, bool needNotify) { 328 sp<AMessage> msg = new AMessage(kWhatSeek, id()); 329 msg->setInt64("seekTimeUs", seekTimeUs); 330 msg->setInt32("needNotify", needNotify); 331 msg->post(); 332 } 333 334 335 void NuPlayer::writeTrackInfo( 336 Parcel* reply, const sp<AMessage> format) const { 337 int32_t trackType; 338 CHECK(format->findInt32("type", &trackType)); 339 340 AString lang; 341 CHECK(format->findString("language", &lang)); 342 343 reply->writeInt32(2); // write something non-zero 344 reply->writeInt32(trackType); 345 reply->writeString16(String16(lang.c_str())); 346 347 if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) { 348 AString mime; 349 CHECK(format->findString("mime", &mime)); 350 351 int32_t isAuto, isDefault, isForced; 352 CHECK(format->findInt32("auto", &isAuto)); 353 CHECK(format->findInt32("default", &isDefault)); 354 CHECK(format->findInt32("forced", &isForced)); 355 356 reply->writeString16(String16(mime.c_str())); 357 reply->writeInt32(isAuto); 358 reply->writeInt32(isDefault); 359 reply->writeInt32(isForced); 360 } 361 } 362 363 void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { 364 switch (msg->what()) { 365 case kWhatSetDataSource: 366 { 367 ALOGV("kWhatSetDataSource"); 368 369 CHECK(mSource == NULL); 370 371 status_t err = OK; 372 sp<RefBase> obj; 373 CHECK(msg->findObject("source", &obj)); 374 if (obj != NULL) { 375 mSource = static_cast<Source *>(obj.get()); 376 } else { 377 err = UNKNOWN_ERROR; 378 } 379 380 CHECK(mDriver != NULL); 381 sp<NuPlayerDriver> driver = mDriver.promote(); 382 if (driver != NULL) { 383 driver->notifySetDataSourceCompleted(err); 384 } 385 break; 386 } 387 388 case kWhatPrepare: 389 { 390 mSource->prepareAsync(); 391 break; 392 } 393 394 case kWhatGetTrackInfo: 395 { 396 uint32_t replyID; 397 CHECK(msg->senderAwaitsResponse(&replyID)); 398 399 Parcel* reply; 400 CHECK(msg->findPointer("reply", (void**)&reply)); 401 402 size_t inbandTracks = 0; 403 if (mSource != NULL) { 404 inbandTracks = mSource->getTrackCount(); 405 } 406 407 size_t ccTracks = 0; 408 if (mCCDecoder != NULL) { 409 ccTracks = mCCDecoder->getTrackCount(); 410 } 411 412 // total track count 413 reply->writeInt32(inbandTracks + ccTracks); 414 415 // write inband tracks 416 for (size_t i = 0; i < inbandTracks; ++i) { 417 writeTrackInfo(reply, mSource->getTrackInfo(i)); 418 } 419 420 // write CC track 421 for (size_t i = 0; i < ccTracks; ++i) { 422 writeTrackInfo(reply, mCCDecoder->getTrackInfo(i)); 423 } 424 425 sp<AMessage> response = new AMessage; 426 response->postReply(replyID); 427 break; 428 } 429 430 case kWhatGetSelectedTrack: 431 { 432 status_t err = INVALID_OPERATION; 433 if (mSource != NULL) { 434 err = OK; 435 436 int32_t type32; 437 CHECK(msg->findInt32("type", (int32_t*)&type32)); 438 media_track_type type = (media_track_type)type32; 439 ssize_t selectedTrack = mSource->getSelectedTrack(type); 440 441 Parcel* reply; 442 CHECK(msg->findPointer("reply", (void**)&reply)); 443 reply->writeInt32(selectedTrack); 444 } 445 446 sp<AMessage> response = new AMessage; 447 response->setInt32("err", err); 448 449 uint32_t replyID; 450 CHECK(msg->senderAwaitsResponse(&replyID)); 451 response->postReply(replyID); 452 break; 453 } 454 455 case kWhatSelectTrack: 456 { 457 uint32_t replyID; 458 CHECK(msg->senderAwaitsResponse(&replyID)); 459 460 size_t trackIndex; 461 int32_t select; 462 CHECK(msg->findSize("trackIndex", &trackIndex)); 463 CHECK(msg->findInt32("select", &select)); 464 465 status_t err = INVALID_OPERATION; 466 467 size_t inbandTracks = 0; 468 if (mSource != NULL) { 469 inbandTracks = mSource->getTrackCount(); 470 } 471 size_t ccTracks = 0; 472 if (mCCDecoder != NULL) { 473 ccTracks = mCCDecoder->getTrackCount(); 474 } 475 476 if (trackIndex < inbandTracks) { 477 err = mSource->selectTrack(trackIndex, select); 478 479 if (!select && err == OK) { 480 int32_t type; 481 sp<AMessage> info = mSource->getTrackInfo(trackIndex); 482 if (info != NULL 483 && info->findInt32("type", &type) 484 && type == MEDIA_TRACK_TYPE_TIMEDTEXT) { 485 ++mTimedTextGeneration; 486 } 487 } 488 } else { 489 trackIndex -= inbandTracks; 490 491 if (trackIndex < ccTracks) { 492 err = mCCDecoder->selectTrack(trackIndex, select); 493 } 494 } 495 496 sp<AMessage> response = new AMessage; 497 response->setInt32("err", err); 498 499 response->postReply(replyID); 500 break; 501 } 502 503 case kWhatPollDuration: 504 { 505 int32_t generation; 506 CHECK(msg->findInt32("generation", &generation)); 507 508 if (generation != mPollDurationGeneration) { 509 // stale 510 break; 511 } 512 513 int64_t durationUs; 514 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) { 515 sp<NuPlayerDriver> driver = mDriver.promote(); 516 if (driver != NULL) { 517 driver->notifyDuration(durationUs); 518 } 519 } 520 521 msg->post(1000000ll); // poll again in a second. 522 break; 523 } 524 525 case kWhatSetVideoNativeWindow: 526 { 527 ALOGV("kWhatSetVideoNativeWindow"); 528 529 mDeferredActions.push_back( 530 new ShutdownDecoderAction( 531 false /* audio */, true /* video */)); 532 533 sp<RefBase> obj; 534 CHECK(msg->findObject("native-window", &obj)); 535 536 mDeferredActions.push_back( 537 new SetSurfaceAction( 538 static_cast<NativeWindowWrapper *>(obj.get()))); 539 540 if (obj != NULL) { 541 if (mStarted && mSource->getFormat(false /* audio */) != NULL) { 542 // Issue a seek to refresh the video screen only if started otherwise 543 // the extractor may not yet be started and will assert. 544 // If the video decoder is not set (perhaps audio only in this case) 545 // do not perform a seek as it is not needed. 546 int64_t currentPositionUs = 0; 547 if (getCurrentPosition(¤tPositionUs) == OK) { 548 mDeferredActions.push_back( 549 new SeekAction(currentPositionUs, false /* needNotify */)); 550 } 551 } 552 553 // If there is a new surface texture, instantiate decoders 554 // again if possible. 555 mDeferredActions.push_back( 556 new SimpleAction(&NuPlayer::performScanSources)); 557 } 558 559 processDeferredActions(); 560 break; 561 } 562 563 case kWhatSetAudioSink: 564 { 565 ALOGV("kWhatSetAudioSink"); 566 567 sp<RefBase> obj; 568 CHECK(msg->findObject("sink", &obj)); 569 570 mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get()); 571 break; 572 } 573 574 case kWhatStart: 575 { 576 ALOGV("kWhatStart"); 577 578 mVideoIsAVC = false; 579 mOffloadAudio = false; 580 mAudioEOS = false; 581 mVideoEOS = false; 582 mSkipRenderingAudioUntilMediaTimeUs = -1; 583 mSkipRenderingVideoUntilMediaTimeUs = -1; 584 mNumFramesTotal = 0; 585 mNumFramesDropped = 0; 586 mStarted = true; 587 588 /* instantiate decoders now for secure playback */ 589 if (mSourceFlags & Source::FLAG_SECURE) { 590 if (mNativeWindow != NULL) { 591 instantiateDecoder(false, &mVideoDecoder); 592 } 593 594 if (mAudioSink != NULL) { 595 instantiateDecoder(true, &mAudioDecoder); 596 } 597 } 598 599 mSource->start(); 600 601 uint32_t flags = 0; 602 603 if (mSource->isRealTime()) { 604 flags |= Renderer::FLAG_REAL_TIME; 605 } 606 607 sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */); 608 audio_stream_type_t streamType = AUDIO_STREAM_MUSIC; 609 if (mAudioSink != NULL) { 610 streamType = mAudioSink->getAudioStreamType(); 611 } 612 613 sp<AMessage> videoFormat = mSource->getFormat(false /* audio */); 614 615 mOffloadAudio = 616 canOffloadStream(audioMeta, (videoFormat != NULL), 617 true /* is_streaming */, streamType); 618 if (mOffloadAudio) { 619 flags |= Renderer::FLAG_OFFLOAD_AUDIO; 620 } 621 622 sp<AMessage> notify = new AMessage(kWhatRendererNotify, id()); 623 ++mRendererGeneration; 624 notify->setInt32("generation", mRendererGeneration); 625 mRenderer = new Renderer(mAudioSink, notify, flags); 626 627 mRendererLooper = new ALooper; 628 mRendererLooper->setName("NuPlayerRenderer"); 629 mRendererLooper->start(false, false, ANDROID_PRIORITY_AUDIO); 630 mRendererLooper->registerHandler(mRenderer); 631 632 sp<MetaData> meta = getFileMeta(); 633 int32_t rate; 634 if (meta != NULL 635 && meta->findInt32(kKeyFrameRate, &rate) && rate > 0) { 636 mRenderer->setVideoFrameRate(rate); 637 } 638 639 postScanSources(); 640 break; 641 } 642 643 case kWhatScanSources: 644 { 645 int32_t generation; 646 CHECK(msg->findInt32("generation", &generation)); 647 if (generation != mScanSourcesGeneration) { 648 // Drop obsolete msg. 649 break; 650 } 651 652 mScanSourcesPending = false; 653 654 ALOGV("scanning sources haveAudio=%d, haveVideo=%d", 655 mAudioDecoder != NULL, mVideoDecoder != NULL); 656 657 bool mHadAnySourcesBefore = 658 (mAudioDecoder != NULL) || (mVideoDecoder != NULL); 659 660 // initialize video before audio because successful initialization of 661 // video may change deep buffer mode of audio. 662 if (mNativeWindow != NULL) { 663 instantiateDecoder(false, &mVideoDecoder); 664 } 665 666 if (mAudioSink != NULL) { 667 if (mOffloadAudio) { 668 // open audio sink early under offload mode. 669 sp<AMessage> format = mSource->getFormat(true /*audio*/); 670 openAudioSink(format, true /*offloadOnly*/); 671 } 672 instantiateDecoder(true, &mAudioDecoder); 673 } 674 675 if (!mHadAnySourcesBefore 676 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) { 677 // This is the first time we've found anything playable. 678 679 if (mSourceFlags & Source::FLAG_DYNAMIC_DURATION) { 680 schedulePollDuration(); 681 } 682 } 683 684 status_t err; 685 if ((err = mSource->feedMoreTSData()) != OK) { 686 if (mAudioDecoder == NULL && mVideoDecoder == NULL) { 687 // We're not currently decoding anything (no audio or 688 // video tracks found) and we just ran out of input data. 689 690 if (err == ERROR_END_OF_STREAM) { 691 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); 692 } else { 693 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 694 } 695 } 696 break; 697 } 698 699 if ((mAudioDecoder == NULL && mAudioSink != NULL) 700 || (mVideoDecoder == NULL && mNativeWindow != NULL)) { 701 msg->post(100000ll); 702 mScanSourcesPending = true; 703 } 704 break; 705 } 706 707 case kWhatVideoNotify: 708 case kWhatAudioNotify: 709 { 710 bool audio = msg->what() == kWhatAudioNotify; 711 712 int32_t currentDecoderGeneration = 713 (audio? mAudioDecoderGeneration : mVideoDecoderGeneration); 714 int32_t requesterGeneration = currentDecoderGeneration - 1; 715 CHECK(msg->findInt32("generation", &requesterGeneration)); 716 717 if (requesterGeneration != currentDecoderGeneration) { 718 ALOGV("got message from old %s decoder, generation(%d:%d)", 719 audio ? "audio" : "video", requesterGeneration, 720 currentDecoderGeneration); 721 sp<AMessage> reply; 722 if (!(msg->findMessage("reply", &reply))) { 723 return; 724 } 725 726 reply->setInt32("err", INFO_DISCONTINUITY); 727 reply->post(); 728 return; 729 } 730 731 int32_t what; 732 CHECK(msg->findInt32("what", &what)); 733 734 if (what == Decoder::kWhatFillThisBuffer) { 735 status_t err = feedDecoderInputData( 736 audio, msg); 737 738 if (err == -EWOULDBLOCK) { 739 if (mSource->feedMoreTSData() == OK) { 740 msg->post(10 * 1000ll); 741 } 742 } 743 } else if (what == Decoder::kWhatEOS) { 744 int32_t err; 745 CHECK(msg->findInt32("err", &err)); 746 747 if (err == ERROR_END_OF_STREAM) { 748 ALOGV("got %s decoder EOS", audio ? "audio" : "video"); 749 } else { 750 ALOGV("got %s decoder EOS w/ error %d", 751 audio ? "audio" : "video", 752 err); 753 } 754 755 mRenderer->queueEOS(audio, err); 756 } else if (what == Decoder::kWhatFlushCompleted) { 757 ALOGV("decoder %s flush completed", audio ? "audio" : "video"); 758 759 handleFlushComplete(audio, true /* isDecoder */); 760 finishFlushIfPossible(); 761 } else if (what == Decoder::kWhatOutputFormatChanged) { 762 sp<AMessage> format; 763 CHECK(msg->findMessage("format", &format)); 764 765 if (audio) { 766 openAudioSink(format, false /*offloadOnly*/); 767 } else { 768 // video 769 sp<AMessage> inputFormat = 770 mSource->getFormat(false /* audio */); 771 772 updateVideoSize(inputFormat, format); 773 } 774 } else if (what == Decoder::kWhatShutdownCompleted) { 775 ALOGV("%s shutdown completed", audio ? "audio" : "video"); 776 if (audio) { 777 mAudioDecoder.clear(); 778 ++mAudioDecoderGeneration; 779 780 CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER); 781 mFlushingAudio = SHUT_DOWN; 782 } else { 783 mVideoDecoder.clear(); 784 ++mVideoDecoderGeneration; 785 786 CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER); 787 mFlushingVideo = SHUT_DOWN; 788 } 789 790 finishFlushIfPossible(); 791 } else if (what == Decoder::kWhatError) { 792 status_t err; 793 if (!msg->findInt32("err", &err) || err == OK) { 794 err = UNKNOWN_ERROR; 795 } 796 797 // Decoder errors can be due to Source (e.g. from streaming), 798 // or from decoding corrupted bitstreams, or from other decoder 799 // MediaCodec operations (e.g. from an ongoing reset or seek). 800 // 801 // We try to gracefully shut down the affected decoder if possible, 802 // rather than trying to force the shutdown with something 803 // similar to performReset(). This method can lead to a hang 804 // if MediaCodec functions block after an error, but they should 805 // typically return INVALID_OPERATION instead of blocking. 806 807 FlushStatus *flushing = audio ? &mFlushingAudio : &mFlushingVideo; 808 ALOGE("received error(%#x) from %s decoder, flushing(%d), now shutting down", 809 err, audio ? "audio" : "video", *flushing); 810 811 switch (*flushing) { 812 case NONE: 813 mDeferredActions.push_back( 814 new ShutdownDecoderAction(audio, !audio /* video */)); 815 processDeferredActions(); 816 break; 817 case FLUSHING_DECODER: 818 *flushing = FLUSHING_DECODER_SHUTDOWN; // initiate shutdown after flush. 819 break; // Wait for flush to complete. 820 case FLUSHING_DECODER_SHUTDOWN: 821 break; // Wait for flush to complete. 822 case SHUTTING_DOWN_DECODER: 823 break; // Wait for shutdown to complete. 824 case FLUSHED: 825 // Widevine source reads must stop before releasing the video decoder. 826 if (!audio && mSource != NULL && mSourceFlags & Source::FLAG_SECURE) { 827 mSource->stop(); 828 } 829 getDecoder(audio)->initiateShutdown(); // In the middle of a seek. 830 *flushing = SHUTTING_DOWN_DECODER; // Shut down. 831 break; 832 case SHUT_DOWN: 833 finishFlushIfPossible(); // Should not occur. 834 break; // Finish anyways. 835 } 836 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 837 } else if (what == Decoder::kWhatDrainThisBuffer) { 838 renderBuffer(audio, msg); 839 } else { 840 ALOGV("Unhandled decoder notification %d '%c%c%c%c'.", 841 what, 842 what >> 24, 843 (what >> 16) & 0xff, 844 (what >> 8) & 0xff, 845 what & 0xff); 846 } 847 848 break; 849 } 850 851 case kWhatRendererNotify: 852 { 853 int32_t requesterGeneration = mRendererGeneration - 1; 854 CHECK(msg->findInt32("generation", &requesterGeneration)); 855 if (requesterGeneration != mRendererGeneration) { 856 ALOGV("got message from old renderer, generation(%d:%d)", 857 requesterGeneration, mRendererGeneration); 858 return; 859 } 860 861 int32_t what; 862 CHECK(msg->findInt32("what", &what)); 863 864 if (what == Renderer::kWhatEOS) { 865 int32_t audio; 866 CHECK(msg->findInt32("audio", &audio)); 867 868 int32_t finalResult; 869 CHECK(msg->findInt32("finalResult", &finalResult)); 870 871 if (audio) { 872 mAudioEOS = true; 873 } else { 874 mVideoEOS = true; 875 } 876 877 if (finalResult == ERROR_END_OF_STREAM) { 878 ALOGV("reached %s EOS", audio ? "audio" : "video"); 879 } else { 880 ALOGE("%s track encountered an error (%d)", 881 audio ? "audio" : "video", finalResult); 882 883 notifyListener( 884 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult); 885 } 886 887 if ((mAudioEOS || mAudioDecoder == NULL) 888 && (mVideoEOS || mVideoDecoder == NULL)) { 889 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); 890 } 891 } else if (what == Renderer::kWhatFlushComplete) { 892 int32_t audio; 893 CHECK(msg->findInt32("audio", &audio)); 894 895 ALOGV("renderer %s flush completed.", audio ? "audio" : "video"); 896 handleFlushComplete(audio, false /* isDecoder */); 897 finishFlushIfPossible(); 898 } else if (what == Renderer::kWhatVideoRenderingStart) { 899 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0); 900 } else if (what == Renderer::kWhatMediaRenderingStart) { 901 ALOGV("media rendering started"); 902 notifyListener(MEDIA_STARTED, 0, 0); 903 } else if (what == Renderer::kWhatAudioOffloadTearDown) { 904 ALOGV("Tear down audio offload, fall back to s/w path"); 905 int64_t positionUs; 906 CHECK(msg->findInt64("positionUs", &positionUs)); 907 int32_t reason; 908 CHECK(msg->findInt32("reason", &reason)); 909 closeAudioSink(); 910 mAudioDecoder.clear(); 911 ++mAudioDecoderGeneration; 912 mRenderer->flush(true /* audio */); 913 if (mVideoDecoder != NULL) { 914 mRenderer->flush(false /* audio */); 915 } 916 mRenderer->signalDisableOffloadAudio(); 917 mOffloadAudio = false; 918 919 performSeek(positionUs, false /* needNotify */); 920 if (reason == Renderer::kDueToError) { 921 instantiateDecoder(true /* audio */, &mAudioDecoder); 922 } 923 } 924 break; 925 } 926 927 case kWhatMoreDataQueued: 928 { 929 break; 930 } 931 932 case kWhatReset: 933 { 934 ALOGV("kWhatReset"); 935 936 mDeferredActions.push_back( 937 new ShutdownDecoderAction( 938 true /* audio */, true /* video */)); 939 940 mDeferredActions.push_back( 941 new SimpleAction(&NuPlayer::performReset)); 942 943 processDeferredActions(); 944 break; 945 } 946 947 case kWhatSeek: 948 { 949 int64_t seekTimeUs; 950 int32_t needNotify; 951 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs)); 952 CHECK(msg->findInt32("needNotify", &needNotify)); 953 954 ALOGV("kWhatSeek seekTimeUs=%lld us, needNotify=%d", 955 seekTimeUs, needNotify); 956 957 mDeferredActions.push_back( 958 new SimpleAction(&NuPlayer::performDecoderFlush)); 959 960 mDeferredActions.push_back( 961 new SeekAction(seekTimeUs, needNotify)); 962 963 processDeferredActions(); 964 break; 965 } 966 967 case kWhatPause: 968 { 969 if (mSource != NULL) { 970 mSource->pause(); 971 } else { 972 ALOGW("pause called when source is gone or not set"); 973 } 974 if (mRenderer != NULL) { 975 mRenderer->pause(); 976 } else { 977 ALOGW("pause called when renderer is gone or not set"); 978 } 979 break; 980 } 981 982 case kWhatResume: 983 { 984 if (mSource != NULL) { 985 mSource->resume(); 986 } else { 987 ALOGW("resume called when source is gone or not set"); 988 } 989 // |mAudioDecoder| may have been released due to the pause timeout, so re-create it if 990 // needed. 991 if (audioDecoderStillNeeded() && mAudioDecoder == NULL) { 992 instantiateDecoder(true /* audio */, &mAudioDecoder); 993 } 994 if (mRenderer != NULL) { 995 mRenderer->resume(); 996 } else { 997 ALOGW("resume called when renderer is gone or not set"); 998 } 999 break; 1000 } 1001 1002 case kWhatSourceNotify: 1003 { 1004 onSourceNotify(msg); 1005 break; 1006 } 1007 1008 case kWhatClosedCaptionNotify: 1009 { 1010 onClosedCaptionNotify(msg); 1011 break; 1012 } 1013 1014 default: 1015 TRESPASS(); 1016 break; 1017 } 1018 } 1019 1020 bool NuPlayer::audioDecoderStillNeeded() { 1021 // Audio decoder is no longer needed if it's in shut/shutting down status. 1022 return ((mFlushingAudio != SHUT_DOWN) && (mFlushingAudio != SHUTTING_DOWN_DECODER)); 1023 } 1024 1025 void NuPlayer::handleFlushComplete(bool audio, bool isDecoder) { 1026 // We wait for both the decoder flush and the renderer flush to complete 1027 // before entering either the FLUSHED or the SHUTTING_DOWN_DECODER state. 1028 1029 mFlushComplete[audio][isDecoder] = true; 1030 if (!mFlushComplete[audio][!isDecoder]) { 1031 return; 1032 } 1033 1034 FlushStatus *state = audio ? &mFlushingAudio : &mFlushingVideo; 1035 switch (*state) { 1036 case FLUSHING_DECODER: 1037 { 1038 *state = FLUSHED; 1039 break; 1040 } 1041 1042 case FLUSHING_DECODER_SHUTDOWN: 1043 { 1044 *state = SHUTTING_DOWN_DECODER; 1045 1046 ALOGV("initiating %s decoder shutdown", audio ? "audio" : "video"); 1047 if (!audio) { 1048 // Widevine source reads must stop before releasing the video decoder. 1049 if (mSource != NULL && mSourceFlags & Source::FLAG_SECURE) { 1050 mSource->stop(); 1051 } 1052 } 1053 getDecoder(audio)->initiateShutdown(); 1054 break; 1055 } 1056 1057 default: 1058 // decoder flush completes only occur in a flushing state. 1059 LOG_ALWAYS_FATAL_IF(isDecoder, "decoder flush in invalid state %d", *state); 1060 break; 1061 } 1062 } 1063 1064 void NuPlayer::finishFlushIfPossible() { 1065 if (mFlushingAudio != NONE && mFlushingAudio != FLUSHED 1066 && mFlushingAudio != SHUT_DOWN) { 1067 return; 1068 } 1069 1070 if (mFlushingVideo != NONE && mFlushingVideo != FLUSHED 1071 && mFlushingVideo != SHUT_DOWN) { 1072 return; 1073 } 1074 1075 ALOGV("both audio and video are flushed now."); 1076 1077 mPendingAudioAccessUnit.clear(); 1078 mAggregateBuffer.clear(); 1079 1080 if (mTimeDiscontinuityPending) { 1081 mRenderer->signalTimeDiscontinuity(); 1082 mTimeDiscontinuityPending = false; 1083 } 1084 1085 if (mAudioDecoder != NULL && mFlushingAudio == FLUSHED) { 1086 mAudioDecoder->signalResume(); 1087 } 1088 1089 if (mVideoDecoder != NULL && mFlushingVideo == FLUSHED) { 1090 mVideoDecoder->signalResume(); 1091 } 1092 1093 mFlushingAudio = NONE; 1094 mFlushingVideo = NONE; 1095 1096 clearFlushComplete(); 1097 1098 processDeferredActions(); 1099 } 1100 1101 void NuPlayer::postScanSources() { 1102 if (mScanSourcesPending) { 1103 return; 1104 } 1105 1106 sp<AMessage> msg = new AMessage(kWhatScanSources, id()); 1107 msg->setInt32("generation", mScanSourcesGeneration); 1108 msg->post(); 1109 1110 mScanSourcesPending = true; 1111 } 1112 1113 void NuPlayer::openAudioSink(const sp<AMessage> &format, bool offloadOnly) { 1114 uint32_t flags; 1115 int64_t durationUs; 1116 bool hasVideo = (mVideoDecoder != NULL); 1117 // FIXME: we should handle the case where the video decoder 1118 // is created after we receive the format change indication. 1119 // Current code will just make that we select deep buffer 1120 // with video which should not be a problem as it should 1121 // not prevent from keeping A/V sync. 1122 if (hasVideo && 1123 mSource->getDuration(&durationUs) == OK && 1124 durationUs 1125 > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) { 1126 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; 1127 } else { 1128 flags = AUDIO_OUTPUT_FLAG_NONE; 1129 } 1130 1131 mOffloadAudio = mRenderer->openAudioSink( 1132 format, offloadOnly, hasVideo, flags); 1133 1134 if (mOffloadAudio) { 1135 sp<MetaData> audioMeta = 1136 mSource->getFormatMeta(true /* audio */); 1137 sendMetaDataToHal(mAudioSink, audioMeta); 1138 } 1139 } 1140 1141 void NuPlayer::closeAudioSink() { 1142 mRenderer->closeAudioSink(); 1143 } 1144 1145 status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) { 1146 if (*decoder != NULL) { 1147 return OK; 1148 } 1149 1150 sp<AMessage> format = mSource->getFormat(audio); 1151 1152 if (format == NULL) { 1153 return -EWOULDBLOCK; 1154 } 1155 1156 if (!audio) { 1157 AString mime; 1158 CHECK(format->findString("mime", &mime)); 1159 mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str()); 1160 1161 sp<AMessage> ccNotify = new AMessage(kWhatClosedCaptionNotify, id()); 1162 mCCDecoder = new CCDecoder(ccNotify); 1163 1164 if (mSourceFlags & Source::FLAG_SECURE) { 1165 format->setInt32("secure", true); 1166 } 1167 } 1168 1169 if (audio) { 1170 sp<AMessage> notify = new AMessage(kWhatAudioNotify, id()); 1171 ++mAudioDecoderGeneration; 1172 notify->setInt32("generation", mAudioDecoderGeneration); 1173 1174 if (mOffloadAudio) { 1175 *decoder = new DecoderPassThrough(notify); 1176 } else { 1177 *decoder = new Decoder(notify); 1178 } 1179 } else { 1180 sp<AMessage> notify = new AMessage(kWhatVideoNotify, id()); 1181 ++mVideoDecoderGeneration; 1182 notify->setInt32("generation", mVideoDecoderGeneration); 1183 1184 *decoder = new Decoder(notify, mNativeWindow); 1185 } 1186 (*decoder)->init(); 1187 (*decoder)->configure(format); 1188 1189 // allocate buffers to decrypt widevine source buffers 1190 if (!audio && (mSourceFlags & Source::FLAG_SECURE)) { 1191 Vector<sp<ABuffer> > inputBufs; 1192 CHECK_EQ((*decoder)->getInputBuffers(&inputBufs), (status_t)OK); 1193 1194 Vector<MediaBuffer *> mediaBufs; 1195 for (size_t i = 0; i < inputBufs.size(); i++) { 1196 const sp<ABuffer> &buffer = inputBufs[i]; 1197 MediaBuffer *mbuf = new MediaBuffer(buffer->data(), buffer->size()); 1198 mediaBufs.push(mbuf); 1199 } 1200 1201 status_t err = mSource->setBuffers(audio, mediaBufs); 1202 if (err != OK) { 1203 for (size_t i = 0; i < mediaBufs.size(); ++i) { 1204 mediaBufs[i]->release(); 1205 } 1206 mediaBufs.clear(); 1207 ALOGE("Secure source didn't support secure mediaBufs."); 1208 return err; 1209 } 1210 } 1211 return OK; 1212 } 1213 1214 status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { 1215 sp<AMessage> reply; 1216 CHECK(msg->findMessage("reply", &reply)); 1217 1218 if ((audio && mFlushingAudio != NONE) 1219 || (!audio && mFlushingVideo != NONE) 1220 || mSource == NULL) { 1221 reply->setInt32("err", INFO_DISCONTINUITY); 1222 reply->post(); 1223 return OK; 1224 } 1225 1226 sp<ABuffer> accessUnit; 1227 1228 // Aggregate smaller buffers into a larger buffer. 1229 // The goal is to reduce power consumption. 1230 // Note this will not work if the decoder requires one frame per buffer. 1231 bool doBufferAggregation = (audio && mOffloadAudio); 1232 bool needMoreData = false; 1233 1234 bool dropAccessUnit; 1235 do { 1236 status_t err; 1237 // Did we save an accessUnit earlier because of a discontinuity? 1238 if (audio && (mPendingAudioAccessUnit != NULL)) { 1239 accessUnit = mPendingAudioAccessUnit; 1240 mPendingAudioAccessUnit.clear(); 1241 err = mPendingAudioErr; 1242 ALOGV("feedDecoderInputData() use mPendingAudioAccessUnit"); 1243 } else { 1244 err = mSource->dequeueAccessUnit(audio, &accessUnit); 1245 } 1246 1247 if (err == -EWOULDBLOCK) { 1248 return err; 1249 } else if (err != OK) { 1250 if (err == INFO_DISCONTINUITY) { 1251 if (doBufferAggregation && (mAggregateBuffer != NULL)) { 1252 // We already have some data so save this for later. 1253 mPendingAudioErr = err; 1254 mPendingAudioAccessUnit = accessUnit; 1255 accessUnit.clear(); 1256 ALOGD("feedDecoderInputData() save discontinuity for later"); 1257 break; 1258 } 1259 int32_t type; 1260 CHECK(accessUnit->meta()->findInt32("discontinuity", &type)); 1261 1262 bool formatChange = 1263 (audio && 1264 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT)) 1265 || (!audio && 1266 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT)); 1267 1268 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0; 1269 1270 ALOGI("%s discontinuity (formatChange=%d, time=%d)", 1271 audio ? "audio" : "video", formatChange, timeChange); 1272 1273 if (audio) { 1274 mSkipRenderingAudioUntilMediaTimeUs = -1; 1275 } else { 1276 mSkipRenderingVideoUntilMediaTimeUs = -1; 1277 } 1278 1279 if (timeChange) { 1280 sp<AMessage> extra; 1281 if (accessUnit->meta()->findMessage("extra", &extra) 1282 && extra != NULL) { 1283 int64_t resumeAtMediaTimeUs; 1284 if (extra->findInt64( 1285 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) { 1286 ALOGI("suppressing rendering of %s until %lld us", 1287 audio ? "audio" : "video", resumeAtMediaTimeUs); 1288 1289 if (audio) { 1290 mSkipRenderingAudioUntilMediaTimeUs = 1291 resumeAtMediaTimeUs; 1292 } else { 1293 mSkipRenderingVideoUntilMediaTimeUs = 1294 resumeAtMediaTimeUs; 1295 } 1296 } 1297 } 1298 } 1299 1300 mTimeDiscontinuityPending = 1301 mTimeDiscontinuityPending || timeChange; 1302 1303 bool seamlessFormatChange = false; 1304 sp<AMessage> newFormat = mSource->getFormat(audio); 1305 if (formatChange) { 1306 seamlessFormatChange = 1307 getDecoder(audio)->supportsSeamlessFormatChange(newFormat); 1308 // treat seamless format change separately 1309 formatChange = !seamlessFormatChange; 1310 } 1311 bool shutdownOrFlush = formatChange || timeChange; 1312 1313 // We want to queue up scan-sources only once per discontinuity. 1314 // We control this by doing it only if neither audio nor video are 1315 // flushing or shutting down. (After handling 1st discontinuity, one 1316 // of the flushing states will not be NONE.) 1317 // No need to scan sources if this discontinuity does not result 1318 // in a flush or shutdown, as the flushing state will stay NONE. 1319 if (mFlushingAudio == NONE && mFlushingVideo == NONE && 1320 shutdownOrFlush) { 1321 // And we'll resume scanning sources once we're done 1322 // flushing. 1323 mDeferredActions.push_front( 1324 new SimpleAction( 1325 &NuPlayer::performScanSources)); 1326 } 1327 1328 if (formatChange /* not seamless */) { 1329 // must change decoder 1330 flushDecoder(audio, /* needShutdown = */ true); 1331 } else if (timeChange) { 1332 // need to flush 1333 flushDecoder(audio, /* needShutdown = */ false, newFormat); 1334 err = OK; 1335 } else if (seamlessFormatChange) { 1336 // reuse existing decoder and don't flush 1337 updateDecoderFormatWithoutFlush(audio, newFormat); 1338 err = OK; 1339 } else { 1340 // This stream is unaffected by the discontinuity 1341 return -EWOULDBLOCK; 1342 } 1343 } 1344 1345 reply->setInt32("err", err); 1346 reply->post(); 1347 return OK; 1348 } 1349 1350 if (!audio) { 1351 ++mNumFramesTotal; 1352 } 1353 1354 dropAccessUnit = false; 1355 if (!audio 1356 && !(mSourceFlags & Source::FLAG_SECURE) 1357 && mRenderer->getVideoLateByUs() > 100000ll 1358 && mVideoIsAVC 1359 && !IsAVCReferenceFrame(accessUnit)) { 1360 dropAccessUnit = true; 1361 ++mNumFramesDropped; 1362 } 1363 1364 size_t smallSize = accessUnit->size(); 1365 needMoreData = false; 1366 if (doBufferAggregation && (mAggregateBuffer == NULL) 1367 // Don't bother if only room for a few small buffers. 1368 && (smallSize < (kAggregateBufferSizeBytes / 3))) { 1369 // Create a larger buffer for combining smaller buffers from the extractor. 1370 mAggregateBuffer = new ABuffer(kAggregateBufferSizeBytes); 1371 mAggregateBuffer->setRange(0, 0); // start empty 1372 } 1373 1374 if (doBufferAggregation && (mAggregateBuffer != NULL)) { 1375 int64_t timeUs; 1376 int64_t dummy; 1377 bool smallTimestampValid = accessUnit->meta()->findInt64("timeUs", &timeUs); 1378 bool bigTimestampValid = mAggregateBuffer->meta()->findInt64("timeUs", &dummy); 1379 // Will the smaller buffer fit? 1380 size_t bigSize = mAggregateBuffer->size(); 1381 size_t roomLeft = mAggregateBuffer->capacity() - bigSize; 1382 // Should we save this small buffer for the next big buffer? 1383 // If the first small buffer did not have a timestamp then save 1384 // any buffer that does have a timestamp until the next big buffer. 1385 if ((smallSize > roomLeft) 1386 || (!bigTimestampValid && (bigSize > 0) && smallTimestampValid)) { 1387 mPendingAudioErr = err; 1388 mPendingAudioAccessUnit = accessUnit; 1389 accessUnit.clear(); 1390 } else { 1391 // Grab time from first small buffer if available. 1392 if ((bigSize == 0) && smallTimestampValid) { 1393 mAggregateBuffer->meta()->setInt64("timeUs", timeUs); 1394 } 1395 // Append small buffer to the bigger buffer. 1396 memcpy(mAggregateBuffer->base() + bigSize, accessUnit->data(), smallSize); 1397 bigSize += smallSize; 1398 mAggregateBuffer->setRange(0, bigSize); 1399 1400 // Keep looping until we run out of room in the mAggregateBuffer. 1401 needMoreData = true; 1402 1403 ALOGV("feedDecoderInputData() smallSize = %zu, bigSize = %zu, capacity = %zu", 1404 smallSize, bigSize, mAggregateBuffer->capacity()); 1405 } 1406 } 1407 } while (dropAccessUnit || needMoreData); 1408 1409 // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video"); 1410 1411 #if 0 1412 int64_t mediaTimeUs; 1413 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs)); 1414 ALOGV("feeding %s input buffer at media time %.2f secs", 1415 audio ? "audio" : "video", 1416 mediaTimeUs / 1E6); 1417 #endif 1418 1419 if (!audio) { 1420 mCCDecoder->decode(accessUnit); 1421 } 1422 1423 if (doBufferAggregation && (mAggregateBuffer != NULL)) { 1424 ALOGV("feedDecoderInputData() reply with aggregated buffer, %zu", 1425 mAggregateBuffer->size()); 1426 reply->setBuffer("buffer", mAggregateBuffer); 1427 mAggregateBuffer.clear(); 1428 } else { 1429 reply->setBuffer("buffer", accessUnit); 1430 } 1431 1432 reply->post(); 1433 1434 return OK; 1435 } 1436 1437 void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) { 1438 // ALOGV("renderBuffer %s", audio ? "audio" : "video"); 1439 1440 sp<AMessage> reply; 1441 CHECK(msg->findMessage("reply", &reply)); 1442 1443 if ((audio && mFlushingAudio != NONE) 1444 || (!audio && mFlushingVideo != NONE)) { 1445 // We're currently attempting to flush the decoder, in order 1446 // to complete this, the decoder wants all its buffers back, 1447 // so we don't want any output buffers it sent us (from before 1448 // we initiated the flush) to be stuck in the renderer's queue. 1449 1450 ALOGV("we're still flushing the %s decoder, sending its output buffer" 1451 " right back.", audio ? "audio" : "video"); 1452 1453 reply->post(); 1454 return; 1455 } 1456 1457 sp<ABuffer> buffer; 1458 CHECK(msg->findBuffer("buffer", &buffer)); 1459 1460 int64_t mediaTimeUs; 1461 CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs)); 1462 1463 int64_t &skipUntilMediaTimeUs = 1464 audio 1465 ? mSkipRenderingAudioUntilMediaTimeUs 1466 : mSkipRenderingVideoUntilMediaTimeUs; 1467 1468 if (skipUntilMediaTimeUs >= 0) { 1469 1470 if (mediaTimeUs < skipUntilMediaTimeUs) { 1471 ALOGV("dropping %s buffer at time %lld as requested.", 1472 audio ? "audio" : "video", 1473 mediaTimeUs); 1474 1475 reply->post(); 1476 return; 1477 } 1478 1479 skipUntilMediaTimeUs = -1; 1480 } 1481 1482 if (!audio && mCCDecoder->isSelected()) { 1483 mCCDecoder->display(mediaTimeUs); 1484 } 1485 1486 mRenderer->queueBuffer(audio, buffer, reply); 1487 } 1488 1489 void NuPlayer::updateVideoSize( 1490 const sp<AMessage> &inputFormat, 1491 const sp<AMessage> &outputFormat) { 1492 if (inputFormat == NULL) { 1493 ALOGW("Unknown video size, reporting 0x0!"); 1494 notifyListener(MEDIA_SET_VIDEO_SIZE, 0, 0); 1495 return; 1496 } 1497 1498 int32_t displayWidth, displayHeight; 1499 int32_t cropLeft, cropTop, cropRight, cropBottom; 1500 1501 if (outputFormat != NULL) { 1502 int32_t width, height; 1503 CHECK(outputFormat->findInt32("width", &width)); 1504 CHECK(outputFormat->findInt32("height", &height)); 1505 1506 int32_t cropLeft, cropTop, cropRight, cropBottom; 1507 CHECK(outputFormat->findRect( 1508 "crop", 1509 &cropLeft, &cropTop, &cropRight, &cropBottom)); 1510 1511 displayWidth = cropRight - cropLeft + 1; 1512 displayHeight = cropBottom - cropTop + 1; 1513 1514 ALOGV("Video output format changed to %d x %d " 1515 "(crop: %d x %d @ (%d, %d))", 1516 width, height, 1517 displayWidth, 1518 displayHeight, 1519 cropLeft, cropTop); 1520 } else { 1521 CHECK(inputFormat->findInt32("width", &displayWidth)); 1522 CHECK(inputFormat->findInt32("height", &displayHeight)); 1523 1524 ALOGV("Video input format %d x %d", displayWidth, displayHeight); 1525 } 1526 1527 // Take into account sample aspect ratio if necessary: 1528 int32_t sarWidth, sarHeight; 1529 if (inputFormat->findInt32("sar-width", &sarWidth) 1530 && inputFormat->findInt32("sar-height", &sarHeight)) { 1531 ALOGV("Sample aspect ratio %d : %d", sarWidth, sarHeight); 1532 1533 displayWidth = (displayWidth * sarWidth) / sarHeight; 1534 1535 ALOGV("display dimensions %d x %d", displayWidth, displayHeight); 1536 } 1537 1538 int32_t rotationDegrees; 1539 if (!inputFormat->findInt32("rotation-degrees", &rotationDegrees)) { 1540 rotationDegrees = 0; 1541 } 1542 1543 if (rotationDegrees == 90 || rotationDegrees == 270) { 1544 int32_t tmp = displayWidth; 1545 displayWidth = displayHeight; 1546 displayHeight = tmp; 1547 } 1548 1549 notifyListener( 1550 MEDIA_SET_VIDEO_SIZE, 1551 displayWidth, 1552 displayHeight); 1553 } 1554 1555 void NuPlayer::notifyListener(int msg, int ext1, int ext2, const Parcel *in) { 1556 if (mDriver == NULL) { 1557 return; 1558 } 1559 1560 sp<NuPlayerDriver> driver = mDriver.promote(); 1561 1562 if (driver == NULL) { 1563 return; 1564 } 1565 1566 driver->notifyListener(msg, ext1, ext2, in); 1567 } 1568 1569 void NuPlayer::flushDecoder( 1570 bool audio, bool needShutdown, const sp<AMessage> &newFormat) { 1571 ALOGV("[%s] flushDecoder needShutdown=%d", 1572 audio ? "audio" : "video", needShutdown); 1573 1574 const sp<Decoder> &decoder = getDecoder(audio); 1575 if (decoder == NULL) { 1576 ALOGI("flushDecoder %s without decoder present", 1577 audio ? "audio" : "video"); 1578 return; 1579 } 1580 1581 // Make sure we don't continue to scan sources until we finish flushing. 1582 ++mScanSourcesGeneration; 1583 mScanSourcesPending = false; 1584 1585 decoder->signalFlush(newFormat); 1586 mRenderer->flush(audio); 1587 1588 FlushStatus newStatus = 1589 needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER; 1590 1591 mFlushComplete[audio][false /* isDecoder */] = false; 1592 mFlushComplete[audio][true /* isDecoder */] = false; 1593 if (audio) { 1594 ALOGE_IF(mFlushingAudio != NONE, 1595 "audio flushDecoder() is called in state %d", mFlushingAudio); 1596 mFlushingAudio = newStatus; 1597 } else { 1598 ALOGE_IF(mFlushingVideo != NONE, 1599 "video flushDecoder() is called in state %d", mFlushingVideo); 1600 mFlushingVideo = newStatus; 1601 1602 if (mCCDecoder != NULL) { 1603 mCCDecoder->flush(); 1604 } 1605 } 1606 } 1607 1608 void NuPlayer::updateDecoderFormatWithoutFlush( 1609 bool audio, const sp<AMessage> &format) { 1610 ALOGV("[%s] updateDecoderFormatWithoutFlush", audio ? "audio" : "video"); 1611 1612 const sp<Decoder> &decoder = getDecoder(audio); 1613 if (decoder == NULL) { 1614 ALOGI("updateDecoderFormatWithoutFlush %s without decoder present", 1615 audio ? "audio" : "video"); 1616 return; 1617 } 1618 1619 decoder->signalUpdateFormat(format); 1620 } 1621 1622 void NuPlayer::queueDecoderShutdown( 1623 bool audio, bool video, const sp<AMessage> &reply) { 1624 ALOGI("queueDecoderShutdown audio=%d, video=%d", audio, video); 1625 1626 mDeferredActions.push_back( 1627 new ShutdownDecoderAction(audio, video)); 1628 1629 mDeferredActions.push_back( 1630 new SimpleAction(&NuPlayer::performScanSources)); 1631 1632 mDeferredActions.push_back(new PostMessageAction(reply)); 1633 1634 processDeferredActions(); 1635 } 1636 1637 status_t NuPlayer::setVideoScalingMode(int32_t mode) { 1638 mVideoScalingMode = mode; 1639 if (mNativeWindow != NULL) { 1640 status_t ret = native_window_set_scaling_mode( 1641 mNativeWindow->getNativeWindow().get(), mVideoScalingMode); 1642 if (ret != OK) { 1643 ALOGE("Failed to set scaling mode (%d): %s", 1644 -ret, strerror(-ret)); 1645 return ret; 1646 } 1647 } 1648 return OK; 1649 } 1650 1651 status_t NuPlayer::getTrackInfo(Parcel* reply) const { 1652 sp<AMessage> msg = new AMessage(kWhatGetTrackInfo, id()); 1653 msg->setPointer("reply", reply); 1654 1655 sp<AMessage> response; 1656 status_t err = msg->postAndAwaitResponse(&response); 1657 return err; 1658 } 1659 1660 status_t NuPlayer::getSelectedTrack(int32_t type, Parcel* reply) const { 1661 sp<AMessage> msg = new AMessage(kWhatGetSelectedTrack, id()); 1662 msg->setPointer("reply", reply); 1663 msg->setInt32("type", type); 1664 1665 sp<AMessage> response; 1666 status_t err = msg->postAndAwaitResponse(&response); 1667 if (err == OK && response != NULL) { 1668 CHECK(response->findInt32("err", &err)); 1669 } 1670 return err; 1671 } 1672 1673 status_t NuPlayer::selectTrack(size_t trackIndex, bool select) { 1674 sp<AMessage> msg = new AMessage(kWhatSelectTrack, id()); 1675 msg->setSize("trackIndex", trackIndex); 1676 msg->setInt32("select", select); 1677 1678 sp<AMessage> response; 1679 status_t err = msg->postAndAwaitResponse(&response); 1680 1681 if (err != OK) { 1682 return err; 1683 } 1684 1685 if (!response->findInt32("err", &err)) { 1686 err = OK; 1687 } 1688 1689 return err; 1690 } 1691 1692 status_t NuPlayer::getCurrentPosition(int64_t *mediaUs) { 1693 sp<Renderer> renderer = mRenderer; 1694 if (renderer == NULL) { 1695 return NO_INIT; 1696 } 1697 1698 return renderer->getCurrentPosition(mediaUs); 1699 } 1700 1701 void NuPlayer::getStats(int64_t *numFramesTotal, int64_t *numFramesDropped) { 1702 *numFramesTotal = mNumFramesTotal; 1703 *numFramesDropped = mNumFramesDropped; 1704 } 1705 1706 sp<MetaData> NuPlayer::getFileMeta() { 1707 return mSource->getFileFormatMeta(); 1708 } 1709 1710 void NuPlayer::schedulePollDuration() { 1711 sp<AMessage> msg = new AMessage(kWhatPollDuration, id()); 1712 msg->setInt32("generation", mPollDurationGeneration); 1713 msg->post(); 1714 } 1715 1716 void NuPlayer::cancelPollDuration() { 1717 ++mPollDurationGeneration; 1718 } 1719 1720 void NuPlayer::processDeferredActions() { 1721 while (!mDeferredActions.empty()) { 1722 // We won't execute any deferred actions until we're no longer in 1723 // an intermediate state, i.e. one more more decoders are currently 1724 // flushing or shutting down. 1725 1726 if (mFlushingAudio != NONE || mFlushingVideo != NONE) { 1727 // We're currently flushing, postpone the reset until that's 1728 // completed. 1729 1730 ALOGV("postponing action mFlushingAudio=%d, mFlushingVideo=%d", 1731 mFlushingAudio, mFlushingVideo); 1732 1733 break; 1734 } 1735 1736 sp<Action> action = *mDeferredActions.begin(); 1737 mDeferredActions.erase(mDeferredActions.begin()); 1738 1739 action->execute(this); 1740 } 1741 } 1742 1743 void NuPlayer::performSeek(int64_t seekTimeUs, bool needNotify) { 1744 ALOGV("performSeek seekTimeUs=%lld us (%.2f secs), needNotify(%d)", 1745 seekTimeUs, 1746 seekTimeUs / 1E6, 1747 needNotify); 1748 1749 if (mSource == NULL) { 1750 // This happens when reset occurs right before the loop mode 1751 // asynchronously seeks to the start of the stream. 1752 LOG_ALWAYS_FATAL_IF(mAudioDecoder != NULL || mVideoDecoder != NULL, 1753 "mSource is NULL and decoders not NULL audio(%p) video(%p)", 1754 mAudioDecoder.get(), mVideoDecoder.get()); 1755 return; 1756 } 1757 mSource->seekTo(seekTimeUs); 1758 ++mTimedTextGeneration; 1759 1760 if (mDriver != NULL) { 1761 sp<NuPlayerDriver> driver = mDriver.promote(); 1762 if (driver != NULL) { 1763 if (needNotify) { 1764 driver->notifySeekComplete(); 1765 } 1766 } 1767 } 1768 1769 // everything's flushed, continue playback. 1770 } 1771 1772 void NuPlayer::performDecoderFlush() { 1773 ALOGV("performDecoderFlush"); 1774 1775 if (mAudioDecoder == NULL && mVideoDecoder == NULL) { 1776 return; 1777 } 1778 1779 mTimeDiscontinuityPending = true; 1780 1781 if (mAudioDecoder != NULL) { 1782 flushDecoder(true /* audio */, false /* needShutdown */); 1783 } 1784 1785 if (mVideoDecoder != NULL) { 1786 flushDecoder(false /* audio */, false /* needShutdown */); 1787 } 1788 } 1789 1790 void NuPlayer::performDecoderShutdown(bool audio, bool video) { 1791 ALOGV("performDecoderShutdown audio=%d, video=%d", audio, video); 1792 1793 if ((!audio || mAudioDecoder == NULL) 1794 && (!video || mVideoDecoder == NULL)) { 1795 return; 1796 } 1797 1798 mTimeDiscontinuityPending = true; 1799 1800 if (audio && mAudioDecoder != NULL) { 1801 flushDecoder(true /* audio */, true /* needShutdown */); 1802 } 1803 1804 if (video && mVideoDecoder != NULL) { 1805 flushDecoder(false /* audio */, true /* needShutdown */); 1806 } 1807 } 1808 1809 void NuPlayer::performReset() { 1810 ALOGV("performReset"); 1811 1812 CHECK(mAudioDecoder == NULL); 1813 CHECK(mVideoDecoder == NULL); 1814 1815 cancelPollDuration(); 1816 1817 ++mScanSourcesGeneration; 1818 mScanSourcesPending = false; 1819 1820 if (mRendererLooper != NULL) { 1821 if (mRenderer != NULL) { 1822 mRendererLooper->unregisterHandler(mRenderer->id()); 1823 } 1824 mRendererLooper->stop(); 1825 mRendererLooper.clear(); 1826 } 1827 mRenderer.clear(); 1828 ++mRendererGeneration; 1829 1830 if (mSource != NULL) { 1831 mSource->stop(); 1832 1833 mSource.clear(); 1834 } 1835 1836 if (mDriver != NULL) { 1837 sp<NuPlayerDriver> driver = mDriver.promote(); 1838 if (driver != NULL) { 1839 driver->notifyResetComplete(); 1840 } 1841 } 1842 1843 mStarted = false; 1844 } 1845 1846 void NuPlayer::performScanSources() { 1847 ALOGV("performScanSources"); 1848 1849 if (!mStarted) { 1850 return; 1851 } 1852 1853 if (mAudioDecoder == NULL || mVideoDecoder == NULL) { 1854 postScanSources(); 1855 } 1856 } 1857 1858 void NuPlayer::performSetSurface(const sp<NativeWindowWrapper> &wrapper) { 1859 ALOGV("performSetSurface"); 1860 1861 mNativeWindow = wrapper; 1862 1863 // XXX - ignore error from setVideoScalingMode for now 1864 setVideoScalingMode(mVideoScalingMode); 1865 1866 if (mDriver != NULL) { 1867 sp<NuPlayerDriver> driver = mDriver.promote(); 1868 if (driver != NULL) { 1869 driver->notifySetSurfaceComplete(); 1870 } 1871 } 1872 } 1873 1874 void NuPlayer::onSourceNotify(const sp<AMessage> &msg) { 1875 int32_t what; 1876 CHECK(msg->findInt32("what", &what)); 1877 1878 switch (what) { 1879 case Source::kWhatPrepared: 1880 { 1881 if (mSource == NULL) { 1882 // This is a stale notification from a source that was 1883 // asynchronously preparing when the client called reset(). 1884 // We handled the reset, the source is gone. 1885 break; 1886 } 1887 1888 int32_t err; 1889 CHECK(msg->findInt32("err", &err)); 1890 1891 sp<NuPlayerDriver> driver = mDriver.promote(); 1892 if (driver != NULL) { 1893 // notify duration first, so that it's definitely set when 1894 // the app received the "prepare complete" callback. 1895 int64_t durationUs; 1896 if (mSource->getDuration(&durationUs) == OK) { 1897 driver->notifyDuration(durationUs); 1898 } 1899 driver->notifyPrepareCompleted(err); 1900 } 1901 1902 break; 1903 } 1904 1905 case Source::kWhatFlagsChanged: 1906 { 1907 uint32_t flags; 1908 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 1909 1910 sp<NuPlayerDriver> driver = mDriver.promote(); 1911 if (driver != NULL) { 1912 driver->notifyFlagsChanged(flags); 1913 } 1914 1915 if ((mSourceFlags & Source::FLAG_DYNAMIC_DURATION) 1916 && (!(flags & Source::FLAG_DYNAMIC_DURATION))) { 1917 cancelPollDuration(); 1918 } else if (!(mSourceFlags & Source::FLAG_DYNAMIC_DURATION) 1919 && (flags & Source::FLAG_DYNAMIC_DURATION) 1920 && (mAudioDecoder != NULL || mVideoDecoder != NULL)) { 1921 schedulePollDuration(); 1922 } 1923 1924 mSourceFlags = flags; 1925 break; 1926 } 1927 1928 case Source::kWhatVideoSizeChanged: 1929 { 1930 sp<AMessage> format; 1931 CHECK(msg->findMessage("format", &format)); 1932 1933 updateVideoSize(format); 1934 break; 1935 } 1936 1937 case Source::kWhatBufferingUpdate: 1938 { 1939 int32_t percentage; 1940 CHECK(msg->findInt32("percentage", &percentage)); 1941 1942 notifyListener(MEDIA_BUFFERING_UPDATE, percentage, 0); 1943 break; 1944 } 1945 1946 case Source::kWhatBufferingStart: 1947 { 1948 notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0); 1949 break; 1950 } 1951 1952 case Source::kWhatBufferingEnd: 1953 { 1954 notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0); 1955 break; 1956 } 1957 1958 case Source::kWhatSubtitleData: 1959 { 1960 sp<ABuffer> buffer; 1961 CHECK(msg->findBuffer("buffer", &buffer)); 1962 1963 sendSubtitleData(buffer, 0 /* baseIndex */); 1964 break; 1965 } 1966 1967 case Source::kWhatTimedTextData: 1968 { 1969 int32_t generation; 1970 if (msg->findInt32("generation", &generation) 1971 && generation != mTimedTextGeneration) { 1972 break; 1973 } 1974 1975 sp<ABuffer> buffer; 1976 CHECK(msg->findBuffer("buffer", &buffer)); 1977 1978 sp<NuPlayerDriver> driver = mDriver.promote(); 1979 if (driver == NULL) { 1980 break; 1981 } 1982 1983 int posMs; 1984 int64_t timeUs, posUs; 1985 driver->getCurrentPosition(&posMs); 1986 posUs = posMs * 1000; 1987 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 1988 1989 if (posUs < timeUs) { 1990 if (!msg->findInt32("generation", &generation)) { 1991 msg->setInt32("generation", mTimedTextGeneration); 1992 } 1993 msg->post(timeUs - posUs); 1994 } else { 1995 sendTimedTextData(buffer); 1996 } 1997 break; 1998 } 1999 2000 case Source::kWhatQueueDecoderShutdown: 2001 { 2002 int32_t audio, video; 2003 CHECK(msg->findInt32("audio", &audio)); 2004 CHECK(msg->findInt32("video", &video)); 2005 2006 sp<AMessage> reply; 2007 CHECK(msg->findMessage("reply", &reply)); 2008 2009 queueDecoderShutdown(audio, video, reply); 2010 break; 2011 } 2012 2013 case Source::kWhatDrmNoLicense: 2014 { 2015 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, ERROR_DRM_NO_LICENSE); 2016 break; 2017 } 2018 2019 default: 2020 TRESPASS(); 2021 } 2022 } 2023 2024 void NuPlayer::onClosedCaptionNotify(const sp<AMessage> &msg) { 2025 int32_t what; 2026 CHECK(msg->findInt32("what", &what)); 2027 2028 switch (what) { 2029 case NuPlayer::CCDecoder::kWhatClosedCaptionData: 2030 { 2031 sp<ABuffer> buffer; 2032 CHECK(msg->findBuffer("buffer", &buffer)); 2033 2034 size_t inbandTracks = 0; 2035 if (mSource != NULL) { 2036 inbandTracks = mSource->getTrackCount(); 2037 } 2038 2039 sendSubtitleData(buffer, inbandTracks); 2040 break; 2041 } 2042 2043 case NuPlayer::CCDecoder::kWhatTrackAdded: 2044 { 2045 notifyListener(MEDIA_INFO, MEDIA_INFO_METADATA_UPDATE, 0); 2046 2047 break; 2048 } 2049 2050 default: 2051 TRESPASS(); 2052 } 2053 2054 2055 } 2056 2057 void NuPlayer::sendSubtitleData(const sp<ABuffer> &buffer, int32_t baseIndex) { 2058 int32_t trackIndex; 2059 int64_t timeUs, durationUs; 2060 CHECK(buffer->meta()->findInt32("trackIndex", &trackIndex)); 2061 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2062 CHECK(buffer->meta()->findInt64("durationUs", &durationUs)); 2063 2064 Parcel in; 2065 in.writeInt32(trackIndex + baseIndex); 2066 in.writeInt64(timeUs); 2067 in.writeInt64(durationUs); 2068 in.writeInt32(buffer->size()); 2069 in.writeInt32(buffer->size()); 2070 in.write(buffer->data(), buffer->size()); 2071 2072 notifyListener(MEDIA_SUBTITLE_DATA, 0, 0, &in); 2073 } 2074 2075 void NuPlayer::sendTimedTextData(const sp<ABuffer> &buffer) { 2076 const void *data; 2077 size_t size = 0; 2078 int64_t timeUs; 2079 int32_t flag = TextDescriptions::LOCAL_DESCRIPTIONS; 2080 2081 AString mime; 2082 CHECK(buffer->meta()->findString("mime", &mime)); 2083 CHECK(strcasecmp(mime.c_str(), MEDIA_MIMETYPE_TEXT_3GPP) == 0); 2084 2085 data = buffer->data(); 2086 size = buffer->size(); 2087 2088 Parcel parcel; 2089 if (size > 0) { 2090 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2091 flag |= TextDescriptions::IN_BAND_TEXT_3GPP; 2092 TextDescriptions::getParcelOfDescriptions( 2093 (const uint8_t *)data, size, flag, timeUs / 1000, &parcel); 2094 } 2095 2096 if ((parcel.dataSize() > 0)) { 2097 notifyListener(MEDIA_TIMED_TEXT, 0, 0, &parcel); 2098 } else { // send an empty timed text 2099 notifyListener(MEDIA_TIMED_TEXT, 0, 0); 2100 } 2101 } 2102 //////////////////////////////////////////////////////////////////////////////// 2103 2104 sp<AMessage> NuPlayer::Source::getFormat(bool audio) { 2105 sp<MetaData> meta = getFormatMeta(audio); 2106 2107 if (meta == NULL) { 2108 return NULL; 2109 } 2110 2111 sp<AMessage> msg = new AMessage; 2112 2113 if(convertMetaDataToMessage(meta, &msg) == OK) { 2114 return msg; 2115 } 2116 return NULL; 2117 } 2118 2119 void NuPlayer::Source::notifyFlagsChanged(uint32_t flags) { 2120 sp<AMessage> notify = dupNotify(); 2121 notify->setInt32("what", kWhatFlagsChanged); 2122 notify->setInt32("flags", flags); 2123 notify->post(); 2124 } 2125 2126 void NuPlayer::Source::notifyVideoSizeChanged(const sp<AMessage> &format) { 2127 sp<AMessage> notify = dupNotify(); 2128 notify->setInt32("what", kWhatVideoSizeChanged); 2129 notify->setMessage("format", format); 2130 notify->post(); 2131 } 2132 2133 void NuPlayer::Source::notifyPrepared(status_t err) { 2134 sp<AMessage> notify = dupNotify(); 2135 notify->setInt32("what", kWhatPrepared); 2136 notify->setInt32("err", err); 2137 notify->post(); 2138 } 2139 2140 void NuPlayer::Source::onMessageReceived(const sp<AMessage> & /* msg */) { 2141 TRESPASS(); 2142 } 2143 2144 } // namespace android 2145