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