Beispiel #1
0
// Allocate a uint8_t frame
int chromalloc(uint8_t *m[3], y4m_stream_info_t *sinfo)
{

	int fs,cfs;

	fs = y4m_si_get_plane_length(sinfo,0);
	cfs = y4m_si_get_plane_length(sinfo,1);

	// I'm gonna cheat and use this as an initialisation function.

	sic.h = y4m_si_get_plane_height(sinfo,0);
	sic.w = y4m_si_get_plane_width(sinfo,0);
	sic.ch = y4m_si_get_plane_height(sinfo,1);
	sic.cw = y4m_si_get_plane_width(sinfo,1);

	m[0] = (uint8_t *)malloc( fs );
	m[1] = (uint8_t *)malloc( cfs);
	m[2] = (uint8_t *)malloc( cfs);

	if( !m[0] || !m[1] || !m[2]) {
		return -1;
	} else {
		return 0;
	}

}
Beispiel #2
0
//Copy a uint8_t frame
void chromacpy(uint8_t *m[3],uint8_t *n[3],y4m_stream_info_t *sinfo)
{

	int fs,cfs;

	fs = y4m_si_get_plane_length(sinfo,0);
	cfs = y4m_si_get_plane_length(sinfo,1);

	memcpy (m[0],n[0],fs);
	memcpy (m[1],n[1],cfs);
	memcpy (m[2],n[2],cfs);

}
Beispiel #3
0
// set a solid colour for a uint8_t frame
void chromaset(uint8_t *m[3], y4m_stream_info_t  *sinfo, int y, int u, int v )
{

	int fs,cfs;

	fs = y4m_si_get_plane_length(sinfo,0);
	cfs = y4m_si_get_plane_length(sinfo,1);

	memset (m[0],y,fs);
	memset (m[1],u,cfs);
	memset (m[2],v,cfs);

}
Beispiel #4
0
void chromalloc(uint8_t *m[3],y4m_stream_info_t *sinfo)
{
	
	int fs,cfs;

	fs = y4m_si_get_plane_length(sinfo,0);
	cfs = y4m_si_get_plane_length(sinfo,1);

	m[0] = (uint8_t *)malloc( fs );
	m[1] = (uint8_t *)malloc( cfs);
	m[2] = (uint8_t *)malloc( cfs);

}
Beispiel #5
0
int chromalloc(uint8_t *m[3],y4m_stream_info_t *sinfo)
{

	int fs,cfs;

	fs = y4m_si_get_plane_length(sinfo,0);
	cfs = y4m_si_get_plane_length(sinfo,1);

	m[0] = (uint8_t *)malloc( fs );
	m[1] = (uint8_t *)malloc( cfs);
	m[2] = (uint8_t *)malloc( cfs);

	if( !m[0] || !m[1] || !m[2]) {
		return -1;
	} else {
		return 0;
	}

}
Beispiel #6
0
int y4m_si_get_framelength(const y4m_stream_info_t *si)
{
  int total = 0;
  int planes = y4m_si_get_plane_count(si);
  int p;
  for (p = 0; p < planes; p++) {
    int plen = y4m_si_get_plane_length(si, p);
    if (plen == Y4M_UNKNOWN) return Y4M_UNKNOWN;
    total += plen;
  }
  return total;
}
Beispiel #7
0
int y4m_js_decode_frame(y4m_cb_reader_t *r, y4m_stream_info_t *si, y4m_frame_info_t *fi, uint8_t *rgba)
{
    int i, j;
    uint8_t *ycbcr[3];
    int32_t plane_length[3];
    int32_t width;
    int32_t height;
    int32_t ret_value;

    if(NULL == r || NULL == si || NULL == fi || NULL == rgba) {
        return Y4M_UNKNOWN;
    }

    if(3 != y4m_si_get_plane_count(si)) {
        return Y4M_UNKNOWN;
    }

    width = y4m_si_get_plane_width(si, 0);
    height = y4m_si_get_plane_height(si, 0);

    for(i = 0; i < 3; ++i) {
        plane_length[i] = y4m_si_get_plane_length(si, i);
        if(NULL == (ycbcr[i] = malloc(width * height))) {
            return Y4M_UNKNOWN;
        }
    }

    ret_value = y4m_read_frame_cb(r, si, fi, ycbcr);
    if(Y4M_OK != ret_value) {
        return ret_value;
    }

    chroma_supersample(Y4M_CHROMA_420JPEG, ycbcr, width, height);
    convert_YCbCr_to_RGB(ycbcr, width * height);

    for(i = 0; i < width * height; ++i) {
        for(j = 0; j < 3; ++j) {
            rgba[i * 4 + j] = ycbcr[j][i];
        }
    }

    return Y4M_OK;
}
Beispiel #8
0
int
main(int argc, char **argv)
	{
	int	i, fdin, ss_v, ss_h, chroma_ss, textout;
	int 	do_vectorscope;
	int	pwidth, pheight; /* Needed for the vectorscope */
	int	plane0_l, plane1_l, plane2_l;
	u_char	*yuv[3], *cp;
#ifdef	HAVE_SDLgfx
	int	j;
	int temp_x, temp_y;
	u_char	*cpx, *cpy;
#endif
	y4m_stream_info_t istream;
	y4m_frame_info_t iframe;

	do_vectorscope = 0;
	scalepercent = 0;

#ifdef	HAVE_SDLgfx
	textout = 0;
#else
	textout = 1;
#endif

	while	((i = getopt(argc, argv, "tps:")) != EOF)
		{
		switch	(i)
			{
			case	't':
				textout = 1;
				break;
			case	'p':
				scalepercent = 1;
				break;
			case	's':
				do_vectorscope = atoi(optarg);
				break;
			default:
				usage();
			}
		}

#ifdef HAVE_SDLgfx
	if ( (do_vectorscope < 0) || (do_vectorscope >16) )
		usage();

	/* Initialize SDL */
	desired_bpp = 8; 
	video_flags = 0;
	video_flags |= SDL_DOUBLEBUF;
	number_of_frames = 1;

	memset(fy_stats, '\0', sizeof (fy_stats));
	memset(ly_stats, '\0', sizeof (ly_stats));

        if	( SDL_Init(SDL_INIT_VIDEO) < 0 ) 
                mjpeg_error_exit1("Couldn't initialize SDL:%s",SDL_GetError());
        atexit(SDL_Quit);                       /* Clean up on exit */
        /* Initialize the display */
	if (do_vectorscope == 0)
	        screen = SDL_SetVideoMode(width,heigth,desired_bpp,video_flags);
	else
	        screen=SDL_SetVideoMode(width_v,heigth,desired_bpp,video_flags);

        if	(screen == NULL)
                mjpeg_error_exit1("Couldn't set %dx%dx%d video mode: %s",
                                width, heigth, desired_bpp, SDL_GetError());

	SDL_WM_SetCaption("y4mhistogram", "y4mhistogram");

	y4m_init_area(screen); /* Here we draw the basic layout */
#endif /* HAVE_SDLgfx */

	fdin = fileno(stdin);

	y4m_accept_extensions(1);

	y4m_init_stream_info(&istream);
	y4m_init_frame_info(&iframe);

	if	(y4m_read_stream_header(fdin, &istream) != Y4M_OK)
		mjpeg_error_exit1("stream header error");

        if      (y4m_si_get_plane_count(&istream) != 3)
                mjpeg_error_exit1("Only 3 plane formats supported");

	pwidth = y4m_si_get_width(&istream);
	pheight = y4m_si_get_height(&istream);
	chroma_ss = y4m_si_get_chroma(&istream);
	ss_h = y4m_chroma_ss_x_ratio(chroma_ss).d;
	ss_v = y4m_chroma_ss_y_ratio(chroma_ss).d;


	plane0_l = y4m_si_get_plane_length(&istream, 0);
	plane1_l = y4m_si_get_plane_length(&istream, 1);
	plane2_l = y4m_si_get_plane_length(&istream, 2);

	yuv[0] = malloc(plane0_l);
	if	(yuv[0] == NULL)
		mjpeg_error_exit1("malloc(%d) plane 0", plane0_l);
	yuv[1] = malloc(plane1_l);
	if	(yuv[1] == NULL)
		mjpeg_error_exit1(" malloc(%d) plane 1", plane1_l);
	yuv[2] = malloc(plane2_l);
	if	(yuv[2] == NULL)
		mjpeg_error_exit1(" malloc(%d) plane 2\n", plane2_l);

	while	(y4m_read_frame(fdin,&istream,&iframe,yuv) == Y4M_OK)
		{
		for	(i = 0, cp = yuv[0]; i < plane0_l; i++, cp++)
			y_stats[*cp]++; /* Y' */
		for	(i = 0, cp = yuv[1]; i < plane1_l; i++, cp++)
			u_stats[*cp]++;	/* U */
		for	(i = 0, cp = yuv[2]; i < plane2_l; i++, cp++)
			v_stats[*cp]++;	/* V */
#ifdef HAVE_SDLgfx
			
		if (do_vectorscope >= 1 )
		{
		
		for (i=0; i<260; i++) /* Resetting the vectorfield */
			for (j=0;j<260;j++)
				vectorfield[i][j]=0;

		cpx = yuv[1];
		cpy = yuv[2];

		for (i=0; i < (pheight/ss_h); i++)
			{
			for (j = 0; j < (pwidth/ss_v); j++)
				{
					cpx++;
					cpy++;

					/* Have no idea why I have to multiply it with that values
					   But than the vectorsscope works correct. If someone has
						a explantion or better fix tell me. Bernhard */
					temp_x = round( 128+ ((*cpx-128) * 0.7857) );
					temp_y = round( 128+ ((*cpy-128) * 1.1143) );
					vectorfield[temp_x][temp_y*-1]=1;
				}

				/* Here we got to the n'th next line if needed */
				i   = i + (do_vectorscope-1);
				cpy = cpy + (pwidth/ss_v) * (do_vectorscope-1);
				cpx = cpx + (pwidth/ss_v) * (do_vectorscope-1);
			}

		}
		make_stat(); /* showing the sats */

		SDL_UpdateRect(screen,0,0,0,0); /* updating all */

		/* Events for SDL */
		HandleEvent();
#endif
		}
	y4m_fini_frame_info(&iframe);
	y4m_fini_stream_info(&istream);

	if	(textout)
		{
		for	(i = 0; i < 255; i++)
			printf("Y %d %lld\n", i, y_stats[i]);
		for	(i = 0; i < 255; i++)
			printf("U %d %lld\n", i, u_stats[i]);
		for	(i = 0; i < 255; i++)
			printf("V %d %lld\n", i, v_stats[i]);
		}
	exit(0);
	}
