NuPlayerDecoder.cpp revision 6301a5e94de3659b4e6e4910394861830f8ebfb7
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 releaseAndResetMediaBuffers(); 72} 73 74void NuPlayer::Decoder::getStats( 75 int64_t *numFramesTotal, 76 int64_t *numFramesDropped) const { 77 *numFramesTotal = mNumFramesTotal; 78 *numFramesDropped = mNumFramesDropped; 79} 80 81void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) { 82 ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str()); 83 84 switch (msg->what()) { 85 case kWhatCodecNotify: 86 { 87 int32_t cbID; 88 CHECK(msg->findInt32("callbackID", &cbID)); 89 90 ALOGV("[%s] kWhatCodecNotify: cbID = %d, paused = %d", 91 mIsAudio ? "audio" : "video", cbID, mPaused); 92 93 if (mPaused) { 94 break; 95 } 96 97 switch (cbID) { 98 case MediaCodec::CB_INPUT_AVAILABLE: 99 { 100 int32_t index; 101 CHECK(msg->findInt32("index", &index)); 102 103 handleAnInputBuffer(index); 104 break; 105 } 106 107 case MediaCodec::CB_OUTPUT_AVAILABLE: 108 { 109 int32_t index; 110 size_t offset; 111 size_t size; 112 int64_t timeUs; 113 int32_t flags; 114 115 CHECK(msg->findInt32("index", &index)); 116 CHECK(msg->findSize("offset", &offset)); 117 CHECK(msg->findSize("size", &size)); 118 CHECK(msg->findInt64("timeUs", &timeUs)); 119 CHECK(msg->findInt32("flags", &flags)); 120 121 handleAnOutputBuffer(index, offset, size, timeUs, flags); 122 break; 123 } 124 125 case MediaCodec::CB_OUTPUT_FORMAT_CHANGED: 126 { 127 sp<AMessage> format; 128 CHECK(msg->findMessage("format", &format)); 129 130 handleOutputFormatChange(format); 131 break; 132 } 133 134 case MediaCodec::CB_ERROR: 135 { 136 status_t err; 137 CHECK(msg->findInt32("err", &err)); 138 ALOGE("Decoder (%s) reported error : 0x%x", 139 mIsAudio ? "audio" : "video", err); 140 141 handleError(err); 142 break; 143 } 144 145 default: 146 { 147 TRESPASS(); 148 break; 149 } 150 } 151 152 break; 153 } 154 155 case kWhatRenderBuffer: 156 { 157 if (!isStaleReply(msg)) { 158 onRenderBuffer(msg); 159 } 160 break; 161 } 162 163 default: 164 DecoderBase::onMessageReceived(msg); 165 break; 166 } 167} 168 169void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) { 170 CHECK(mCodec == NULL); 171 172 mFormatChangePending = false; 173 mTimeChangePending = false; 174 175 ++mBufferGeneration; 176 177 AString mime; 178 CHECK(format->findString("mime", &mime)); 179 180 mIsAudio = !strncasecmp("audio/", mime.c_str(), 6); 181 mIsVideoAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str()); 182 183 mComponentName = mime; 184 mComponentName.append(" decoder"); 185 ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), mSurface.get()); 186 187 mCodec = MediaCodec::CreateByType(mCodecLooper, mime.c_str(), false /* encoder */); 188 int32_t secure = 0; 189 if (format->findInt32("secure", &secure) && secure != 0) { 190 if (mCodec != NULL) { 191 mCodec->getName(&mComponentName); 192 mComponentName.append(".secure"); 193 mCodec->release(); 194 ALOGI("[%s] creating", mComponentName.c_str()); 195 mCodec = MediaCodec::CreateByComponentName( 196 mCodecLooper, mComponentName.c_str()); 197 } 198 } 199 if (mCodec == NULL) { 200 ALOGE("Failed to create %s%s decoder", 201 (secure ? "secure " : ""), mime.c_str()); 202 handleError(UNKNOWN_ERROR); 203 return; 204 } 205 mIsSecure = secure; 206 207 mCodec->getName(&mComponentName); 208 209 status_t err; 210 if (mSurface != NULL) { 211 // disconnect from surface as MediaCodec will reconnect 212 err = native_window_api_disconnect( 213 mSurface.get(), NATIVE_WINDOW_API_MEDIA); 214 // We treat this as a warning, as this is a preparatory step. 215 // Codec will try to connect to the surface, which is where 216 // any error signaling will occur. 217 ALOGW_IF(err != OK, "failed to disconnect from surface: %d", err); 218 } 219 err = mCodec->configure( 220 format, mSurface, NULL /* crypto */, 0 /* flags */); 221 if (err != OK) { 222 ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err); 223 mCodec->release(); 224 mCodec.clear(); 225 handleError(err); 226 return; 227 } 228 rememberCodecSpecificData(format); 229 230 // the following should work in configured state 231 CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat)); 232 CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat)); 233 234 sp<AMessage> reply = new AMessage(kWhatCodecNotify, this); 235 mCodec->setCallback(reply); 236 237 err = mCodec->start(); 238 if (err != OK) { 239 ALOGE("Failed to start %s decoder (err=%d)", mComponentName.c_str(), err); 240 mCodec->release(); 241 mCodec.clear(); 242 handleError(err); 243 return; 244 } 245 246 releaseAndResetMediaBuffers(); 247 248 mPaused = false; 249 mResumePending = false; 250} 251 252void NuPlayer::Decoder::onSetParameters(const sp<AMessage> ¶ms) { 253 if (mCodec == NULL) { 254 ALOGW("onSetParameters called before codec is created."); 255 return; 256 } 257 mCodec->setParameters(params); 258} 259 260void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) { 261 bool hadNoRenderer = (mRenderer == NULL); 262 mRenderer = renderer; 263 if (hadNoRenderer && mRenderer != NULL) { 264 // this means that the widevine legacy source is ready 265 onRequestInputBuffers(); 266 } 267} 268 269void NuPlayer::Decoder::onGetInputBuffers( 270 Vector<sp<ABuffer> > *dstBuffers) { 271 CHECK_EQ((status_t)OK, mCodec->getWidevineLegacyBuffers(dstBuffers)); 272} 273 274void NuPlayer::Decoder::onResume(bool notifyComplete) { 275 mPaused = false; 276 277 if (notifyComplete) { 278 mResumePending = true; 279 } 280 mCodec->start(); 281} 282 283void NuPlayer::Decoder::doFlush(bool notifyComplete) { 284 if (mCCDecoder != NULL) { 285 mCCDecoder->flush(); 286 } 287 288 if (mRenderer != NULL) { 289 mRenderer->flush(mIsAudio, notifyComplete); 290 mRenderer->signalTimeDiscontinuity(); 291 } 292 293 status_t err = OK; 294 if (mCodec != NULL) { 295 err = mCodec->flush(); 296 mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator 297 ++mBufferGeneration; 298 } 299 300 if (err != OK) { 301 ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err); 302 handleError(err); 303 // finish with posting kWhatFlushCompleted. 304 // we attempt to release the buffers even if flush fails. 305 } 306 releaseAndResetMediaBuffers(); 307 mPaused = true; 308} 309 310 311void NuPlayer::Decoder::onFlush() { 312 doFlush(true); 313 314 if (isDiscontinuityPending()) { 315 // This could happen if the client starts seeking/shutdown 316 // after we queued an EOS for discontinuities. 317 // We can consider discontinuity handled. 318 finishHandleDiscontinuity(false /* flushOnTimeChange */); 319 } 320 321 sp<AMessage> notify = mNotify->dup(); 322 notify->setInt32("what", kWhatFlushCompleted); 323 notify->post(); 324} 325 326void NuPlayer::Decoder::onShutdown(bool notifyComplete) { 327 status_t err = OK; 328 329 // if there is a pending resume request, notify complete now 330 notifyResumeCompleteIfNecessary(); 331 332 if (mCodec != NULL) { 333 err = mCodec->release(); 334 mCodec = NULL; 335 ++mBufferGeneration; 336 337 if (mSurface != NULL) { 338 // reconnect to surface as MediaCodec disconnected from it 339 status_t error = 340 native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_MEDIA); 341 ALOGW_IF(error != NO_ERROR, 342 "[%s] failed to connect to native window, error=%d", 343 mComponentName.c_str(), error); 344 } 345 mComponentName = "decoder"; 346 } 347 348 releaseAndResetMediaBuffers(); 349 350 if (err != OK) { 351 ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err); 352 handleError(err); 353 // finish with posting kWhatShutdownCompleted. 354 } 355 356 if (notifyComplete) { 357 sp<AMessage> notify = mNotify->dup(); 358 notify->setInt32("what", kWhatShutdownCompleted); 359 notify->post(); 360 mPaused = true; 361 } 362} 363 364/* 365 * returns true if we should request more data 366 */ 367bool NuPlayer::Decoder::doRequestBuffers() { 368 // mRenderer is only NULL if we have a legacy widevine source that 369 // is not yet ready. In this case we must not fetch input. 370 if (isDiscontinuityPending() || mRenderer == NULL) { 371 return false; 372 } 373 status_t err = OK; 374 while (err == OK && !mDequeuedInputBuffers.empty()) { 375 size_t bufferIx = *mDequeuedInputBuffers.begin(); 376 sp<AMessage> msg = new AMessage(); 377 msg->setSize("buffer-ix", bufferIx); 378 err = fetchInputData(msg); 379 if (err != OK && err != ERROR_END_OF_STREAM) { 380 // if EOS, need to queue EOS buffer 381 break; 382 } 383 mDequeuedInputBuffers.erase(mDequeuedInputBuffers.begin()); 384 385 if (!mPendingInputMessages.empty() 386 || !onInputBufferFetched(msg)) { 387 mPendingInputMessages.push_back(msg); 388 } 389 } 390 391 return err == -EWOULDBLOCK 392 && mSource->feedMoreTSData() == OK; 393} 394 395void NuPlayer::Decoder::handleError(int32_t err) 396{ 397 // We cannot immediately release the codec due to buffers still outstanding 398 // in the renderer. We signal to the player the error so it can shutdown/release the 399 // decoder after flushing and increment the generation to discard unnecessary messages. 400 401 ++mBufferGeneration; 402 403 sp<AMessage> notify = mNotify->dup(); 404 notify->setInt32("what", kWhatError); 405 notify->setInt32("err", err); 406 notify->post(); 407} 408 409bool NuPlayer::Decoder::handleAnInputBuffer(size_t index) { 410 if (isDiscontinuityPending()) { 411 return false; 412 } 413 414 sp<ABuffer> buffer; 415 mCodec->getInputBuffer(index, &buffer); 416 417 if (buffer == NULL) { 418 handleError(UNKNOWN_ERROR); 419 return false; 420 } 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