1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
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
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 /*******************************************************************************************
19 Class :: CCYUV420SEMItoYUV420.cpp
20 ------------------------------------
21 The YUV420SEMI is semi interleaved and output format is YUV420 planar
22
23 ********************************************************************************************/
24 #include "colorconv_config.h"
25 #include "ccyuv420semitoyuv420.h"
26
27
New()28 OSCL_EXPORT_REF ColorConvertBase* CCYUV420SEMItoYUV420 :: New()
29 {
30 CCYUV420SEMItoYUV420* self = OSCL_NEW(CCYUV420SEMItoYUV420, ());
31 return OSCL_STATIC_CAST(ColorConvertBase*, self);
32 }
33
34
CCYUV420SEMItoYUV420()35 CCYUV420SEMItoYUV420 :: CCYUV420SEMItoYUV420()
36 {
37 }
38
39
~CCYUV420SEMItoYUV420()40 OSCL_EXPORT_REF CCYUV420SEMItoYUV420 :: ~CCYUV420SEMItoYUV420()
41 {
42 }
43
44
Init(int32 SrcWidth,int32 SrcHeight,int32 SrcPitch,int32 DstWidth,int32 DstHeight,int32 DstPitch,int32 nRotation)45 int32 CCYUV420SEMItoYUV420:: Init(int32 SrcWidth, int32 SrcHeight, int32 SrcPitch, int32 DstWidth, int32 DstHeight, int32 DstPitch, int32 nRotation)
46 {
47 /* no scaled outputs */
48 if (!(nRotation&0x1))
49 {
50 if ((SrcWidth != DstWidth) || (SrcHeight != DstHeight))
51 {
52 return 0;
53 }
54 }
55 else // with rotation
56 {
57 if ((SrcWidth != DstHeight) || (SrcHeight != DstWidth))
58 {
59 return 0;
60 }
61 }
62
63 if (SrcPitch != SrcWidth) // not support source cropping
64 {
65 return 0;
66 }
67 else
68 {
69 _mSrc_width = SrcWidth;
70 _mSrc_height = SrcHeight;
71 _mSrc_pitch = SrcPitch;
72 _mDst_width = DstWidth;
73 _mDst_height = DstHeight;
74 _mDst_pitch = DstPitch;
75 _mDst_mheight = DstHeight;
76 _mRotation = nRotation;
77
78 _mInitialized = true;
79
80 return 1;
81 }
82
83 }
84
85
GetOutputBufferSize(void)86 int32 CCYUV420SEMItoYUV420:: GetOutputBufferSize(void)
87 {
88 OSCL_ASSERT(_mInitialized == true);
89
90 return((_mDst_pitch * _mDst_mheight*3) >> 1);
91 }
92
93
SetMode(int32 nMode)94 int32 CCYUV420SEMItoYUV420::SetMode(int32 nMode)
95 {
96 OSCL_UNUSED_ARG(nMode);
97 OSCL_ASSERT(_mInitialized == true);
98
99 return 1;
100 }
101
SetYuvFullRange(bool range)102 int32 CCYUV420SEMItoYUV420::SetYuvFullRange(bool range)
103 {
104 OSCL_UNUSED_ARG(range);
105 OSCL_ASSERT(_mInitialized == true);
106
107 return 1; // has no meaning in this class. Always return 1
108 }
109
Convert(uint8 * inyuvBuf,uint8 * outyuvBuf)110 int32 CCYUV420SEMItoYUV420::Convert(uint8 *inyuvBuf, uint8 *outyuvBuf)
111 {
112 uint8 *yuvBuf[3] = {NULL, NULL, NULL };
113 int outYsize = (_mDst_pitch * _mDst_mheight);
114 OSCL_ASSERT(inyuvBuf);
115 OSCL_ASSERT(outyuvBuf);
116
117 yuvBuf[0] = outyuvBuf;
118 yuvBuf[1] = (outyuvBuf + outYsize);
119 yuvBuf[2] = (outyuvBuf + outYsize + (outYsize >> 2));
120
121 return (Convert(inyuvBuf, yuvBuf));
122 }
123
124
Convert(uint8 * inyuv,uint8 ** outyuv)125 int32 CCYUV420SEMItoYUV420::Convert(uint8 *inyuv, uint8 **outyuv)
126 {
127
128 int32 i, j;
129 uint16 *outcb, *outcr;
130 uint32 *outy;
131 uint32 *inyuv_4;
132 uint32 temp, tempU, tempV;
133 int outYsize, offset;
134
135 int lpitch = _mDst_pitch;
136 int lheight = _mSrc_height;
137
138 OSCL_ASSERT(inyuv);
139 OSCL_ASSERT(outyuv);
140 OSCL_ASSERT(_mInitialized == true);
141
142 outYsize = (lpitch * _mDst_mheight);
143
144 inyuv_4 = (uint32 *)inyuv;
145
146 switch (_mRotation)
147 {
148 case 0://Rotation0
149
150 outy = (uint32*) outyuv[0];
151 outcb = (uint16*) outyuv[1];
152 outcr = (uint16*) outyuv[2];
153
154 offset = lpitch - _mSrc_width;
155
156 /* Y copying */
157 for (i = lheight; i > 0; i--)
158 {
159 for (j = _mSrc_width >> 2; j > 0; j--)
160 {
161 temp = *inyuv_4++;
162 *outy++ = temp;
163 }
164 /* in case the dest pitch is larger than width */
165 outy += (offset >> 2);
166 }
167
168 /* U & V copying */
169 for (i = lheight >> 1; i > 0; i--)
170 {
171 for (j = _mSrc_width >> 2; j > 0; j--)
172 {
173 temp = *inyuv_4++; /* V1U1V0U0 */
174 tempU = temp & 0xFF; // U0
175 tempU = tempU | ((temp >> 8) & 0xFF00); //U1U0
176
177 tempV = (temp >> 8) & 0xFF; // V0
178 tempV = tempV | ((temp >> 16) & 0xFF00); //V1V0
179
180 *outcb++ = tempU;
181 *outcr++ = tempV;
182 }
183 /* in case the dest pitch is larger than width */
184 outcb += (offset >> 2);
185 outcr += (offset >> 2);
186 }
187
188 break;
189
190 case 1: // Rotation90 CW
191 /* To traverse in raster scan for output and vertical scan on the input.
192 ** You can write output 4 bytes at a time.
193 ** However, it takes more number of variables and more code size.
194 */
195 uint32 temp1;
196 outy = (uint32*) outyuv[0];
197 outcb = (uint16*) outyuv[1];
198 outcr = (uint16*) outyuv[2];
199
200 outy = outy + (lpitch >> 2) - 1;
201 outcb = outcb + (lpitch >> 2) - 1;
202 outcr = outcr + (lpitch >> 2) - 1;
203
204 /* Y copying */
205 for (i = _mSrc_width; i > 0; i--)
206 {
207 for (j = lheight >> 2; j > 0; j--)
208 {
209 temp = (*inyuv);
210 inyuv += _mSrc_width;
211 temp = (temp << 8) | (*inyuv);
212 inyuv += _mSrc_width;
213 temp = (temp << 8) | (*inyuv);
214 inyuv += _mSrc_width;
215 temp = (temp << 8) | (*inyuv);
216 inyuv += _mSrc_width;
217 *outy = temp;
218 outy--;
219 }
220 inyuv = inyuv - (lheight * _mSrc_width) + 1;
221 outy = outy + (lheight >> 2) + (lpitch >> 2);
222 /* in case the dest pitch is larger than width */
223 }
224
225 inyuv = inyuv + (lheight * _mSrc_width) - _mSrc_width;
226
227 /* U & V copying */
228 for (i = _mSrc_width >> 1; i > 0; i--)
229 {
230 for (j = lheight >> 2; j > 0; j--)
231 {
232 temp = *inyuv++; //U0
233 temp1 = *inyuv--; //V0
234 inyuv += _mSrc_width;
235 temp = (temp << 8) | (*inyuv); //U1U0
236 inyuv++;
237 temp1 = (temp1 << 8) | (*inyuv); //V1V0
238 inyuv--;
239 inyuv += _mSrc_width;
240
241 *outcb = temp;
242 *outcr = temp1;
243 outcb--;
244 outcr--;
245 }
246 /* in case the dest pitch is larger than width */
247 inyuv = inyuv - ((lheight >> 1) * _mSrc_width) + 2;
248 outcb = outcb + (lheight >> 2) + (lpitch >> 2);
249 outcr = outcr + (lheight >> 2) + (lpitch >> 2);
250 }
251 break;
252
253 case 2://Rotation180
254
255 outy = (uint32*)((uint8*)outyuv[0] + outYsize - 4);
256 outcb = (uint16*)((uint8*)outyuv[1] + (outYsize >> 2) - 4);
257 outcr = (uint16*)((uint8*)outyuv[2] + (outYsize >> 2) - 4);
258
259 offset = lpitch - _mSrc_width;
260
261 /* Y copying */
262 for (i = lheight; i > 0; i--)
263 {
264 for (j = _mSrc_width >> 2; j > 0; j--)
265 {
266 temp = *inyuv_4++;
267 *outy-- = SWAP_4(temp);
268 }
269 /* in case the dest pitch is larger than width */
270 outy -= (offset >> 2);
271 }
272
273 /* U & V copying */
274 for (i = lheight >> 1; i > 0; i--)
275 {
276 for (j = _mSrc_width >> 2; j > 0; j--)
277 {
278 temp = *inyuv_4++; /* V1U1V0U0 */
279 tempU = temp & 0xFF; // U0
280 tempU = (tempU << 8) | ((temp >> 16) & 0xFF); //U0U1
281
282 tempV = (temp >> 8) & 0xFF; // V0
283 tempV = (tempV << 8) | (temp >> 24); //V0V1
284
285 *outcb-- = tempU;
286 *outcr-- = tempV;
287 }
288 /* in case the dest pitch is larger than width */
289 outcb -= (offset >> 2);
290 outcr -= (offset >> 2);
291 }
292
293 break;
294
295 case 3: // Rotation270 CW
296 /* To traverse in raster scan for output and vertical scan on the input.
297 ** You can write output 4 bytes at a time.
298 ** However, it takes more number of variables and more code size.
299 */
300 outy = (uint32*) outyuv[0];
301 outcb = (uint16*) outyuv[1];
302 outcr = (uint16*) outyuv[2];
303
304 outy = outy + ((lpitch >> 2) * (_mSrc_width - 1));
305 outcb = outcb + ((lpitch >> 2) * ((_mSrc_width >> 1) - 1));
306 outcr = outcr + ((lpitch >> 2) * ((_mSrc_width >> 1) - 1));
307
308 /* Y copying */
309 for (i = _mSrc_width; i > 0; i--)
310 {
311 for (j = lheight >> 2; j > 0; j--)
312 {
313 temp = (*inyuv);
314 inyuv += _mSrc_width;
315 temp |= ((*inyuv) << 8);
316 inyuv += _mSrc_width;
317 temp |= ((*inyuv) << 16);
318 inyuv += _mSrc_width;
319 temp |= ((*inyuv) << 24);
320 inyuv += _mSrc_width;
321 *outy = temp;
322 outy++;
323 }
324 inyuv = inyuv - (lheight * _mSrc_width) + 1;
325 outy = outy - ((lheight >> 2) + (lpitch >> 2));
326 /* in case the dest pitch is larger than width */
327 }
328
329 inyuv = inyuv + (lheight * _mSrc_width) - _mSrc_width;
330
331 /* U & V copying */
332 for (i = _mSrc_width >> 1; i > 0; i--)
333 {
334 for (j = lheight >> 2; j > 0; j--)
335 {
336 temp = *inyuv++; //U0
337 temp1 = *inyuv--; //V0
338 inyuv += _mSrc_width;
339 temp |= ((*inyuv) << 8); //U0U1
340 inyuv++;
341 temp1 |= ((*inyuv) << 8); //V0V1
342 inyuv--;
343 inyuv += _mSrc_width;
344
345 *outcb = temp;
346 *outcr = temp1;
347 outcb++;
348 outcr++;
349 }
350 /* in case the dest pitch is larger than width */
351 inyuv = inyuv - ((lheight >> 1) * _mSrc_width) + 2;
352 outcb = outcb - ((lheight >> 2) + (lpitch >> 2));
353 outcr = outcr - ((lheight >> 2) + (lpitch >> 2));
354 }
355 break;
356
357 default:
358 break;
359
360 }//switch
361
362 return 1;
363 }
364
365
366
367
368
369