MediaCodec.cpp revision c71601c3b1dd63afc9be462194809813e4dbacf1
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 <utils/Log.h> 20 21#include <media/stagefright/MediaCodec.h> 22 23#include "include/SoftwareRenderer.h" 24 25#include <gui/SurfaceTextureClient.h> 26#include <media/ICrypto.h> 27#include <media/stagefright/foundation/ABuffer.h> 28#include <media/stagefright/foundation/ADebug.h> 29#include <media/stagefright/foundation/AMessage.h> 30#include <media/stagefright/foundation/AString.h> 31#include <media/stagefright/foundation/hexdump.h> 32#include <media/stagefright/ACodec.h> 33#include <media/stagefright/MediaErrors.h> 34#include <media/stagefright/MetaData.h> 35#include <media/stagefright/NativeWindowWrapper.h> 36 37namespace android { 38 39// static 40sp<MediaCodec> MediaCodec::CreateByType( 41 const sp<ALooper> &looper, const char *mime, bool encoder) { 42 sp<MediaCodec> codec = new MediaCodec(looper); 43 if (codec->init(mime, true /* nameIsType */, encoder) != OK) { 44 return NULL; 45 } 46 47 return codec; 48} 49 50// static 51sp<MediaCodec> MediaCodec::CreateByComponentName( 52 const sp<ALooper> &looper, const char *name) { 53 sp<MediaCodec> codec = new MediaCodec(looper); 54 if (codec->init(name, false /* nameIsType */, false /* encoder */) != OK) { 55 return NULL; 56 } 57 58 return codec; 59} 60 61MediaCodec::MediaCodec(const sp<ALooper> &looper) 62 : mState(UNINITIALIZED), 63 mLooper(looper), 64 mCodec(new ACodec), 65 mFlags(0), 66 mSoftRenderer(NULL), 67 mDequeueInputTimeoutGeneration(0), 68 mDequeueInputReplyID(0), 69 mDequeueOutputTimeoutGeneration(0), 70 mDequeueOutputReplyID(0) { 71} 72 73MediaCodec::~MediaCodec() { 74 CHECK_EQ(mState, UNINITIALIZED); 75} 76 77// static 78status_t MediaCodec::PostAndAwaitResponse( 79 const sp<AMessage> &msg, sp<AMessage> *response) { 80 status_t err = msg->postAndAwaitResponse(response); 81 82 if (err != OK) { 83 return err; 84 } 85 86 if (!(*response)->findInt32("err", &err)) { 87 err = OK; 88 } 89 90 return err; 91} 92 93status_t MediaCodec::init(const char *name, bool nameIsType, bool encoder) { 94 // Current video decoders do not return from OMX_FillThisBuffer 95 // quickly, violating the OpenMAX specs, until that is remedied 96 // we need to invest in an extra looper to free the main event 97 // queue. 98 bool needDedicatedLooper = false; 99 if (nameIsType && !strncasecmp(name, "video/", 6)) { 100 needDedicatedLooper = true; 101 } else if (!nameIsType && !strncmp(name, "OMX.TI.DUCATI1.VIDEO.", 21)) { 102 needDedicatedLooper = true; 103 } 104 105 if (needDedicatedLooper) { 106 if (mCodecLooper == NULL) { 107 mCodecLooper = new ALooper; 108 mCodecLooper->setName("CodecLooper"); 109 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO); 110 } 111 112 mCodecLooper->registerHandler(mCodec); 113 } else { 114 mLooper->registerHandler(mCodec); 115 } 116 117 mLooper->registerHandler(this); 118 119 mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id())); 120 121 sp<AMessage> msg = new AMessage(kWhatInit, id()); 122 msg->setString("name", name); 123 msg->setInt32("nameIsType", nameIsType); 124 125 if (nameIsType) { 126 msg->setInt32("encoder", encoder); 127 } 128 129 sp<AMessage> response; 130 return PostAndAwaitResponse(msg, &response); 131} 132 133status_t MediaCodec::configure( 134 const sp<AMessage> &format, 135 const sp<SurfaceTextureClient> &nativeWindow, 136 const sp<ICrypto> &crypto, 137 uint32_t flags) { 138 sp<AMessage> msg = new AMessage(kWhatConfigure, id()); 139 140 msg->setMessage("format", format); 141 msg->setInt32("flags", flags); 142 143 if (nativeWindow != NULL) { 144 msg->setObject( 145 "native-window", 146 new NativeWindowWrapper(nativeWindow)); 147 } 148 149 if (crypto != NULL) { 150 msg->setPointer("crypto", crypto.get()); 151 } 152 153 sp<AMessage> response; 154 return PostAndAwaitResponse(msg, &response); 155} 156 157status_t MediaCodec::start() { 158 sp<AMessage> msg = new AMessage(kWhatStart, id()); 159 160 sp<AMessage> response; 161 return PostAndAwaitResponse(msg, &response); 162} 163 164status_t MediaCodec::stop() { 165 sp<AMessage> msg = new AMessage(kWhatStop, id()); 166 167 sp<AMessage> response; 168 return PostAndAwaitResponse(msg, &response); 169} 170 171status_t MediaCodec::release() { 172 sp<AMessage> msg = new AMessage(kWhatRelease, id()); 173 174 sp<AMessage> response; 175 return PostAndAwaitResponse(msg, &response); 176} 177 178status_t MediaCodec::queueInputBuffer( 179 size_t index, 180 size_t offset, 181 size_t size, 182 int64_t presentationTimeUs, 183 uint32_t flags, 184 AString *errorDetailMsg) { 185 if (errorDetailMsg != NULL) { 186 errorDetailMsg->clear(); 187 } 188 189 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id()); 190 msg->setSize("index", index); 191 msg->setSize("offset", offset); 192 msg->setSize("size", size); 193 msg->setInt64("timeUs", presentationTimeUs); 194 msg->setInt32("flags", flags); 195 msg->setPointer("errorDetailMsg", errorDetailMsg); 196 197 sp<AMessage> response; 198 return PostAndAwaitResponse(msg, &response); 199} 200 201status_t MediaCodec::queueSecureInputBuffer( 202 size_t index, 203 size_t offset, 204 const CryptoPlugin::SubSample *subSamples, 205 size_t numSubSamples, 206 const uint8_t key[16], 207 const uint8_t iv[16], 208 CryptoPlugin::Mode mode, 209 int64_t presentationTimeUs, 210 uint32_t flags, 211 AString *errorDetailMsg) { 212 if (errorDetailMsg != NULL) { 213 errorDetailMsg->clear(); 214 } 215 216 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id()); 217 msg->setSize("index", index); 218 msg->setSize("offset", offset); 219 msg->setPointer("subSamples", (void *)subSamples); 220 msg->setSize("numSubSamples", numSubSamples); 221 msg->setPointer("key", (void *)key); 222 msg->setPointer("iv", (void *)iv); 223 msg->setInt32("mode", mode); 224 msg->setInt64("timeUs", presentationTimeUs); 225 msg->setInt32("flags", flags); 226 msg->setPointer("errorDetailMsg", errorDetailMsg); 227 228 sp<AMessage> response; 229 status_t err = PostAndAwaitResponse(msg, &response); 230 231 return err; 232} 233 234status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) { 235 sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id()); 236 msg->setInt64("timeoutUs", timeoutUs); 237 238 sp<AMessage> response; 239 status_t err; 240 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 241 return err; 242 } 243 244 CHECK(response->findSize("index", index)); 245 246 return OK; 247} 248 249status_t MediaCodec::dequeueOutputBuffer( 250 size_t *index, 251 size_t *offset, 252 size_t *size, 253 int64_t *presentationTimeUs, 254 uint32_t *flags, 255 int64_t timeoutUs) { 256 sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, id()); 257 msg->setInt64("timeoutUs", timeoutUs); 258 259 sp<AMessage> response; 260 status_t err; 261 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 262 return err; 263 } 264 265 CHECK(response->findSize("index", index)); 266 CHECK(response->findSize("offset", offset)); 267 CHECK(response->findSize("size", size)); 268 CHECK(response->findInt64("timeUs", presentationTimeUs)); 269 CHECK(response->findInt32("flags", (int32_t *)flags)); 270 271 return OK; 272} 273 274status_t MediaCodec::renderOutputBufferAndRelease(size_t index) { 275 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id()); 276 msg->setSize("index", index); 277 msg->setInt32("render", true); 278 279 sp<AMessage> response; 280 return PostAndAwaitResponse(msg, &response); 281} 282 283status_t MediaCodec::releaseOutputBuffer(size_t index) { 284 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id()); 285 msg->setSize("index", index); 286 287 sp<AMessage> response; 288 return PostAndAwaitResponse(msg, &response); 289} 290 291status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const { 292 sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, id()); 293 294 sp<AMessage> response; 295 status_t err; 296 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 297 return err; 298 } 299 300 CHECK(response->findMessage("format", format)); 301 302 return OK; 303} 304 305status_t MediaCodec::getName(AString *name) const { 306 sp<AMessage> msg = new AMessage(kWhatGetName, id()); 307 308 sp<AMessage> response; 309 status_t err; 310 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 311 return err; 312 } 313 314 CHECK(response->findString("name", name)); 315 316 return OK; 317} 318 319status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const { 320 sp<AMessage> msg = new AMessage(kWhatGetBuffers, id()); 321 msg->setInt32("portIndex", kPortIndexInput); 322 msg->setPointer("buffers", buffers); 323 324 sp<AMessage> response; 325 return PostAndAwaitResponse(msg, &response); 326} 327 328status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const { 329 sp<AMessage> msg = new AMessage(kWhatGetBuffers, id()); 330 msg->setInt32("portIndex", kPortIndexOutput); 331 msg->setPointer("buffers", buffers); 332 333 sp<AMessage> response; 334 return PostAndAwaitResponse(msg, &response); 335} 336 337status_t MediaCodec::flush() { 338 sp<AMessage> msg = new AMessage(kWhatFlush, id()); 339 340 sp<AMessage> response; 341 return PostAndAwaitResponse(msg, &response); 342} 343 344status_t MediaCodec::requestIDRFrame() { 345 (new AMessage(kWhatRequestIDRFrame, id()))->post(); 346 347 return OK; 348} 349 350void MediaCodec::requestActivityNotification(const sp<AMessage> ¬ify) { 351 sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, id()); 352 msg->setMessage("notify", notify); 353 msg->post(); 354} 355 356//////////////////////////////////////////////////////////////////////////////// 357 358void MediaCodec::cancelPendingDequeueOperations() { 359 if (mFlags & kFlagDequeueInputPending) { 360 sp<AMessage> response = new AMessage; 361 response->setInt32("err", INVALID_OPERATION); 362 response->postReply(mDequeueInputReplyID); 363 364 ++mDequeueInputTimeoutGeneration; 365 mDequeueInputReplyID = 0; 366 mFlags &= ~kFlagDequeueInputPending; 367 } 368 369 if (mFlags & kFlagDequeueOutputPending) { 370 sp<AMessage> response = new AMessage; 371 response->setInt32("err", INVALID_OPERATION); 372 response->postReply(mDequeueOutputReplyID); 373 374 ++mDequeueOutputTimeoutGeneration; 375 mDequeueOutputReplyID = 0; 376 mFlags &= ~kFlagDequeueOutputPending; 377 } 378} 379 380bool MediaCodec::handleDequeueInputBuffer(uint32_t replyID, bool newRequest) { 381 if (mState != STARTED 382 || (mFlags & kFlagStickyError) 383 || (newRequest && (mFlags & kFlagDequeueInputPending))) { 384 sp<AMessage> response = new AMessage; 385 response->setInt32("err", INVALID_OPERATION); 386 387 response->postReply(replyID); 388 389 return true; 390 } 391 392 ssize_t index = dequeuePortBuffer(kPortIndexInput); 393 394 if (index < 0) { 395 CHECK_EQ(index, -EAGAIN); 396 return false; 397 } 398 399 sp<AMessage> response = new AMessage; 400 response->setSize("index", index); 401 response->postReply(replyID); 402 403 return true; 404} 405 406bool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) { 407 sp<AMessage> response = new AMessage; 408 409 if (mState != STARTED 410 || (mFlags & kFlagStickyError) 411 || (newRequest && (mFlags & kFlagDequeueOutputPending))) { 412 response->setInt32("err", INVALID_OPERATION); 413 } else if (mFlags & kFlagOutputBuffersChanged) { 414 response->setInt32("err", INFO_OUTPUT_BUFFERS_CHANGED); 415 mFlags &= ~kFlagOutputBuffersChanged; 416 } else if (mFlags & kFlagOutputFormatChanged) { 417 response->setInt32("err", INFO_FORMAT_CHANGED); 418 mFlags &= ~kFlagOutputFormatChanged; 419 } else { 420 ssize_t index = dequeuePortBuffer(kPortIndexOutput); 421 422 if (index < 0) { 423 CHECK_EQ(index, -EAGAIN); 424 return false; 425 } 426 427 const sp<ABuffer> &buffer = 428 mPortBuffers[kPortIndexOutput].itemAt(index).mData; 429 430 response->setSize("index", index); 431 response->setSize("offset", buffer->offset()); 432 response->setSize("size", buffer->size()); 433 434 int64_t timeUs; 435 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 436 437 response->setInt64("timeUs", timeUs); 438 439 int32_t omxFlags; 440 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags)); 441 442 uint32_t flags = 0; 443 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) { 444 flags |= BUFFER_FLAG_SYNCFRAME; 445 } 446 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 447 flags |= BUFFER_FLAG_CODECCONFIG; 448 } 449 if (omxFlags & OMX_BUFFERFLAG_EOS) { 450 flags |= BUFFER_FLAG_EOS; 451 } 452 453 response->setInt32("flags", flags); 454 } 455 456 response->postReply(replyID); 457 458 return true; 459} 460 461void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { 462 switch (msg->what()) { 463 case kWhatCodecNotify: 464 { 465 int32_t what; 466 CHECK(msg->findInt32("what", &what)); 467 468 switch (what) { 469 case ACodec::kWhatError: 470 { 471 int32_t omxError, internalError; 472 CHECK(msg->findInt32("omx-error", &omxError)); 473 CHECK(msg->findInt32("err", &internalError)); 474 475 ALOGE("Codec reported an error. " 476 "(omx error 0x%08x, internalError %d)", 477 omxError, internalError); 478 479 bool sendErrorReponse = true; 480 481 switch (mState) { 482 case INITIALIZING: 483 { 484 setState(UNINITIALIZED); 485 break; 486 } 487 488 case CONFIGURING: 489 { 490 setState(INITIALIZED); 491 break; 492 } 493 494 case STARTING: 495 { 496 setState(CONFIGURED); 497 break; 498 } 499 500 case STOPPING: 501 case RELEASING: 502 { 503 // Ignore the error, assuming we'll still get 504 // the shutdown complete notification. 505 506 sendErrorReponse = false; 507 break; 508 } 509 510 case FLUSHING: 511 { 512 setState(STARTED); 513 break; 514 } 515 516 case STARTED: 517 { 518 sendErrorReponse = false; 519 520 mFlags |= kFlagStickyError; 521 postActivityNotificationIfPossible(); 522 523 cancelPendingDequeueOperations(); 524 break; 525 } 526 527 default: 528 { 529 sendErrorReponse = false; 530 531 mFlags |= kFlagStickyError; 532 postActivityNotificationIfPossible(); 533 break; 534 } 535 } 536 537 if (sendErrorReponse) { 538 sp<AMessage> response = new AMessage; 539 response->setInt32("err", UNKNOWN_ERROR); 540 541 response->postReply(mReplyID); 542 } 543 break; 544 } 545 546 case ACodec::kWhatComponentAllocated: 547 { 548 CHECK_EQ(mState, INITIALIZING); 549 setState(INITIALIZED); 550 551 CHECK(msg->findString("componentName", &mComponentName)); 552 553 if (mComponentName.startsWith("OMX.google.")) { 554 mFlags |= kFlagIsSoftwareCodec; 555 } else { 556 mFlags &= ~kFlagIsSoftwareCodec; 557 } 558 559 if (mComponentName.endsWith(".secure")) { 560 mFlags |= kFlagIsSecure; 561 } else { 562 mFlags &= ~kFlagIsSecure; 563 } 564 565 (new AMessage)->postReply(mReplyID); 566 break; 567 } 568 569 case ACodec::kWhatComponentConfigured: 570 { 571 CHECK_EQ(mState, CONFIGURING); 572 setState(CONFIGURED); 573 574 (new AMessage)->postReply(mReplyID); 575 break; 576 } 577 578 case ACodec::kWhatBuffersAllocated: 579 { 580 int32_t portIndex; 581 CHECK(msg->findInt32("portIndex", &portIndex)); 582 583 ALOGV("%s buffers allocated", 584 portIndex == kPortIndexInput ? "input" : "output"); 585 586 CHECK(portIndex == kPortIndexInput 587 || portIndex == kPortIndexOutput); 588 589 mPortBuffers[portIndex].clear(); 590 591 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 592 593 sp<RefBase> obj; 594 CHECK(msg->findObject("portDesc", &obj)); 595 596 sp<ACodec::PortDescription> portDesc = 597 static_cast<ACodec::PortDescription *>(obj.get()); 598 599 size_t numBuffers = portDesc->countBuffers(); 600 601 for (size_t i = 0; i < numBuffers; ++i) { 602 BufferInfo info; 603 info.mBufferID = portDesc->bufferIDAt(i); 604 info.mOwnedByClient = false; 605 info.mData = portDesc->bufferAt(i); 606 607 if (portIndex == kPortIndexInput && mCrypto != NULL) { 608 info.mEncryptedData = 609 new ABuffer(info.mData->capacity()); 610 } 611 612 buffers->push_back(info); 613 } 614 615 if (portIndex == kPortIndexOutput) { 616 if (mState == STARTING) { 617 // We're always allocating output buffers after 618 // allocating input buffers, so this is a good 619 // indication that now all buffers are allocated. 620 setState(STARTED); 621 (new AMessage)->postReply(mReplyID); 622 } else { 623 mFlags |= kFlagOutputBuffersChanged; 624 postActivityNotificationIfPossible(); 625 } 626 } 627 break; 628 } 629 630 case ACodec::kWhatOutputFormatChanged: 631 { 632 ALOGV("codec output format changed"); 633 634 if ((mFlags & kFlagIsSoftwareCodec) 635 && mNativeWindow != NULL) { 636 AString mime; 637 CHECK(msg->findString("mime", &mime)); 638 639 if (!strncasecmp("video/", mime.c_str(), 6)) { 640 delete mSoftRenderer; 641 mSoftRenderer = NULL; 642 643 int32_t width, height; 644 CHECK(msg->findInt32("width", &width)); 645 CHECK(msg->findInt32("height", &height)); 646 647 int32_t colorFormat; 648 CHECK(msg->findInt32( 649 "color-format", &colorFormat)); 650 651 sp<MetaData> meta = new MetaData; 652 meta->setInt32(kKeyWidth, width); 653 meta->setInt32(kKeyHeight, height); 654 meta->setInt32(kKeyColorFormat, colorFormat); 655 656 mSoftRenderer = 657 new SoftwareRenderer(mNativeWindow, meta); 658 } 659 } 660 661 mOutputFormat = msg; 662 mFlags |= kFlagOutputFormatChanged; 663 postActivityNotificationIfPossible(); 664 break; 665 } 666 667 case ACodec::kWhatFillThisBuffer: 668 { 669 /* size_t index = */updateBuffers(kPortIndexInput, msg); 670 671 if (mState == FLUSHING 672 || mState == STOPPING 673 || mState == RELEASING) { 674 returnBuffersToCodecOnPort(kPortIndexInput); 675 break; 676 } 677 678 if (!mCSD.empty()) { 679 ssize_t index = dequeuePortBuffer(kPortIndexInput); 680 CHECK_GE(index, 0); 681 682 // If codec specific data had been specified as 683 // part of the format in the call to configure and 684 // if there's more csd left, we submit it here 685 // clients only get access to input buffers once 686 // this data has been exhausted. 687 688 status_t err = queueCSDInputBuffer(index); 689 690 if (err != OK) { 691 ALOGE("queueCSDInputBuffer failed w/ error %d", 692 err); 693 694 mFlags |= kFlagStickyError; 695 postActivityNotificationIfPossible(); 696 697 cancelPendingDequeueOperations(); 698 } 699 break; 700 } 701 702 if (mFlags & kFlagDequeueInputPending) { 703 CHECK(handleDequeueInputBuffer(mDequeueInputReplyID)); 704 705 ++mDequeueInputTimeoutGeneration; 706 mFlags &= ~kFlagDequeueInputPending; 707 mDequeueInputReplyID = 0; 708 } else { 709 postActivityNotificationIfPossible(); 710 } 711 break; 712 } 713 714 case ACodec::kWhatDrainThisBuffer: 715 { 716 /* size_t index = */updateBuffers(kPortIndexOutput, msg); 717 718 if (mState == FLUSHING 719 || mState == STOPPING 720 || mState == RELEASING) { 721 returnBuffersToCodecOnPort(kPortIndexOutput); 722 break; 723 } 724 725 sp<ABuffer> buffer; 726 CHECK(msg->findBuffer("buffer", &buffer)); 727 728 int32_t omxFlags; 729 CHECK(msg->findInt32("flags", &omxFlags)); 730 731 buffer->meta()->setInt32("omxFlags", omxFlags); 732 733 if (mFlags & kFlagDequeueOutputPending) { 734 CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID)); 735 736 ++mDequeueOutputTimeoutGeneration; 737 mFlags &= ~kFlagDequeueOutputPending; 738 mDequeueOutputReplyID = 0; 739 } else { 740 postActivityNotificationIfPossible(); 741 } 742 743 break; 744 } 745 746 case ACodec::kWhatEOS: 747 { 748 // We already notify the client of this by using the 749 // corresponding flag in "onOutputBufferReady". 750 break; 751 } 752 753 case ACodec::kWhatShutdownCompleted: 754 { 755 if (mState == STOPPING) { 756 setState(INITIALIZED); 757 } else { 758 CHECK_EQ(mState, RELEASING); 759 setState(UNINITIALIZED); 760 } 761 762 (new AMessage)->postReply(mReplyID); 763 break; 764 } 765 766 case ACodec::kWhatFlushCompleted: 767 { 768 CHECK_EQ(mState, FLUSHING); 769 setState(STARTED); 770 771 mCodec->signalResume(); 772 773 (new AMessage)->postReply(mReplyID); 774 break; 775 } 776 777 default: 778 TRESPASS(); 779 } 780 break; 781 } 782 783 case kWhatInit: 784 { 785 uint32_t replyID; 786 CHECK(msg->senderAwaitsResponse(&replyID)); 787 788 if (mState != UNINITIALIZED) { 789 sp<AMessage> response = new AMessage; 790 response->setInt32("err", INVALID_OPERATION); 791 792 response->postReply(replyID); 793 break; 794 } 795 796 mReplyID = replyID; 797 setState(INITIALIZING); 798 799 AString name; 800 CHECK(msg->findString("name", &name)); 801 802 int32_t nameIsType; 803 int32_t encoder = false; 804 CHECK(msg->findInt32("nameIsType", &nameIsType)); 805 if (nameIsType) { 806 CHECK(msg->findInt32("encoder", &encoder)); 807 } 808 809 sp<AMessage> format = new AMessage; 810 811 if (nameIsType) { 812 format->setString("mime", name.c_str()); 813 format->setInt32("encoder", encoder); 814 } else { 815 format->setString("componentName", name.c_str()); 816 } 817 818 mCodec->initiateAllocateComponent(format); 819 break; 820 } 821 822 case kWhatConfigure: 823 { 824 uint32_t replyID; 825 CHECK(msg->senderAwaitsResponse(&replyID)); 826 827 if (mState != INITIALIZED) { 828 sp<AMessage> response = new AMessage; 829 response->setInt32("err", INVALID_OPERATION); 830 831 response->postReply(replyID); 832 break; 833 } 834 835 sp<RefBase> obj; 836 if (!msg->findObject("native-window", &obj)) { 837 obj.clear(); 838 } 839 840 sp<AMessage> format; 841 CHECK(msg->findMessage("format", &format)); 842 843 if (obj != NULL) { 844 format->setObject("native-window", obj); 845 846 status_t err = setNativeWindow( 847 static_cast<NativeWindowWrapper *>(obj.get()) 848 ->getSurfaceTextureClient()); 849 850 if (err != OK) { 851 sp<AMessage> response = new AMessage; 852 response->setInt32("err", err); 853 854 response->postReply(replyID); 855 break; 856 } 857 } else { 858 setNativeWindow(NULL); 859 } 860 861 mReplyID = replyID; 862 setState(CONFIGURING); 863 864 void *crypto; 865 if (!msg->findPointer("crypto", &crypto)) { 866 crypto = NULL; 867 } 868 869 mCrypto = static_cast<ICrypto *>(crypto); 870 871 uint32_t flags; 872 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 873 874 if (flags & CONFIGURE_FLAG_ENCODE) { 875 format->setInt32("encoder", true); 876 } 877 878 extractCSD(format); 879 880 mCodec->initiateConfigureComponent(format); 881 break; 882 } 883 884 case kWhatStart: 885 { 886 uint32_t replyID; 887 CHECK(msg->senderAwaitsResponse(&replyID)); 888 889 if (mState != CONFIGURED) { 890 sp<AMessage> response = new AMessage; 891 response->setInt32("err", INVALID_OPERATION); 892 893 response->postReply(replyID); 894 break; 895 } 896 897 mReplyID = replyID; 898 setState(STARTING); 899 900 mCodec->initiateStart(); 901 break; 902 } 903 904 case kWhatStop: 905 { 906 uint32_t replyID; 907 CHECK(msg->senderAwaitsResponse(&replyID)); 908 909 if (mState != INITIALIZED 910 && mState != CONFIGURED && mState != STARTED) { 911 sp<AMessage> response = new AMessage; 912 response->setInt32("err", INVALID_OPERATION); 913 914 response->postReply(replyID); 915 break; 916 } 917 918 mReplyID = replyID; 919 setState(STOPPING); 920 921 mCodec->initiateShutdown(true /* keepComponentAllocated */); 922 returnBuffersToCodec(); 923 break; 924 } 925 926 case kWhatRelease: 927 { 928 uint32_t replyID; 929 CHECK(msg->senderAwaitsResponse(&replyID)); 930 931 if (mState != INITIALIZED 932 && mState != CONFIGURED && mState != STARTED) { 933 sp<AMessage> response = new AMessage; 934 response->setInt32("err", INVALID_OPERATION); 935 936 response->postReply(replyID); 937 break; 938 } 939 940 mReplyID = replyID; 941 setState(RELEASING); 942 943 mCodec->initiateShutdown(); 944 returnBuffersToCodec(); 945 break; 946 } 947 948 case kWhatDequeueInputBuffer: 949 { 950 uint32_t replyID; 951 CHECK(msg->senderAwaitsResponse(&replyID)); 952 953 if (handleDequeueInputBuffer(replyID, true /* new request */)) { 954 break; 955 } 956 957 int64_t timeoutUs; 958 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 959 960 if (timeoutUs == 0ll) { 961 sp<AMessage> response = new AMessage; 962 response->setInt32("err", -EAGAIN); 963 response->postReply(replyID); 964 break; 965 } 966 967 mFlags |= kFlagDequeueInputPending; 968 mDequeueInputReplyID = replyID; 969 970 if (timeoutUs > 0ll) { 971 sp<AMessage> timeoutMsg = 972 new AMessage(kWhatDequeueInputTimedOut, id()); 973 timeoutMsg->setInt32( 974 "generation", ++mDequeueInputTimeoutGeneration); 975 timeoutMsg->post(timeoutUs); 976 } 977 break; 978 } 979 980 case kWhatDequeueInputTimedOut: 981 { 982 int32_t generation; 983 CHECK(msg->findInt32("generation", &generation)); 984 985 if (generation != mDequeueInputTimeoutGeneration) { 986 // Obsolete 987 break; 988 } 989 990 CHECK(mFlags & kFlagDequeueInputPending); 991 992 sp<AMessage> response = new AMessage; 993 response->setInt32("err", -EAGAIN); 994 response->postReply(mDequeueInputReplyID); 995 996 mFlags &= ~kFlagDequeueInputPending; 997 mDequeueInputReplyID = 0; 998 break; 999 } 1000 1001 case kWhatQueueInputBuffer: 1002 { 1003 uint32_t replyID; 1004 CHECK(msg->senderAwaitsResponse(&replyID)); 1005 1006 if (mState != STARTED || (mFlags & kFlagStickyError)) { 1007 sp<AMessage> response = new AMessage; 1008 response->setInt32("err", INVALID_OPERATION); 1009 1010 response->postReply(replyID); 1011 break; 1012 } 1013 1014 status_t err = onQueueInputBuffer(msg); 1015 1016 sp<AMessage> response = new AMessage; 1017 response->setInt32("err", err); 1018 response->postReply(replyID); 1019 break; 1020 } 1021 1022 case kWhatDequeueOutputBuffer: 1023 { 1024 uint32_t replyID; 1025 CHECK(msg->senderAwaitsResponse(&replyID)); 1026 1027 if (handleDequeueOutputBuffer(replyID, true /* new request */)) { 1028 break; 1029 } 1030 1031 int64_t timeoutUs; 1032 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 1033 1034 if (timeoutUs == 0ll) { 1035 sp<AMessage> response = new AMessage; 1036 response->setInt32("err", -EAGAIN); 1037 response->postReply(replyID); 1038 break; 1039 } 1040 1041 mFlags |= kFlagDequeueOutputPending; 1042 mDequeueOutputReplyID = replyID; 1043 1044 if (timeoutUs > 0ll) { 1045 sp<AMessage> timeoutMsg = 1046 new AMessage(kWhatDequeueOutputTimedOut, id()); 1047 timeoutMsg->setInt32( 1048 "generation", ++mDequeueOutputTimeoutGeneration); 1049 timeoutMsg->post(timeoutUs); 1050 } 1051 break; 1052 } 1053 1054 case kWhatDequeueOutputTimedOut: 1055 { 1056 int32_t generation; 1057 CHECK(msg->findInt32("generation", &generation)); 1058 1059 if (generation != mDequeueOutputTimeoutGeneration) { 1060 // Obsolete 1061 break; 1062 } 1063 1064 CHECK(mFlags & kFlagDequeueOutputPending); 1065 1066 sp<AMessage> response = new AMessage; 1067 response->setInt32("err", -EAGAIN); 1068 response->postReply(mDequeueOutputReplyID); 1069 1070 mFlags &= ~kFlagDequeueOutputPending; 1071 mDequeueOutputReplyID = 0; 1072 break; 1073 } 1074 1075 case kWhatReleaseOutputBuffer: 1076 { 1077 uint32_t replyID; 1078 CHECK(msg->senderAwaitsResponse(&replyID)); 1079 1080 if (mState != STARTED || (mFlags & kFlagStickyError)) { 1081 sp<AMessage> response = new AMessage; 1082 response->setInt32("err", INVALID_OPERATION); 1083 1084 response->postReply(replyID); 1085 break; 1086 } 1087 1088 status_t err = onReleaseOutputBuffer(msg); 1089 1090 sp<AMessage> response = new AMessage; 1091 response->setInt32("err", err); 1092 response->postReply(replyID); 1093 break; 1094 } 1095 1096 case kWhatGetBuffers: 1097 { 1098 uint32_t replyID; 1099 CHECK(msg->senderAwaitsResponse(&replyID)); 1100 1101 if (mState != STARTED || (mFlags & kFlagStickyError)) { 1102 sp<AMessage> response = new AMessage; 1103 response->setInt32("err", INVALID_OPERATION); 1104 1105 response->postReply(replyID); 1106 break; 1107 } 1108 1109 int32_t portIndex; 1110 CHECK(msg->findInt32("portIndex", &portIndex)); 1111 1112 Vector<sp<ABuffer> > *dstBuffers; 1113 CHECK(msg->findPointer("buffers", (void **)&dstBuffers)); 1114 1115 dstBuffers->clear(); 1116 const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex]; 1117 1118 for (size_t i = 0; i < srcBuffers.size(); ++i) { 1119 const BufferInfo &info = srcBuffers.itemAt(i); 1120 1121 dstBuffers->push_back( 1122 (portIndex == kPortIndexInput && mCrypto != NULL) 1123 ? info.mEncryptedData : info.mData); 1124 } 1125 1126 (new AMessage)->postReply(replyID); 1127 break; 1128 } 1129 1130 case kWhatFlush: 1131 { 1132 uint32_t replyID; 1133 CHECK(msg->senderAwaitsResponse(&replyID)); 1134 1135 if (mState != STARTED || (mFlags & kFlagStickyError)) { 1136 sp<AMessage> response = new AMessage; 1137 response->setInt32("err", INVALID_OPERATION); 1138 1139 response->postReply(replyID); 1140 break; 1141 } 1142 1143 mReplyID = replyID; 1144 setState(FLUSHING); 1145 1146 mCodec->signalFlush(); 1147 returnBuffersToCodec(); 1148 break; 1149 } 1150 1151 case kWhatGetOutputFormat: 1152 { 1153 uint32_t replyID; 1154 CHECK(msg->senderAwaitsResponse(&replyID)); 1155 1156 if ((mState != STARTED && mState != FLUSHING) 1157 || (mFlags & kFlagStickyError) 1158 || mOutputFormat == NULL) { 1159 sp<AMessage> response = new AMessage; 1160 response->setInt32("err", INVALID_OPERATION); 1161 1162 response->postReply(replyID); 1163 break; 1164 } 1165 1166 sp<AMessage> response = new AMessage; 1167 response->setMessage("format", mOutputFormat); 1168 response->postReply(replyID); 1169 break; 1170 } 1171 1172 case kWhatRequestIDRFrame: 1173 { 1174 mCodec->signalRequestIDRFrame(); 1175 break; 1176 } 1177 1178 case kWhatRequestActivityNotification: 1179 { 1180 CHECK(mActivityNotify == NULL); 1181 CHECK(msg->findMessage("notify", &mActivityNotify)); 1182 1183 postActivityNotificationIfPossible(); 1184 break; 1185 } 1186 1187 case kWhatGetName: 1188 { 1189 uint32_t replyID; 1190 CHECK(msg->senderAwaitsResponse(&replyID)); 1191 1192 if (mComponentName.empty()) { 1193 sp<AMessage> response = new AMessage; 1194 response->setInt32("err", INVALID_OPERATION); 1195 1196 response->postReply(replyID); 1197 break; 1198 } 1199 1200 sp<AMessage> response = new AMessage; 1201 response->setString("name", mComponentName.c_str()); 1202 response->postReply(replyID); 1203 break; 1204 } 1205 1206 case kWhatSetParameters: 1207 { 1208 uint32_t replyID; 1209 CHECK(msg->senderAwaitsResponse(&replyID)); 1210 1211 sp<AMessage> params; 1212 CHECK(msg->findMessage("params", ¶ms)); 1213 1214 status_t err = onSetParameters(params); 1215 1216 sp<AMessage> response = new AMessage; 1217 response->setInt32("err", err); 1218 1219 response->postReply(replyID); 1220 break; 1221 } 1222 1223 default: 1224 TRESPASS(); 1225 } 1226} 1227 1228void MediaCodec::extractCSD(const sp<AMessage> &format) { 1229 mCSD.clear(); 1230 1231 size_t i = 0; 1232 for (;;) { 1233 sp<ABuffer> csd; 1234 if (!format->findBuffer(StringPrintf("csd-%u", i).c_str(), &csd)) { 1235 break; 1236 } 1237 1238 mCSD.push_back(csd); 1239 ++i; 1240 } 1241 1242 ALOGV("Found %u pieces of codec specific data.", mCSD.size()); 1243} 1244 1245status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) { 1246 CHECK(!mCSD.empty()); 1247 1248 BufferInfo *info = 1249 &mPortBuffers[kPortIndexInput].editItemAt(bufferIndex); 1250 1251 sp<ABuffer> csd = *mCSD.begin(); 1252 mCSD.erase(mCSD.begin()); 1253 1254 const sp<ABuffer> &codecInputData = 1255 (mCrypto != NULL) ? info->mEncryptedData : info->mData; 1256 1257 if (csd->size() > codecInputData->capacity()) { 1258 return -EINVAL; 1259 } 1260 1261 memcpy(codecInputData->data(), csd->data(), csd->size()); 1262 1263 AString errorDetailMsg; 1264 1265 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id()); 1266 msg->setSize("index", bufferIndex); 1267 msg->setSize("offset", 0); 1268 msg->setSize("size", csd->size()); 1269 msg->setInt64("timeUs", 0ll); 1270 msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG); 1271 msg->setPointer("errorDetailMsg", &errorDetailMsg); 1272 1273 return onQueueInputBuffer(msg); 1274} 1275 1276void MediaCodec::setState(State newState) { 1277 if (newState == INITIALIZED || newState == UNINITIALIZED) { 1278 delete mSoftRenderer; 1279 mSoftRenderer = NULL; 1280 1281 mCrypto.clear(); 1282 setNativeWindow(NULL); 1283 1284 mOutputFormat.clear(); 1285 mFlags &= ~kFlagOutputFormatChanged; 1286 mFlags &= ~kFlagOutputBuffersChanged; 1287 mFlags &= ~kFlagStickyError; 1288 1289 mActivityNotify.clear(); 1290 } 1291 1292 if (newState == UNINITIALIZED) { 1293 mComponentName.clear(); 1294 } 1295 1296 mState = newState; 1297 1298 cancelPendingDequeueOperations(); 1299} 1300 1301void MediaCodec::returnBuffersToCodec() { 1302 returnBuffersToCodecOnPort(kPortIndexInput); 1303 returnBuffersToCodecOnPort(kPortIndexOutput); 1304} 1305 1306void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) { 1307 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1308 1309 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 1310 1311 for (size_t i = 0; i < buffers->size(); ++i) { 1312 BufferInfo *info = &buffers->editItemAt(i); 1313 1314 if (info->mNotify != NULL) { 1315 sp<AMessage> msg = info->mNotify; 1316 info->mNotify = NULL; 1317 info->mOwnedByClient = false; 1318 1319 if (portIndex == kPortIndexInput) { 1320 msg->setInt32("err", ERROR_END_OF_STREAM); 1321 } 1322 msg->post(); 1323 } 1324 } 1325 1326 mAvailPortBuffers[portIndex].clear(); 1327} 1328 1329size_t MediaCodec::updateBuffers( 1330 int32_t portIndex, const sp<AMessage> &msg) { 1331 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1332 1333 void *bufferID; 1334 CHECK(msg->findPointer("buffer-id", &bufferID)); 1335 1336 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 1337 1338 for (size_t i = 0; i < buffers->size(); ++i) { 1339 BufferInfo *info = &buffers->editItemAt(i); 1340 1341 if (info->mBufferID == bufferID) { 1342 CHECK(info->mNotify == NULL); 1343 CHECK(msg->findMessage("reply", &info->mNotify)); 1344 1345 mAvailPortBuffers[portIndex].push_back(i); 1346 1347 return i; 1348 } 1349 } 1350 1351 TRESPASS(); 1352 1353 return 0; 1354} 1355 1356status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) { 1357 size_t index; 1358 size_t offset; 1359 size_t size; 1360 int64_t timeUs; 1361 uint32_t flags; 1362 CHECK(msg->findSize("index", &index)); 1363 CHECK(msg->findSize("offset", &offset)); 1364 CHECK(msg->findInt64("timeUs", &timeUs)); 1365 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 1366 1367 const CryptoPlugin::SubSample *subSamples; 1368 size_t numSubSamples; 1369 const uint8_t *key; 1370 const uint8_t *iv; 1371 CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted; 1372 1373 // We allow the simpler queueInputBuffer API to be used even in 1374 // secure mode, by fabricating a single unencrypted subSample. 1375 CryptoPlugin::SubSample ss; 1376 1377 if (msg->findSize("size", &size)) { 1378 if (mCrypto != NULL) { 1379 ss.mNumBytesOfClearData = size; 1380 ss.mNumBytesOfEncryptedData = 0; 1381 1382 subSamples = &ss; 1383 numSubSamples = 1; 1384 key = NULL; 1385 iv = NULL; 1386 } 1387 } else { 1388 if (mCrypto == NULL) { 1389 return -EINVAL; 1390 } 1391 1392 CHECK(msg->findPointer("subSamples", (void **)&subSamples)); 1393 CHECK(msg->findSize("numSubSamples", &numSubSamples)); 1394 CHECK(msg->findPointer("key", (void **)&key)); 1395 CHECK(msg->findPointer("iv", (void **)&iv)); 1396 1397 int32_t tmp; 1398 CHECK(msg->findInt32("mode", &tmp)); 1399 1400 mode = (CryptoPlugin::Mode)tmp; 1401 1402 size = 0; 1403 for (size_t i = 0; i < numSubSamples; ++i) { 1404 size += subSamples[i].mNumBytesOfClearData; 1405 size += subSamples[i].mNumBytesOfEncryptedData; 1406 } 1407 } 1408 1409 if (index >= mPortBuffers[kPortIndexInput].size()) { 1410 return -ERANGE; 1411 } 1412 1413 BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index); 1414 1415 if (info->mNotify == NULL || !info->mOwnedByClient) { 1416 return -EACCES; 1417 } 1418 1419 if (offset + size > info->mData->capacity()) { 1420 return -EINVAL; 1421 } 1422 1423 sp<AMessage> reply = info->mNotify; 1424 info->mData->setRange(offset, size); 1425 info->mData->meta()->setInt64("timeUs", timeUs); 1426 1427 if (flags & BUFFER_FLAG_EOS) { 1428 info->mData->meta()->setInt32("eos", true); 1429 } 1430 1431 if (flags & BUFFER_FLAG_CODECCONFIG) { 1432 info->mData->meta()->setInt32("csd", true); 1433 } 1434 1435 if (mCrypto != NULL) { 1436 if (size > info->mEncryptedData->capacity()) { 1437 return -ERANGE; 1438 } 1439 1440 AString *errorDetailMsg; 1441 CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg)); 1442 1443 ssize_t result = mCrypto->decrypt( 1444 (mFlags & kFlagIsSecure) != 0, 1445 key, 1446 iv, 1447 mode, 1448 info->mEncryptedData->base() + offset, 1449 subSamples, 1450 numSubSamples, 1451 info->mData->base(), 1452 errorDetailMsg); 1453 1454 if (result < 0) { 1455 return result; 1456 } 1457 1458 info->mData->setRange(0, result); 1459 } 1460 1461 reply->setBuffer("buffer", info->mData); 1462 reply->post(); 1463 1464 info->mNotify = NULL; 1465 info->mOwnedByClient = false; 1466 1467 return OK; 1468} 1469 1470status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) { 1471 size_t index; 1472 CHECK(msg->findSize("index", &index)); 1473 1474 int32_t render; 1475 if (!msg->findInt32("render", &render)) { 1476 render = 0; 1477 } 1478 1479 if (mState != STARTED) { 1480 return -EINVAL; 1481 } 1482 1483 if (index >= mPortBuffers[kPortIndexOutput].size()) { 1484 return -ERANGE; 1485 } 1486 1487 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index); 1488 1489 if (info->mNotify == NULL || !info->mOwnedByClient) { 1490 return -EACCES; 1491 } 1492 1493 if (render) { 1494 info->mNotify->setInt32("render", true); 1495 1496 if (mSoftRenderer != NULL) { 1497 mSoftRenderer->render( 1498 info->mData->data(), info->mData->size(), NULL); 1499 } 1500 } 1501 1502 info->mNotify->post(); 1503 info->mNotify = NULL; 1504 info->mOwnedByClient = false; 1505 1506 return OK; 1507} 1508 1509ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) { 1510 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1511 1512 List<size_t> *availBuffers = &mAvailPortBuffers[portIndex]; 1513 1514 if (availBuffers->empty()) { 1515 return -EAGAIN; 1516 } 1517 1518 size_t index = *availBuffers->begin(); 1519 availBuffers->erase(availBuffers->begin()); 1520 1521 BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index); 1522 CHECK(!info->mOwnedByClient); 1523 info->mOwnedByClient = true; 1524 1525 return index; 1526} 1527 1528status_t MediaCodec::setNativeWindow( 1529 const sp<SurfaceTextureClient> &surfaceTextureClient) { 1530 status_t err; 1531 1532 if (mNativeWindow != NULL) { 1533 err = native_window_api_disconnect( 1534 mNativeWindow.get(), NATIVE_WINDOW_API_MEDIA); 1535 1536 if (err != OK) { 1537 ALOGW("native_window_api_disconnect returned an error: %s (%d)", 1538 strerror(-err), err); 1539 } 1540 1541 mNativeWindow.clear(); 1542 } 1543 1544 if (surfaceTextureClient != NULL) { 1545 err = native_window_api_connect( 1546 surfaceTextureClient.get(), NATIVE_WINDOW_API_MEDIA); 1547 1548 if (err != OK) { 1549 ALOGE("native_window_api_connect returned an error: %s (%d)", 1550 strerror(-err), err); 1551 1552 return err; 1553 } 1554 1555 mNativeWindow = surfaceTextureClient; 1556 } 1557 1558 return OK; 1559} 1560 1561void MediaCodec::postActivityNotificationIfPossible() { 1562 if (mActivityNotify == NULL) { 1563 return; 1564 } 1565 1566 if ((mFlags & (kFlagStickyError 1567 | kFlagOutputBuffersChanged 1568 | kFlagOutputFormatChanged)) 1569 || !mAvailPortBuffers[kPortIndexInput].empty() 1570 || !mAvailPortBuffers[kPortIndexOutput].empty()) { 1571 mActivityNotify->post(); 1572 mActivityNotify.clear(); 1573 } 1574} 1575 1576status_t MediaCodec::setParameters(const sp<AMessage> ¶ms) { 1577 sp<AMessage> msg = new AMessage(kWhatSetParameters, id()); 1578 msg->setMessage("params", params); 1579 1580 sp<AMessage> response; 1581 return PostAndAwaitResponse(msg, &response); 1582} 1583 1584status_t MediaCodec::onSetParameters(const sp<AMessage> ¶ms) { 1585 mCodec->signalSetParameters(params); 1586 1587 return OK; 1588} 1589 1590} // namespace android 1591