| 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 | -------------------------------------------------------------------------- |