⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgmtoy4m.c

📁 Motion JPEG编解码器源代码
💻 C
字号:
/* * $Id: pgmtoy4m.c,v 1.15 2004/05/07 04:19:45 sms00 Exp $ * * pgmtoy4m converts the PGM output of "mpeg2dec -o pgmpipe" to YUV4MPEG2 on * stdout. * * Note: mpeg2dec uses a rather interesting variation  of the PGM format - the * output is not actually traditional "Grey Maps" but rather a catenation of  * the Y'CrCb planes.  From the libmpeg2 project's video_out_pgm.c: * * Layout of the Y, U, and V buffers in our pgm image * *      YY        YY        YY * 420: YY   422: YY   444: YY *      UV        UV        UUVV *                UV        UUVV * * The PGM type is P5 ("raw") and the number of rows is really the * total of the Y', Cb and Cr heights.   The Cb and Cr data is "joined" * together. * * NOTE: You MAY need to know the field order (top or bottom field first), *	sample aspect ratio and frame rate because the PGM format makes *	none of that information available!  There are defaults provided *	that hopefully will do the right thing in the common cases. * *	The defaults provided are: 4:2:0, top field first, NTSC rate of  *	30000/1001 frames/second, and a sample aspect of 10:11. * *      If the incoming chroma space is not 4:2:0 then you MUST specify the *	"-x chroma_tag" option or chaos and/or a program crash will occur.*/#if defined(HAVE_CONFIG_H)#include "config.h"#endif#include <stdio.h>#include <sys/types.h>#include <ctype.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include "yuv4mpeg.h"static	void	usage(char *progname);static	void	chroma_usage(char *progname);static	int	getint(int);#define	P5MAGIC	(('P' * 256) + '5')static intgetmagicnumber(int fd)	{	char	ch1 = -1, ch2 = -1;	read(fd, &ch1, 1);	read(fd, &ch2, 1);	return((ch1 * 256) + ch2);	}static intpiperead(int fd, u_char *buf, int len)	{	int n = 0;	int r = 0;	while	(r < len)		{		n = read (fd, buf + r, len - r);		if	(n <= 0)			return(r);		r += n;		}	return(r);	}intmain(int argc, char **argv)	{	int	width, height, uvlen, verbose = 1, fdout, fdin, c, i;	int	columns, rows, maxval, magicn, frameno;	int	ss_h, ss_v, chroma_height, chroma_width;	int	chroma_mode = Y4M_UNKNOWN;	u_char	*yuv[3];	char	junkbuffer[16384];	y4m_ratio_t	rate_ratio = y4m_fps_UNKNOWN;	y4m_ratio_t	aspect_ratio = y4m_sar_UNKNOWN;	char	ilace = Y4M_ILACE_TOP_FIRST;	y4m_frame_info_t  oframe;	y4m_stream_info_t ostream;	fdin = fileno(stdin);	fdout = fileno(stdout);	y4m_accept_extensions(1);	opterr = 0;	while	((c = getopt(argc, argv, "i:a:r:hv:x:")) != EOF)		{		switch	(c)			{			case	'i':				switch	(optarg[0])					{					case	'p':						ilace = Y4M_ILACE_NONE;						break;					case	't':						ilace = Y4M_ILACE_TOP_FIRST;						break;					case	'b':						ilace = Y4M_ILACE_BOTTOM_FIRST;						break;					default:						usage(argv[0]);					}				break;			case	'v':				verbose = atoi(optarg);				if	(verbose < 0 || verbose > 3)					mjpeg_error_exit1("Verbosity [0..2]");				break;			case	'a':				i = y4m_parse_ratio(&aspect_ratio, optarg);				if	(i != Y4M_OK)					mjpeg_error_exit1("Invalid aspect: %s",						optarg);				break;			case	'r':				i = y4m_parse_ratio(&rate_ratio, optarg);				if	(i != Y4M_OK)					mjpeg_error_exit1("Invalid rate: %s",						optarg);				break;			case	'x':				chroma_mode = y4m_chroma_parse_keyword(optarg);				if	(chroma_mode == Y4M_UNKNOWN)					{					if	(strcmp(optarg, "help") == 0)						chroma_usage(argv[0]);					mjpeg_error_exit1("bad chroma arg");					}				break;			case	'h':			case	'?':			default:				usage(argv[0]);				/* NOTREACHED */			}		}	if	(chroma_mode == Y4M_UNKNOWN)		chroma_mode = Y4M_CHROMA_420MPEG2;	if	(isatty(fdout))		mjpeg_error_exit1("stdout must not be a terminal");	mjpeg_default_handler_verbosity(verbose);/* * Check that the input stream is really a P5 (rawbits PGM) stream, then if it * is retrieve the "rows" and "columns" (width and height) and the maxval. * The maxval will be 255 if the data was generated from mpeg2dec!*/	magicn = getmagicnumber(fdin);	if	(magicn != P5MAGIC)		mjpeg_error_exit1("Input not P5 PGM data, got %x", magicn);	columns = getint(fdin);	rows = getint(fdin);	maxval = getint(fdin);	mjpeg_log(LOG_INFO, "P5 cols: %d rows: %d maxval: %d", 		columns, rows, maxval);	if	(maxval != 255)		mjpeg_error_exit1("Maxval (%d) != 255, not mpeg2dec output?",			maxval);/* * Put some sanity checks on the sizes - handling up to 4096x4096 should be  * enough for now :)*/	if	(columns < 0 || columns > 4096 || rows < 0 || rows > 4096)		mjpeg_error_exit1("columns (%d) or rows(%d) < 0 or > 4096",			columns, rows);	y4m_init_frame_info(&oframe);	y4m_init_stream_info(&ostream);	y4m_si_set_chroma(&ostream, chroma_mode);	if	(y4m_si_get_plane_count(&ostream) != 3)		mjpeg_error_exit1("Only the 3 plane formats supported");	ss_h = y4m_chroma_ss_x_ratio(chroma_mode).d;	ss_v = y4m_chroma_ss_y_ratio(chroma_mode).d;	width = columns;	height = (rows * ss_v) / (ss_v + 1);	chroma_width = width / ss_h;	chroma_height = height / ss_v;	uvlen = chroma_height * chroma_width;	yuv[0] = malloc(height * width);	yuv[1] = malloc(uvlen);	yuv[2] = malloc(uvlen);	if	(yuv[0] == NULL || yuv[1] == NULL || yuv[2] == NULL)		mjpeg_error_exit1("malloc yuv[]");/* * If the (sample) aspect ratio and frame rate were not specified on the * command line try to intuit the video norm of NTSC or PAL by looking at the * height of the frame.*/	if	(Y4M_RATIO_EQL(aspect_ratio, y4m_sar_UNKNOWN))		{		if	(height == 480 || height == 240)			{			aspect_ratio = y4m_sar_NTSC_CCIR601;			mjpeg_log(LOG_WARN, "sample aspect not specified, using NTSC CCIR601 value based on frame height of %d", height);			}		else if	(height == 576 || height == 288)			{			aspect_ratio = y4m_sar_PAL_CCIR601;			mjpeg_log(LOG_WARN, "sample aspect not specified, using PAL CCIR601 value based on frame height of %d", height);			}		else			{			mjpeg_log(LOG_WARN, "sample aspect not specified and can not be inferred from frame height of %d (leaving sar as unknown", height);			}		}	if	(Y4M_RATIO_EQL(rate_ratio, y4m_fps_UNKNOWN))		{		if	(height == 480 || height == 240)			{			rate_ratio = y4m_fps_NTSC;			mjpeg_log(LOG_WARN, "frame rate not specified, using NTSC value based on frame height of %d", height);			}		else if	(height == 576 || height == 288)			{			rate_ratio = y4m_fps_PAL;			mjpeg_log(LOG_WARN, "frame rate not specified, using PAL value based on frame height of %d", height);			}		else			{			mjpeg_log(LOG_WARN, "frame rate not specified and can not be inferred from frame height of %d (using NTSC value)", height);			rate_ratio = y4m_fps_NTSC;			}		}	y4m_si_set_interlace(&ostream, ilace);	y4m_si_set_framerate(&ostream, rate_ratio);	y4m_si_set_sampleaspect(&ostream, aspect_ratio);	y4m_si_set_width(&ostream, width);	y4m_si_set_height(&ostream, height);	y4m_write_stream_header(fdout, &ostream);/* * Now continue reading P5 frames as long as the magic number appears.  Corrupt * (malformed) input or EOF will terminate the loop.   The columns, rows and * maxval must be read to get to the raw data.  It's probably not worth doing * anything (in fact it's unclear what could be done ;)) with the values  * if they're different from the first header which was used to set the * output stream parameters.*/	frameno = 0;	while	(1)			{		for	(i = 0; i < height; i++)			{			piperead(fdin, yuv[0] + i * width, width);			piperead(fdin, junkbuffer, 2 * chroma_width - width);			}		for	(i = 0; i < chroma_height; i++)			{			piperead(fdin, yuv[1] + i * chroma_width, chroma_width);			piperead(fdin, yuv[2] + i * chroma_width, chroma_width);			}		y4m_write_frame(fdout, &ostream, &oframe, yuv);		magicn = getmagicnumber(fdin);		if	(magicn != P5MAGIC)			{			mjpeg_log(LOG_DEBUG, "frame: %d got magic: %x\n",				frameno, magicn);			break;			}		columns = getint(fdin);		rows = getint(fdin);		maxval = getint(fdin);		frameno++;		mjpeg_log(LOG_DEBUG, "frame: %d P5MAGIC cols: %d rows: %d maxval: %d", frameno, columns, rows, maxval);		}	y4m_fini_frame_info(&oframe);	y4m_fini_stream_info(&ostream);	return 0;	}static voidusage(char *progname)	{	fprintf(stderr, "%s usage: [-v n] [-i t|b|p] [-x chroma] [-a sample aspect] [-r rate]\n",		progname);	fprintf(stderr, "%s\taspect and rate in ratio form: -a  10:11 and -r 30000:1001 or -r 25:1 for example\n", progname);	fprintf(stderr, "%s\t chroma default is 420mpeg2, -x help for list\n",		progname);	exit(0);	}static intgetint(int fd)	{	char	ch;	int	i;	do		{		if	(read(fd, &ch, 1) == -1)			return(-1);		if	(ch == '#')			{			while	(ch != '\n')				{				if	(read(fd, &ch, 1) == -1)					return(-1);				}			}		} while (isspace(ch));	if	(!isdigit(ch))		return(-1);	i = 0;	do		{		i = i * 10 + (ch - '0');		if	(read(fd, &ch, 1) == -1)			break;		} while (isdigit(ch));	return(i);	}void chroma_usage(char *pname)	{	int mode = 0;	const char *keyword;	fprintf(stderr, "%s -x usage: Only the 3 plane formats are actually supported\n",		pname);	for	(mode = 0; (keyword = y4m_chroma_keyword(mode)) != NULL; mode++)		fprintf(stderr, "\t%s - %s\n", keyword, y4m_chroma_description(mode));	exit(1);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -