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