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 39 namespace android { 40 41 NuPlayer::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 67 NuPlayer::Decoder::~Decoder() { 68 releaseAndResetMediaBuffers(); 69 } 70 71 void NuPlayer::Decoder::getStats( 72 int64_t *numFramesTotal, 73 int64_t *numFramesDropped) const { 74 *numFramesTotal = mNumFramesTotal; 75 *numFramesDropped = mNumFramesDropped; 76 } 77 78 void 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 120 void 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 214 void 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 222 void 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 230 void NuPlayer::Decoder::onResume(bool notifyComplete) { 231 mPaused = false; 232 233 if (notifyComplete) { 234 mResumePending = true; 235 } 236 } 237 238 void 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 271 void 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 311 void 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 338 bool 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 393 bool 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 513 void 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 535 void 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 546 bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) { 547 int32_t generation; 548 CHECK(msg->findInt32("generation", &generation)); 549 return generation != mBufferGeneration; 550 } 551 552 status_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 err = OK; 606 } else if (seamlessFormatChange) { 607 // reuse existing decoder and don't flush 608 rememberCodecSpecificData(newFormat); 609 err = OK; 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 653 bool 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 if (streamErr == OK) { 700 /* buffers are returned to hold on to */ 701 return true; 702 } 703 704 // attempt to queue EOS 705 status_t err = mCodec->queueInputBuffer( 706 bufferIx, 707 0, 708 0, 709 0, 710 MediaCodec::BUFFER_FLAG_EOS); 711 if (err == OK) { 712 mInputBufferIsDequeued.editItemAt(bufferIx) = false; 713 } else if (streamErr == ERROR_END_OF_STREAM) { 714 streamErr = err; 715 // err will not be ERROR_END_OF_STREAM 716 } 717 718 if (streamErr != ERROR_END_OF_STREAM) { 719 ALOGE("Stream error for %s (err=%d), EOS %s queued", 720 mComponentName.c_str(), 721 streamErr, 722 err == OK ? "successfully" : "unsuccessfully"); 723 handleError(streamErr); 724 } 725 } else { 726 sp<AMessage> extra; 727 if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) { 728 int64_t resumeAtMediaTimeUs; 729 if (extra->findInt64( 730 "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) { 731 ALOGI("[%s] suppressing rendering until %lld us", 732 mComponentName.c_str(), (long long)resumeAtMediaTimeUs); 733 mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs; 734 } 735 } 736 737 int64_t timeUs = 0; 738 uint32_t flags = 0; 739 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 740 741 int32_t eos, csd; 742 // we do not expect SYNCFRAME for decoder 743 if (buffer->meta()->findInt32("eos", &eos) && eos) { 744 flags |= MediaCodec::BUFFER_FLAG_EOS; 745 } else if (buffer->meta()->findInt32("csd", &csd) && csd) { 746 flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG; 747 } 748 749 // copy into codec buffer 750 if (buffer != codecBuffer) { 751 CHECK_LE(buffer->size(), codecBuffer->capacity()); 752 codecBuffer->setRange(0, buffer->size()); 753 memcpy(codecBuffer->data(), buffer->data(), buffer->size()); 754 } 755 756 status_t err = mCodec->queueInputBuffer( 757 bufferIx, 758 codecBuffer->offset(), 759 codecBuffer->size(), 760 timeUs, 761 flags); 762 if (err != OK) { 763 if (mediaBuffer != NULL) { 764 mediaBuffer->release(); 765 } 766 ALOGE("Failed to queue input buffer for %s (err=%d)", 767 mComponentName.c_str(), err); 768 handleError(err); 769 } else { 770 mInputBufferIsDequeued.editItemAt(bufferIx) = false; 771 if (mediaBuffer != NULL) { 772 CHECK(mMediaBuffers[bufferIx] == NULL); 773 mMediaBuffers.editItemAt(bufferIx) = mediaBuffer; 774 } 775 } 776 } 777 return true; 778 } 779 780 void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) { 781 status_t err; 782 int32_t render; 783 size_t bufferIx; 784 CHECK(msg->findSize("buffer-ix", &bufferIx)); 785 786 if (!mIsAudio) { 787 int64_t timeUs; 788 sp<ABuffer> buffer = mOutputBuffers[bufferIx]; 789 buffer->meta()->findInt64("timeUs", &timeUs); 790 791 if (mCCDecoder != NULL && mCCDecoder->isSelected()) { 792 mCCDecoder->display(timeUs); 793 } 794 } 795 796 if (msg->findInt32("render", &render) && render) { 797 int64_t timestampNs; 798 CHECK(msg->findInt64("timestampNs", ×tampNs)); 799 err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs); 800 } else { 801 err = mCodec->releaseOutputBuffer(bufferIx); 802 } 803 if (err != OK) { 804 ALOGE("failed to release output buffer for %s (err=%d)", 805 mComponentName.c_str(), err); 806 handleError(err); 807 } 808 } 809 810 bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange( 811 const sp<AMessage> &targetFormat) const { 812 if (targetFormat == NULL) { 813 return true; 814 } 815 816 AString mime; 817 if (!targetFormat->findString("mime", &mime)) { 818 return false; 819 } 820 821 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) { 822 // field-by-field comparison 823 const char * keys[] = { "channel-count", "sample-rate", "is-adts" }; 824 for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) { 825 int32_t oldVal, newVal; 826 if (!mInputFormat->findInt32(keys[i], &oldVal) || 827 !targetFormat->findInt32(keys[i], &newVal) || 828 oldVal != newVal) { 829 return false; 830 } 831 } 832 833 sp<ABuffer> oldBuf, newBuf; 834 if (mInputFormat->findBuffer("csd-0", &oldBuf) && 835 targetFormat->findBuffer("csd-0", &newBuf)) { 836 if (oldBuf->size() != newBuf->size()) { 837 return false; 838 } 839 return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size()); 840 } 841 } 842 return false; 843 } 844 845 bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const { 846 if (mInputFormat == NULL) { 847 return false; 848 } 849 850 if (targetFormat == NULL) { 851 return true; 852 } 853 854 AString oldMime, newMime; 855 if (!mInputFormat->findString("mime", &oldMime) 856 || !targetFormat->findString("mime", &newMime) 857 || !(oldMime == newMime)) { 858 return false; 859 } 860 861 bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/")); 862 bool seamless; 863 if (audio) { 864 seamless = supportsSeamlessAudioFormatChange(targetFormat); 865 } else { 866 int32_t isAdaptive; 867 seamless = (mCodec != NULL && 868 mInputFormat->findInt32("adaptive-playback", &isAdaptive) && 869 isAdaptive); 870 } 871 872 ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str()); 873 return seamless; 874 } 875 876 void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) { 877 if (format == NULL) { 878 return; 879 } 880 mCSDsForCurrentFormat.clear(); 881 for (int32_t i = 0; ; ++i) { 882 AString tag = "csd-"; 883 tag.append(i); 884 sp<ABuffer> buffer; 885 if (!format->findBuffer(tag.c_str(), &buffer)) { 886 break; 887 } 888 mCSDsForCurrentFormat.push(buffer); 889 } 890 } 891 892 void NuPlayer::Decoder::notifyResumeCompleteIfNecessary() { 893 if (mResumePending) { 894 mResumePending = false; 895 896 sp<AMessage> notify = mNotify->dup(); 897 notify->setInt32("what", kWhatResumeCompleted); 898 notify->post(); 899 } 900 } 901 902 } // namespace android 903 904