MediaCodec.cpp revision c481b5012a5f6cf72e5e93b36f1ed4c9169916f2
1/* 2 * Copyright 2012, 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 "MediaCodec" 19#include <inttypes.h> 20 21#include "include/avc_utils.h" 22#include "include/SoftwareRenderer.h" 23 24#include <binder/IBatteryStats.h> 25#include <binder/IMemory.h> 26#include <binder/IServiceManager.h> 27#include <binder/MemoryDealer.h> 28#include <gui/Surface.h> 29#include <media/ICrypto.h> 30#include <media/stagefright/foundation/ABuffer.h> 31#include <media/stagefright/foundation/ADebug.h> 32#include <media/stagefright/foundation/AMessage.h> 33#include <media/stagefright/foundation/AString.h> 34#include <media/stagefright/foundation/hexdump.h> 35#include <media/stagefright/ACodec.h> 36#include <media/stagefright/BufferProducerWrapper.h> 37#include <media/stagefright/MediaCodec.h> 38#include <media/stagefright/MediaCodecList.h> 39#include <media/stagefright/MediaDefs.h> 40#include <media/stagefright/MediaErrors.h> 41#include <media/stagefright/MediaFilter.h> 42#include <media/stagefright/MetaData.h> 43#include <media/stagefright/NativeWindowWrapper.h> 44#include <private/android_filesystem_config.h> 45#include <utils/Log.h> 46#include <utils/Singleton.h> 47 48namespace android { 49 50struct MediaCodec::BatteryNotifier : public Singleton<BatteryNotifier> { 51 BatteryNotifier(); 52 53 void noteStartVideo(); 54 void noteStopVideo(); 55 void noteStartAudio(); 56 void noteStopAudio(); 57 58private: 59 int32_t mVideoRefCount; 60 int32_t mAudioRefCount; 61 sp<IBatteryStats> mBatteryStatService; 62}; 63 64ANDROID_SINGLETON_STATIC_INSTANCE(MediaCodec::BatteryNotifier) 65 66MediaCodec::BatteryNotifier::BatteryNotifier() : 67 mVideoRefCount(0), 68 mAudioRefCount(0) { 69 // get battery service 70 const sp<IServiceManager> sm(defaultServiceManager()); 71 if (sm != NULL) { 72 const String16 name("batterystats"); 73 mBatteryStatService = interface_cast<IBatteryStats>(sm->getService(name)); 74 if (mBatteryStatService == NULL) { 75 ALOGE("batterystats service unavailable!"); 76 } 77 } 78} 79 80void MediaCodec::BatteryNotifier::noteStartVideo() { 81 if (mVideoRefCount == 0 && mBatteryStatService != NULL) { 82 mBatteryStatService->noteStartVideo(AID_MEDIA); 83 } 84 mVideoRefCount++; 85} 86 87void MediaCodec::BatteryNotifier::noteStopVideo() { 88 if (mVideoRefCount == 0) { 89 ALOGW("BatteryNotifier::noteStop(): video refcount is broken!"); 90 return; 91 } 92 93 mVideoRefCount--; 94 if (mVideoRefCount == 0 && mBatteryStatService != NULL) { 95 mBatteryStatService->noteStopVideo(AID_MEDIA); 96 } 97} 98 99void MediaCodec::BatteryNotifier::noteStartAudio() { 100 if (mAudioRefCount == 0 && mBatteryStatService != NULL) { 101 mBatteryStatService->noteStartAudio(AID_MEDIA); 102 } 103 mAudioRefCount++; 104} 105 106void MediaCodec::BatteryNotifier::noteStopAudio() { 107 if (mAudioRefCount == 0) { 108 ALOGW("BatteryNotifier::noteStop(): audio refcount is broken!"); 109 return; 110 } 111 112 mAudioRefCount--; 113 if (mAudioRefCount == 0 && mBatteryStatService != NULL) { 114 mBatteryStatService->noteStopAudio(AID_MEDIA); 115 } 116} 117// static 118sp<MediaCodec> MediaCodec::CreateByType( 119 const sp<ALooper> &looper, const char *mime, bool encoder, status_t *err) { 120 sp<MediaCodec> codec = new MediaCodec(looper); 121 122 const status_t ret = codec->init(mime, true /* nameIsType */, encoder); 123 if (err != NULL) { 124 *err = ret; 125 } 126 return ret == OK ? codec : NULL; // NULL deallocates codec. 127} 128 129// static 130sp<MediaCodec> MediaCodec::CreateByComponentName( 131 const sp<ALooper> &looper, const char *name, status_t *err) { 132 sp<MediaCodec> codec = new MediaCodec(looper); 133 134 const status_t ret = codec->init(name, false /* nameIsType */, false /* encoder */); 135 if (err != NULL) { 136 *err = ret; 137 } 138 return ret == OK ? codec : NULL; // NULL deallocates codec. 139} 140 141MediaCodec::MediaCodec(const sp<ALooper> &looper) 142 : mState(UNINITIALIZED), 143 mLooper(looper), 144 mCodec(NULL), 145 mReplyID(0), 146 mFlags(0), 147 mStickyError(OK), 148 mSoftRenderer(NULL), 149 mBatteryStatNotified(false), 150 mIsVideo(false), 151 mDequeueInputTimeoutGeneration(0), 152 mDequeueInputReplyID(0), 153 mDequeueOutputTimeoutGeneration(0), 154 mDequeueOutputReplyID(0), 155 mHaveInputSurface(false) { 156} 157 158MediaCodec::~MediaCodec() { 159 CHECK_EQ(mState, UNINITIALIZED); 160} 161 162// static 163status_t MediaCodec::PostAndAwaitResponse( 164 const sp<AMessage> &msg, sp<AMessage> *response) { 165 status_t err = msg->postAndAwaitResponse(response); 166 167 if (err != OK) { 168 return err; 169 } 170 171 if (!(*response)->findInt32("err", &err)) { 172 err = OK; 173 } 174 175 return err; 176} 177 178// static 179void MediaCodec::PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err) { 180 sp<AMessage> response = new AMessage; 181 response->setInt32("err", err); 182 response->postReply(replyID); 183} 184 185status_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder) { 186 // save init parameters for reset 187 mInitName = name; 188 mInitNameIsType = nameIsType; 189 mInitIsEncoder = encoder; 190 191 // Current video decoders do not return from OMX_FillThisBuffer 192 // quickly, violating the OpenMAX specs, until that is remedied 193 // we need to invest in an extra looper to free the main event 194 // queue. 195 196 if (nameIsType || !strncasecmp(name.c_str(), "omx.", 4)) { 197 mCodec = new ACodec; 198 } else if (!nameIsType 199 && !strncasecmp(name.c_str(), "android.filter.", 15)) { 200 mCodec = new MediaFilter; 201 } else { 202 return NAME_NOT_FOUND; 203 } 204 205 bool needDedicatedLooper = false; 206 if (nameIsType && !strncasecmp(name.c_str(), "video/", 6)) { 207 needDedicatedLooper = true; 208 } else { 209 AString tmp = name; 210 if (tmp.endsWith(".secure")) { 211 tmp.erase(tmp.size() - 7, 7); 212 } 213 const sp<IMediaCodecList> mcl = MediaCodecList::getInstance(); 214 ssize_t codecIdx = mcl->findCodecByName(tmp.c_str()); 215 if (codecIdx >= 0) { 216 const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx); 217 Vector<AString> mimes; 218 info->getSupportedMimes(&mimes); 219 for (size_t i = 0; i < mimes.size(); i++) { 220 if (mimes[i].startsWith("video/")) { 221 needDedicatedLooper = true; 222 break; 223 } 224 } 225 } 226 } 227 228 if (needDedicatedLooper) { 229 if (mCodecLooper == NULL) { 230 mCodecLooper = new ALooper; 231 mCodecLooper->setName("CodecLooper"); 232 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO); 233 } 234 235 mCodecLooper->registerHandler(mCodec); 236 } else { 237 mLooper->registerHandler(mCodec); 238 } 239 240 mLooper->registerHandler(this); 241 242 mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, this)); 243 244 sp<AMessage> msg = new AMessage(kWhatInit, this); 245 msg->setString("name", name); 246 msg->setInt32("nameIsType", nameIsType); 247 248 if (nameIsType) { 249 msg->setInt32("encoder", encoder); 250 } 251 252 sp<AMessage> response; 253 return PostAndAwaitResponse(msg, &response); 254} 255 256status_t MediaCodec::setCallback(const sp<AMessage> &callback) { 257 sp<AMessage> msg = new AMessage(kWhatSetCallback, this); 258 msg->setMessage("callback", callback); 259 260 sp<AMessage> response; 261 return PostAndAwaitResponse(msg, &response); 262} 263 264status_t MediaCodec::configure( 265 const sp<AMessage> &format, 266 const sp<Surface> &nativeWindow, 267 const sp<ICrypto> &crypto, 268 uint32_t flags) { 269 sp<AMessage> msg = new AMessage(kWhatConfigure, this); 270 271 msg->setMessage("format", format); 272 msg->setInt32("flags", flags); 273 274 if (nativeWindow != NULL) { 275 msg->setObject( 276 "native-window", 277 new NativeWindowWrapper(nativeWindow)); 278 } 279 280 if (crypto != NULL) { 281 msg->setPointer("crypto", crypto.get()); 282 } 283 284 sp<AMessage> response; 285 status_t err = PostAndAwaitResponse(msg, &response); 286 287 if (err != OK && err != INVALID_OPERATION) { 288 // MediaCodec now set state to UNINITIALIZED upon any fatal error. 289 // To maintain backward-compatibility, do a reset() to put codec 290 // back into INITIALIZED state. 291 // But don't reset if the err is INVALID_OPERATION, which means 292 // the configure failure is due to wrong state. 293 294 ALOGE("configure failed with err 0x%08x, resetting...", err); 295 reset(); 296 } 297 298 return err; 299} 300 301status_t MediaCodec::createInputSurface( 302 sp<IGraphicBufferProducer>* bufferProducer) { 303 sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, this); 304 305 sp<AMessage> response; 306 status_t err = PostAndAwaitResponse(msg, &response); 307 if (err == NO_ERROR) { 308 // unwrap the sp<IGraphicBufferProducer> 309 sp<RefBase> obj; 310 bool found = response->findObject("input-surface", &obj); 311 CHECK(found); 312 sp<BufferProducerWrapper> wrapper( 313 static_cast<BufferProducerWrapper*>(obj.get())); 314 *bufferProducer = wrapper->getBufferProducer(); 315 } else { 316 ALOGW("createInputSurface failed, err=%d", err); 317 } 318 return err; 319} 320 321status_t MediaCodec::start() { 322 sp<AMessage> msg = new AMessage(kWhatStart, this); 323 324 sp<AMessage> response; 325 return PostAndAwaitResponse(msg, &response); 326} 327 328status_t MediaCodec::stop() { 329 sp<AMessage> msg = new AMessage(kWhatStop, this); 330 331 sp<AMessage> response; 332 return PostAndAwaitResponse(msg, &response); 333} 334 335status_t MediaCodec::release() { 336 sp<AMessage> msg = new AMessage(kWhatRelease, this); 337 338 sp<AMessage> response; 339 return PostAndAwaitResponse(msg, &response); 340} 341 342status_t MediaCodec::reset() { 343 /* When external-facing MediaCodec object is created, 344 it is already initialized. Thus, reset is essentially 345 release() followed by init(), plus clearing the state */ 346 347 status_t err = release(); 348 349 // unregister handlers 350 if (mCodec != NULL) { 351 if (mCodecLooper != NULL) { 352 mCodecLooper->unregisterHandler(mCodec->id()); 353 } else { 354 mLooper->unregisterHandler(mCodec->id()); 355 } 356 mCodec = NULL; 357 } 358 mLooper->unregisterHandler(id()); 359 360 mFlags = 0; // clear all flags 361 mStickyError = OK; 362 363 // reset state not reset by setState(UNINITIALIZED) 364 mReplyID = 0; 365 mDequeueInputReplyID = 0; 366 mDequeueOutputReplyID = 0; 367 mDequeueInputTimeoutGeneration = 0; 368 mDequeueOutputTimeoutGeneration = 0; 369 mHaveInputSurface = false; 370 371 if (err == OK) { 372 err = init(mInitName, mInitNameIsType, mInitIsEncoder); 373 } 374 return err; 375} 376 377status_t MediaCodec::queueInputBuffer( 378 size_t index, 379 size_t offset, 380 size_t size, 381 int64_t presentationTimeUs, 382 uint32_t flags, 383 AString *errorDetailMsg) { 384 if (errorDetailMsg != NULL) { 385 errorDetailMsg->clear(); 386 } 387 388 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this); 389 msg->setSize("index", index); 390 msg->setSize("offset", offset); 391 msg->setSize("size", size); 392 msg->setInt64("timeUs", presentationTimeUs); 393 msg->setInt32("flags", flags); 394 msg->setPointer("errorDetailMsg", errorDetailMsg); 395 396 sp<AMessage> response; 397 return PostAndAwaitResponse(msg, &response); 398} 399 400status_t MediaCodec::queueSecureInputBuffer( 401 size_t index, 402 size_t offset, 403 const CryptoPlugin::SubSample *subSamples, 404 size_t numSubSamples, 405 const uint8_t key[16], 406 const uint8_t iv[16], 407 CryptoPlugin::Mode mode, 408 int64_t presentationTimeUs, 409 uint32_t flags, 410 AString *errorDetailMsg) { 411 if (errorDetailMsg != NULL) { 412 errorDetailMsg->clear(); 413 } 414 415 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this); 416 msg->setSize("index", index); 417 msg->setSize("offset", offset); 418 msg->setPointer("subSamples", (void *)subSamples); 419 msg->setSize("numSubSamples", numSubSamples); 420 msg->setPointer("key", (void *)key); 421 msg->setPointer("iv", (void *)iv); 422 msg->setInt32("mode", mode); 423 msg->setInt64("timeUs", presentationTimeUs); 424 msg->setInt32("flags", flags); 425 msg->setPointer("errorDetailMsg", errorDetailMsg); 426 427 sp<AMessage> response; 428 status_t err = PostAndAwaitResponse(msg, &response); 429 430 return err; 431} 432 433status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) { 434 sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, this); 435 msg->setInt64("timeoutUs", timeoutUs); 436 437 sp<AMessage> response; 438 status_t err; 439 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 440 return err; 441 } 442 443 CHECK(response->findSize("index", index)); 444 445 return OK; 446} 447 448status_t MediaCodec::dequeueOutputBuffer( 449 size_t *index, 450 size_t *offset, 451 size_t *size, 452 int64_t *presentationTimeUs, 453 uint32_t *flags, 454 int64_t timeoutUs) { 455 sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, this); 456 msg->setInt64("timeoutUs", timeoutUs); 457 458 sp<AMessage> response; 459 status_t err; 460 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 461 return err; 462 } 463 464 CHECK(response->findSize("index", index)); 465 CHECK(response->findSize("offset", offset)); 466 CHECK(response->findSize("size", size)); 467 CHECK(response->findInt64("timeUs", presentationTimeUs)); 468 CHECK(response->findInt32("flags", (int32_t *)flags)); 469 470 return OK; 471} 472 473status_t MediaCodec::renderOutputBufferAndRelease(size_t index) { 474 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this); 475 msg->setSize("index", index); 476 msg->setInt32("render", true); 477 478 sp<AMessage> response; 479 return PostAndAwaitResponse(msg, &response); 480} 481 482status_t MediaCodec::renderOutputBufferAndRelease(size_t index, int64_t timestampNs) { 483 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this); 484 msg->setSize("index", index); 485 msg->setInt32("render", true); 486 msg->setInt64("timestampNs", timestampNs); 487 488 sp<AMessage> response; 489 return PostAndAwaitResponse(msg, &response); 490} 491 492status_t MediaCodec::releaseOutputBuffer(size_t index) { 493 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this); 494 msg->setSize("index", index); 495 496 sp<AMessage> response; 497 return PostAndAwaitResponse(msg, &response); 498} 499 500status_t MediaCodec::signalEndOfInputStream() { 501 sp<AMessage> msg = new AMessage(kWhatSignalEndOfInputStream, this); 502 503 sp<AMessage> response; 504 return PostAndAwaitResponse(msg, &response); 505} 506 507status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const { 508 sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, this); 509 510 sp<AMessage> response; 511 status_t err; 512 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 513 return err; 514 } 515 516 CHECK(response->findMessage("format", format)); 517 518 return OK; 519} 520 521status_t MediaCodec::getInputFormat(sp<AMessage> *format) const { 522 sp<AMessage> msg = new AMessage(kWhatGetInputFormat, this); 523 524 sp<AMessage> response; 525 status_t err; 526 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 527 return err; 528 } 529 530 CHECK(response->findMessage("format", format)); 531 532 return OK; 533} 534 535status_t MediaCodec::getName(AString *name) const { 536 sp<AMessage> msg = new AMessage(kWhatGetName, this); 537 538 sp<AMessage> response; 539 status_t err; 540 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 541 return err; 542 } 543 544 CHECK(response->findString("name", name)); 545 546 return OK; 547} 548 549status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const { 550 sp<AMessage> msg = new AMessage(kWhatGetBuffers, this); 551 msg->setInt32("portIndex", kPortIndexInput); 552 msg->setPointer("buffers", buffers); 553 554 sp<AMessage> response; 555 return PostAndAwaitResponse(msg, &response); 556} 557 558status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const { 559 sp<AMessage> msg = new AMessage(kWhatGetBuffers, this); 560 msg->setInt32("portIndex", kPortIndexOutput); 561 msg->setPointer("buffers", buffers); 562 563 sp<AMessage> response; 564 return PostAndAwaitResponse(msg, &response); 565} 566 567status_t MediaCodec::getOutputBuffer(size_t index, sp<ABuffer> *buffer) { 568 sp<AMessage> format; 569 return getBufferAndFormat(kPortIndexOutput, index, buffer, &format); 570} 571 572status_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) { 573 sp<ABuffer> buffer; 574 return getBufferAndFormat(kPortIndexOutput, index, &buffer, format); 575} 576 577status_t MediaCodec::getInputBuffer(size_t index, sp<ABuffer> *buffer) { 578 sp<AMessage> format; 579 return getBufferAndFormat(kPortIndexInput, index, buffer, &format); 580} 581 582bool MediaCodec::isExecuting() const { 583 return mState == STARTED || mState == FLUSHED; 584} 585 586status_t MediaCodec::getBufferAndFormat( 587 size_t portIndex, size_t index, 588 sp<ABuffer> *buffer, sp<AMessage> *format) { 589 // use mutex instead of a context switch 590 591 buffer->clear(); 592 format->clear(); 593 if (!isExecuting()) { 594 return INVALID_OPERATION; 595 } 596 597 // we do not want mPortBuffers to change during this section 598 // we also don't want mOwnedByClient to change during this 599 Mutex::Autolock al(mBufferLock); 600 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 601 if (index < buffers->size()) { 602 const BufferInfo &info = buffers->itemAt(index); 603 if (info.mOwnedByClient) { 604 // by the time buffers array is initialized, crypto is set 605 if (portIndex == kPortIndexInput && mCrypto != NULL) { 606 *buffer = info.mEncryptedData; 607 } else { 608 *buffer = info.mData; 609 } 610 *format = info.mFormat; 611 } 612 } 613 return OK; 614} 615 616status_t MediaCodec::flush() { 617 sp<AMessage> msg = new AMessage(kWhatFlush, this); 618 619 sp<AMessage> response; 620 return PostAndAwaitResponse(msg, &response); 621} 622 623status_t MediaCodec::requestIDRFrame() { 624 (new AMessage(kWhatRequestIDRFrame, this))->post(); 625 626 return OK; 627} 628 629void MediaCodec::requestActivityNotification(const sp<AMessage> ¬ify) { 630 sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, this); 631 msg->setMessage("notify", notify); 632 msg->post(); 633} 634 635//////////////////////////////////////////////////////////////////////////////// 636 637void MediaCodec::cancelPendingDequeueOperations() { 638 if (mFlags & kFlagDequeueInputPending) { 639 PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION); 640 641 ++mDequeueInputTimeoutGeneration; 642 mDequeueInputReplyID = 0; 643 mFlags &= ~kFlagDequeueInputPending; 644 } 645 646 if (mFlags & kFlagDequeueOutputPending) { 647 PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION); 648 649 ++mDequeueOutputTimeoutGeneration; 650 mDequeueOutputReplyID = 0; 651 mFlags &= ~kFlagDequeueOutputPending; 652 } 653} 654 655bool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest) { 656 if (!isExecuting() || (mFlags & kFlagIsAsync) 657 || (newRequest && (mFlags & kFlagDequeueInputPending))) { 658 PostReplyWithError(replyID, INVALID_OPERATION); 659 return true; 660 } else if (mFlags & kFlagStickyError) { 661 PostReplyWithError(replyID, getStickyError()); 662 return true; 663 } 664 665 ssize_t index = dequeuePortBuffer(kPortIndexInput); 666 667 if (index < 0) { 668 CHECK_EQ(index, -EAGAIN); 669 return false; 670 } 671 672 sp<AMessage> response = new AMessage; 673 response->setSize("index", index); 674 response->postReply(replyID); 675 676 return true; 677} 678 679bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest) { 680 sp<AMessage> response = new AMessage; 681 682 if (!isExecuting() || (mFlags & kFlagIsAsync) 683 || (newRequest && (mFlags & kFlagDequeueOutputPending))) { 684 response->setInt32("err", INVALID_OPERATION); 685 } else if (mFlags & kFlagStickyError) { 686 response->setInt32("err", getStickyError()); 687 } else if (mFlags & kFlagOutputBuffersChanged) { 688 response->setInt32("err", INFO_OUTPUT_BUFFERS_CHANGED); 689 mFlags &= ~kFlagOutputBuffersChanged; 690 } else if (mFlags & kFlagOutputFormatChanged) { 691 response->setInt32("err", INFO_FORMAT_CHANGED); 692 mFlags &= ~kFlagOutputFormatChanged; 693 } else { 694 ssize_t index = dequeuePortBuffer(kPortIndexOutput); 695 696 if (index < 0) { 697 CHECK_EQ(index, -EAGAIN); 698 return false; 699 } 700 701 const sp<ABuffer> &buffer = 702 mPortBuffers[kPortIndexOutput].itemAt(index).mData; 703 704 response->setSize("index", index); 705 response->setSize("offset", buffer->offset()); 706 response->setSize("size", buffer->size()); 707 708 int64_t timeUs; 709 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 710 711 response->setInt64("timeUs", timeUs); 712 713 int32_t omxFlags; 714 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags)); 715 716 uint32_t flags = 0; 717 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) { 718 flags |= BUFFER_FLAG_SYNCFRAME; 719 } 720 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 721 flags |= BUFFER_FLAG_CODECCONFIG; 722 } 723 if (omxFlags & OMX_BUFFERFLAG_EOS) { 724 flags |= BUFFER_FLAG_EOS; 725 } 726 727 response->setInt32("flags", flags); 728 } 729 730 response->postReply(replyID); 731 732 return true; 733} 734 735void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { 736 switch (msg->what()) { 737 case kWhatCodecNotify: 738 { 739 int32_t what; 740 CHECK(msg->findInt32("what", &what)); 741 742 switch (what) { 743 case CodecBase::kWhatError: 744 { 745 int32_t err, actionCode; 746 CHECK(msg->findInt32("err", &err)); 747 CHECK(msg->findInt32("actionCode", &actionCode)); 748 749 ALOGE("Codec reported err %#x, actionCode %d, while in state %d", 750 err, actionCode, mState); 751 if (err == DEAD_OBJECT) { 752 mFlags |= kFlagSawMediaServerDie; 753 mFlags &= ~kFlagIsComponentAllocated; 754 } 755 756 bool sendErrorResponse = true; 757 758 switch (mState) { 759 case INITIALIZING: 760 { 761 setState(UNINITIALIZED); 762 break; 763 } 764 765 case CONFIGURING: 766 { 767 setState(actionCode == ACTION_CODE_FATAL ? 768 UNINITIALIZED : INITIALIZED); 769 break; 770 } 771 772 case STARTING: 773 { 774 setState(actionCode == ACTION_CODE_FATAL ? 775 UNINITIALIZED : CONFIGURED); 776 break; 777 } 778 779 case STOPPING: 780 case RELEASING: 781 { 782 // Ignore the error, assuming we'll still get 783 // the shutdown complete notification. 784 785 sendErrorResponse = false; 786 787 if (mFlags & kFlagSawMediaServerDie) { 788 // MediaServer died, there definitely won't 789 // be a shutdown complete notification after 790 // all. 791 792 // note that we're directly going from 793 // STOPPING->UNINITIALIZED, instead of the 794 // usual STOPPING->INITIALIZED state. 795 setState(UNINITIALIZED); 796 if (mState == RELEASING) { 797 mComponentName.clear(); 798 } 799 (new AMessage)->postReply(mReplyID); 800 } 801 break; 802 } 803 804 case FLUSHING: 805 { 806 if (actionCode == ACTION_CODE_FATAL) { 807 setState(UNINITIALIZED); 808 } else { 809 setState( 810 (mFlags & kFlagIsAsync) ? FLUSHED : STARTED); 811 } 812 break; 813 } 814 815 case FLUSHED: 816 case STARTED: 817 { 818 sendErrorResponse = false; 819 820 setStickyError(err); 821 postActivityNotificationIfPossible(); 822 823 cancelPendingDequeueOperations(); 824 825 if (mFlags & kFlagIsAsync) { 826 onError(err, actionCode); 827 } 828 switch (actionCode) { 829 case ACTION_CODE_TRANSIENT: 830 break; 831 case ACTION_CODE_RECOVERABLE: 832 setState(INITIALIZED); 833 break; 834 default: 835 setState(UNINITIALIZED); 836 break; 837 } 838 break; 839 } 840 841 default: 842 { 843 sendErrorResponse = false; 844 845 setStickyError(err); 846 postActivityNotificationIfPossible(); 847 848 // actionCode in an uninitialized state is always fatal. 849 if (mState == UNINITIALIZED) { 850 actionCode = ACTION_CODE_FATAL; 851 } 852 if (mFlags & kFlagIsAsync) { 853 onError(err, actionCode); 854 } 855 switch (actionCode) { 856 case ACTION_CODE_TRANSIENT: 857 break; 858 case ACTION_CODE_RECOVERABLE: 859 setState(INITIALIZED); 860 break; 861 default: 862 setState(UNINITIALIZED); 863 break; 864 } 865 break; 866 } 867 } 868 869 if (sendErrorResponse) { 870 PostReplyWithError(mReplyID, err); 871 } 872 break; 873 } 874 875 case CodecBase::kWhatComponentAllocated: 876 { 877 CHECK_EQ(mState, INITIALIZING); 878 setState(INITIALIZED); 879 mFlags |= kFlagIsComponentAllocated; 880 881 CHECK(msg->findString("componentName", &mComponentName)); 882 883 if (mComponentName.startsWith("OMX.google.")) { 884 mFlags |= kFlagUsesSoftwareRenderer; 885 } else { 886 mFlags &= ~kFlagUsesSoftwareRenderer; 887 } 888 889 if (mComponentName.endsWith(".secure")) { 890 mFlags |= kFlagIsSecure; 891 } else { 892 mFlags &= ~kFlagIsSecure; 893 } 894 895 (new AMessage)->postReply(mReplyID); 896 break; 897 } 898 899 case CodecBase::kWhatComponentConfigured: 900 { 901 CHECK_EQ(mState, CONFIGURING); 902 903 // reset input surface flag 904 mHaveInputSurface = false; 905 906 CHECK(msg->findMessage("input-format", &mInputFormat)); 907 CHECK(msg->findMessage("output-format", &mOutputFormat)); 908 909 int32_t usingSwRenderer; 910 if (mOutputFormat->findInt32("using-sw-renderer", &usingSwRenderer) 911 && usingSwRenderer) { 912 mFlags |= kFlagUsesSoftwareRenderer; 913 } 914 setState(CONFIGURED); 915 (new AMessage)->postReply(mReplyID); 916 break; 917 } 918 919 case CodecBase::kWhatInputSurfaceCreated: 920 { 921 // response to initiateCreateInputSurface() 922 status_t err = NO_ERROR; 923 sp<AMessage> response = new AMessage(); 924 if (!msg->findInt32("err", &err)) { 925 sp<RefBase> obj; 926 msg->findObject("input-surface", &obj); 927 CHECK(obj != NULL); 928 response->setObject("input-surface", obj); 929 mHaveInputSurface = true; 930 } else { 931 response->setInt32("err", err); 932 } 933 response->postReply(mReplyID); 934 break; 935 } 936 937 case CodecBase::kWhatSignaledInputEOS: 938 { 939 // response to signalEndOfInputStream() 940 sp<AMessage> response = new AMessage(); 941 status_t err; 942 if (msg->findInt32("err", &err)) { 943 response->setInt32("err", err); 944 } 945 response->postReply(mReplyID); 946 break; 947 } 948 949 950 case CodecBase::kWhatBuffersAllocated: 951 { 952 Mutex::Autolock al(mBufferLock); 953 int32_t portIndex; 954 CHECK(msg->findInt32("portIndex", &portIndex)); 955 956 ALOGV("%s buffers allocated", 957 portIndex == kPortIndexInput ? "input" : "output"); 958 959 CHECK(portIndex == kPortIndexInput 960 || portIndex == kPortIndexOutput); 961 962 mPortBuffers[portIndex].clear(); 963 964 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 965 966 sp<RefBase> obj; 967 CHECK(msg->findObject("portDesc", &obj)); 968 969 sp<CodecBase::PortDescription> portDesc = 970 static_cast<CodecBase::PortDescription *>(obj.get()); 971 972 size_t numBuffers = portDesc->countBuffers(); 973 974 size_t totalSize = 0; 975 for (size_t i = 0; i < numBuffers; ++i) { 976 if (portIndex == kPortIndexInput && mCrypto != NULL) { 977 totalSize += portDesc->bufferAt(i)->capacity(); 978 } 979 } 980 981 if (totalSize) { 982 mDealer = new MemoryDealer(totalSize, "MediaCodec"); 983 } 984 985 for (size_t i = 0; i < numBuffers; ++i) { 986 BufferInfo info; 987 info.mBufferID = portDesc->bufferIDAt(i); 988 info.mOwnedByClient = false; 989 info.mData = portDesc->bufferAt(i); 990 991 if (portIndex == kPortIndexInput && mCrypto != NULL) { 992 sp<IMemory> mem = mDealer->allocate(info.mData->capacity()); 993 info.mEncryptedData = 994 new ABuffer(mem->pointer(), info.mData->capacity()); 995 info.mSharedEncryptedBuffer = mem; 996 } 997 998 buffers->push_back(info); 999 } 1000 1001 if (portIndex == kPortIndexOutput) { 1002 if (mState == STARTING) { 1003 // We're always allocating output buffers after 1004 // allocating input buffers, so this is a good 1005 // indication that now all buffers are allocated. 1006 setState(STARTED); 1007 (new AMessage)->postReply(mReplyID); 1008 } else { 1009 mFlags |= kFlagOutputBuffersChanged; 1010 postActivityNotificationIfPossible(); 1011 } 1012 } 1013 break; 1014 } 1015 1016 case CodecBase::kWhatOutputFormatChanged: 1017 { 1018 ALOGV("codec output format changed"); 1019 1020 if (mSoftRenderer == NULL && 1021 mNativeWindow != NULL && 1022 (mFlags & kFlagUsesSoftwareRenderer)) { 1023 AString mime; 1024 CHECK(msg->findString("mime", &mime)); 1025 1026 if (mime.startsWithIgnoreCase("video/")) { 1027 mSoftRenderer = new SoftwareRenderer(mNativeWindow); 1028 } 1029 } 1030 1031 mOutputFormat = msg; 1032 1033 if (mFlags & kFlagIsEncoder) { 1034 // Before we announce the format change we should 1035 // collect codec specific data and amend the output 1036 // format as necessary. 1037 mFlags |= kFlagGatherCodecSpecificData; 1038 } else if (mFlags & kFlagIsAsync) { 1039 onOutputFormatChanged(); 1040 } else { 1041 mFlags |= kFlagOutputFormatChanged; 1042 postActivityNotificationIfPossible(); 1043 } 1044 1045 // Notify mCrypto of video resolution changes 1046 if (mCrypto != NULL) { 1047 int32_t left, top, right, bottom, width, height; 1048 if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) { 1049 mCrypto->notifyResolution(right - left + 1, bottom - top + 1); 1050 } else if (mOutputFormat->findInt32("width", &width) 1051 && mOutputFormat->findInt32("height", &height)) { 1052 mCrypto->notifyResolution(width, height); 1053 } 1054 } 1055 1056 break; 1057 } 1058 1059 case CodecBase::kWhatFillThisBuffer: 1060 { 1061 /* size_t index = */updateBuffers(kPortIndexInput, msg); 1062 1063 if (mState == FLUSHING 1064 || mState == STOPPING 1065 || mState == RELEASING) { 1066 returnBuffersToCodecOnPort(kPortIndexInput); 1067 break; 1068 } 1069 1070 if (!mCSD.empty()) { 1071 ssize_t index = dequeuePortBuffer(kPortIndexInput); 1072 CHECK_GE(index, 0); 1073 1074 // If codec specific data had been specified as 1075 // part of the format in the call to configure and 1076 // if there's more csd left, we submit it here 1077 // clients only get access to input buffers once 1078 // this data has been exhausted. 1079 1080 status_t err = queueCSDInputBuffer(index); 1081 1082 if (err != OK) { 1083 ALOGE("queueCSDInputBuffer failed w/ error %d", 1084 err); 1085 1086 setStickyError(err); 1087 postActivityNotificationIfPossible(); 1088 1089 cancelPendingDequeueOperations(); 1090 } 1091 break; 1092 } 1093 1094 if (mFlags & kFlagIsAsync) { 1095 if (!mHaveInputSurface) { 1096 onInputBufferAvailable(); 1097 } 1098 } else if (mFlags & kFlagDequeueInputPending) { 1099 CHECK(handleDequeueInputBuffer(mDequeueInputReplyID)); 1100 1101 ++mDequeueInputTimeoutGeneration; 1102 mFlags &= ~kFlagDequeueInputPending; 1103 mDequeueInputReplyID = 0; 1104 } else { 1105 postActivityNotificationIfPossible(); 1106 } 1107 break; 1108 } 1109 1110 case CodecBase::kWhatDrainThisBuffer: 1111 { 1112 /* size_t index = */updateBuffers(kPortIndexOutput, msg); 1113 1114 if (mState == FLUSHING 1115 || mState == STOPPING 1116 || mState == RELEASING) { 1117 returnBuffersToCodecOnPort(kPortIndexOutput); 1118 break; 1119 } 1120 1121 sp<ABuffer> buffer; 1122 CHECK(msg->findBuffer("buffer", &buffer)); 1123 1124 int32_t omxFlags; 1125 CHECK(msg->findInt32("flags", &omxFlags)); 1126 1127 buffer->meta()->setInt32("omxFlags", omxFlags); 1128 1129 if (mFlags & kFlagGatherCodecSpecificData) { 1130 // This is the very first output buffer after a 1131 // format change was signalled, it'll either contain 1132 // the one piece of codec specific data we can expect 1133 // or there won't be codec specific data. 1134 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 1135 status_t err = 1136 amendOutputFormatWithCodecSpecificData(buffer); 1137 1138 if (err != OK) { 1139 ALOGE("Codec spit out malformed codec " 1140 "specific data!"); 1141 } 1142 } 1143 1144 mFlags &= ~kFlagGatherCodecSpecificData; 1145 if (mFlags & kFlagIsAsync) { 1146 onOutputFormatChanged(); 1147 } else { 1148 mFlags |= kFlagOutputFormatChanged; 1149 } 1150 } 1151 1152 if (mFlags & kFlagIsAsync) { 1153 onOutputBufferAvailable(); 1154 } else if (mFlags & kFlagDequeueOutputPending) { 1155 CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID)); 1156 1157 ++mDequeueOutputTimeoutGeneration; 1158 mFlags &= ~kFlagDequeueOutputPending; 1159 mDequeueOutputReplyID = 0; 1160 } else { 1161 postActivityNotificationIfPossible(); 1162 } 1163 1164 break; 1165 } 1166 1167 case CodecBase::kWhatEOS: 1168 { 1169 // We already notify the client of this by using the 1170 // corresponding flag in "onOutputBufferReady". 1171 break; 1172 } 1173 1174 case CodecBase::kWhatShutdownCompleted: 1175 { 1176 if (mState == STOPPING) { 1177 setState(INITIALIZED); 1178 } else { 1179 CHECK_EQ(mState, RELEASING); 1180 setState(UNINITIALIZED); 1181 mComponentName.clear(); 1182 } 1183 mFlags &= ~kFlagIsComponentAllocated; 1184 1185 (new AMessage)->postReply(mReplyID); 1186 break; 1187 } 1188 1189 case CodecBase::kWhatFlushCompleted: 1190 { 1191 if (mState != FLUSHING) { 1192 ALOGW("received FlushCompleted message in state %d", 1193 mState); 1194 break; 1195 } 1196 1197 if (mFlags & kFlagIsAsync) { 1198 setState(FLUSHED); 1199 } else { 1200 setState(STARTED); 1201 mCodec->signalResume(); 1202 } 1203 1204 (new AMessage)->postReply(mReplyID); 1205 break; 1206 } 1207 1208 default: 1209 TRESPASS(); 1210 } 1211 break; 1212 } 1213 1214 case kWhatInit: 1215 { 1216 sp<AReplyToken> replyID; 1217 CHECK(msg->senderAwaitsResponse(&replyID)); 1218 1219 if (mState != UNINITIALIZED) { 1220 PostReplyWithError(replyID, INVALID_OPERATION); 1221 break; 1222 } 1223 1224 mReplyID = replyID; 1225 setState(INITIALIZING); 1226 1227 AString name; 1228 CHECK(msg->findString("name", &name)); 1229 1230 int32_t nameIsType; 1231 int32_t encoder = false; 1232 CHECK(msg->findInt32("nameIsType", &nameIsType)); 1233 if (nameIsType) { 1234 CHECK(msg->findInt32("encoder", &encoder)); 1235 } 1236 1237 sp<AMessage> format = new AMessage; 1238 1239 if (nameIsType) { 1240 format->setString("mime", name.c_str()); 1241 format->setInt32("encoder", encoder); 1242 } else { 1243 format->setString("componentName", name.c_str()); 1244 } 1245 1246 mCodec->initiateAllocateComponent(format); 1247 break; 1248 } 1249 1250 case kWhatSetCallback: 1251 { 1252 sp<AReplyToken> replyID; 1253 CHECK(msg->senderAwaitsResponse(&replyID)); 1254 1255 if (mState == UNINITIALIZED 1256 || mState == INITIALIZING 1257 || isExecuting()) { 1258 // callback can't be set after codec is executing, 1259 // or before it's initialized (as the callback 1260 // will be cleared when it goes to INITIALIZED) 1261 PostReplyWithError(replyID, INVALID_OPERATION); 1262 break; 1263 } 1264 1265 sp<AMessage> callback; 1266 CHECK(msg->findMessage("callback", &callback)); 1267 1268 mCallback = callback; 1269 1270 if (mCallback != NULL) { 1271 ALOGI("MediaCodec will operate in async mode"); 1272 mFlags |= kFlagIsAsync; 1273 } else { 1274 mFlags &= ~kFlagIsAsync; 1275 } 1276 1277 sp<AMessage> response = new AMessage; 1278 response->postReply(replyID); 1279 break; 1280 } 1281 1282 case kWhatConfigure: 1283 { 1284 sp<AReplyToken> replyID; 1285 CHECK(msg->senderAwaitsResponse(&replyID)); 1286 1287 if (mState != INITIALIZED) { 1288 PostReplyWithError(replyID, INVALID_OPERATION); 1289 break; 1290 } 1291 1292 sp<RefBase> obj; 1293 if (!msg->findObject("native-window", &obj)) { 1294 obj.clear(); 1295 } 1296 1297 sp<AMessage> format; 1298 CHECK(msg->findMessage("format", &format)); 1299 1300 if (obj != NULL) { 1301 format->setObject("native-window", obj); 1302 1303 status_t err = setNativeWindow( 1304 static_cast<NativeWindowWrapper *>(obj.get()) 1305 ->getSurfaceTextureClient()); 1306 1307 if (err != OK) { 1308 PostReplyWithError(replyID, err); 1309 break; 1310 } 1311 } else { 1312 setNativeWindow(NULL); 1313 } 1314 1315 mReplyID = replyID; 1316 setState(CONFIGURING); 1317 1318 void *crypto; 1319 if (!msg->findPointer("crypto", &crypto)) { 1320 crypto = NULL; 1321 } 1322 1323 mCrypto = static_cast<ICrypto *>(crypto); 1324 1325 uint32_t flags; 1326 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 1327 1328 if (flags & CONFIGURE_FLAG_ENCODE) { 1329 format->setInt32("encoder", true); 1330 mFlags |= kFlagIsEncoder; 1331 } 1332 1333 extractCSD(format); 1334 1335 mCodec->initiateConfigureComponent(format); 1336 break; 1337 } 1338 1339 case kWhatCreateInputSurface: 1340 { 1341 sp<AReplyToken> replyID; 1342 CHECK(msg->senderAwaitsResponse(&replyID)); 1343 1344 // Must be configured, but can't have been started yet. 1345 if (mState != CONFIGURED) { 1346 PostReplyWithError(replyID, INVALID_OPERATION); 1347 break; 1348 } 1349 1350 mReplyID = replyID; 1351 mCodec->initiateCreateInputSurface(); 1352 break; 1353 } 1354 1355 case kWhatStart: 1356 { 1357 sp<AReplyToken> replyID; 1358 CHECK(msg->senderAwaitsResponse(&replyID)); 1359 1360 if (mState == FLUSHED) { 1361 setState(STARTED); 1362 mCodec->signalResume(); 1363 PostReplyWithError(replyID, OK); 1364 break; 1365 } else if (mState != CONFIGURED) { 1366 PostReplyWithError(replyID, INVALID_OPERATION); 1367 break; 1368 } 1369 1370 mReplyID = replyID; 1371 setState(STARTING); 1372 1373 mCodec->initiateStart(); 1374 break; 1375 } 1376 1377 case kWhatStop: 1378 case kWhatRelease: 1379 { 1380 State targetState = 1381 (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED; 1382 1383 sp<AReplyToken> replyID; 1384 CHECK(msg->senderAwaitsResponse(&replyID)); 1385 1386 if (!((mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED) // See 1 1387 && mState != INITIALIZED 1388 && mState != CONFIGURED && !isExecuting()) { 1389 // 1) Permit release to shut down the component if allocated. 1390 // 1391 // 2) We may be in "UNINITIALIZED" state already and 1392 // also shutdown the encoder/decoder without the 1393 // client being aware of this if media server died while 1394 // we were being stopped. The client would assume that 1395 // after stop() returned, it would be safe to call release() 1396 // and it should be in this case, no harm to allow a release() 1397 // if we're already uninitialized. 1398 sp<AMessage> response = new AMessage; 1399 status_t err = mState == targetState ? OK : INVALID_OPERATION; 1400 response->setInt32("err", err); 1401 if (err == OK && targetState == UNINITIALIZED) { 1402 mComponentName.clear(); 1403 } 1404 response->postReply(replyID); 1405 break; 1406 } 1407 1408 if (mFlags & kFlagSawMediaServerDie) { 1409 // It's dead, Jim. Don't expect initiateShutdown to yield 1410 // any useful results now... 1411 setState(UNINITIALIZED); 1412 if (targetState == UNINITIALIZED) { 1413 mComponentName.clear(); 1414 } 1415 (new AMessage)->postReply(replyID); 1416 break; 1417 } 1418 1419 mReplyID = replyID; 1420 setState(msg->what() == kWhatStop ? STOPPING : RELEASING); 1421 1422 mCodec->initiateShutdown( 1423 msg->what() == kWhatStop /* keepComponentAllocated */); 1424 1425 returnBuffersToCodec(); 1426 break; 1427 } 1428 1429 case kWhatDequeueInputBuffer: 1430 { 1431 sp<AReplyToken> replyID; 1432 CHECK(msg->senderAwaitsResponse(&replyID)); 1433 1434 if (mFlags & kFlagIsAsync) { 1435 ALOGE("dequeueOutputBuffer can't be used in async mode"); 1436 PostReplyWithError(replyID, INVALID_OPERATION); 1437 break; 1438 } 1439 1440 if (mHaveInputSurface) { 1441 ALOGE("dequeueInputBuffer can't be used with input surface"); 1442 PostReplyWithError(replyID, INVALID_OPERATION); 1443 break; 1444 } 1445 1446 if (handleDequeueInputBuffer(replyID, true /* new request */)) { 1447 break; 1448 } 1449 1450 int64_t timeoutUs; 1451 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 1452 1453 if (timeoutUs == 0ll) { 1454 PostReplyWithError(replyID, -EAGAIN); 1455 break; 1456 } 1457 1458 mFlags |= kFlagDequeueInputPending; 1459 mDequeueInputReplyID = replyID; 1460 1461 if (timeoutUs > 0ll) { 1462 sp<AMessage> timeoutMsg = 1463 new AMessage(kWhatDequeueInputTimedOut, this); 1464 timeoutMsg->setInt32( 1465 "generation", ++mDequeueInputTimeoutGeneration); 1466 timeoutMsg->post(timeoutUs); 1467 } 1468 break; 1469 } 1470 1471 case kWhatDequeueInputTimedOut: 1472 { 1473 int32_t generation; 1474 CHECK(msg->findInt32("generation", &generation)); 1475 1476 if (generation != mDequeueInputTimeoutGeneration) { 1477 // Obsolete 1478 break; 1479 } 1480 1481 CHECK(mFlags & kFlagDequeueInputPending); 1482 1483 PostReplyWithError(mDequeueInputReplyID, -EAGAIN); 1484 1485 mFlags &= ~kFlagDequeueInputPending; 1486 mDequeueInputReplyID = 0; 1487 break; 1488 } 1489 1490 case kWhatQueueInputBuffer: 1491 { 1492 sp<AReplyToken> replyID; 1493 CHECK(msg->senderAwaitsResponse(&replyID)); 1494 1495 if (!isExecuting()) { 1496 PostReplyWithError(replyID, INVALID_OPERATION); 1497 break; 1498 } else if (mFlags & kFlagStickyError) { 1499 PostReplyWithError(replyID, getStickyError()); 1500 break; 1501 } 1502 1503 status_t err = onQueueInputBuffer(msg); 1504 1505 PostReplyWithError(replyID, err); 1506 break; 1507 } 1508 1509 case kWhatDequeueOutputBuffer: 1510 { 1511 sp<AReplyToken> replyID; 1512 CHECK(msg->senderAwaitsResponse(&replyID)); 1513 1514 if (mFlags & kFlagIsAsync) { 1515 ALOGE("dequeueOutputBuffer can't be used in async mode"); 1516 PostReplyWithError(replyID, INVALID_OPERATION); 1517 break; 1518 } 1519 1520 if (handleDequeueOutputBuffer(replyID, true /* new request */)) { 1521 break; 1522 } 1523 1524 int64_t timeoutUs; 1525 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 1526 1527 if (timeoutUs == 0ll) { 1528 PostReplyWithError(replyID, -EAGAIN); 1529 break; 1530 } 1531 1532 mFlags |= kFlagDequeueOutputPending; 1533 mDequeueOutputReplyID = replyID; 1534 1535 if (timeoutUs > 0ll) { 1536 sp<AMessage> timeoutMsg = 1537 new AMessage(kWhatDequeueOutputTimedOut, this); 1538 timeoutMsg->setInt32( 1539 "generation", ++mDequeueOutputTimeoutGeneration); 1540 timeoutMsg->post(timeoutUs); 1541 } 1542 break; 1543 } 1544 1545 case kWhatDequeueOutputTimedOut: 1546 { 1547 int32_t generation; 1548 CHECK(msg->findInt32("generation", &generation)); 1549 1550 if (generation != mDequeueOutputTimeoutGeneration) { 1551 // Obsolete 1552 break; 1553 } 1554 1555 CHECK(mFlags & kFlagDequeueOutputPending); 1556 1557 PostReplyWithError(mDequeueOutputReplyID, -EAGAIN); 1558 1559 mFlags &= ~kFlagDequeueOutputPending; 1560 mDequeueOutputReplyID = 0; 1561 break; 1562 } 1563 1564 case kWhatReleaseOutputBuffer: 1565 { 1566 sp<AReplyToken> replyID; 1567 CHECK(msg->senderAwaitsResponse(&replyID)); 1568 1569 if (!isExecuting()) { 1570 PostReplyWithError(replyID, INVALID_OPERATION); 1571 break; 1572 } else if (mFlags & kFlagStickyError) { 1573 PostReplyWithError(replyID, getStickyError()); 1574 break; 1575 } 1576 1577 status_t err = onReleaseOutputBuffer(msg); 1578 1579 PostReplyWithError(replyID, err); 1580 break; 1581 } 1582 1583 case kWhatSignalEndOfInputStream: 1584 { 1585 sp<AReplyToken> replyID; 1586 CHECK(msg->senderAwaitsResponse(&replyID)); 1587 1588 if (!isExecuting()) { 1589 PostReplyWithError(replyID, INVALID_OPERATION); 1590 break; 1591 } else if (mFlags & kFlagStickyError) { 1592 PostReplyWithError(replyID, getStickyError()); 1593 break; 1594 } 1595 1596 mReplyID = replyID; 1597 mCodec->signalEndOfInputStream(); 1598 break; 1599 } 1600 1601 case kWhatGetBuffers: 1602 { 1603 sp<AReplyToken> replyID; 1604 CHECK(msg->senderAwaitsResponse(&replyID)); 1605 1606 if (!isExecuting() || (mFlags & kFlagIsAsync)) { 1607 PostReplyWithError(replyID, INVALID_OPERATION); 1608 break; 1609 } else if (mFlags & kFlagStickyError) { 1610 PostReplyWithError(replyID, getStickyError()); 1611 break; 1612 } 1613 1614 int32_t portIndex; 1615 CHECK(msg->findInt32("portIndex", &portIndex)); 1616 1617 Vector<sp<ABuffer> > *dstBuffers; 1618 CHECK(msg->findPointer("buffers", (void **)&dstBuffers)); 1619 1620 dstBuffers->clear(); 1621 const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex]; 1622 1623 for (size_t i = 0; i < srcBuffers.size(); ++i) { 1624 const BufferInfo &info = srcBuffers.itemAt(i); 1625 1626 dstBuffers->push_back( 1627 (portIndex == kPortIndexInput && mCrypto != NULL) 1628 ? info.mEncryptedData : info.mData); 1629 } 1630 1631 (new AMessage)->postReply(replyID); 1632 break; 1633 } 1634 1635 case kWhatFlush: 1636 { 1637 sp<AReplyToken> replyID; 1638 CHECK(msg->senderAwaitsResponse(&replyID)); 1639 1640 if (!isExecuting()) { 1641 PostReplyWithError(replyID, INVALID_OPERATION); 1642 break; 1643 } else if (mFlags & kFlagStickyError) { 1644 PostReplyWithError(replyID, getStickyError()); 1645 break; 1646 } 1647 1648 mReplyID = replyID; 1649 // TODO: skip flushing if already FLUSHED 1650 setState(FLUSHING); 1651 1652 mCodec->signalFlush(); 1653 returnBuffersToCodec(); 1654 break; 1655 } 1656 1657 case kWhatGetInputFormat: 1658 case kWhatGetOutputFormat: 1659 { 1660 sp<AMessage> format = 1661 (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat); 1662 1663 sp<AReplyToken> replyID; 1664 CHECK(msg->senderAwaitsResponse(&replyID)); 1665 1666 if ((mState != CONFIGURED && mState != STARTING && 1667 mState != STARTED && mState != FLUSHING && 1668 mState != FLUSHED) 1669 || format == NULL) { 1670 PostReplyWithError(replyID, INVALID_OPERATION); 1671 break; 1672 } else if (mFlags & kFlagStickyError) { 1673 PostReplyWithError(replyID, getStickyError()); 1674 break; 1675 } 1676 1677 sp<AMessage> response = new AMessage; 1678 response->setMessage("format", format); 1679 response->postReply(replyID); 1680 break; 1681 } 1682 1683 case kWhatRequestIDRFrame: 1684 { 1685 mCodec->signalRequestIDRFrame(); 1686 break; 1687 } 1688 1689 case kWhatRequestActivityNotification: 1690 { 1691 CHECK(mActivityNotify == NULL); 1692 CHECK(msg->findMessage("notify", &mActivityNotify)); 1693 1694 postActivityNotificationIfPossible(); 1695 break; 1696 } 1697 1698 case kWhatGetName: 1699 { 1700 sp<AReplyToken> replyID; 1701 CHECK(msg->senderAwaitsResponse(&replyID)); 1702 1703 if (mComponentName.empty()) { 1704 PostReplyWithError(replyID, INVALID_OPERATION); 1705 break; 1706 } 1707 1708 sp<AMessage> response = new AMessage; 1709 response->setString("name", mComponentName.c_str()); 1710 response->postReply(replyID); 1711 break; 1712 } 1713 1714 case kWhatSetParameters: 1715 { 1716 sp<AReplyToken> replyID; 1717 CHECK(msg->senderAwaitsResponse(&replyID)); 1718 1719 sp<AMessage> params; 1720 CHECK(msg->findMessage("params", ¶ms)); 1721 1722 status_t err = onSetParameters(params); 1723 1724 PostReplyWithError(replyID, err); 1725 break; 1726 } 1727 1728 default: 1729 TRESPASS(); 1730 } 1731} 1732 1733void MediaCodec::extractCSD(const sp<AMessage> &format) { 1734 mCSD.clear(); 1735 1736 size_t i = 0; 1737 for (;;) { 1738 sp<ABuffer> csd; 1739 if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) { 1740 break; 1741 } 1742 1743 mCSD.push_back(csd); 1744 ++i; 1745 } 1746 1747 ALOGV("Found %zu pieces of codec specific data.", mCSD.size()); 1748} 1749 1750status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) { 1751 CHECK(!mCSD.empty()); 1752 1753 const BufferInfo *info = 1754 &mPortBuffers[kPortIndexInput].itemAt(bufferIndex); 1755 1756 sp<ABuffer> csd = *mCSD.begin(); 1757 mCSD.erase(mCSD.begin()); 1758 1759 const sp<ABuffer> &codecInputData = 1760 (mCrypto != NULL) ? info->mEncryptedData : info->mData; 1761 1762 if (csd->size() > codecInputData->capacity()) { 1763 return -EINVAL; 1764 } 1765 1766 memcpy(codecInputData->data(), csd->data(), csd->size()); 1767 1768 AString errorDetailMsg; 1769 1770 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this); 1771 msg->setSize("index", bufferIndex); 1772 msg->setSize("offset", 0); 1773 msg->setSize("size", csd->size()); 1774 msg->setInt64("timeUs", 0ll); 1775 msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG); 1776 msg->setPointer("errorDetailMsg", &errorDetailMsg); 1777 1778 return onQueueInputBuffer(msg); 1779} 1780 1781void MediaCodec::setState(State newState) { 1782 if (newState == INITIALIZED || newState == UNINITIALIZED) { 1783 delete mSoftRenderer; 1784 mSoftRenderer = NULL; 1785 1786 mCrypto.clear(); 1787 setNativeWindow(NULL); 1788 1789 mInputFormat.clear(); 1790 mOutputFormat.clear(); 1791 mFlags &= ~kFlagOutputFormatChanged; 1792 mFlags &= ~kFlagOutputBuffersChanged; 1793 mFlags &= ~kFlagStickyError; 1794 mFlags &= ~kFlagIsEncoder; 1795 mFlags &= ~kFlagGatherCodecSpecificData; 1796 mFlags &= ~kFlagIsAsync; 1797 mStickyError = OK; 1798 1799 mActivityNotify.clear(); 1800 mCallback.clear(); 1801 } 1802 1803 if (newState == UNINITIALIZED) { 1804 // return any straggling buffers, e.g. if we got here on an error 1805 returnBuffersToCodec(); 1806 1807 // The component is gone, mediaserver's probably back up already 1808 // but should definitely be back up should we try to instantiate 1809 // another component.. and the cycle continues. 1810 mFlags &= ~kFlagSawMediaServerDie; 1811 } 1812 1813 mState = newState; 1814 1815 cancelPendingDequeueOperations(); 1816 1817 updateBatteryStat(); 1818} 1819 1820void MediaCodec::returnBuffersToCodec() { 1821 returnBuffersToCodecOnPort(kPortIndexInput); 1822 returnBuffersToCodecOnPort(kPortIndexOutput); 1823} 1824 1825void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) { 1826 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1827 Mutex::Autolock al(mBufferLock); 1828 1829 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 1830 1831 for (size_t i = 0; i < buffers->size(); ++i) { 1832 BufferInfo *info = &buffers->editItemAt(i); 1833 1834 if (info->mNotify != NULL) { 1835 sp<AMessage> msg = info->mNotify; 1836 info->mNotify = NULL; 1837 info->mOwnedByClient = false; 1838 1839 if (portIndex == kPortIndexInput) { 1840 /* no error, just returning buffers */ 1841 msg->setInt32("err", OK); 1842 } 1843 msg->post(); 1844 } 1845 } 1846 1847 mAvailPortBuffers[portIndex].clear(); 1848} 1849 1850size_t MediaCodec::updateBuffers( 1851 int32_t portIndex, const sp<AMessage> &msg) { 1852 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1853 1854 uint32_t bufferID; 1855 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 1856 1857 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 1858 1859 for (size_t i = 0; i < buffers->size(); ++i) { 1860 BufferInfo *info = &buffers->editItemAt(i); 1861 1862 if (info->mBufferID == bufferID) { 1863 CHECK(info->mNotify == NULL); 1864 CHECK(msg->findMessage("reply", &info->mNotify)); 1865 1866 info->mFormat = 1867 (portIndex == kPortIndexInput) ? mInputFormat : mOutputFormat; 1868 mAvailPortBuffers[portIndex].push_back(i); 1869 1870 return i; 1871 } 1872 } 1873 1874 TRESPASS(); 1875 1876 return 0; 1877} 1878 1879status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) { 1880 size_t index; 1881 size_t offset; 1882 size_t size; 1883 int64_t timeUs; 1884 uint32_t flags; 1885 CHECK(msg->findSize("index", &index)); 1886 CHECK(msg->findSize("offset", &offset)); 1887 CHECK(msg->findInt64("timeUs", &timeUs)); 1888 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 1889 1890 const CryptoPlugin::SubSample *subSamples; 1891 size_t numSubSamples; 1892 const uint8_t *key; 1893 const uint8_t *iv; 1894 CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted; 1895 1896 // We allow the simpler queueInputBuffer API to be used even in 1897 // secure mode, by fabricating a single unencrypted subSample. 1898 CryptoPlugin::SubSample ss; 1899 1900 if (msg->findSize("size", &size)) { 1901 if (mCrypto != NULL) { 1902 ss.mNumBytesOfClearData = size; 1903 ss.mNumBytesOfEncryptedData = 0; 1904 1905 subSamples = &ss; 1906 numSubSamples = 1; 1907 key = NULL; 1908 iv = NULL; 1909 } 1910 } else { 1911 if (mCrypto == NULL) { 1912 return -EINVAL; 1913 } 1914 1915 CHECK(msg->findPointer("subSamples", (void **)&subSamples)); 1916 CHECK(msg->findSize("numSubSamples", &numSubSamples)); 1917 CHECK(msg->findPointer("key", (void **)&key)); 1918 CHECK(msg->findPointer("iv", (void **)&iv)); 1919 1920 int32_t tmp; 1921 CHECK(msg->findInt32("mode", &tmp)); 1922 1923 mode = (CryptoPlugin::Mode)tmp; 1924 1925 size = 0; 1926 for (size_t i = 0; i < numSubSamples; ++i) { 1927 size += subSamples[i].mNumBytesOfClearData; 1928 size += subSamples[i].mNumBytesOfEncryptedData; 1929 } 1930 } 1931 1932 if (index >= mPortBuffers[kPortIndexInput].size()) { 1933 return -ERANGE; 1934 } 1935 1936 BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index); 1937 1938 if (info->mNotify == NULL || !info->mOwnedByClient) { 1939 return -EACCES; 1940 } 1941 1942 if (offset + size > info->mData->capacity()) { 1943 return -EINVAL; 1944 } 1945 1946 sp<AMessage> reply = info->mNotify; 1947 info->mData->setRange(offset, size); 1948 info->mData->meta()->setInt64("timeUs", timeUs); 1949 1950 if (flags & BUFFER_FLAG_EOS) { 1951 info->mData->meta()->setInt32("eos", true); 1952 } 1953 1954 if (flags & BUFFER_FLAG_CODECCONFIG) { 1955 info->mData->meta()->setInt32("csd", true); 1956 } 1957 1958 if (mCrypto != NULL) { 1959 if (size > info->mEncryptedData->capacity()) { 1960 return -ERANGE; 1961 } 1962 1963 AString *errorDetailMsg; 1964 CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg)); 1965 1966 ssize_t result = mCrypto->decrypt( 1967 (mFlags & kFlagIsSecure) != 0, 1968 key, 1969 iv, 1970 mode, 1971 info->mSharedEncryptedBuffer, 1972 offset, 1973 subSamples, 1974 numSubSamples, 1975 info->mData->base(), 1976 errorDetailMsg); 1977 1978 if (result < 0) { 1979 return result; 1980 } 1981 1982 info->mData->setRange(0, result); 1983 } 1984 1985 // synchronization boundary for getBufferAndFormat 1986 { 1987 Mutex::Autolock al(mBufferLock); 1988 info->mOwnedByClient = false; 1989 } 1990 reply->setBuffer("buffer", info->mData); 1991 reply->post(); 1992 1993 info->mNotify = NULL; 1994 1995 return OK; 1996} 1997 1998status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) { 1999 size_t index; 2000 CHECK(msg->findSize("index", &index)); 2001 2002 int32_t render; 2003 if (!msg->findInt32("render", &render)) { 2004 render = 0; 2005 } 2006 2007 if (!isExecuting()) { 2008 return -EINVAL; 2009 } 2010 2011 if (index >= mPortBuffers[kPortIndexOutput].size()) { 2012 return -ERANGE; 2013 } 2014 2015 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index); 2016 2017 if (info->mNotify == NULL || !info->mOwnedByClient) { 2018 return -EACCES; 2019 } 2020 2021 // synchronization boundary for getBufferAndFormat 2022 { 2023 Mutex::Autolock al(mBufferLock); 2024 info->mOwnedByClient = false; 2025 } 2026 2027 if (render && info->mData != NULL && info->mData->size() != 0) { 2028 info->mNotify->setInt32("render", true); 2029 2030 int64_t timestampNs = 0; 2031 if (msg->findInt64("timestampNs", ×tampNs)) { 2032 info->mNotify->setInt64("timestampNs", timestampNs); 2033 } else { 2034 // TODO: it seems like we should use the timestamp 2035 // in the (media)buffer as it potentially came from 2036 // an input surface, but we did not propagate it prior to 2037 // API 20. Perhaps check for target SDK version. 2038#if 0 2039 if (info->mData->meta()->findInt64("timeUs", ×tampNs)) { 2040 ALOGV("using buffer PTS of %" PRId64, timestampNs); 2041 timestampNs *= 1000; 2042 } 2043#endif 2044 } 2045 2046 if (mSoftRenderer != NULL) { 2047 mSoftRenderer->render( 2048 info->mData->data(), info->mData->size(), 2049 timestampNs, NULL, info->mFormat); 2050 } 2051 } 2052 2053 info->mNotify->post(); 2054 info->mNotify = NULL; 2055 2056 return OK; 2057} 2058 2059ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) { 2060 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 2061 2062 List<size_t> *availBuffers = &mAvailPortBuffers[portIndex]; 2063 2064 if (availBuffers->empty()) { 2065 return -EAGAIN; 2066 } 2067 2068 size_t index = *availBuffers->begin(); 2069 availBuffers->erase(availBuffers->begin()); 2070 2071 BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index); 2072 CHECK(!info->mOwnedByClient); 2073 { 2074 Mutex::Autolock al(mBufferLock); 2075 info->mOwnedByClient = true; 2076 2077 // set image-data 2078 if (info->mFormat != NULL) { 2079 sp<ABuffer> imageData; 2080 if (info->mFormat->findBuffer("image-data", &imageData)) { 2081 info->mData->meta()->setBuffer("image-data", imageData); 2082 } 2083 int32_t left, top, right, bottom; 2084 if (info->mFormat->findRect("crop", &left, &top, &right, &bottom)) { 2085 info->mData->meta()->setRect("crop-rect", left, top, right, bottom); 2086 } 2087 } 2088 } 2089 2090 return index; 2091} 2092 2093status_t MediaCodec::setNativeWindow( 2094 const sp<Surface> &surfaceTextureClient) { 2095 status_t err; 2096 2097 if (mNativeWindow != NULL) { 2098 err = native_window_api_disconnect( 2099 mNativeWindow.get(), NATIVE_WINDOW_API_MEDIA); 2100 2101 if (err != OK) { 2102 ALOGW("native_window_api_disconnect returned an error: %s (%d)", 2103 strerror(-err), err); 2104 } 2105 2106 mNativeWindow.clear(); 2107 } 2108 2109 if (surfaceTextureClient != NULL) { 2110 err = native_window_api_connect( 2111 surfaceTextureClient.get(), NATIVE_WINDOW_API_MEDIA); 2112 2113 if (err != OK) { 2114 ALOGE("native_window_api_connect returned an error: %s (%d)", 2115 strerror(-err), err); 2116 2117 return err; 2118 } 2119 2120 mNativeWindow = surfaceTextureClient; 2121 } 2122 2123 return OK; 2124} 2125 2126void MediaCodec::onInputBufferAvailable() { 2127 int32_t index; 2128 while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) { 2129 sp<AMessage> msg = mCallback->dup(); 2130 msg->setInt32("callbackID", CB_INPUT_AVAILABLE); 2131 msg->setInt32("index", index); 2132 msg->post(); 2133 } 2134} 2135 2136void MediaCodec::onOutputBufferAvailable() { 2137 int32_t index; 2138 while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) { 2139 const sp<ABuffer> &buffer = 2140 mPortBuffers[kPortIndexOutput].itemAt(index).mData; 2141 sp<AMessage> msg = mCallback->dup(); 2142 msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE); 2143 msg->setInt32("index", index); 2144 msg->setSize("offset", buffer->offset()); 2145 msg->setSize("size", buffer->size()); 2146 2147 int64_t timeUs; 2148 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 2149 2150 msg->setInt64("timeUs", timeUs); 2151 2152 int32_t omxFlags; 2153 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags)); 2154 2155 uint32_t flags = 0; 2156 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) { 2157 flags |= BUFFER_FLAG_SYNCFRAME; 2158 } 2159 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 2160 flags |= BUFFER_FLAG_CODECCONFIG; 2161 } 2162 if (omxFlags & OMX_BUFFERFLAG_EOS) { 2163 flags |= BUFFER_FLAG_EOS; 2164 } 2165 2166 msg->setInt32("flags", flags); 2167 2168 msg->post(); 2169 } 2170} 2171 2172void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) { 2173 if (mCallback != NULL) { 2174 sp<AMessage> msg = mCallback->dup(); 2175 msg->setInt32("callbackID", CB_ERROR); 2176 msg->setInt32("err", err); 2177 msg->setInt32("actionCode", actionCode); 2178 2179 if (detail != NULL) { 2180 msg->setString("detail", detail); 2181 } 2182 2183 msg->post(); 2184 } 2185} 2186 2187void MediaCodec::onOutputFormatChanged() { 2188 if (mCallback != NULL) { 2189 sp<AMessage> msg = mCallback->dup(); 2190 msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED); 2191 msg->setMessage("format", mOutputFormat); 2192 msg->post(); 2193 } 2194} 2195 2196 2197void MediaCodec::postActivityNotificationIfPossible() { 2198 if (mActivityNotify == NULL) { 2199 return; 2200 } 2201 2202 bool isErrorOrOutputChanged = 2203 (mFlags & (kFlagStickyError 2204 | kFlagOutputBuffersChanged 2205 | kFlagOutputFormatChanged)); 2206 2207 if (isErrorOrOutputChanged 2208 || !mAvailPortBuffers[kPortIndexInput].empty() 2209 || !mAvailPortBuffers[kPortIndexOutput].empty()) { 2210 mActivityNotify->setInt32("input-buffers", 2211 mAvailPortBuffers[kPortIndexInput].size()); 2212 2213 if (isErrorOrOutputChanged) { 2214 // we want consumer to dequeue as many times as it can 2215 mActivityNotify->setInt32("output-buffers", INT32_MAX); 2216 } else { 2217 mActivityNotify->setInt32("output-buffers", 2218 mAvailPortBuffers[kPortIndexOutput].size()); 2219 } 2220 mActivityNotify->post(); 2221 mActivityNotify.clear(); 2222 } 2223} 2224 2225status_t MediaCodec::setParameters(const sp<AMessage> ¶ms) { 2226 sp<AMessage> msg = new AMessage(kWhatSetParameters, this); 2227 msg->setMessage("params", params); 2228 2229 sp<AMessage> response; 2230 return PostAndAwaitResponse(msg, &response); 2231} 2232 2233status_t MediaCodec::onSetParameters(const sp<AMessage> ¶ms) { 2234 mCodec->signalSetParameters(params); 2235 2236 return OK; 2237} 2238 2239status_t MediaCodec::amendOutputFormatWithCodecSpecificData( 2240 const sp<ABuffer> &buffer) { 2241 AString mime; 2242 CHECK(mOutputFormat->findString("mime", &mime)); 2243 2244 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { 2245 // Codec specific data should be SPS and PPS in a single buffer, 2246 // each prefixed by a startcode (0x00 0x00 0x00 0x01). 2247 // We separate the two and put them into the output format 2248 // under the keys "csd-0" and "csd-1". 2249 2250 unsigned csdIndex = 0; 2251 2252 const uint8_t *data = buffer->data(); 2253 size_t size = buffer->size(); 2254 2255 const uint8_t *nalStart; 2256 size_t nalSize; 2257 while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) { 2258 sp<ABuffer> csd = new ABuffer(nalSize + 4); 2259 memcpy(csd->data(), "\x00\x00\x00\x01", 4); 2260 memcpy(csd->data() + 4, nalStart, nalSize); 2261 2262 mOutputFormat->setBuffer( 2263 AStringPrintf("csd-%u", csdIndex).c_str(), csd); 2264 2265 ++csdIndex; 2266 } 2267 2268 if (csdIndex != 2) { 2269 return ERROR_MALFORMED; 2270 } 2271 } else { 2272 // For everything else we just stash the codec specific data into 2273 // the output format as a single piece of csd under "csd-0". 2274 mOutputFormat->setBuffer("csd-0", buffer); 2275 } 2276 2277 return OK; 2278} 2279 2280void MediaCodec::updateBatteryStat() { 2281 if (mState == CONFIGURED && !mBatteryStatNotified) { 2282 AString mime; 2283 CHECK(mOutputFormat != NULL && 2284 mOutputFormat->findString("mime", &mime)); 2285 2286 mIsVideo = mime.startsWithIgnoreCase("video/"); 2287 2288 BatteryNotifier& notifier(BatteryNotifier::getInstance()); 2289 2290 if (mIsVideo) { 2291 notifier.noteStartVideo(); 2292 } else { 2293 notifier.noteStartAudio(); 2294 } 2295 2296 mBatteryStatNotified = true; 2297 } else if (mState == UNINITIALIZED && mBatteryStatNotified) { 2298 BatteryNotifier& notifier(BatteryNotifier::getInstance()); 2299 2300 if (mIsVideo) { 2301 notifier.noteStopVideo(); 2302 } else { 2303 notifier.noteStopAudio(); 2304 } 2305 2306 mBatteryStatNotified = false; 2307 } 2308} 2309 2310} // namespace android 2311