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