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