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