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