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