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