Commit | Line | Data |
---|---|---|
29900661 HV |
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 | ||
d7493e51 HV |
35 | If the height is not a multiple of 32 lines, then the captured video is |
36 | missing macroblocks at the end and is unusable. So the height must be a | |
37 | multiple of 32. | |
38 | ||
29900661 HV |
39 | -------------------------------------------------------------------------- |
40 | ||
41 | #include <stdio.h> | |
42 | #include <stdlib.h> | |
43 | #include <string.h> | |
44 | ||
45 | static unsigned char frame[576*720*3/2]; | |
46 | static unsigned char framey[576*720]; | |
47 | static unsigned char frameu[576*720 / 4]; | |
48 | static unsigned char framev[576*720 / 4]; | |
49 | ||
50 | static void de_macro_y(unsigned char* dst, unsigned char *src, int dstride, int w, int h) | |
51 | { | |
52 | unsigned int y, x, i; | |
53 | ||
54 | // descramble Y plane | |
55 | // dstride = 720 = w | |
56 | // The Y plane is divided into blocks of 16x16 pixels | |
57 | // Each block in transmitted in turn, line-by-line. | |
58 | for (y = 0; y < h; y += 16) { | |
59 | for (x = 0; x < w; x += 16) { | |
60 | for (i = 0; i < 16; i++) { | |
61 | memcpy(dst + x + (y + i) * dstride, src, 16); | |
62 | src += 16; | |
63 | } | |
64 | } | |
65 | } | |
66 | } | |
67 | ||
68 | static void de_macro_uv(unsigned char *dstu, unsigned char *dstv, unsigned char *src, int dstride, int w, int h) | |
69 | { | |
70 | unsigned int y, x, i; | |
71 | ||
72 | // descramble U/V plane | |
73 | // dstride = 720 / 2 = w | |
74 | // The U/V values are interlaced (UVUV...). | |
75 | // Again, the UV plane is divided into blocks of 16x16 UV values. | |
76 | // Each block in transmitted in turn, line-by-line. | |
77 | for (y = 0; y < h; y += 16) { | |
78 | for (x = 0; x < w; x += 8) { | |
79 | for (i = 0; i < 16; i++) { | |
80 | int idx = x + (y + i) * dstride; | |
81 | ||
82 | dstu[idx+0] = src[0]; dstv[idx+0] = src[1]; | |
83 | dstu[idx+1] = src[2]; dstv[idx+1] = src[3]; | |
84 | dstu[idx+2] = src[4]; dstv[idx+2] = src[5]; | |
85 | dstu[idx+3] = src[6]; dstv[idx+3] = src[7]; | |
86 | dstu[idx+4] = src[8]; dstv[idx+4] = src[9]; | |
87 | dstu[idx+5] = src[10]; dstv[idx+5] = src[11]; | |
88 | dstu[idx+6] = src[12]; dstv[idx+6] = src[13]; | |
89 | dstu[idx+7] = src[14]; dstv[idx+7] = src[15]; | |
90 | src += 16; | |
91 | } | |
92 | } | |
93 | } | |
94 | } | |
95 | ||
96 | /*************************************************************************/ | |
97 | int main(int argc, char **argv) | |
98 | { | |
99 | FILE *fin; | |
100 | int i; | |
101 | ||
102 | if (argc == 1) fin = stdin; | |
103 | else fin = fopen(argv[1], "r"); | |
104 | ||
105 | if (fin == NULL) { | |
106 | fprintf(stderr, "cannot open input\n"); | |
107 | exit(-1); | |
108 | } | |
109 | while (fread(frame, sizeof(frame), 1, fin) == 1) { | |
110 | de_macro_y(framey, frame, 720, 720, 576); | |
111 | de_macro_uv(frameu, framev, frame + 720 * 576, 720 / 2, 720 / 2, 576 / 2); | |
112 | fwrite(framey, sizeof(framey), 1, stdout); | |
113 | fwrite(framev, sizeof(framev), 1, stdout); | |
114 | fwrite(frameu, sizeof(frameu), 1, stdout); | |
115 | } | |
116 | fclose(fin); | |
117 | return 0; | |
118 | } | |
119 | ||
120 | -------------------------------------------------------------------------- |