Hans Verkuil | 2990066 | 2006-08-26 05:00:12 -0300 | [diff] [blame] | 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 | -------------------------------------------------------------------------- |