Beispiel #9
0
int
main(int argc, char **argv)
	{
	int	fdin, fdout, err, c, i, verbose = 1;
	y4m_stream_info_t istream, ostream;
	y4m_frame_info_t iframe;

	fdin = fileno(stdin);
	fdout = fileno(stdout);

	y4m_accept_extensions(1);
	y4m_init_stream_info(&istream);
	y4m_init_frame_info(&iframe);

	while	((c = getopt(argc, argv, "L:C:hv:N")) != EOF)
		{
		switch	(c)
			{
			case	'N':
				lowuv = lowy = 0;
				lowuv = highy = 255;
				break;
			case	'L':
				i = sscanf(optarg, "%lf,%lf,%d", &y_radius, 
						&y_amount, &y_threshold);
				if	(i != 3)
					{
					mjpeg_error("-L r,a,t");
					usage(argv[0]);
					}
				break;
			case	'C':
				i = sscanf(optarg, "%lf,%lf,%d", &uv_radius,
						&uv_amount, &uv_threshold);
				if	(i != 3)
					{
					mjpeg_error("-C r,a,t");
					usage(argv[0]);
					}
				break;
			case	'v':
				verbose = atoi(optarg);
				if	(verbose < 0 || verbose > 2)
					mjpeg_error_exit1("-v 0|1|2");
				break;
			case	'h':
			default:
				usage(argv[0]);
				break;
			}
		}

	if	(isatty(fdout))
		mjpeg_error_exit1("stdout must not be a terminal");

	mjpeg_default_handler_verbosity(verbose);

	err = y4m_read_stream_header(fdin, &istream);
	if	(err != Y4M_OK)
		mjpeg_error_exit1("Couldn't read input stream header");

	switch	(y4m_si_get_interlace(&istream))
		{
		case	Y4M_ILACE_NONE:
			interlaced = 0;
			break;
		case	Y4M_ILACE_BOTTOM_FIRST:
		case	Y4M_ILACE_TOP_FIRST:
			interlaced = 1;
			break;
		default:
			mjpeg_error_exit1("Unsupported/unknown interlacing");
		}

	if	(y4m_si_get_plane_count(&istream) != 3)
		mjpeg_error_exit1("Only 3 plane formats supported");

	yheight = y4m_si_get_plane_height(&istream, 0);
	uvheight = y4m_si_get_plane_height(&istream, 1);
	ywidth = y4m_si_get_plane_width(&istream, 0);
	uvwidth = y4m_si_get_plane_width(&istream, 1);
	ylen = y4m_si_get_plane_length(&istream, 0);
	uvlen = y4m_si_get_plane_length(&istream, 1);

/* Input and output frame buffers */
	i_yuv[0] = (u_char *)malloc(ylen);
	i_yuv[1] = (u_char *)malloc(uvlen);
	i_yuv[2] = (u_char *)malloc(uvlen);
	o_yuv[0] = (u_char *)malloc(ylen);
	o_yuv[1] = (u_char *)malloc(uvlen);
	o_yuv[2] = (u_char *)malloc(uvlen);

/*
 * general purpose row/column scratch buffers.  Slightly over allocated to
 * simplify life.
*/
	cur_col = (u_char *)malloc(MAX(ywidth, yheight));
	dest_col = (u_char *)malloc(MAX(ywidth, yheight));
	cur_row = (u_char *)malloc(MAX(ywidth, yheight));
	dest_row = (u_char *)malloc(MAX(ywidth, yheight));

/*
 * Generate the convolution matrices.  The generation routine allocates the
 * memory and returns the length.
*/
	cmatrix_y_len = gen_convolve_matrix(y_radius, &cmatrix_y);
	cmatrix_uv_len = gen_convolve_matrix(uv_radius, &cmatrix_uv);
	ctable_y = gen_lookup_table(cmatrix_y, cmatrix_y_len);
	ctable_uv = gen_lookup_table(cmatrix_uv, cmatrix_uv_len);

	y4m_init_stream_info(&ostream);
	y4m_copy_stream_info(&ostream, &istream);
	y4m_write_stream_header(fileno(stdout), &ostream);

	mjpeg_info("Luma radius: %f", y_radius);
	mjpeg_info("Luma amount: %f", y_amount);
	mjpeg_info("Luma threshold: %d", y_threshold);
	if	(uv_radius != -1.0)
		{
		mjpeg_info("Chroma radius: %f", uv_radius);
		mjpeg_info("Chroma amount: %f", uv_amount);
		mjpeg_info("Chroma threshold: %d", uv_threshold);
		}

	for	(frameno = 0; y4m_read_frame(fdin, &istream, &iframe, i_yuv) == Y4M_OK; frameno++)
		{
		y4munsharp();
		err = y4m_write_frame(fdout, &ostream, &iframe, o_yuv);
		if	(err != Y4M_OK)
			{
			mjpeg_error("y4m_write_frame err at frame %d", frameno);
			break;
			}
		}
	y4m_fini_frame_info(&iframe);
	y4m_fini_stream_info(&istream);
	y4m_fini_stream_info(&ostream);
	exit(0);
	}
