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