SoftVideoEncoderOMXComponent.cpp revision a21bed3d626d148e584bdddeeecf287b782b3fcb
1/* 2 * Copyright 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#include <inttypes.h> 18 19//#define LOG_NDEBUG 0 20#define LOG_TAG "SoftVideoEncoderOMXComponent" 21#include <utils/Log.h> 22#include <utils/misc.h> 23 24#include "include/SoftVideoEncoderOMXComponent.h" 25 26#include <hardware/gralloc.h> 27#include <media/hardware/HardwareAPI.h> 28#include <media/stagefright/foundation/ADebug.h> 29#include <media/stagefright/foundation/ALooper.h> 30#include <media/stagefright/foundation/AMessage.h> 31#include <media/stagefright/foundation/AUtils.h> 32#include <media/stagefright/MediaDefs.h> 33 34#include <ui/GraphicBuffer.h> 35#include <ui/GraphicBufferMapper.h> 36 37#include <OMX_IndexExt.h> 38 39namespace android { 40 41const static OMX_COLOR_FORMATTYPE kSupportedColorFormats[] = { 42 OMX_COLOR_FormatYUV420Planar, 43 OMX_COLOR_FormatYUV420SemiPlanar, 44 OMX_COLOR_FormatAndroidOpaque 45}; 46 47template<class T> 48static void InitOMXParams(T *params) { 49 params->nSize = sizeof(T); 50 params->nVersion.s.nVersionMajor = 1; 51 params->nVersion.s.nVersionMinor = 0; 52 params->nVersion.s.nRevision = 0; 53 params->nVersion.s.nStep = 0; 54} 55 56SoftVideoEncoderOMXComponent::SoftVideoEncoderOMXComponent( 57 const char *name, 58 const char *componentRole, 59 OMX_VIDEO_CODINGTYPE codingType, 60 const CodecProfileLevel *profileLevels, 61 size_t numProfileLevels, 62 int32_t width, 63 int32_t height, 64 const OMX_CALLBACKTYPE *callbacks, 65 OMX_PTR appData, 66 OMX_COMPONENTTYPE **component) 67 : SimpleSoftOMXComponent(name, callbacks, appData, component), 68 mInputDataIsMeta(false), 69 mWidth(width), 70 mHeight(height), 71 mBitrate(192000), 72 mFramerate(30 << 16), // Q16 format 73 mColorFormat(OMX_COLOR_FormatYUV420Planar), 74 mGrallocModule(NULL), 75 mMinOutputBufferSize(384), // arbitrary, using one uncompressed macroblock 76 mMinCompressionRatio(1), // max output size is normally the input size 77 mComponentRole(componentRole), 78 mCodingType(codingType), 79 mProfileLevels(profileLevels), 80 mNumProfileLevels(numProfileLevels) { 81} 82 83void SoftVideoEncoderOMXComponent::initPorts( 84 OMX_U32 numInputBuffers, OMX_U32 numOutputBuffers, OMX_U32 outputBufferSize, 85 const char *mime, OMX_U32 minCompressionRatio) { 86 OMX_PARAM_PORTDEFINITIONTYPE def; 87 88 mMinOutputBufferSize = outputBufferSize; 89 mMinCompressionRatio = minCompressionRatio; 90 91 InitOMXParams(&def); 92 93 def.nPortIndex = kInputPortIndex; 94 def.eDir = OMX_DirInput; 95 def.nBufferCountMin = numInputBuffers; 96 def.nBufferCountActual = def.nBufferCountMin; 97 def.bEnabled = OMX_TRUE; 98 def.bPopulated = OMX_FALSE; 99 def.eDomain = OMX_PortDomainVideo; 100 def.bBuffersContiguous = OMX_FALSE; 101 def.format.video.pNativeRender = NULL; 102 def.format.video.nFrameWidth = mWidth; 103 def.format.video.nFrameHeight = mHeight; 104 def.format.video.nStride = def.format.video.nFrameWidth; 105 def.format.video.nSliceHeight = def.format.video.nFrameHeight; 106 def.format.video.nBitrate = 0; 107 // frameRate is in Q16 format. 108 def.format.video.xFramerate = mFramerate; 109 def.format.video.bFlagErrorConcealment = OMX_FALSE; 110 def.nBufferAlignment = kInputBufferAlignment; 111 def.format.video.cMIMEType = const_cast<char *>("video/raw"); 112 def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; 113 def.format.video.eColorFormat = mColorFormat; 114 def.format.video.pNativeWindow = NULL; 115 // buffersize set in updatePortParams 116 117 addPort(def); 118 119 InitOMXParams(&def); 120 121 def.nPortIndex = kOutputPortIndex; 122 def.eDir = OMX_DirOutput; 123 def.nBufferCountMin = numOutputBuffers; 124 def.nBufferCountActual = def.nBufferCountMin; 125 def.bEnabled = OMX_TRUE; 126 def.bPopulated = OMX_FALSE; 127 def.eDomain = OMX_PortDomainVideo; 128 def.bBuffersContiguous = OMX_FALSE; 129 def.format.video.pNativeRender = NULL; 130 def.format.video.nFrameWidth = mWidth; 131 def.format.video.nFrameHeight = mHeight; 132 def.format.video.nStride = 0; 133 def.format.video.nSliceHeight = 0; 134 def.format.video.nBitrate = mBitrate; 135 def.format.video.xFramerate = 0 << 16; 136 def.format.video.bFlagErrorConcealment = OMX_FALSE; 137 def.nBufferAlignment = kOutputBufferAlignment; 138 def.format.video.cMIMEType = const_cast<char *>(mime); 139 def.format.video.eCompressionFormat = mCodingType; 140 def.format.video.eColorFormat = OMX_COLOR_FormatUnused; 141 def.format.video.pNativeWindow = NULL; 142 // buffersize set in updatePortParams 143 144 addPort(def); 145 146 updatePortParams(); 147} 148 149void SoftVideoEncoderOMXComponent::updatePortParams() { 150 OMX_PARAM_PORTDEFINITIONTYPE *inDef = &editPortInfo(kInputPortIndex)->mDef; 151 inDef->format.video.nFrameWidth = mWidth; 152 inDef->format.video.nFrameHeight = mHeight; 153 inDef->format.video.nStride = inDef->format.video.nFrameWidth; 154 inDef->format.video.nSliceHeight = inDef->format.video.nFrameHeight; 155 inDef->format.video.xFramerate = mFramerate; 156 inDef->format.video.eColorFormat = mColorFormat; 157 uint32_t rawBufferSize = 158 inDef->format.video.nStride * inDef->format.video.nSliceHeight * 3 / 2; 159 if (inDef->format.video.eColorFormat == OMX_COLOR_FormatAndroidOpaque) { 160 inDef->nBufferSize = max(sizeof(VideoNativeMetadata), sizeof(VideoGrallocMetadata)); 161 } else { 162 inDef->nBufferSize = rawBufferSize; 163 } 164 165 OMX_PARAM_PORTDEFINITIONTYPE *outDef = &editPortInfo(kOutputPortIndex)->mDef; 166 outDef->format.video.nFrameWidth = mWidth; 167 outDef->format.video.nFrameHeight = mHeight; 168 outDef->format.video.nBitrate = mBitrate; 169 170 outDef->nBufferSize = max(mMinOutputBufferSize, rawBufferSize / mMinCompressionRatio); 171} 172 173OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalSetPortParams( 174 const OMX_PARAM_PORTDEFINITIONTYPE *port) { 175 176 if (!isValidOMXParam(port)) { 177 return OMX_ErrorBadParameter; 178 } 179 180 if (port->nPortIndex == kInputPortIndex) { 181 mWidth = port->format.video.nFrameWidth; 182 mHeight = port->format.video.nFrameHeight; 183 184 // xFramerate comes in Q16 format, in frames per second unit 185 mFramerate = port->format.video.xFramerate; 186 187 if (port->format.video.eCompressionFormat != OMX_VIDEO_CodingUnused 188 || (port->format.video.eColorFormat != OMX_COLOR_FormatYUV420Planar 189 && port->format.video.eColorFormat != OMX_COLOR_FormatYUV420SemiPlanar 190 && port->format.video.eColorFormat != OMX_COLOR_FormatAndroidOpaque)) { 191 return OMX_ErrorUnsupportedSetting; 192 } 193 194 mColorFormat = port->format.video.eColorFormat; 195 } else if (port->nPortIndex == kOutputPortIndex) { 196 if (port->format.video.eCompressionFormat != mCodingType 197 || port->format.video.eColorFormat != OMX_COLOR_FormatUnused) { 198 return OMX_ErrorUnsupportedSetting; 199 } 200 201 mBitrate = port->format.video.nBitrate; 202 } else { 203 return OMX_ErrorBadPortIndex; 204 } 205 206 updatePortParams(); 207 return OMX_ErrorNone; 208} 209 210OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalSetParameter( 211 OMX_INDEXTYPE index, const OMX_PTR param) { 212 // can include extension index OMX_INDEXEXTTYPE 213 const int32_t indexFull = index; 214 215 switch (indexFull) { 216 case OMX_IndexParamVideoErrorCorrection: 217 { 218 return OMX_ErrorNotImplemented; 219 } 220 221 case OMX_IndexParamStandardComponentRole: 222 { 223 const OMX_PARAM_COMPONENTROLETYPE *roleParams = 224 (const OMX_PARAM_COMPONENTROLETYPE *)param; 225 226 if (!isValidOMXParam(roleParams)) { 227 return OMX_ErrorBadParameter; 228 } 229 230 if (strncmp((const char *)roleParams->cRole, 231 mComponentRole, 232 OMX_MAX_STRINGNAME_SIZE - 1)) { 233 return OMX_ErrorUnsupportedSetting; 234 } 235 236 return OMX_ErrorNone; 237 } 238 239 case OMX_IndexParamPortDefinition: 240 { 241 OMX_ERRORTYPE err = internalSetPortParams((const OMX_PARAM_PORTDEFINITIONTYPE *)param); 242 243 if (err != OMX_ErrorNone) { 244 return err; 245 } 246 247 return SimpleSoftOMXComponent::internalSetParameter(index, param); 248 } 249 250 case OMX_IndexParamVideoPortFormat: 251 { 252 const OMX_VIDEO_PARAM_PORTFORMATTYPE* format = 253 (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)param; 254 255 if (!isValidOMXParam(format)) { 256 return OMX_ErrorBadParameter; 257 } 258 259 if (format->nPortIndex == kInputPortIndex) { 260 if (format->eColorFormat == OMX_COLOR_FormatYUV420Planar || 261 format->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar || 262 format->eColorFormat == OMX_COLOR_FormatAndroidOpaque) { 263 mColorFormat = format->eColorFormat; 264 265 updatePortParams(); 266 return OMX_ErrorNone; 267 } else { 268 ALOGE("Unsupported color format %i", format->eColorFormat); 269 return OMX_ErrorUnsupportedSetting; 270 } 271 } else if (format->nPortIndex == kOutputPortIndex) { 272 if (format->eCompressionFormat == mCodingType) { 273 return OMX_ErrorNone; 274 } else { 275 return OMX_ErrorUnsupportedSetting; 276 } 277 } else { 278 return OMX_ErrorBadPortIndex; 279 } 280 } 281 282 case kStoreMetaDataExtensionIndex: 283 { 284 // storeMetaDataInBuffers 285 const StoreMetaDataInBuffersParams *storeParam = 286 (const StoreMetaDataInBuffersParams *)param; 287 288 if (!isValidOMXParam(storeParam)) { 289 return OMX_ErrorBadParameter; 290 } 291 292 if (storeParam->nPortIndex == kOutputPortIndex) { 293 return storeParam->bStoreMetaData ? OMX_ErrorUnsupportedSetting : OMX_ErrorNone; 294 } else if (storeParam->nPortIndex != kInputPortIndex) { 295 return OMX_ErrorBadPortIndex; 296 } 297 298 mInputDataIsMeta = (storeParam->bStoreMetaData == OMX_TRUE); 299 if (mInputDataIsMeta) { 300 mColorFormat = OMX_COLOR_FormatAndroidOpaque; 301 } else if (mColorFormat == OMX_COLOR_FormatAndroidOpaque) { 302 mColorFormat = OMX_COLOR_FormatYUV420Planar; 303 } 304 updatePortParams(); 305 return OMX_ErrorNone; 306 } 307 308 default: 309 return SimpleSoftOMXComponent::internalSetParameter(index, param); 310 } 311} 312 313OMX_ERRORTYPE SoftVideoEncoderOMXComponent::internalGetParameter( 314 OMX_INDEXTYPE index, OMX_PTR param) { 315 switch ((int)index) { 316 case OMX_IndexParamVideoErrorCorrection: 317 { 318 return OMX_ErrorNotImplemented; 319 } 320 321 case OMX_IndexParamVideoPortFormat: 322 { 323 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams = 324 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)param; 325 326 if (!isValidOMXParam(formatParams)) { 327 return OMX_ErrorBadParameter; 328 } 329 330 if (formatParams->nPortIndex == kInputPortIndex) { 331 if (formatParams->nIndex >= NELEM(kSupportedColorFormats)) { 332 return OMX_ErrorNoMore; 333 } 334 335 // Color formats, in order of preference 336 formatParams->eColorFormat = kSupportedColorFormats[formatParams->nIndex]; 337 formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused; 338 formatParams->xFramerate = mFramerate; 339 return OMX_ErrorNone; 340 } else if (formatParams->nPortIndex == kOutputPortIndex) { 341 formatParams->eCompressionFormat = mCodingType; 342 formatParams->eColorFormat = OMX_COLOR_FormatUnused; 343 formatParams->xFramerate = 0; 344 return OMX_ErrorNone; 345 } else { 346 return OMX_ErrorBadPortIndex; 347 } 348 } 349 350 case OMX_IndexParamVideoProfileLevelQuerySupported: 351 { 352 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profileLevel = 353 (OMX_VIDEO_PARAM_PROFILELEVELTYPE *) param; 354 355 if (!isValidOMXParam(profileLevel)) { 356 return OMX_ErrorBadParameter; 357 } 358 359 if (profileLevel->nPortIndex != kOutputPortIndex) { 360 ALOGE("Invalid port index: %u", profileLevel->nPortIndex); 361 return OMX_ErrorUnsupportedIndex; 362 } 363 364 if (profileLevel->nProfileIndex >= mNumProfileLevels) { 365 return OMX_ErrorNoMore; 366 } 367 368 profileLevel->eProfile = mProfileLevels[profileLevel->nProfileIndex].mProfile; 369 profileLevel->eLevel = mProfileLevels[profileLevel->nProfileIndex].mLevel; 370 return OMX_ErrorNone; 371 } 372 373 case OMX_IndexParamConsumerUsageBits: 374 { 375 OMX_U32 *usageBits = (OMX_U32 *)param; 376 *usageBits = GRALLOC_USAGE_SW_READ_OFTEN; 377 return OMX_ErrorNone; 378 } 379 380 default: 381 return SimpleSoftOMXComponent::internalGetParameter(index, param); 382 } 383} 384 385// static 386void SoftVideoEncoderOMXComponent::ConvertFlexYUVToPlanar( 387 uint8_t *dst, size_t dstStride, size_t dstVStride, 388 struct android_ycbcr *ycbcr, int32_t width, int32_t height) { 389 const uint8_t *src = (const uint8_t *)ycbcr->y; 390 const uint8_t *srcU = (const uint8_t *)ycbcr->cb; 391 const uint8_t *srcV = (const uint8_t *)ycbcr->cr; 392 uint8_t *dstU = dst + dstVStride * dstStride; 393 uint8_t *dstV = dstU + (dstVStride >> 1) * (dstStride >> 1); 394 395 for (size_t y = height; y > 0; --y) { 396 memcpy(dst, src, width); 397 dst += dstStride; 398 src += ycbcr->ystride; 399 } 400 if (ycbcr->cstride == ycbcr->ystride >> 1 && ycbcr->chroma_step == 1) { 401 // planar 402 for (size_t y = height >> 1; y > 0; --y) { 403 memcpy(dstU, srcU, width >> 1); 404 dstU += dstStride >> 1; 405 srcU += ycbcr->cstride; 406 memcpy(dstV, srcV, width >> 1); 407 dstV += dstStride >> 1; 408 srcV += ycbcr->cstride; 409 } 410 } else { 411 // arbitrary 412 for (size_t y = height >> 1; y > 0; --y) { 413 for (size_t x = width >> 1; x > 0; --x) { 414 *dstU++ = *srcU; 415 *dstV++ = *srcV; 416 srcU += ycbcr->chroma_step; 417 srcV += ycbcr->chroma_step; 418 } 419 dstU += (dstStride >> 1) - (width >> 1); 420 dstV += (dstStride >> 1) - (width >> 1); 421 srcU += ycbcr->cstride - (width >> 1) * ycbcr->chroma_step; 422 srcV += ycbcr->cstride - (width >> 1) * ycbcr->chroma_step; 423 } 424 } 425} 426 427// static 428void SoftVideoEncoderOMXComponent::ConvertYUV420SemiPlanarToYUV420Planar( 429 const uint8_t *inYVU, uint8_t* outYUV, int32_t width, int32_t height) { 430 // TODO: add support for stride 431 int32_t outYsize = width * height; 432 uint32_t *outY = (uint32_t *) outYUV; 433 uint16_t *outCb = (uint16_t *) (outYUV + outYsize); 434 uint16_t *outCr = (uint16_t *) (outYUV + outYsize + (outYsize >> 2)); 435 436 /* Y copying */ 437 memcpy(outY, inYVU, outYsize); 438 439 /* U & V copying */ 440 // FIXME this only works if width is multiple of 4 441 uint32_t *inYVU_4 = (uint32_t *) (inYVU + outYsize); 442 for (int32_t i = height >> 1; i > 0; --i) { 443 for (int32_t j = width >> 2; j > 0; --j) { 444 uint32_t temp = *inYVU_4++; 445 uint32_t tempU = temp & 0xFF; 446 tempU = tempU | ((temp >> 8) & 0xFF00); 447 448 uint32_t tempV = (temp >> 8) & 0xFF; 449 tempV = tempV | ((temp >> 16) & 0xFF00); 450 451 *outCb++ = tempU; 452 *outCr++ = tempV; 453 } 454 } 455} 456 457// static 458void SoftVideoEncoderOMXComponent::ConvertRGB32ToPlanar( 459 uint8_t *dstY, size_t dstStride, size_t dstVStride, 460 const uint8_t *src, size_t width, size_t height, size_t srcStride, 461 bool bgr) { 462 CHECK((width & 1) == 0); 463 CHECK((height & 1) == 0); 464 465 uint8_t *dstU = dstY + dstStride * dstVStride; 466 uint8_t *dstV = dstU + (dstStride >> 1) * (dstVStride >> 1); 467 468#ifdef SURFACE_IS_BGR32 469 bgr = !bgr; 470#endif 471 472 const size_t redOffset = bgr ? 2 : 0; 473 const size_t greenOffset = 1; 474 const size_t blueOffset = bgr ? 0 : 2; 475 476 for (size_t y = 0; y < height; ++y) { 477 for (size_t x = 0; x < width; ++x) { 478 unsigned red = src[redOffset]; 479 unsigned green = src[greenOffset]; 480 unsigned blue = src[blueOffset]; 481 482 // using ITU-R BT.601 conversion matrix 483 unsigned luma = 484 ((red * 66 + green * 129 + blue * 25) >> 8) + 16; 485 486 dstY[x] = luma; 487 488 if ((x & 1) == 0 && (y & 1) == 0) { 489 unsigned U = 490 ((-red * 38 - green * 74 + blue * 112) >> 8) + 128; 491 492 unsigned V = 493 ((red * 112 - green * 94 - blue * 18) >> 8) + 128; 494 495 dstU[x >> 1] = U; 496 dstV[x >> 1] = V; 497 } 498 src += 4; 499 } 500 501 if ((y & 1) == 0) { 502 dstU += dstStride >> 1; 503 dstV += dstStride >> 1; 504 } 505 506 src += srcStride - 4 * width; 507 dstY += dstStride; 508 } 509} 510 511const uint8_t *SoftVideoEncoderOMXComponent::extractGraphicBuffer( 512 uint8_t *dst, size_t dstSize, 513 const uint8_t *src, size_t srcSize, 514 size_t width, size_t height) const { 515 size_t dstStride = width; 516 size_t dstVStride = height; 517 518 MetadataBufferType bufferType = *(MetadataBufferType *)src; 519 bool usingANWBuffer = bufferType == kMetadataBufferTypeANWBuffer; 520 if (!usingANWBuffer && bufferType != kMetadataBufferTypeGrallocSource) { 521 ALOGE("Unsupported metadata type (%d)", bufferType); 522 return NULL; 523 } 524 525 if (mGrallocModule == NULL) { 526 CHECK_EQ(0, hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mGrallocModule)); 527 } 528 529 const gralloc_module_t *grmodule = 530 (const gralloc_module_t *)mGrallocModule; 531 532 buffer_handle_t handle; 533 int format; 534 size_t srcStride; 535 size_t srcVStride; 536 if (usingANWBuffer) { 537 if (srcSize < sizeof(VideoNativeMetadata)) { 538 ALOGE("Metadata is too small (%zu vs %zu)", srcSize, sizeof(VideoNativeMetadata)); 539 return NULL; 540 } 541 542 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)src; 543 ANativeWindowBuffer *buffer = nativeMeta.pBuffer; 544 handle = buffer->handle; 545 format = buffer->format; 546 srcStride = buffer->stride; 547 srcVStride = buffer->height; 548 // convert stride from pixels to bytes 549 if (format != HAL_PIXEL_FORMAT_YV12 && 550 format != HAL_PIXEL_FORMAT_YCbCr_420_888) { 551 // TODO do we need to support other formats? 552 srcStride *= 4; 553 } 554 555 if (nativeMeta.nFenceFd >= 0) { 556 sp<Fence> fence = new Fence(nativeMeta.nFenceFd); 557 nativeMeta.nFenceFd = -1; 558 status_t err = fence->wait(IOMX::kFenceTimeoutMs); 559 if (err != OK) { 560 ALOGE("Timed out waiting on input fence"); 561 return NULL; 562 } 563 } 564 } else { 565 // TODO: remove this part. Check if anyone uses this. 566 567 if (srcSize < sizeof(VideoGrallocMetadata)) { 568 ALOGE("Metadata is too small (%zu vs %zu)", srcSize, sizeof(VideoGrallocMetadata)); 569 return NULL; 570 } 571 572 VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)(src); 573 handle = grallocMeta.pHandle; 574 // assume HAL_PIXEL_FORMAT_RGBA_8888 575 // there is no way to get the src stride without the graphic buffer 576 format = HAL_PIXEL_FORMAT_RGBA_8888; 577 srcStride = width * 4; 578 srcVStride = height; 579 } 580 581 size_t neededSize = 582 dstStride * dstVStride + (width >> 1) 583 + (dstStride >> 1) * ((dstVStride >> 1) + (height >> 1) - 1); 584 if (dstSize < neededSize) { 585 ALOGE("destination buffer is too small (%zu vs %zu)", dstSize, neededSize); 586 return NULL; 587 } 588 589 void *bits = NULL; 590 struct android_ycbcr ycbcr; 591 status_t res; 592 if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) { 593 res = grmodule->lock_ycbcr( 594 grmodule, handle, 595 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER, 596 0, 0, width, height, &ycbcr); 597 } else { 598 res = grmodule->lock( 599 grmodule, handle, 600 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER, 601 0, 0, width, height, &bits); 602 } 603 if (res != OK) { 604 ALOGE("Unable to lock image buffer %p for access", handle); 605 return NULL; 606 } 607 608 switch (format) { 609 case HAL_PIXEL_FORMAT_YV12: // YCrCb / YVU planar 610 // convert to flex YUV 611 ycbcr.y = bits; 612 ycbcr.cr = (uint8_t *)bits + srcStride * srcVStride; 613 ycbcr.cb = (uint8_t *)ycbcr.cr + (srcStride >> 1) * (srcVStride >> 1); 614 ycbcr.chroma_step = 1; 615 ycbcr.cstride = srcVStride >> 1; 616 ycbcr.ystride = srcVStride; 617 ConvertFlexYUVToPlanar(dst, dstStride, dstVStride, &ycbcr, width, height); 618 break; 619 case HAL_PIXEL_FORMAT_YCrCb_420_SP: // YCrCb / YVU semiplanar, NV21 620 // convert to flex YUV 621 ycbcr.y = bits; 622 ycbcr.cr = (uint8_t *)bits + srcStride * srcVStride; 623 ycbcr.cb = (uint8_t *)ycbcr.cr + 1; 624 ycbcr.chroma_step = 2; 625 ycbcr.cstride = srcVStride; 626 ycbcr.ystride = srcVStride; 627 ConvertFlexYUVToPlanar(dst, dstStride, dstVStride, &ycbcr, width, height); 628 break; 629 case HAL_PIXEL_FORMAT_YCbCr_420_888: 630 ConvertFlexYUVToPlanar(dst, dstStride, dstVStride, &ycbcr, width, height); 631 break; 632 case HAL_PIXEL_FORMAT_RGBA_8888: 633 case HAL_PIXEL_FORMAT_BGRA_8888: 634 ConvertRGB32ToPlanar( 635 dst, dstStride, dstVStride, 636 (const uint8_t *)bits, width, height, srcStride, 637 format == HAL_PIXEL_FORMAT_BGRA_8888); 638 break; 639 default: 640 ALOGE("Unsupported pixel format %#x", format); 641 dst = NULL; 642 break; 643 } 644 645 if (grmodule->unlock(grmodule, handle) != OK) { 646 ALOGE("Unable to unlock image buffer %p for access", handle); 647 } 648 649 return dst; 650} 651 652OMX_ERRORTYPE SoftVideoEncoderOMXComponent::getExtensionIndex( 653 const char *name, OMX_INDEXTYPE *index) { 654 if (!strcmp(name, "OMX.google.android.index.storeMetaDataInBuffers") || 655 !strcmp(name, "OMX.google.android.index.storeANWBufferInMetadata")) { 656 *(int32_t*)index = kStoreMetaDataExtensionIndex; 657 return OMX_ErrorNone; 658 } 659 return SimpleSoftOMXComponent::getExtensionIndex(name, index); 660} 661 662} // namespace android 663