1 /* 2 * Copyright (C) 2011 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 <II420ColorConverter.h> 18 #include <OMX_IVCommon.h> 19 #include <string.h> 20 21 static int getDecoderOutputFormat() { 22 return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar; 23 } 24 25 static int convertDecoderOutputToI420( 26 void* srcBits, int srcWidth, int srcHeight, ARect srcRect, void* dstBits) { 27 28 const uint8_t *pSrc_y = (const uint8_t *)srcBits + 29 srcWidth * srcRect.top + srcRect.left; 30 const uint8_t *pSrc_uv = (const uint8_t *)pSrc_y + 31 srcWidth * (srcHeight - srcRect.top / 2); 32 33 int dstWidth = srcRect.right - srcRect.left + 1; 34 int dstHeight = srcRect.bottom - srcRect.top + 1; 35 size_t dst_y_size = dstWidth * dstHeight; 36 size_t dst_uv_stride = dstWidth / 2; 37 size_t dst_uv_size = dstWidth / 2 * dstHeight / 2; 38 uint8_t *pDst_y = (uint8_t *)dstBits; 39 uint8_t *pDst_u = pDst_y + dst_y_size; 40 uint8_t *pDst_v = pDst_u + dst_uv_size; 41 42 for (int y = 0; y < dstHeight; ++y) { 43 memcpy(pDst_y, pSrc_y, dstWidth); 44 pSrc_y += srcWidth; 45 pDst_y += dstWidth; 46 } 47 48 size_t tmp = (dstWidth + 1) / 2; 49 for (int y = 0; y < (dstHeight + 1) / 2; ++y) { 50 for (size_t x = 0; x < tmp; ++x) { 51 pDst_u[x] = pSrc_uv[2 * x]; 52 pDst_v[x] = pSrc_uv[2 * x + 1]; 53 } 54 pSrc_uv += srcWidth; 55 pDst_u += dst_uv_stride; 56 pDst_v += dst_uv_stride; 57 } 58 return 0; 59 } 60 61 static int getEncoderInputFormat() { 62 return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar; 63 } 64 65 static int convertI420ToEncoderInput( 66 void* srcBits, int srcWidth, int srcHeight, 67 int dstWidth, int dstHeight, ARect dstRect, 68 void* dstBits) { 69 uint8_t *pSrc_y = (uint8_t*) srcBits; 70 uint8_t *pDst_y = (uint8_t*) dstBits; 71 for(int i=0; i < srcHeight; i++) { 72 memcpy(pDst_y, pSrc_y, srcWidth); 73 pSrc_y += srcWidth; 74 pDst_y += dstWidth; 75 } 76 uint8_t* pSrc_u = (uint8_t*)srcBits + (srcWidth * srcHeight); 77 uint8_t* pSrc_v = (uint8_t*)pSrc_u + (srcWidth / 2) * (srcHeight / 2); 78 uint8_t* pDst_uv = (uint8_t*)dstBits + dstWidth * dstHeight; 79 80 for(int i=0; i < srcHeight / 2; i++) { 81 for(int j=0, k=0; j < srcWidth / 2; j++, k+=2) { 82 pDst_uv[k] = pSrc_u[j]; 83 pDst_uv[k+1] = pSrc_v[j]; 84 } 85 pDst_uv += dstWidth; 86 pSrc_u += srcWidth / 2; 87 pSrc_v += srcWidth / 2; 88 } 89 return 0; 90 } 91 92 static int getEncoderInputBufferInfo( 93 int actualWidth, int actualHeight, 94 int* encoderWidth, int* encoderHeight, 95 ARect* encoderRect, int* encoderBufferSize) { 96 97 *encoderWidth = actualWidth; 98 *encoderHeight = actualHeight; 99 encoderRect->left = 0; 100 encoderRect->top = 0; 101 encoderRect->right = actualWidth - 1; 102 encoderRect->bottom = actualHeight - 1; 103 *encoderBufferSize = (actualWidth * actualHeight * 3 / 2); 104 105 return 0; 106 } 107 108 extern "C" void getI420ColorConverter(II420ColorConverter *converter) { 109 converter->getDecoderOutputFormat = getDecoderOutputFormat; 110 converter->convertDecoderOutputToI420 = convertDecoderOutputToI420; 111 converter->getEncoderInputFormat = getEncoderInputFormat; 112 converter->convertI420ToEncoderInput = convertI420ToEncoderInput; 113 converter->getEncoderInputBufferInfo = getEncoderInputBufferInfo; 114 } 115