NuPlayerDecoder.cpp revision 1de1e25cba872bd4c077c2e394f8ca9c70b65856
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 (index >= mInputBuffers.size()) { 418 for (size_t i = mInputBuffers.size(); i <= index; ++i) { 419 mInputBuffers.add(); 420 mMediaBuffers.add(); 421 mInputBufferIsDequeued.add(); 422 mMediaBuffers.editItemAt(i) = NULL; 423 mInputBufferIsDequeued.editItemAt(i) = false; 424 } 425 } 426 mInputBuffers.editItemAt(index) = buffer; 427 428 //CHECK_LT(bufferIx, mInputBuffers.size()); 429 430 if (mMediaBuffers[index] != NULL) { 431 mMediaBuffers[index]->release(); 432 mMediaBuffers.editItemAt(index) = NULL; 433 } 434 mInputBufferIsDequeued.editItemAt(index) = true; 435 436 if (!mCSDsToSubmit.isEmpty()) { 437 sp<AMessage> msg = new AMessage(); 438 msg->setSize("buffer-ix", index); 439 440 sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0); 441 ALOGI("[%s] resubmitting CSD", mComponentName.c_str()); 442 msg->setBuffer("buffer", buffer); 443 mCSDsToSubmit.removeAt(0); 444 CHECK(onInputBufferFetched(msg)); 445 return true; 446 } 447 448 while (!mPendingInputMessages.empty()) { 449 sp<AMessage> msg = *mPendingInputMessages.begin(); 450 if (!onInputBufferFetched(msg)) { 451 break; 452 } 453 mPendingInputMessages.erase(mPendingInputMessages.begin()); 454 } 455 456 if (!mInputBufferIsDequeued.editItemAt(index)) { 457 return true; 458 } 459 460 mDequeuedInputBuffers.push_back(index); 461 462 onRequestInputBuffers(); 463 return true; 464} 465 466bool NuPlayer::Decoder::handleAnOutputBuffer( 467 size_t index, 468 size_t offset, 469 size_t size, 470 int64_t timeUs, 471 int32_t flags) { 472// CHECK_LT(bufferIx, mOutputBuffers.size()); 473 sp<ABuffer> buffer; 474 mCodec->getOutputBuffer(index, &buffer); 475 476 if (index >= mOutputBuffers.size()) { 477 for (size_t i = mOutputBuffers.size(); i <= index; ++i) { 478 mOutputBuffers.add(); 479 } 480 } 481 482 mOutputBuffers.editItemAt(index) = buffer; 483 484 buffer->setRange(offset, size); 485 buffer->meta()->clear(); 486 buffer->meta()->setInt64("timeUs", timeUs); 487 488 bool eos = flags & MediaCodec::BUFFER_FLAG_EOS; 489 // we do not expect CODECCONFIG or SYNCFRAME for decoder 490 491 sp<AMessage> reply = new AMessage(kWhatRenderBuffer, this); 492 reply->setSize("buffer-ix", index); 493 reply->setInt32("generation", mBufferGeneration); 494 495 if (eos) { 496 ALOGI("[%s] saw output EOS", mIsAudio ? "audio" : "video"); 497 498 buffer->meta()->setInt32("eos", true); 499 reply->setInt32("eos", true); 500 } else if (mSkipRenderingUntilMediaTimeUs >= 0) { 501 if (timeUs < mSkipRenderingUntilMediaTimeUs) { 502 ALOGV("[%s] dropping buffer at time %lld as requested.", 503 mComponentName.c_str(), (long long)timeUs); 504 505 reply->post(); 506 return true; 507 } 508 509 mSkipRenderingUntilMediaTimeUs = -1; 510 } 511 512 // wait until 1st frame comes out to signal resume complete 513 notifyResumeCompleteIfNecessary(); 514 515 if (mRenderer != NULL) { 516 // send the buffer to renderer. 517 mRenderer->queueBuffer(mIsAudio, buffer, reply); 518 if (eos && !isDiscontinuityPending()) { 519 mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM); 520 } 521 } 522 523 return true; 524} 525 526void NuPlayer::Decoder::handleOutputFormatChange(const sp<AMessage> &format) { 527 if (!mIsAudio) { 528 sp<AMessage> notify = mNotify->dup(); 529 notify->setInt32("what", kWhatVideoSizeChanged); 530 notify->setMessage("format", format); 531 notify->post(); 532 } else if (mRenderer != NULL) { 533 uint32_t flags; 534 int64_t durationUs; 535 bool hasVideo = (mSource->getFormat(false /* audio */) != NULL); 536 if (!hasVideo && 537 mSource->getDuration(&durationUs) == OK && 538 durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) { 539 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; 540 } else { 541 flags = AUDIO_OUTPUT_FLAG_NONE; 542 } 543 544 mRenderer->openAudioSink( 545 format, false /* offloadOnly */, hasVideo, flags, NULL /* isOffloaed */); 546 } 547} 548 549void NuPlayer::Decoder::releaseAndResetMediaBuffers() { 550 for (size_t i = 0; i < mMediaBuffers.size(); i++) { 551 if (mMediaBuffers[i] != NULL) { 552 mMediaBuffers[i]->release(); 553 mMediaBuffers.editItemAt(i) = NULL; 554 } 555 } 556 mMediaBuffers.resize(mInputBuffers.size()); 557 for (size_t i = 0; i < mMediaBuffers.size(); i++) { 558 mMediaBuffers.editItemAt(i) = NULL; 559 } 560 mInputBufferIsDequeued.clear(); 561 mInputBufferIsDequeued.resize(mInputBuffers.size()); 562 for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) { 563 mInputBufferIsDequeued.editItemAt(i) = false; 564 } 565 566 mPendingInputMessages.clear(); 567 mDequeuedInputBuffers.clear(); 568 mSkipRenderingUntilMediaTimeUs = -1; 569} 570 571void NuPlayer::Decoder::requestCodecNotification() { 572 if (mCodec != NULL) { 573 sp<AMessage> reply = new AMessage(kWhatCodecNotify, this); 574 reply->setInt32("generation", mBufferGeneration); 575 mCodec->requestActivityNotification(reply); 576 } 577} 578 579bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) { 580 int32_t generation; 581 CHECK(msg->findInt32("generation", &generation)); 582 return generation != mBufferGeneration; 583} 584 585status_t NuPlayer::Decoder::fetchInputData(sp<AMessage> &reply) { 586 sp<ABuffer> accessUnit; 587 bool dropAccessUnit; 588 do { 589 status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit); 590 591 if (err == -EWOULDBLOCK) { 592 return err; 593 } else if (err != OK) { 594 if (err == INFO_DISCONTINUITY) { 595 int32_t type; 596 CHECK(accessUnit->meta()->findInt32("discontinuity", &type)); 597 598 bool formatChange = 599 (mIsAudio && 600 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT)) 601 || (!mIsAudio && 602 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT)); 603 604 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0; 605 606 ALOGI("%s discontinuity (format=%d, time=%d)", 607 mIsAudio ? "audio" : "video", formatChange, timeChange); 608 609 bool seamlessFormatChange = false; 610 sp<AMessage> newFormat = mSource->getFormat(mIsAudio); 611 if (formatChange) { 612 seamlessFormatChange = 613 supportsSeamlessFormatChange(newFormat); 614 // treat seamless format change separately 615 formatChange = !seamlessFormatChange; 616 } 617 618 // For format or time change, return EOS to queue EOS input, 619 // then wait for EOS on output. 620 if (formatChange /* not seamless */) { 621 mFormatChangePending = true; 622 err = ERROR_END_OF_STREAM; 623 } else if (timeChange) { 624 rememberCodecSpecificData(newFormat); 625 mTimeChangePending = true; 626 err = ERROR_END_OF_STREAM; 627 } else if (seamlessFormatChange) { 628 // reuse existing decoder and don't flush 629 rememberCodecSpecificData(newFormat); 630 continue; 631 } else { 632 // This stream is unaffected by the discontinuity 633 return -EWOULDBLOCK; 634 } 635 } 636 637 // reply should only be returned without a buffer set 638 // when there is an error (including EOS) 639 CHECK(err != OK); 640 641 reply->setInt32("err", err); 642 return ERROR_END_OF_STREAM; 643 } 644 645 if (!mIsAudio) { 646 ++mNumFramesTotal; 647 } 648 649 dropAccessUnit = false; 650 if (!mIsAudio 651 && !mIsSecure 652 && mRenderer->getVideoLateByUs() > 100000ll 653 && mIsVideoAVC 654 && !IsAVCReferenceFrame(accessUnit)) { 655 dropAccessUnit = true; 656 ++mNumFramesDropped; 657 } 658 } while (dropAccessUnit); 659 660 // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video"); 661#if 0 662 int64_t mediaTimeUs; 663 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs)); 664 ALOGV("[%s] feeding input buffer at media time %.3f", 665 mIsAudio ? "audio" : "video", 666 mediaTimeUs / 1E6); 667#endif 668 669 if (mCCDecoder != NULL) { 670 mCCDecoder->decode(accessUnit); 671 } 672 673 reply->setBuffer("buffer", accessUnit); 674 675 return OK; 676} 677 678bool NuPlayer::Decoder::onInputBufferFetched(const sp<AMessage> &msg) { 679 size_t bufferIx; 680 CHECK(msg->findSize("buffer-ix", &bufferIx)); 681 CHECK_LT(bufferIx, mInputBuffers.size()); 682 sp<ABuffer> codecBuffer = mInputBuffers[bufferIx]; 683 684 sp<ABuffer> buffer; 685 bool hasBuffer = msg->findBuffer("buffer", &buffer); 686 687 // handle widevine classic source - that fills an arbitrary input buffer 688 MediaBuffer *mediaBuffer = NULL; 689 if (hasBuffer) { 690 mediaBuffer = (MediaBuffer *)(buffer->getMediaBufferBase()); 691 if (mediaBuffer != NULL) { 692 // likely filled another buffer than we requested: adjust buffer index 693 size_t ix; 694 for (ix = 0; ix < mInputBuffers.size(); ix++) { 695 const sp<ABuffer> &buf = mInputBuffers[ix]; 696 if (buf->data() == mediaBuffer->data()) { 697 // all input buffers are dequeued on start, hence the check 698 if (!mInputBufferIsDequeued[ix]) { 699 ALOGV("[%s] received MediaBuffer for #%zu instead of #%zu", 700 mComponentName.c_str(), ix, bufferIx); 701 mediaBuffer->release(); 702 return false; 703 } 704 705 // TRICKY: need buffer for the metadata, so instead, set 706 // codecBuffer to the same (though incorrect) buffer to 707 // avoid a memcpy into the codecBuffer 708 codecBuffer = buffer; 709 codecBuffer->setRange( 710 mediaBuffer->range_offset(), 711 mediaBuffer->range_length()); 712 bufferIx = ix; 713 break; 714 } 715 } 716 CHECK(ix < mInputBuffers.size()); 717 } 718 } 719 720 if (buffer == NULL /* includes !hasBuffer */) { 721 int32_t streamErr = ERROR_END_OF_STREAM; 722 CHECK(msg->findInt32("err", &streamErr) || !hasBuffer); 723 724 CHECK(streamErr != OK); 725 726 // attempt to queue EOS 727 status_t err = mCodec->queueInputBuffer( 728 bufferIx, 729 0, 730 0, 731 0, 732 MediaCodec::BUFFER_FLAG_EOS); 733 if (err == OK) { 734 mInputBufferIsDequeued.editItemAt(bufferIx) = false; 735 } else if (streamErr == ERROR_END_OF_STREAM) { 736 streamErr = err; 737 // err will not be ERROR_END_OF_STREAM 738 } 739 740 if (streamErr != ERROR_END_OF_STREAM) { 741 ALOGE("Stream error for %s (err=%d), EOS %s queued", 742 mComponentName.c_str(), 743 streamErr, 744 err == OK ? "successfully" : "unsuccessfully"); 745 handleError(streamErr); 746 } 747 } else { 748 sp<AMessage> extra; 749 if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) { 750 int64_t resumeAtMediaTimeUs; 751 if (extra->findInt64( 752 "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) { 753 ALOGI("[%s] suppressing rendering until %lld us", 754 mComponentName.c_str(), (long long)resumeAtMediaTimeUs); 755 mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs; 756 } 757 } 758 759 int64_t timeUs = 0; 760 uint32_t flags = 0; 761 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 762 763 int32_t eos, csd; 764 // we do not expect SYNCFRAME for decoder 765 if (buffer->meta()->findInt32("eos", &eos) && eos) { 766 flags |= MediaCodec::BUFFER_FLAG_EOS; 767 } else if (buffer->meta()->findInt32("csd", &csd) && csd) { 768 flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG; 769 } 770 771 // copy into codec buffer 772 if (buffer != codecBuffer) { 773 CHECK_LE(buffer->size(), codecBuffer->capacity()); 774 codecBuffer->setRange(0, buffer->size()); 775 memcpy(codecBuffer->data(), buffer->data(), buffer->size()); 776 } 777 778 status_t err = mCodec->queueInputBuffer( 779 bufferIx, 780 codecBuffer->offset(), 781 codecBuffer->size(), 782 timeUs, 783 flags); 784 if (err != OK) { 785 if (mediaBuffer != NULL) { 786 mediaBuffer->release(); 787 } 788 ALOGE("Failed to queue input buffer for %s (err=%d)", 789 mComponentName.c_str(), err); 790 handleError(err); 791 } else { 792 mInputBufferIsDequeued.editItemAt(bufferIx) = false; 793 if (mediaBuffer != NULL) { 794 CHECK(mMediaBuffers[bufferIx] == NULL); 795 mMediaBuffers.editItemAt(bufferIx) = mediaBuffer; 796 } 797 } 798 } 799 return true; 800} 801 802void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) { 803 status_t err; 804 int32_t render; 805 size_t bufferIx; 806 int32_t eos; 807 CHECK(msg->findSize("buffer-ix", &bufferIx)); 808 809 if (!mIsAudio) { 810 int64_t timeUs; 811 sp<ABuffer> buffer = mOutputBuffers[bufferIx]; 812 buffer->meta()->findInt64("timeUs", &timeUs); 813 814 if (mCCDecoder != NULL && mCCDecoder->isSelected()) { 815 mCCDecoder->display(timeUs); 816 } 817 } 818 819 if (msg->findInt32("render", &render) && render) { 820 int64_t timestampNs; 821 CHECK(msg->findInt64("timestampNs", ×tampNs)); 822 err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs); 823 } else { 824 err = mCodec->releaseOutputBuffer(bufferIx); 825 } 826 if (err != OK) { 827 ALOGE("failed to release output buffer for %s (err=%d)", 828 mComponentName.c_str(), err); 829 handleError(err); 830 } 831 if (msg->findInt32("eos", &eos) && eos 832 && isDiscontinuityPending()) { 833 finishHandleDiscontinuity(true /* flushOnTimeChange */); 834 } 835} 836 837bool NuPlayer::Decoder::isDiscontinuityPending() const { 838 return mFormatChangePending || mTimeChangePending; 839} 840 841void NuPlayer::Decoder::finishHandleDiscontinuity(bool flushOnTimeChange) { 842 ALOGV("finishHandleDiscontinuity: format %d, time %d, flush %d", 843 mFormatChangePending, mTimeChangePending, flushOnTimeChange); 844 845 // If we have format change, pause and wait to be killed; 846 // If we have time change only, flush and restart fetching. 847 848 if (mFormatChangePending) { 849 mPaused = true; 850 } else if (mTimeChangePending) { 851 if (flushOnTimeChange) { 852 doFlush(false /* notifyComplete */); 853 signalResume(false /* notifyComplete */); 854 } 855 } 856 857 // Notify NuPlayer to either shutdown decoder, or rescan sources 858 sp<AMessage> msg = mNotify->dup(); 859 msg->setInt32("what", kWhatInputDiscontinuity); 860 msg->setInt32("formatChange", mFormatChangePending); 861 msg->post(); 862 863 mFormatChangePending = false; 864 mTimeChangePending = false; 865} 866 867bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange( 868 const sp<AMessage> &targetFormat) const { 869 if (targetFormat == NULL) { 870 return true; 871 } 872 873 AString mime; 874 if (!targetFormat->findString("mime", &mime)) { 875 return false; 876 } 877 878 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) { 879 // field-by-field comparison 880 const char * keys[] = { "channel-count", "sample-rate", "is-adts" }; 881 for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) { 882 int32_t oldVal, newVal; 883 if (!mInputFormat->findInt32(keys[i], &oldVal) || 884 !targetFormat->findInt32(keys[i], &newVal) || 885 oldVal != newVal) { 886 return false; 887 } 888 } 889 890 sp<ABuffer> oldBuf, newBuf; 891 if (mInputFormat->findBuffer("csd-0", &oldBuf) && 892 targetFormat->findBuffer("csd-0", &newBuf)) { 893 if (oldBuf->size() != newBuf->size()) { 894 return false; 895 } 896 return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size()); 897 } 898 } 899 return false; 900} 901 902bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const { 903 if (mInputFormat == NULL) { 904 return false; 905 } 906 907 if (targetFormat == NULL) { 908 return true; 909 } 910 911 AString oldMime, newMime; 912 if (!mInputFormat->findString("mime", &oldMime) 913 || !targetFormat->findString("mime", &newMime) 914 || !(oldMime == newMime)) { 915 return false; 916 } 917 918 bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/")); 919 bool seamless; 920 if (audio) { 921 seamless = supportsSeamlessAudioFormatChange(targetFormat); 922 } else { 923 int32_t isAdaptive; 924 seamless = (mCodec != NULL && 925 mInputFormat->findInt32("adaptive-playback", &isAdaptive) && 926 isAdaptive); 927 } 928 929 ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str()); 930 return seamless; 931} 932 933void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) { 934 if (format == NULL) { 935 return; 936 } 937 mCSDsForCurrentFormat.clear(); 938 for (int32_t i = 0; ; ++i) { 939 AString tag = "csd-"; 940 tag.append(i); 941 sp<ABuffer> buffer; 942 if (!format->findBuffer(tag.c_str(), &buffer)) { 943 break; 944 } 945 mCSDsForCurrentFormat.push(buffer); 946 } 947} 948 949void NuPlayer::Decoder::notifyResumeCompleteIfNecessary() { 950 if (mResumePending) { 951 mResumePending = false; 952 953 sp<AMessage> notify = mNotify->dup(); 954 notify->setInt32("what", kWhatResumeCompleted); 955 notify->post(); 956 } 957} 958 959} // namespace android 960 961