1 /*
2 * Sonix SN9C20X decoder
3 * Vasily Khoruzhick, (C) 2008-2009
4 * Algorithm based on Java code written by Jens on microdia google group
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
19 *
20 * Note this code was originally licensed under the GNU GPL instead of the
21 * GNU LGPL, its license has been changed by its author.
22 */
23
24 #include "libv4lconvert-priv.h"
25
26 #define DO_SANITY_CHECKS 0
27
28 static const int Y_coords_624x[128][2] = {
29 { 0, 0}, { 1, 0}, { 2, 0}, { 3, 0}, { 4, 0}, { 5, 0}, { 6, 0}, { 7, 0},
30 { 0, 1}, { 1, 1}, { 2, 1}, { 3, 1}, { 4, 1}, { 5, 1}, { 6, 1}, { 7, 1},
31 { 0, 2}, { 1, 2}, { 2, 2}, { 3, 2}, { 4, 2}, { 5, 2}, { 6, 2}, { 7, 2},
32 { 0, 3}, { 1, 3}, { 2, 3}, { 3, 3}, { 4, 3}, { 5, 3}, { 6, 3}, { 7, 3},
33
34 { 0, 4}, { 1, 4}, { 2, 4}, { 3, 4}, { 4, 4}, { 5, 4}, { 6, 4}, { 7, 4},
35 { 0, 5}, { 1, 5}, { 2, 5}, { 3, 5}, { 4, 5}, { 5, 5}, { 6, 5}, { 7, 5},
36 { 0, 6}, { 1, 6}, { 2, 6}, { 3, 6}, { 4, 6}, { 5, 6}, { 6, 6}, { 7, 6},
37 { 0, 7}, { 1, 7}, { 2, 7}, { 3, 7}, { 4, 7}, { 5, 7}, { 6, 7}, { 7, 7},
38
39 { 8, 0}, { 9, 0}, {10, 0}, {11, 0}, {12, 0}, {13, 0}, {14, 0}, {15, 0},
40 { 8, 1}, { 9, 1}, {10, 1}, {11, 1}, {12, 1}, {13, 1}, {14, 1}, {15, 1},
41 { 8, 2}, { 9, 2}, {10, 2}, {11, 2}, {12, 2}, {13, 2}, {14, 2}, {15, 2},
42 { 8, 3}, { 9, 3}, {10, 3}, {11, 3}, {12, 3}, {13, 3}, {14, 3}, {15, 3},
43
44 { 8, 4}, { 9, 4}, {10, 4}, {11, 4}, {12, 4}, {13, 4}, {14, 4}, {15, 4},
45 { 8, 5}, { 9, 5}, {10, 5}, {11, 5}, {12, 5}, {13, 5}, {14, 5}, {15, 5},
46 { 8, 6}, { 9, 6}, {10, 6}, {11, 6}, {12, 6}, {13, 6}, {14, 6}, {15, 6},
47 { 8, 7}, { 9, 7}, {10, 7}, {11, 7}, {12, 7}, {13, 7}, {14, 7}, {15, 7}
48 };
49
do_write_u(const unsigned char * buf,unsigned char * ptr,int i,int j)50 static void do_write_u(const unsigned char *buf, unsigned char *ptr,
51 int i, int j)
52 {
53 *ptr = buf[i + 128 + j];
54 }
55
do_write_v(const unsigned char * buf,unsigned char * ptr,int i,int j)56 static void do_write_v(const unsigned char *buf, unsigned char *ptr,
57 int i, int j)
58 {
59 *ptr = buf[i + 160 + j];
60 }
61
v4lconvert_sn9c20x_to_yuv420(const unsigned char * raw,unsigned char * i420,int width,int height,int yvu)62 void v4lconvert_sn9c20x_to_yuv420(const unsigned char *raw, unsigned char *i420,
63 int width, int height, int yvu)
64 {
65 int i = 0, x = 0, y = 0, j, relX, relY, x_div2, y_div2;
66 const unsigned char *buf = raw;
67 unsigned char *ptr;
68 int frame_size = width * height;
69 int frame_size_div2 = frame_size >> 1;
70 int frame_size_div4 = frame_size >> 2;
71 int width_div2 = width >> 1;
72 #if (DO_SANITY_CHECKS == 1)
73 int height_div2 = height >> 1;
74 #endif
75 void (*do_write_uv1)(const unsigned char *buf, unsigned char *ptr, int i,
76 int j) = NULL;
77 void (*do_write_uv2)(const unsigned char *buf, unsigned char *ptr, int i,
78 int j) = NULL;
79
80 if (yvu) {
81 do_write_uv1 = do_write_v;
82 do_write_uv2 = do_write_u;
83 } else {
84 do_write_uv1 = do_write_u;
85 do_write_uv2 = do_write_v;
86 }
87
88 while (i < (frame_size + frame_size_div2)) {
89 for (j = 0; j < 128; j++) {
90 relX = x + Y_coords_624x[j][0];
91 relY = y + Y_coords_624x[j][1];
92
93 #if (DO_SANITY_CHECKS == 1)
94 if ((relX < width) && (relY < height)) {
95 #endif
96 ptr = i420 + relY * width + relX;
97 *ptr = buf[i + j];
98 #if (DO_SANITY_CHECKS == 1)
99 }
100 #endif
101
102 }
103 x_div2 = x >> 1;
104 y_div2 = y >> 1;
105 for (j = 0; j < 32; j++) {
106 relX = (x_div2) + (j & 0x07);
107 relY = (y_div2) + (j >> 3);
108
109 #if (DO_SANITY_CHECKS == 1)
110 if ((relX < width_div2) && (relY < height_div2)) {
111 #endif
112 ptr = i420 + frame_size +
113 relY * width_div2 + relX;
114 do_write_uv1(buf, ptr, i, j);
115 ptr += frame_size_div4;
116 do_write_uv2(buf, ptr, i, j);
117 #if (DO_SANITY_CHECKS == 1)
118 }
119 #endif
120 }
121
122 i += 192;
123 x += 16;
124 if (x >= width) {
125 x = 0;
126 y += 8;
127 }
128 }
129 }
130