mirror of
				https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
				synced 2025-10-31 06:18:54 +00:00 
			
		
		
		
	 d7493e518f
			
		
	
	
		d7493e518f
		
	
	
	
	
		
			
			Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
		
			
				
	
	
		
			121 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| The cx23416 can produce (and the cx23415 can also read) raw YUV output. The
 | |
| format of a YUV frame is specific to this chip and is called HM12. 'HM' stands
 | |
| for 'Hauppauge Macroblock', which is a misnomer as 'Conexant Macroblock' would
 | |
| be more accurate.
 | |
| 
 | |
| The format is YUV 4:2:0 which uses 1 Y byte per pixel and 1 U and V byte per
 | |
| four pixels.
 | |
| 
 | |
| The data is encoded as two macroblock planes, the first containing the Y
 | |
| values, the second containing UV macroblocks.
 | |
| 
 | |
| The Y plane is divided into blocks of 16x16 pixels from left to right
 | |
| and from top to bottom. Each block is transmitted in turn, line-by-line.
 | |
| 
 | |
| So the first 16 bytes are the first line of the top-left block, the
 | |
| second 16 bytes are the second line of the top-left block, etc. After
 | |
| transmitting this block the first line of the block on the right to the
 | |
| first block is transmitted, etc.
 | |
| 
 | |
| The UV plane is divided into blocks of 16x8 UV values going from left
 | |
| to right, top to bottom. Each block is transmitted in turn, line-by-line.
 | |
| 
 | |
| So the first 16 bytes are the first line of the top-left block and
 | |
| contain 8 UV value pairs (16 bytes in total). The second 16 bytes are the
 | |
| second line of 8 UV pairs of the top-left block, etc. After transmitting
 | |
| this block the first line of the block on the right to the first block is
 | |
| transmitted, etc.
 | |
| 
 | |
| The code below is given as an example on how to convert HM12 to separate
 | |
| Y, U and V planes. This code assumes frames of 720x576 (PAL) pixels.
 | |
| 
 | |
| The width of a frame is always 720 pixels, regardless of the actual specified
 | |
| width.
 | |
| 
 | |
| If the height is not a multiple of 32 lines, then the captured video is
 | |
| missing macroblocks at the end and is unusable. So the height must be a
 | |
| multiple of 32.
 | |
| 
 | |
| --------------------------------------------------------------------------
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| 
 | |
| static unsigned char frame[576*720*3/2];
 | |
| static unsigned char framey[576*720];
 | |
| static unsigned char frameu[576*720 / 4];
 | |
| static unsigned char framev[576*720 / 4];
 | |
| 
 | |
| static void de_macro_y(unsigned char* dst, unsigned char *src, int dstride, int w, int h)
 | |
| {
 | |
|     unsigned int y, x, i;
 | |
| 
 | |
|     // descramble Y plane
 | |
|     // dstride = 720 = w
 | |
|     // The Y plane is divided into blocks of 16x16 pixels
 | |
|     // Each block in transmitted in turn, line-by-line.
 | |
|     for (y = 0; y < h; y += 16) {
 | |
| 	for (x = 0; x < w; x += 16) {
 | |
| 	    for (i = 0; i < 16; i++) {
 | |
| 		memcpy(dst + x + (y + i) * dstride, src, 16);
 | |
| 		src += 16;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void de_macro_uv(unsigned char *dstu, unsigned char *dstv, unsigned char *src, int dstride, int w, int h)
 | |
| {
 | |
|     unsigned int y, x, i;
 | |
| 
 | |
|     // descramble U/V plane
 | |
|     // dstride = 720 / 2 = w
 | |
|     // The U/V values are interlaced (UVUV...).
 | |
|     // Again, the UV plane is divided into blocks of 16x16 UV values.
 | |
|     // Each block in transmitted in turn, line-by-line.
 | |
|     for (y = 0; y < h; y += 16) {
 | |
| 	for (x = 0; x < w; x += 8) {
 | |
| 	    for (i = 0; i < 16; i++) {
 | |
| 		int idx = x + (y + i) * dstride;
 | |
| 
 | |
| 		dstu[idx+0] = src[0];  dstv[idx+0] = src[1];
 | |
| 		dstu[idx+1] = src[2];  dstv[idx+1] = src[3];
 | |
| 		dstu[idx+2] = src[4];  dstv[idx+2] = src[5];
 | |
| 		dstu[idx+3] = src[6];  dstv[idx+3] = src[7];
 | |
| 		dstu[idx+4] = src[8];  dstv[idx+4] = src[9];
 | |
| 		dstu[idx+5] = src[10]; dstv[idx+5] = src[11];
 | |
| 		dstu[idx+6] = src[12]; dstv[idx+6] = src[13];
 | |
| 		dstu[idx+7] = src[14]; dstv[idx+7] = src[15];
 | |
| 		src += 16;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*************************************************************************/
 | |
| int main(int argc, char **argv)
 | |
| {
 | |
|     FILE *fin;
 | |
|     int i;
 | |
| 
 | |
|     if (argc == 1) fin = stdin;
 | |
|     else fin = fopen(argv[1], "r");
 | |
| 
 | |
|     if (fin == NULL) {
 | |
| 	fprintf(stderr, "cannot open input\n");
 | |
| 	exit(-1);
 | |
|     }
 | |
|     while (fread(frame, sizeof(frame), 1, fin) == 1) {
 | |
| 	de_macro_y(framey, frame, 720, 720, 576);
 | |
| 	de_macro_uv(frameu, framev, frame + 720 * 576, 720 / 2, 720 / 2, 576 / 2);
 | |
| 	fwrite(framey, sizeof(framey), 1, stdout);
 | |
| 	fwrite(framev, sizeof(framev), 1, stdout);
 | |
| 	fwrite(frameu, sizeof(frameu), 1, stdout);
 | |
|     }
 | |
|     fclose(fin);
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| --------------------------------------------------------------------------
 |