NuPlayerDecoder.cpp revision c5eef08195a6f81c2ae8fe7d4c346f12b15944e5
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 notifyResumeCompleteIfNecessary(); 480 } 481 // we do not expect CODECCONFIG or SYNCFRAME for decoder 482 483 sp<AMessage> reply = new AMessage(kWhatRenderBuffer, id()); 484 reply->setSize("buffer-ix", bufferIx); 485 reply->setInt32("generation", mBufferGeneration); 486 487 if (mSkipRenderingUntilMediaTimeUs >= 0) { 488 if (timeUs < mSkipRenderingUntilMediaTimeUs) { 489 ALOGV("[%s] dropping buffer at time %lld as requested.", 490 mComponentName.c_str(), (long long)timeUs); 491 492 reply->post(); 493 return true; 494 } 495 496 mSkipRenderingUntilMediaTimeUs = -1; 497 } 498 499 // wait until 1st frame comes out to signal resume complete 500 notifyResumeCompleteIfNecessary(); 501 502 if (mRenderer != NULL) { 503 // send the buffer to renderer. 504 mRenderer->queueBuffer(mIsAudio, buffer, reply); 505 if (flags & MediaCodec::BUFFER_FLAG_EOS) { 506 mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM); 507 } 508 } 509 510 return true; 511} 512 513void NuPlayer::Decoder::releaseAndResetMediaBuffers() { 514 for (size_t i = 0; i < mMediaBuffers.size(); i++) { 515 if (mMediaBuffers[i] != NULL) { 516 mMediaBuffers[i]->release(); 517 mMediaBuffers.editItemAt(i) = NULL; 518 } 519 } 520 mMediaBuffers.resize(mInputBuffers.size()); 521 for (size_t i = 0; i < mMediaBuffers.size(); i++) { 522 mMediaBuffers.editItemAt(i) = NULL; 523 } 524 mInputBufferIsDequeued.clear(); 525 mInputBufferIsDequeued.resize(mInputBuffers.size()); 526 for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) { 527 mInputBufferIsDequeued.editItemAt(i) = false; 528 } 529 530 mPendingInputMessages.clear(); 531 mDequeuedInputBuffers.clear(); 532 mSkipRenderingUntilMediaTimeUs = -1; 533} 534 535void NuPlayer::Decoder::requestCodecNotification() { 536 if (mFormatChangePending) { 537 return; 538 } 539 if (mCodec != NULL) { 540 sp<AMessage> reply = new AMessage(kWhatCodecNotify, id()); 541 reply->setInt32("generation", mBufferGeneration); 542 mCodec->requestActivityNotification(reply); 543 } 544} 545 546bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) { 547 int32_t generation; 548 CHECK(msg->findInt32("generation", &generation)); 549 return generation != mBufferGeneration; 550} 551 552status_t NuPlayer::Decoder::fetchInputData(sp<AMessage> &reply) { 553 sp<ABuffer> accessUnit; 554 bool dropAccessUnit; 555 do { 556 status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit); 557 558 if (err == -EWOULDBLOCK) { 559 return err; 560 } else if (err != OK) { 561 if (err == INFO_DISCONTINUITY) { 562 int32_t type; 563 CHECK(accessUnit->meta()->findInt32("discontinuity", &type)); 564 565 bool formatChange = 566 (mIsAudio && 567 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT)) 568 || (!mIsAudio && 569 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT)); 570 571 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0; 572 573 ALOGI("%s discontinuity (format=%d, time=%d)", 574 mIsAudio ? "audio" : "video", formatChange, timeChange); 575 576 bool seamlessFormatChange = false; 577 sp<AMessage> newFormat = mSource->getFormat(mIsAudio); 578 if (formatChange) { 579 seamlessFormatChange = 580 supportsSeamlessFormatChange(newFormat); 581 // treat seamless format change separately 582 formatChange = !seamlessFormatChange; 583 } 584 585 if (formatChange || timeChange) { 586 sp<AMessage> msg = mNotify->dup(); 587 msg->setInt32("what", kWhatInputDiscontinuity); 588 msg->setInt32("formatChange", formatChange); 589 msg->post(); 590 } 591 592 if (formatChange /* not seamless */) { 593 // must change decoder 594 // return EOS and wait to be killed 595 mFormatChangePending = true; 596 return ERROR_END_OF_STREAM; 597 } else if (timeChange) { 598 // need to flush 599 // TODO: Ideally we shouldn't need a flush upon time 600 // discontinuity, flushing will cause loss of frames. 601 // We probably should queue a time change marker to the 602 // output queue, and handles it in renderer instead. 603 rememberCodecSpecificData(newFormat); 604 onFlush(false /* notifyComplete */); 605 continue; 606 } else if (seamlessFormatChange) { 607 // reuse existing decoder and don't flush 608 rememberCodecSpecificData(newFormat); 609 continue; 610 } else { 611 // This stream is unaffected by the discontinuity 612 return -EWOULDBLOCK; 613 } 614 } 615 616 reply->setInt32("err", err); 617 return OK; 618 } 619 620 if (!mIsAudio) { 621 ++mNumFramesTotal; 622 } 623 624 dropAccessUnit = false; 625 if (!mIsAudio 626 && !mIsSecure 627 && mRenderer->getVideoLateByUs() > 100000ll 628 && mIsVideoAVC 629 && !IsAVCReferenceFrame(accessUnit)) { 630 dropAccessUnit = true; 631 ++mNumFramesDropped; 632 } 633 } while (dropAccessUnit); 634 635 // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video"); 636#if 0 637 int64_t mediaTimeUs; 638 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs)); 639 ALOGV("feeding %s input buffer at media time %.2f secs", 640 mIsAudio ? "audio" : "video", 641 mediaTimeUs / 1E6); 642#endif 643 644 if (mCCDecoder != NULL) { 645 mCCDecoder->decode(accessUnit); 646 } 647 648 reply->setBuffer("buffer", accessUnit); 649 650 return OK; 651} 652 653bool NuPlayer::Decoder::onInputBufferFetched(const sp<AMessage> &msg) { 654 size_t bufferIx; 655 CHECK(msg->findSize("buffer-ix", &bufferIx)); 656 CHECK_LT(bufferIx, mInputBuffers.size()); 657 sp<ABuffer> codecBuffer = mInputBuffers[bufferIx]; 658 659 sp<ABuffer> buffer; 660 bool hasBuffer = msg->findBuffer("buffer", &buffer); 661 662 // handle widevine classic source - that fills an arbitrary input buffer 663 MediaBuffer *mediaBuffer = NULL; 664 if (hasBuffer) { 665 mediaBuffer = (MediaBuffer *)(buffer->getMediaBufferBase()); 666 if (mediaBuffer != NULL) { 667 // likely filled another buffer than we requested: adjust buffer index 668 size_t ix; 669 for (ix = 0; ix < mInputBuffers.size(); ix++) { 670 const sp<ABuffer> &buf = mInputBuffers[ix]; 671 if (buf->data() == mediaBuffer->data()) { 672 // all input buffers are dequeued on start, hence the check 673 if (!mInputBufferIsDequeued[ix]) { 674 ALOGV("[%s] received MediaBuffer for #%zu instead of #%zu", 675 mComponentName.c_str(), ix, bufferIx); 676 mediaBuffer->release(); 677 return false; 678 } 679 680 // TRICKY: need buffer for the metadata, so instead, set 681 // codecBuffer to the same (though incorrect) buffer to 682 // avoid a memcpy into the codecBuffer 683 codecBuffer = buffer; 684 codecBuffer->setRange( 685 mediaBuffer->range_offset(), 686 mediaBuffer->range_length()); 687 bufferIx = ix; 688 break; 689 } 690 } 691 CHECK(ix < mInputBuffers.size()); 692 } 693 } 694 695 if (buffer == NULL /* includes !hasBuffer */) { 696 int32_t streamErr = ERROR_END_OF_STREAM; 697 CHECK(msg->findInt32("err", &streamErr) || !hasBuffer); 698 699 CHECK(streamErr != OK); 700 701 // attempt to queue EOS 702 status_t err = mCodec->queueInputBuffer( 703 bufferIx, 704 0, 705 0, 706 0, 707 MediaCodec::BUFFER_FLAG_EOS); 708 if (err == OK) { 709 mInputBufferIsDequeued.editItemAt(bufferIx) = false; 710 } else if (streamErr == ERROR_END_OF_STREAM) { 711 streamErr = err; 712 // err will not be ERROR_END_OF_STREAM 713 } 714 715 if (streamErr != ERROR_END_OF_STREAM) { 716 ALOGE("Stream error for %s (err=%d), EOS %s queued", 717 mComponentName.c_str(), 718 streamErr, 719 err == OK ? "successfully" : "unsuccessfully"); 720 handleError(streamErr); 721 } 722 } else { 723 sp<AMessage> extra; 724 if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) { 725 int64_t resumeAtMediaTimeUs; 726 if (extra->findInt64( 727 "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) { 728 ALOGI("[%s] suppressing rendering until %lld us", 729 mComponentName.c_str(), (long long)resumeAtMediaTimeUs); 730 mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs; 731 } 732 } 733 734 int64_t timeUs = 0; 735 uint32_t flags = 0; 736 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 737 738 int32_t eos, csd; 739 // we do not expect SYNCFRAME for decoder 740 if (buffer->meta()->findInt32("eos", &eos) && eos) { 741 flags |= MediaCodec::BUFFER_FLAG_EOS; 742 } else if (buffer->meta()->findInt32("csd", &csd) && csd) { 743 flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG; 744 } 745 746 // copy into codec buffer 747 if (buffer != codecBuffer) { 748 CHECK_LE(buffer->size(), codecBuffer->capacity()); 749 codecBuffer->setRange(0, buffer->size()); 750 memcpy(codecBuffer->data(), buffer->data(), buffer->size()); 751 } 752 753 status_t err = mCodec->queueInputBuffer( 754 bufferIx, 755 codecBuffer->offset(), 756 codecBuffer->size(), 757 timeUs, 758 flags); 759 if (err != OK) { 760 if (mediaBuffer != NULL) { 761 mediaBuffer->release(); 762 } 763 ALOGE("Failed to queue input buffer for %s (err=%d)", 764 mComponentName.c_str(), err); 765 handleError(err); 766 } else { 767 mInputBufferIsDequeued.editItemAt(bufferIx) = false; 768 if (mediaBuffer != NULL) { 769 CHECK(mMediaBuffers[bufferIx] == NULL); 770 mMediaBuffers.editItemAt(bufferIx) = mediaBuffer; 771 } 772 } 773 } 774 return true; 775} 776 777void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) { 778 status_t err; 779 int32_t render; 780 size_t bufferIx; 781 CHECK(msg->findSize("buffer-ix", &bufferIx)); 782 783 if (!mIsAudio) { 784 int64_t timeUs; 785 sp<ABuffer> buffer = mOutputBuffers[bufferIx]; 786 buffer->meta()->findInt64("timeUs", &timeUs); 787 788 if (mCCDecoder != NULL && mCCDecoder->isSelected()) { 789 mCCDecoder->display(timeUs); 790 } 791 } 792 793 if (msg->findInt32("render", &render) && render) { 794 int64_t timestampNs; 795 CHECK(msg->findInt64("timestampNs", ×tampNs)); 796 err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs); 797 } else { 798 err = mCodec->releaseOutputBuffer(bufferIx); 799 } 800 if (err != OK) { 801 ALOGE("failed to release output buffer for %s (err=%d)", 802 mComponentName.c_str(), err); 803 handleError(err); 804 } 805} 806 807bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange( 808 const sp<AMessage> &targetFormat) const { 809 if (targetFormat == NULL) { 810 return true; 811 } 812 813 AString mime; 814 if (!targetFormat->findString("mime", &mime)) { 815 return false; 816 } 817 818 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) { 819 // field-by-field comparison 820 const char * keys[] = { "channel-count", "sample-rate", "is-adts" }; 821 for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) { 822 int32_t oldVal, newVal; 823 if (!mInputFormat->findInt32(keys[i], &oldVal) || 824 !targetFormat->findInt32(keys[i], &newVal) || 825 oldVal != newVal) { 826 return false; 827 } 828 } 829 830 sp<ABuffer> oldBuf, newBuf; 831 if (mInputFormat->findBuffer("csd-0", &oldBuf) && 832 targetFormat->findBuffer("csd-0", &newBuf)) { 833 if (oldBuf->size() != newBuf->size()) { 834 return false; 835 } 836 return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size()); 837 } 838 } 839 return false; 840} 841 842bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const { 843 if (mInputFormat == NULL) { 844 return false; 845 } 846 847 if (targetFormat == NULL) { 848 return true; 849 } 850 851 AString oldMime, newMime; 852 if (!mInputFormat->findString("mime", &oldMime) 853 || !targetFormat->findString("mime", &newMime) 854 || !(oldMime == newMime)) { 855 return false; 856 } 857 858 bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/")); 859 bool seamless; 860 if (audio) { 861 seamless = supportsSeamlessAudioFormatChange(targetFormat); 862 } else { 863 int32_t isAdaptive; 864 seamless = (mCodec != NULL && 865 mInputFormat->findInt32("adaptive-playback", &isAdaptive) && 866 isAdaptive); 867 } 868 869 ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str()); 870 return seamless; 871} 872 873void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) { 874 if (format == NULL) { 875 return; 876 } 877 mCSDsForCurrentFormat.clear(); 878 for (int32_t i = 0; ; ++i) { 879 AString tag = "csd-"; 880 tag.append(i); 881 sp<ABuffer> buffer; 882 if (!format->findBuffer(tag.c_str(), &buffer)) { 883 break; 884 } 885 mCSDsForCurrentFormat.push(buffer); 886 } 887} 888 889void NuPlayer::Decoder::notifyResumeCompleteIfNecessary() { 890 if (mResumePending) { 891 mResumePending = false; 892 893 sp<AMessage> notify = mNotify->dup(); 894 notify->setInt32("what", kWhatResumeCompleted); 895 notify->post(); 896 } 897} 898 899} // namespace android 900 901