MediaCodec.cpp revision c95c2ddcdfc974f42408a377fbe2de51b94a8c94
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/stagefright/foundation/ABuffer.h> 27#include <media/stagefright/foundation/ADebug.h> 28#include <media/stagefright/foundation/AMessage.h> 29#include <media/stagefright/ACodec.h> 30#include <media/stagefright/MediaErrors.h> 31#include <media/stagefright/MetaData.h> 32#include <media/stagefright/NativeWindowWrapper.h> 33 34namespace android { 35 36// static 37sp<MediaCodec> MediaCodec::CreateByType( 38 const sp<ALooper> &looper, const char *mime, bool encoder) { 39 sp<MediaCodec> codec = new MediaCodec(looper); 40 if (codec->init(mime, true /* nameIsType */, encoder) != OK) { 41 return NULL; 42 } 43 44 return codec; 45} 46 47// static 48sp<MediaCodec> MediaCodec::CreateByComponentName( 49 const sp<ALooper> &looper, const char *name) { 50 sp<MediaCodec> codec = new MediaCodec(looper); 51 if (codec->init(name, false /* nameIsType */, false /* encoder */) != OK) { 52 return NULL; 53 } 54 55 return codec; 56} 57 58MediaCodec::MediaCodec(const sp<ALooper> &looper) 59 : mState(UNINITIALIZED), 60 mLooper(looper), 61 mCodec(new ACodec), 62 mFlags(0), 63 mSoftRenderer(NULL), 64 mDequeueInputTimeoutGeneration(0), 65 mDequeueInputReplyID(0), 66 mDequeueOutputTimeoutGeneration(0), 67 mDequeueOutputReplyID(0) { 68} 69 70MediaCodec::~MediaCodec() { 71 CHECK_EQ(mState, UNINITIALIZED); 72} 73 74// static 75status_t MediaCodec::PostAndAwaitResponse( 76 const sp<AMessage> &msg, sp<AMessage> *response) { 77 status_t err = msg->postAndAwaitResponse(response); 78 79 if (err != OK) { 80 return err; 81 } 82 83 if (!(*response)->findInt32("err", &err)) { 84 err = OK; 85 } 86 87 return err; 88} 89 90status_t MediaCodec::init(const char *name, bool nameIsType, bool encoder) { 91 // Current video decoders do not return from OMX_FillThisBuffer 92 // quickly, violating the OpenMAX specs, until that is remedied 93 // we need to invest in an extra looper to free the main event 94 // queue. 95 bool needDedicatedLooper = false; 96 if (nameIsType && !strncasecmp(name, "video/", 6)) { 97 needDedicatedLooper = true; 98 } else if (!nameIsType && !strncmp(name, "OMX.TI.DUCATI1.VIDEO.", 21)) { 99 needDedicatedLooper = true; 100 } 101 102 if (needDedicatedLooper) { 103 if (mCodecLooper == NULL) { 104 mCodecLooper = new ALooper; 105 mCodecLooper->setName("CodecLooper"); 106 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO); 107 } 108 109 mCodecLooper->registerHandler(mCodec); 110 } else { 111 mLooper->registerHandler(mCodec); 112 } 113 114 mLooper->registerHandler(this); 115 116 mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id())); 117 118 sp<AMessage> msg = new AMessage(kWhatInit, id()); 119 msg->setString("name", name); 120 msg->setInt32("nameIsType", nameIsType); 121 122 if (nameIsType) { 123 msg->setInt32("encoder", encoder); 124 } 125 126 sp<AMessage> response; 127 return PostAndAwaitResponse(msg, &response); 128} 129 130status_t MediaCodec::configure( 131 const sp<AMessage> &format, 132 const sp<SurfaceTextureClient> &nativeWindow, 133 uint32_t flags) { 134 sp<AMessage> msg = new AMessage(kWhatConfigure, id()); 135 136 msg->setMessage("format", format); 137 msg->setInt32("flags", flags); 138 139 if (nativeWindow != NULL) { 140 if (!(mFlags & kFlagIsSoftwareCodec)) { 141 msg->setObject( 142 "native-window", 143 new NativeWindowWrapper(nativeWindow)); 144 } else { 145 mNativeWindow = nativeWindow; 146 } 147 } 148 149 sp<AMessage> response; 150 return PostAndAwaitResponse(msg, &response); 151} 152 153status_t MediaCodec::start() { 154 sp<AMessage> msg = new AMessage(kWhatStart, id()); 155 156 sp<AMessage> response; 157 return PostAndAwaitResponse(msg, &response); 158} 159 160status_t MediaCodec::stop() { 161 sp<AMessage> msg = new AMessage(kWhatStop, id()); 162 163 sp<AMessage> response; 164 return PostAndAwaitResponse(msg, &response); 165} 166 167status_t MediaCodec::release() { 168 sp<AMessage> msg = new AMessage(kWhatRelease, id()); 169 170 sp<AMessage> response; 171 return PostAndAwaitResponse(msg, &response); 172} 173 174status_t MediaCodec::queueInputBuffer( 175 size_t index, 176 size_t offset, 177 size_t size, 178 int64_t presentationTimeUs, 179 uint32_t flags) { 180 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id()); 181 msg->setSize("index", index); 182 msg->setSize("offset", offset); 183 msg->setSize("size", size); 184 msg->setInt64("timeUs", presentationTimeUs); 185 msg->setInt32("flags", flags); 186 187 sp<AMessage> response; 188 return PostAndAwaitResponse(msg, &response); 189} 190 191status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) { 192 sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id()); 193 msg->setInt64("timeoutUs", timeoutUs); 194 195 sp<AMessage> response; 196 status_t err; 197 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 198 return err; 199 } 200 201 CHECK(response->findSize("index", index)); 202 203 return OK; 204} 205 206status_t MediaCodec::dequeueOutputBuffer( 207 size_t *index, 208 size_t *offset, 209 size_t *size, 210 int64_t *presentationTimeUs, 211 uint32_t *flags, 212 int64_t timeoutUs) { 213 sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, id()); 214 msg->setInt64("timeoutUs", timeoutUs); 215 216 sp<AMessage> response; 217 status_t err; 218 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 219 return err; 220 } 221 222 CHECK(response->findSize("index", index)); 223 CHECK(response->findSize("offset", offset)); 224 CHECK(response->findSize("size", size)); 225 CHECK(response->findInt64("timeUs", presentationTimeUs)); 226 CHECK(response->findInt32("flags", (int32_t *)flags)); 227 228 return OK; 229} 230 231status_t MediaCodec::renderOutputBufferAndRelease(size_t index) { 232 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id()); 233 msg->setSize("index", index); 234 msg->setInt32("render", true); 235 236 sp<AMessage> response; 237 return PostAndAwaitResponse(msg, &response); 238} 239 240status_t MediaCodec::releaseOutputBuffer(size_t index) { 241 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id()); 242 msg->setSize("index", index); 243 244 sp<AMessage> response; 245 return PostAndAwaitResponse(msg, &response); 246} 247 248status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const { 249 sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, id()); 250 251 sp<AMessage> response; 252 status_t err; 253 if ((err = PostAndAwaitResponse(msg, &response)) != OK) { 254 return err; 255 } 256 257 CHECK(response->findMessage("format", format)); 258 259 return OK; 260} 261 262status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const { 263 sp<AMessage> msg = new AMessage(kWhatGetBuffers, id()); 264 msg->setInt32("portIndex", kPortIndexInput); 265 msg->setPointer("buffers", buffers); 266 267 sp<AMessage> response; 268 return PostAndAwaitResponse(msg, &response); 269} 270 271status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const { 272 sp<AMessage> msg = new AMessage(kWhatGetBuffers, id()); 273 msg->setInt32("portIndex", kPortIndexOutput); 274 msg->setPointer("buffers", buffers); 275 276 sp<AMessage> response; 277 return PostAndAwaitResponse(msg, &response); 278} 279 280status_t MediaCodec::flush() { 281 sp<AMessage> msg = new AMessage(kWhatFlush, id()); 282 283 sp<AMessage> response; 284 return PostAndAwaitResponse(msg, &response); 285} 286 287//////////////////////////////////////////////////////////////////////////////// 288 289void MediaCodec::cancelPendingDequeueOperations() { 290 if (mFlags & kFlagDequeueInputPending) { 291 sp<AMessage> response = new AMessage; 292 response->setInt32("err", INVALID_OPERATION); 293 response->postReply(mDequeueInputReplyID); 294 295 ++mDequeueInputTimeoutGeneration; 296 mDequeueInputReplyID = 0; 297 mFlags &= ~kFlagDequeueInputPending; 298 } 299 300 if (mFlags & kFlagDequeueOutputPending) { 301 sp<AMessage> response = new AMessage; 302 response->setInt32("err", INVALID_OPERATION); 303 response->postReply(mDequeueOutputReplyID); 304 305 ++mDequeueOutputTimeoutGeneration; 306 mDequeueOutputReplyID = 0; 307 mFlags &= ~kFlagDequeueOutputPending; 308 } 309} 310 311bool MediaCodec::handleDequeueInputBuffer(uint32_t replyID, bool newRequest) { 312 if (mState != STARTED 313 || (mFlags & kFlagStickyError) 314 || (newRequest && (mFlags & kFlagDequeueInputPending))) { 315 sp<AMessage> response = new AMessage; 316 response->setInt32("err", INVALID_OPERATION); 317 318 response->postReply(replyID); 319 320 return true; 321 } 322 323 ssize_t index = dequeuePortBuffer(kPortIndexInput); 324 325 if (index < 0) { 326 CHECK_EQ(index, -EAGAIN); 327 return false; 328 } 329 330 sp<AMessage> response = new AMessage; 331 response->setSize("index", index); 332 response->postReply(replyID); 333 334 return true; 335} 336 337bool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) { 338 sp<AMessage> response = new AMessage; 339 340 if (mState != STARTED 341 || (mFlags & kFlagStickyError) 342 || (newRequest && (mFlags & kFlagDequeueOutputPending))) { 343 response->setInt32("err", INVALID_OPERATION); 344 } else if (mFlags & kFlagOutputBuffersChanged) { 345 response->setInt32("err", INFO_OUTPUT_BUFFERS_CHANGED); 346 mFlags &= ~kFlagOutputBuffersChanged; 347 } else if (mFlags & kFlagOutputFormatChanged) { 348 response->setInt32("err", INFO_FORMAT_CHANGED); 349 mFlags &= ~kFlagOutputFormatChanged; 350 } else { 351 ssize_t index = dequeuePortBuffer(kPortIndexOutput); 352 353 if (index < 0) { 354 CHECK_EQ(index, -EAGAIN); 355 return false; 356 } 357 358 const sp<ABuffer> &buffer = 359 mPortBuffers[kPortIndexOutput].itemAt(index).mData; 360 361 response->setSize("index", index); 362 response->setSize("offset", buffer->offset()); 363 response->setSize("size", buffer->size()); 364 365 int64_t timeUs; 366 CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); 367 368 response->setInt64("timeUs", timeUs); 369 370 int32_t omxFlags; 371 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags)); 372 373 uint32_t flags = 0; 374 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) { 375 flags |= BUFFER_FLAG_SYNCFRAME; 376 } 377 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) { 378 flags |= BUFFER_FLAG_CODECCONFIG; 379 } 380 if (omxFlags & OMX_BUFFERFLAG_EOS) { 381 flags |= BUFFER_FLAG_EOS; 382 } 383 384 response->setInt32("flags", flags); 385 } 386 387 response->postReply(replyID); 388 389 return true; 390} 391 392void MediaCodec::onMessageReceived(const sp<AMessage> &msg) { 393 switch (msg->what()) { 394 case kWhatCodecNotify: 395 { 396 int32_t what; 397 CHECK(msg->findInt32("what", &what)); 398 399 switch (what) { 400 case ACodec::kWhatError: 401 { 402 int32_t omxError, internalError; 403 CHECK(msg->findInt32("omx-error", &omxError)); 404 CHECK(msg->findInt32("err", &internalError)); 405 406 ALOGE("Codec reported an error. " 407 "(omx error 0x%08x, internalError %d)", 408 omxError, internalError); 409 410 bool sendErrorReponse = true; 411 412 switch (mState) { 413 case INITIALIZING: 414 { 415 setState(UNINITIALIZED); 416 break; 417 } 418 419 case CONFIGURING: 420 { 421 setState(INITIALIZED); 422 break; 423 } 424 425 case STARTING: 426 { 427 setState(CONFIGURED); 428 break; 429 } 430 431 case STOPPING: 432 case RELEASING: 433 { 434 // Ignore the error, assuming we'll still get 435 // the shutdown complete notification. 436 437 sendErrorReponse = false; 438 break; 439 } 440 441 case FLUSHING: 442 { 443 setState(STARTED); 444 break; 445 } 446 447 case STARTED: 448 { 449 sendErrorReponse = false; 450 451 mFlags |= kFlagStickyError; 452 453 cancelPendingDequeueOperations(); 454 break; 455 } 456 457 default: 458 { 459 sendErrorReponse = false; 460 461 mFlags |= kFlagStickyError; 462 break; 463 } 464 } 465 466 if (sendErrorReponse) { 467 sp<AMessage> response = new AMessage; 468 response->setInt32("err", UNKNOWN_ERROR); 469 470 response->postReply(mReplyID); 471 } 472 break; 473 } 474 475 case ACodec::kWhatComponentAllocated: 476 { 477 CHECK_EQ(mState, INITIALIZING); 478 setState(INITIALIZED); 479 480 AString componentName; 481 CHECK(msg->findString("componentName", &componentName)); 482 483 if (componentName.startsWith("OMX.google.")) { 484 mFlags |= kFlagIsSoftwareCodec; 485 } else { 486 mFlags &= ~kFlagIsSoftwareCodec; 487 } 488 489 (new AMessage)->postReply(mReplyID); 490 break; 491 } 492 493 case ACodec::kWhatComponentConfigured: 494 { 495 CHECK_EQ(mState, CONFIGURING); 496 setState(CONFIGURED); 497 498 (new AMessage)->postReply(mReplyID); 499 break; 500 } 501 502 case ACodec::kWhatBuffersAllocated: 503 { 504 int32_t portIndex; 505 CHECK(msg->findInt32("portIndex", &portIndex)); 506 507 ALOGV("%s buffers allocated", 508 portIndex == kPortIndexInput ? "input" : "output"); 509 510 CHECK(portIndex == kPortIndexInput 511 || portIndex == kPortIndexOutput); 512 513 mPortBuffers[portIndex].clear(); 514 515 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 516 for (size_t i = 0;; ++i) { 517 AString name = StringPrintf("buffer-id_%d", i); 518 519 void *bufferID; 520 if (!msg->findPointer(name.c_str(), &bufferID)) { 521 break; 522 } 523 524 name = StringPrintf("data_%d", i); 525 526 BufferInfo info; 527 info.mBufferID = bufferID; 528 info.mOwnedByClient = false; 529 CHECK(msg->findBuffer(name.c_str(), &info.mData)); 530 531 buffers->push_back(info); 532 } 533 534 if (portIndex == kPortIndexOutput) { 535 if (mState == STARTING) { 536 // We're always allocating output buffers after 537 // allocating input buffers, so this is a good 538 // indication that now all buffers are allocated. 539 setState(STARTED); 540 (new AMessage)->postReply(mReplyID); 541 } else { 542 mFlags |= kFlagOutputBuffersChanged; 543 } 544 } 545 break; 546 } 547 548 case ACodec::kWhatOutputFormatChanged: 549 { 550 ALOGV("codec output format changed"); 551 552 if ((mFlags & kFlagIsSoftwareCodec) 553 && mNativeWindow != NULL) { 554 AString mime; 555 CHECK(msg->findString("mime", &mime)); 556 557 if (!strncasecmp("video/", mime.c_str(), 6)) { 558 delete mSoftRenderer; 559 mSoftRenderer = NULL; 560 561 int32_t width, height; 562 CHECK(msg->findInt32("width", &width)); 563 CHECK(msg->findInt32("height", &height)); 564 565 int32_t colorFormat; 566 CHECK(msg->findInt32( 567 "color-format", &colorFormat)); 568 569 sp<MetaData> meta = new MetaData; 570 meta->setInt32(kKeyWidth, width); 571 meta->setInt32(kKeyHeight, height); 572 meta->setInt32(kKeyColorFormat, colorFormat); 573 574 mSoftRenderer = 575 new SoftwareRenderer(mNativeWindow, meta); 576 } 577 } 578 579 mOutputFormat = msg; 580 mFlags |= kFlagOutputFormatChanged; 581 break; 582 } 583 584 case ACodec::kWhatFillThisBuffer: 585 { 586 /* size_t index = */updateBuffers(kPortIndexInput, msg); 587 588 if (mState == FLUSHING 589 || mState == STOPPING 590 || mState == RELEASING) { 591 returnBuffersToCodecOnPort(kPortIndexInput); 592 break; 593 } 594 595 if (mFlags & kFlagDequeueInputPending) { 596 CHECK(handleDequeueInputBuffer(mDequeueInputReplyID)); 597 598 ++mDequeueInputTimeoutGeneration; 599 mFlags &= ~kFlagDequeueInputPending; 600 mDequeueInputReplyID = 0; 601 } 602 break; 603 } 604 605 case ACodec::kWhatDrainThisBuffer: 606 { 607 /* size_t index = */updateBuffers(kPortIndexOutput, msg); 608 609 if (mState == FLUSHING 610 || mState == STOPPING 611 || mState == RELEASING) { 612 returnBuffersToCodecOnPort(kPortIndexOutput); 613 break; 614 } 615 616 sp<ABuffer> buffer; 617 CHECK(msg->findBuffer("buffer", &buffer)); 618 619 int32_t omxFlags; 620 CHECK(msg->findInt32("flags", &omxFlags)); 621 622 buffer->meta()->setInt32("omxFlags", omxFlags); 623 624 if (mFlags & kFlagDequeueOutputPending) { 625 CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID)); 626 627 ++mDequeueOutputTimeoutGeneration; 628 mFlags &= ~kFlagDequeueOutputPending; 629 mDequeueOutputReplyID = 0; 630 } 631 break; 632 } 633 634 case ACodec::kWhatEOS: 635 { 636 // We already notify the client of this by using the 637 // corresponding flag in "onOutputBufferReady". 638 break; 639 } 640 641 case ACodec::kWhatShutdownCompleted: 642 { 643 if (mState == STOPPING) { 644 setState(INITIALIZED); 645 } else { 646 CHECK_EQ(mState, RELEASING); 647 setState(UNINITIALIZED); 648 } 649 650 (new AMessage)->postReply(mReplyID); 651 break; 652 } 653 654 case ACodec::kWhatFlushCompleted: 655 { 656 CHECK_EQ(mState, FLUSHING); 657 setState(STARTED); 658 659 mCodec->signalResume(); 660 661 (new AMessage)->postReply(mReplyID); 662 break; 663 } 664 665 default: 666 TRESPASS(); 667 } 668 break; 669 } 670 671 case kWhatInit: 672 { 673 uint32_t replyID; 674 CHECK(msg->senderAwaitsResponse(&replyID)); 675 676 if (mState != UNINITIALIZED) { 677 sp<AMessage> response = new AMessage; 678 response->setInt32("err", INVALID_OPERATION); 679 680 response->postReply(replyID); 681 break; 682 } 683 684 mReplyID = replyID; 685 setState(INITIALIZING); 686 687 AString name; 688 CHECK(msg->findString("name", &name)); 689 690 int32_t nameIsType; 691 int32_t encoder = false; 692 CHECK(msg->findInt32("nameIsType", &nameIsType)); 693 if (nameIsType) { 694 CHECK(msg->findInt32("encoder", &encoder)); 695 } 696 697 sp<AMessage> format = new AMessage; 698 699 if (nameIsType) { 700 format->setString("mime", name.c_str()); 701 format->setInt32("encoder", encoder); 702 } else { 703 format->setString("componentName", name.c_str()); 704 } 705 706 mCodec->initiateAllocateComponent(format); 707 break; 708 } 709 710 case kWhatConfigure: 711 { 712 uint32_t replyID; 713 CHECK(msg->senderAwaitsResponse(&replyID)); 714 715 if (mState != INITIALIZED) { 716 sp<AMessage> response = new AMessage; 717 response->setInt32("err", INVALID_OPERATION); 718 719 response->postReply(replyID); 720 break; 721 } 722 723 mReplyID = replyID; 724 setState(CONFIGURING); 725 726 sp<RefBase> obj; 727 if (!msg->findObject("native-window", &obj)) { 728 obj.clear(); 729 } 730 731 sp<AMessage> format; 732 CHECK(msg->findMessage("format", &format)); 733 734 if (obj != NULL) { 735 format->setObject("native-window", obj); 736 } 737 738 uint32_t flags; 739 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 740 741 if (flags & CONFIGURE_FLAG_ENCODE) { 742 format->setInt32("encoder", true); 743 } 744 745 mCodec->initiateConfigureComponent(format); 746 break; 747 } 748 749 case kWhatStart: 750 { 751 uint32_t replyID; 752 CHECK(msg->senderAwaitsResponse(&replyID)); 753 754 if (mState != CONFIGURED) { 755 sp<AMessage> response = new AMessage; 756 response->setInt32("err", INVALID_OPERATION); 757 758 response->postReply(replyID); 759 break; 760 } 761 762 mReplyID = replyID; 763 setState(STARTING); 764 765 mCodec->initiateStart(); 766 break; 767 } 768 769 case kWhatStop: 770 { 771 uint32_t replyID; 772 CHECK(msg->senderAwaitsResponse(&replyID)); 773 774 if (mState != INITIALIZED 775 && mState != CONFIGURED && mState != STARTED) { 776 sp<AMessage> response = new AMessage; 777 response->setInt32("err", INVALID_OPERATION); 778 779 response->postReply(replyID); 780 break; 781 } 782 783 mReplyID = replyID; 784 setState(STOPPING); 785 786 mCodec->initiateShutdown(true /* keepComponentAllocated */); 787 returnBuffersToCodec(); 788 break; 789 } 790 791 case kWhatRelease: 792 { 793 uint32_t replyID; 794 CHECK(msg->senderAwaitsResponse(&replyID)); 795 796 if (mState != INITIALIZED 797 && mState != CONFIGURED && mState != STARTED) { 798 sp<AMessage> response = new AMessage; 799 response->setInt32("err", INVALID_OPERATION); 800 801 response->postReply(replyID); 802 break; 803 } 804 805 mReplyID = replyID; 806 setState(RELEASING); 807 808 mCodec->initiateShutdown(); 809 returnBuffersToCodec(); 810 break; 811 } 812 813 case kWhatDequeueInputBuffer: 814 { 815 uint32_t replyID; 816 CHECK(msg->senderAwaitsResponse(&replyID)); 817 818 if (handleDequeueInputBuffer(replyID, true /* new request */)) { 819 break; 820 } 821 822 int64_t timeoutUs; 823 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 824 825 if (timeoutUs == 0ll) { 826 sp<AMessage> response = new AMessage; 827 response->setInt32("err", -EAGAIN); 828 response->postReply(replyID); 829 break; 830 } 831 832 mFlags |= kFlagDequeueInputPending; 833 mDequeueInputReplyID = replyID; 834 835 if (timeoutUs > 0ll) { 836 sp<AMessage> timeoutMsg = 837 new AMessage(kWhatDequeueInputTimedOut, id()); 838 timeoutMsg->setInt32( 839 "generation", ++mDequeueInputTimeoutGeneration); 840 timeoutMsg->post(timeoutUs); 841 } 842 break; 843 } 844 845 case kWhatDequeueInputTimedOut: 846 { 847 int32_t generation; 848 CHECK(msg->findInt32("generation", &generation)); 849 850 if (generation != mDequeueInputTimeoutGeneration) { 851 // Obsolete 852 break; 853 } 854 855 CHECK(mFlags & kFlagDequeueInputPending); 856 857 sp<AMessage> response = new AMessage; 858 response->setInt32("err", -EAGAIN); 859 response->postReply(mDequeueInputReplyID); 860 861 mFlags &= ~kFlagDequeueInputPending; 862 mDequeueInputReplyID = 0; 863 break; 864 } 865 866 case kWhatQueueInputBuffer: 867 { 868 uint32_t replyID; 869 CHECK(msg->senderAwaitsResponse(&replyID)); 870 871 if (mState != STARTED || (mFlags & kFlagStickyError)) { 872 sp<AMessage> response = new AMessage; 873 response->setInt32("err", INVALID_OPERATION); 874 875 response->postReply(replyID); 876 break; 877 } 878 879 status_t err = onQueueInputBuffer(msg); 880 881 sp<AMessage> response = new AMessage; 882 response->setInt32("err", err); 883 response->postReply(replyID); 884 break; 885 } 886 887 case kWhatDequeueOutputBuffer: 888 { 889 uint32_t replyID; 890 CHECK(msg->senderAwaitsResponse(&replyID)); 891 892 if (handleDequeueOutputBuffer(replyID, true /* new request */)) { 893 break; 894 } 895 896 int64_t timeoutUs; 897 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 898 899 if (timeoutUs == 0ll) { 900 sp<AMessage> response = new AMessage; 901 response->setInt32("err", -EAGAIN); 902 response->postReply(replyID); 903 break; 904 } 905 906 mFlags |= kFlagDequeueOutputPending; 907 mDequeueOutputReplyID = replyID; 908 909 if (timeoutUs > 0ll) { 910 sp<AMessage> timeoutMsg = 911 new AMessage(kWhatDequeueOutputTimedOut, id()); 912 timeoutMsg->setInt32( 913 "generation", ++mDequeueOutputTimeoutGeneration); 914 timeoutMsg->post(timeoutUs); 915 } 916 break; 917 } 918 919 case kWhatDequeueOutputTimedOut: 920 { 921 int32_t generation; 922 CHECK(msg->findInt32("generation", &generation)); 923 924 if (generation != mDequeueOutputTimeoutGeneration) { 925 // Obsolete 926 break; 927 } 928 929 CHECK(mFlags & kFlagDequeueOutputPending); 930 931 sp<AMessage> response = new AMessage; 932 response->setInt32("err", -EAGAIN); 933 response->postReply(mDequeueOutputReplyID); 934 935 mFlags &= ~kFlagDequeueOutputPending; 936 mDequeueOutputReplyID = 0; 937 break; 938 } 939 940 case kWhatReleaseOutputBuffer: 941 { 942 uint32_t replyID; 943 CHECK(msg->senderAwaitsResponse(&replyID)); 944 945 if (mState != STARTED || (mFlags & kFlagStickyError)) { 946 sp<AMessage> response = new AMessage; 947 response->setInt32("err", INVALID_OPERATION); 948 949 response->postReply(replyID); 950 break; 951 } 952 953 status_t err = onReleaseOutputBuffer(msg); 954 955 sp<AMessage> response = new AMessage; 956 response->setInt32("err", err); 957 response->postReply(replyID); 958 break; 959 } 960 961 case kWhatGetBuffers: 962 { 963 uint32_t replyID; 964 CHECK(msg->senderAwaitsResponse(&replyID)); 965 966 if (mState != STARTED || (mFlags & kFlagStickyError)) { 967 sp<AMessage> response = new AMessage; 968 response->setInt32("err", INVALID_OPERATION); 969 970 response->postReply(replyID); 971 break; 972 } 973 974 int32_t portIndex; 975 CHECK(msg->findInt32("portIndex", &portIndex)); 976 977 Vector<sp<ABuffer> > *dstBuffers; 978 CHECK(msg->findPointer("buffers", (void **)&dstBuffers)); 979 980 dstBuffers->clear(); 981 const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex]; 982 983 for (size_t i = 0; i < srcBuffers.size(); ++i) { 984 const BufferInfo &info = srcBuffers.itemAt(i); 985 986 dstBuffers->push_back(info.mData); 987 } 988 989 (new AMessage)->postReply(replyID); 990 break; 991 } 992 993 case kWhatFlush: 994 { 995 uint32_t replyID; 996 CHECK(msg->senderAwaitsResponse(&replyID)); 997 998 if (mState != STARTED || (mFlags & kFlagStickyError)) { 999 sp<AMessage> response = new AMessage; 1000 response->setInt32("err", INVALID_OPERATION); 1001 1002 response->postReply(replyID); 1003 break; 1004 } 1005 1006 mReplyID = replyID; 1007 setState(FLUSHING); 1008 1009 mCodec->signalFlush(); 1010 returnBuffersToCodec(); 1011 break; 1012 } 1013 1014 case kWhatGetOutputFormat: 1015 { 1016 uint32_t replyID; 1017 CHECK(msg->senderAwaitsResponse(&replyID)); 1018 1019 if ((mState != STARTED && mState != FLUSHING) 1020 || (mFlags & kFlagStickyError)) { 1021 sp<AMessage> response = new AMessage; 1022 response->setInt32("err", INVALID_OPERATION); 1023 1024 response->postReply(replyID); 1025 break; 1026 } 1027 1028 sp<AMessage> response = new AMessage; 1029 response->setMessage("format", mOutputFormat); 1030 response->postReply(replyID); 1031 break; 1032 } 1033 1034 default: 1035 TRESPASS(); 1036 } 1037} 1038 1039void MediaCodec::setState(State newState) { 1040 if (newState == UNINITIALIZED) { 1041 delete mSoftRenderer; 1042 mSoftRenderer = NULL; 1043 1044 mNativeWindow.clear(); 1045 1046 mOutputFormat.clear(); 1047 mFlags &= ~kFlagOutputFormatChanged; 1048 mFlags &= ~kFlagOutputBuffersChanged; 1049 mFlags &= ~kFlagStickyError; 1050 } 1051 1052 mState = newState; 1053 1054 cancelPendingDequeueOperations(); 1055} 1056 1057void MediaCodec::returnBuffersToCodec() { 1058 returnBuffersToCodecOnPort(kPortIndexInput); 1059 returnBuffersToCodecOnPort(kPortIndexOutput); 1060} 1061 1062void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) { 1063 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1064 1065 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 1066 1067 for (size_t i = 0; i < buffers->size(); ++i) { 1068 BufferInfo *info = &buffers->editItemAt(i); 1069 1070 if (info->mNotify != NULL) { 1071 sp<AMessage> msg = info->mNotify; 1072 info->mNotify = NULL; 1073 info->mOwnedByClient = false; 1074 1075 if (portIndex == kPortIndexInput) { 1076 msg->setInt32("err", ERROR_END_OF_STREAM); 1077 } 1078 msg->post(); 1079 } 1080 } 1081 1082 mAvailPortBuffers[portIndex].clear(); 1083} 1084 1085size_t MediaCodec::updateBuffers( 1086 int32_t portIndex, const sp<AMessage> &msg) { 1087 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1088 1089 void *bufferID; 1090 CHECK(msg->findPointer("buffer-id", &bufferID)); 1091 1092 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 1093 1094 for (size_t i = 0; i < buffers->size(); ++i) { 1095 BufferInfo *info = &buffers->editItemAt(i); 1096 1097 if (info->mBufferID == bufferID) { 1098 CHECK(info->mNotify == NULL); 1099 CHECK(msg->findMessage("reply", &info->mNotify)); 1100 1101 mAvailPortBuffers[portIndex].push_back(i); 1102 1103 return i; 1104 } 1105 } 1106 1107 TRESPASS(); 1108 1109 return 0; 1110} 1111 1112status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) { 1113 size_t index; 1114 size_t offset; 1115 size_t size; 1116 int64_t timeUs; 1117 uint32_t flags; 1118 CHECK(msg->findSize("index", &index)); 1119 CHECK(msg->findSize("offset", &offset)); 1120 CHECK(msg->findSize("size", &size)); 1121 CHECK(msg->findInt64("timeUs", &timeUs)); 1122 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 1123 1124 if (index >= mPortBuffers[kPortIndexInput].size()) { 1125 return -ERANGE; 1126 } 1127 1128 BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index); 1129 1130 if (info->mNotify == NULL || !info->mOwnedByClient) { 1131 return -EACCES; 1132 } 1133 1134 if (offset + size > info->mData->capacity()) { 1135 return -EINVAL; 1136 } 1137 1138 sp<AMessage> reply = info->mNotify; 1139 info->mNotify = NULL; 1140 info->mOwnedByClient = false; 1141 1142 info->mData->setRange(offset, size); 1143 info->mData->meta()->setInt64("timeUs", timeUs); 1144 1145 if (flags & BUFFER_FLAG_EOS) { 1146 info->mData->meta()->setInt32("eos", true); 1147 } 1148 1149 if (flags & BUFFER_FLAG_CODECCONFIG) { 1150 info->mData->meta()->setInt32("csd", true); 1151 } 1152 1153 reply->setBuffer("buffer", info->mData); 1154 reply->post(); 1155 1156 return OK; 1157} 1158 1159status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) { 1160 size_t index; 1161 CHECK(msg->findSize("index", &index)); 1162 1163 int32_t render; 1164 if (!msg->findInt32("render", &render)) { 1165 render = 0; 1166 } 1167 1168 if (mState != STARTED) { 1169 return -EINVAL; 1170 } 1171 1172 if (index >= mPortBuffers[kPortIndexOutput].size()) { 1173 return -ERANGE; 1174 } 1175 1176 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index); 1177 1178 if (info->mNotify == NULL || !info->mOwnedByClient) { 1179 return -EACCES; 1180 } 1181 1182 if (render) { 1183 info->mNotify->setInt32("render", true); 1184 1185 if (mSoftRenderer != NULL) { 1186 mSoftRenderer->render( 1187 info->mData->data(), info->mData->size(), NULL); 1188 } 1189 } 1190 1191 info->mNotify->post(); 1192 info->mNotify = NULL; 1193 info->mOwnedByClient = false; 1194 1195 return OK; 1196} 1197 1198ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) { 1199 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1200 1201 List<size_t> *availBuffers = &mAvailPortBuffers[portIndex]; 1202 1203 if (availBuffers->empty()) { 1204 return -EAGAIN; 1205 } 1206 1207 size_t index = *availBuffers->begin(); 1208 availBuffers->erase(availBuffers->begin()); 1209 1210 BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index); 1211 CHECK(!info->mOwnedByClient); 1212 info->mOwnedByClient = true; 1213 1214 return index; 1215} 1216 1217} // namespace android 1218