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