NuPlayerDecoder.cpp revision e6109e2f10b43c2cc2561c6fd6633b5f988bd7a9
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 if (mPaused) { 86 break; 87 } 88 89 int32_t cbID; 90 CHECK(msg->findInt32("callbackID", &cbID)); 91 92 ALOGV("kWhatCodecNotify: cbID = %d", cbID); 93 switch (cbID) { 94 case MediaCodec::CB_INPUT_AVAILABLE: 95 { 96 int32_t index; 97 CHECK(msg->findInt32("index", &index)); 98 99 handleAnInputBuffer(index); 100 break; 101 } 102 103 case MediaCodec::CB_OUTPUT_AVAILABLE: 104 { 105 int32_t index; 106 size_t offset; 107 size_t size; 108 int64_t timeUs; 109 int32_t flags; 110 111 CHECK(msg->findInt32("index", &index)); 112 CHECK(msg->findSize("offset", &offset)); 113 CHECK(msg->findSize("size", &size)); 114 CHECK(msg->findInt64("timeUs", &timeUs)); 115 CHECK(msg->findInt32("flags", &flags)); 116 117 handleAnOutputBuffer(index, offset, size, timeUs, flags); 118 break; 119 } 120 121 case MediaCodec::CB_OUTPUT_FORMAT_CHANGED: 122 { 123 sp<AMessage> format; 124 CHECK(msg->findMessage("format", &format)); 125 126 handleOutputFormatChange(format); 127 break; 128 } 129 130 case MediaCodec::CB_ERROR: 131 { 132 status_t err; 133 CHECK(msg->findInt32("err", &err)); 134 ALOGE("Decoder (%s) reported error : 0x%x", 135 mIsAudio ? "audio" : "video", err); 136 137 handleError(err); 138 break; 139 } 140 141 default: 142 { 143 TRESPASS(); 144 break; 145 } 146 } 147 148 break; 149 } 150 151 case kWhatRenderBuffer: 152 { 153 if (!isStaleReply(msg)) { 154 onRenderBuffer(msg); 155 } 156 break; 157 } 158 159 default: 160 DecoderBase::onMessageReceived(msg); 161 break; 162 } 163} 164 165void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) { 166 CHECK(mCodec == NULL); 167 168 mFormatChangePending = false; 169 mTimeChangePending = false; 170 171 ++mBufferGeneration; 172 173 AString mime; 174 CHECK(format->findString("mime", &mime)); 175 176 mIsAudio = !strncasecmp("audio/", mime.c_str(), 6); 177 mIsVideoAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str()); 178 179 sp<Surface> surface = NULL; 180 if (mNativeWindow != NULL) { 181 surface = mNativeWindow->getSurfaceTextureClient(); 182 } 183 184 mComponentName = mime; 185 mComponentName.append(" decoder"); 186 ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), surface.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 (mNativeWindow != NULL) { 212 // disconnect from surface as MediaCodec will reconnect 213 err = native_window_api_disconnect( 214 surface.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, surface, 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::onSetRenderer(const sp<Renderer> &renderer) { 254 bool hadNoRenderer = (mRenderer == NULL); 255 mRenderer = renderer; 256 if (hadNoRenderer && mRenderer != NULL) { 257 // this means that the widevine legacy source is ready 258 onRequestInputBuffers(); 259 } 260} 261 262void NuPlayer::Decoder::onGetInputBuffers( 263 Vector<sp<ABuffer> > *dstBuffers) { 264 CHECK_EQ((status_t)OK, mCodec->getWidevineLegacyBuffers(dstBuffers)); 265} 266 267void NuPlayer::Decoder::onResume(bool notifyComplete) { 268 mPaused = false; 269 270 if (notifyComplete) { 271 mResumePending = true; 272 } 273 mCodec->start(); 274} 275 276void NuPlayer::Decoder::doFlush(bool notifyComplete) { 277 if (mCCDecoder != NULL) { 278 mCCDecoder->flush(); 279 } 280 281 if (mRenderer != NULL) { 282 mRenderer->flush(mIsAudio, notifyComplete); 283 mRenderer->signalTimeDiscontinuity(); 284 } 285 286 status_t err = OK; 287 if (mCodec != NULL) { 288 err = mCodec->flush(); 289 mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator 290 ++mBufferGeneration; 291 } 292 293 if (err != OK) { 294 ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err); 295 handleError(err); 296 // finish with posting kWhatFlushCompleted. 297 // we attempt to release the buffers even if flush fails. 298 } 299 releaseAndResetMediaBuffers(); 300 mPaused = true; 301} 302 303 304void NuPlayer::Decoder::onFlush() { 305 doFlush(true); 306 307 if (isDiscontinuityPending()) { 308 // This could happen if the client starts seeking/shutdown 309 // after we queued an EOS for discontinuities. 310 // We can consider discontinuity handled. 311 finishHandleDiscontinuity(false /* flushOnTimeChange */); 312 } 313 314 sp<AMessage> notify = mNotify->dup(); 315 notify->setInt32("what", kWhatFlushCompleted); 316 notify->post(); 317} 318 319void NuPlayer::Decoder::onShutdown(bool notifyComplete) { 320 status_t err = OK; 321 322 // if there is a pending resume request, notify complete now 323 notifyResumeCompleteIfNecessary(); 324 325 if (mCodec != NULL) { 326 err = mCodec->release(); 327 mCodec = NULL; 328 ++mBufferGeneration; 329 330 if (mNativeWindow != NULL) { 331 // reconnect to surface as MediaCodec disconnected from it 332 status_t error = 333 native_window_api_connect( 334 mNativeWindow->getNativeWindow().get(), 335 NATIVE_WINDOW_API_MEDIA); 336 ALOGW_IF(error != NO_ERROR, 337 "[%s] failed to connect to native window, error=%d", 338 mComponentName.c_str(), error); 339 } 340 mComponentName = "decoder"; 341 } 342 343 releaseAndResetMediaBuffers(); 344 345 if (err != OK) { 346 ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err); 347 handleError(err); 348 // finish with posting kWhatShutdownCompleted. 349 } 350 351 if (notifyComplete) { 352 sp<AMessage> notify = mNotify->dup(); 353 notify->setInt32("what", kWhatShutdownCompleted); 354 notify->post(); 355 mPaused = true; 356 } 357} 358 359void NuPlayer::Decoder::doRequestBuffers() { 360 // mRenderer is only NULL if we have a legacy widevine source that 361 // is not yet ready. In this case we must not fetch input. 362 if (isDiscontinuityPending() || mRenderer == NULL) { 363 return; 364 } 365 status_t err = OK; 366 while (err == OK && !mDequeuedInputBuffers.empty()) { 367 size_t bufferIx = *mDequeuedInputBuffers.begin(); 368 sp<AMessage> msg = new AMessage(); 369 msg->setSize("buffer-ix", bufferIx); 370 err = fetchInputData(msg); 371 if (err != OK && err != ERROR_END_OF_STREAM) { 372 // if EOS, need to queue EOS buffer 373 break; 374 } 375 mDequeuedInputBuffers.erase(mDequeuedInputBuffers.begin()); 376 377 if (!mPendingInputMessages.empty() 378 || !onInputBufferFetched(msg)) { 379 mPendingInputMessages.push_back(msg); 380 } 381 } 382 383 if (err == -EWOULDBLOCK 384 && mSource->feedMoreTSData() == OK) { 385 scheduleRequestBuffers(); 386 } 387} 388 389void NuPlayer::Decoder::handleError(int32_t err) 390{ 391 // We cannot immediately release the codec due to buffers still outstanding 392 // in the renderer. We signal to the player the error so it can shutdown/release the 393 // decoder after flushing and increment the generation to discard unnecessary messages. 394 395 ++mBufferGeneration; 396 397 sp<AMessage> notify = mNotify->dup(); 398 notify->setInt32("what", kWhatError); 399 notify->setInt32("err", err); 400 notify->post(); 401} 402 403bool NuPlayer::Decoder::handleAnInputBuffer(size_t index) { 404 if (isDiscontinuityPending()) { 405 return false; 406 } 407 408 sp<ABuffer> buffer; 409 mCodec->getInputBuffer(index, &buffer); 410 411 if (index >= mInputBuffers.size()) { 412 for (size_t i = mInputBuffers.size(); i <= index; ++i) { 413 mInputBuffers.add(); 414 mMediaBuffers.add(); 415 mInputBufferIsDequeued.add(); 416 mMediaBuffers.editItemAt(i) = NULL; 417 mInputBufferIsDequeued.editItemAt(i) = false; 418 } 419 } 420 mInputBuffers.editItemAt(index) = buffer; 421 422 //CHECK_LT(bufferIx, mInputBuffers.size()); 423 424 if (mMediaBuffers[index] != NULL) { 425 mMediaBuffers[index]->release(); 426 mMediaBuffers.editItemAt(index) = NULL; 427 } 428 mInputBufferIsDequeued.editItemAt(index) = true; 429 430 if (!mCSDsToSubmit.isEmpty()) { 431 sp<AMessage> msg = new AMessage(); 432 msg->setSize("buffer-ix", index); 433 434 sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0); 435 ALOGI("[%s] resubmitting CSD", mComponentName.c_str()); 436 msg->setBuffer("buffer", buffer); 437 mCSDsToSubmit.removeAt(0); 438 CHECK(onInputBufferFetched(msg)); 439 return true; 440 } 441 442 while (!mPendingInputMessages.empty()) { 443 sp<AMessage> msg = *mPendingInputMessages.begin(); 444 if (!onInputBufferFetched(msg)) { 445 break; 446 } 447 mPendingInputMessages.erase(mPendingInputMessages.begin()); 448 } 449 450 if (!mInputBufferIsDequeued.editItemAt(index)) { 451 return true; 452 } 453 454 mDequeuedInputBuffers.push_back(index); 455 456 onRequestInputBuffers(); 457 return true; 458} 459 460bool NuPlayer::Decoder::handleAnOutputBuffer( 461 size_t index, 462 size_t offset, 463 size_t size, 464 int64_t timeUs, 465 int32_t flags) { 466 if (mFormatChangePending) { 467 return false; 468 } 469 470// CHECK_LT(bufferIx, mOutputBuffers.size()); 471 sp<ABuffer> buffer; 472 mCodec->getOutputBuffer(index, &buffer); 473 474 if (index >= mOutputBuffers.size()) { 475 for (size_t i = mOutputBuffers.size(); i <= index; ++i) { 476 mOutputBuffers.add(); 477 } 478 } 479 480 mOutputBuffers.editItemAt(index) = buffer; 481 482 buffer->setRange(offset, size); 483 buffer->meta()->clear(); 484 buffer->meta()->setInt64("timeUs", timeUs); 485 486 bool eos = flags & MediaCodec::BUFFER_FLAG_EOS; 487 // we do not expect CODECCONFIG or SYNCFRAME for decoder 488 489 sp<AMessage> reply = new AMessage(kWhatRenderBuffer, this); 490 reply->setSize("buffer-ix", index); 491 reply->setInt32("generation", mBufferGeneration); 492 493 if (eos) { 494 ALOGI("[%s] saw output EOS", mIsAudio ? "audio" : "video"); 495 496 buffer->meta()->setInt32("eos", true); 497 reply->setInt32("eos", true); 498 } else if (mSkipRenderingUntilMediaTimeUs >= 0) { 499 if (timeUs < mSkipRenderingUntilMediaTimeUs) { 500 ALOGV("[%s] dropping buffer at time %lld as requested.", 501 mComponentName.c_str(), (long long)timeUs); 502 503 reply->post(); 504 return true; 505 } 506 507 mSkipRenderingUntilMediaTimeUs = -1; 508 } 509 510 // wait until 1st frame comes out to signal resume complete 511 notifyResumeCompleteIfNecessary(); 512 513 if (mRenderer != NULL) { 514 // send the buffer to renderer. 515 mRenderer->queueBuffer(mIsAudio, buffer, reply); 516 if (eos && !isDiscontinuityPending()) { 517 mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM); 518 } 519 } 520 521 return true; 522} 523 524void NuPlayer::Decoder::handleOutputFormatChange(const sp<AMessage> &format) { 525 if (!mIsAudio) { 526 sp<AMessage> notify = mNotify->dup(); 527 notify->setInt32("what", kWhatVideoSizeChanged); 528 notify->setMessage("format", format); 529 notify->post(); 530 } else if (mRenderer != NULL) { 531 uint32_t flags; 532 int64_t durationUs; 533 bool hasVideo = (mSource->getFormat(false /* audio */) != NULL); 534 if (!hasVideo && 535 mSource->getDuration(&durationUs) == OK && 536 durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) { 537 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; 538 } else { 539 flags = AUDIO_OUTPUT_FLAG_NONE; 540 } 541 542 mRenderer->openAudioSink( 543 format, false /* offloadOnly */, hasVideo, flags, NULL /* isOffloaed */); 544 } 545} 546 547void NuPlayer::Decoder::releaseAndResetMediaBuffers() { 548 for (size_t i = 0; i < mMediaBuffers.size(); i++) { 549 if (mMediaBuffers[i] != NULL) { 550 mMediaBuffers[i]->release(); 551 mMediaBuffers.editItemAt(i) = NULL; 552 } 553 } 554 mMediaBuffers.resize(mInputBuffers.size()); 555 for (size_t i = 0; i < mMediaBuffers.size(); i++) { 556 mMediaBuffers.editItemAt(i) = NULL; 557 } 558 mInputBufferIsDequeued.clear(); 559 mInputBufferIsDequeued.resize(mInputBuffers.size()); 560 for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) { 561 mInputBufferIsDequeued.editItemAt(i) = false; 562 } 563 564 mPendingInputMessages.clear(); 565 mDequeuedInputBuffers.clear(); 566 mSkipRenderingUntilMediaTimeUs = -1; 567} 568 569void NuPlayer::Decoder::requestCodecNotification() { 570 if (mCodec != NULL) { 571 sp<AMessage> reply = new AMessage(kWhatCodecNotify, this); 572 reply->setInt32("generation", mBufferGeneration); 573 mCodec->requestActivityNotification(reply); 574 } 575} 576 577bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) { 578 int32_t generation; 579 CHECK(msg->findInt32("generation", &generation)); 580 return generation != mBufferGeneration; 581} 582 583status_t NuPlayer::Decoder::fetchInputData(sp<AMessage> &reply) { 584 sp<ABuffer> accessUnit; 585 bool dropAccessUnit; 586 do { 587 status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit); 588 589 if (err == -EWOULDBLOCK) { 590 return err; 591 } else if (err != OK) { 592 if (err == INFO_DISCONTINUITY) { 593 int32_t type; 594 CHECK(accessUnit->meta()->findInt32("discontinuity", &type)); 595 596 bool formatChange = 597 (mIsAudio && 598 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT)) 599 || (!mIsAudio && 600 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT)); 601 602 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0; 603 604 ALOGI("%s discontinuity (format=%d, time=%d)", 605 mIsAudio ? "audio" : "video", formatChange, timeChange); 606 607 bool seamlessFormatChange = false; 608 sp<AMessage> newFormat = mSource->getFormat(mIsAudio); 609 if (formatChange) { 610 seamlessFormatChange = 611 supportsSeamlessFormatChange(newFormat); 612 // treat seamless format change separately 613 formatChange = !seamlessFormatChange; 614 } 615 616 // For format or time change, return EOS to queue EOS input, 617 // then wait for EOS on output. 618 if (formatChange /* not seamless */) { 619 mFormatChangePending = true; 620 err = ERROR_END_OF_STREAM; 621 } else if (timeChange) { 622 rememberCodecSpecificData(newFormat); 623 mTimeChangePending = true; 624 err = ERROR_END_OF_STREAM; 625 } else if (seamlessFormatChange) { 626 // reuse existing decoder and don't flush 627 rememberCodecSpecificData(newFormat); 628 continue; 629 } else { 630 // This stream is unaffected by the discontinuity 631 return -EWOULDBLOCK; 632 } 633 } 634 635 // reply should only be returned without a buffer set 636 // when there is an error (including EOS) 637 CHECK(err != OK); 638 639 reply->setInt32("err", err); 640 return ERROR_END_OF_STREAM; 641 } 642 643 if (!mIsAudio) { 644 ++mNumFramesTotal; 645 } 646 647 dropAccessUnit = false; 648 if (!mIsAudio 649 && !mIsSecure 650 && mRenderer->getVideoLateByUs() > 100000ll 651 && mIsVideoAVC 652 && !IsAVCReferenceFrame(accessUnit)) { 653 dropAccessUnit = true; 654 ++mNumFramesDropped; 655 } 656 } while (dropAccessUnit); 657 658 // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video"); 659#if 0 660 int64_t mediaTimeUs; 661 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs)); 662 ALOGV("[%s] feeding input buffer at media time %" PRId64, 663 mIsAudio ? "audio" : "video", 664 mediaTimeUs / 1E6); 665#endif 666 667 if (mCCDecoder != NULL) { 668 mCCDecoder->decode(accessUnit); 669 } 670 671 reply->setBuffer("buffer", accessUnit); 672 673 return OK; 674} 675 676bool NuPlayer::Decoder::onInputBufferFetched(const sp<AMessage> &msg) { 677 size_t bufferIx; 678 CHECK(msg->findSize("buffer-ix", &bufferIx)); 679 CHECK_LT(bufferIx, mInputBuffers.size()); 680 sp<ABuffer> codecBuffer = mInputBuffers[bufferIx]; 681 682 sp<ABuffer> buffer; 683 bool hasBuffer = msg->findBuffer("buffer", &buffer); 684 685 // handle widevine classic source - that fills an arbitrary input buffer 686 MediaBuffer *mediaBuffer = NULL; 687 if (hasBuffer) { 688 mediaBuffer = (MediaBuffer *)(buffer->getMediaBufferBase()); 689 if (mediaBuffer != NULL) { 690 // likely filled another buffer than we requested: adjust buffer index 691 size_t ix; 692 for (ix = 0; ix < mInputBuffers.size(); ix++) { 693 const sp<ABuffer> &buf = mInputBuffers[ix]; 694 if (buf->data() == mediaBuffer->data()) { 695 // all input buffers are dequeued on start, hence the check 696 if (!mInputBufferIsDequeued[ix]) { 697 ALOGV("[%s] received MediaBuffer for #%zu instead of #%zu", 698 mComponentName.c_str(), ix, bufferIx); 699 mediaBuffer->release(); 700 return false; 701 } 702 703 // TRICKY: need buffer for the metadata, so instead, set 704 // codecBuffer to the same (though incorrect) buffer to 705 // avoid a memcpy into the codecBuffer 706 codecBuffer = buffer; 707 codecBuffer->setRange( 708 mediaBuffer->range_offset(), 709 mediaBuffer->range_length()); 710 bufferIx = ix; 711 break; 712 } 713 } 714 CHECK(ix < mInputBuffers.size()); 715 } 716 } 717 718 if (buffer == NULL /* includes !hasBuffer */) { 719 int32_t streamErr = ERROR_END_OF_STREAM; 720 CHECK(msg->findInt32("err", &streamErr) || !hasBuffer); 721 722 CHECK(streamErr != OK); 723 724 // attempt to queue EOS 725 status_t err = mCodec->queueInputBuffer( 726 bufferIx, 727 0, 728 0, 729 0, 730 MediaCodec::BUFFER_FLAG_EOS); 731 if (err == OK) { 732 mInputBufferIsDequeued.editItemAt(bufferIx) = false; 733 } else if (streamErr == ERROR_END_OF_STREAM) { 734 streamErr = err; 735 // err will not be ERROR_END_OF_STREAM 736 } 737 738 if (streamErr != ERROR_END_OF_STREAM) { 739 ALOGE("Stream error for %s (err=%d), EOS %s queued", 740 mComponentName.c_str(), 741 streamErr, 742 err == OK ? "successfully" : "unsuccessfully"); 743 handleError(streamErr); 744 } 745 } else { 746 sp<AMessage> extra; 747 if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) { 748 int64_t resumeAtMediaTimeUs; 749 if (extra->findInt64( 750 "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) { 751 ALOGI("[%s] suppressing rendering until %lld us", 752 mComponentName.c_str(), (long long)resumeAtMediaTimeUs); 753 mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs; 754 } 755 } 756 757 int64_t timeUs = 0; 758 uint32_t flags = 0; 759 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 760 761 int32_t eos, csd; 762 // we do not expect SYNCFRAME for decoder 763 if (buffer->meta()->findInt32("eos", &eos) && eos) { 764 flags |= MediaCodec::BUFFER_FLAG_EOS; 765 } else if (buffer->meta()->findInt32("csd", &csd) && csd) { 766 flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG; 767 } 768 769 // copy into codec buffer 770 if (buffer != codecBuffer) { 771 CHECK_LE(buffer->size(), codecBuffer->capacity()); 772 codecBuffer->setRange(0, buffer->size()); 773 memcpy(codecBuffer->data(), buffer->data(), buffer->size()); 774 } 775 776 status_t err = mCodec->queueInputBuffer( 777 bufferIx, 778 codecBuffer->offset(), 779 codecBuffer->size(), 780 timeUs, 781 flags); 782 if (err != OK) { 783 if (mediaBuffer != NULL) { 784 mediaBuffer->release(); 785 } 786 ALOGE("Failed to queue input buffer for %s (err=%d)", 787 mComponentName.c_str(), err); 788 handleError(err); 789 } else { 790 mInputBufferIsDequeued.editItemAt(bufferIx) = false; 791 if (mediaBuffer != NULL) { 792 CHECK(mMediaBuffers[bufferIx] == NULL); 793 mMediaBuffers.editItemAt(bufferIx) = mediaBuffer; 794 } 795 } 796 } 797 return true; 798} 799 800void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) { 801 status_t err; 802 int32_t render; 803 size_t bufferIx; 804 int32_t eos; 805 CHECK(msg->findSize("buffer-ix", &bufferIx)); 806 807 if (!mIsAudio) { 808 int64_t timeUs; 809 sp<ABuffer> buffer = mOutputBuffers[bufferIx]; 810 buffer->meta()->findInt64("timeUs", &timeUs); 811 812 if (mCCDecoder != NULL && mCCDecoder->isSelected()) { 813 mCCDecoder->display(timeUs); 814 } 815 } 816 817 if (msg->findInt32("render", &render) && render) { 818 int64_t timestampNs; 819 CHECK(msg->findInt64("timestampNs", ×tampNs)); 820 err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs); 821 } else { 822 err = mCodec->releaseOutputBuffer(bufferIx); 823 } 824 if (err != OK) { 825 ALOGE("failed to release output buffer for %s (err=%d)", 826 mComponentName.c_str(), err); 827 handleError(err); 828 } 829 if (msg->findInt32("eos", &eos) && eos 830 && isDiscontinuityPending()) { 831 finishHandleDiscontinuity(true /* flushOnTimeChange */); 832 } 833} 834 835bool NuPlayer::Decoder::isDiscontinuityPending() const { 836 return mFormatChangePending || mTimeChangePending; 837} 838 839void NuPlayer::Decoder::finishHandleDiscontinuity(bool flushOnTimeChange) { 840 ALOGV("finishHandleDiscontinuity: format %d, time %d, flush %d", 841 mFormatChangePending, mTimeChangePending, flushOnTimeChange); 842 843 // If we have format change, pause and wait to be killed; 844 // If we have time change only, flush and restart fetching. 845 846 if (mFormatChangePending) { 847 mPaused = true; 848 } else if (mTimeChangePending) { 849 if (flushOnTimeChange) { 850 doFlush(false /* notifyComplete */); 851 signalResume(false /* notifyComplete */); 852 } 853 854 // restart fetching input 855 scheduleRequestBuffers(); 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