1 /* 2 * Copyright (C) 2014 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 "MediaFilter" 19 20 #include <inttypes.h> 21 #include <utils/Trace.h> 22 23 #include <binder/MemoryDealer.h> 24 25 #include <media/stagefright/BufferProducerWrapper.h> 26 #include <media/stagefright/foundation/ABuffer.h> 27 #include <media/stagefright/foundation/ADebug.h> 28 #include <media/stagefright/foundation/AMessage.h> 29 30 #include <media/stagefright/MediaDefs.h> 31 #include <media/stagefright/MediaErrors.h> 32 #include <media/stagefright/MediaFilter.h> 33 34 #include <media/MediaCodecBuffer.h> 35 36 #include <gui/BufferItem.h> 37 38 #include "ColorConvert.h" 39 #include "GraphicBufferListener.h" 40 #include "IntrinsicBlurFilter.h" 41 #include "RSFilter.h" 42 #include "SaturationFilter.h" 43 #include "ZeroFilter.h" 44 45 #include "../include/ACodecBufferChannel.h" 46 #include "../include/SharedMemoryBuffer.h" 47 48 namespace android { 49 50 // parameter: number of input and output buffers 51 static const size_t kBufferCountActual = 4; 52 53 MediaFilter::MediaFilter() 54 : mState(UNINITIALIZED), 55 mGeneration(0), 56 mGraphicBufferListener(NULL) { 57 mBufferChannel = std::make_shared<ACodecBufferChannel>( 58 new AMessage(kWhatInputBufferFilled, this), 59 new AMessage(kWhatOutputBufferDrained, this)); 60 } 61 62 MediaFilter::~MediaFilter() { 63 } 64 65 //////////////////// PUBLIC FUNCTIONS ////////////////////////////////////////// 66 67 std::shared_ptr<BufferChannelBase> MediaFilter::getBufferChannel() { 68 return mBufferChannel; 69 } 70 71 void MediaFilter::initiateAllocateComponent(const sp<AMessage> &msg) { 72 msg->setWhat(kWhatAllocateComponent); 73 msg->setTarget(this); 74 msg->post(); 75 } 76 77 void MediaFilter::initiateConfigureComponent(const sp<AMessage> &msg) { 78 msg->setWhat(kWhatConfigureComponent); 79 msg->setTarget(this); 80 msg->post(); 81 } 82 83 void MediaFilter::initiateCreateInputSurface() { 84 (new AMessage(kWhatCreateInputSurface, this))->post(); 85 } 86 87 void MediaFilter::initiateSetInputSurface( 88 const sp<PersistentSurface> & /* surface */) { 89 ALOGW("initiateSetInputSurface() unsupported"); 90 } 91 92 void MediaFilter::initiateStart() { 93 (new AMessage(kWhatStart, this))->post(); 94 } 95 96 void MediaFilter::initiateShutdown(bool keepComponentAllocated) { 97 sp<AMessage> msg = new AMessage(kWhatShutdown, this); 98 msg->setInt32("keepComponentAllocated", keepComponentAllocated); 99 msg->post(); 100 } 101 102 void MediaFilter::signalFlush() { 103 (new AMessage(kWhatFlush, this))->post(); 104 } 105 106 void MediaFilter::signalResume() { 107 (new AMessage(kWhatResume, this))->post(); 108 } 109 110 // nothing to do 111 void MediaFilter::signalRequestIDRFrame() { 112 return; 113 } 114 115 void MediaFilter::signalSetParameters(const sp<AMessage> ¶ms) { 116 sp<AMessage> msg = new AMessage(kWhatSetParameters, this); 117 msg->setMessage("params", params); 118 msg->post(); 119 } 120 121 void MediaFilter::signalEndOfInputStream() { 122 (new AMessage(kWhatSignalEndOfInputStream, this))->post(); 123 } 124 125 void MediaFilter::onMessageReceived(const sp<AMessage> &msg) { 126 switch (msg->what()) { 127 case kWhatAllocateComponent: 128 { 129 onAllocateComponent(msg); 130 break; 131 } 132 case kWhatConfigureComponent: 133 { 134 onConfigureComponent(msg); 135 break; 136 } 137 case kWhatStart: 138 { 139 onStart(); 140 break; 141 } 142 case kWhatProcessBuffers: 143 { 144 processBuffers(); 145 break; 146 } 147 case kWhatInputBufferFilled: 148 { 149 onInputBufferFilled(msg); 150 break; 151 } 152 case kWhatOutputBufferDrained: 153 { 154 onOutputBufferDrained(msg); 155 break; 156 } 157 case kWhatShutdown: 158 { 159 onShutdown(msg); 160 break; 161 } 162 case kWhatFlush: 163 { 164 onFlush(); 165 break; 166 } 167 case kWhatResume: 168 { 169 // nothing to do 170 break; 171 } 172 case kWhatSetParameters: 173 { 174 onSetParameters(msg); 175 break; 176 } 177 case kWhatCreateInputSurface: 178 { 179 onCreateInputSurface(); 180 break; 181 } 182 case GraphicBufferListener::kWhatFrameAvailable: 183 { 184 onInputFrameAvailable(); 185 break; 186 } 187 case kWhatSignalEndOfInputStream: 188 { 189 onSignalEndOfInputStream(); 190 break; 191 } 192 default: 193 { 194 ALOGE("Message not handled:\n%s", msg->debugString().c_str()); 195 break; 196 } 197 } 198 } 199 200 //////////////////// HELPER FUNCTIONS ////////////////////////////////////////// 201 202 void MediaFilter::signalProcessBuffers() { 203 (new AMessage(kWhatProcessBuffers, this))->post(); 204 } 205 206 void MediaFilter::signalError(status_t error) { 207 mCallback->onError(error, ACTION_CODE_FATAL); 208 } 209 210 status_t MediaFilter::allocateBuffersOnPort(OMX_U32 portIndex) { 211 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput); 212 const bool isInput = portIndex == kPortIndexInput; 213 const size_t bufferSize = isInput ? mMaxInputSize : mMaxOutputSize; 214 215 CHECK(mDealer[portIndex] == NULL); 216 CHECK(mBuffers[portIndex].isEmpty()); 217 218 ALOGV("Allocating %zu buffers of size %zu on %s port", 219 kBufferCountActual, bufferSize, 220 isInput ? "input" : "output"); 221 222 size_t totalSize = kBufferCountActual * bufferSize; 223 224 mDealer[portIndex] = new MemoryDealer(totalSize, "MediaFilter"); 225 226 for (size_t i = 0; i < kBufferCountActual; ++i) { 227 sp<IMemory> mem = mDealer[portIndex]->allocate(bufferSize); 228 CHECK(mem.get() != NULL); 229 230 BufferInfo info; 231 info.mStatus = BufferInfo::OWNED_BY_US; 232 info.mBufferID = i; 233 info.mGeneration = mGeneration; 234 info.mOutputFlags = 0; 235 info.mData = new SharedMemoryBuffer( 236 isInput ? mInputFormat : mOutputFormat, mem); 237 info.mData->meta()->setInt64("timeUs", 0); 238 239 mBuffers[portIndex].push_back(info); 240 241 if (!isInput) { 242 mAvailableOutputBuffers.push( 243 &mBuffers[portIndex].editItemAt(i)); 244 } 245 } 246 247 std::vector<ACodecBufferChannel::BufferAndId> array(mBuffers[portIndex].size()); 248 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 249 array[i] = {mBuffers[portIndex][i].mData, mBuffers[portIndex][i].mBufferID}; 250 } 251 if (portIndex == kPortIndexInput) { 252 mBufferChannel->setInputBufferArray(array); 253 } else { 254 mBufferChannel->setOutputBufferArray(array); 255 } 256 257 return OK; 258 } 259 260 MediaFilter::BufferInfo* MediaFilter::findBufferByID( 261 uint32_t portIndex, IOMX::buffer_id bufferID, 262 ssize_t *index) { 263 for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) { 264 BufferInfo *info = &mBuffers[portIndex].editItemAt(i); 265 266 if (info->mBufferID == bufferID) { 267 if (index != NULL) { 268 *index = i; 269 } 270 return info; 271 } 272 } 273 274 TRESPASS(); 275 276 return NULL; 277 } 278 279 void MediaFilter::postFillThisBuffer(BufferInfo *info) { 280 ALOGV("postFillThisBuffer on buffer %d", info->mBufferID); 281 if (mPortEOS[kPortIndexInput]) { 282 return; 283 } 284 285 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 286 287 info->mGeneration = mGeneration; 288 289 info->mData->meta()->clear(); 290 291 sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, this); 292 reply->setInt32("buffer-id", info->mBufferID); 293 294 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 295 296 mBufferChannel->fillThisBuffer(info->mBufferID); 297 } 298 299 void MediaFilter::postDrainThisBuffer(BufferInfo *info) { 300 CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US); 301 302 info->mGeneration = mGeneration; 303 304 sp<AMessage> reply = new AMessage(kWhatOutputBufferDrained, this); 305 reply->setInt32("buffer-id", info->mBufferID); 306 307 mBufferChannel->drainThisBuffer(info->mBufferID, info->mOutputFlags); 308 309 info->mStatus = BufferInfo::OWNED_BY_UPSTREAM; 310 } 311 312 void MediaFilter::postEOS() { 313 mCallback->onEos(ERROR_END_OF_STREAM); 314 315 ALOGV("Sent kWhatEOS."); 316 } 317 318 void MediaFilter::requestFillEmptyInput() { 319 if (mPortEOS[kPortIndexInput]) { 320 return; 321 } 322 323 for (size_t i = 0; i < mBuffers[kPortIndexInput].size(); ++i) { 324 BufferInfo *info = &mBuffers[kPortIndexInput].editItemAt(i); 325 326 if (info->mStatus == BufferInfo::OWNED_BY_US) { 327 postFillThisBuffer(info); 328 } 329 } 330 } 331 332 void MediaFilter::processBuffers() { 333 if (mAvailableInputBuffers.empty() || mAvailableOutputBuffers.empty()) { 334 ALOGV("Skipping process (buffers unavailable)"); 335 return; 336 } 337 338 if (mPortEOS[kPortIndexOutput]) { 339 // TODO notify caller of queueInput error when it is supported 340 // in MediaCodec 341 ALOGW("Tried to process a buffer after EOS."); 342 return; 343 } 344 345 BufferInfo *inputInfo = mAvailableInputBuffers[0]; 346 mAvailableInputBuffers.removeAt(0); 347 BufferInfo *outputInfo = mAvailableOutputBuffers[0]; 348 mAvailableOutputBuffers.removeAt(0); 349 350 status_t err; 351 err = mFilter->processBuffers(inputInfo->mData, outputInfo->mData); 352 if (err != (status_t)OK) { 353 outputInfo->mData->meta()->setInt32("err", err); 354 } 355 356 int64_t timeUs; 357 CHECK(inputInfo->mData->meta()->findInt64("timeUs", &timeUs)); 358 outputInfo->mData->meta()->setInt64("timeUs", timeUs); 359 outputInfo->mOutputFlags = 0; 360 int32_t eos = 0; 361 if (inputInfo->mData->meta()->findInt32("eos", &eos) && eos != 0) { 362 outputInfo->mOutputFlags |= OMX_BUFFERFLAG_EOS; 363 mPortEOS[kPortIndexOutput] = true; 364 outputInfo->mData->meta()->setInt32("eos", eos); 365 postEOS(); 366 ALOGV("Output stream saw EOS."); 367 } 368 369 ALOGV("Processed input buffer %u [%zu], output buffer %u [%zu]", 370 inputInfo->mBufferID, inputInfo->mData->size(), 371 outputInfo->mBufferID, outputInfo->mData->size()); 372 373 if (mGraphicBufferListener != NULL) { 374 delete inputInfo; 375 } else { 376 postFillThisBuffer(inputInfo); 377 } 378 postDrainThisBuffer(outputInfo); 379 380 // prevent any corner case where buffers could get stuck in queue 381 signalProcessBuffers(); 382 } 383 384 void MediaFilter::onAllocateComponent(const sp<AMessage> &msg) { 385 CHECK_EQ(mState, UNINITIALIZED); 386 387 CHECK(msg->findString("componentName", &mComponentName)); 388 const char* name = mComponentName.c_str(); 389 if (!strcasecmp(name, "android.filter.zerofilter")) { 390 mFilter = new ZeroFilter; 391 } else if (!strcasecmp(name, "android.filter.saturation")) { 392 mFilter = new SaturationFilter; 393 } else if (!strcasecmp(name, "android.filter.intrinsicblur")) { 394 mFilter = new IntrinsicBlurFilter; 395 } else if (!strcasecmp(name, "android.filter.RenderScript")) { 396 mFilter = new RSFilter; 397 } else { 398 ALOGE("Unrecognized filter name: %s", name); 399 signalError(NAME_NOT_FOUND); 400 return; 401 } 402 403 // HACK - need "OMX.google" to use MediaCodec's software renderer 404 mCallback->onComponentAllocated("OMX.google.MediaFilter"); 405 mState = INITIALIZED; 406 ALOGV("Handled kWhatAllocateComponent."); 407 } 408 409 void MediaFilter::onConfigureComponent(const sp<AMessage> &msg) { 410 // TODO: generalize to allow audio filters as well as video 411 412 CHECK_EQ(mState, INITIALIZED); 413 414 // get params - at least mime, width & height 415 AString mime; 416 CHECK(msg->findString("mime", &mime)); 417 if (strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_RAW)) { 418 ALOGE("Bad mime: %s", mime.c_str()); 419 signalError(BAD_VALUE); 420 return; 421 } 422 423 CHECK(msg->findInt32("width", &mWidth)); 424 CHECK(msg->findInt32("height", &mHeight)); 425 if (!msg->findInt32("stride", &mStride)) { 426 mStride = mWidth; 427 } 428 if (!msg->findInt32("slice-height", &mSliceHeight)) { 429 mSliceHeight = mHeight; 430 } 431 432 mMaxInputSize = mWidth * mHeight * 4; // room for ARGB8888 433 int32_t maxInputSize; 434 if (msg->findInt32("max-input-size", &maxInputSize) 435 && (size_t)maxInputSize > mMaxInputSize) { 436 mMaxInputSize = maxInputSize; 437 } 438 439 if (!msg->findInt32("color-format", &mColorFormatIn)) { 440 // default to OMX_COLOR_Format32bitARGB8888 441 mColorFormatIn = OMX_COLOR_Format32bitARGB8888; 442 msg->setInt32("color-format", mColorFormatIn); 443 } 444 mColorFormatOut = mColorFormatIn; 445 446 mMaxOutputSize = mWidth * mHeight * 4; // room for ARGB8888 447 448 AString cacheDir; 449 if (!msg->findString("cacheDir", &cacheDir)) { 450 ALOGE("Failed to find cache directory in config message."); 451 signalError(NAME_NOT_FOUND); 452 return; 453 } 454 455 status_t err; 456 err = mFilter->configure(msg); 457 if (err != (status_t)OK) { 458 ALOGE("Failed to configure filter component, err %d", err); 459 signalError(err); 460 return; 461 } 462 463 mInputFormat = new AMessage(); 464 mInputFormat->setString("mime", mime.c_str()); 465 mInputFormat->setInt32("stride", mStride); 466 mInputFormat->setInt32("slice-height", mSliceHeight); 467 mInputFormat->setInt32("color-format", mColorFormatIn); 468 mInputFormat->setRect("crop", 0, 0, mStride, mSliceHeight); 469 mInputFormat->setInt32("width", mWidth); 470 mInputFormat->setInt32("height", mHeight); 471 472 mOutputFormat = new AMessage(); 473 mOutputFormat->setString("mime", mime.c_str()); 474 mOutputFormat->setInt32("stride", mStride); 475 mOutputFormat->setInt32("slice-height", mSliceHeight); 476 mOutputFormat->setInt32("color-format", mColorFormatOut); 477 mOutputFormat->setRect("crop", 0, 0, mStride, mSliceHeight); 478 mOutputFormat->setInt32("width", mWidth); 479 mOutputFormat->setInt32("height", mHeight); 480 481 mCallback->onComponentConfigured(mInputFormat, mOutputFormat); 482 mState = CONFIGURED; 483 ALOGV("Handled kWhatConfigureComponent."); 484 } 485 486 void MediaFilter::onStart() { 487 CHECK_EQ(mState, CONFIGURED); 488 489 allocateBuffersOnPort(kPortIndexInput); 490 491 allocateBuffersOnPort(kPortIndexOutput); 492 493 mCallback->onStartCompleted(); 494 495 status_t err = mFilter->start(); 496 if (err != (status_t)OK) { 497 ALOGE("Failed to start filter component, err %d", err); 498 signalError(err); 499 return; 500 } 501 502 mPortEOS[kPortIndexInput] = false; 503 mPortEOS[kPortIndexOutput] = false; 504 mInputEOSResult = OK; 505 mState = STARTED; 506 507 requestFillEmptyInput(); 508 ALOGV("Handled kWhatStart."); 509 } 510 511 void MediaFilter::onInputBufferFilled(const sp<AMessage> &msg) { 512 IOMX::buffer_id bufferID; 513 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 514 BufferInfo *info = findBufferByID(kPortIndexInput, bufferID); 515 516 if (mState != STARTED) { 517 // we're not running, so we'll just keep that buffer... 518 info->mStatus = BufferInfo::OWNED_BY_US; 519 return; 520 } 521 522 if (info->mGeneration != mGeneration) { 523 ALOGV("Caught a stale input buffer [ID %d]", bufferID); 524 // buffer is stale (taken before a flush/shutdown) - repost it 525 CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US); 526 postFillThisBuffer(info); 527 return; 528 } 529 530 CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM); 531 info->mStatus = BufferInfo::OWNED_BY_US; 532 533 sp<MediaCodecBuffer> buffer; 534 int32_t err = OK; 535 bool eos = false; 536 537 sp<RefBase> obj; 538 if (!msg->findObject("buffer", &obj)) { 539 // these are unfilled buffers returned by client 540 CHECK(msg->findInt32("err", &err)); 541 542 if (err == OK) { 543 // buffers with no errors are returned on MediaCodec.flush 544 ALOGV("saw unfilled buffer (MediaCodec.flush)"); 545 postFillThisBuffer(info); 546 return; 547 } else { 548 ALOGV("saw error %d instead of an input buffer", err); 549 eos = true; 550 } 551 552 buffer.clear(); 553 } else { 554 buffer = static_cast<MediaCodecBuffer *>(obj.get()); 555 } 556 557 int32_t isCSD; 558 if (buffer != NULL && buffer->meta()->findInt32("csd", &isCSD) 559 && isCSD != 0) { 560 // ignore codec-specific data buffers 561 ALOGW("MediaFilter received a codec-specific data buffer"); 562 postFillThisBuffer(info); 563 return; 564 } 565 566 int32_t tmp; 567 if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) { 568 eos = true; 569 err = ERROR_END_OF_STREAM; 570 } 571 572 mAvailableInputBuffers.push_back(info); 573 processBuffers(); 574 575 if (eos) { 576 mPortEOS[kPortIndexInput] = true; 577 mInputEOSResult = err; 578 } 579 580 ALOGV("Handled kWhatInputBufferFilled. [ID %u]", bufferID); 581 } 582 583 void MediaFilter::onOutputBufferDrained(const sp<AMessage> &msg) { 584 IOMX::buffer_id bufferID; 585 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID)); 586 BufferInfo *info = findBufferByID(kPortIndexOutput, bufferID); 587 588 if (mState != STARTED) { 589 // we're not running, so we'll just keep that buffer... 590 info->mStatus = BufferInfo::OWNED_BY_US; 591 return; 592 } 593 594 if (info->mGeneration != mGeneration) { 595 ALOGV("Caught a stale output buffer [ID %d]", bufferID); 596 // buffer is stale (taken before a flush/shutdown) - keep it 597 CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US); 598 return; 599 } 600 601 CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM); 602 info->mStatus = BufferInfo::OWNED_BY_US; 603 604 mAvailableOutputBuffers.push_back(info); 605 606 processBuffers(); 607 608 ALOGV("Handled kWhatOutputBufferDrained. [ID %u]", 609 bufferID); 610 } 611 612 void MediaFilter::onShutdown(const sp<AMessage> &msg) { 613 mGeneration++; 614 615 if (mState != UNINITIALIZED) { 616 mFilter->reset(); 617 } 618 619 int32_t keepComponentAllocated; 620 CHECK(msg->findInt32("keepComponentAllocated", &keepComponentAllocated)); 621 if (!keepComponentAllocated || mState == UNINITIALIZED) { 622 mState = UNINITIALIZED; 623 } else { 624 mState = INITIALIZED; 625 } 626 627 if (keepComponentAllocated) { 628 mCallback->onStopCompleted(); 629 } else { 630 mCallback->onReleaseCompleted(); 631 } 632 } 633 634 void MediaFilter::onFlush() { 635 mGeneration++; 636 637 mAvailableInputBuffers.clear(); 638 for (size_t i = 0; i < mBuffers[kPortIndexInput].size(); ++i) { 639 BufferInfo *info = &mBuffers[kPortIndexInput].editItemAt(i); 640 info->mStatus = BufferInfo::OWNED_BY_US; 641 } 642 mAvailableOutputBuffers.clear(); 643 for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) { 644 BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i); 645 info->mStatus = BufferInfo::OWNED_BY_US; 646 mAvailableOutputBuffers.push_back(info); 647 } 648 649 mPortEOS[kPortIndexInput] = false; 650 mPortEOS[kPortIndexOutput] = false; 651 mInputEOSResult = OK; 652 653 mCallback->onFlushCompleted(); 654 ALOGV("Posted kWhatFlushCompleted"); 655 656 // MediaCodec returns all input buffers after flush, so in 657 // onInputBufferFilled we call postFillThisBuffer on them 658 } 659 660 void MediaFilter::onSetParameters(const sp<AMessage> &msg) { 661 CHECK(mState != STARTED); 662 663 status_t err = mFilter->setParameters(msg); 664 if (err != (status_t)OK) { 665 ALOGE("setParameters returned err %d", err); 666 } 667 } 668 669 void MediaFilter::onCreateInputSurface() { 670 CHECK(mState == CONFIGURED); 671 672 mGraphicBufferListener = new GraphicBufferListener; 673 674 sp<AMessage> notify = new AMessage(); 675 notify->setTarget(this); 676 status_t err = mGraphicBufferListener->init( 677 notify, mStride, mSliceHeight, kBufferCountActual); 678 679 if (err != OK) { 680 ALOGE("Failed to init mGraphicBufferListener: %d", err); 681 signalError(err); 682 return; 683 } 684 685 mCallback->onInputSurfaceCreated( 686 nullptr, nullptr, 687 new BufferProducerWrapper( 688 mGraphicBufferListener->getIGraphicBufferProducer())); 689 } 690 691 void MediaFilter::onInputFrameAvailable() { 692 BufferItem item = mGraphicBufferListener->getBufferItem(); 693 sp<GraphicBuffer> buf = mGraphicBufferListener->getBuffer(item); 694 695 // get pointer to graphic buffer 696 void* bufPtr; 697 buf->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &bufPtr); 698 699 // HACK - there is no OMX_COLOR_FORMATTYPE value for RGBA, so the format 700 // conversion is hardcoded until we add this. 701 // TODO: check input format and convert only if necessary 702 // copy RGBA graphic buffer into temporary ARGB input buffer 703 BufferInfo *inputInfo = new BufferInfo; 704 inputInfo->mData = new MediaCodecBuffer( 705 mInputFormat, new ABuffer(buf->getWidth() * buf->getHeight() * 4)); 706 ALOGV("Copying surface data into temp buffer."); 707 convertRGBAToARGB( 708 (uint8_t*)bufPtr, buf->getWidth(), buf->getHeight(), 709 buf->getStride(), inputInfo->mData->data()); 710 inputInfo->mBufferID = item.mSlot; 711 inputInfo->mGeneration = mGeneration; 712 inputInfo->mOutputFlags = 0; 713 inputInfo->mStatus = BufferInfo::OWNED_BY_US; 714 inputInfo->mData->meta()->setInt64("timeUs", item.mTimestamp / 1000); 715 716 mAvailableInputBuffers.push_back(inputInfo); 717 718 mGraphicBufferListener->releaseBuffer(item); 719 720 signalProcessBuffers(); 721 } 722 723 void MediaFilter::onSignalEndOfInputStream() { 724 // if using input surface, need to send an EOS output buffer 725 if (mGraphicBufferListener != NULL) { 726 Vector<BufferInfo> *outputBufs = &mBuffers[kPortIndexOutput]; 727 BufferInfo* eosBuf; 728 bool foundBuf = false; 729 for (size_t i = 0; i < kBufferCountActual; i++) { 730 eosBuf = &outputBufs->editItemAt(i); 731 if (eosBuf->mStatus == BufferInfo::OWNED_BY_US) { 732 foundBuf = true; 733 break; 734 } 735 } 736 737 if (!foundBuf) { 738 ALOGE("onSignalEndOfInputStream failed to find an output buffer"); 739 return; 740 } 741 742 eosBuf->mOutputFlags = OMX_BUFFERFLAG_EOS; 743 eosBuf->mGeneration = mGeneration; 744 eosBuf->mData->setRange(0, 0); 745 postDrainThisBuffer(eosBuf); 746 ALOGV("Posted EOS on output buffer %u", eosBuf->mBufferID); 747 } 748 749 mPortEOS[kPortIndexOutput] = true; 750 mCallback->onSignaledInputEOS(OK); 751 752 ALOGV("Output stream saw EOS."); 753 } 754 755 } // namespace android 756