NuPlayer.cpp revision 1183a4ab06b9fe01fe39a4b8728bfc71789361fc
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 31#include "ATSParser.h" 32 33#include <media/stagefright/foundation/hexdump.h> 34#include <media/stagefright/foundation/ABuffer.h> 35#include <media/stagefright/foundation/ADebug.h> 36#include <media/stagefright/foundation/AMessage.h> 37#include <media/stagefright/ACodec.h> 38#include <media/stagefright/MediaDefs.h> 39#include <media/stagefright/MediaErrors.h> 40#include <media/stagefright/MetaData.h> 41#include <surfaceflinger/Surface.h> 42#include <gui/ISurfaceTexture.h> 43 44#include "avc_utils.h" 45 46namespace android { 47 48//////////////////////////////////////////////////////////////////////////////// 49 50NuPlayer::NuPlayer() 51 : mUIDValid(false), 52 mVideoIsAVC(false), 53 mAudioEOS(false), 54 mVideoEOS(false), 55 mScanSourcesPending(false), 56 mScanSourcesGeneration(0), 57 mFlushingAudio(NONE), 58 mFlushingVideo(NONE), 59 mResetInProgress(false), 60 mResetPostponed(false), 61 mSkipRenderingAudioUntilMediaTimeUs(-1ll), 62 mSkipRenderingVideoUntilMediaTimeUs(-1ll), 63 mVideoLateByUs(0ll), 64 mNumFramesTotal(0ll), 65 mNumFramesDropped(0ll) { 66} 67 68NuPlayer::~NuPlayer() { 69} 70 71void NuPlayer::setUID(uid_t uid) { 72 mUIDValid = true; 73 mUID = uid; 74} 75 76void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) { 77 mDriver = driver; 78} 79 80void NuPlayer::setDataSource(const sp<IStreamSource> &source) { 81 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); 82 83 msg->setObject("source", new StreamingSource(source)); 84 msg->post(); 85} 86 87void NuPlayer::setDataSource( 88 const char *url, const KeyedVector<String8, String8> *headers) { 89 sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); 90 91 if (!strncasecmp(url, "rtsp://", 7)) { 92 msg->setObject( 93 "source", new RTSPSource(url, headers, mUIDValid, mUID)); 94 } else { 95 msg->setObject( 96 "source", new HTTPLiveSource(url, headers, mUIDValid, mUID)); 97 } 98 99 msg->post(); 100} 101 102void NuPlayer::setVideoSurface(const sp<Surface> &surface) { 103 sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id()); 104 msg->setObject("native-window", new NativeWindowWrapper(surface)); 105 msg->post(); 106} 107 108void NuPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) { 109 sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id()); 110 sp<SurfaceTextureClient> surfaceTextureClient(surfaceTexture != NULL ? 111 new SurfaceTextureClient(surfaceTexture) : NULL); 112 msg->setObject("native-window", new NativeWindowWrapper(surfaceTextureClient)); 113 msg->post(); 114} 115 116void NuPlayer::setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink) { 117 sp<AMessage> msg = new AMessage(kWhatSetAudioSink, id()); 118 msg->setObject("sink", sink); 119 msg->post(); 120} 121 122void NuPlayer::start() { 123 (new AMessage(kWhatStart, id()))->post(); 124} 125 126void NuPlayer::pause() { 127 (new AMessage(kWhatPause, id()))->post(); 128} 129 130void NuPlayer::resume() { 131 (new AMessage(kWhatResume, id()))->post(); 132} 133 134void NuPlayer::resetAsync() { 135 (new AMessage(kWhatReset, id()))->post(); 136} 137 138void NuPlayer::seekToAsync(int64_t seekTimeUs) { 139 sp<AMessage> msg = new AMessage(kWhatSeek, id()); 140 msg->setInt64("seekTimeUs", seekTimeUs); 141 msg->post(); 142} 143 144// static 145bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) { 146 switch (state) { 147 case FLUSHING_DECODER: 148 if (needShutdown != NULL) { 149 *needShutdown = false; 150 } 151 return true; 152 153 case FLUSHING_DECODER_SHUTDOWN: 154 if (needShutdown != NULL) { 155 *needShutdown = true; 156 } 157 return true; 158 159 default: 160 return false; 161 } 162} 163 164void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { 165 switch (msg->what()) { 166 case kWhatSetDataSource: 167 { 168 LOGV("kWhatSetDataSource"); 169 170 CHECK(mSource == NULL); 171 172 sp<RefBase> obj; 173 CHECK(msg->findObject("source", &obj)); 174 175 mSource = static_cast<Source *>(obj.get()); 176 break; 177 } 178 179 case kWhatSetVideoNativeWindow: 180 { 181 LOGV("kWhatSetVideoNativeWindow"); 182 183 sp<RefBase> obj; 184 CHECK(msg->findObject("native-window", &obj)); 185 186 mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get()); 187 break; 188 } 189 190 case kWhatSetAudioSink: 191 { 192 LOGV("kWhatSetAudioSink"); 193 194 sp<RefBase> obj; 195 CHECK(msg->findObject("sink", &obj)); 196 197 mAudioSink = static_cast<MediaPlayerBase::AudioSink *>(obj.get()); 198 break; 199 } 200 201 case kWhatStart: 202 { 203 LOGV("kWhatStart"); 204 205 mVideoIsAVC = false; 206 mAudioEOS = false; 207 mVideoEOS = false; 208 mSkipRenderingAudioUntilMediaTimeUs = -1; 209 mSkipRenderingVideoUntilMediaTimeUs = -1; 210 mVideoLateByUs = 0; 211 mNumFramesTotal = 0; 212 mNumFramesDropped = 0; 213 214 mSource->start(); 215 216 mRenderer = new Renderer( 217 mAudioSink, 218 new AMessage(kWhatRendererNotify, id())); 219 220 looper()->registerHandler(mRenderer); 221 222 postScanSources(); 223 break; 224 } 225 226 case kWhatScanSources: 227 { 228 int32_t generation; 229 CHECK(msg->findInt32("generation", &generation)); 230 if (generation != mScanSourcesGeneration) { 231 // Drop obsolete msg. 232 break; 233 } 234 235 mScanSourcesPending = false; 236 237 LOGV("scanning sources haveAudio=%d, haveVideo=%d", 238 mAudioDecoder != NULL, mVideoDecoder != NULL); 239 240 instantiateDecoder(false, &mVideoDecoder); 241 242 if (mAudioSink != NULL) { 243 instantiateDecoder(true, &mAudioDecoder); 244 } 245 246 status_t err; 247 if ((err = mSource->feedMoreTSData()) != OK) { 248 if (mAudioDecoder == NULL && mVideoDecoder == NULL) { 249 // We're not currently decoding anything (no audio or 250 // video tracks found) and we just ran out of input data. 251 252 if (err == ERROR_END_OF_STREAM) { 253 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); 254 } else { 255 notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err); 256 } 257 } 258 break; 259 } 260 261 if (mAudioDecoder == NULL || mVideoDecoder == NULL) { 262 msg->post(100000ll); 263 mScanSourcesPending = true; 264 } 265 break; 266 } 267 268 case kWhatVideoNotify: 269 case kWhatAudioNotify: 270 { 271 bool audio = msg->what() == kWhatAudioNotify; 272 273 sp<AMessage> codecRequest; 274 CHECK(msg->findMessage("codec-request", &codecRequest)); 275 276 int32_t what; 277 CHECK(codecRequest->findInt32("what", &what)); 278 279 if (what == ACodec::kWhatFillThisBuffer) { 280 status_t err = feedDecoderInputData( 281 audio, codecRequest); 282 283 if (err == -EWOULDBLOCK) { 284 if (mSource->feedMoreTSData() == OK) { 285 msg->post(10000ll); 286 } 287 } 288 } else if (what == ACodec::kWhatEOS) { 289 int32_t err; 290 CHECK(codecRequest->findInt32("err", &err)); 291 292 if (err == ERROR_END_OF_STREAM) { 293 LOGV("got %s decoder EOS", audio ? "audio" : "video"); 294 } else { 295 LOGV("got %s decoder EOS w/ error %d", 296 audio ? "audio" : "video", 297 err); 298 } 299 300 mRenderer->queueEOS(audio, err); 301 } else if (what == ACodec::kWhatFlushCompleted) { 302 bool needShutdown; 303 304 if (audio) { 305 CHECK(IsFlushingState(mFlushingAudio, &needShutdown)); 306 mFlushingAudio = FLUSHED; 307 } else { 308 CHECK(IsFlushingState(mFlushingVideo, &needShutdown)); 309 mFlushingVideo = FLUSHED; 310 311 mVideoLateByUs = 0; 312 } 313 314 LOGV("decoder %s flush completed", audio ? "audio" : "video"); 315 316 if (needShutdown) { 317 LOGV("initiating %s decoder shutdown", 318 audio ? "audio" : "video"); 319 320 (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown(); 321 322 if (audio) { 323 mFlushingAudio = SHUTTING_DOWN_DECODER; 324 } else { 325 mFlushingVideo = SHUTTING_DOWN_DECODER; 326 } 327 } 328 329 finishFlushIfPossible(); 330 } else if (what == ACodec::kWhatOutputFormatChanged) { 331 if (audio) { 332 int32_t numChannels; 333 CHECK(codecRequest->findInt32("channel-count", &numChannels)); 334 335 int32_t sampleRate; 336 CHECK(codecRequest->findInt32("sample-rate", &sampleRate)); 337 338 LOGV("Audio output format changed to %d Hz, %d channels", 339 sampleRate, numChannels); 340 341 mAudioSink->close(); 342 CHECK_EQ(mAudioSink->open( 343 sampleRate, 344 numChannels, 345 AUDIO_FORMAT_PCM_16_BIT, 346 8 /* bufferCount */), 347 (status_t)OK); 348 mAudioSink->start(); 349 350 mRenderer->signalAudioSinkChanged(); 351 } else { 352 // video 353 354 int32_t width, height; 355 CHECK(codecRequest->findInt32("width", &width)); 356 CHECK(codecRequest->findInt32("height", &height)); 357 358 int32_t cropLeft, cropTop, cropRight, cropBottom; 359 CHECK(codecRequest->findRect( 360 "crop", 361 &cropLeft, &cropTop, &cropRight, &cropBottom)); 362 363 LOGV("Video output format changed to %d x %d " 364 "(crop: %d x %d @ (%d, %d))", 365 width, height, 366 (cropRight - cropLeft + 1), 367 (cropBottom - cropTop + 1), 368 cropLeft, cropTop); 369 370 notifyListener( 371 MEDIA_SET_VIDEO_SIZE, 372 cropRight - cropLeft + 1, 373 cropBottom - cropTop + 1); 374 } 375 } else if (what == ACodec::kWhatShutdownCompleted) { 376 LOGV("%s shutdown completed", audio ? "audio" : "video"); 377 if (audio) { 378 mAudioDecoder.clear(); 379 380 CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER); 381 mFlushingAudio = SHUT_DOWN; 382 } else { 383 mVideoDecoder.clear(); 384 385 CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER); 386 mFlushingVideo = SHUT_DOWN; 387 } 388 389 finishFlushIfPossible(); 390 } else if (what == ACodec::kWhatError) { 391 LOGE("Received error from %s decoder, aborting playback.", 392 audio ? "audio" : "video"); 393 394 mRenderer->queueEOS(audio, UNKNOWN_ERROR); 395 } else { 396 CHECK_EQ((int)what, (int)ACodec::kWhatDrainThisBuffer); 397 398 renderBuffer(audio, codecRequest); 399 } 400 401 break; 402 } 403 404 case kWhatRendererNotify: 405 { 406 int32_t what; 407 CHECK(msg->findInt32("what", &what)); 408 409 if (what == Renderer::kWhatEOS) { 410 int32_t audio; 411 CHECK(msg->findInt32("audio", &audio)); 412 413 int32_t finalResult; 414 CHECK(msg->findInt32("finalResult", &finalResult)); 415 416 if (audio) { 417 mAudioEOS = true; 418 } else { 419 mVideoEOS = true; 420 } 421 422 if (finalResult == ERROR_END_OF_STREAM) { 423 LOGV("reached %s EOS", audio ? "audio" : "video"); 424 } else { 425 LOGE("%s track encountered an error (%d)", 426 audio ? "audio" : "video", finalResult); 427 428 notifyListener( 429 MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, finalResult); 430 } 431 432 if ((mAudioEOS || mAudioDecoder == NULL) 433 && (mVideoEOS || mVideoDecoder == NULL)) { 434 notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); 435 } 436 } else if (what == Renderer::kWhatPosition) { 437 int64_t positionUs; 438 CHECK(msg->findInt64("positionUs", &positionUs)); 439 440 CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs)); 441 442 if (mDriver != NULL) { 443 sp<NuPlayerDriver> driver = mDriver.promote(); 444 if (driver != NULL) { 445 driver->notifyPosition(positionUs); 446 447 driver->notifyFrameStats( 448 mNumFramesTotal, mNumFramesDropped); 449 } 450 } 451 } else if (what == Renderer::kWhatFlushComplete) { 452 CHECK_EQ(what, (int32_t)Renderer::kWhatFlushComplete); 453 454 int32_t audio; 455 CHECK(msg->findInt32("audio", &audio)); 456 457 LOGV("renderer %s flush completed.", audio ? "audio" : "video"); 458 } 459 break; 460 } 461 462 case kWhatMoreDataQueued: 463 { 464 break; 465 } 466 467 case kWhatReset: 468 { 469 LOGV("kWhatReset"); 470 471 if (mFlushingAudio != NONE || mFlushingVideo != NONE) { 472 // We're currently flushing, postpone the reset until that's 473 // completed. 474 475 LOGV("postponing reset"); 476 477 mResetPostponed = true; 478 break; 479 } 480 481 if (mAudioDecoder == NULL && mVideoDecoder == NULL) { 482 finishReset(); 483 break; 484 } 485 486 if (mAudioDecoder != NULL) { 487 flushDecoder(true /* audio */, true /* needShutdown */); 488 } 489 490 if (mVideoDecoder != NULL) { 491 flushDecoder(false /* audio */, true /* needShutdown */); 492 } 493 494 mResetInProgress = true; 495 break; 496 } 497 498 case kWhatSeek: 499 { 500 int64_t seekTimeUs; 501 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs)); 502 503 LOGV("kWhatSeek seekTimeUs=%lld us (%.2f secs)", 504 seekTimeUs, seekTimeUs / 1E6); 505 506 mSource->seekTo(seekTimeUs); 507 508 if (mDriver != NULL) { 509 sp<NuPlayerDriver> driver = mDriver.promote(); 510 if (driver != NULL) { 511 driver->notifySeekComplete(); 512 } 513 } 514 515 break; 516 } 517 518 case kWhatPause: 519 { 520 CHECK(mRenderer != NULL); 521 mRenderer->pause(); 522 break; 523 } 524 525 case kWhatResume: 526 { 527 CHECK(mRenderer != NULL); 528 mRenderer->resume(); 529 break; 530 } 531 532 default: 533 TRESPASS(); 534 break; 535 } 536} 537 538void NuPlayer::finishFlushIfPossible() { 539 if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) { 540 return; 541 } 542 543 if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) { 544 return; 545 } 546 547 LOGV("both audio and video are flushed now."); 548 549 mRenderer->signalTimeDiscontinuity(); 550 551 if (mAudioDecoder != NULL) { 552 mAudioDecoder->signalResume(); 553 } 554 555 if (mVideoDecoder != NULL) { 556 mVideoDecoder->signalResume(); 557 } 558 559 mFlushingAudio = NONE; 560 mFlushingVideo = NONE; 561 562 if (mResetInProgress) { 563 LOGV("reset completed"); 564 565 mResetInProgress = false; 566 finishReset(); 567 } else if (mResetPostponed) { 568 (new AMessage(kWhatReset, id()))->post(); 569 mResetPostponed = false; 570 } else if (mAudioDecoder == NULL || mVideoDecoder == NULL) { 571 postScanSources(); 572 } 573} 574 575void NuPlayer::finishReset() { 576 CHECK(mAudioDecoder == NULL); 577 CHECK(mVideoDecoder == NULL); 578 579 ++mScanSourcesGeneration; 580 mScanSourcesPending = false; 581 582 mRenderer.clear(); 583 584 if (mSource != NULL) { 585 mSource->stop(); 586 mSource.clear(); 587 } 588 589 if (mDriver != NULL) { 590 sp<NuPlayerDriver> driver = mDriver.promote(); 591 if (driver != NULL) { 592 driver->notifyResetComplete(); 593 } 594 } 595} 596 597void NuPlayer::postScanSources() { 598 if (mScanSourcesPending) { 599 return; 600 } 601 602 sp<AMessage> msg = new AMessage(kWhatScanSources, id()); 603 msg->setInt32("generation", mScanSourcesGeneration); 604 msg->post(); 605 606 mScanSourcesPending = true; 607} 608 609status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) { 610 if (*decoder != NULL) { 611 return OK; 612 } 613 614 sp<MetaData> meta = mSource->getFormat(audio); 615 616 if (meta == NULL) { 617 return -EWOULDBLOCK; 618 } 619 620 if (!audio) { 621 const char *mime; 622 CHECK(meta->findCString(kKeyMIMEType, &mime)); 623 mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime); 624 } 625 626 sp<AMessage> notify = 627 new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify, 628 id()); 629 630 *decoder = audio ? new Decoder(notify) : 631 new Decoder(notify, mNativeWindow); 632 looper()->registerHandler(*decoder); 633 634 (*decoder)->configure(meta); 635 636 int64_t durationUs; 637 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) { 638 sp<NuPlayerDriver> driver = mDriver.promote(); 639 if (driver != NULL) { 640 driver->notifyDuration(durationUs); 641 } 642 } 643 644 return OK; 645} 646 647status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { 648 sp<AMessage> reply; 649 CHECK(msg->findMessage("reply", &reply)); 650 651 if ((audio && IsFlushingState(mFlushingAudio)) 652 || (!audio && IsFlushingState(mFlushingVideo))) { 653 reply->setInt32("err", INFO_DISCONTINUITY); 654 reply->post(); 655 return OK; 656 } 657 658 sp<ABuffer> accessUnit; 659 660 bool dropAccessUnit; 661 do { 662 status_t err = mSource->dequeueAccessUnit(audio, &accessUnit); 663 664 if (err == -EWOULDBLOCK) { 665 return err; 666 } else if (err != OK) { 667 if (err == INFO_DISCONTINUITY) { 668 int32_t type; 669 CHECK(accessUnit->meta()->findInt32("discontinuity", &type)); 670 671 bool formatChange = 672 type == ATSParser::DISCONTINUITY_FORMATCHANGE; 673 674 LOGV("%s discontinuity (formatChange=%d)", 675 audio ? "audio" : "video", formatChange); 676 677 if (audio) { 678 mSkipRenderingAudioUntilMediaTimeUs = -1; 679 } else { 680 mSkipRenderingVideoUntilMediaTimeUs = -1; 681 } 682 683 sp<AMessage> extra; 684 if (accessUnit->meta()->findMessage("extra", &extra) 685 && extra != NULL) { 686 int64_t resumeAtMediaTimeUs; 687 if (extra->findInt64( 688 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) { 689 LOGI("suppressing rendering of %s until %lld us", 690 audio ? "audio" : "video", resumeAtMediaTimeUs); 691 692 if (audio) { 693 mSkipRenderingAudioUntilMediaTimeUs = 694 resumeAtMediaTimeUs; 695 } else { 696 mSkipRenderingVideoUntilMediaTimeUs = 697 resumeAtMediaTimeUs; 698 } 699 } 700 } 701 702 flushDecoder(audio, formatChange); 703 } 704 705 reply->setInt32("err", err); 706 reply->post(); 707 return OK; 708 } 709 710 if (!audio) { 711 ++mNumFramesTotal; 712 } 713 714 dropAccessUnit = false; 715 if (!audio 716 && mVideoLateByUs > 100000ll 717 && mVideoIsAVC 718 && !IsAVCReferenceFrame(accessUnit)) { 719 dropAccessUnit = true; 720 ++mNumFramesDropped; 721 } 722 } while (dropAccessUnit); 723 724 // LOGV("returned a valid buffer of %s data", audio ? "audio" : "video"); 725 726#if 0 727 int64_t mediaTimeUs; 728 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs)); 729 LOGV("feeding %s input buffer at media time %.2f secs", 730 audio ? "audio" : "video", 731 mediaTimeUs / 1E6); 732#endif 733 734 reply->setObject("buffer", accessUnit); 735 reply->post(); 736 737 return OK; 738} 739 740void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) { 741 // LOGV("renderBuffer %s", audio ? "audio" : "video"); 742 743 sp<AMessage> reply; 744 CHECK(msg->findMessage("reply", &reply)); 745 746 if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) { 747 // We're currently attempting to flush the decoder, in order 748 // to complete this, the decoder wants all its buffers back, 749 // so we don't want any output buffers it sent us (from before 750 // we initiated the flush) to be stuck in the renderer's queue. 751 752 LOGV("we're still flushing the %s decoder, sending its output buffer" 753 " right back.", audio ? "audio" : "video"); 754 755 reply->post(); 756 return; 757 } 758 759 sp<RefBase> obj; 760 CHECK(msg->findObject("buffer", &obj)); 761 762 sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get()); 763 764 int64_t &skipUntilMediaTimeUs = 765 audio 766 ? mSkipRenderingAudioUntilMediaTimeUs 767 : mSkipRenderingVideoUntilMediaTimeUs; 768 769 if (skipUntilMediaTimeUs >= 0) { 770 int64_t mediaTimeUs; 771 CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs)); 772 773 if (mediaTimeUs < skipUntilMediaTimeUs) { 774 LOGV("dropping %s buffer at time %lld as requested.", 775 audio ? "audio" : "video", 776 mediaTimeUs); 777 778 reply->post(); 779 return; 780 } 781 782 skipUntilMediaTimeUs = -1; 783 } 784 785 mRenderer->queueBuffer(audio, buffer, reply); 786} 787 788void NuPlayer::notifyListener(int msg, int ext1, int ext2) { 789 if (mDriver == NULL) { 790 return; 791 } 792 793 sp<NuPlayerDriver> driver = mDriver.promote(); 794 795 if (driver == NULL) { 796 return; 797 } 798 799 driver->notifyListener(msg, ext1, ext2); 800} 801 802void NuPlayer::flushDecoder(bool audio, bool needShutdown) { 803 // Make sure we don't continue to scan sources until we finish flushing. 804 ++mScanSourcesGeneration; 805 mScanSourcesPending = false; 806 807 (audio ? mAudioDecoder : mVideoDecoder)->signalFlush(); 808 mRenderer->flush(audio); 809 810 FlushStatus newStatus = 811 needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER; 812 813 if (audio) { 814 CHECK(mFlushingAudio == NONE 815 || mFlushingAudio == AWAITING_DISCONTINUITY); 816 817 mFlushingAudio = newStatus; 818 819 if (mFlushingVideo == NONE) { 820 mFlushingVideo = (mVideoDecoder != NULL) 821 ? AWAITING_DISCONTINUITY 822 : FLUSHED; 823 } 824 } else { 825 CHECK(mFlushingVideo == NONE 826 || mFlushingVideo == AWAITING_DISCONTINUITY); 827 828 mFlushingVideo = newStatus; 829 830 if (mFlushingAudio == NONE) { 831 mFlushingAudio = (mAudioDecoder != NULL) 832 ? AWAITING_DISCONTINUITY 833 : FLUSHED; 834 } 835 } 836} 837 838} // namespace android 839