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