1The cx23416 can produce (and the cx23415 can also read) raw YUV output. The 2format of a YUV frame is specific to this chip and is called HM12. 'HM' stands 3for 'Hauppauge Macroblock', which is a misnomer as 'Conexant Macroblock' would 4be more accurate. 5 6The format is YUV 4:2:0 which uses 1 Y byte per pixel and 1 U and V byte per 7four pixels. 8 9The data is encoded as two macroblock planes, the first containing the Y 10values, the second containing UV macroblocks. 11 12The Y plane is divided into blocks of 16x16 pixels from left to right 13and from top to bottom. Each block is transmitted in turn, line-by-line. 14 15So the first 16 bytes are the first line of the top-left block, the 16second 16 bytes are the second line of the top-left block, etc. After 17transmitting this block the first line of the block on the right to the 18first block is transmitted, etc. 19 20The UV plane is divided into blocks of 16x8 UV values going from left 21to right, top to bottom. Each block is transmitted in turn, line-by-line. 22 23So the first 16 bytes are the first line of the top-left block and 24contain 8 UV value pairs (16 bytes in total). The second 16 bytes are the 25second line of 8 UV pairs of the top-left block, etc. After transmitting 26this block the first line of the block on the right to the first block is 27transmitted, etc. 28 29The code below is given as an example on how to convert HM12 to separate 30Y, U and V planes. This code assumes frames of 720x576 (PAL) pixels. 31 32The width of a frame is always 720 pixels, regardless of the actual specified 33width. 34 35-------------------------------------------------------------------------- 36 37#include <stdio.h> 38#include <stdlib.h> 39#include <string.h> 40 41static unsigned char frame[576*720*3/2]; 42static unsigned char framey[576*720]; 43static unsigned char frameu[576*720 / 4]; 44static unsigned char framev[576*720 / 4]; 45 46static 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 64static 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/*************************************************************************/ 93int 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-------------------------------------------------------------------------- 117