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 <media/stagefright/omx/SoftVideoEncoderOMXComponent.h> 25#include <media/stagefright/foundation/ADebug.h> 26#include <media/stagefright/foundation/ALooper.h> 27#include <media/stagefright/foundation/AMessage.h> 28#include <media/stagefright/foundation/AUtils.h> 29#include <media/hardware/HardwareAPI.h> 30#include <media/openmax/OMX_IndexExt.h> 31#include <media/MediaDefs.h> 32 33#include <ui/Fence.h> 34#include <ui/GraphicBufferMapper.h> 35#include <ui/Rect.h> 36 37#include <hardware/gralloc.h> 38#include <nativebase/nativebase.h> 39 40namespace android { 41 42const static OMX_COLOR_FORMATTYPE kSupportedColorFormats[] = { 43 OMX_COLOR_FormatYUV420Planar, 44 OMX_COLOR_FormatYUV420SemiPlanar, 45 OMX_COLOR_FormatAndroidOpaque 46}; 47 48template<class T> 49static void InitOMXParams(T *params) { 50 params->nSize = sizeof(T); 51 params->nVersion.s.nVersionMajor = 1; 52 params->nVersion.s.nVersionMinor = 0; 53 params->nVersion.s.nRevision = 0; 54 params->nVersion.s.nStep = 0; 55} 56 57SoftVideoEncoderOMXComponent::SoftVideoEncoderOMXComponent( 58 const char *name, 59 const char *componentRole, 60 OMX_VIDEO_CODINGTYPE codingType, 61 const CodecProfileLevel *profileLevels, 62 size_t numProfileLevels, 63 int32_t width, 64 int32_t height, 65 const OMX_CALLBACKTYPE *callbacks, 66 OMX_PTR appData, 67 OMX_COMPONENTTYPE **component) 68 : SimpleSoftOMXComponent(name, callbacks, appData, component), 69 mInputDataIsMeta(false), 70 mWidth(width), 71 mHeight(height), 72 mBitrate(192000), 73 mFramerate(30 << 16), // Q16 format 74 mColorFormat(OMX_COLOR_FormatYUV420Planar), 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 386__attribute__((no_sanitize("integer"))) 387void SoftVideoEncoderOMXComponent::ConvertFlexYUVToPlanar( 388 uint8_t *dst, size_t dstStride, size_t dstVStride, 389 struct android_ycbcr *ycbcr, int32_t width, int32_t height) { 390 const uint8_t *src = (const uint8_t *)ycbcr->y; 391 const uint8_t *srcU = (const uint8_t *)ycbcr->cb; 392 const uint8_t *srcV = (const uint8_t *)ycbcr->cr; 393 uint8_t *dstU = dst + dstVStride * dstStride; 394 uint8_t *dstV = dstU + (dstVStride >> 1) * (dstStride >> 1); 395 396 for (size_t y = height; y > 0; --y) { 397 memcpy(dst, src, width); 398 dst += dstStride; 399 src += ycbcr->ystride; 400 } 401 if (ycbcr->cstride == ycbcr->ystride >> 1 && ycbcr->chroma_step == 1) { 402 // planar 403 for (size_t y = height >> 1; y > 0; --y) { 404 memcpy(dstU, srcU, width >> 1); 405 dstU += dstStride >> 1; 406 srcU += ycbcr->cstride; 407 memcpy(dstV, srcV, width >> 1); 408 dstV += dstStride >> 1; 409 srcV += ycbcr->cstride; 410 } 411 } else { 412 // arbitrary 413 for (size_t y = height >> 1; y > 0; --y) { 414 for (size_t x = width >> 1; x > 0; --x) { 415 *dstU++ = *srcU; 416 *dstV++ = *srcV; 417 srcU += ycbcr->chroma_step; 418 srcV += ycbcr->chroma_step; 419 } 420 dstU += (dstStride >> 1) - (width >> 1); 421 dstV += (dstStride >> 1) - (width >> 1); 422 srcU += ycbcr->cstride - (width >> 1) * ycbcr->chroma_step; 423 srcV += ycbcr->cstride - (width >> 1) * ycbcr->chroma_step; 424 } 425 } 426} 427 428// static 429__attribute__((no_sanitize("integer"))) 430void SoftVideoEncoderOMXComponent::ConvertYUV420SemiPlanarToYUV420Planar( 431 const uint8_t *inYVU, uint8_t* outYUV, int32_t width, int32_t height) { 432 // TODO: add support for stride 433 int32_t outYsize = width * height; 434 uint32_t *outY = (uint32_t *) outYUV; 435 uint16_t *outCb = (uint16_t *) (outYUV + outYsize); 436 uint16_t *outCr = (uint16_t *) (outYUV + outYsize + (outYsize >> 2)); 437 438 /* Y copying */ 439 memcpy(outY, inYVU, outYsize); 440 441 /* U & V copying */ 442 // FIXME this only works if width is multiple of 4 443 uint32_t *inYVU_4 = (uint32_t *) (inYVU + outYsize); 444 for (int32_t i = height >> 1; i > 0; --i) { 445 for (int32_t j = width >> 2; j > 0; --j) { 446 uint32_t temp = *inYVU_4++; 447 uint32_t tempU = temp & 0xFF; 448 tempU = tempU | ((temp >> 8) & 0xFF00); 449 450 uint32_t tempV = (temp >> 8) & 0xFF; 451 tempV = tempV | ((temp >> 16) & 0xFF00); 452 453 *outCb++ = tempU; 454 *outCr++ = tempV; 455 } 456 } 457} 458 459// static 460__attribute__((no_sanitize("integer"))) 461void SoftVideoEncoderOMXComponent::ConvertRGB32ToPlanar( 462 uint8_t *dstY, size_t dstStride, size_t dstVStride, 463 const uint8_t *src, size_t width, size_t height, size_t srcStride, 464 bool bgr) { 465 CHECK((width & 1) == 0); 466 CHECK((height & 1) == 0); 467 468 uint8_t *dstU = dstY + dstStride * dstVStride; 469 uint8_t *dstV = dstU + (dstStride >> 1) * (dstVStride >> 1); 470 471#ifdef SURFACE_IS_BGR32 472 bgr = !bgr; 473#endif 474 475 const size_t redOffset = bgr ? 2 : 0; 476 const size_t greenOffset = 1; 477 const size_t blueOffset = bgr ? 0 : 2; 478 479 for (size_t y = 0; y < height; ++y) { 480 for (size_t x = 0; x < width; ++x) { 481 unsigned red = src[redOffset]; 482 unsigned green = src[greenOffset]; 483 unsigned blue = src[blueOffset]; 484 485 // Using ITU-R BT.601-7 (03/2011) 486 // 2.5.1: Ey' = ( 0.299*R + 0.587*G + 0.114*B) 487 // 2.5.2: ECr' = ( 0.701*R - 0.587*G - 0.114*B) / 1.402 488 // ECb' = (-0.299*R - 0.587*G + 0.886*B) / 1.772 489 // 2.5.3: Y = 219 * Ey' + 16 490 // Cr = 224 * ECr' + 128 491 // Cb = 224 * ECb' + 128 492 493 unsigned luma = 494 ((red * 65 + green * 129 + blue * 25 + 128) >> 8) + 16; 495 496 dstY[x] = luma; 497 498 if ((x & 1) == 0 && (y & 1) == 0) { 499 unsigned U = 500 ((-red * 38 - green * 74 + blue * 112 + 128) >> 8) + 128; 501 502 unsigned V = 503 ((red * 112 - green * 94 - blue * 18 + 128) >> 8) + 128; 504 505 dstU[x >> 1] = U; 506 dstV[x >> 1] = V; 507 } 508 src += 4; 509 } 510 511 if ((y & 1) == 0) { 512 dstU += dstStride >> 1; 513 dstV += dstStride >> 1; 514 } 515 516 src += srcStride - 4 * width; 517 dstY += dstStride; 518 } 519} 520 521const uint8_t *SoftVideoEncoderOMXComponent::extractGraphicBuffer( 522 uint8_t *dst, size_t dstSize, 523 const uint8_t *src, size_t srcSize, 524 size_t width, size_t height) const { 525 size_t dstStride = width; 526 size_t dstVStride = height; 527 528 MetadataBufferType bufferType = *(MetadataBufferType *)src; 529 bool usingANWBuffer = bufferType == kMetadataBufferTypeANWBuffer; 530 if (!usingANWBuffer && bufferType != kMetadataBufferTypeGrallocSource) { 531 ALOGE("Unsupported metadata type (%d)", bufferType); 532 return NULL; 533 } 534 535 buffer_handle_t handle; 536 int format; 537 size_t srcStride; 538 size_t srcVStride; 539 if (usingANWBuffer) { 540 if (srcSize < sizeof(VideoNativeMetadata)) { 541 ALOGE("Metadata is too small (%zu vs %zu)", srcSize, sizeof(VideoNativeMetadata)); 542 return NULL; 543 } 544 545 VideoNativeMetadata &nativeMeta = *(VideoNativeMetadata *)src; 546 ANativeWindowBuffer *buffer = nativeMeta.pBuffer; 547 handle = buffer->handle; 548 format = buffer->format; 549 srcStride = buffer->stride; 550 srcVStride = buffer->height; 551 // convert stride from pixels to bytes 552 if (format != HAL_PIXEL_FORMAT_YV12 && 553 format != HAL_PIXEL_FORMAT_YCrCb_420_SP && 554 format != HAL_PIXEL_FORMAT_YCbCr_420_888) { 555 // TODO do we need to support other formats? 556 srcStride *= 4; 557 } 558 559 if (nativeMeta.nFenceFd >= 0) { 560 sp<Fence> fence = new Fence(nativeMeta.nFenceFd); 561 nativeMeta.nFenceFd = -1; 562 status_t err = fence->wait(IOMX::kFenceTimeoutMs); 563 if (err != OK) { 564 ALOGE("Timed out waiting on input fence"); 565 return NULL; 566 } 567 } 568 } else { 569 // TODO: remove this part. Check if anyone uses this. 570 571 if (srcSize < sizeof(VideoGrallocMetadata)) { 572 ALOGE("Metadata is too small (%zu vs %zu)", srcSize, sizeof(VideoGrallocMetadata)); 573 return NULL; 574 } 575 576 VideoGrallocMetadata &grallocMeta = *(VideoGrallocMetadata *)(src); 577 handle = grallocMeta.pHandle; 578 // assume HAL_PIXEL_FORMAT_RGBA_8888 579 // there is no way to get the src stride without the graphic buffer 580 format = HAL_PIXEL_FORMAT_RGBA_8888; 581 srcStride = width * 4; 582 srcVStride = height; 583 } 584 585 size_t neededSize = 586 dstStride * dstVStride + (width >> 1) 587 + (dstStride >> 1) * ((dstVStride >> 1) + (height >> 1) - 1); 588 if (dstSize < neededSize) { 589 ALOGE("destination buffer is too small (%zu vs %zu)", dstSize, neededSize); 590 return NULL; 591 } 592 593 auto& mapper = GraphicBufferMapper::get(); 594 595 void *bits = NULL; 596 struct android_ycbcr ycbcr; 597 status_t res; 598 if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) { 599 res = mapper.lockYCbCr( 600 handle, 601 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER, 602 Rect(width, height), &ycbcr); 603 } else { 604 res = mapper.lock( 605 handle, 606 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER, 607 Rect(width, height), &bits); 608 } 609 if (res != OK) { 610 ALOGE("Unable to lock image buffer %p for access", handle); 611 return NULL; 612 } 613 614 switch (format) { 615 case HAL_PIXEL_FORMAT_YV12: // YCrCb / YVU planar 616 ycbcr.y = bits; 617 ycbcr.cr = (uint8_t *)bits + srcStride * srcVStride; 618 ycbcr.cb = (uint8_t *)ycbcr.cr + (srcStride >> 1) * (srcVStride >> 1); 619 ycbcr.chroma_step = 1; 620 ycbcr.cstride = srcStride >> 1; 621 ycbcr.ystride = srcStride; 622 ConvertFlexYUVToPlanar(dst, dstStride, dstVStride, &ycbcr, width, height); 623 break; 624 case HAL_PIXEL_FORMAT_YCrCb_420_SP: // YCrCb / YVU semiplanar, NV21 625 ycbcr.y = bits; 626 ycbcr.cr = (uint8_t *)bits + srcStride * srcVStride; 627 ycbcr.cb = (uint8_t *)ycbcr.cr + 1; 628 ycbcr.chroma_step = 2; 629 ycbcr.cstride = srcStride; 630 ycbcr.ystride = srcStride; 631 ConvertFlexYUVToPlanar(dst, dstStride, dstVStride, &ycbcr, width, height); 632 break; 633 case HAL_PIXEL_FORMAT_YCbCr_420_888: // YCbCr / YUV planar 634 ConvertFlexYUVToPlanar(dst, dstStride, dstVStride, &ycbcr, width, height); 635 break; 636 case HAL_PIXEL_FORMAT_RGBX_8888: 637 case HAL_PIXEL_FORMAT_RGBA_8888: 638 case HAL_PIXEL_FORMAT_BGRA_8888: 639 ConvertRGB32ToPlanar( 640 dst, dstStride, dstVStride, 641 (const uint8_t *)bits, width, height, srcStride, 642 format == HAL_PIXEL_FORMAT_BGRA_8888); 643 break; 644 default: 645 ALOGE("Unsupported pixel format %#x", format); 646 dst = NULL; 647 break; 648 } 649 650 if (mapper.unlock(handle) != OK) { 651 ALOGE("Unable to unlock image buffer %p for access", handle); 652 } 653 654 return dst; 655} 656 657OMX_ERRORTYPE SoftVideoEncoderOMXComponent::getExtensionIndex( 658 const char *name, OMX_INDEXTYPE *index) { 659 if (!strcmp(name, "OMX.google.android.index.storeMetaDataInBuffers") || 660 !strcmp(name, "OMX.google.android.index.storeANWBufferInMetadata")) { 661 *(int32_t*)index = kStoreMetaDataExtensionIndex; 662 return OMX_ErrorNone; 663 } 664 return SimpleSoftOMXComponent::getExtensionIndex(name, index); 665} 666 667OMX_ERRORTYPE SoftVideoEncoderOMXComponent::validateInputBuffer( 668 const OMX_BUFFERHEADERTYPE *inputBufferHeader) { 669 size_t frameSize = mInputDataIsMeta ? 670 max(sizeof(VideoNativeMetadata), sizeof(VideoGrallocMetadata)) 671 : mWidth * mHeight * 3 / 2; 672 if (inputBufferHeader->nFilledLen < frameSize) { 673 return OMX_ErrorUndefined; 674 } else if (inputBufferHeader->nFilledLen > frameSize) { 675 ALOGW("Input buffer contains more data than expected."); 676 } 677 return OMX_ErrorNone; 678} 679 680} // namespace android 681