1 /**
2 * Copyright (C) 2022 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 "ImsMediaImageRotate.h"
18 #include <ImsMediaTrace.h>
19
YUV420_Planar_Rotate90_Flip(uint8_t * pbDst,uint8_t * pbSrc,uint16_t nSrcWidth,uint16_t nSrcHeight)20 void ImsMediaImageRotate::YUV420_Planar_Rotate90_Flip(
21 uint8_t* pbDst, uint8_t* pbSrc, uint16_t nSrcWidth, uint16_t nSrcHeight)
22 {
23 uint16_t x, y;
24 uint64_t srcIdx, dstIdx;
25 const size_t size = nSrcWidth * nSrcHeight;
26 dstIdx = size - 1;
27
28 // Rotate Y buffer
29 for (y = 0; y < nSrcWidth; y++)
30 {
31 srcIdx = y;
32 for (x = 0; x < nSrcHeight; x++)
33 {
34 pbDst[dstIdx] = pbSrc[srcIdx]; // Y
35
36 srcIdx += nSrcWidth;
37 dstIdx--;
38 }
39 }
40
41 dstIdx = (size * 1.5f) - 1;
42 const uint64_t usize = size / 4;
43 nSrcWidth /= 2;
44 nSrcHeight /= 2;
45
46 // Rotate UV buffer
47 for (y = 0; y < nSrcWidth; y++)
48 {
49 srcIdx = size + y;
50 for (x = 0; x < nSrcHeight; x++)
51 {
52 pbDst[dstIdx - usize] = pbSrc[srcIdx]; // U
53 pbDst[dstIdx] = pbSrc[usize + srcIdx]; // V
54
55 srcIdx += nSrcWidth;
56 dstIdx--;
57 }
58 }
59 }
60
YUV420_SP_Rotate90(uint8_t * pOutBuffer,size_t nOutBufSize,uint16_t outputStride,uint8_t * pYPlane,uint8_t * pUVPlane,uint16_t nSrcWidth,uint16_t nSrcHeight)61 int ImsMediaImageRotate::YUV420_SP_Rotate90(uint8_t* pOutBuffer, size_t nOutBufSize,
62 uint16_t outputStride, uint8_t* pYPlane, uint8_t* pUVPlane, uint16_t nSrcWidth,
63 uint16_t nSrcHeight)
64 {
65 uint16_t x, y, nDstWidth = nSrcHeight, nDstHt = nSrcWidth, nPadWidth = outputStride - nDstWidth;
66 uint64_t srcIdx, dstIdx = (outputStride * nDstHt) - 1;
67 const size_t dstSize = outputStride * nDstHt * 1.5f;
68
69 if (nOutBufSize < (dstSize - nPadWidth))
70 {
71 IMLOGE4("Output buffer size is not sufficient. \
72 Required(outputStride[%d] * outputHeight[%d] * 1.5 = %d) but passed[%d]",
73 outputStride, nDstHt, dstSize, nOutBufSize);
74 return -1;
75 }
76
77 if (nDstWidth > outputStride)
78 {
79 IMLOGE2("Destination width[%d] cannot be bigger than stride[%d]", nDstWidth, outputStride);
80 return -1;
81 }
82
83 // Rotate Y buffer
84 for (y = 0; y < nSrcWidth; y++)
85 {
86 dstIdx -= nPadWidth;
87 srcIdx = nSrcWidth - y - 1;
88 for (x = 0; x < nSrcHeight; x++)
89 {
90 pOutBuffer[dstIdx] = pYPlane[srcIdx]; // Y
91 srcIdx += nSrcWidth;
92 dstIdx--;
93 }
94 }
95
96 dstIdx = dstSize - 1;
97 nSrcWidth /= 2;
98 nSrcHeight /= 2;
99
100 // Rotate UV buffer
101 for (y = 0; y < nSrcWidth; y++)
102 {
103 dstIdx -= nPadWidth;
104 srcIdx = (nSrcWidth - y - 1) * 2;
105 for (x = 0; x < nSrcHeight; x++)
106 {
107 pOutBuffer[dstIdx--] = pUVPlane[srcIdx + 1]; // V
108 pOutBuffer[dstIdx--] = pUVPlane[srcIdx]; // U
109 srcIdx += nSrcWidth * 2;
110 }
111 }
112
113 return 0;
114 }
115
YUV420_SP_Rotate90_Flip(uint8_t * pbDst,uint8_t * pYPlane,uint8_t * pUVPlane,uint16_t nSrcWidth,uint16_t nSrcHeight)116 void ImsMediaImageRotate::YUV420_SP_Rotate90_Flip(uint8_t* pbDst, uint8_t* pYPlane,
117 uint8_t* pUVPlane, uint16_t nSrcWidth, uint16_t nSrcHeight)
118 {
119 uint16_t x, y;
120 uint64_t srcIdx, dstIdx;
121 const size_t size = nSrcWidth * nSrcHeight;
122
123 dstIdx = size - 1;
124
125 // Rotate Y buffer
126 for (y = 0; y < nSrcWidth; y++)
127 {
128 srcIdx = y;
129 for (x = 0; x < nSrcHeight; x++)
130 {
131 pbDst[dstIdx] = pYPlane[srcIdx]; // Y
132 srcIdx += nSrcWidth;
133 dstIdx--;
134 }
135 }
136
137 dstIdx = (size * 1.5f) - 1;
138 nSrcWidth /= 2;
139 nSrcHeight /= 2;
140
141 // Rotate UV buffer
142 for (y = 0; y < nSrcWidth; y++)
143 {
144 srcIdx = y * 2;
145 for (x = 0; x < nSrcHeight; x++)
146 {
147 pbDst[dstIdx--] = pUVPlane[srcIdx + 1]; // V
148 pbDst[dstIdx--] = pUVPlane[srcIdx]; // U
149 srcIdx += nSrcWidth * 2;
150 }
151 }
152 }
153
YUV420_SP_Rotate270(uint8_t * pOutBuffer,size_t nOutBufSize,uint16_t outputStride,uint8_t * pYPlane,uint8_t * pUVPlane,uint16_t nSrcWidth,uint16_t nSrcHeight)154 int ImsMediaImageRotate::YUV420_SP_Rotate270(uint8_t* pOutBuffer, size_t nOutBufSize,
155 uint16_t outputStride, uint8_t* pYPlane, uint8_t* pUVPlane, uint16_t nSrcWidth,
156 uint16_t nSrcHeight)
157 {
158 uint16_t x, y, nDstWth = nSrcHeight, nDstHt = nSrcWidth, nPadWidth = outputStride - nDstWth;
159 uint64_t srcIdx, dstIdx = outputStride * nDstHt - 1;
160 const size_t size = nSrcWidth * nSrcHeight;
161 const size_t dstSize = outputStride * nDstHt * 1.5f;
162
163 if (nOutBufSize < (dstSize - nPadWidth))
164 {
165 IMLOGE4("Output buffer size is not sufficient. \
166 Required(outputStride[%d] * outputHeight[%d] * 1.5 = %d) but passed[%d]",
167 outputStride, nDstHt, dstSize, nOutBufSize);
168 return -1;
169 }
170
171 if (nDstWth > outputStride)
172 {
173 IMLOGE2("Destination width[%d] cannot be bigger than stride[%d]", nDstWth, outputStride);
174 return -1;
175 }
176
177 // Rotate Y buffer
178 for (y = 0; y < nSrcWidth; y++)
179 {
180 dstIdx -= nPadWidth;
181 srcIdx = size - nSrcWidth + y;
182 for (x = 0; x < nSrcHeight; x++)
183 {
184 pOutBuffer[dstIdx] = pYPlane[srcIdx]; // Y
185 srcIdx -= nSrcWidth;
186 dstIdx--;
187 }
188 }
189
190 dstIdx = dstSize - 1;
191 nSrcWidth /= 2;
192 nSrcHeight /= 2;
193
194 // Rotate UV buffer
195 for (y = 0; y < nSrcWidth; y++)
196 {
197 dstIdx -= nPadWidth;
198 srcIdx = (size / 2) - (nSrcWidth - y) * 2;
199 for (x = 0; x < nSrcHeight; x++)
200 {
201 pOutBuffer[dstIdx--] = pUVPlane[srcIdx + 1]; // V
202 pOutBuffer[dstIdx--] = pUVPlane[srcIdx]; // U
203 srcIdx -= nSrcWidth * 2;
204 }
205 }
206
207 return 0;
208 }