int main(int argc, char **argv)
{
    int    i, c, interlace, frames, err;
    int    ywidth, yheight, uvwidth, uvheight, ylen, uvlen;
    int    verbose = 0, fdin;
    int    NlumaX = 4, NlumaY = 4, NchromaX = 4, NchromaY = 4;
    float  BWlumaX = 0.8, BWlumaY = 0.8, BWchromaX = 0.7, BWchromaY = 0.7;
    struct filter *lumaXtaps, *lumaYtaps, *chromaXtaps, *chromaYtaps;
    u_char *yuvinout[3];
    float *yuvtmp1,*yuvtmp2;
    y4m_stream_info_t istream, ostream;
    y4m_frame_info_t iframe;

    fdin = fileno(stdin);
    
    y4m_accept_extensions(1);

    /* read command line */
    opterr = 0;
    while   ((c = getopt(argc, argv, "hvL:C:x:X:y:Y:")) != EOF)
	{
	    switch  (c)
		{
		case    'L':
		    sscanf(optarg,"%d,%f,%d,%f",&NlumaX,&BWlumaX,&NlumaY,&BWlumaY);
		    break;
		case    'C':
		    sscanf(optarg,"%d,%f,%d,%f",&NchromaX,&BWchromaX,&NchromaY,&BWchromaY);
		    break;
		case    'x':
		    sscanf(optarg,"%d,%f",&NchromaX,&BWchromaX);
		    break;
		case    'X':
		    sscanf(optarg,"%d,%f",&NlumaX,&BWlumaX);
		    break;
		case    'y':
		    sscanf(optarg,"%d,%f",&NchromaY,&BWchromaY);
		    break;
		case    'Y':
		    sscanf(optarg,"%d,%f",&NlumaY,&BWlumaY);
		    break;
		case    'v':
		    verbose++;
		    break;
		case    '?':
		case    'h':
		default:
		    usage();
		}
	}
    
    if (BWlumaX <= 0.0 || BWlumaX > 1.0)
       mjpeg_error_exit1("Horizontal luma bandwidth '%f' not >0 and <=1.0", BWlumaX);
    if (BWlumaY <= 0.0 || BWlumaY > 1.0)
       mjpeg_error_exit1("Vertical luma bandwidth '%f' not >0 and <=1.0", BWlumaY);
    if (BWchromaX <= 0.0 || BWchromaX > 1.0)
       mjpeg_error_exit1("Horizontal chroma bandwidth '%f' not >0 and <=1.0", BWchromaX);
    if (BWchromaY <= 0.0 || BWchromaY > 1.0)
       mjpeg_error_exit1("Vertical chroma bandwidth '%f' not >0 and <=1.0", BWchromaY);

    /* initialize input stream and check chroma subsampling and interlacing */
    y4m_init_stream_info(&istream);
    y4m_init_frame_info(&iframe);
    err = y4m_read_stream_header(fdin, &istream);
    if (err != Y4M_OK)
	mjpeg_error_exit1("Input stream error: %s\n", y4m_strerr(err));

    if	(y4m_si_get_plane_count(&istream) != 3)
	mjpeg_error_exit1("Only the 3 plane formats supported");

    i = y4m_si_get_interlace(&istream);
    switch (i)
        {
        case Y4M_ILACE_NONE:
	    interlace = 0;
	    break;
        case Y4M_ILACE_BOTTOM_FIRST:
        case Y4M_ILACE_TOP_FIRST:
	    interlace = 1;
	    break;
        default:
	    mjpeg_warn("Unknown interlacing '%d', assuming non-interlaced", i);
	    interlace = 0;
	    break;
        }

    ywidth = y4m_si_get_width(&istream);	/* plane 0 = Y */
    yheight = y4m_si_get_height(&istream);
    ylen = ywidth * yheight;
    uvwidth = y4m_si_get_plane_width(&istream, 1);	/* planes 1&2 = U+V */
    uvheight = y4m_si_get_plane_height(&istream, 1);
    uvlen = y4m_si_get_plane_length(&istream, 1);
    
    /* initialize output stream */
    y4m_init_stream_info(&ostream);
    y4m_copy_stream_info(&ostream, &istream);
    y4m_write_stream_header(fileno(stdout), &ostream);
    
    /* allocate input and output buffers */
    yuvinout[0] = my_malloc(ylen*sizeof(u_char));
    yuvinout[1] = my_malloc(uvlen*sizeof(u_char));
    yuvinout[2] = my_malloc(uvlen*sizeof(u_char));
    yuvtmp1 = my_malloc(MAX(ylen,uvlen)*sizeof(float));
    yuvtmp2 = my_malloc(MAX(ylen,uvlen)*sizeof(float));

    /* get filter taps */
    lumaXtaps   = get_coeff(NlumaX, BWlumaX);
    lumaYtaps   = get_coeff(NlumaY, BWlumaY);
    chromaXtaps = get_coeff(NchromaX, BWchromaX);
    chromaYtaps = get_coeff(NchromaY, BWchromaY);

    set_accel(uvwidth,uvheight);

    if (verbose)
	y4m_log_stream_info(mjpeg_loglev_t("info"), "", &istream);
    
    /* main processing loop */
    for (frames=0; y4m_read_frame(fdin,&istream,&iframe,yuvinout) == Y4M_OK; frames++)
	{
	    if (verbose && ((frames % 100) == 0))
		mjpeg_info("Frame %d\n", frames);
	    
            convolveFrame(yuvinout[0],ywidth,yheight,interlace,lumaXtaps,lumaYtaps,yuvtmp1,yuvtmp2);
            convolveFrame(yuvinout[1],uvwidth,uvheight,interlace,chromaXtaps,chromaYtaps,yuvtmp1,yuvtmp2);
            convolveFrame(yuvinout[2],uvwidth,uvheight,interlace,chromaXtaps,chromaYtaps,yuvtmp1,yuvtmp2);

	    y4m_write_frame(fileno(stdout), &ostream, &iframe, yuvinout);

	}
    
    /* clean up */
    y4m_fini_frame_info(&iframe);
    y4m_fini_stream_info(&istream);
    y4m_fini_stream_info(&ostream);
    exit(0);
}
int main(int argc, char **argv)
	{
	int	c, err, ilace;
	int	fd_in = fileno(stdin), fd_out = fileno(stdout);
	y4m_ratio_t rate;
	y4m_stream_info_t si, so;
	y4m_frame_info_t fi;
	uint8_t *top1[3], *bot1[3], *top2[3], *bot2[3];

	opterr = 0;
	while	((c = getopt(argc, argv, "h")) != EOF)
		{
		switch	(c)
			{
			case	'h':
			case	'?':
			default:
				usage();
			}
		}

	y4m_accept_extensions(1);
	y4m_init_stream_info(&si);
	y4m_init_stream_info(&so);
	y4m_init_frame_info(&fi);

	err = y4m_read_stream_header(fd_in, &si);
	if	(err != Y4M_OK)
		mjpeg_error_exit1("Input stream error: %s\n", y4m_strerr(err));

	if	(y4m_si_get_plane_count(&si) != 3)
		mjpeg_error_exit1("only 3 plane formats supported");

	rate = y4m_si_get_framerate(&si);
	if	(!Y4M_RATIO_EQL(rate, y4m_fps_NTSC))
		mjpeg_error_exit1("input stream not NTSC 30000:1001");

	ilace = y4m_si_get_interlace(&si);
	if	(ilace != Y4M_ILACE_BOTTOM_FIRST && ilace != Y4M_ILACE_TOP_FIRST)
		mjpeg_error_exit1("input stream not interlaced");

	top1[0] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,0) / 2);
	top1[1] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,1) / 2);
	top1[2] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,2) / 2);

	bot1[0] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,0) / 2);
	bot1[1] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,1) / 2);
	bot1[2] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,2) / 2);

	top2[0] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,0) / 2);
	top2[1] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,1) / 2);
	top2[2] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,2) / 2);

	bot2[0] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,0) / 2);
	bot2[1] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,1) / 2);
	bot2[2] = (uint8_t *) malloc(y4m_si_get_plane_length(&si,2) / 2);

	y4m_copy_stream_info(&so, &si);
	y4m_si_set_framerate(&so, y4m_fps_NTSC_FILM);
	y4m_si_set_interlace(&so, Y4M_ILACE_NONE);

