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 }