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