/*
 * At this point the input stream has been verified to be interlaced NTSC,
 * the output stream rate set to NTSC_FILM, interlacing tag changed to 
 * progressive, and the field buffers allocated.
 *
 * Time to write the output stream header and commence processing input.
*/
	y4m_write_stream_header(fd_out, &so);

	while	(1)
		{
		err = y4m_read_fields(fd_in, &si, &fi, top1, bot1);
		if	(err != Y4M_OK)
			goto done;
		y4m_write_fields(fd_out, &so, &fi, top1, bot1);		/* A */

		err = y4m_read_fields(fd_in, &si, &fi, top1, bot1);
		if	(err != Y4M_OK)
			goto done;
		y4m_write_fields(fd_out, &so, &fi, top1, bot1);		/* B */

		err = y4m_read_fields(fd_in, &si, &fi, top1, bot1);
		if	(err != Y4M_OK)
			goto done;
		err = y4m_read_fields(fd_in, &si, &fi, top2, bot2);
		if	(err != Y4M_OK)
			{
/*
 * End of input when reading the 2nd "mixed field" frame (C+D).  The previous
 * frame was the first "mixed field" frame (B+C).  Rather than emit a mixed
 * interlaced frame duplicate a field and output the previous frame.
*/
			if	(ilace == Y4M_ILACE_BOTTOM_FIRST)
				y4m_write_fields(fd_out, &so, &fi, bot1,bot1);
			else
				y4m_write_fields(fd_out, &so, &fi, top1,top1);
			goto done;
			}
/*
 * Now the key part of the processing - effectively discarding the first mixed
 * frame with fields from frames B + C and creating the C frame from the two
 * mixed frames.  For a BOTTOM FIELD FIRST stream use the 'top' field from
 * frame 3 and the 'bottom' fields from frame 4.  With a TOP FIELD FIRST stream
 * it's the other way around - use the 'bottom' field from frame 3 and the
 * 'top' field from frame 4.
*/
		if	(ilace == Y4M_ILACE_BOTTOM_FIRST)
			y4m_write_fields(fd_out, &so, &fi, top1, bot2);	/* C */
		else
			y4m_write_fields(fd_out, &so, &fi, top2, bot1); /* C */
		
		err = y4m_read_fields(fd_in, &si, &fi, top1, bot1);
		y4m_write_fields(fd_out, &so, &fi, top1, bot1);		/* D */
		}
