Home | History | Annotate | Download | only in libI420colorconvert
      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