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