NuPlayerDecoder.cpp revision 56097a8ecc31ec308a1caa38f92b69f99324eada
1/* 2 * Copyright 2014 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 "NuPlayerDecoder" 19#include <utils/Log.h> 20#include <inttypes.h> 21 22#include "NuPlayerCCDecoder.h" 23#include "NuPlayerDecoder.h" 24#include "NuPlayerRenderer.h" 25#include "NuPlayerSource.h" 26 27#include <cutils/properties.h> 28#include <media/ICrypto.h> 29#include <media/stagefright/foundation/ABuffer.h> 30#include <media/stagefright/foundation/ADebug.h> 31#include <media/stagefright/foundation/AMessage.h> 32#include <media/stagefright/MediaBuffer.h> 33#include <media/stagefright/MediaCodec.h> 34#include <media/stagefright/MediaDefs.h> 35#include <media/stagefright/MediaErrors.h> 36 37#include <gui/Surface.h> 38 39#include "avc_utils.h" 40#include "ATSParser.h" 41 42namespace android { 43 44static inline bool getAudioDeepBufferSetting() { 45 return property_get_bool("media.stagefright.audio.deep", false /* default_value */); 46} 47 48NuPlayer::Decoder::Decoder( 49 const sp<AMessage> ¬ify, 50 const sp<Source> &source, 51 pid_t pid, 52 const sp<Renderer> &renderer, 53 const sp<Surface> &surface, 54 const sp<CCDecoder> &ccDecoder) 55 : DecoderBase(notify), 56 mSurface(surface), 57 mSource(source), 58 mRenderer(renderer), 59 mCCDecoder(ccDecoder), 60 mPid(pid), 61 mSkipRenderingUntilMediaTimeUs(-1ll), 62 mNumFramesTotal(0ll), 63 mNumInputFramesDropped(0ll), 64 mNumOutputFramesDropped(0ll), 65 mVideoWidth(0), 66 mVideoHeight(0), 67 mIsAudio(true), 68 mIsVideoAVC(false), 69 mIsSecure(false), 70 mFormatChangePending(false), 71 mTimeChangePending(false), 72 mResumePending(false), 73 mComponentName("decoder") { 74 mCodecLooper = new ALooper; 75 mCodecLooper->setName("NPDecoder-CL"); 76 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO); 77} 78 79NuPlayer::Decoder::~Decoder() { 80 mCodec->release(); 81 releaseAndResetMediaBuffers(); 82} 83 84sp<AMessage> NuPlayer::Decoder::getStats() const { 85 mStats->setInt64("frames-total", mNumFramesTotal); 86 mStats->setInt64("frames-dropped-input", mNumInputFramesDropped); 87 mStats->setInt64("frames-dropped-output", mNumOutputFramesDropped); 88 return mStats; 89} 90 91status_t NuPlayer::Decoder::setVideoSurface(const sp<Surface> &surface) { 92 if (surface == NULL || ADebug::isExperimentEnabled("legacy-setsurface")) { 93 return BAD_VALUE; 94 } 95 96 sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, this); 97 98 msg->setObject("surface", surface); 99 sp<AMessage> response; 100 status_t err = msg->postAndAwaitResponse(&response); 101 if (err == OK && response != NULL) { 102 CHECK(response->findInt32("err", &err)); 103 } 104 return err; 105} 106 107void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) { 108 ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str()); 109 110 switch (msg->what()) { 111 case kWhatCodecNotify: 112 { 113 int32_t cbID; 114 CHECK(msg->findInt32("callbackID", &cbID)); 115 116 ALOGV("[%s] kWhatCodecNotify: cbID = %d, paused = %d", 117 mIsAudio ? "audio" : "video", cbID, mPaused); 118 119 if (mPaused) { 120 break; 121 } 122 123 switch (cbID) { 124 case MediaCodec::CB_INPUT_AVAILABLE: 125 { 126 int32_t index; 127 CHECK(msg->findInt32("index", &index)); 128 129 handleAnInputBuffer(index); 130 break; 131 } 132 133 case MediaCodec::CB_OUTPUT_AVAILABLE: 134 { 135 int32_t index; 136 size_t offset; 137 size_t size; 138 int64_t timeUs; 139 int32_t flags; 140 141 CHECK(msg->findInt32("index", &index)); 142 CHECK(msg->findSize("offset", &offset)); 143 CHECK(msg->findSize("size", &size)); 144 CHECK(msg->findInt64("timeUs", &timeUs)); 145 CHECK(msg->findInt32("flags", &flags)); 146 147 handleAnOutputBuffer(index, offset, size, timeUs, flags); 148 break; 149 } 150 151 case MediaCodec::CB_OUTPUT_FORMAT_CHANGED: 152 { 153 sp<AMessage> format; 154 CHECK(msg->findMessage("format", &format)); 155 156 handleOutputFormatChange(format); 157 break; 158 } 159 160 case MediaCodec::CB_ERROR: 161 { 162 status_t err; 163 CHECK(msg->findInt32("err", &err)); 164 ALOGE("Decoder (%s) reported error : 0x%x", 165 mIsAudio ? "audio" : "video", err); 166 167 handleError(err); 168 break; 169 } 170 171 default: 172 { 173 TRESPASS(); 174 break; 175 } 176 } 177 178 break; 179 } 180 181 case kWhatRenderBuffer: 182 { 183 if (!isStaleReply(msg)) { 184 onRenderBuffer(msg); 185 } 186 break; 187 } 188 189 case kWhatSetVideoSurface: 190 { 191 sp<AReplyToken> replyID; 192 CHECK(msg->senderAwaitsResponse(&replyID)); 193 194 sp<RefBase> obj; 195 CHECK(msg->findObject("surface", &obj)); 196 sp<Surface> surface = static_cast<Surface *>(obj.get()); // non-null 197 int32_t err = INVALID_OPERATION; 198 // NOTE: in practice mSurface is always non-null, but checking here for completeness 199 if (mCodec != NULL && mSurface != NULL) { 200 // TODO: once AwesomePlayer is removed, remove this automatic connecting 201 // to the surface by MediaPlayerService. 202 // 203 // at this point MediaPlayerService::client has already connected to the 204 // surface, which MediaCodec does not expect 205 err = native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA); 206 if (err == OK) { 207 err = mCodec->setSurface(surface); 208 ALOGI_IF(err, "codec setSurface returned: %d", err); 209 if (err == OK) { 210 // reconnect to the old surface as MPS::Client will expect to 211 // be able to disconnect from it. 212 (void)native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_MEDIA); 213 mSurface = surface; 214 } 215 } 216 if (err != OK) { 217 // reconnect to the new surface on error as MPS::Client will expect to 218 // be able to disconnect from it. 219 (void)native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA); 220 } 221 } 222 223 sp<AMessage> response = new AMessage; 224 response->setInt32("err", err); 225 response->postReply(replyID); 226 break; 227 } 228 229 default: 230 DecoderBase::onMessageReceived(msg); 231 break; 232 } 233} 234 235void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) { 236 CHECK(mCodec == NULL); 237 238 mFormatChangePending = false; 239 mTimeChangePending = false; 240 241 ++mBufferGeneration; 242 243 AString mime; 244 CHECK(format->findString("mime", &mime)); 245 246 mIsAudio = !strncasecmp("audio/", mime.c_str(), 6); 247 mIsVideoAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str()); 248 249 mComponentName = mime; 250 mComponentName.append(" decoder"); 251 ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), mSurface.get()); 252 253 mCodec = MediaCodec::CreateByType( 254 mCodecLooper, mime.c_str(), false /* encoder */, NULL /* err */, mPid); 255 int32_t secure = 0; 256 if (format->findInt32("secure", &secure) && secure != 0) { 257 if (mCodec != NULL) { 258 mCodec->getName(&mComponentName); 259 mComponentName.append(".secure"); 260 mCodec->release(); 261 ALOGI("[%s] creating", mComponentName.c_str()); 262 mCodec = MediaCodec::CreateByComponentName( 263 mCodecLooper, mComponentName.c_str(), NULL /* err */, mPid); 264 } 265 } 266 if (mCodec == NULL) { 267 ALOGE("Failed to create %s%s decoder", 268 (secure ? "secure " : ""), mime.c_str()); 269 handleError(UNKNOWN_ERROR); 270 return; 271 } 272 mIsSecure = secure; 273 274 mCodec->getName(&mComponentName); 275 276 status_t err; 277 if (mSurface != NULL) { 278 // disconnect from surface as MediaCodec will reconnect 279 err = native_window_api_disconnect( 280 mSurface.get(), NATIVE_WINDOW_API_MEDIA); 281 // We treat this as a warning, as this is a preparatory step. 282 // Codec will try to connect to the surface, which is where 283 // any error signaling will occur. 284 ALOGW_IF(err != OK, "failed to disconnect from surface: %d", err); 285 } 286 err = mCodec->configure( 287 format, mSurface, NULL /* crypto */, 0 /* flags */); 288 if (err != OK) { 289 ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err); 290 mCodec->release(); 291 mCodec.clear(); 292 handleError(err); 293 return; 294 } 295 rememberCodecSpecificData(format); 296 297 // the following should work in configured state 298 CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat)); 299 CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat)); 300 301 mStats->setString("mime", mime.c_str()); 302 mStats->setString("component-name", mComponentName.c_str()); 303 304 if (!mIsAudio) { 305 int32_t width, height; 306 if (mOutputFormat->findInt32("width", &width) 307 && mOutputFormat->findInt32("height", &height)) { 308 mStats->setInt32("width", width); 309 mStats->setInt32("height", height); 310 } 311 } 312 313 sp<AMessage> reply = new AMessage(kWhatCodecNotify, this); 314 mCodec->setCallback(reply); 315 316 err = mCodec->start(); 317 if (err != OK) { 318 ALOGE("Failed to start %s decoder (err=%d)", mComponentName.c_str(), err); 319 mCodec->release(); 320 mCodec.clear(); 321 handleError(err); 322 return; 323 } 324 325 releaseAndResetMediaBuffers(); 326 327 mPaused = false; 328 mResumePending = false; 329} 330 331void NuPlayer::Decoder::onSetParameters(const sp<AMessage> ¶ms) { 332 if (mCodec == NULL) { 333 ALOGW("onSetParameters called before codec is created."); 334 return; 335 } 336 mCodec->setParameters(params); 337} 338 339void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) { 340 bool hadNoRenderer = (mRenderer == NULL); 341 mRenderer = renderer; 342 if (hadNoRenderer && mRenderer != NULL) { 343 // this means that the widevine legacy source is ready 344 onRequestInputBuffers(); 345 } 346} 347 348void NuPlayer::Decoder::onGetInputBuffers( 349 Vector<sp<ABuffer> > *dstBuffers) { 350 CHECK_EQ((status_t)OK, mCodec->getWidevineLegacyBuffers(dstBuffers)); 351} 352 353void NuPlayer::Decoder::onResume(bool notifyComplete) { 354 mPaused = false; 355 356 if (notifyComplete) { 357 mResumePending = true; 358 } 359 mCodec->start(); 360} 361 362void NuPlayer::Decoder::doFlush(bool notifyComplete) { 363 if (mCCDecoder != NULL) { 364 mCCDecoder->flush(); 365 } 366 367 if (mRenderer != NULL) { 368 mRenderer->flush(mIsAudio, notifyComplete); 369 mRenderer->signalTimeDiscontinuity(); 370 } 371 372 status_t err = OK; 373 if (mCodec != NULL) { 374 err = mCodec->flush(); 375 mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator 376 ++mBufferGeneration; 377 } 378 379 if (err != OK) { 380 ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err); 381 handleError(err); 382 // finish with posting kWhatFlushCompleted. 383 // we attempt to release the buffers even if flush fails. 384 } 385 releaseAndResetMediaBuffers(); 386 mPaused = true; 387} 388 389 390void NuPlayer::Decoder::onFlush() { 391 doFlush(true); 392 393 if (isDiscontinuityPending()) { 394 // This could happen if the client starts seeking/shutdown 395 // after we queued an EOS for discontinuities. 396 // We can consider discontinuity handled. 397 finishHandleDiscontinuity(false /* flushOnTimeChange */); 398 } 399 400 sp<AMessage> notify = mNotify->dup(); 401 notify->setInt32("what", kWhatFlushCompleted); 402 notify->post(); 403} 404 405void NuPlayer::Decoder::onShutdown(bool notifyComplete) { 406 status_t err = OK; 407 408 // if there is a pending resume request, notify complete now 409 notifyResumeCompleteIfNecessary(); 410 411 if (mCodec != NULL) { 412 err = mCodec->release(); 413 mCodec = NULL; 414 ++mBufferGeneration; 415 416 if (mSurface != NULL) { 417 // reconnect to surface as MediaCodec disconnected from it 418 status_t error = 419 native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_MEDIA); 420 ALOGW_IF(error != NO_ERROR, 421 "[%s] failed to connect to native window, error=%d", 422 mComponentName.c_str(), error); 423 } 424 mComponentName = "decoder"; 425 } 426 427 releaseAndResetMediaBuffers(); 428 429 if (err != OK) { 430 ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err); 431 handleError(err); 432 // finish with posting kWhatShutdownCompleted. 433 } 434 435 if (notifyComplete) { 436 sp<AMessage> notify = mNotify->dup(); 437 notify->setInt32("what", kWhatShutdownCompleted); 438 notify->post(); 439 mPaused = true; 440 } 441} 442 443/* 444 * returns true if we should request more data 445 */ 446bool NuPlayer::Decoder::doRequestBuffers() { 447 // mRenderer is only NULL if we have a legacy widevine source that 448 // is not yet ready. In this case we must not fetch input. 449 if (isDiscontinuityPending() || mRenderer == NULL) { 450 return false; 451 } 452 status_t err = OK; 453 while (err == OK && !mDequeuedInputBuffers.empty()) { 454 size_t bufferIx = *mDequeuedInputBuffers.begin(); 455 sp<AMessage> msg = new AMessage(); 456 msg->setSize("buffer-ix", bufferIx); 457 err = fetchInputData(msg); 458 if (err != OK && err != ERROR_END_OF_STREAM) { 459 // if EOS, need to queue EOS buffer 460 break; 461 } 462 mDequeuedInputBuffers.erase(mDequeuedInputBuffers.begin()); 463 464 if (!mPendingInputMessages.empty() 465 || !onInputBufferFetched(msg)) { 466 mPendingInputMessages.push_back(msg); 467 } 468 } 469 470 return err == -EWOULDBLOCK 471 && mSource->feedMoreTSData() == OK; 472} 473 474void NuPlayer::Decoder::handleError(int32_t err) 475{ 476 // We cannot immediately release the codec due to buffers still outstanding 477 // in the renderer. We signal to the player the error so it can shutdown/release the 478 // decoder after flushing and increment the generation to discard unnecessary messages. 479 480 ++mBufferGeneration; 481 482 sp<AMessage> notify = mNotify->dup(); 483 notify->setInt32("what", kWhatError); 484 notify->setInt32("err", err); 485 notify->post(); 486} 487 488bool NuPlayer::Decoder::handleAnInputBuffer(size_t index) { 489 if (isDiscontinuityPending()) { 490 return false; 491 } 492 493 sp<ABuffer> buffer; 494 mCodec->getInputBuffer(index, &buffer); 495 496 if (buffer == NULL) { 497 handleError(UNKNOWN_ERROR); 498 return false; 499 } 500 501 if (index >= mInputBuffers.size()) { 502 for (size_t i = mInputBuffers.size(); i <= index; ++i) { 503 mInputBuffers.add(); 504 mMediaBuffers.add(); 505 mInputBufferIsDequeued.add(); 506 mMediaBuffers.editItemAt(i) = NULL; 507 mInputBufferIsDequeued.editItemAt(i) = false; 508 } 509 } 510 mInputBuffers.editItemAt(index) = buffer; 511 512 //CHECK_LT(bufferIx, mInputBuffers.size()); 513 514 if (mMediaBuffers[index] != NULL) { 515 mMediaBuffers[index]->release(); 516 mMediaBuffers.editItemAt(index) = NULL; 517 } 518 mInputBufferIsDequeued.editItemAt(index) = true; 519 520 if (!mCSDsToSubmit.isEmpty()) { 521 sp<AMessage> msg = new AMessage(); 522 msg->setSize("buffer-ix", index); 523 524 sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0); 525 ALOGI("[%s] resubmitting CSD", mComponentName.c_str()); 526 msg->setBuffer("buffer", buffer); 527 mCSDsToSubmit.removeAt(0); 528 if (!onInputBufferFetched(msg)) { 529 handleError(UNKNOWN_ERROR); 530 return false; 531 } 532 return true; 533 } 534 535 while (!mPendingInputMessages.empty()) { 536 sp<AMessage> msg = *mPendingInputMessages.begin(); 537 if (!onInputBufferFetched(msg)) { 538 break; 539 } 540 mPendingInputMessages.erase(mPendingInputMessages.begin()); 541 } 542 543 if (!mInputBufferIsDequeued.editItemAt(index)) { 544 return true; 545 } 546 547 mDequeuedInputBuffers.push_back(index); 548 549 onRequestInputBuffers(); 550 return true; 551} 552 553bool NuPlayer::Decoder::handleAnOutputBuffer( 554 size_t index, 555 size_t offset, 556 size_t size, 557 int64_t timeUs, 558 int32_t flags) { 559// CHECK_LT(bufferIx, mOutputBuffers.size()); 560 sp<ABuffer> buffer; 561 mCodec->getOutputBuffer(index, &buffer); 562 563 if (index >= mOutputBuffers.size()) { 564 for (size_t i = mOutputBuffers.size(); i <= index; ++i) { 565 mOutputBuffers.add(); 566 } 567 } 568 569 mOutputBuffers.editItemAt(index) = buffer; 570 571 buffer->setRange(offset, size); 572 buffer->meta()->clear(); 573 buffer->meta()->setInt64("timeUs", timeUs); 574 575 bool eos = flags & MediaCodec::BUFFER_FLAG_EOS; 576 // we do not expect CODECCONFIG or SYNCFRAME for decoder 577 578 sp<AMessage> reply = new AMessage(kWhatRenderBuffer, this); 579 reply->setSize("buffer-ix", index); 580 reply->setInt32("generation", mBufferGeneration); 581 582 if (eos) { 583 ALOGI("[%s] saw output EOS", mIsAudio ? "audio" : "video"); 584 585 buffer->meta()->setInt32("eos", true); 586 reply->setInt32("eos", true); 587 } else if (mSkipRenderingUntilMediaTimeUs >= 0) { 588 if (timeUs < mSkipRenderingUntilMediaTimeUs) { 589 ALOGV("[%s] dropping buffer at time %lld as requested.", 590 mComponentName.c_str(), (long long)timeUs); 591 592 reply->post(); 593 return true; 594 } 595 596 mSkipRenderingUntilMediaTimeUs = -1; 597 } 598 599 mNumFramesTotal += !mIsAudio; 600 601 // wait until 1st frame comes out to signal resume complete 602 notifyResumeCompleteIfNecessary(); 603 604 if (mRenderer != NULL) { 605 // send the buffer to renderer. 606 mRenderer->queueBuffer(mIsAudio, buffer, reply); 607 if (eos && !isDiscontinuityPending()) { 608 mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM); 609 } 610 } 611 612 return true; 613} 614 615void NuPlayer::Decoder::handleOutputFormatChange(const sp<AMessage> &format) { 616 if (!mIsAudio) { 617 int32_t width, height; 618 if (format->findInt32("width", &width) 619 && format->findInt32("height", &height)) { 620 mStats->setInt32("width", width); 621 mStats->setInt32("height", height); 622 } 623 sp<AMessage> notify = mNotify->dup(); 624 notify->setInt32("what", kWhatVideoSizeChanged); 625 notify->setMessage("format", format); 626 notify->post(); 627 } else if (mRenderer != NULL) { 628 uint32_t flags; 629 int64_t durationUs; 630 bool hasVideo = (mSource->getFormat(false /* audio */) != NULL); 631 if (getAudioDeepBufferSetting() // override regardless of source duration 632 || (!hasVideo 633 && mSource->getDuration(&durationUs) == OK 634 && durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US)) { 635 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; 636 } else { 637 flags = AUDIO_OUTPUT_FLAG_NONE; 638 } 639 640 status_t err = mRenderer->openAudioSink( 641 format, false /* offloadOnly */, hasVideo, flags, NULL /* isOffloaed */); 642 if (err != OK) { 643 handleError(err); 644 } 645 } 646} 647 648void NuPlayer::Decoder::releaseAndResetMediaBuffers() { 649 for (size_t i = 0; i < mMediaBuffers.size(); i++) { 650 if (mMediaBuffers[i] != NULL) { 651 mMediaBuffers[i]->release(); 652 mMediaBuffers.editItemAt(i) = NULL; 653 } 654 } 655 mMediaBuffers.resize(mInputBuffers.size()); 656 for (size_t i = 0; i < mMediaBuffers.size(); i++) { 657 mMediaBuffers.editItemAt(i) = NULL; 658 } 659 mInputBufferIsDequeued.clear(); 660 mInputBufferIsDequeued.resize(mInputBuffers.size()); 661 for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) { 662 mInputBufferIsDequeued.editItemAt(i) = false; 663 } 664 665 mPendingInputMessages.clear(); 666 mDequeuedInputBuffers.clear(); 667 mSkipRenderingUntilMediaTimeUs = -1; 668} 669 670void NuPlayer::Decoder::requestCodecNotification() { 671 if (mCodec != NULL) { 672 sp<AMessage> reply = new AMessage(kWhatCodecNotify, this); 673 reply->setInt32("generation", mBufferGeneration); 674 mCodec->requestActivityNotification(reply); 675 } 676} 677 678bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) { 679 int32_t generation; 680 CHECK(msg->findInt32("generation", &generation)); 681 return generation != mBufferGeneration; 682} 683 684status_t NuPlayer::Decoder::fetchInputData(sp<AMessage> &reply) { 685 sp<ABuffer> accessUnit; 686 bool dropAccessUnit; 687 do { 688 status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit); 689 690 if (err == -EWOULDBLOCK) { 691 return err; 692 } else if (err != OK) { 693 if (err == INFO_DISCONTINUITY) { 694 int32_t type; 695 CHECK(accessUnit->meta()->findInt32("discontinuity", &type)); 696 697 bool formatChange = 698 (mIsAudio && 699 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT)) 700 || (!mIsAudio && 701 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT)); 702 703 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0; 704 705 ALOGI("%s discontinuity (format=%d, time=%d)", 706 mIsAudio ? "audio" : "video", formatChange, timeChange); 707 708 bool seamlessFormatChange = false; 709 sp<AMessage> newFormat = mSource->getFormat(mIsAudio); 710 if (formatChange) { 711 seamlessFormatChange = 712 supportsSeamlessFormatChange(newFormat); 713 // treat seamless format change separately 714 formatChange = !seamlessFormatChange; 715 } 716 717 // For format or time change, return EOS to queue EOS input, 718 // then wait for EOS on output. 719 if (formatChange /* not seamless */) { 720 mFormatChangePending = true; 721 err = ERROR_END_OF_STREAM; 722 } else if (timeChange) { 723 rememberCodecSpecificData(newFormat); 724 mTimeChangePending = true; 725 err = ERROR_END_OF_STREAM; 726 } else if (seamlessFormatChange) { 727 // reuse existing decoder and don't flush 728 rememberCodecSpecificData(newFormat); 729 continue; 730 } else { 731 // This stream is unaffected by the discontinuity 732 return -EWOULDBLOCK; 733 } 734 } 735 736 // reply should only be returned without a buffer set 737 // when there is an error (including EOS) 738 CHECK(err != OK); 739 740 reply->setInt32("err", err); 741 return ERROR_END_OF_STREAM; 742 } 743 744 dropAccessUnit = false; 745 if (!mIsAudio 746 && !mIsSecure 747 && mRenderer->getVideoLateByUs() > 100000ll 748 && mIsVideoAVC 749 && !IsAVCReferenceFrame(accessUnit)) { 750 dropAccessUnit = true; 751 ++mNumInputFramesDropped; 752 } 753 } while (dropAccessUnit); 754 755 // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video"); 756#if 0 757 int64_t mediaTimeUs; 758 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs)); 759 ALOGV("[%s] feeding input buffer at media time %.3f", 760 mIsAudio ? "audio" : "video", 761 mediaTimeUs / 1E6); 762#endif 763 764 if (mCCDecoder != NULL) { 765 mCCDecoder->decode(accessUnit); 766 } 767 768 reply->setBuffer("buffer", accessUnit); 769 770 return OK; 771} 772 773bool NuPlayer::Decoder::onInputBufferFetched(const sp<AMessage> &msg) { 774 size_t bufferIx; 775 CHECK(msg->findSize("buffer-ix", &bufferIx)); 776 CHECK_LT(bufferIx, mInputBuffers.size()); 777 sp<ABuffer> codecBuffer = mInputBuffers[bufferIx]; 778 779 sp<ABuffer> buffer; 780 bool hasBuffer = msg->findBuffer("buffer", &buffer); 781 782 // handle widevine classic source - that fills an arbitrary input buffer 783 MediaBuffer *mediaBuffer = NULL; 784 if (hasBuffer) { 785 mediaBuffer = (MediaBuffer *)(buffer->getMediaBufferBase()); 786 if (mediaBuffer != NULL) { 787 // likely filled another buffer than we requested: adjust buffer index 788 size_t ix; 789 for (ix = 0; ix < mInputBuffers.size(); ix++) { 790 const sp<ABuffer> &buf = mInputBuffers[ix]; 791 if (buf->data() == mediaBuffer->data()) { 792 // all input buffers are dequeued on start, hence the check 793 if (!mInputBufferIsDequeued[ix]) { 794 ALOGV("[%s] received MediaBuffer for #%zu instead of #%zu", 795 mComponentName.c_str(), ix, bufferIx); 796 mediaBuffer->release(); 797 return false; 798 } 799 800 // TRICKY: need buffer for the metadata, so instead, set 801 // codecBuffer to the same (though incorrect) buffer to 802 // avoid a memcpy into the codecBuffer 803 codecBuffer = buffer; 804 codecBuffer->setRange( 805 mediaBuffer->range_offset(), 806 mediaBuffer->range_length()); 807 bufferIx = ix; 808 break; 809 } 810 } 811 CHECK(ix < mInputBuffers.size()); 812 } 813 } 814 815 if (buffer == NULL /* includes !hasBuffer */) { 816 int32_t streamErr = ERROR_END_OF_STREAM; 817 CHECK(msg->findInt32("err", &streamErr) || !hasBuffer); 818 819 CHECK(streamErr != OK); 820 821 // attempt to queue EOS 822 status_t err = mCodec->queueInputBuffer( 823 bufferIx, 824 0, 825 0, 826 0, 827 MediaCodec::BUFFER_FLAG_EOS); 828 if (err == OK) { 829 mInputBufferIsDequeued.editItemAt(bufferIx) = false; 830 } else if (streamErr == ERROR_END_OF_STREAM) { 831 streamErr = err; 832 // err will not be ERROR_END_OF_STREAM 833 } 834 835 if (streamErr != ERROR_END_OF_STREAM) { 836 ALOGE("Stream error for %s (err=%d), EOS %s queued", 837 mComponentName.c_str(), 838 streamErr, 839 err == OK ? "successfully" : "unsuccessfully"); 840 handleError(streamErr); 841 } 842 } else { 843 sp<AMessage> extra; 844 if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) { 845 int64_t resumeAtMediaTimeUs; 846 if (extra->findInt64( 847 "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) { 848 ALOGI("[%s] suppressing rendering until %lld us", 849 mComponentName.c_str(), (long long)resumeAtMediaTimeUs); 850 mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs; 851 } 852 } 853 854 int64_t timeUs = 0; 855 uint32_t flags = 0; 856 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 857 858 int32_t eos, csd; 859 // we do not expect SYNCFRAME for decoder 860 if (buffer->meta()->findInt32("eos", &eos) && eos) { 861 flags |= MediaCodec::BUFFER_FLAG_EOS; 862 } else if (buffer->meta()->findInt32("csd", &csd) && csd) { 863 flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG; 864 } 865 866 // copy into codec buffer 867 if (buffer != codecBuffer) { 868 if (buffer->size() > codecBuffer->capacity()) { 869 handleError(ERROR_BUFFER_TOO_SMALL); 870 mDequeuedInputBuffers.push_back(bufferIx); 871 return false; 872 } 873 codecBuffer->setRange(0, buffer->size()); 874 memcpy(codecBuffer->data(), buffer->data(), buffer->size()); 875 } 876 877 status_t err = mCodec->queueInputBuffer( 878 bufferIx, 879 codecBuffer->offset(), 880 codecBuffer->size(), 881 timeUs, 882 flags); 883 if (err != OK) { 884 if (mediaBuffer != NULL) { 885 mediaBuffer->release(); 886 } 887 ALOGE("Failed to queue input buffer for %s (err=%d)", 888 mComponentName.c_str(), err); 889 handleError(err); 890 } else { 891 mInputBufferIsDequeued.editItemAt(bufferIx) = false; 892 if (mediaBuffer != NULL) { 893 CHECK(mMediaBuffers[bufferIx] == NULL); 894 mMediaBuffers.editItemAt(bufferIx) = mediaBuffer; 895 } 896 } 897 } 898 return true; 899} 900 901void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) { 902 status_t err; 903 int32_t render; 904 size_t bufferIx; 905 int32_t eos; 906 CHECK(msg->findSize("buffer-ix", &bufferIx)); 907 908 if (!mIsAudio) { 909 int64_t timeUs; 910 sp<ABuffer> buffer = mOutputBuffers[bufferIx]; 911 buffer->meta()->findInt64("timeUs", &timeUs); 912 913 if (mCCDecoder != NULL && mCCDecoder->isSelected()) { 914 mCCDecoder->display(timeUs); 915 } 916 } 917 918 if (msg->findInt32("render", &render) && render) { 919 int64_t timestampNs; 920 CHECK(msg->findInt64("timestampNs", ×tampNs)); 921 err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs); 922 } else { 923 mNumOutputFramesDropped += !mIsAudio; 924 err = mCodec->releaseOutputBuffer(bufferIx); 925 } 926 if (err != OK) { 927 ALOGE("failed to release output buffer for %s (err=%d)", 928 mComponentName.c_str(), err); 929 handleError(err); 930 } 931 if (msg->findInt32("eos", &eos) && eos 932 && isDiscontinuityPending()) { 933 finishHandleDiscontinuity(true /* flushOnTimeChange */); 934 } 935} 936 937bool NuPlayer::Decoder::isDiscontinuityPending() const { 938 return mFormatChangePending || mTimeChangePending; 939} 940 941void NuPlayer::Decoder::finishHandleDiscontinuity(bool flushOnTimeChange) { 942 ALOGV("finishHandleDiscontinuity: format %d, time %d, flush %d", 943 mFormatChangePending, mTimeChangePending, flushOnTimeChange); 944 945 // If we have format change, pause and wait to be killed; 946 // If we have time change only, flush and restart fetching. 947 948 if (mFormatChangePending) { 949 mPaused = true; 950 } else if (mTimeChangePending) { 951 if (flushOnTimeChange) { 952 doFlush(false /* notifyComplete */); 953 signalResume(false /* notifyComplete */); 954 } 955 } 956 957 // Notify NuPlayer to either shutdown decoder, or rescan sources 958 sp<AMessage> msg = mNotify->dup(); 959 msg->setInt32("what", kWhatInputDiscontinuity); 960 msg->setInt32("formatChange", mFormatChangePending); 961 msg->post(); 962 963 mFormatChangePending = false; 964 mTimeChangePending = false; 965} 966 967bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange( 968 const sp<AMessage> &targetFormat) const { 969 if (targetFormat == NULL) { 970 return true; 971 } 972 973 AString mime; 974 if (!targetFormat->findString("mime", &mime)) { 975 return false; 976 } 977 978 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) { 979 // field-by-field comparison 980 const char * keys[] = { "channel-count", "sample-rate", "is-adts" }; 981 for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) { 982 int32_t oldVal, newVal; 983 if (!mInputFormat->findInt32(keys[i], &oldVal) || 984 !targetFormat->findInt32(keys[i], &newVal) || 985 oldVal != newVal) { 986 return false; 987 } 988 } 989 990 sp<ABuffer> oldBuf, newBuf; 991 if (mInputFormat->findBuffer("csd-0", &oldBuf) && 992 targetFormat->findBuffer("csd-0", &newBuf)) { 993 if (oldBuf->size() != newBuf->size()) { 994 return false; 995 } 996 return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size()); 997 } 998 } 999 return false; 1000} 1001 1002bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const { 1003 if (mInputFormat == NULL) { 1004 return false; 1005 } 1006 1007 if (targetFormat == NULL) { 1008 return true; 1009 } 1010 1011 AString oldMime, newMime; 1012 if (!mInputFormat->findString("mime", &oldMime) 1013 || !targetFormat->findString("mime", &newMime) 1014 || !(oldMime == newMime)) { 1015 return false; 1016 } 1017 1018 bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/")); 1019 bool seamless; 1020 if (audio) { 1021 seamless = supportsSeamlessAudioFormatChange(targetFormat); 1022 } else { 1023 int32_t isAdaptive; 1024 seamless = (mCodec != NULL && 1025 mInputFormat->findInt32("adaptive-playback", &isAdaptive) && 1026 isAdaptive); 1027 } 1028 1029 ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str()); 1030 return seamless; 1031} 1032 1033void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) { 1034 if (format == NULL) { 1035 return; 1036 } 1037 mCSDsForCurrentFormat.clear(); 1038 for (int32_t i = 0; ; ++i) { 1039 AString tag = "csd-"; 1040 tag.append(i); 1041 sp<ABuffer> buffer; 1042 if (!format->findBuffer(tag.c_str(), &buffer)) { 1043 break; 1044 } 1045 mCSDsForCurrentFormat.push(buffer); 1046 } 1047} 1048 1049void NuPlayer::Decoder::notifyResumeCompleteIfNecessary() { 1050 if (mResumePending) { 1051 mResumePending = false; 1052 1053 sp<AMessage> notify = mNotify->dup(); 1054 notify->setInt32("what", kWhatResumeCompleted); 1055 notify->post(); 1056 } 1057} 1058 1059} // namespace android 1060 1061