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