1 /*
2  *
3  * Copyright 2012 Samsung Electronics S.LSI Co. LTD
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /*
19  * @file    swconvertor.c
20  *
21  * @brief   SEC_OMX specific define. It support MFC 6.x tiled.
22  *
23  * @author  ShinWon Lee (shinwon.lee@samsung.com)
24  *
25  * @version 1.0
26  *
27  * @history
28  *   2012.02.01 : Create
29  */
30 
31 #include "stdio.h"
32 #include "stdlib.h"
33 #include "swconverter.h"
34 
35 /* 2D Configurable tiled memory access (TM)
36  * Return the linear address from tiled position (x, y) */
Tile2D_To_Linear(unsigned int width,unsigned int height,unsigned int xpos,unsigned int ypos,int crFlag)37 unsigned int Tile2D_To_Linear(
38     unsigned int width,
39     unsigned int height,
40     unsigned int xpos,
41     unsigned int ypos,
42     int crFlag)
43 {
44     int  tileNumX;
45     int  tileX, tileY;
46     int  tileAddr;
47     int  offset;
48     int  addr;
49 
50     width = ((width + 15) / 16) * 16;
51     tileNumX = width / 16;
52 
53     /* crFlag - 0: Y plane, 1: CbCr plane */
54     if (crFlag == 0) {
55         tileX = xpos / 16;
56         tileY = ypos / 16;
57         tileAddr = tileY * tileNumX + tileX;
58         offset = (ypos & 15) * 16 + (xpos & 15);
59         addr = (tileAddr << 8) | offset;
60     } else {
61         tileX = xpos / 16;
62         tileY = ypos / 8;
63         tileAddr = tileY * tileNumX + tileX;
64         offset = (ypos & 7) * 16 + (xpos & 15);
65         addr = (tileAddr << 7) | offset;
66     }
67 
68     return addr;
69 }
70 
71 /*
72  * De-interleaves src to dest1, dest2
73  *
74  * @param dest1
75  *   Address of de-interleaved data[out]
76  *
77  * @param dest2
78  *   Address of de-interleaved data[out]
79  *
80  * @param src
81  *   Address of interleaved data[in]
82  *
83  * @param src_size
84  *   Size of interleaved data[in]
85  */
csc_deinterleave_memcpy(unsigned char * dest1,unsigned char * dest2,unsigned char * src,unsigned int src_size)86 void csc_deinterleave_memcpy(
87     unsigned char *dest1,
88     unsigned char *dest2,
89     unsigned char *src,
90     unsigned int src_size)
91 {
92     unsigned int i = 0;
93     for(i=0; i<src_size/2; i++) {
94         dest1[i] = src[i*2];
95         dest2[i] = src[i*2+1];
96     }
97 }
98 
99 /*
100  * Interleaves src1, src2 to dest
101  *
102  * @param dest
103  *   Address of interleaved data[out]
104  *
105  * @param src1
106  *   Address of de-interleaved data[in]
107  *
108  * @param src2
109  *   Address of de-interleaved data[in]
110  *
111  * @param src_size
112  *   Size of de-interleaved data[in]
113  */
csc_interleave_memcpy(unsigned char * dest,unsigned char * src1,unsigned char * src2,unsigned int src_size)114 void csc_interleave_memcpy(
115     unsigned char *dest,
116     unsigned char *src1,
117     unsigned char *src2,
118     unsigned int src_size)
119 {
120     unsigned int i = 0;
121     for(i=0; i<src_size; i++) {
122         dest[i*2] = src1[i];
123         dest[i*2+1] = src2[i];
124     }
125 }
126 
127 /*
128  * Converts tiled data to linear for mfc 6.x tiled
129  * 1. y of nv12t to y of yuv420p
130  * 2. y of nv12t to y of yuv420s
131  *
132  * @param dst
133  *   y address of yuv420[out]
134  *
135  * @param src
136  *   y address of nv12t[in]
137  *
138  * @param yuv420_width
139  *   real width of yuv420[in]
140  *   it should be even
141  *
142  * @param yuv420_height
143  *   real height of yuv420[in]
144  *   it should be even.
145  *
146  */
csc_tiled_to_linear_y(unsigned char * y_dst,unsigned char * y_src,unsigned int width,unsigned int height)147 void csc_tiled_to_linear_y(
148     unsigned char *y_dst,
149     unsigned char *y_src,
150     unsigned int width,
151     unsigned int height)
152 {
153     unsigned int i, j, k;
154     unsigned int aligned_width, aligned_height;
155     unsigned int tiled_width;
156     unsigned int src_offset, dst_offset;
157 
158     aligned_height = height & (~0xF);
159     aligned_width = width & (~0xF);
160     tiled_width = ((width + 15) >> 4) << 4;
161 
162     for (i = 0; i < aligned_height; i = i + 16) {
163         for (j = 0; j<aligned_width; j = j + 16) {
164             src_offset = (tiled_width * i) + (j << 4);
165             dst_offset = width * i + j;
166             for (k = 0; k < 8; k++) {
167                 memcpy(y_dst + dst_offset, y_src + src_offset, 16);
168                 src_offset += 16;
169                 dst_offset += width;
170                 memcpy(y_dst + dst_offset, y_src + src_offset, 16);
171                 src_offset += 16;
172                 dst_offset += width;
173             }
174         }
175         if (aligned_width != width) {
176             src_offset = (tiled_width * i) + (j << 4);
177             dst_offset = width * i + j;
178             for (k = 0; k < 8; k++) {
179                 memcpy(y_dst + dst_offset, y_src + src_offset, width - j);
180                 src_offset += 16;
181                 dst_offset += width;
182                 memcpy(y_dst + dst_offset, y_src + src_offset, width - j);
183                 src_offset += 16;
184                 dst_offset += width;
185             }
186         }
187     }
188 
189     if (aligned_height != height) {
190         for (j = 0; j<aligned_width; j = j + 16) {
191             src_offset = (tiled_width * i) + (j << 4);
192             dst_offset = width * i + j;
193             for (k = 0; k < height - aligned_height; k = k + 2) {
194                 memcpy(y_dst + dst_offset, y_src + src_offset, 16);
195                 src_offset += 16;
196                 dst_offset += width;
197                 memcpy(y_dst + dst_offset, y_src + src_offset, 16);
198                 src_offset += 16;
199                 dst_offset += width;
200             }
201         }
202         if (aligned_width != width) {
203             src_offset = (tiled_width * i) + (j << 4);
204             dst_offset = width * i + j;
205             for (k = 0; k < height - aligned_height; k = k + 2) {
206                 memcpy(y_dst + dst_offset, y_src + src_offset, width - j);
207                 src_offset += 16;
208                 dst_offset += width;
209                 memcpy(y_dst + dst_offset, y_src + src_offset, width - j);
210                 src_offset += 16;
211                 dst_offset += width;
212             }
213         }
214     }
215 }
216 
217 /*
218  * Converts tiled data to linear for mfc 6.x tiled
219  * 1. uv of nv12t to uv of yuv420s
220  *
221  * @param dst
222  *   uv address of yuv420s[out]
223  *
224  * @param src
225  *   uv address of nv12t[in]
226  *
227  * @param yuv420_width
228  *   real width of yuv420s[in]
229  *
230  * @param yuv420_height
231  *   real height of yuv420s[in]
232  *
233  */
csc_tiled_to_linear_uv(unsigned char * uv_dst,unsigned char * uv_src,unsigned int width,unsigned int height)234 void csc_tiled_to_linear_uv(
235     unsigned char *uv_dst,
236     unsigned char *uv_src,
237     unsigned int width,
238     unsigned int height)
239 {
240     unsigned int i, j, k;
241     unsigned int aligned_width, aligned_height;
242     unsigned int tiled_width;
243     unsigned int src_offset, dst_offset;
244 
245     aligned_height = height & (~0x7);
246     aligned_width = width & (~0xF);
247     tiled_width = ((width + 15) >> 4) << 4;
248 
249     for (i = 0; i < aligned_height; i = i + 8) {
250         for (j = 0; j<aligned_width; j = j + 16) {
251             src_offset = (tiled_width * i) + (j << 3);
252             dst_offset = width * i + j;
253             for (k = 0; k < 4; k++) {
254                 memcpy(uv_dst + dst_offset, uv_src + src_offset, 16);
255                 src_offset += 16;
256                 dst_offset += width;
257                 memcpy(uv_dst + dst_offset, uv_src + src_offset, 16);
258                 src_offset += 16;
259                 dst_offset += width;
260             }
261         }
262         if (aligned_width != width) {
263             src_offset = (tiled_width * i) + (j << 3);
264             dst_offset = width * i + j;
265             for (k = 0; k < 4; k++) {
266                 memcpy(uv_dst + dst_offset, uv_src + src_offset, width - j);
267                 src_offset += 16;
268                 dst_offset += width;
269                 memcpy(uv_dst + dst_offset, uv_src + src_offset, width - j);
270                 src_offset += 16;
271                 dst_offset += width;
272             }
273         }
274     }
275 
276     if (aligned_height != height) {
277         for (j = 0; j<aligned_width; j = j + 16) {
278             src_offset = (tiled_width * i) + (j << 3);
279             dst_offset = width * i + j;
280             for (k = 0; k < height - aligned_height; k = k + 1) {
281                 memcpy(uv_dst + dst_offset, uv_src + src_offset, 16);
282                 src_offset += 16;
283                 dst_offset += width;
284             }
285         }
286         if (aligned_width != width) {
287             src_offset = (tiled_width * i) + (j << 3);
288             dst_offset = width * i + j;
289             for (k = 0; k < height - aligned_height; k = k + 1) {
290                 memcpy(uv_dst + dst_offset, uv_src + src_offset, width - j);
291                 src_offset += 16;
292                 dst_offset += width;
293             }
294         }
295     }
296 }
297 
298 /*
299  * Converts tiled data to linear for mfc 6.x tiled
300  * 1. uv of nt12t to uv of yuv420p
301  *
302  * @param u_dst
303  *   u address of yuv420p[out]
304  *
305  * @param v_dst
306  *   v address of yuv420p[out]
307  *
308  * @param uv_src
309  *   uv address of nt12t[in]
310  *
311  * @param yuv420_width
312  *   real width of yuv420p[in]
313  *
314  * @param yuv420_height
315  *   real height of yuv420p[in]
316  */
csc_tiled_to_linear_uv_deinterleave(unsigned char * u_dst,unsigned char * v_dst,unsigned char * uv_src,unsigned int width,unsigned int height)317 void csc_tiled_to_linear_uv_deinterleave(
318     unsigned char *u_dst,
319     unsigned char *v_dst,
320     unsigned char *uv_src,
321     unsigned int width,
322     unsigned int height)
323 {
324     unsigned int i, j, k;
325     unsigned int aligned_width, aligned_height;
326     unsigned int tiled_width;
327     unsigned int src_offset, dst_offset;
328 
329     aligned_height = height & (~0x7);
330     aligned_width = width & (~0xF);
331     tiled_width = ((width + 15) >> 4) << 4;
332 
333     for (i = 0; i < aligned_height; i = i + 8) {
334         for (j = 0; j<aligned_width; j = j + 16) {
335             src_offset = (tiled_width * i) + (j << 3);
336             dst_offset = (width >> 1) * i + (j >> 1);
337             for (k = 0; k < 4; k++) {
338                 csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset,
339                                         uv_src + src_offset, 16);
340                 src_offset += 16;
341                 dst_offset += width >> 1;
342                 csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset,
343                                         uv_src + src_offset, 16);
344                 src_offset += 16;
345                 dst_offset += width >> 1;
346             }
347         }
348         if (aligned_width != width) {
349             src_offset = (tiled_width * i) + (j << 3);
350             dst_offset = (width >> 1) * i + (j >> 1);
351             for (k = 0; k < 4; k++) {
352                 csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset,
353                                         uv_src + src_offset, width - j);
354                 src_offset += 16;
355                 dst_offset += width >> 1;
356                 csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset,
357                                         uv_src + src_offset, width - j);
358                 src_offset += 16;
359                 dst_offset += width >> 1;
360             }
361         }
362     }
363     if (aligned_height != height) {
364         for (j = 0; j<aligned_width; j = j + 16) {
365             src_offset = (tiled_width * i) + (j << 3);
366             dst_offset = (width >> 1) * i + (j >> 1);
367             for (k = 0; k < height - aligned_height; k = k + 1) {
368                 csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset,
369                                         uv_src + src_offset, 16);
370                 src_offset += 16;
371                 dst_offset += width >> 1;
372             }
373         }
374         if (aligned_width != width) {
375             src_offset = (tiled_width * i) + (j << 3);
376             dst_offset = (width >> 1) * i + (j >> 1);
377             for (k = 0; k < height - aligned_height; k = k + 1) {
378                 csc_deinterleave_memcpy(u_dst + dst_offset, v_dst + dst_offset,
379                                         uv_src + src_offset, width - j);
380                 src_offset += 16;
381                 dst_offset += width >> 1;
382             }
383         }
384     }
385 }
386 
387 /*
388  * Converts linear data to tiled
389  * It supports mfc 6.x tiled
390  * 1. y of yuv420 to y of nv12t
391  *
392  * @param dst
393  *   y address of nv12t[out]
394  *
395  * @param src
396  *   y address of yuv420[in]
397  *
398  * @param yuv420_width
399  *   real width of yuv420[in]
400  *   it should be even
401  *
402  * @param yuv420_height
403  *   real height of yuv420[in]
404  *   it should be even.
405  *
406  */
csc_linear_to_tiled_y(unsigned char * y_dst,unsigned char * y_src,unsigned int width,unsigned int height)407 void csc_linear_to_tiled_y(
408     unsigned char *y_dst,
409     unsigned char *y_src,
410     unsigned int width,
411     unsigned int height)
412 {
413 
414 }
415 
416 /*
417  * Converts and interleaves linear data to tiled
418  * It supports mfc 6.x tiled
419  * 1. uv of nv12t to uv of yuv420
420  *
421  * @param dst
422  *   uv address of nv12t[out]
423  *
424  * @param src
425  *   u address of yuv420[in]
426  *
427  * @param src
428  *   v address of yuv420[in]
429  *
430  * @param yuv420_width
431  *   real width of yuv420[in]
432  *
433  * @param yuv420_height
434  *   real height of yuv420[in]
435  *
436  */
csc_linear_to_tiled_uv(unsigned char * uv_dst,unsigned char * u_src,unsigned char * v_src,unsigned int width,unsigned int height)437 void csc_linear_to_tiled_uv(
438     unsigned char *uv_dst,
439     unsigned char *u_src,
440     unsigned char *v_src,
441     unsigned int width,
442     unsigned int height)
443 {
444 
445 }
446 
Tile2D_To_YUV420(unsigned char * Y_plane,unsigned char * Cb_plane,unsigned char * Cr_plane,unsigned int y_addr,unsigned int c_addr,unsigned int width,unsigned int height)447 void Tile2D_To_YUV420(unsigned char *Y_plane, unsigned char *Cb_plane, unsigned char *Cr_plane,
448                         unsigned int y_addr, unsigned int c_addr, unsigned int width, unsigned int height)
449 {
450     int x, y, j, k, l;
451     int out_of_width, actual_width;
452     unsigned int base_addr, data;
453 
454     // y: 0, 16, 32, ...
455     for (y = 0; y < height; y += 16) {
456         // x: 0, 16, 32, ...
457         for (x = 0; x < width; x += 16) {
458             out_of_width = (x + 16) > width ? 1 : 0;
459             base_addr = y_addr + Tile2D_To_Linear(width, height, x, y, 0);
460 
461             for (k = 0; (k < 16) && ((y + k) < height); k++) {
462                 actual_width = out_of_width ? ((width%4)?((width%16) / 4 + 1) : ((width%16) / 4)) : 4;
463                 for (l = 0; l < actual_width; l++) {
464                     data = *((unsigned int*)(base_addr + 16*k + l*4));
465                     for (j = 0; (j < 4) && (x + l*4 + j) < width; j++) {
466                         Y_plane[(y+k)*width + x + l*4 +j] = (data>>(8*j))&0xff;
467                     }
468                 }
469             }
470         }
471     }
472 
473     for (y = 0; y < height/2; y += 8) {
474         for (x = 0; x < width; x += 16) {
475             out_of_width = (x + 16) > width ? 1 : 0;
476             base_addr = c_addr + Tile2D_To_Linear(width, height/2, x, y, 1);
477             for (k = 0; (k < 8) && ((y+k) < height/2); k++) {
478                 actual_width = out_of_width ? ((width%4) ? ((width%16) / 4 + 1) : ((width%16) / 4)) : 4;
479                 for (l = 0; l < actual_width; l++) {
480                     data = *((unsigned int*)(base_addr + 16*k + l*4));
481                     for (j = 0; (j < 2) && (x/2 + l*2 +j) < width/2; j++) {
482                         Cb_plane[(y+k)*width/2 + x/2 + l*2 +j] = (data>> (8*2*j))&0xff;
483                         Cr_plane[(y+k)*width/2 + x/2 + l*2 +j] = (data>>(8*2*j+8))&0xff;
484                     }
485                 }
486             }
487         }
488     }
489 }
490 
491 /*
492  * Converts RGB565 to YUV420P
493  *
494  * @param y_dst
495  *   Y plane address of YUV420P[out]
496  *
497  * @param u_dst
498  *   U plane address of YUV420P[out]
499  *
500  * @param v_dst
501  *   V plane address of YUV420P[out]
502  *
503  * @param rgb_src
504  *   Address of RGB565[in]
505  *
506  * @param width
507  *   Width of RGB565[in]
508  *
509  * @param height
510  *   Height of RGB565[in]
511  */
csc_RGB565_to_YUV420P(unsigned char * y_dst,unsigned char * u_dst,unsigned char * v_dst,unsigned char * rgb_src,int width,int height)512 void csc_RGB565_to_YUV420P(
513     unsigned char *y_dst,
514     unsigned char *u_dst,
515     unsigned char *v_dst,
516     unsigned char *rgb_src,
517     int width,
518     int height)
519 {
520     unsigned int i, j;
521     unsigned int tmp;
522 
523     unsigned int R, G, B;
524     unsigned int Y, U, V;
525 
526     unsigned int offset1 = width * height;
527     unsigned int offset2 = width/2 * height/2;
528 
529     unsigned short int *pSrc = (unsigned short int *)rgb_src;
530 
531     unsigned char *pDstY = (unsigned char *)y_dst;
532     unsigned char *pDstU = (unsigned char *)u_dst;
533     unsigned char *pDstV = (unsigned char *)v_dst;
534 
535     unsigned int yIndex = 0;
536     unsigned int uIndex = 0;
537     unsigned int vIndex = 0;
538 
539     for (j = 0; j < height; j++) {
540         for (i = 0; i < width; i++) {
541             tmp = pSrc[j * width + i];
542 
543             R = (tmp & 0x0000F800) >> 8;
544             G = (tmp & 0x000007E0) >> 3;
545             B = (tmp & 0x0000001F);
546             B = B << 3;
547 
548             Y = ((66 * R) + (129 * G) + (25 * B) + 128);
549             Y = Y >> 8;
550             Y += 16;
551 
552             pDstY[yIndex++] = (unsigned char)Y;
553 
554             if ((j % 2) == 0 && (i % 2) == 0) {
555                 U = ((-38 * R) - (74 * G) + (112 * B) + 128);
556                 U = U >> 8;
557                 U += 128;
558                 V = ((112 * R) - (94 * G) - (18 * B) + 128);
559                 V = V >> 8;
560                 V += 128;
561 
562                 pDstU[uIndex++] = (unsigned char)U;
563                 pDstV[vIndex++] = (unsigned char)V;
564             }
565         }
566     }
567 }
568 
569 /*
570  * Converts RGB565 to YUV420SP
571  *
572  * @param y_dst
573  *   Y plane address of YUV420SP[out]
574  *
575  * @param uv_dst
576  *   UV plane address of YUV420SP[out]
577  *
578  * @param rgb_src
579  *   Address of RGB565[in]
580  *
581  * @param width
582  *   Width of RGB565[in]
583  *
584  * @param height
585  *   Height of RGB565[in]
586  */
csc_RGB565_to_YUV420SP(unsigned char * y_dst,unsigned char * uv_dst,unsigned char * rgb_src,int width,int height)587 void csc_RGB565_to_YUV420SP(
588     unsigned char *y_dst,
589     unsigned char *uv_dst,
590     unsigned char *rgb_src,
591     int width,
592     int height)
593 {
594     unsigned int i, j;
595     unsigned int tmp;
596 
597     unsigned int R, G, B;
598     unsigned int Y, U, V;
599 
600     unsigned int offset = width * height;
601 
602     unsigned short int *pSrc = (unsigned short int *)rgb_src;
603 
604     unsigned char *pDstY = (unsigned char *)y_dst;
605     unsigned char *pDstUV = (unsigned char *)uv_dst;
606 
607     unsigned int yIndex = 0;
608     unsigned int uvIndex = 0;
609 
610     for (j = 0; j < height; j++) {
611         for (i = 0; i < width; i++) {
612             tmp = pSrc[j * width + i];
613 
614             R = (tmp & 0x0000F800) >> 11;
615             R = R * 8;
616             G = (tmp & 0x000007E0) >> 5;
617             G = G * 4;
618             B = (tmp & 0x0000001F);
619             B = B * 8;
620 
621             Y = ((66 * R) + (129 * G) + (25 * B) + 128);
622             Y = Y >> 8;
623             Y += 16;
624 
625             pDstY[yIndex++] = (unsigned char)Y;
626 
627             if ((j % 2) == 0 && (i % 2) == 0) {
628                 U = ((-38 * R) - (74 * G) + (112 * B) + 128);
629                 U = U >> 8;
630                 U += 128;
631                 V = ((112 * R) - (94 * G) - (18 * B) + 128);
632                 V = V >> 8;
633                 V += 128;
634 
635                 pDstUV[uvIndex++] = (unsigned char)U;
636                 pDstUV[uvIndex++] = (unsigned char)V;
637             }
638         }
639     }
640 }
641 
642 /*
643  * Converts RGB8888 to YUV420P
644  *
645  * @param y_dst
646  *   Y plane address of YUV420P[out]
647  *
648  * @param u_dst
649  *   U plane address of YUV420P[out]
650  *
651  * @param v_dst
652  *   V plane address of YUV420P[out]
653  *
654  * @param rgb_src
655  *   Address of ARGB8888[in]
656  *
657  * @param width
658  *   Width of ARGB8888[in]
659  *
660  * @param height
661  *   Height of ARGB8888[in]
662  */
csc_ARGB8888_to_YUV420P(unsigned char * y_dst,unsigned char * u_dst,unsigned char * v_dst,unsigned char * rgb_src,unsigned int width,unsigned int height)663 void csc_ARGB8888_to_YUV420P(
664     unsigned char *y_dst,
665     unsigned char *u_dst,
666     unsigned char *v_dst,
667     unsigned char *rgb_src,
668     unsigned int width,
669     unsigned int height)
670 {
671     unsigned int i, j;
672     unsigned int tmp;
673 
674     unsigned int R, G, B;
675     unsigned int Y, U, V;
676 
677     unsigned int offset1 = width * height;
678     unsigned int offset2 = width/2 * height/2;
679 
680     unsigned int *pSrc = (unsigned int *)rgb_src;
681 
682     unsigned char *pDstY = (unsigned char *)y_dst;
683     unsigned char *pDstU = (unsigned char *)u_dst;
684     unsigned char *pDstV = (unsigned char *)v_dst;
685 
686     unsigned int yIndex = 0;
687     unsigned int uIndex = 0;
688     unsigned int vIndex = 0;
689 
690     for (j = 0; j < height; j++) {
691         for (i = 0; i < width; i++) {
692             tmp = pSrc[j * width + i];
693 
694             R = (tmp & 0x00FF0000) >> 16;
695             G = (tmp & 0x0000FF00) >> 8;
696             B = (tmp & 0x000000FF);
697 
698             Y = ((66 * R) + (129 * G) + (25 * B) + 128);
699             Y = Y >> 8;
700             Y += 16;
701 
702             pDstY[yIndex++] = (unsigned char)Y;
703 
704             if ((j % 2) == 0 && (i % 2) == 0) {
705                 U = ((-38 * R) - (74 * G) + (112 * B) + 128);
706                 U = U >> 8;
707                 U += 128;
708                 V = ((112 * R) - (94 * G) - (18 * B) + 128);
709                 V = V >> 8;
710                 V += 128;
711 
712                 pDstU[uIndex++] = (unsigned char)U;
713                 pDstV[vIndex++] = (unsigned char)V;
714             }
715         }
716     }
717 }
718 
719 
720 /*
721  * Converts ARGB8888 to YUV420S
722  *
723  * @param y_dst
724  *   Y plane address of YUV420S[out]
725  *
726  * @param uv_dst
727  *   UV plane address of YUV420S[out]
728  *
729  * @param rgb_src
730  *   Address of ARGB8888[in]
731  *
732  * @param width
733  *   Width of ARGB8888[in]
734  *
735  * @param height
736  *   Height of ARGB8888[in]
737  */
csc_ARGB8888_to_YUV420SP(unsigned char * y_dst,unsigned char * uv_dst,unsigned char * rgb_src,unsigned int width,unsigned int height)738 void csc_ARGB8888_to_YUV420SP(
739     unsigned char *y_dst,
740     unsigned char *uv_dst,
741     unsigned char *rgb_src,
742     unsigned int width,
743     unsigned int height)
744 {
745     unsigned int i, j;
746     unsigned int tmp;
747 
748     unsigned int R, G, B;
749     unsigned int Y, U, V;
750 
751     unsigned int offset = width * height;
752 
753     unsigned int *pSrc = (unsigned int *)rgb_src;
754 
755     unsigned char *pDstY = (unsigned char *)y_dst;
756     unsigned char *pDstUV = (unsigned char *)uv_dst;
757 
758     unsigned int yIndex = 0;
759     unsigned int uvIndex = 0;
760 
761     for (j = 0; j < height; j++) {
762         for (i = 0; i < width; i++) {
763             tmp = pSrc[j * width + i];
764 
765             R = (tmp & 0x00FF0000) >> 16;
766             G = (tmp & 0x0000FF00) >> 8;
767             B = (tmp & 0x000000FF);
768 
769             Y = ((66 * R) + (129 * G) + (25 * B) + 128);
770             Y = Y >> 8;
771             Y += 16;
772 
773             pDstY[yIndex++] = (unsigned char)Y;
774 
775             if ((j % 2) == 0 && (i % 2) == 0) {
776                 U = ((-38 * R) - (74 * G) + (112 * B) + 128);
777                 U = U >> 8;
778                 U += 128;
779                 V = ((112 * R) - (94 * G) - (18 * B) + 128);
780                 V = V >> 8;
781                 V += 128;
782 
783                 pDstUV[uvIndex++] = (unsigned char)U;
784                 pDstUV[uvIndex++] = (unsigned char)V;
785             }
786         }
787     }
788 }