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