NuPlayer.cpp revision 09359d4e7b9186eec9ce744257a8d1dcb6cbbf15
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "NuPlayer" 19#include <utils/Log.h> 20 21#include "NuPlayer.h" 22 23#include "HTTPLiveSource.h" 24#include "NuPlayerDecoder.h" 25#include "NuPlayerDriver.h" 26#include "NuPlayerRenderer.h" 27#include "NuPlayerSource.h" 28#include "RTSPSource.h" 29#include "StreamingSource.h" 30#include "GenericSource.h" 31#include "mp4/MP4Source.h" 32 33#include "ATSParser.h" 34 35#include <cutils/properties.h> // for property_get 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/ACodec.h> 41#include <media/stagefright/MediaDefs.h> 42#include <media/stagefright/MediaErrors.h> 43#include <media/stagefright/MetaData.h> 44#include <gui/ISurfaceTexture.h> 45 46#include "avc_utils.h" 47 48#include "ESDS.h" 49#include <media/stagefright/Utils.h> 50 51namespace android { 52 53//////////////////////////////////////////////////////////////////////////////// 54 55NuPlayer::NuPlayer() 56 : mUIDValid(false), 57 mVideoIsAVC(false), 58 mAudioEOS(false), 59 mVideoEOS(false), 60 mScanSourcesPending(false), 61 mScanSourcesGeneration(0), 62 mTimeDiscontinuityPending(false), 63 mFlushingAudio(NONE), 64 mFlushingVideo(NONE), 65 mResetInProgress(false), 66 mResetPostponed(false), 67 mSkipRenderingAudioUntilMediaTimeUs(-1ll), 68 mSkipRenderingVideoUntilMediaTimeUs(-1ll), 69 mVideoLateByUs(0ll), 70 mNumFramesTotal(0ll), 71 mNumFramesDropped(0ll) { 72} 73 74NuPlayer::~NuPlayer() { 75} 76 77void NuPlayer::setUID(uid_t uid) { 78 mUIDValid = true; 79 mUID = uid; 80} 81 82void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) { 83 mDriver = driver; 84} 85 86void NuPlayer::setDataSource(const sp<IStreamSource> &source) { 87 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); 88 89 char prop[PROPERTY_VALUE_MAX]; 90 if (property_get("media.stagefright.use-mp4source", prop, NULL) 91 && (!strcmp(prop, "1") || !strcasecmp(prop, "true"))) { 92 msg->setObject("source", new MP4Source(source)); 93 } else { 94 msg->setObject("source", new StreamingSource(source)); 95 } 96 97 msg->post(); 98} 99 100static bool IsHTTPLiveURL(const char *url) { 101 if (!strncasecmp("http://", url, 7) 102 || !strncasecmp("https://", url, 8)) { 103 size_t len = strlen(url); 104 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) { 105 return true; 106 } 107 108 if (strstr(url,"m3u8")) { 109 return true; 110 } 111 } 112 113 return false; 114} 115 116void NuPlayer::setDataSource( 117 const char *url, const KeyedVector<String8, String8> *headers) { 118 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); 119 120 sp<Source> source; 121 if (IsHTTPLiveURL(url)) { 122 source = new HTTPLiveSource(url, headers, mUIDValid, mUID); 123 } else if (!strncasecmp(url, "rtsp://", 7)) { 124 source = new RTSPSource(url, headers, mUIDValid, mUID); 125 } else { 126 source = new GenericSource(url, headers, mUIDValid, mUID); 127 } 128 129 msg->setObject("source", source); 130 msg->post(); 131} 132 133void NuPlayer::setDataSource(int fd, int64_t offset, int64_t length) { 134 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); 135 136 sp<Source> source = new GenericSource(fd, offset, length); 137 msg->setObject("source", source); 138 msg->post(); 139} 140 141void NuPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) { 142 sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id()); 143 sp<SurfaceTextureClient> surfaceTextureClient(surfaceTexture != NULL ? 144 new SurfaceTextureClient(surfaceTexture) : NULL); 145 msg->setObject("native-window", new NativeWindowWrapper(surfaceTextureClient)); 146 msg->post(); 147} 148 149void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) { 150 sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id()); 151 msg->setObject("sink", sink); 152 msg->post(); 153} 154 155void NuPlayer::start() { 156 (new AMessage(kWhatStart, id()))->post(); 157} 158 159void NuPlayer::pause() { 160 (new AMessage(kWhatPause, id()))->post(); 161} 162 163void NuPlayer::resume() { 164 (new AMessage(kWhatResume, id()))->post(); 165} 166 167void NuPlayer::resetAsync() { 168 (new AMessage(kWhatReset, id()))->post(); 169} 170 171void NuPlayer::seekToAsync(int64_t seekTimeUs) { 172 sp<AMessage> msg = new AMessage(kWhatSeek, id()); 173 msg->setInt64("seekTimeUs", seekTimeUs); 174 msg->post(); 175} 176 177// static 178bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) { 179 switch (state) { 180 case FLUSHING_DECODER: 181 if (needShutdown != NULL) { 182 *needShutdown = false; 183 } 184 return true; 185 186 case FLUSHING_DECODER_SHUTDOWN: 187 if (needShutdown != NULL) { 188 *needShutdown = true; 189 } 190 return true; 191 192 default: 193 return false; 194 } 195} 196 197void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { 198 switch (msg->what()) { 199 case kWhatSetDataSource: 200 { 201 ALOGV("kWhatSetDataSource"); 202 203 CHECK(mSource == NULL); 204 205 sp<RefBase> obj; 206 CHECK(msg->findObject("source", &obj)); 207 208 mSource = static_cast<Source *>(obj.get()); 209 break; 210 } 211 212 case kWhatSetVideoNativeWindow: 213 { 214 ALOGV("kWhatSetVideoNativeWindow"); 215 216 sp<RefBase> obj; 217 CHECK(msg->findObject("native-window", &obj)); 218 219 mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get()); 220 break; 221 } 222 223 case kWhatSetAudioSink: 224 { 225 ALOGV("kWhatSetAudioSink"); 226 227 sp<RefBase> obj; 228 CHECK(msg->findObject("sink", &obj)); 229 230 mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get()); 231 break; 232 } 233 234 case kWhatStart: 235 { 236 ALOGV("kWhatStart"); 237 238 mVideoIsAVC = false; 239 mAudioEOS = false; 240 mVideoEOS = false; 241 mSkipRenderingAudioUntilMediaTimeUs = -1; 242 mSkipRenderingVideoUntilMediaTimeUs = -1; 243 mVideoLateByUs = 0; 244 mNumFramesTotal = 0; 245 mNumFramesDropped = 0; 246 247 mSource->start(); 248 249 mRenderer = new Renderer( 250 mAudioSink, 251 new AMessage(kWhatRendererNotify, id())); 252 253 looper()->registerHandler(mRenderer); 254 255 postScanSources(); 256 break; 257 } 258 259 case kWhatScanSources: 260 { 261 int32_t generation; 262 CHECK(msg->findInt32("generation", &generation)); 263 if (generation != mScanSourcesGeneration) { 264 // Drop obsolete msg. 265 break; 266 } 267 268 mScanSourcesPending = false; 269 270 ALOGV("scanning sources haveAudio=%d, haveVideo=%d", 271 mAudioDecoder != NULL, mVideoDecoder != NULL); 272 273 if (mNativeWindow != NULL) { 274 instantiateDecoder(false, &mVideoDecoder); 275 } 276 277 if (mAudioSink != NULL) { 278 instantiateDecoder(true, &mAudioDecoder); 279 } 280 281 status_t err; 282 if ((err = mSource->feedMoreTSData()) != OK) { 283 if (mAudioDecoder == NULL && mVideoDecoder == NULL) { 284 // We're not currently decoding anything (no audio or 285 // video tracks found) and we just ran out of input data. 286 287 if (err == ERROR_END_OF_STREAM) { 288 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); 289 } else { 290 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 291 } 292 } 293 break; 294 } 295 296 if ((mAudioDecoder == NULL && mAudioSink != NULL) 297 || (mVideoDecoder == NULL && mNativeWindow != NULL)) { 298 msg->post(100000ll); 299 mScanSourcesPending = true; 300 } 301 break; 302 } 303 304 case kWhatVideoNotify: 305 case kWhatAudioNotify: 306 { 307 bool audio = msg->what() == kWhatAudioNotify; 308 309 sp<AMessage> codecRequest; 310 CHECK(msg->findMessage("codec-request", &codecRequest)); 311 312 int32_t what; 313 CHECK(codecRequest->findInt32("what", &what)); 314 315 if (what == ACodec::kWhatFillThisBuffer) { 316 status_t err = feedDecoderInputData( 317 audio, codecRequest); 318 319 if (err == -EWOULDBLOCK) { 320 if (mSource->feedMoreTSData() == OK) { 321 msg->post(10000ll); 322 } 323 } 324 } else if (what == ACodec::kWhatEOS) { 325 int32_t err; 326 CHECK(codecRequest->findInt32("err", &err)); 327 328 if (err == ERROR_END_OF_STREAM) { 329 ALOGV("got %s decoder EOS", audio ? "audio" : "video"); 330 } else { 331 ALOGV("got %s decoder EOS w/ error %d", 332 audio ? "audio" : "video", 333 err); 334 } 335 336 mRenderer->queueEOS(audio, err); 337 } else if (what == ACodec::kWhatFlushCompleted) { 338 bool needShutdown; 339 340 if (audio) { 341 CHECK(IsFlushingState(mFlushingAudio, &needShutdown)); 342 mFlushingAudio = FLUSHED; 343 } else { 344 CHECK(IsFlushingState(mFlushingVideo, &needShutdown)); 345 mFlushingVideo = FLUSHED; 346 347 mVideoLateByUs = 0; 348 } 349 350 ALOGV("decoder %s flush completed", audio ? "audio" : "video"); 351 352 if (needShutdown) { 353 ALOGV("initiating %s decoder shutdown", 354 audio ? "audio" : "video"); 355 356 (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown(); 357 358 if (audio) { 359 mFlushingAudio = SHUTTING_DOWN_DECODER; 360 } else { 361 mFlushingVideo = SHUTTING_DOWN_DECODER; 362 } 363 } 364 365 finishFlushIfPossible(); 366 } else if (what == ACodec::kWhatOutputFormatChanged) { 367 if (audio) { 368 int32_t numChannels; 369 CHECK(codecRequest->findInt32("channel-count", &numChannels)); 370 371 int32_t sampleRate; 372 CHECK(codecRequest->findInt32("sample-rate", &sampleRate)); 373 374 ALOGV("Audio output format changed to %d Hz, %d channels", 375 sampleRate, numChannels); 376 377 mAudioSink->close(); 378 379 audio_output_flags_t flags; 380 int64_t durationUs; 381 // FIXME: we should handle the case where the video decoder is created after 382 // we receive the format change indication. Current code will just make that 383 // we select deep buffer with video which should not be a problem as it should 384 // not prevent from keeping A/V sync. 385 if (mVideoDecoder == NULL && 386 mSource->getDuration(&durationUs) == OK && 387 durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) { 388 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; 389 } else { 390 flags = AUDIO_OUTPUT_FLAG_NONE; 391 } 392 393 int32_t channelMask; 394 if (!codecRequest->findInt32("channel-mask", &channelMask)) { 395 channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER; 396 } 397 398 CHECK_EQ(mAudioSink->open( 399 sampleRate, 400 numChannels, 401 (audio_channel_mask_t)channelMask, 402 AUDIO_FORMAT_PCM_16_BIT, 403 8 /* bufferCount */, 404 NULL, 405 NULL, 406 flags), 407 (status_t)OK); 408 mAudioSink->start(); 409 410 mRenderer->signalAudioSinkChanged(); 411 } else { 412 // video 413 414 int32_t width, height; 415 CHECK(codecRequest->findInt32("width", &width)); 416 CHECK(codecRequest->findInt32("height", &height)); 417 418 int32_t cropLeft, cropTop, cropRight, cropBottom; 419 CHECK(codecRequest->findRect( 420 "crop", 421 &cropLeft, &cropTop, &cropRight, &cropBottom)); 422 423 ALOGV("Video output format changed to %d x %d " 424 "(crop: %d x %d @ (%d, %d))", 425 width, height, 426 (cropRight - cropLeft + 1), 427 (cropBottom - cropTop + 1), 428 cropLeft, cropTop); 429 430 notifyListener( 431 MEDIA_SET_VIDEO_SIZE, 432 cropRight - cropLeft + 1, 433 cropBottom - cropTop + 1); 434 } 435 } else if (what == ACodec::kWhatShutdownCompleted) { 436 ALOGV("%s shutdown completed", audio ? "audio" : "video"); 437 if (audio) { 438 mAudioDecoder.clear(); 439 440 CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER); 441 mFlushingAudio = SHUT_DOWN; 442 } else { 443 mVideoDecoder.clear(); 444 445 CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER); 446 mFlushingVideo = SHUT_DOWN; 447 } 448 449 finishFlushIfPossible(); 450 } else if (what == ACodec::kWhatError) { 451 ALOGE("Received error from %s decoder, aborting playback.", 452 audio ? "audio" : "video"); 453 454 mRenderer->queueEOS(audio, UNKNOWN_ERROR); 455 } else if (what == ACodec::kWhatDrainThisBuffer) { 456 renderBuffer(audio, codecRequest); 457 } else { 458 ALOGV("Unhandled codec notification %d.", what); 459 } 460 461 break; 462 } 463 464 case kWhatRendererNotify: 465 { 466 int32_t what; 467 CHECK(msg->findInt32("what", &what)); 468 469 if (what == Renderer::kWhatEOS) { 470 int32_t audio; 471 CHECK(msg->findInt32("audio", &audio)); 472 473 int32_t finalResult; 474 CHECK(msg->findInt32("finalResult", &finalResult)); 475 476 if (audio) { 477 mAudioEOS = true; 478 } else { 479 mVideoEOS = true; 480 } 481 482 if (finalResult == ERROR_END_OF_STREAM) { 483 ALOGV("reached %s EOS", audio ? "audio" : "video"); 484 } else { 485 ALOGE("%s track encountered an error (%d)", 486 audio ? "audio" : "video", finalResult); 487 488 notifyListener( 489 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult); 490 } 491 492 if ((mAudioEOS || mAudioDecoder == NULL) 493 && (mVideoEOS || mVideoDecoder == NULL)) { 494 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); 495 } 496 } else if (what == Renderer::kWhatPosition) { 497 int64_t positionUs; 498 CHECK(msg->findInt64("positionUs", &positionUs)); 499 500 CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs)); 501 502 if (mDriver != NULL) { 503 sp<NuPlayerDriver> driver = mDriver.promote(); 504 if (driver != NULL) { 505 driver->notifyPosition(positionUs); 506 507 driver->notifyFrameStats( 508 mNumFramesTotal, mNumFramesDropped); 509 } 510 } 511 } else if (what == Renderer::kWhatFlushComplete) { 512 int32_t audio; 513 CHECK(msg->findInt32("audio", &audio)); 514 515 ALOGV("renderer %s flush completed.", audio ? "audio" : "video"); 516 } else if (what == Renderer::kWhatVideoRenderingStart) { 517 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0); 518 } 519 break; 520 } 521 522 case kWhatMoreDataQueued: 523 { 524 break; 525 } 526 527 case kWhatReset: 528 { 529 ALOGV("kWhatReset"); 530 531 if (mRenderer != NULL) { 532 // There's an edge case where the renderer owns all output 533 // buffers and is paused, therefore the decoder will not read 534 // more input data and will never encounter the matching 535 // discontinuity. To avoid this, we resume the renderer. 536 537 if (mFlushingAudio == AWAITING_DISCONTINUITY 538 || mFlushingVideo == AWAITING_DISCONTINUITY) { 539 mRenderer->resume(); 540 } 541 } 542 543 if (mFlushingAudio != NONE || mFlushingVideo != NONE) { 544 // We're currently flushing, postpone the reset until that's 545 // completed. 546 547 ALOGV("postponing reset mFlushingAudio=%d, mFlushingVideo=%d", 548 mFlushingAudio, mFlushingVideo); 549 550 mResetPostponed = true; 551 break; 552 } 553 554 if (mAudioDecoder == NULL && mVideoDecoder == NULL) { 555 finishReset(); 556 break; 557 } 558 559 mTimeDiscontinuityPending = true; 560 561 if (mAudioDecoder != NULL) { 562 flushDecoder(true /* audio */, true /* needShutdown */); 563 } 564 565 if (mVideoDecoder != NULL) { 566 flushDecoder(false /* audio */, true /* needShutdown */); 567 } 568 569 mResetInProgress = true; 570 break; 571 } 572 573 case kWhatSeek: 574 { 575 int64_t seekTimeUs; 576 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs)); 577 578 ALOGV("kWhatSeek seekTimeUs=%lld us (%.2f secs)", 579 seekTimeUs, seekTimeUs / 1E6); 580 581 mSource->seekTo(seekTimeUs); 582 583 if (mDriver != NULL) { 584 sp<NuPlayerDriver> driver = mDriver.promote(); 585 if (driver != NULL) { 586 driver->notifySeekComplete(); 587 } 588 } 589 590 break; 591 } 592 593 case kWhatPause: 594 { 595 CHECK(mRenderer != NULL); 596 mRenderer->pause(); 597 break; 598 } 599 600 case kWhatResume: 601 { 602 CHECK(mRenderer != NULL); 603 mRenderer->resume(); 604 break; 605 } 606 607 default: 608 TRESPASS(); 609 break; 610 } 611} 612 613void NuPlayer::finishFlushIfPossible() { 614 if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) { 615 return; 616 } 617 618 if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) { 619 return; 620 } 621 622 ALOGV("both audio and video are flushed now."); 623 624 if (mTimeDiscontinuityPending) { 625 mRenderer->signalTimeDiscontinuity(); 626 mTimeDiscontinuityPending = false; 627 } 628 629 if (mAudioDecoder != NULL) { 630 mAudioDecoder->signalResume(); 631 } 632 633 if (mVideoDecoder != NULL) { 634 mVideoDecoder->signalResume(); 635 } 636 637 mFlushingAudio = NONE; 638 mFlushingVideo = NONE; 639 640 if (mResetInProgress) { 641 ALOGV("reset completed"); 642 643 mResetInProgress = false; 644 finishReset(); 645 } else if (mResetPostponed) { 646 (new AMessage(kWhatReset, id()))->post(); 647 mResetPostponed = false; 648 } else if (mAudioDecoder == NULL || mVideoDecoder == NULL) { 649 postScanSources(); 650 } 651} 652 653void NuPlayer::finishReset() { 654 CHECK(mAudioDecoder == NULL); 655 CHECK(mVideoDecoder == NULL); 656 657 ++mScanSourcesGeneration; 658 mScanSourcesPending = false; 659 660 mRenderer.clear(); 661 662 if (mSource != NULL) { 663 mSource->stop(); 664 mSource.clear(); 665 } 666 667 if (mDriver != NULL) { 668 sp<NuPlayerDriver> driver = mDriver.promote(); 669 if (driver != NULL) { 670 driver->notifyResetComplete(); 671 } 672 } 673} 674 675void NuPlayer::postScanSources() { 676 if (mScanSourcesPending) { 677 return; 678 } 679 680 sp<AMessage> msg = new AMessage(kWhatScanSources, id()); 681 msg->setInt32("generation", mScanSourcesGeneration); 682 msg->post(); 683 684 mScanSourcesPending = true; 685} 686 687status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) { 688 if (*decoder != NULL) { 689 return OK; 690 } 691 692 sp<AMessage> format = mSource->getFormat(audio); 693 694 if (format == NULL) { 695 return -EWOULDBLOCK; 696 } 697 698 if (!audio) { 699 AString mime; 700 CHECK(format->findString("mime", &mime)); 701 mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str()); 702 } 703 704 sp<AMessage> notify = 705 new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify, 706 id()); 707 708 *decoder = audio ? new Decoder(notify) : 709 new Decoder(notify, mNativeWindow); 710 looper()->registerHandler(*decoder); 711 712 (*decoder)->configure(format); 713 714 int64_t durationUs; 715 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) { 716 sp<NuPlayerDriver> driver = mDriver.promote(); 717 if (driver != NULL) { 718 driver->notifyDuration(durationUs); 719 } 720 } 721 722 return OK; 723} 724 725status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { 726 sp<AMessage> reply; 727 CHECK(msg->findMessage("reply", &reply)); 728 729 if ((audio && IsFlushingState(mFlushingAudio)) 730 || (!audio && IsFlushingState(mFlushingVideo))) { 731 reply->setInt32("err", INFO_DISCONTINUITY); 732 reply->post(); 733 return OK; 734 } 735 736 sp<ABuffer> accessUnit; 737 738 bool dropAccessUnit; 739 do { 740 status_t err = mSource->dequeueAccessUnit(audio, &accessUnit); 741 742 if (err == -EWOULDBLOCK) { 743 return err; 744 } else if (err != OK) { 745 if (err == INFO_DISCONTINUITY) { 746 int32_t type; 747 CHECK(accessUnit->meta()->findInt32("discontinuity", &type)); 748 749 bool formatChange = 750 (audio && 751 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT)) 752 || (!audio && 753 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT)); 754 755 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0; 756 757 ALOGI("%s discontinuity (formatChange=%d, time=%d)", 758 audio ? "audio" : "video", formatChange, timeChange); 759 760 if (audio) { 761 mSkipRenderingAudioUntilMediaTimeUs = -1; 762 } else { 763 mSkipRenderingVideoUntilMediaTimeUs = -1; 764 } 765 766 if (timeChange) { 767 sp<AMessage> extra; 768 if (accessUnit->meta()->findMessage("extra", &extra) 769 && extra != NULL) { 770 int64_t resumeAtMediaTimeUs; 771 if (extra->findInt64( 772 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) { 773 ALOGI("suppressing rendering of %s until %lld us", 774 audio ? "audio" : "video", resumeAtMediaTimeUs); 775 776 if (audio) { 777 mSkipRenderingAudioUntilMediaTimeUs = 778 resumeAtMediaTimeUs; 779 } else { 780 mSkipRenderingVideoUntilMediaTimeUs = 781 resumeAtMediaTimeUs; 782 } 783 } 784 } 785 } 786 787 mTimeDiscontinuityPending = 788 mTimeDiscontinuityPending || timeChange; 789 790 if (formatChange || timeChange) { 791 flushDecoder(audio, formatChange); 792 } else { 793 // This stream is unaffected by the discontinuity 794 795 if (audio) { 796 mFlushingAudio = FLUSHED; 797 } else { 798 mFlushingVideo = FLUSHED; 799 } 800 801 finishFlushIfPossible(); 802 803 return -EWOULDBLOCK; 804 } 805 } 806 807 reply->setInt32("err", err); 808 reply->post(); 809 return OK; 810 } 811 812 if (!audio) { 813 ++mNumFramesTotal; 814 } 815 816 dropAccessUnit = false; 817 if (!audio 818 && mVideoLateByUs > 100000ll 819 && mVideoIsAVC 820 && !IsAVCReferenceFrame(accessUnit)) { 821 dropAccessUnit = true; 822 ++mNumFramesDropped; 823 } 824 } while (dropAccessUnit); 825 826 // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video"); 827 828#if 0 829 int64_t mediaTimeUs; 830 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs)); 831 ALOGV("feeding %s input buffer at media time %.2f secs", 832 audio ? "audio" : "video", 833 mediaTimeUs / 1E6); 834#endif 835 836 reply->setBuffer("buffer", accessUnit); 837 reply->post(); 838 839 return OK; 840} 841 842void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) { 843 // ALOGV("renderBuffer %s", audio ? "audio" : "video"); 844 845 sp<AMessage> reply; 846 CHECK(msg->findMessage("reply", &reply)); 847 848 if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) { 849 // We're currently attempting to flush the decoder, in order 850 // to complete this, the decoder wants all its buffers back, 851 // so we don't want any output buffers it sent us (from before 852 // we initiated the flush) to be stuck in the renderer's queue. 853 854 ALOGV("we're still flushing the %s decoder, sending its output buffer" 855 " right back.", audio ? "audio" : "video"); 856 857 reply->post(); 858 return; 859 } 860 861 sp<ABuffer> buffer; 862 CHECK(msg->findBuffer("buffer", &buffer)); 863 864 int64_t &skipUntilMediaTimeUs = 865 audio 866 ? mSkipRenderingAudioUntilMediaTimeUs 867 : mSkipRenderingVideoUntilMediaTimeUs; 868 869 if (skipUntilMediaTimeUs >= 0) { 870 int64_t mediaTimeUs; 871 CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs)); 872 873 if (mediaTimeUs < skipUntilMediaTimeUs) { 874 ALOGV("dropping %s buffer at time %lld as requested.", 875 audio ? "audio" : "video", 876 mediaTimeUs); 877 878 reply->post(); 879 return; 880 } 881 882 skipUntilMediaTimeUs = -1; 883 } 884 885 mRenderer->queueBuffer(audio, buffer, reply); 886} 887 888void NuPlayer::notifyListener(int msg, int ext1, int ext2) { 889 if (mDriver == NULL) { 890 return; 891 } 892 893 sp<NuPlayerDriver> driver = mDriver.promote(); 894 895 if (driver == NULL) { 896 return; 897 } 898 899 driver->notifyListener(msg, ext1, ext2); 900} 901 902void NuPlayer::flushDecoder(bool audio, bool needShutdown) { 903 if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) { 904 ALOGI("flushDecoder %s without decoder present", 905 audio ? "audio" : "video"); 906 } 907 908 // Make sure we don't continue to scan sources until we finish flushing. 909 ++mScanSourcesGeneration; 910 mScanSourcesPending = false; 911 912 (audio ? mAudioDecoder : mVideoDecoder)->signalFlush(); 913 mRenderer->flush(audio); 914 915 FlushStatus newStatus = 916 needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER; 917 918 if (audio) { 919 CHECK(mFlushingAudio == NONE 920 || mFlushingAudio == AWAITING_DISCONTINUITY); 921 922 mFlushingAudio = newStatus; 923 924 if (mFlushingVideo == NONE) { 925 mFlushingVideo = (mVideoDecoder != NULL) 926 ? AWAITING_DISCONTINUITY 927 : FLUSHED; 928 } 929 } else { 930 CHECK(mFlushingVideo == NONE 931 || mFlushingVideo == AWAITING_DISCONTINUITY); 932 933 mFlushingVideo = newStatus; 934 935 if (mFlushingAudio == NONE) { 936 mFlushingAudio = (mAudioDecoder != NULL) 937 ? AWAITING_DISCONTINUITY 938 : FLUSHED; 939 } 940 } 941} 942 943sp<AMessage> NuPlayer::Source::getFormat(bool audio) { 944 sp<MetaData> meta = getFormatMeta(audio); 945 946 if (meta == NULL) { 947 return NULL; 948 } 949 950 sp<AMessage> msg = new AMessage; 951 952 if(convertMetaDataToMessage(meta, &msg) == OK) { 953 return msg; 954 } 955 return NULL; 956} 957 958} // namespace android 959