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