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 
getDecoderOutputFormat()21 static int getDecoderOutputFormat() {
22     return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
23 }
24 
convertDecoderOutputToI420(void * srcBits,int srcWidth,int srcHeight,ARect srcRect,void * dstBits)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 
getEncoderInputFormat()61 static int getEncoderInputFormat() {
62     return OMX_TI_COLOR_FormatYUV420PackedSemiPlanar;
63 }
64 
convertI420ToEncoderInput(void * srcBits,int srcWidth,int srcHeight,int dstWidth,int dstHeight,ARect dstRect,void * dstBits)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 
getEncoderInputBufferInfo(int actualWidth,int actualHeight,int * encoderWidth,int * encoderHeight,ARect * encoderRect,int * encoderBufferSize)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 
getI420ColorConverter(II420ColorConverter * converter)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