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