NuPlayer.cpp revision fbe9d81ff5fbdc5aecdcdd13e4a5d7f019824f96
1affc150dc44fab1911775a49636d0ce85333b634Zonr Chang/* 2affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * Copyright (C) 2010 The Android Open Source Project 3affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * 4affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License"); 5affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * you may not use this file except in compliance with the License. 6affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * You may obtain a copy of the License at 7affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * 8affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * http://www.apache.org/licenses/LICENSE-2.0 937b74a387bb3993387029859c2d9d051c41c724eStephen Hines * 10affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * Unless required by applicable law or agreed to in writing, software 1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines * distributed under the License is distributed on an "AS IS" BASIS, 12affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * See the License for the specific language governing permissions and 14affc150dc44fab1911775a49636d0ce85333b634Zonr Chang * limitations under the License. 15affc150dc44fab1911775a49636d0ce85333b634Zonr Chang */ 1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines 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 CHECK_EQ(what, (int32_t)Renderer::kWhatFlushComplete); 513 514 int32_t audio; 515 CHECK(msg->findInt32("audio", &audio)); 516 517 ALOGV("renderer %s flush completed.", audio ? "audio" : "video"); 518 } else if (what == Renderer::kWhatVideoRenderingStart) { 519 notifyListener(MEDIA_INFO, MEDIA_INFO_RENDERING_START, 0); 520 } 521 break; 522 } 523 524 case kWhatMoreDataQueued: 525 { 526 break; 527 } 528 529 case kWhatReset: 530 { 531 ALOGV("kWhatReset"); 532 533 if (mRenderer != NULL) { 534 // There's an edge case where the renderer owns all output 535 // buffers and is paused, therefore the decoder will not read 536 // more input data and will never encounter the matching 537 // discontinuity. To avoid this, we resume the renderer. 538 539 if (mFlushingAudio == AWAITING_DISCONTINUITY 540 || mFlushingVideo == AWAITING_DISCONTINUITY) { 541 mRenderer->resume(); 542 } 543 } 544 545 if (mFlushingAudio != NONE || mFlushingVideo != NONE) { 546 // We're currently flushing, postpone the reset until that's 547 // completed. 548 549 ALOGV("postponing reset mFlushingAudio=%d, mFlushingVideo=%d", 550 mFlushingAudio, mFlushingVideo); 551 552 mResetPostponed = true; 553 break; 554 } 555 556 if (mAudioDecoder == NULL && mVideoDecoder == NULL) { 557 finishReset(); 558 break; 559 } 560 561 mTimeDiscontinuityPending = true; 562 563 if (mAudioDecoder != NULL) { 564 flushDecoder(true /* audio */, true /* needShutdown */); 565 } 566 567 if (mVideoDecoder != NULL) { 568 flushDecoder(false /* audio */, true /* needShutdown */); 569 } 570 571 mResetInProgress = true; 572 break; 573 } 574 575 case kWhatSeek: 576 { 577 int64_t seekTimeUs; 578 CHECK(msg->findInt64("seekTimeUs", &seekTimeUs)); 579 580 ALOGV("kWhatSeek seekTimeUs=%lld us (%.2f secs)", 581 seekTimeUs, seekTimeUs / 1E6); 582 583 mSource->seekTo(seekTimeUs); 584 585 if (mDriver != NULL) { 586 sp<NuPlayerDriver> driver = mDriver.promote(); 587 if (driver != NULL) { 588 driver->notifySeekComplete(); 589 } 590 } 591 592 break; 593 } 594 595 case kWhatPause: 596 { 597 CHECK(mRenderer != NULL); 598 mRenderer->pause(); 599 break; 600 } 601 602 case kWhatResume: 603 { 604 CHECK(mRenderer != NULL); 605 mRenderer->resume(); 606 break; 607 } 608 609 default: 610 TRESPASS(); 611 break; 612 } 613} 614 615void NuPlayer::finishFlushIfPossible() { 616 if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) { 617 return; 618 } 619 620 if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) { 621 return; 622 } 623 624 ALOGV("both audio and video are flushed now."); 625 626 if (mTimeDiscontinuityPending) { 627 mRenderer->signalTimeDiscontinuity(); 628 mTimeDiscontinuityPending = false; 629 } 630 631 if (mAudioDecoder != NULL) { 632 mAudioDecoder->signalResume(); 633 } 634 635 if (mVideoDecoder != NULL) { 636 mVideoDecoder->signalResume(); 637 } 638 639 mFlushingAudio = NONE; 640 mFlushingVideo = NONE; 641 642 if (mResetInProgress) { 643 ALOGV("reset completed"); 644 645 mResetInProgress = false; 646 finishReset(); 647 } else if (mResetPostponed) { 648 (new AMessage(kWhatReset, id()))->post(); 649 mResetPostponed = false; 650 } else if (mAudioDecoder == NULL || mVideoDecoder == NULL) { 651 postScanSources(); 652 } 653} 654 655void NuPlayer::finishReset() { 656 CHECK(mAudioDecoder == NULL); 657 CHECK(mVideoDecoder == NULL); 658 659 ++mScanSourcesGeneration; 660 mScanSourcesPending = false; 661 662 mRenderer.clear(); 663 664 if (mSource != NULL) { 665 mSource->stop(); 666 mSource.clear(); 667 } 668 669 if (mDriver != NULL) { 670 sp<NuPlayerDriver> driver = mDriver.promote(); 671 if (driver != NULL) { 672 driver->notifyResetComplete(); 673 } 674 } 675} 676 677void NuPlayer::postScanSources() { 678 if (mScanSourcesPending) { 679 return; 680 } 681 682 sp<AMessage> msg = new AMessage(kWhatScanSources, id()); 683 msg->setInt32("generation", mScanSourcesGeneration); 684 msg->post(); 685 686 mScanSourcesPending = true; 687} 688 689status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) { 690 if (*decoder != NULL) { 691 return OK; 692 } 693 694 sp<AMessage> format = mSource->getFormat(audio); 695 696 if (format == NULL) { 697 return -EWOULDBLOCK; 698 } 699 700 if (!audio) { 701 AString mime; 702 CHECK(format->findString("mime", &mime)); 703 mVideoIsAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str()); 704 } 705 706 sp<AMessage> notify = 707 new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify, 708 id()); 709 710 *decoder = audio ? new Decoder(notify) : 711 new Decoder(notify, mNativeWindow); 712 looper()->registerHandler(*decoder); 713 714 (*decoder)->configure(format); 715 716 int64_t durationUs; 717 if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) { 718 sp<NuPlayerDriver> driver = mDriver.promote(); 719 if (driver != NULL) { 720 driver->notifyDuration(durationUs); 721 } 722 } 723 724 return OK; 725} 726 727status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { 728 sp<AMessage> reply; 729 CHECK(msg->findMessage("reply", &reply)); 730 731 if ((audio && IsFlushingState(mFlushingAudio)) 732 || (!audio && IsFlushingState(mFlushingVideo))) { 733 reply->setInt32("err", INFO_DISCONTINUITY); 734 reply->post(); 735 return OK; 736 } 737 738 sp<ABuffer> accessUnit; 739 740 bool dropAccessUnit; 741 do { 742 status_t err = mSource->dequeueAccessUnit(audio, &accessUnit); 743 744 if (err == -EWOULDBLOCK) { 745 return err; 746 } else if (err != OK) { 747 if (err == INFO_DISCONTINUITY) { 748 int32_t type; 749 CHECK(accessUnit->meta()->findInt32("discontinuity", &type)); 750 751 bool formatChange = 752 (audio && 753 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT)) 754 || (!audio && 755 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT)); 756 757 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0; 758 759 ALOGI("%s discontinuity (formatChange=%d, time=%d)", 760 audio ? "audio" : "video", formatChange, timeChange); 761 762 if (audio) { 763 mSkipRenderingAudioUntilMediaTimeUs = -1; 764 } else { 765 mSkipRenderingVideoUntilMediaTimeUs = -1; 766 } 767 768 if (timeChange) { 769 sp<AMessage> extra; 770 if (accessUnit->meta()->findMessage("extra", &extra) 771 && extra != NULL) { 772 int64_t resumeAtMediaTimeUs; 773 if (extra->findInt64( 774 "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) { 775 ALOGI("suppressing rendering of %s until %lld us", 776 audio ? "audio" : "video", resumeAtMediaTimeUs); 777 778 if (audio) { 779 mSkipRenderingAudioUntilMediaTimeUs = 780 resumeAtMediaTimeUs; 781 } else { 782 mSkipRenderingVideoUntilMediaTimeUs = 783 resumeAtMediaTimeUs; 784 } 785 } 786 } 787 } 788 789 mTimeDiscontinuityPending = 790 mTimeDiscontinuityPending || timeChange; 791 792 if (formatChange || timeChange) { 793 flushDecoder(audio, formatChange); 794 } else { 795 // This stream is unaffected by the discontinuity 796 797 if (audio) { 798 mFlushingAudio = FLUSHED; 799 } else { 800 mFlushingVideo = FLUSHED; 801 } 802 803 finishFlushIfPossible(); 804 805 return -EWOULDBLOCK; 806 } 807 } 808 809 reply->setInt32("err", err); 810 reply->post(); 811 return OK; 812 } 813 814 if (!audio) { 815 ++mNumFramesTotal; 816 } 817 818 dropAccessUnit = false; 819 if (!audio 820 && mVideoLateByUs > 100000ll 821 && mVideoIsAVC 822 && !IsAVCReferenceFrame(accessUnit)) { 823 dropAccessUnit = true; 824 ++mNumFramesDropped; 825 } 826 } while (dropAccessUnit); 827 828 // ALOGV("returned a valid buffer of %s data", audio ? "audio" : "video"); 829 830#if 0 831 int64_t mediaTimeUs; 832 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs)); 833 ALOGV("feeding %s input buffer at media time %.2f secs", 834 audio ? "audio" : "video", 835 mediaTimeUs / 1E6); 836#endif 837 838 reply->setBuffer("buffer", accessUnit); 839 reply->post(); 840 841 return OK; 842} 843 844void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) { 845 // ALOGV("renderBuffer %s", audio ? "audio" : "video"); 846 847 sp<AMessage> reply; 848 CHECK(msg->findMessage("reply", &reply)); 849 850 if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) { 851 // We're currently attempting to flush the decoder, in order 852 // to complete this, the decoder wants all its buffers back, 853 // so we don't want any output buffers it sent us (from before 854 // we initiated the flush) to be stuck in the renderer's queue. 855 856 ALOGV("we're still flushing the %s decoder, sending its output buffer" 857 " right back.", audio ? "audio" : "video"); 858 859 reply->post(); 860 return; 861 } 862 863 sp<ABuffer> buffer; 864 CHECK(msg->findBuffer("buffer", &buffer)); 865 866 int64_t &skipUntilMediaTimeUs = 867 audio 868 ? mSkipRenderingAudioUntilMediaTimeUs 869 : mSkipRenderingVideoUntilMediaTimeUs; 870 871 if (skipUntilMediaTimeUs >= 0) { 872 int64_t mediaTimeUs; 873 CHECK(buffer->meta()->findInt64("timeUs", &mediaTimeUs)); 874 875 if (mediaTimeUs < skipUntilMediaTimeUs) { 876 ALOGV("dropping %s buffer at time %lld as requested.", 877 audio ? "audio" : "video", 878 mediaTimeUs); 879 880 reply->post(); 881 return; 882 } 883 884 skipUntilMediaTimeUs = -1; 885 } 886 887 mRenderer->queueBuffer(audio, buffer, reply); 888} 889 890void NuPlayer::notifyListener(int msg, int ext1, int ext2) { 891 if (mDriver == NULL) { 892 return; 893 } 894 895 sp<NuPlayerDriver> driver = mDriver.promote(); 896 897 if (driver == NULL) { 898 return; 899 } 900 901 driver->notifyListener(msg, ext1, ext2); 902} 903 904void NuPlayer::flushDecoder(bool audio, bool needShutdown) { 905 if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) { 906 ALOGI("flushDecoder %s without decoder present", 907 audio ? "audio" : "video"); 908 } 909 910 // Make sure we don't continue to scan sources until we finish flushing. 911 ++mScanSourcesGeneration; 912 mScanSourcesPending = false; 913 914 (audio ? mAudioDecoder : mVideoDecoder)->signalFlush(); 915 mRenderer->flush(audio); 916 917 FlushStatus newStatus = 918 needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER; 919 920 if (audio) { 921 CHECK(mFlushingAudio == NONE 922 || mFlushingAudio == AWAITING_DISCONTINUITY); 923 924 mFlushingAudio = newStatus; 925 926 if (mFlushingVideo == NONE) { 927 mFlushingVideo = (mVideoDecoder != NULL) 928 ? AWAITING_DISCONTINUITY 929 : FLUSHED; 930 } 931 } else { 932 CHECK(mFlushingVideo == NONE 933 || mFlushingVideo == AWAITING_DISCONTINUITY); 934 935 mFlushingVideo = newStatus; 936 937 if (mFlushingAudio == NONE) { 938 mFlushingAudio = (mAudioDecoder != NULL) 939 ? AWAITING_DISCONTINUITY 940 : FLUSHED; 941 } 942 } 943} 944 945sp<AMessage> NuPlayer::Source::getFormat(bool audio) { 946 sp<MetaData> meta = getFormatMeta(audio); 947 948 if (meta == NULL) { 949 return NULL; 950 } 951 952 sp<AMessage> msg = new AMessage; 953 954 if(convertMetaDataToMessage(meta, &msg) == OK) { 955 return msg; 956 } 957 return NULL; 958} 959 960} // namespace android 961