done:	y4m_fini_frame_info(&fi);
	y4m_fini_stream_info(&si);
	y4m_fini_stream_info(&so);
	exit(0);
	}
int
main(int argc, char **argv)
	{
	int	sts, c, width = 640, height = 480, noheader = 0;
	int	Y = 16, U = 128, V = 128, chroma_mode = Y4M_CHROMA_420MPEG2;
	int	numframes = 1, force = 0;
	y4m_ratio_t	rate_ratio = y4m_fps_NTSC;
	y4m_ratio_t	aspect_ratio = y4m_sar_SQUARE;
	int	plane_length[3];
	u_char	*yuv[3];
	y4m_stream_info_t ostream;
	y4m_frame_info_t oframe;
	char	interlace = Y4M_ILACE_NONE;

	opterr = 0;
	y4m_accept_extensions(1);

	while	((c = getopt(argc, argv, "Hfx:w:h:r:i:a:Y:U:V:n:")) != EOF)
		{
		switch	(c)
			{
			case	'H':
				noheader = 1;
				break;
			case	'a':
				sts = y4m_parse_ratio(&aspect_ratio, optarg);
				if	(sts != Y4M_OK)
					mjpeg_error_exit1("Invalid aspect: %s",
						optarg);
				break;
			case	'w':
				width = atoi(optarg);
				break;
			case	'h':
				height = atoi(optarg);
				break;
			case	'r':
				sts = y4m_parse_ratio(&rate_ratio, optarg);
				if	(sts != Y4M_OK)
					mjpeg_error_exit1("Invalid rate: %s", optarg);
				break;
			case	'Y':
				Y = atoi(optarg);
				break;
			case	'U':
				U = atoi(optarg);
				break;
			case	'V':
				V = atoi(optarg);
				break;
			case	'i':
				switch	(optarg[0])
					{
					case	'p':
						interlace = Y4M_ILACE_NONE;
						break;
					case	't':
						interlace = Y4M_ILACE_TOP_FIRST;
						break;
					case	'b':
						interlace = Y4M_ILACE_BOTTOM_FIRST;
						break;
					default:
						usage();
					}
				break;
			case	'x':
				chroma_mode = y4m_chroma_parse_keyword(optarg);
				if	(chroma_mode == Y4M_UNKNOWN)
					{
					if	(strcmp(optarg, "help") != 0)
						mjpeg_error("Invalid -x arg '%s'", optarg);
					chroma_usage();
					}

				break;
			case	'f':
				force = 1;
				break;
			case	'n':
				numframes = atoi(optarg);
				break;
			case	'?':
			default:
				usage();
			}
		}

	if	(width <= 0)
		mjpeg_error_exit1("Invalid Width: %d", width);

	if	(height <= 0)
		mjpeg_error_exit1("Invalid Height: %d", height);

	if	(!force && (Y < 16 || Y > 235))
		mjpeg_error_exit1("16 < Y < 235");

	if	(!force && (U < 16 || U > 240))
		mjpeg_error_exit1("16 < U < 240");

	if	(!force && (V < 16 || V > 240))
		mjpeg_error_exit1("16 < V < 240");

	y4m_init_stream_info(&ostream);
	y4m_init_frame_info(&oframe);
	y4m_si_set_width(&ostream, width);
	y4m_si_set_height(&ostream, height);
	y4m_si_set_interlace(&ostream, interlace);
	y4m_si_set_framerate(&ostream, rate_ratio);
	y4m_si_set_sampleaspect(&ostream, aspect_ratio);
	y4m_si_set_chroma(&ostream, chroma_mode);

	if	(y4m_si_get_plane_count(&ostream) != 3)
		mjpeg_error_exit1("Only the 3 plane formats supported");

	plane_length[0] = y4m_si_get_plane_length(&ostream, 0);
	plane_length[1] = y4m_si_get_plane_length(&ostream, 1);
	plane_length[2] = y4m_si_get_plane_length(&ostream, 2);

	yuv[0] = malloc(plane_length[0]);
	yuv[1] = malloc(plane_length[1]);
	yuv[2] = malloc(plane_length[2]);

/*
 * Now fill the array once with black but use the provided Y, U and V values
*/
	memset(yuv[0], Y, plane_length[0]);
	memset(yuv[1], U, plane_length[1]);
	memset(yuv[2], V, plane_length[2]);

	if	(noheader == 0)
		y4m_write_stream_header(fileno(stdout), &ostream);
	while	(numframes--)
		y4m_write_frame(fileno(stdout), &ostream, &oframe, yuv);

	free(yuv[0]);
	free(yuv[1]);
	free(yuv[2]);
	y4m_fini_stream_info(&ostream);
	y4m_fini_frame_info(&oframe);
	exit(0);
	}