MediaCodecSource.cpp revision ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5
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 "MediaCodecSource" 19#define DEBUG_DRIFT_TIME 0 20 21#include <inttypes.h> 22 23#include <gui/IGraphicBufferConsumer.h> 24#include <gui/IGraphicBufferProducer.h> 25#include <gui/Surface.h> 26#include <media/ICrypto.h> 27#include <media/stagefright/foundation/ABuffer.h> 28#include <media/stagefright/foundation/ADebug.h> 29#include <media/stagefright/foundation/ALooper.h> 30#include <media/stagefright/foundation/AMessage.h> 31#include <media/stagefright/MediaBuffer.h> 32#include <media/stagefright/MediaCodec.h> 33#include <media/stagefright/MediaCodecList.h> 34#include <media/stagefright/MediaCodecSource.h> 35#include <media/stagefright/MediaErrors.h> 36#include <media/stagefright/MediaSource.h> 37#include <media/stagefright/MetaData.h> 38#include <media/stagefright/PersistentSurface.h> 39#include <media/stagefright/Utils.h> 40 41namespace android { 42 43const int kDefaultSwVideoEncoderFormat = HAL_PIXEL_FORMAT_YCbCr_420_888; 44const int kDefaultSwVideoEncoderDataSpace = HAL_DATASPACE_BT709; 45 46const int kStopTimeoutUs = 300000; // allow 1 sec for shutting down encoder 47 48struct MediaCodecSource::Puller : public AHandler { 49 Puller(const sp<MediaSource> &source); 50 51 status_t start(const sp<MetaData> &meta, const sp<AMessage> ¬ify); 52 void stop(); 53 void stopSource(); 54 void pause(); 55 void resume(); 56 57 bool readBuffer(MediaBuffer **buffer); 58 59protected: 60 virtual void onMessageReceived(const sp<AMessage> &msg); 61 virtual ~Puller(); 62 63private: 64 enum { 65 kWhatStart = 'msta', 66 kWhatStop, 67 kWhatPull, 68 }; 69 70 sp<MediaSource> mSource; 71 sp<AMessage> mNotify; 72 sp<ALooper> mLooper; 73 bool mIsAudio; 74 75 struct Queue { 76 Queue() 77 : mReadPendingSince(0), 78 mPaused(false), 79 mPulling(false) { } 80 int64_t mReadPendingSince; 81 bool mPaused; 82 bool mPulling; 83 Vector<MediaBuffer *> mReadBuffers; 84 85 void flush(); 86 // if queue is empty, return false and set *|buffer| to NULL . Otherwise, pop 87 // buffer from front of the queue, place it into *|buffer| and return true. 88 bool readBuffer(MediaBuffer **buffer); 89 // add a buffer to the back of the queue 90 void pushBuffer(MediaBuffer *mbuf); 91 }; 92 Mutexed<Queue> mQueue; 93 94 status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg); 95 void schedulePull(); 96 void handleEOS(); 97 98 DISALLOW_EVIL_CONSTRUCTORS(Puller); 99}; 100 101MediaCodecSource::Puller::Puller(const sp<MediaSource> &source) 102 : mSource(source), 103 mLooper(new ALooper()), 104 mIsAudio(false) 105{ 106 sp<MetaData> meta = source->getFormat(); 107 const char *mime; 108 CHECK(meta->findCString(kKeyMIMEType, &mime)); 109 110 mIsAudio = !strncasecmp(mime, "audio/", 6); 111 112 mLooper->setName("pull_looper"); 113} 114 115MediaCodecSource::Puller::~Puller() { 116 mLooper->unregisterHandler(id()); 117 mLooper->stop(); 118} 119 120void MediaCodecSource::Puller::Queue::pushBuffer(MediaBuffer *mbuf) { 121 mReadBuffers.push_back(mbuf); 122} 123 124bool MediaCodecSource::Puller::Queue::readBuffer(MediaBuffer **mbuf) { 125 if (mReadBuffers.empty()) { 126 *mbuf = NULL; 127 return false; 128 } 129 *mbuf = *mReadBuffers.begin(); 130 mReadBuffers.erase(mReadBuffers.begin()); 131 return true; 132} 133 134void MediaCodecSource::Puller::Queue::flush() { 135 MediaBuffer *mbuf; 136 while (readBuffer(&mbuf)) { 137 // there are no null buffers in the queue 138 mbuf->release(); 139 } 140} 141 142bool MediaCodecSource::Puller::readBuffer(MediaBuffer **mbuf) { 143 Mutexed<Queue>::Locked queue(mQueue); 144 return queue->readBuffer(mbuf); 145} 146 147status_t MediaCodecSource::Puller::postSynchronouslyAndReturnError( 148 const sp<AMessage> &msg) { 149 sp<AMessage> response; 150 status_t err = msg->postAndAwaitResponse(&response); 151 152 if (err != OK) { 153 return err; 154 } 155 156 if (!response->findInt32("err", &err)) { 157 err = OK; 158 } 159 160 return err; 161} 162 163status_t MediaCodecSource::Puller::start(const sp<MetaData> &meta, const sp<AMessage> ¬ify) { 164 ALOGV("puller (%s) start", mIsAudio ? "audio" : "video"); 165 mLooper->start( 166 false /* runOnCallingThread */, 167 false /* canCallJava */, 168 PRIORITY_AUDIO); 169 mLooper->registerHandler(this); 170 mNotify = notify; 171 172 sp<AMessage> msg = new AMessage(kWhatStart, this); 173 msg->setObject("meta", meta); 174 return postSynchronouslyAndReturnError(msg); 175} 176 177void MediaCodecSource::Puller::stop() { 178 bool interrupt = false; 179 { 180 // mark stopping before actually reaching kWhatStop on the looper, so the pulling will 181 // stop. 182 Mutexed<Queue>::Locked queue(mQueue); 183 queue->mPulling = false; 184 interrupt = queue->mReadPendingSince && (queue->mReadPendingSince < ALooper::GetNowUs() - 1000000); 185 queue->flush(); // flush any unprocessed pulled buffers 186 } 187 188 if (interrupt) { 189 // call source->stop if read has been pending for over a second 190 // TODO: we should really call this if kWhatStop has not returned for more than a second. 191 mSource->stop(); 192 } 193} 194 195void MediaCodecSource::Puller::stopSource() { 196 (new AMessage(kWhatStop, this))->post(); 197} 198 199void MediaCodecSource::Puller::pause() { 200 Mutexed<Queue>::Locked queue(mQueue); 201 queue->mPaused = true; 202} 203 204void MediaCodecSource::Puller::resume() { 205 Mutexed<Queue>::Locked queue(mQueue); 206 queue->mPaused = false; 207} 208 209void MediaCodecSource::Puller::schedulePull() { 210 (new AMessage(kWhatPull, this))->post(); 211} 212 213void MediaCodecSource::Puller::handleEOS() { 214 ALOGV("puller (%s) posting EOS", mIsAudio ? "audio" : "video"); 215 sp<AMessage> msg = mNotify->dup(); 216 msg->setInt32("eos", 1); 217 msg->post(); 218} 219 220void MediaCodecSource::Puller::onMessageReceived(const sp<AMessage> &msg) { 221 switch (msg->what()) { 222 case kWhatStart: 223 { 224 sp<RefBase> obj; 225 CHECK(msg->findObject("meta", &obj)); 226 227 { 228 Mutexed<Queue>::Locked queue(mQueue); 229 queue->mPulling = true; 230 } 231 232 status_t err = mSource->start(static_cast<MetaData *>(obj.get())); 233 234 if (err == OK) { 235 schedulePull(); 236 } 237 238 sp<AMessage> response = new AMessage; 239 response->setInt32("err", err); 240 241 sp<AReplyToken> replyID; 242 CHECK(msg->senderAwaitsResponse(&replyID)); 243 response->postReply(replyID); 244 break; 245 } 246 247 case kWhatStop: 248 { 249 mSource->stop(); 250 break; 251 } 252 253 case kWhatPull: 254 { 255 Mutexed<Queue>::Locked queue(mQueue); 256 queue->mReadPendingSince = ALooper::GetNowUs(); 257 if (!queue->mPulling) { 258 handleEOS(); 259 break; 260 } 261 262 queue.unlock(); 263 MediaBuffer *mbuf = NULL; 264 status_t err = mSource->read(&mbuf); 265 queue.lock(); 266 267 queue->mReadPendingSince = 0; 268 // if we need to discard buffer 269 if (!queue->mPulling || queue->mPaused || err != OK) { 270 if (mbuf != NULL) { 271 mbuf->release(); 272 mbuf = NULL; 273 } 274 if (queue->mPulling && err == OK) { 275 msg->post(); // if simply paused, keep pulling source 276 } else if (err == ERROR_END_OF_STREAM) { 277 ALOGV("stream ended, mbuf %p", mbuf); 278 } else if (err != OK) { 279 ALOGE("error %d reading stream.", err); 280 } 281 } 282 283 if (mbuf != NULL) { 284 queue->pushBuffer(mbuf); 285 } 286 287 queue.unlock(); 288 289 if (mbuf != NULL) { 290 mNotify->post(); 291 msg->post(); 292 } else { 293 handleEOS(); 294 } 295 break; 296 } 297 298 default: 299 TRESPASS(); 300 } 301} 302 303MediaCodecSource::Output::Output() 304 : mEncoderReachedEOS(false), 305 mErrorCode(OK) { 306} 307 308// static 309sp<MediaCodecSource> MediaCodecSource::Create( 310 const sp<ALooper> &looper, 311 const sp<AMessage> &format, 312 const sp<MediaSource> &source, 313 const sp<IGraphicBufferConsumer> &consumer, 314 uint32_t flags) { 315 sp<MediaCodecSource> mediaSource = 316 new MediaCodecSource(looper, format, source, consumer, flags); 317 318 if (mediaSource->init() == OK) { 319 return mediaSource; 320 } 321 return NULL; 322} 323 324status_t MediaCodecSource::start(MetaData* params) { 325 sp<AMessage> msg = new AMessage(kWhatStart, mReflector); 326 msg->setObject("meta", params); 327 return postSynchronouslyAndReturnError(msg); 328} 329 330status_t MediaCodecSource::stop() { 331 sp<AMessage> msg = new AMessage(kWhatStop, mReflector); 332 return postSynchronouslyAndReturnError(msg); 333} 334 335status_t MediaCodecSource::pause() { 336 (new AMessage(kWhatPause, mReflector))->post(); 337 return OK; 338} 339 340sp<IGraphicBufferProducer> MediaCodecSource::getGraphicBufferProducer() { 341 CHECK(mFlags & FLAG_USE_SURFACE_INPUT); 342 return mGraphicBufferProducer; 343} 344 345status_t MediaCodecSource::read( 346 MediaBuffer** buffer, const ReadOptions* /* options */) { 347 Mutexed<Output>::Locked output(mOutput); 348 349 *buffer = NULL; 350 while (output->mBufferQueue.size() == 0 && !output->mEncoderReachedEOS) { 351 output.waitForCondition(output->mCond); 352 } 353 if (!output->mEncoderReachedEOS) { 354 *buffer = *output->mBufferQueue.begin(); 355 output->mBufferQueue.erase(output->mBufferQueue.begin()); 356 return OK; 357 } 358 return output->mErrorCode; 359} 360 361void MediaCodecSource::signalBufferReturned(MediaBuffer *buffer) { 362 buffer->setObserver(0); 363 buffer->release(); 364} 365 366MediaCodecSource::MediaCodecSource( 367 const sp<ALooper> &looper, 368 const sp<AMessage> &outputFormat, 369 const sp<MediaSource> &source, 370 const sp<IGraphicBufferConsumer> &consumer, 371 uint32_t flags) 372 : mLooper(looper), 373 mOutputFormat(outputFormat), 374 mMeta(new MetaData), 375 mFlags(flags), 376 mIsVideo(false), 377 mStarted(false), 378 mStopping(false), 379 mDoMoreWorkPending(false), 380 mSetEncoderFormat(false), 381 mEncoderFormat(0), 382 mEncoderDataSpace(0), 383 mGraphicBufferConsumer(consumer), 384 mFirstSampleTimeUs(-1ll), 385 mGeneration(0) { 386 CHECK(mLooper != NULL); 387 388 AString mime; 389 CHECK(mOutputFormat->findString("mime", &mime)); 390 391 if (!strncasecmp("video/", mime.c_str(), 6)) { 392 mIsVideo = true; 393 } 394 395 if (!(mFlags & FLAG_USE_SURFACE_INPUT)) { 396 mPuller = new Puller(source); 397 } 398} 399 400MediaCodecSource::~MediaCodecSource() { 401 releaseEncoder(); 402 403 mCodecLooper->stop(); 404 mLooper->unregisterHandler(mReflector->id()); 405} 406 407status_t MediaCodecSource::init() { 408 status_t err = initEncoder(); 409 410 if (err != OK) { 411 releaseEncoder(); 412 } 413 414 return err; 415} 416 417status_t MediaCodecSource::initEncoder() { 418 mReflector = new AHandlerReflector<MediaCodecSource>(this); 419 mLooper->registerHandler(mReflector); 420 421 mCodecLooper = new ALooper; 422 mCodecLooper->setName("codec_looper"); 423 mCodecLooper->start(); 424 425 if (mFlags & FLAG_USE_METADATA_INPUT) { 426 mOutputFormat->setInt32("store-metadata-in-buffers", 1); 427 } 428 429 if (mFlags & FLAG_USE_SURFACE_INPUT) { 430 mOutputFormat->setInt32("create-input-buffers-suspended", 1); 431 } 432 433 AString outputMIME; 434 CHECK(mOutputFormat->findString("mime", &outputMIME)); 435 436 Vector<AString> matchingCodecs; 437 MediaCodecList::findMatchingCodecs( 438 outputMIME.c_str(), true /* encoder */, 439 ((mFlags & FLAG_PREFER_SOFTWARE_CODEC) ? MediaCodecList::kPreferSoftwareCodecs : 0), 440 &matchingCodecs); 441 442 status_t err = NO_INIT; 443 for (size_t ix = 0; ix < matchingCodecs.size(); ++ix) { 444 mEncoder = MediaCodec::CreateByComponentName( 445 mCodecLooper, matchingCodecs[ix]); 446 447 if (mEncoder == NULL) { 448 continue; 449 } 450 451 ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str()); 452 453 mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, mReflector); 454 mEncoder->setCallback(mEncoderActivityNotify); 455 456 err = mEncoder->configure( 457 mOutputFormat, 458 NULL /* nativeWindow */, 459 NULL /* crypto */, 460 MediaCodec::CONFIGURE_FLAG_ENCODE); 461 462 if (err == OK) { 463 break; 464 } 465 mEncoder->release(); 466 mEncoder = NULL; 467 } 468 469 if (err != OK) { 470 return err; 471 } 472 473 mEncoder->getOutputFormat(&mOutputFormat); 474 convertMessageToMetaData(mOutputFormat, mMeta); 475 476 if (mFlags & FLAG_USE_SURFACE_INPUT) { 477 CHECK(mIsVideo); 478 479 if (mGraphicBufferConsumer != NULL) { 480 // When using persistent surface, we are only interested in the 481 // consumer, but have to use PersistentSurface as a wrapper to 482 // pass consumer over messages (similar to BufferProducerWrapper) 483 err = mEncoder->setInputSurface( 484 new PersistentSurface(NULL, mGraphicBufferConsumer)); 485 } else { 486 err = mEncoder->createInputSurface(&mGraphicBufferProducer); 487 } 488 489 if (err != OK) { 490 return err; 491 } 492 } 493 494 sp<AMessage> inputFormat; 495 int32_t usingSwReadOften; 496 mSetEncoderFormat = false; 497 if (mEncoder->getInputFormat(&inputFormat) == OK 498 && inputFormat->findInt32("using-sw-read-often", &usingSwReadOften) 499 && usingSwReadOften) { 500 // this is a SW encoder; signal source to allocate SW readable buffers 501 mSetEncoderFormat = true; 502 mEncoderFormat = kDefaultSwVideoEncoderFormat; 503 mEncoderDataSpace = kDefaultSwVideoEncoderDataSpace; 504 } 505 506 err = mEncoder->start(); 507 508 if (err != OK) { 509 return err; 510 } 511 512 { 513 Mutexed<Output>::Locked output(mOutput); 514 output->mEncoderReachedEOS = false; 515 output->mErrorCode = OK; 516 } 517 518 return OK; 519} 520 521void MediaCodecSource::releaseEncoder() { 522 if (mEncoder == NULL) { 523 return; 524 } 525 526 mEncoder->release(); 527 mEncoder.clear(); 528} 529 530status_t MediaCodecSource::postSynchronouslyAndReturnError( 531 const sp<AMessage> &msg) { 532 sp<AMessage> response; 533 status_t err = msg->postAndAwaitResponse(&response); 534 535 if (err != OK) { 536 return err; 537 } 538 539 if (!response->findInt32("err", &err)) { 540 err = OK; 541 } 542 543 return err; 544} 545 546void MediaCodecSource::signalEOS(status_t err) { 547 bool reachedEOS = false; 548 { 549 Mutexed<Output>::Locked output(mOutput); 550 reachedEOS = output->mEncoderReachedEOS; 551 if (!reachedEOS) { 552 ALOGV("encoder (%s) reached EOS", mIsVideo ? "video" : "audio"); 553 // release all unread media buffers 554 for (List<MediaBuffer*>::iterator it = output->mBufferQueue.begin(); 555 it != output->mBufferQueue.end(); it++) { 556 (*it)->release(); 557 } 558 output->mBufferQueue.clear(); 559 output->mEncoderReachedEOS = true; 560 output->mErrorCode = err; 561 output->mCond.signal(); 562 563 reachedEOS = true; 564 output.unlock(); 565 releaseEncoder(); 566 } 567 } 568 569 if (mStopping && reachedEOS) { 570 ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio"); 571 mPuller->stopSource(); 572 ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio"); 573 // posting reply to everyone that's waiting 574 List<sp<AReplyToken>>::iterator it; 575 for (it = mStopReplyIDQueue.begin(); 576 it != mStopReplyIDQueue.end(); it++) { 577 (new AMessage)->postReply(*it); 578 } 579 mStopReplyIDQueue.clear(); 580 mStopping = false; 581 ++mGeneration; 582 } 583} 584 585void MediaCodecSource::suspend() { 586 CHECK(mFlags & FLAG_USE_SURFACE_INPUT); 587 if (mEncoder != NULL) { 588 sp<AMessage> params = new AMessage; 589 params->setInt32("drop-input-frames", true); 590 mEncoder->setParameters(params); 591 } 592} 593 594void MediaCodecSource::resume(int64_t skipFramesBeforeUs) { 595 CHECK(mFlags & FLAG_USE_SURFACE_INPUT); 596 if (mEncoder != NULL) { 597 sp<AMessage> params = new AMessage; 598 params->setInt32("drop-input-frames", false); 599 if (skipFramesBeforeUs > 0) { 600 params->setInt64("skip-frames-before", skipFramesBeforeUs); 601 } 602 mEncoder->setParameters(params); 603 } 604} 605 606status_t MediaCodecSource::feedEncoderInputBuffers() { 607 MediaBuffer* mbuf = NULL; 608 while (!mAvailEncoderInputIndices.empty() && mPuller->readBuffer(&mbuf)) { 609 size_t bufferIndex = *mAvailEncoderInputIndices.begin(); 610 mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin()); 611 612 int64_t timeUs = 0ll; 613 uint32_t flags = 0; 614 size_t size = 0; 615 616 if (mbuf != NULL) { 617 CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs)); 618 619 // push decoding time for video, or drift time for audio 620 if (mIsVideo) { 621 mDecodingTimeQueue.push_back(timeUs); 622 } else { 623#if DEBUG_DRIFT_TIME 624 if (mFirstSampleTimeUs < 0ll) { 625 mFirstSampleTimeUs = timeUs; 626 } 627 628 int64_t driftTimeUs = 0; 629 if (mbuf->meta_data()->findInt64(kKeyDriftTime, &driftTimeUs) 630 && driftTimeUs) { 631 driftTimeUs = timeUs - mFirstSampleTimeUs - driftTimeUs; 632 } 633 mDriftTimeQueue.push_back(driftTimeUs); 634#endif // DEBUG_DRIFT_TIME 635 } 636 637 sp<ABuffer> inbuf; 638 status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf); 639 if (err != OK || inbuf == NULL) { 640 mbuf->release(); 641 signalEOS(); 642 break; 643 } 644 645 size = mbuf->size(); 646 647 memcpy(inbuf->data(), mbuf->data(), size); 648 649 if (mIsVideo) { 650 // video encoder will release MediaBuffer when done 651 // with underlying data. 652 inbuf->setMediaBufferBase(mbuf); 653 } else { 654 mbuf->release(); 655 } 656 } else { 657 flags = MediaCodec::BUFFER_FLAG_EOS; 658 } 659 660 status_t err = mEncoder->queueInputBuffer( 661 bufferIndex, 0, size, timeUs, flags); 662 663 if (err != OK) { 664 return err; 665 } 666 } 667 668 return OK; 669} 670 671status_t MediaCodecSource::onStart(MetaData *params) { 672 if (mStopping) { 673 ALOGE("Failed to start while we're stopping"); 674 return INVALID_OPERATION; 675 } 676 677 if (mStarted) { 678 ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio"); 679 if (mFlags & FLAG_USE_SURFACE_INPUT) { 680 resume(); 681 } else { 682 CHECK(mPuller != NULL); 683 mPuller->resume(); 684 } 685 return OK; 686 } 687 688 ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio"); 689 690 status_t err = OK; 691 692 if (mFlags & FLAG_USE_SURFACE_INPUT) { 693 int64_t startTimeUs; 694 if (!params || !params->findInt64(kKeyTime, &startTimeUs)) { 695 startTimeUs = -1ll; 696 } 697 resume(startTimeUs); 698 } else { 699 CHECK(mPuller != NULL); 700 sp<MetaData> meta = params; 701 if (mSetEncoderFormat) { 702 if (meta == NULL) { 703 meta = new MetaData; 704 } 705 meta->setInt32(kKeyPixelFormat, mEncoderFormat); 706 meta->setInt32(kKeyColorSpace, mEncoderDataSpace); 707 } 708 709 sp<AMessage> notify = new AMessage(kWhatPullerNotify, mReflector); 710 err = mPuller->start(meta.get(), notify); 711 if (err != OK) { 712 return err; 713 } 714 } 715 716 ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio"); 717 718 mStarted = true; 719 return OK; 720} 721 722void MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) { 723 switch (msg->what()) { 724 case kWhatPullerNotify: 725 { 726 int32_t eos = 0; 727 if (msg->findInt32("eos", &eos) && eos) { 728 ALOGV("puller (%s) reached EOS", mIsVideo ? "video" : "audio"); 729 signalEOS(); 730 break; 731 } 732 733 if (mEncoder == NULL) { 734 ALOGV("got msg '%s' after encoder shutdown.", msg->debugString().c_str()); 735 break; 736 } 737 738 feedEncoderInputBuffers(); 739 break; 740 } 741 case kWhatEncoderActivity: 742 { 743 if (mEncoder == NULL) { 744 break; 745 } 746 747 int32_t cbID; 748 CHECK(msg->findInt32("callbackID", &cbID)); 749 if (cbID == MediaCodec::CB_INPUT_AVAILABLE) { 750 int32_t index; 751 CHECK(msg->findInt32("index", &index)); 752 753 mAvailEncoderInputIndices.push_back(index); 754 feedEncoderInputBuffers(); 755 } else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) { 756 int32_t index; 757 size_t offset; 758 size_t size; 759 int64_t timeUs; 760 int32_t flags; 761 762 CHECK(msg->findInt32("index", &index)); 763 CHECK(msg->findSize("offset", &offset)); 764 CHECK(msg->findSize("size", &size)); 765 CHECK(msg->findInt64("timeUs", &timeUs)); 766 CHECK(msg->findInt32("flags", &flags)); 767 768 if (flags & MediaCodec::BUFFER_FLAG_EOS) { 769 mEncoder->releaseOutputBuffer(index); 770 signalEOS(); 771 break; 772 } 773 774 sp<ABuffer> outbuf; 775 status_t err = mEncoder->getOutputBuffer(index, &outbuf); 776 if (err != OK || outbuf == NULL) { 777 signalEOS(); 778 break; 779 } 780 781 MediaBuffer *mbuf = new MediaBuffer(outbuf->size()); 782 memcpy(mbuf->data(), outbuf->data(), outbuf->size()); 783 784 if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) { 785 if (mIsVideo) { 786 int64_t decodingTimeUs; 787 if (mFlags & FLAG_USE_SURFACE_INPUT) { 788 // GraphicBufferSource is supposed to discard samples 789 // queued before start, and offset timeUs by start time 790 CHECK_GE(timeUs, 0ll); 791 // TODO: 792 // Decoding time for surface source is unavailable, 793 // use presentation time for now. May need to move 794 // this logic into MediaCodec. 795 decodingTimeUs = timeUs; 796 } else { 797 CHECK(!mDecodingTimeQueue.empty()); 798 decodingTimeUs = *(mDecodingTimeQueue.begin()); 799 mDecodingTimeQueue.erase(mDecodingTimeQueue.begin()); 800 } 801 mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs); 802 803 ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64, 804 timeUs, timeUs / 1E6, decodingTimeUs - timeUs); 805 } else { 806 int64_t driftTimeUs = 0; 807#if DEBUG_DRIFT_TIME 808 CHECK(!mDriftTimeQueue.empty()); 809 driftTimeUs = *(mDriftTimeQueue.begin()); 810 mDriftTimeQueue.erase(mDriftTimeQueue.begin()); 811 mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs); 812#endif // DEBUG_DRIFT_TIME 813 ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64, 814 timeUs, timeUs / 1E6, driftTimeUs); 815 } 816 mbuf->meta_data()->setInt64(kKeyTime, timeUs); 817 } else { 818 mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true); 819 } 820 if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) { 821 mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true); 822 } 823 mbuf->setObserver(this); 824 mbuf->add_ref(); 825 826 { 827 Mutexed<Output>::Locked output(mOutput); 828 output->mBufferQueue.push_back(mbuf); 829 output->mCond.signal(); 830 } 831 832 mEncoder->releaseOutputBuffer(index); 833 } else if (cbID == MediaCodec::CB_ERROR) { 834 status_t err; 835 CHECK(msg->findInt32("err", &err)); 836 ALOGE("Encoder (%s) reported error : 0x%x", 837 mIsVideo ? "video" : "audio", err); 838 signalEOS(); 839 } 840 break; 841 } 842 case kWhatStart: 843 { 844 sp<AReplyToken> replyID; 845 CHECK(msg->senderAwaitsResponse(&replyID)); 846 847 sp<RefBase> obj; 848 CHECK(msg->findObject("meta", &obj)); 849 MetaData *params = static_cast<MetaData *>(obj.get()); 850 851 sp<AMessage> response = new AMessage; 852 response->setInt32("err", onStart(params)); 853 response->postReply(replyID); 854 break; 855 } 856 case kWhatStop: 857 { 858 ALOGI("encoder (%s) stopping", mIsVideo ? "video" : "audio"); 859 860 sp<AReplyToken> replyID; 861 CHECK(msg->senderAwaitsResponse(&replyID)); 862 863 if (mOutput.lock()->mEncoderReachedEOS) { 864 // if we already reached EOS, reply and return now 865 ALOGI("encoder (%s) already stopped", 866 mIsVideo ? "video" : "audio"); 867 (new AMessage)->postReply(replyID); 868 break; 869 } 870 871 mStopReplyIDQueue.push_back(replyID); 872 if (mStopping) { 873 // nothing to do if we're already stopping, reply will be posted 874 // to all when we're stopped. 875 break; 876 } 877 878 mStopping = true; 879 880 // if using surface, signal source EOS and wait for EOS to come back. 881 // otherwise, stop puller (which also clears the input buffer queue) 882 // and wait for the EOS message. We cannot call source->stop() because 883 // the encoder may still be processing input buffers. 884 if (mFlags & FLAG_USE_SURFACE_INPUT) { 885 mEncoder->signalEndOfInputStream(); 886 } else { 887 mPuller->stop(); 888 } 889 890 // complete stop even if encoder/puller stalled 891 sp<AMessage> timeoutMsg = new AMessage(kWhatStopStalled, mReflector); 892 timeoutMsg->setInt32("generation", mGeneration); 893 timeoutMsg->post(kStopTimeoutUs); 894 break; 895 } 896 897 case kWhatStopStalled: 898 { 899 int32_t generation; 900 CHECK(msg->findInt32("generation", &generation)); 901 if (generation != mGeneration) { 902 break; 903 } 904 905 if (!(mFlags & FLAG_USE_SURFACE_INPUT)) { 906 ALOGV("source (%s) stopping", mIsVideo ? "video" : "audio"); 907 mPuller->stopSource(); 908 ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio"); 909 } 910 signalEOS(); 911 } 912 913 case kWhatPause: 914 { 915 if (mFlags & FLAG_USE_SURFACE_INPUT) { 916 suspend(); 917 } else { 918 CHECK(mPuller != NULL); 919 mPuller->pause(); 920 } 921 break; 922 } 923 default: 924 TRESPASS(); 925 } 926} 927 928} // namespace android 929