File: sn9c20x.c

package info (click to toggle)
v4l-utils 1.32.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 12,276 kB
  • sloc: ansic: 85,528; cpp: 69,473; perl: 11,915; sh: 1,333; python: 883; php: 119; makefile: 39
file content (129 lines) | stat: -rw-r--r-- 4,253 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
 * Sonix SN9C20X decoder
 * Vasily Khoruzhick, (C) 2008-2009
 * Algorithm based on Java code written by Jens on microdia google group
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335  USA
 *
 * Note this code was originally licensed under the GNU GPL instead of the
 * GNU LGPL, its license has been changed by its author.
 */

#include "libv4lconvert-priv.h"

#define DO_SANITY_CHECKS 0

static const int Y_coords_624x[128][2] = {
	{ 0,  0}, { 1,  0}, { 2,  0}, { 3,  0}, { 4,  0}, { 5,  0}, { 6,  0}, { 7,  0},
	{ 0,  1}, { 1,  1}, { 2,  1}, { 3,  1}, { 4,  1}, { 5,  1}, { 6,  1}, { 7,  1},
	{ 0,  2}, { 1,  2}, { 2,  2}, { 3,  2}, { 4,  2}, { 5,  2}, { 6,  2}, { 7,  2},
	{ 0,  3}, { 1,  3}, { 2,  3}, { 3,  3}, { 4,  3}, { 5,  3}, { 6,  3}, { 7,  3},

	{ 0,  4}, { 1,  4}, { 2,  4}, { 3,  4}, { 4,  4}, { 5,  4}, { 6,  4}, { 7,  4},
	{ 0,  5}, { 1,  5}, { 2,  5}, { 3,  5}, { 4,  5}, { 5,  5}, { 6,  5}, { 7,  5},
	{ 0,  6}, { 1,  6}, { 2,  6}, { 3,  6}, { 4,  6}, { 5,  6}, { 6,  6}, { 7,  6},
	{ 0,  7}, { 1,  7}, { 2,  7}, { 3,  7}, { 4,  7}, { 5,  7}, { 6,  7}, { 7,  7},

	{ 8,  0}, { 9,  0}, {10,  0}, {11,  0}, {12,  0}, {13,  0}, {14,  0}, {15,  0},
	{ 8,  1}, { 9,  1}, {10,  1}, {11,  1}, {12,  1}, {13,  1}, {14,  1}, {15,  1},
	{ 8,  2}, { 9,  2}, {10,  2}, {11,  2}, {12,  2}, {13,  2}, {14,  2}, {15,  2},
	{ 8,  3}, { 9,  3}, {10,  3}, {11,  3}, {12,  3}, {13,  3}, {14,  3}, {15,  3},

	{ 8,  4}, { 9,  4}, {10,  4}, {11,  4}, {12,  4}, {13,  4}, {14,  4}, {15,  4},
	{ 8,  5}, { 9,  5}, {10,  5}, {11,  5}, {12,  5}, {13,  5}, {14,  5}, {15,  5},
	{ 8,  6}, { 9,  6}, {10,  6}, {11,  6}, {12,  6}, {13,  6}, {14,  6}, {15,  6},
	{ 8,  7}, { 9,  7}, {10,  7}, {11,  7}, {12,  7}, {13,  7}, {14,  7}, {15,  7}
};

static void do_write_u(const unsigned char *buf, unsigned char *ptr,
		int i, int j)
{
	*ptr = buf[i + 128 + j];
}

static void do_write_v(const unsigned char *buf, unsigned char *ptr,
		int i, int j)
{
	*ptr = buf[i + 160 + j];
}

void v4lconvert_sn9c20x_to_yuv420(const unsigned char *raw, unsigned char *i420,
		int width, int height, int yvu)
{
	int i = 0, x = 0, y = 0, j, relX, relY, x_div2, y_div2;
	const unsigned char *buf = raw;
	unsigned char *ptr;
	int frame_size = width * height;
	int frame_size_div2 = frame_size >> 1;
	int frame_size_div4 = frame_size >> 2;
	int width_div2 = width >> 1;
#if (DO_SANITY_CHECKS == 1)
	int height_div2 = height >> 1;
#endif
	void (*do_write_uv1)(const unsigned char *buf, unsigned char *ptr, int i,
			int j) = NULL;
	void (*do_write_uv2)(const unsigned char *buf, unsigned char *ptr, int i,
			int j) = NULL;

	if (yvu) {
		do_write_uv1 = do_write_v;
		do_write_uv2 = do_write_u;
	} else {
		do_write_uv1 = do_write_u;
		do_write_uv2 = do_write_v;
	}

	while (i < (frame_size + frame_size_div2)) {
		for (j = 0; j < 128; j++) {
			relX = x + Y_coords_624x[j][0];
			relY = y + Y_coords_624x[j][1];

#if (DO_SANITY_CHECKS == 1)
			if ((relX < width) && (relY < height)) {
#endif
				ptr = i420 + relY * width + relX;
				*ptr = buf[i + j];
#if (DO_SANITY_CHECKS == 1)
			}
#endif

		}
		x_div2 = x >> 1;
		y_div2 = y >> 1;
		for (j = 0; j < 32; j++) {
			relX = (x_div2) + (j & 0x07);
			relY = (y_div2) + (j >> 3);

#if (DO_SANITY_CHECKS == 1)
			if ((relX < width_div2) && (relY < height_div2)) {
#endif
				ptr = i420 + frame_size +
					relY * width_div2 + relX;
				do_write_uv1(buf, ptr, i, j);
				ptr += frame_size_div4;
				do_write_uv2(buf, ptr, i, j);
#if (DO_SANITY_CHECKS == 1)
			}
#endif
		}

		i += 192;
		x += 16;
		if (x >= width) {
			x = 0;
			y += 8;
		}
	}
}