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