diff options
Diffstat (limited to 'Documentation/video4linux/cx2341x/README.hm12')
-rw-r--r-- | Documentation/video4linux/cx2341x/README.hm12 | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/Documentation/video4linux/cx2341x/README.hm12 b/Documentation/video4linux/cx2341x/README.hm12 new file mode 100644 index 000000000000..0e213ed095e6 --- /dev/null +++ b/Documentation/video4linux/cx2341x/README.hm12 | |||
@@ -0,0 +1,116 @@ | |||
1 | The cx23416 can produce (and the cx23415 can also read) raw YUV output. The | ||
2 | format of a YUV frame is specific to this chip and is called HM12. 'HM' stands | ||
3 | for 'Hauppauge Macroblock', which is a misnomer as 'Conexant Macroblock' would | ||
4 | be more accurate. | ||
5 | |||
6 | The format is YUV 4:2:0 which uses 1 Y byte per pixel and 1 U and V byte per | ||
7 | four pixels. | ||
8 | |||
9 | The data is encoded as two macroblock planes, the first containing the Y | ||
10 | values, the second containing UV macroblocks. | ||
11 | |||
12 | The Y plane is divided into blocks of 16x16 pixels from left to right | ||
13 | and from top to bottom. Each block is transmitted in turn, line-by-line. | ||
14 | |||
15 | So the first 16 bytes are the first line of the top-left block, the | ||
16 | second 16 bytes are the second line of the top-left block, etc. After | ||
17 | transmitting this block the first line of the block on the right to the | ||
18 | first block is transmitted, etc. | ||
19 | |||
20 | The UV plane is divided into blocks of 16x8 UV values going from left | ||
21 | to right, top to bottom. Each block is transmitted in turn, line-by-line. | ||
22 | |||
23 | So the first 16 bytes are the first line of the top-left block and | ||
24 | contain 8 UV value pairs (16 bytes in total). The second 16 bytes are the | ||
25 | second line of 8 UV pairs of the top-left block, etc. After transmitting | ||
26 | this block the first line of the block on the right to the first block is | ||
27 | transmitted, etc. | ||
28 | |||
29 | The code below is given as an example on how to convert HM12 to separate | ||
30 | Y, U and V planes. This code assumes frames of 720x576 (PAL) pixels. | ||
31 | |||
32 | The width of a frame is always 720 pixels, regardless of the actual specified | ||
33 | width. | ||
34 | |||
35 | -------------------------------------------------------------------------- | ||
36 | |||
37 | #include <stdio.h> | ||
38 | #include <stdlib.h> | ||
39 | #include <string.h> | ||
40 | |||
41 | static unsigned char frame[576*720*3/2]; | ||
42 | static unsigned char framey[576*720]; | ||
43 | static unsigned char frameu[576*720 / 4]; | ||
44 | static unsigned char framev[576*720 / 4]; | ||
45 | |||
46 | static void de_macro_y(unsigned char* dst, unsigned char *src, int dstride, int w, int h) | ||
47 | { | ||
48 | unsigned int y, x, i; | ||
49 | |||
50 | // descramble Y plane | ||
51 | // dstride = 720 = w | ||
52 | // The Y plane is divided into blocks of 16x16 pixels | ||
53 | // Each block in transmitted in turn, line-by-line. | ||
54 | for (y = 0; y < h; y += 16) { | ||
55 | for (x = 0; x < w; x += 16) { | ||
56 | for (i = 0; i < 16; i++) { | ||
57 | memcpy(dst + x + (y + i) * dstride, src, 16); | ||
58 | src += 16; | ||
59 | } | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | |||
64 | static void de_macro_uv(unsigned char *dstu, unsigned char *dstv, unsigned char *src, int dstride, int w, int h) | ||
65 | { | ||
66 | unsigned int y, x, i; | ||
67 | |||
68 | // descramble U/V plane | ||
69 | // dstride = 720 / 2 = w | ||
70 | // The U/V values are interlaced (UVUV...). | ||
71 | // Again, the UV plane is divided into blocks of 16x16 UV values. | ||
72 | // Each block in transmitted in turn, line-by-line. | ||
73 | for (y = 0; y < h; y += 16) { | ||
74 | for (x = 0; x < w; x += 8) { | ||
75 | for (i = 0; i < 16; i++) { | ||
76 | int idx = x + (y + i) * dstride; | ||
77 | |||
78 | dstu[idx+0] = src[0]; dstv[idx+0] = src[1]; | ||
79 | dstu[idx+1] = src[2]; dstv[idx+1] = src[3]; | ||
80 | dstu[idx+2] = src[4]; dstv[idx+2] = src[5]; | ||
81 | dstu[idx+3] = src[6]; dstv[idx+3] = src[7]; | ||
82 | dstu[idx+4] = src[8]; dstv[idx+4] = src[9]; | ||
83 | dstu[idx+5] = src[10]; dstv[idx+5] = src[11]; | ||
84 | dstu[idx+6] = src[12]; dstv[idx+6] = src[13]; | ||
85 | dstu[idx+7] = src[14]; dstv[idx+7] = src[15]; | ||
86 | src += 16; | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | } | ||
91 | |||
92 | /*************************************************************************/ | ||
93 | int main(int argc, char **argv) | ||
94 | { | ||
95 | FILE *fin; | ||
96 | int i; | ||
97 | |||
98 | if (argc == 1) fin = stdin; | ||
99 | else fin = fopen(argv[1], "r"); | ||
100 | |||
101 | if (fin == NULL) { | ||
102 | fprintf(stderr, "cannot open input\n"); | ||
103 | exit(-1); | ||
104 | } | ||
105 | while (fread(frame, sizeof(frame), 1, fin) == 1) { | ||
106 | de_macro_y(framey, frame, 720, 720, 576); | ||
107 | de_macro_uv(frameu, framev, frame + 720 * 576, 720 / 2, 720 / 2, 576 / 2); | ||
108 | fwrite(framey, sizeof(framey), 1, stdout); | ||
109 | fwrite(framev, sizeof(framev), 1, stdout); | ||
110 | fwrite(frameu, sizeof(frameu), 1, stdout); | ||
111 | } | ||
112 | fclose(fin); | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | -------------------------------------------------------------------------- | ||