NuPlayerDecoder.cpp revision 674649bcb5d3e5fd6e527906c7b166f96d35ec16
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 <cutils/properties.h> 28#include <media/ICrypto.h> 29#include <media/stagefright/foundation/ABuffer.h> 30#include <media/stagefright/foundation/ADebug.h> 31#include <media/stagefright/foundation/AMessage.h> 32#include <media/stagefright/MediaBuffer.h> 33#include <media/stagefright/MediaCodec.h> 34#include <media/stagefright/MediaDefs.h> 35#include <media/stagefright/MediaErrors.h> 36 37#include <gui/Surface.h> 38 39#include "avc_utils.h" 40#include "ATSParser.h" 41 42namespace android { 43 44static inline bool getAudioDeepBufferSetting() { 45 return property_get_bool("media.stagefright.audio.deep", false /* default_value */); 46} 47 48NuPlayer::Decoder::Decoder( 49 const sp<AMessage> ¬ify, 50 const sp<Source> &source, 51 pid_t pid, 52 const sp<Renderer> &renderer, 53 const sp<Surface> &surface, 54 const sp<CCDecoder> &ccDecoder) 55 : DecoderBase(notify), 56 mSurface(surface), 57 mSource(source), 58 mRenderer(renderer), 59 mCCDecoder(ccDecoder), 60 mPid(pid), 61 mSkipRenderingUntilMediaTimeUs(-1ll), 62 mNumFramesTotal(0ll), 63 mNumInputFramesDropped(0ll), 64 mNumOutputFramesDropped(0ll), 65 mVideoWidth(0), 66 mVideoHeight(0), 67 mIsAudio(true), 68 mIsVideoAVC(false), 69 mIsSecure(false), 70 mFormatChangePending(false), 71 mTimeChangePending(false), 72 mResumePending(false), 73 mComponentName("decoder") { 74 mCodecLooper = new ALooper; 75 mCodecLooper->setName("NPDecoder-CL"); 76 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO); 77} 78 79NuPlayer::Decoder::~Decoder() { 80 mCodec->release(); 81 releaseAndResetMediaBuffers(); 82} 83 84sp<AMessage> NuPlayer::Decoder::getStats() const { 85 mStats->setInt64("frames-total", mNumFramesTotal); 86 mStats->setInt64("frames-dropped-input", mNumInputFramesDropped); 87 mStats->setInt64("frames-dropped-output", mNumOutputFramesDropped); 88 return mStats; 89} 90 91status_t NuPlayer::Decoder::setVideoSurface(const sp<Surface> &surface) { 92 if (surface == NULL || ADebug::isExperimentEnabled("legacy-setsurface")) { 93 return BAD_VALUE; 94 } 95 96 sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, this); 97 98 msg->setObject("surface", surface); 99 sp<AMessage> response; 100 status_t err = msg->postAndAwaitResponse(&response); 101 if (err == OK && response != NULL) { 102 CHECK(response->findInt32("err", &err)); 103 } 104 return err; 105} 106 107void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) { 108 ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str()); 109 110 switch (msg->what()) { 111 case kWhatCodecNotify: 112 { 113 int32_t cbID; 114 CHECK(msg->findInt32("callbackID", &cbID)); 115 116 ALOGV("[%s] kWhatCodecNotify: cbID = %d, paused = %d", 117 mIsAudio ? "audio" : "video", cbID, mPaused); 118 119 if (mPaused) { 120 break; 121 } 122 123 switch (cbID) { 124 case MediaCodec::CB_INPUT_AVAILABLE: 125 { 126 int32_t index; 127 CHECK(msg->findInt32("index", &index)); 128 129 handleAnInputBuffer(index); 130 break; 131 } 132 133 case MediaCodec::CB_OUTPUT_AVAILABLE: 134 { 135 int32_t index; 136 size_t offset; 137 size_t size; 138 int64_t timeUs; 139 int32_t flags; 140 141 CHECK(msg->findInt32("index", &index)); 142 CHECK(msg->findSize("offset", &offset)); 143 CHECK(msg->findSize("size", &size)); 144 CHECK(msg->findInt64("timeUs", &timeUs)); 145 CHECK(msg->findInt32("flags", &flags)); 146 147 handleAnOutputBuffer(index, offset, size, timeUs, flags); 148 break; 149 } 150 151 case MediaCodec::CB_OUTPUT_FORMAT_CHANGED: 152 { 153 sp<AMessage> format; 154 CHECK(msg->findMessage("format", &format)); 155 156 handleOutputFormatChange(format); 157 break; 158 } 159 160 case MediaCodec::CB_ERROR: 161 { 162 status_t err; 163 CHECK(msg->findInt32("err", &err)); 164 ALOGE("Decoder (%s) reported error : 0x%x", 165 mIsAudio ? "audio" : "video", err); 166 167 handleError(err); 168 break; 169 } 170 171 default: 172 { 173 TRESPASS(); 174 break; 175 } 176 } 177 178 break; 179 } 180 181 case kWhatRenderBuffer: 182 { 183 if (!isStaleReply(msg)) { 184 onRenderBuffer(msg); 185 } 186 break; 187 } 188 189 case kWhatSetVideoSurface: 190 { 191 sp<AReplyToken> replyID; 192 CHECK(msg->senderAwaitsResponse(&replyID)); 193 194 sp<RefBase> obj; 195 CHECK(msg->findObject("surface", &obj)); 196 sp<Surface> surface = static_cast<Surface *>(obj.get()); // non-null 197 int32_t err = INVALID_OPERATION; 198 // NOTE: in practice mSurface is always non-null, but checking here for completeness 199 if (mCodec != NULL && mSurface != NULL) { 200 // TODO: once AwesomePlayer is removed, remove this automatic connecting 201 // to the surface by MediaPlayerService. 202 // 203 // at this point MediaPlayerService::client has already connected to the 204 // surface, which MediaCodec does not expect 205 err = native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA); 206 if (err == OK) { 207 err = mCodec->setSurface(surface); 208 ALOGI_IF(err, "codec setSurface returned: %d", err); 209 if (err == OK) { 210 // reconnect to the old surface as MPS::Client will expect to 211 // be able to disconnect from it. 212 (void)native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_MEDIA); 213 mSurface = surface; 214 } 215 } 216 if (err != OK) { 217 // reconnect to the new surface on error as MPS::Client will expect to 218 // be able to disconnect from it. 219 (void)native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA); 220 } 221 } 222 223 sp<AMessage> response = new AMessage; 224 response->setInt32("err", err); 225 response->postReply(replyID); 226 break; 227 } 228 229 default: 230 DecoderBase::onMessageReceived(msg); 231 break; 232 } 233} 234 235void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) { 236 CHECK(mCodec == NULL); 237 238 mFormatChangePending = false; 239 mTimeChangePending = false; 240 241 ++mBufferGeneration; 242 243 AString mime; 244 CHECK(format->findString("mime", &mime)); 245 246 mIsAudio = !strncasecmp("audio/", mime.c_str(), 6); 247 mIsVideoAVC = !strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime.c_str()); 248 249 mComponentName = mime; 250 mComponentName.append(" decoder"); 251 ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), mSurface.get()); 252 253 mCodec = MediaCodec::CreateByType( 254 mCodecLooper, mime.c_str(), false /* encoder */, NULL /* err */, mPid); 255 int32_t secure = 0; 256 if (format->findInt32("secure", &secure) && secure != 0) { 257 if (mCodec != NULL) { 258 mCodec->getName(&mComponentName); 259 mComponentName.append(".secure"); 260 mCodec->release(); 261 ALOGI("[%s] creating", mComponentName.c_str()); 262 mCodec = MediaCodec::CreateByComponentName( 263 mCodecLooper, mComponentName.c_str(), NULL /* err */, mPid); 264 } 265 } 266 if (mCodec == NULL) { 267 ALOGE("Failed to create %s%s decoder", 268 (secure ? "secure " : ""), mime.c_str()); 269 handleError(UNKNOWN_ERROR); 270 return; 271 } 272 mIsSecure = secure; 273 274 mCodec->getName(&mComponentName); 275 276 status_t err; 277 if (mSurface != NULL) { 278 // disconnect from surface as MediaCodec will reconnect 279 err = native_window_api_disconnect( 280 mSurface.get(), NATIVE_WINDOW_API_MEDIA); 281 // We treat this as a warning, as this is a preparatory step. 282 // Codec will try to connect to the surface, which is where 283 // any error signaling will occur. 284 ALOGW_IF(err != OK, "failed to disconnect from surface: %d", err); 285 } 286 err = mCodec->configure( 287 format, mSurface, NULL /* crypto */, 0 /* flags */); 288 if (err != OK) { 289 ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err); 290 mCodec->release(); 291 mCodec.clear(); 292 handleError(err); 293 return; 294 } 295 rememberCodecSpecificData(format); 296 297 // the following should work in configured state 298 CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat)); 299 CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat)); 300 301 mStats->setString("mime", mime.c_str()); 302 mStats->setString("component-name", mComponentName.c_str()); 303 304 if (!mIsAudio) { 305 int32_t width, height; 306 if (mOutputFormat->findInt32("width", &width) 307 && mOutputFormat->findInt32("height", &height)) { 308 mStats->setInt32("width", width); 309 mStats->setInt32("height", height); 310 } 311 } 312 313 sp<AMessage> reply = new AMessage(kWhatCodecNotify, this); 314 mCodec->setCallback(reply); 315 316 err = mCodec->start(); 317 if (err != OK) { 318 ALOGE("Failed to start %s decoder (err=%d)", mComponentName.c_str(), err); 319 mCodec->release(); 320 mCodec.clear(); 321 handleError(err); 322 return; 323 } 324 325 releaseAndResetMediaBuffers(); 326 327 mPaused = false; 328 mResumePending = false; 329} 330 331void NuPlayer::Decoder::onSetParameters(const sp<AMessage> ¶ms) { 332 if (mCodec == NULL) { 333 ALOGW("onSetParameters called before codec is created."); 334 return; 335 } 336 mCodec->setParameters(params); 337} 338 339void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) { 340 bool hadNoRenderer = (mRenderer == NULL); 341 mRenderer = renderer; 342 if (hadNoRenderer && mRenderer != NULL) { 343 // this means that the widevine legacy source is ready 344 onRequestInputBuffers(); 345 } 346} 347 348void NuPlayer::Decoder::onGetInputBuffers( 349 Vector<sp<ABuffer> > *dstBuffers) { 350 CHECK_EQ((status_t)OK, mCodec->getWidevineLegacyBuffers(dstBuffers)); 351} 352 353void NuPlayer::Decoder::onResume(bool notifyComplete) { 354 mPaused = false; 355 356 if (notifyComplete) { 357 mResumePending = true; 358 } 359 mCodec->start(); 360} 361 362void NuPlayer::Decoder::doFlush(bool notifyComplete) { 363 if (mCCDecoder != NULL) { 364 mCCDecoder->flush(); 365 } 366 367 if (mRenderer != NULL) { 368 mRenderer->flush(mIsAudio, notifyComplete); 369 mRenderer->signalTimeDiscontinuity(); 370 } 371 372 status_t err = OK; 373 if (mCodec != NULL) { 374 err = mCodec->flush(); 375 mCSDsToSubmit = mCSDsForCurrentFormat; // copy operator 376 ++mBufferGeneration; 377 } 378 379 if (err != OK) { 380 ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err); 381 handleError(err); 382 // finish with posting kWhatFlushCompleted. 383 // we attempt to release the buffers even if flush fails. 384 } 385 releaseAndResetMediaBuffers(); 386 mPaused = true; 387} 388 389 390void NuPlayer::Decoder::onFlush() { 391 doFlush(true); 392 393 if (isDiscontinuityPending()) { 394 // This could happen if the client starts seeking/shutdown 395 // after we queued an EOS for discontinuities. 396 // We can consider discontinuity handled. 397 finishHandleDiscontinuity(false /* flushOnTimeChange */); 398 } 399 400 sp<AMessage> notify = mNotify->dup(); 401 notify->setInt32("what", kWhatFlushCompleted); 402 notify->post(); 403} 404 405void NuPlayer::Decoder::onShutdown(bool notifyComplete) { 406 status_t err = OK; 407 408 // if there is a pending resume request, notify complete now 409 notifyResumeCompleteIfNecessary(); 410 411 if (mCodec != NULL) { 412 err = mCodec->release(); 413 mCodec = NULL; 414 ++mBufferGeneration; 415 416 if (mSurface != NULL) { 417 // reconnect to surface as MediaCodec disconnected from it 418 status_t error = 419 native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_MEDIA); 420 ALOGW_IF(error != NO_ERROR, 421 "[%s] failed to connect to native window, error=%d", 422 mComponentName.c_str(), error); 423 } 424 mComponentName = "decoder"; 425 } 426 427 releaseAndResetMediaBuffers(); 428 429 if (err != OK) { 430 ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err); 431 handleError(err); 432 // finish with posting kWhatShutdownCompleted. 433 } 434 435 if (notifyComplete) { 436 sp<AMessage> notify = mNotify->dup(); 437 notify->setInt32("what", kWhatShutdownCompleted); 438 notify->post(); 439 mPaused = true; 440 } 441} 442 443/* 444 * returns true if we should request more data 445 */ 446bool NuPlayer::Decoder::doRequestBuffers() { 447 // mRenderer is only NULL if we have a legacy widevine source that 448 // is not yet ready. In this case we must not fetch input. 449 if (isDiscontinuityPending() || mRenderer == NULL) { 450 return false; 451 } 452 status_t err = OK; 453 while (err == OK && !mDequeuedInputBuffers.empty()) { 454 size_t bufferIx = *mDequeuedInputBuffers.begin(); 455 sp<AMessage> msg = new AMessage(); 456 msg->setSize("buffer-ix", bufferIx); 457 err = fetchInputData(msg); 458 if (err != OK && err != ERROR_END_OF_STREAM) { 459 // if EOS, need to queue EOS buffer 460 break; 461 } 462 mDequeuedInputBuffers.erase(mDequeuedInputBuffers.begin()); 463 464 if (!mPendingInputMessages.empty() 465 || !onInputBufferFetched(msg)) { 466 mPendingInputMessages.push_back(msg); 467 } 468 } 469 470 return err == -EWOULDBLOCK 471 && mSource->feedMoreTSData() == OK; 472} 473 474void NuPlayer::Decoder::handleError(int32_t err) 475{ 476 // We cannot immediately release the codec due to buffers still outstanding 477 // in the renderer. We signal to the player the error so it can shutdown/release the 478 // decoder after flushing and increment the generation to discard unnecessary messages. 479 480 ++mBufferGeneration; 481 482 sp<AMessage> notify = mNotify->dup(); 483 notify->setInt32("what", kWhatError); 484 notify->setInt32("err", err); 485 notify->post(); 486} 487 488bool NuPlayer::Decoder::handleAnInputBuffer(size_t index) { 489 if (isDiscontinuityPending()) { 490 return false; 491 } 492 493 sp<ABuffer> buffer; 494 mCodec->getInputBuffer(index, &buffer); 495 496 if (buffer == NULL) { 497 handleError(UNKNOWN_ERROR); 498 return false; 499 } 500 501 if (index >= mInputBuffers.size()) { 502 for (size_t i = mInputBuffers.size(); i <= index; ++i) { 503 mInputBuffers.add(); 504 mMediaBuffers.add(); 505 mInputBufferIsDequeued.add(); 506 mMediaBuffers.editItemAt(i) = NULL; 507 mInputBufferIsDequeued.editItemAt(i) = false; 508 } 509 } 510 mInputBuffers.editItemAt(index) = buffer; 511 512 //CHECK_LT(bufferIx, mInputBuffers.size()); 513 514 if (mMediaBuffers[index] != NULL) { 515 mMediaBuffers[index]->release(); 516 mMediaBuffers.editItemAt(index) = NULL; 517 } 518 mInputBufferIsDequeued.editItemAt(index) = true; 519 520 if (!mCSDsToSubmit.isEmpty()) { 521 sp<AMessage> msg = new AMessage(); 522 msg->setSize("buffer-ix", index); 523 524 sp<ABuffer> buffer = mCSDsToSubmit.itemAt(0); 525 ALOGI("[%s] resubmitting CSD", mComponentName.c_str()); 526 msg->setBuffer("buffer", buffer); 527 mCSDsToSubmit.removeAt(0); 528 CHECK(onInputBufferFetched(msg)); 529 return true; 530 } 531 532 while (!mPendingInputMessages.empty()) { 533 sp<AMessage> msg = *mPendingInputMessages.begin(); 534 if (!onInputBufferFetched(msg)) { 535 break; 536 } 537 mPendingInputMessages.erase(mPendingInputMessages.begin()); 538 } 539 540 if (!mInputBufferIsDequeued.editItemAt(index)) { 541 return true; 542 } 543 544 mDequeuedInputBuffers.push_back(index); 545 546 onRequestInputBuffers(); 547 return true; 548} 549 550bool NuPlayer::Decoder::handleAnOutputBuffer( 551 size_t index, 552 size_t offset, 553 size_t size, 554 int64_t timeUs, 555 int32_t flags) { 556// CHECK_LT(bufferIx, mOutputBuffers.size()); 557 sp<ABuffer> buffer; 558 mCodec->getOutputBuffer(index, &buffer); 559 560 if (index >= mOutputBuffers.size()) { 561 for (size_t i = mOutputBuffers.size(); i <= index; ++i) { 562 mOutputBuffers.add(); 563 } 564 } 565 566 mOutputBuffers.editItemAt(index) = buffer; 567 568 buffer->setRange(offset, size); 569 buffer->meta()->clear(); 570 buffer->meta()->setInt64("timeUs", timeUs); 571 572 bool eos = flags & MediaCodec::BUFFER_FLAG_EOS; 573 // we do not expect CODECCONFIG or SYNCFRAME for decoder 574 575 sp<AMessage> reply = new AMessage(kWhatRenderBuffer, this); 576 reply->setSize("buffer-ix", index); 577 reply->setInt32("generation", mBufferGeneration); 578 579 if (eos) { 580 ALOGI("[%s] saw output EOS", mIsAudio ? "audio" : "video"); 581 582 buffer->meta()->setInt32("eos", true); 583 reply->setInt32("eos", true); 584 } else if (mSkipRenderingUntilMediaTimeUs >= 0) { 585 if (timeUs < mSkipRenderingUntilMediaTimeUs) { 586 ALOGV("[%s] dropping buffer at time %lld as requested.", 587 mComponentName.c_str(), (long long)timeUs); 588 589 reply->post(); 590 return true; 591 } 592 593 mSkipRenderingUntilMediaTimeUs = -1; 594 } 595 596 mNumFramesTotal += !mIsAudio; 597 598 // wait until 1st frame comes out to signal resume complete 599 notifyResumeCompleteIfNecessary(); 600 601 if (mRenderer != NULL) { 602 // send the buffer to renderer. 603 mRenderer->queueBuffer(mIsAudio, buffer, reply); 604 if (eos && !isDiscontinuityPending()) { 605 mRenderer->queueEOS(mIsAudio, ERROR_END_OF_STREAM); 606 } 607 } 608 609 return true; 610} 611 612void NuPlayer::Decoder::handleOutputFormatChange(const sp<AMessage> &format) { 613 if (!mIsAudio) { 614 int32_t width, height; 615 if (format->findInt32("width", &width) 616 && format->findInt32("height", &height)) { 617 mStats->setInt32("width", width); 618 mStats->setInt32("height", height); 619 } 620 sp<AMessage> notify = mNotify->dup(); 621 notify->setInt32("what", kWhatVideoSizeChanged); 622 notify->setMessage("format", format); 623 notify->post(); 624 } else if (mRenderer != NULL) { 625 uint32_t flags; 626 int64_t durationUs; 627 bool hasVideo = (mSource->getFormat(false /* audio */) != NULL); 628 if (getAudioDeepBufferSetting() // override regardless of source duration 629 || (!hasVideo 630 && mSource->getDuration(&durationUs) == OK 631 && durationUs > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US)) { 632 flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; 633 } else { 634 flags = AUDIO_OUTPUT_FLAG_NONE; 635 } 636 637 status_t err = mRenderer->openAudioSink( 638 format, false /* offloadOnly */, hasVideo, flags, NULL /* isOffloaed */); 639 if (err != OK) { 640 handleError(err); 641 } 642 } 643} 644 645void NuPlayer::Decoder::releaseAndResetMediaBuffers() { 646 for (size_t i = 0; i < mMediaBuffers.size(); i++) { 647 if (mMediaBuffers[i] != NULL) { 648 mMediaBuffers[i]->release(); 649 mMediaBuffers.editItemAt(i) = NULL; 650 } 651 } 652 mMediaBuffers.resize(mInputBuffers.size()); 653 for (size_t i = 0; i < mMediaBuffers.size(); i++) { 654 mMediaBuffers.editItemAt(i) = NULL; 655 } 656 mInputBufferIsDequeued.clear(); 657 mInputBufferIsDequeued.resize(mInputBuffers.size()); 658 for (size_t i = 0; i < mInputBufferIsDequeued.size(); i++) { 659 mInputBufferIsDequeued.editItemAt(i) = false; 660 } 661 662 mPendingInputMessages.clear(); 663 mDequeuedInputBuffers.clear(); 664 mSkipRenderingUntilMediaTimeUs = -1; 665} 666 667void NuPlayer::Decoder::requestCodecNotification() { 668 if (mCodec != NULL) { 669 sp<AMessage> reply = new AMessage(kWhatCodecNotify, this); 670 reply->setInt32("generation", mBufferGeneration); 671 mCodec->requestActivityNotification(reply); 672 } 673} 674 675bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) { 676 int32_t generation; 677 CHECK(msg->findInt32("generation", &generation)); 678 return generation != mBufferGeneration; 679} 680 681status_t NuPlayer::Decoder::fetchInputData(sp<AMessage> &reply) { 682 sp<ABuffer> accessUnit; 683 bool dropAccessUnit; 684 do { 685 status_t err = mSource->dequeueAccessUnit(mIsAudio, &accessUnit); 686 687 if (err == -EWOULDBLOCK) { 688 return err; 689 } else if (err != OK) { 690 if (err == INFO_DISCONTINUITY) { 691 int32_t type; 692 CHECK(accessUnit->meta()->findInt32("discontinuity", &type)); 693 694 bool formatChange = 695 (mIsAudio && 696 (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT)) 697 || (!mIsAudio && 698 (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT)); 699 700 bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0; 701 702 ALOGI("%s discontinuity (format=%d, time=%d)", 703 mIsAudio ? "audio" : "video", formatChange, timeChange); 704 705 bool seamlessFormatChange = false; 706 sp<AMessage> newFormat = mSource->getFormat(mIsAudio); 707 if (formatChange) { 708 seamlessFormatChange = 709 supportsSeamlessFormatChange(newFormat); 710 // treat seamless format change separately 711 formatChange = !seamlessFormatChange; 712 } 713 714 // For format or time change, return EOS to queue EOS input, 715 // then wait for EOS on output. 716 if (formatChange /* not seamless */) { 717 mFormatChangePending = true; 718 err = ERROR_END_OF_STREAM; 719 } else if (timeChange) { 720 rememberCodecSpecificData(newFormat); 721 mTimeChangePending = true; 722 err = ERROR_END_OF_STREAM; 723 } else if (seamlessFormatChange) { 724 // reuse existing decoder and don't flush 725 rememberCodecSpecificData(newFormat); 726 continue; 727 } else { 728 // This stream is unaffected by the discontinuity 729 return -EWOULDBLOCK; 730 } 731 } 732 733 // reply should only be returned without a buffer set 734 // when there is an error (including EOS) 735 CHECK(err != OK); 736 737 reply->setInt32("err", err); 738 return ERROR_END_OF_STREAM; 739 } 740 741 dropAccessUnit = false; 742 if (!mIsAudio 743 && !mIsSecure 744 && mRenderer->getVideoLateByUs() > 100000ll 745 && mIsVideoAVC 746 && !IsAVCReferenceFrame(accessUnit)) { 747 dropAccessUnit = true; 748 ++mNumInputFramesDropped; 749 } 750 } while (dropAccessUnit); 751 752 // ALOGV("returned a valid buffer of %s data", mIsAudio ? "mIsAudio" : "video"); 753#if 0 754 int64_t mediaTimeUs; 755 CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs)); 756 ALOGV("[%s] feeding input buffer at media time %.3f", 757 mIsAudio ? "audio" : "video", 758 mediaTimeUs / 1E6); 759#endif 760 761 if (mCCDecoder != NULL) { 762 mCCDecoder->decode(accessUnit); 763 } 764 765 reply->setBuffer("buffer", accessUnit); 766 767 return OK; 768} 769 770bool NuPlayer::Decoder::onInputBufferFetched(const sp<AMessage> &msg) { 771 size_t bufferIx; 772 CHECK(msg->findSize("buffer-ix", &bufferIx)); 773 CHECK_LT(bufferIx, mInputBuffers.size()); 774 sp<ABuffer> codecBuffer = mInputBuffers[bufferIx]; 775 776 sp<ABuffer> buffer; 777 bool hasBuffer = msg->findBuffer("buffer", &buffer); 778 779 // handle widevine classic source - that fills an arbitrary input buffer 780 MediaBuffer *mediaBuffer = NULL; 781 if (hasBuffer) { 782 mediaBuffer = (MediaBuffer *)(buffer->getMediaBufferBase()); 783 if (mediaBuffer != NULL) { 784 // likely filled another buffer than we requested: adjust buffer index 785 size_t ix; 786 for (ix = 0; ix < mInputBuffers.size(); ix++) { 787 const sp<ABuffer> &buf = mInputBuffers[ix]; 788 if (buf->data() == mediaBuffer->data()) { 789 // all input buffers are dequeued on start, hence the check 790 if (!mInputBufferIsDequeued[ix]) { 791 ALOGV("[%s] received MediaBuffer for #%zu instead of #%zu", 792 mComponentName.c_str(), ix, bufferIx); 793 mediaBuffer->release(); 794 return false; 795 } 796 797 // TRICKY: need buffer for the metadata, so instead, set 798 // codecBuffer to the same (though incorrect) buffer to 799 // avoid a memcpy into the codecBuffer 800 codecBuffer = buffer; 801 codecBuffer->setRange( 802 mediaBuffer->range_offset(), 803 mediaBuffer->range_length()); 804 bufferIx = ix; 805 break; 806 } 807 } 808 CHECK(ix < mInputBuffers.size()); 809 } 810 } 811 812 if (buffer == NULL /* includes !hasBuffer */) { 813 int32_t streamErr = ERROR_END_OF_STREAM; 814 CHECK(msg->findInt32("err", &streamErr) || !hasBuffer); 815 816 CHECK(streamErr != OK); 817 818 // attempt to queue EOS 819 status_t err = mCodec->queueInputBuffer( 820 bufferIx, 821 0, 822 0, 823 0, 824 MediaCodec::BUFFER_FLAG_EOS); 825 if (err == OK) { 826 mInputBufferIsDequeued.editItemAt(bufferIx) = false; 827 } else if (streamErr == ERROR_END_OF_STREAM) { 828 streamErr = err; 829 // err will not be ERROR_END_OF_STREAM 830 } 831 832 if (streamErr != ERROR_END_OF_STREAM) { 833 ALOGE("Stream error for %s (err=%d), EOS %s queued", 834 mComponentName.c_str(), 835 streamErr, 836 err == OK ? "successfully" : "unsuccessfully"); 837 handleError(streamErr); 838 } 839 } else { 840 sp<AMessage> extra; 841 if (buffer->meta()->findMessage("extra", &extra) && extra != NULL) { 842 int64_t resumeAtMediaTimeUs; 843 if (extra->findInt64( 844 "resume-at-mediaTimeUs", &resumeAtMediaTimeUs)) { 845 ALOGI("[%s] suppressing rendering until %lld us", 846 mComponentName.c_str(), (long long)resumeAtMediaTimeUs); 847 mSkipRenderingUntilMediaTimeUs = resumeAtMediaTimeUs; 848 } 849 } 850 851 int64_t timeUs = 0; 852 uint32_t flags = 0; 853 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 854 855 int32_t eos, csd; 856 // we do not expect SYNCFRAME for decoder 857 if (buffer->meta()->findInt32("eos", &eos) && eos) { 858 flags |= MediaCodec::BUFFER_FLAG_EOS; 859 } else if (buffer->meta()->findInt32("csd", &csd) && csd) { 860 flags |= MediaCodec::BUFFER_FLAG_CODECCONFIG; 861 } 862 863 // copy into codec buffer 864 if (buffer != codecBuffer) { 865 CHECK_LE(buffer->size(), codecBuffer->capacity()); 866 codecBuffer->setRange(0, buffer->size()); 867 memcpy(codecBuffer->data(), buffer->data(), buffer->size()); 868 } 869 870 status_t err = mCodec->queueInputBuffer( 871 bufferIx, 872 codecBuffer->offset(), 873 codecBuffer->size(), 874 timeUs, 875 flags); 876 if (err != OK) { 877 if (mediaBuffer != NULL) { 878 mediaBuffer->release(); 879 } 880 ALOGE("Failed to queue input buffer for %s (err=%d)", 881 mComponentName.c_str(), err); 882 handleError(err); 883 } else { 884 mInputBufferIsDequeued.editItemAt(bufferIx) = false; 885 if (mediaBuffer != NULL) { 886 CHECK(mMediaBuffers[bufferIx] == NULL); 887 mMediaBuffers.editItemAt(bufferIx) = mediaBuffer; 888 } 889 } 890 } 891 return true; 892} 893 894void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) { 895 status_t err; 896 int32_t render; 897 size_t bufferIx; 898 int32_t eos; 899 CHECK(msg->findSize("buffer-ix", &bufferIx)); 900 901 if (!mIsAudio) { 902 int64_t timeUs; 903 sp<ABuffer> buffer = mOutputBuffers[bufferIx]; 904 buffer->meta()->findInt64("timeUs", &timeUs); 905 906 if (mCCDecoder != NULL && mCCDecoder->isSelected()) { 907 mCCDecoder->display(timeUs); 908 } 909 } 910 911 if (msg->findInt32("render", &render) && render) { 912 int64_t timestampNs; 913 CHECK(msg->findInt64("timestampNs", ×tampNs)); 914 err = mCodec->renderOutputBufferAndRelease(bufferIx, timestampNs); 915 } else { 916 mNumOutputFramesDropped += !mIsAudio; 917 err = mCodec->releaseOutputBuffer(bufferIx); 918 } 919 if (err != OK) { 920 ALOGE("failed to release output buffer for %s (err=%d)", 921 mComponentName.c_str(), err); 922 handleError(err); 923 } 924 if (msg->findInt32("eos", &eos) && eos 925 && isDiscontinuityPending()) { 926 finishHandleDiscontinuity(true /* flushOnTimeChange */); 927 } 928} 929 930bool NuPlayer::Decoder::isDiscontinuityPending() const { 931 return mFormatChangePending || mTimeChangePending; 932} 933 934void NuPlayer::Decoder::finishHandleDiscontinuity(bool flushOnTimeChange) { 935 ALOGV("finishHandleDiscontinuity: format %d, time %d, flush %d", 936 mFormatChangePending, mTimeChangePending, flushOnTimeChange); 937 938 // If we have format change, pause and wait to be killed; 939 // If we have time change only, flush and restart fetching. 940 941 if (mFormatChangePending) { 942 mPaused = true; 943 } else if (mTimeChangePending) { 944 if (flushOnTimeChange) { 945 doFlush(false /* notifyComplete */); 946 signalResume(false /* notifyComplete */); 947 } 948 } 949 950 // Notify NuPlayer to either shutdown decoder, or rescan sources 951 sp<AMessage> msg = mNotify->dup(); 952 msg->setInt32("what", kWhatInputDiscontinuity); 953 msg->setInt32("formatChange", mFormatChangePending); 954 msg->post(); 955 956 mFormatChangePending = false; 957 mTimeChangePending = false; 958} 959 960bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange( 961 const sp<AMessage> &targetFormat) const { 962 if (targetFormat == NULL) { 963 return true; 964 } 965 966 AString mime; 967 if (!targetFormat->findString("mime", &mime)) { 968 return false; 969 } 970 971 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) { 972 // field-by-field comparison 973 const char * keys[] = { "channel-count", "sample-rate", "is-adts" }; 974 for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) { 975 int32_t oldVal, newVal; 976 if (!mInputFormat->findInt32(keys[i], &oldVal) || 977 !targetFormat->findInt32(keys[i], &newVal) || 978 oldVal != newVal) { 979 return false; 980 } 981 } 982 983 sp<ABuffer> oldBuf, newBuf; 984 if (mInputFormat->findBuffer("csd-0", &oldBuf) && 985 targetFormat->findBuffer("csd-0", &newBuf)) { 986 if (oldBuf->size() != newBuf->size()) { 987 return false; 988 } 989 return !memcmp(oldBuf->data(), newBuf->data(), oldBuf->size()); 990 } 991 } 992 return false; 993} 994 995bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const { 996 if (mInputFormat == NULL) { 997 return false; 998 } 999 1000 if (targetFormat == NULL) { 1001 return true; 1002 } 1003 1004 AString oldMime, newMime; 1005 if (!mInputFormat->findString("mime", &oldMime) 1006 || !targetFormat->findString("mime", &newMime) 1007 || !(oldMime == newMime)) { 1008 return false; 1009 } 1010 1011 bool audio = !strncasecmp(oldMime.c_str(), "audio/", strlen("audio/")); 1012 bool seamless; 1013 if (audio) { 1014 seamless = supportsSeamlessAudioFormatChange(targetFormat); 1015 } else { 1016 int32_t isAdaptive; 1017 seamless = (mCodec != NULL && 1018 mInputFormat->findInt32("adaptive-playback", &isAdaptive) && 1019 isAdaptive); 1020 } 1021 1022 ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str()); 1023 return seamless; 1024} 1025 1026void NuPlayer::Decoder::rememberCodecSpecificData(const sp<AMessage> &format) { 1027 if (format == NULL) { 1028 return; 1029 } 1030 mCSDsForCurrentFormat.clear(); 1031 for (int32_t i = 0; ; ++i) { 1032 AString tag = "csd-"; 1033 tag.append(i); 1034 sp<ABuffer> buffer; 1035 if (!format->findBuffer(tag.c_str(), &buffer)) { 1036 break; 1037 } 1038 mCSDsForCurrentFormat.push(buffer); 1039 } 1040} 1041 1042void NuPlayer::Decoder::notifyResumeCompleteIfNecessary() { 1043 if (mResumePending) { 1044 mResumePending = false; 1045 1046 sp<AMessage> notify = mNotify->dup(); 1047 notify->setInt32("what", kWhatResumeCompleted); 1048 notify->post(); 1049 } 1050} 1051 1052} // namespace android 1053 1054