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