MediaCodec.cpp revision 7fb5e8832f582ec515550696e9dabc3a8d9de14d
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 || mState == STOPPING) { 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 || mState == STOPPING) { 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 CHECK(msg->findInt32("nameIsType", &nameIsType)); 677 if (nameIsType) { 678 CHECK(msg->findInt32("encoder", &encoder)); 679 } 680 681 sp<AMessage> format = new AMessage; 682 683 if (nameIsType) { 684 format->setString("mime", name.c_str()); 685 format->setInt32("encoder", encoder); 686 } else { 687 format->setString("componentName", name.c_str()); 688 } 689 690 mCodec->initiateAllocateComponent(format); 691 break; 692 } 693 694 case kWhatConfigure: 695 { 696 uint32_t replyID; 697 CHECK(msg->senderAwaitsResponse(&replyID)); 698 699 if (mState != INITIALIZED) { 700 sp<AMessage> response = new AMessage; 701 response->setInt32("err", INVALID_OPERATION); 702 703 response->postReply(replyID); 704 break; 705 } 706 707 mReplyID = replyID; 708 setState(CONFIGURING); 709 710 sp<RefBase> obj; 711 if (!msg->findObject("native-window", &obj)) { 712 obj.clear(); 713 } 714 715 sp<AMessage> format; 716 CHECK(msg->findMessage("format", &format)); 717 718 if (obj != NULL) { 719 format->setObject("native-window", obj); 720 } 721 722 uint32_t flags; 723 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 724 725 if (flags & CONFIGURE_FLAG_ENCODE) { 726 format->setInt32("encoder", true); 727 } 728 729 mCodec->initiateConfigureComponent(format); 730 break; 731 } 732 733 case kWhatStart: 734 { 735 uint32_t replyID; 736 CHECK(msg->senderAwaitsResponse(&replyID)); 737 738 if (mState != CONFIGURED) { 739 sp<AMessage> response = new AMessage; 740 response->setInt32("err", INVALID_OPERATION); 741 742 response->postReply(replyID); 743 break; 744 } 745 746 mReplyID = replyID; 747 setState(STARTING); 748 749 mCodec->initiateStart(); 750 break; 751 } 752 753 case kWhatStop: 754 { 755 uint32_t replyID; 756 CHECK(msg->senderAwaitsResponse(&replyID)); 757 758 if (mState != INITIALIZED 759 && mState != CONFIGURED && mState != STARTED) { 760 sp<AMessage> response = new AMessage; 761 response->setInt32("err", INVALID_OPERATION); 762 763 response->postReply(replyID); 764 break; 765 } 766 767 mReplyID = replyID; 768 setState(STOPPING); 769 770 mCodec->initiateShutdown(); 771 returnBuffersToCodec(); 772 break; 773 } 774 775 case kWhatDequeueInputBuffer: 776 { 777 uint32_t replyID; 778 CHECK(msg->senderAwaitsResponse(&replyID)); 779 780 if (handleDequeueInputBuffer(replyID, true /* new request */)) { 781 break; 782 } 783 784 int64_t timeoutUs; 785 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 786 787 if (timeoutUs == 0ll) { 788 sp<AMessage> response = new AMessage; 789 response->setInt32("err", -EAGAIN); 790 response->postReply(replyID); 791 break; 792 } 793 794 mFlags |= kFlagDequeueInputPending; 795 mDequeueInputReplyID = replyID; 796 797 if (timeoutUs > 0ll) { 798 sp<AMessage> timeoutMsg = 799 new AMessage(kWhatDequeueInputTimedOut, id()); 800 timeoutMsg->setInt32( 801 "generation", ++mDequeueInputTimeoutGeneration); 802 timeoutMsg->post(timeoutUs); 803 } 804 break; 805 } 806 807 case kWhatDequeueInputTimedOut: 808 { 809 int32_t generation; 810 CHECK(msg->findInt32("generation", &generation)); 811 812 if (generation != mDequeueInputTimeoutGeneration) { 813 // Obsolete 814 break; 815 } 816 817 CHECK(mFlags & kFlagDequeueInputPending); 818 819 sp<AMessage> response = new AMessage; 820 response->setInt32("err", -EAGAIN); 821 response->postReply(mDequeueInputReplyID); 822 823 mFlags &= ~kFlagDequeueInputPending; 824 mDequeueInputReplyID = 0; 825 break; 826 } 827 828 case kWhatQueueInputBuffer: 829 { 830 uint32_t replyID; 831 CHECK(msg->senderAwaitsResponse(&replyID)); 832 833 if (mState != STARTED || (mFlags & kFlagStickyError)) { 834 sp<AMessage> response = new AMessage; 835 response->setInt32("err", INVALID_OPERATION); 836 837 response->postReply(replyID); 838 break; 839 } 840 841 status_t err = onQueueInputBuffer(msg); 842 843 sp<AMessage> response = new AMessage; 844 response->setInt32("err", err); 845 response->postReply(replyID); 846 break; 847 } 848 849 case kWhatDequeueOutputBuffer: 850 { 851 uint32_t replyID; 852 CHECK(msg->senderAwaitsResponse(&replyID)); 853 854 if (handleDequeueOutputBuffer(replyID, true /* new request */)) { 855 break; 856 } 857 858 int64_t timeoutUs; 859 CHECK(msg->findInt64("timeoutUs", &timeoutUs)); 860 861 if (timeoutUs == 0ll) { 862 sp<AMessage> response = new AMessage; 863 response->setInt32("err", -EAGAIN); 864 response->postReply(replyID); 865 break; 866 } 867 868 mFlags |= kFlagDequeueOutputPending; 869 mDequeueOutputReplyID = replyID; 870 871 if (timeoutUs > 0ll) { 872 sp<AMessage> timeoutMsg = 873 new AMessage(kWhatDequeueOutputTimedOut, id()); 874 timeoutMsg->setInt32( 875 "generation", ++mDequeueOutputTimeoutGeneration); 876 timeoutMsg->post(timeoutUs); 877 } 878 break; 879 } 880 881 case kWhatDequeueOutputTimedOut: 882 { 883 int32_t generation; 884 CHECK(msg->findInt32("generation", &generation)); 885 886 if (generation != mDequeueOutputTimeoutGeneration) { 887 // Obsolete 888 break; 889 } 890 891 CHECK(mFlags & kFlagDequeueOutputPending); 892 893 sp<AMessage> response = new AMessage; 894 response->setInt32("err", -EAGAIN); 895 response->postReply(mDequeueOutputReplyID); 896 897 mFlags &= ~kFlagDequeueOutputPending; 898 mDequeueOutputReplyID = 0; 899 break; 900 } 901 902 case kWhatReleaseOutputBuffer: 903 { 904 uint32_t replyID; 905 CHECK(msg->senderAwaitsResponse(&replyID)); 906 907 if (mState != STARTED || (mFlags & kFlagStickyError)) { 908 sp<AMessage> response = new AMessage; 909 response->setInt32("err", INVALID_OPERATION); 910 911 response->postReply(replyID); 912 break; 913 } 914 915 status_t err = onReleaseOutputBuffer(msg); 916 917 sp<AMessage> response = new AMessage; 918 response->setInt32("err", err); 919 response->postReply(replyID); 920 break; 921 } 922 923 case kWhatGetBuffers: 924 { 925 uint32_t replyID; 926 CHECK(msg->senderAwaitsResponse(&replyID)); 927 928 if (mState != STARTED || (mFlags & kFlagStickyError)) { 929 sp<AMessage> response = new AMessage; 930 response->setInt32("err", INVALID_OPERATION); 931 932 response->postReply(replyID); 933 break; 934 } 935 936 int32_t portIndex; 937 CHECK(msg->findInt32("portIndex", &portIndex)); 938 939 Vector<sp<ABuffer> > *dstBuffers; 940 CHECK(msg->findPointer("buffers", (void **)&dstBuffers)); 941 942 dstBuffers->clear(); 943 const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex]; 944 945 for (size_t i = 0; i < srcBuffers.size(); ++i) { 946 const BufferInfo &info = srcBuffers.itemAt(i); 947 948 dstBuffers->push_back(info.mData); 949 } 950 951 (new AMessage)->postReply(replyID); 952 break; 953 } 954 955 case kWhatFlush: 956 { 957 uint32_t replyID; 958 CHECK(msg->senderAwaitsResponse(&replyID)); 959 960 if (mState != STARTED || (mFlags & kFlagStickyError)) { 961 sp<AMessage> response = new AMessage; 962 response->setInt32("err", INVALID_OPERATION); 963 964 response->postReply(replyID); 965 break; 966 } 967 968 mReplyID = replyID; 969 setState(FLUSHING); 970 971 mCodec->signalFlush(); 972 returnBuffersToCodec(); 973 break; 974 } 975 976 case kWhatGetOutputFormat: 977 { 978 uint32_t replyID; 979 CHECK(msg->senderAwaitsResponse(&replyID)); 980 981 if ((mState != STARTED && mState != FLUSHING) 982 || (mFlags & kFlagStickyError)) { 983 sp<AMessage> response = new AMessage; 984 response->setInt32("err", INVALID_OPERATION); 985 986 response->postReply(replyID); 987 break; 988 } 989 990 sp<AMessage> response = new AMessage; 991 response->setMessage("format", mOutputFormat); 992 response->postReply(replyID); 993 break; 994 } 995 996 default: 997 TRESPASS(); 998 } 999} 1000 1001void MediaCodec::setState(State newState) { 1002 if (newState == UNINITIALIZED) { 1003 delete mSoftRenderer; 1004 mSoftRenderer = NULL; 1005 1006 mNativeWindow.clear(); 1007 1008 mOutputFormat.clear(); 1009 mFlags &= ~kFlagOutputFormatChanged; 1010 mFlags &= ~kFlagOutputBuffersChanged; 1011 mFlags &= ~kFlagStickyError; 1012 } 1013 1014 mState = newState; 1015 1016 cancelPendingDequeueOperations(); 1017} 1018 1019void MediaCodec::returnBuffersToCodec() { 1020 returnBuffersToCodecOnPort(kPortIndexInput); 1021 returnBuffersToCodecOnPort(kPortIndexOutput); 1022} 1023 1024void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) { 1025 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1026 1027 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 1028 1029 for (size_t i = 0; i < buffers->size(); ++i) { 1030 BufferInfo *info = &buffers->editItemAt(i); 1031 1032 if (info->mNotify != NULL) { 1033 sp<AMessage> msg = info->mNotify; 1034 info->mNotify = NULL; 1035 info->mOwnedByClient = false; 1036 1037 if (portIndex == kPortIndexInput) { 1038 msg->setInt32("err", ERROR_END_OF_STREAM); 1039 } 1040 msg->post(); 1041 } 1042 } 1043 1044 mAvailPortBuffers[portIndex].clear(); 1045} 1046 1047size_t MediaCodec::updateBuffers( 1048 int32_t portIndex, const sp<AMessage> &msg) { 1049 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1050 1051 void *bufferID; 1052 CHECK(msg->findPointer("buffer-id", &bufferID)); 1053 1054 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex]; 1055 1056 for (size_t i = 0; i < buffers->size(); ++i) { 1057 BufferInfo *info = &buffers->editItemAt(i); 1058 1059 if (info->mBufferID == bufferID) { 1060 CHECK(info->mNotify == NULL); 1061 CHECK(msg->findMessage("reply", &info->mNotify)); 1062 1063 mAvailPortBuffers[portIndex].push_back(i); 1064 1065 return i; 1066 } 1067 } 1068 1069 TRESPASS(); 1070 1071 return 0; 1072} 1073 1074status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) { 1075 size_t index; 1076 size_t offset; 1077 size_t size; 1078 int64_t timeUs; 1079 uint32_t flags; 1080 CHECK(msg->findSize("index", &index)); 1081 CHECK(msg->findSize("offset", &offset)); 1082 CHECK(msg->findSize("size", &size)); 1083 CHECK(msg->findInt64("timeUs", &timeUs)); 1084 CHECK(msg->findInt32("flags", (int32_t *)&flags)); 1085 1086 if (index >= mPortBuffers[kPortIndexInput].size()) { 1087 return -ERANGE; 1088 } 1089 1090 BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index); 1091 1092 if (info->mNotify == NULL || !info->mOwnedByClient) { 1093 return -EACCES; 1094 } 1095 1096 if (offset + size > info->mData->capacity()) { 1097 return -EINVAL; 1098 } 1099 1100 sp<AMessage> reply = info->mNotify; 1101 info->mNotify = NULL; 1102 info->mOwnedByClient = false; 1103 1104 info->mData->setRange(offset, size); 1105 info->mData->meta()->setInt64("timeUs", timeUs); 1106 1107 if (flags & BUFFER_FLAG_EOS) { 1108 info->mData->meta()->setInt32("eos", true); 1109 } 1110 1111 if (flags & BUFFER_FLAG_CODECCONFIG) { 1112 info->mData->meta()->setInt32("csd", true); 1113 } 1114 1115 reply->setBuffer("buffer", info->mData); 1116 reply->post(); 1117 1118 return OK; 1119} 1120 1121status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) { 1122 size_t index; 1123 CHECK(msg->findSize("index", &index)); 1124 1125 int32_t render; 1126 if (!msg->findInt32("render", &render)) { 1127 render = 0; 1128 } 1129 1130 if (mState != STARTED) { 1131 return -EINVAL; 1132 } 1133 1134 if (index >= mPortBuffers[kPortIndexOutput].size()) { 1135 return -ERANGE; 1136 } 1137 1138 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index); 1139 1140 if (info->mNotify == NULL || !info->mOwnedByClient) { 1141 return -EACCES; 1142 } 1143 1144 if (render) { 1145 info->mNotify->setInt32("render", true); 1146 1147 if (mSoftRenderer != NULL) { 1148 mSoftRenderer->render( 1149 info->mData->data(), info->mData->size(), NULL); 1150 } 1151 } 1152 1153 info->mNotify->post(); 1154 info->mNotify = NULL; 1155 info->mOwnedByClient = false; 1156 1157 return OK; 1158} 1159 1160ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) { 1161 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 1162 1163 List<size_t> *availBuffers = &mAvailPortBuffers[portIndex]; 1164 1165 if (availBuffers->empty()) { 1166 return -EAGAIN; 1167 } 1168 1169 size_t index = *availBuffers->begin(); 1170 availBuffers->erase(availBuffers->begin()); 1171 1172 BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index); 1173 CHECK(!info->mOwnedByClient); 1174 info->mOwnedByClient = true; 1175 1176 return index; 1177} 1178 1179} // namespace android 1180