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

📄 y4mtoppm.c

📁 Motion JPEG编解码器源代码
💻 C
字号:
/* * y4mtoppm.c:  Generate one or more PPM images from a YUV4MPEG2 stream * *              Performs 4:2:0->4:4:4 chroma supersampling and then *               converts ITU-Rec.601 Y'CbCr to R'G'B' colorspace. * * *  Copyright (C) 2004 Matthew J. Marjanovic <maddog@mir.com> * * *  This program is free software; you can redistribute it and/or *  modify it under the terms of the GNU General Public License *  as published by the Free Software Foundation; either version 2 *  of the License, or (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. * */#include "config.h"#include <stdio.h>#include <unistd.h>#include <string.h>#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <yuv4mpeg.h>#include <mpegconsts.h>#include "subsample.h"#include "colorspace.h"/* command-line parameters */typedef struct _cl_info {  int interleave;  int verbosity;  FILE *outfp;} cl_info_t;staticvoid usage(const char *progname){  fprintf(stdout, "\n");  fprintf(stdout, "usage:  %s [options]\n", progname);  fprintf(stdout, "\n");  fprintf(stdout, "Reads YUV4MPEG2 stream from stdin and produces RAW PPM image(s) on stdout.\n");  fprintf(stdout, "Converts digital video Y'CbCr colorspace to computer graphics R'G'B',\n");  fprintf(stdout, " and performs chroma supersampling.\n");  fprintf(stdout, "\n");  fprintf(stdout, " options:  (defaults specified in [])\n");  fprintf(stdout, "\n");  fprintf(stdout, "  -L       interleave fields into single PPM image\n");  fprintf(stdout, "  -v n     verbosity (0,1,2) [1]\n");}staticvoid parse_args(cl_info_t *cl, int argc, char **argv){  int c;  cl->interleave = 0;  cl->verbosity = 1;  cl->outfp = stdout; /* default to stdout */  while ((c = getopt(argc, argv, "Lv:h")) != -1) {    switch (c) {    case 'L':      cl->interleave = 1;      break;    case 'v':      cl->verbosity = atoi(optarg);      if ((cl->verbosity < 0) || (cl->verbosity > 2))	mjpeg_error("Verbosity must be 0, 1, or 2:  '%s'", optarg);      break;    case 'h':      usage(argv[0]);      exit(0);      break;    case '?':    default:      goto ERROR_EXIT;      break;    }  }  if (optind != argc)     goto ERROR_EXIT;  mjpeg_default_handler_verbosity(cl->verbosity);  /* DONE! */  return; ERROR_EXIT:  mjpeg_error("For usage hints, use option '-h'.  Please take a hint.");  exit(1);}staticvoid write_ppm_from_two_buffers(FILE *fp,				uint8_t *buffers[], 				uint8_t *buffers2[], 				uint8_t *rowbuffer,				int width, int height){  int x, y;  uint8_t *pixels;  uint8_t *R = buffers[0];  uint8_t *G = buffers[1];  uint8_t *B = buffers[2];  uint8_t *R2 = buffers2[0];  uint8_t *G2 = buffers2[1];  uint8_t *B2 = buffers2[2];  mjpeg_debug("write PPM image from two buffers, %dx%d", width, height);  fprintf(fp, "P6\n%d %d 255\n", width, height);  for (y = 0; y < height; y += 2) {    pixels = rowbuffer;    for (x = 0; x < width; x++) {      *(pixels++) = *(R++);      *(pixels++) = *(G++);      *(pixels++) = *(B++);    }    fwrite(rowbuffer, sizeof(rowbuffer[0]), width * 3, fp);    pixels = rowbuffer;    for (x = 0; x < width; x++) {      *(pixels++) = *(R2++);      *(pixels++) = *(G2++);      *(pixels++) = *(B2++);    }    fwrite(rowbuffer, sizeof(rowbuffer[0]), width * 3, fp);  }}staticvoid write_ppm_from_one_buffer(FILE *fp,			       uint8_t *buffers[],			       uint8_t *rowbuffer,			       int width, int height) {  int x, y;  uint8_t *pixels;  uint8_t *R = buffers[0];  uint8_t *G = buffers[1];  uint8_t *B = buffers[2];  mjpeg_debug("write PPM image from one buffer, %dx%d", width, height);  fprintf(fp, "P6\n%d %d 255\n", width, height);  for (y = 0; y < height; y++) {    pixels = rowbuffer;    for (x = 0; x < width; x++) {      *(pixels++) = *(R++);      *(pixels++) = *(G++);      *(pixels++) = *(B++);    }    fwrite(rowbuffer, sizeof(rowbuffer[0]), width * 3, fp);  }}int main(int argc, char **argv){  int in_fd = 0;  cl_info_t cl;  y4m_stream_info_t streaminfo;  y4m_frame_info_t frameinfo;  uint8_t *buffers[Y4M_MAX_NUM_PLANES];  /* R'G'B' or Y'CbCr */  uint8_t *buffers2[Y4M_MAX_NUM_PLANES]; /* R'G'B' or Y'CbCr */  int err, i;  int width, height;  int interlace, chroma, planes;  uint8_t *rowbuffer;  y4m_accept_extensions(1); /* allow non-4:2:0 chroma */  y4m_init_stream_info(&streaminfo);  y4m_init_frame_info(&frameinfo);  parse_args(&cl, argc, argv);  if ((err = y4m_read_stream_header(in_fd, &streaminfo)) != Y4M_OK) {    mjpeg_error("Couldn't read YUV4MPEG2 header: %s!", y4m_strerr(err));    exit(1);  }  mjpeg_info("input stream parameters:");  y4m_log_stream_info(LOG_INFO, "<<<", &streaminfo);  width = y4m_si_get_width(&streaminfo);  height = y4m_si_get_height(&streaminfo);  interlace = y4m_si_get_interlace(&streaminfo);  chroma = y4m_si_get_chroma(&streaminfo);  planes = y4m_si_get_plane_count(&streaminfo);  if (interlace == Y4M_ILACE_MIXED) {    mjpeg_error("Cannot (yet) handle 'mixed' interlacing mode!");    exit(1);  }  if (!chroma_super_implemented(chroma))    mjpeg_error_exit1("Cannot handle stream's chroma mode!");      /*** Allocate buffers ***/  mjpeg_debug("allocating buffers...");  rowbuffer = malloc(width * planes * sizeof(rowbuffer[0]));  mjpeg_debug("  rowbuffer %p", rowbuffer);  /* allocate buffers big enough for 4:4:4 supersampled components */  for (i = 0; i < planes; i++) {    if (interlace == Y4M_ILACE_NONE) {      buffers[i] = malloc(width * height * sizeof(buffers[i][0]));      buffers2[i] = NULL;    } else {      buffers[i] = malloc(width * height / 2 * sizeof(buffers[i][0]));      buffers2[i] = malloc(width * height / 2 * sizeof(buffers[i][0]));    }    mjpeg_debug("  buffers[%d] %p   buffers2[%d] %p", 		i, buffers[i], i, buffers2[i]);  }  /*** Process frames ***/  while (1) {        if (interlace == Y4M_ILACE_NONE) {      mjpeg_debug("reading noninterlaced frame...");      err = y4m_read_frame(in_fd, &streaminfo, &frameinfo, buffers);      if (err != Y4M_OK) break;      if (chroma != Y4M_CHROMA_444) {	mjpeg_debug("supersampling noninterlaced frame...");	chroma_supersample(chroma, buffers, width, height);      }      mjpeg_debug("color converting noninterlaced frame...");      convert_YCbCr_to_RGB(buffers, width * height);      write_ppm_from_one_buffer(cl.outfp, buffers, rowbuffer, width, height);    } else {      err = y4m_read_fields(in_fd, &streaminfo, &frameinfo, 			    buffers, buffers2);      if (err != Y4M_OK) break;      if (chroma != Y4M_CHROMA_444) {	mjpeg_debug("supersampling top field...");	chroma_supersample(chroma, buffers, width, height / 2);	mjpeg_debug("supersampling bottom field...");	chroma_supersample(chroma, buffers2, width, height / 2);      }      mjpeg_debug("color converting top field...");      convert_YCbCr_to_RGB(buffers, width * height / 2);      mjpeg_debug("color converting bottom field...");      convert_YCbCr_to_RGB(buffers2, width * height / 2);      if (cl.interleave) {	write_ppm_from_two_buffers(cl.outfp, buffers, buffers2, 				   rowbuffer, width, height);      } else if (interlace == Y4M_ILACE_TOP_FIRST) {	write_ppm_from_one_buffer(cl.outfp, buffers,				  rowbuffer, width, height / 2);	write_ppm_from_one_buffer(cl.outfp, buffers2,				  rowbuffer, width, height / 2);      } else { /* ilace == Y4M_ILACE_BOTTOM_FIRST */	write_ppm_from_one_buffer(cl.outfp, buffers2,				  rowbuffer, width, height / 2);	write_ppm_from_one_buffer(cl.outfp, buffers,				  rowbuffer, width, height / 2);      }    }  }       if ((err != Y4M_OK) && (err != Y4M_ERR_EOF))    mjpeg_error("Couldn't read frame:  %s", y4m_strerr(err));  /*** Clean-up after ourselves ***/  mjpeg_debug("freeing buffers; cleaning up");  free(rowbuffer);  for (i = 0; i < 3; i++) {    free(buffers[i]);    free(buffers2[i]);  }  y4m_fini_stream_info(&streaminfo);  y4m_fini_frame_info(&frameinfo);    mjpeg_debug("Done.");  return 0;}

⌨️ 快捷键说明

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