• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /** class CCRGB12toYUV420.cpp
19 */
20 #include "ccrgb12toyuv420.h"
21 
New()22 OSCL_EXPORT_REF ColorConvertBase* CCRGB12toYUV420 :: New()
23 {
24     CCRGB12toYUV420* self = OSCL_NEW(CCRGB12toYUV420, ());
25     return OSCL_STATIC_CAST(ColorConvertBase*, self);
26 }
27 
28 
CCRGB12toYUV420()29 CCRGB12toYUV420::CCRGB12toYUV420()
30 {
31 }
32 
33 
~CCRGB12toYUV420()34 OSCL_EXPORT_REF CCRGB12toYUV420 :: ~CCRGB12toYUV420()
35 {
36 // add destructor code here
37     if (_mInitialized == true)
38     {
39         freeRGB2YUVTables();
40     }
41 }
42 
43 
freeRGB2YUVTables()44 void CCRGB12toYUV420::freeRGB2YUVTables()
45 {
46     if (iY_Table) oscl_free(iY_Table);
47     if (iCb_Table) oscl_free(iCb_Table);
48     if (iCr_Table) oscl_free(iCr_Table);
49 
50     iY_Table  = NULL;
51     iCb_Table = iCr_Table = ipCb_Table = ipCr_Table = NULL;
52 
53 }
54 
55 
Init(int32 Src_width,int32 Src_height,int32 Src_pitch,int32 Dst_width,int32 Dst_height,int32 Dst_pitch,int32 nRotation)56 int32 CCRGB12toYUV420:: Init(int32 Src_width, int32 Src_height, int32 Src_pitch, int32 Dst_width,
57                              int32 Dst_height, int32 Dst_pitch, int32 nRotation)
58 {
59     int i;
60     uint8 *pTable;
61 
62     if ((Src_width != Dst_width) || (Src_height != Dst_height) || (nRotation != 0 && nRotation != CCBOTTOM_UP))
63     {
64         return 0;
65     }
66 
67     iBottomUp = false;
68     if (nRotation == CCBOTTOM_UP)
69     {
70         iBottomUp = true;
71     }
72 
73     if (_mInitialized == true)
74     {
75         freeRGB2YUVTables();
76         _mInitialized = false;
77     }
78 
79     /* memory allocation */
80     if ((iY_Table = (uint8*)oscl_malloc(384)) == NULL)
81         return 0;
82 
83     if ((iCb_Table = (uint8*)oscl_malloc(768 * 2)) == NULL)
84         return 0;
85 
86     if ((iCr_Table = (uint8*)oscl_malloc(768 * 2)) == NULL)
87         return 0;
88 
89 #define pv_max(a, b)    ((a) >= (b) ? (a) : (b))
90 #define pv_min(a, b)    ((a) <= (b) ? (a) : (b))
91 
92     /* Table generation */
93     for (i = 0; i < 384; i++)
94         iY_Table[i] = (uint8) pv_max(pv_min(255, (int32)(0.7152 * i + 16 + 0.5)), 0);
95 
96     pTable = iCb_Table + 384;
97     for (i = -384; i < 384; i++)
98         pTable[i] = (uint8) pv_max(pv_min(255, (int32)(0.386 * i + 128 + 0.5)), 0);
99     ipCb_Table = iCb_Table + 384;
100 
101     pTable = iCr_Table + 384;
102     for (i = -384; i < 384; i++)
103         pTable[i] = (uint8) pv_max(pv_min(255, (int32)(0.454 * i + 128 + 0.5)), 0);
104     ipCr_Table = iCr_Table + 384;
105 
106 
107     _mSrc_width  = Src_width;
108     _mSrc_height = Src_height;
109     _mSrc_pitch = Src_pitch;
110     _mDst_width = Dst_width;
111     _mDst_height = Dst_height;
112     _mDst_mheight = Dst_height;
113     _mDst_pitch = Dst_pitch;
114     _mInitialized = true;
115 
116     SetMode(0);
117 
118     return 1;
119 }
120 
121 
GetOutputBufferSize(void)122 int32 CCRGB12toYUV420::GetOutputBufferSize(void)
123 {
124     OSCL_ASSERT(_mInitialized == true);
125 
126     // only return value for _mState = 0 case
127     return ((((_mSrc_width + 15) >> 4) << 4) *(((_mSrc_height + 15) >> 4) << 4) * 3 / 2);
128 }
129 
130 
SetMode(int32 nMode)131 int32 CCRGB12toYUV420::SetMode(int32 nMode)
132 {
133     OSCL_ASSERT(_mInitialized == true);
134 
135     if (nMode == 1) // do not allow scaling nor rotation
136     {
137         _mState = 1;
138         return 0;
139     }
140     else
141     {
142         _mState = 0;
143         return 1;
144     }
145 }
146 
SetYuvFullRange(bool range)147 int32 CCRGB12toYUV420::SetYuvFullRange(bool range)
148 {
149     OSCL_ASSERT(_mInitialized == true);
150     if (range == true)
151     {
152         return 0; // not supported yet
153     }
154     else
155     {
156         return 1;
157     }
158 }
159 
160 extern "C"
161 {
162     int32 ccrgb12toyuv(uint8 *rgb12, uint8 *yuv[], uint32 *param, uint8 *table[]);
163 }
164 
Convert(uint8 * rgb12,uint8 * yuv420)165 int32 CCRGB12toYUV420::Convert(uint8 *rgb12, uint8 *yuv420)
166 {
167     uint32 param[3];
168     uint8 *table[3];
169     int32 size16 = _mDst_pitch * _mDst_mheight;
170     uint8 *yuv[3];
171 
172     OSCL_ASSERT(rgb12);
173     OSCL_ASSERT(yuv420);
174     OSCL_ASSERT(_mInitialized == true);
175 
176     param[0] = (uint32) _mSrc_width;
177     param[1] = (uint32) _mSrc_height;
178     param[2] = (uint32) iBottomUp;
179 
180     table[0] = iY_Table;
181     table[1] = ipCb_Table;
182     table[2] = ipCr_Table;
183 
184     yuv[0] = yuv420;
185     yuv[1] = yuv420 + size16;
186     yuv[2] = yuv[1] + (size16 >> 2);
187 
188     return ccrgb12toyuv(rgb12, yuv, param, table);
189 
190 }
191 
Convert(uint8 * rgb12,uint8 ** yuv420)192 int32 CCRGB12toYUV420::Convert(uint8 *rgb12, uint8 **yuv420)
193 {
194     uint32 param[3];
195     uint8 *table[3];
196 
197     OSCL_ASSERT(rgb12);
198     OSCL_ASSERT(yuv420);
199     OSCL_ASSERT(yuv420[0]);
200     OSCL_ASSERT(yuv420[1]);
201     OSCL_ASSERT(yuv420[2]);
202     OSCL_ASSERT(_mInitialized == true);
203 
204     param[0] = (uint32) _mSrc_width;
205     param[1] = (uint32) _mSrc_height;
206     param[2] = (uint32) iBottomUp;
207 
208     table[0] = iY_Table;
209     table[1] = ipCb_Table;
210     table[2] = ipCr_Table;
211 
212     return ccrgb12toyuv(rgb12, yuv420, param, table);
213 
214 }
215 
ccrgb12toyuv(uint8 * rgb12,uint8 * yuv[],uint32 * param,uint8 * table[])216 int32 ccrgb12toyuv(uint8 *rgb12, uint8 *yuv[], uint32 *param, uint8 *table[])
217 {
218     uint32 *inputRGB = NULL;
219     int i, j, ilimit, jlimit;
220     uint32 *tempY, *tempU, *tempV;
221     uint32 pixels;
222     uint32 pixels_nextRow;
223     uint32 yuv_value;
224     uint32 yuv_value1;
225     uint32 yuv_value2;
226     int R_ds; /* "_ds" is the downsample version */
227     int G_ds; /* "_ds" is the downsample version */
228     int B_ds; /* "_ds" is the downsample version */
229     int tmp;
230     uint32 temp;
231 
232     int32 width = param[0];
233     int32 height = param[1];
234     int32 width_16 = ((width + 15) >> 4) << 4;
235     int32 height_16 = ((height + 15) >> 4) << 4;
236     uint32 iBottomUp = param[2];
237     uint8 *y_tab = table[0];
238     uint8 *cb_tab = table[1];
239     uint8 *cr_tab = table[2];
240     int32 size16 = height_16 * width_16;
241     int adjust = (width >> 1);
242 
243     inputRGB = (uint32*) rgb12;
244 
245     /* do padding at the bottom first */
246     /* do padding if input RGB size(height) is different from the output YUV size(height_16) */
247     if (height < height_16 || width < width_16)
248     { /* if padding */
249         int offset = (height < height_16) ? height : height_16;
250 
251         offset = (offset * width_16);
252 
253         if (width < width_16)
254         {
255             offset -= (width_16 - width);
256         }
257 
258         tempY = (uint32 *)yuv[0] + (offset >> 2);
259         oscl_memset((uint8 *)tempY, 16, size16 - offset); /* pad with zeros */
260 
261         tempU = (uint32 *)yuv[0] + (size16 >> 2) + (offset >> 4);
262         oscl_memset((uint8 *)tempU, 128, (size16 - offset) >> 2);
263 
264         tempV = (uint32 *)yuv[0] + (size16 >> 2) + (size16 >> 4) + (offset >> 4);
265         oscl_memset((uint8 *)tempV, 128, (size16 - offset) >> 2);
266     }
267 
268     /* then do padding on the top */
269     tempY = (uint32 *)yuv[0]; /* Normal order */
270     tempU = tempY + ((size16) >> 2);
271     tempV = tempU + ((size16) >> 4);
272 
273     /* To center the output */
274     if (height_16 > height)
275     {
276         if (width_16 >= width)
277         {
278             i = ((height_16 - height) >> 1) * width_16 + (((width_16 - width) >> 3) << 2);
279             /* make sure that (width_16-width)>>1 is divisible by 4 */
280             j = ((height_16 - height) >> 2) * (width_16 >> 1) + (((width_16 - width) >> 4) << 2);
281             /* make sure that (width_16-width)>>2 is divisible by 4 */
282         }
283         else
284         {
285             i = ((height_16 - height) >> 1) * width_16;
286             j = ((height_16 - height) >> 2) * (width_16 >> 1);
287             inputRGB += (width - width_16) >> 2;
288         }
289         oscl_memset((uint8 *)tempY, 16, i);
290         tempY += (i >> 2);
291         oscl_memset((uint8 *)tempU, 128, j);
292         tempU += (j >> 2);
293         oscl_memset((uint8 *)tempV, 128, j);
294         tempV += (j >> 2);
295     }
296     else
297     {
298         if (width_16 >= width)
299         {
300             i = (((width_16 - width) >> 3) << 2);
301             /* make sure that (width_16-width)>>1 is divisible by 4 */
302             j = (((width_16 - width) >> 4) << 2);
303             /* make sure that (width_16-width)>>2 is divisible by 4 */
304             inputRGB += (((height - height_16) >> 1) * width) >> 1;
305 
306             oscl_memset((uint8 *)tempY, 16, i);
307             tempY += (i >> 2);
308             oscl_memset((uint8 *)tempU, 128, j);
309             tempU += (j >> 2);
310             oscl_memset((uint8 *)tempV, 128, j);
311             tempV += (j >> 2);
312 
313         }
314         else
315         {
316             i = 0;
317             j = 0;
318             inputRGB += (((height - height_16) >> 1) * width + ((width - width_16) >> 1)) >> 1 ;
319         }
320     }
321 
322     /* ColorConv RGB12-to-YUV420 with cropping or zero-padding */
323     if (height < height_16)
324     {
325         jlimit = height;
326     }
327     else
328     {
329         jlimit = height_16;
330     }
331 
332     if (width < width_16)
333     {
334         ilimit = width >> 1;
335     }
336     else
337     {
338         ilimit = width_16 >> 1;
339     }
340 
341     if (iBottomUp == 1)
342     {
343         inputRGB += (jlimit - 1) * (width >> 1) ; // move to last row
344         adjust = -adjust;
345     }
346 
347     width = width_16 - width;
348 
349 
350     for (j = 0; j < jlimit; j++)
351     {
352 
353         for (i = 0; i < ilimit; i += 4)
354         {
355             pixels =  inputRGB[i];
356             temp = (827 * (pixels & 0x000F000F) + 2435 * ((pixels & 0x0F000F00) >> 8));
357             yuv_value = (y_tab[((temp&0x0FFFF)>> 9) + (pixels & 0x000000F0)]    |
358                          (y_tab[(temp         >>25) + ((pixels & 0x00F00000)>>16)] << 8));
359 
360             pixels =  inputRGB[i+1];
361             temp = (827 * (pixels & 0x000F000F) + 2435 * ((pixels & 0x0F000F00) >> 8));
362             *tempY++ = (yuv_value                                                         |
363                         (y_tab[((temp&0x0FFFF)>> 9) + (pixels & 0x000000F0)]     |
364                          (y_tab[(temp         >>25) + ((pixels & 0x00F00000)>>16)] << 8)) << 16);
365 
366             pixels =  inputRGB[i+2];
367             temp = (827 * (pixels & 0x000F000F) + 2435 * ((pixels & 0x0F000F00) >> 8));
368             yuv_value = (y_tab[((temp&0x0FFFF)>> 9) + (pixels & 0x000000F0)]    |
369                          (y_tab[(temp         >>25) + ((pixels & 0x00F00000)>>16)] << 8));
370 
371             pixels =  inputRGB[i+3];
372             temp = (827 * (pixels & 0x000F000F) + 2435 * ((pixels & 0x0F000F00) >> 8));
373             *tempY++ = (yuv_value                                                         |
374                         (y_tab[((temp&0x0FFFF)>> 9) + (pixels & 0x000000F0)]     |
375                          (y_tab[(temp         >>25) + ((pixels & 0x00F00000)>>16)] << 8)) << 16);
376 
377 
378             /* downsampling U, V */
379 
380             pixels_nextRow = inputRGB[i+3+adjust/*(width>>1)*/];
381             G_ds    =  pixels & 0x00F000F0;
382             G_ds   += (pixels_nextRow & 0x00F000F0);
383             G_ds   += (G_ds >> 16);
384 
385             G_ds   -= 2; /* equivalent to adding constant 2<<16 = 131072 */
386 
387             pixels &= 0x0F0F0F0F;
388             pixels += (pixels_nextRow & 0x0F0F0F0F);
389 
390             pixels += (pixels >> 16);
391 
392             B_ds = (pixels & 0x0003F) << 4;
393 
394             R_ds = (pixels & 0x03F00) >> 4;
395 
396             tmp  = B_ds - R_ds;
397 
398             yuv_value1 = cb_tab[(((B_ds-G_ds)<<16) + 19525*tmp)>>18] << 24;
399             yuv_value2 = cr_tab[(((R_ds-G_ds)<<16) -  6640*tmp)>>18] << 24;
400 
401             pixels =  inputRGB[i+2];
402             pixels_nextRow = inputRGB[i+2+adjust/*(width>>1)*/];
403 
404             G_ds    =  pixels & 0x00F000F0;
405             G_ds   += (pixels_nextRow & 0x00F000F0);
406             G_ds   += (G_ds >> 16);
407 
408             G_ds   -= 2; /* equivalent to adding constant 2<<16 = 131072 */
409 
410             pixels &= 0x0F0F0F0F;
411             pixels += (pixels_nextRow & 0x0F0F0F0F);
412 
413             pixels += (pixels >> 16);
414 
415             B_ds = (pixels & 0x0003F) << 4;
416 
417             R_ds = (pixels & 0x03F00) >> 4;
418             tmp  = B_ds - R_ds;
419 
420             yuv_value1 |= cb_tab[(((B_ds-G_ds)<<16) + 19525*tmp)>>18] << 16;
421             yuv_value2 |= cr_tab[(((R_ds-G_ds)<<16) -  6640*tmp)>>18] << 16;
422 
423             pixels =  inputRGB[i+1];
424             pixels_nextRow = inputRGB[i+1+adjust /*(width>>1)*/];
425 
426             G_ds    =  pixels & 0x00F000F0;
427             G_ds   += (pixels_nextRow & 0x00F000F0);
428             G_ds   += (G_ds >> 16);
429 
430             G_ds   -= 2; /* equivalent to adding constant 2<<16 = 131072 */
431 
432             pixels &= 0x0F0F0F0F;
433             pixels += (pixels_nextRow & 0x0F0F0F0F);
434 
435             pixels += (pixels >> 16);
436 
437             B_ds = (pixels & 0x0003F) << 4;
438 
439             R_ds = (pixels & 0x03F00) >> 4;
440             tmp  = B_ds - R_ds;
441 
442 
443             yuv_value1 |= cb_tab[(((B_ds-G_ds)<<16) + 19525*tmp)>>18] << 8;
444             yuv_value2 |= cr_tab[(((R_ds-G_ds)<<16) -  6640*tmp)>>18] << 8;
445 
446             pixels =  inputRGB[i];
447             pixels_nextRow = inputRGB[i+adjust/*(width>>1)*/];
448 
449             G_ds    =  pixels & 0x00F000F0;
450             G_ds   += (pixels_nextRow & 0x00F000F0);
451             G_ds   += (G_ds >> 16);
452 
453             G_ds   -= 2; /* equivalent to adding constant 2<<16 = 131072 */
454 
455             pixels &= 0x0F0F0F0F;
456             pixels += (pixels_nextRow & 0x0F0F0F0F);
457 
458             pixels += (pixels >> 16);
459 
460             B_ds = (pixels & 0x0003F) << 4;
461 
462             R_ds = (pixels & 0x03F00) >> 4;
463             tmp  = B_ds - R_ds;
464 
465             *tempU++ = yuv_value1 | (cb_tab[(((B_ds-G_ds)<<16) + 19525*tmp)>>18]);
466             *tempV++ = yuv_value2 | (cr_tab[(((R_ds-G_ds)<<16) -  6640*tmp)>>18]);
467         }
468 
469         /* do padding if input RGB size(width) is different from the output YUV size(width_16) */
470 
471         if ((width > 0) && j < jlimit - 1)
472         {
473             oscl_memset((uint8 *)tempY, 16/*(*(tempY-1))>>24*/, width);
474             tempY += width >> 2;
475         }
476 
477         if (j++ == (jlimit - 1))
478         {
479             break; /* dealing with a odd height */
480         }
481 
482         if ((width > 0) && j < jlimit - 1)
483         {
484             oscl_memset((uint8 *)tempU, 128/*(*(tempU-1))>>24*/, width >> 1);
485             tempU += width >> 3;
486             oscl_memset((uint8 *)tempV, 128/*(*(tempV-1))>>24*/, width >> 1);
487             tempV += width >> 3;
488         }
489 
490         inputRGB += adjust; /* (160/2 = 80 ) */ /*(width>>1)*/; /* move to the next row */
491 
492         for (i = 0; i < ilimit; i += 4)
493         {
494             pixels =  inputRGB[i];
495             temp = (827 * (pixels & 0x000F000F) + 2435 * ((pixels & 0x0F000F00) >> 8));
496             yuv_value = (y_tab[((temp&0x0FFFF)>> 9) + (pixels & 0x000000F0)]    |
497                          (y_tab[(temp         >>25) + ((pixels & 0x00F00000)>>16)] << 8));
498 
499             pixels =  inputRGB[i+1];
500             temp = (827 * (pixels & 0x000F000F) + 2435 * ((pixels & 0x0F000F00) >> 8));
501             *tempY++ = (yuv_value                                                         |
502                         (y_tab[((temp&0x0FFFF)>> 9) + (pixels & 0x000000F0)]     |
503                          (y_tab[(temp         >>25) + ((pixels & 0x00F00000)>>16)] << 8)) << 16);
504 
505             pixels =  inputRGB[i+2];
506             temp = (827 * (pixels & 0x000F000F) + 2435 * ((pixels & 0x0F000F00) >> 8));
507             yuv_value = (y_tab[((temp&0x0FFFF)>> 9) + (pixels & 0x000000F0)]    |
508                          (y_tab[(temp         >>25) + ((pixels & 0x00F00000)>>16)] << 8));
509 
510             pixels =  inputRGB[i+3];
511             temp = (827 * (pixels & 0x000F000F) + 2435 * ((pixels & 0x0F000F00) >> 8));
512             *tempY++ = (yuv_value                                                         |
513                         (y_tab[((temp&0x0FFFF)>> 9) + (pixels & 0x000000F0)]     |
514                          (y_tab[(temp         >>25) + ((pixels & 0x00F00000)>>16)] << 8)) << 16);
515 
516         }
517 
518         /* do padding if input RGB size(width) is different from the output YUV size(width_16) */
519         if ((width > 0) && j < jlimit - 1)
520         {
521             oscl_memset((uint8 *)tempY, 16/*(*(tempY-1))>>24*/, width);
522             tempY += width >> 2;
523         }
524 
525         inputRGB += adjust; /* (160/2 = 80 ) */ /*(width>>1)*/; /* move to the next row */
526 
527     } /* for(j=0; j<jlimit; j++)*/
528 
529     return 1;
530 }
531