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

📄 yuvkineco.c

📁 Motion JPEG编解码器源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Copyright (C) 2001,2002 Kawamata/Hitoshi <hitoshi.kawamata@nifty.ne.jp> * *  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., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <config.h>#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <ctype.h>#include <unistd.h>#include <mpegtimecode.h>#include "yuvfilters.h"#define NOISERATIO(N) (((N)+63)/64*63)#define MAXHALFHEIGHT 288#define NOISEMAX 31#define DEINTLRESO 1000#define DEFAULTDTHR16 4#define DEFAULTNOISE 10#define DEFAULTDEINTL 10static voidbuf_debug(char *buf, FILE *fp, const char *format, ...){  size_t n;  va_list ap;  va_start(ap, format);  vsprintf(buf + strlen(buf), format, ap);  va_end(ap);  if (buf[(n = strlen(buf) - 1)] == '\n') {    if (fp) {      fputs(buf, fp);    } else {#ifdef MJPEGTOOLS      buf[n] = '\0';      mjpeg_debug(buf);#else      fputs(buf, stderr);#endif    }    buf[0] = '\0';  }}typedef struct {  YfTaskCore_t _;  int fpscode0;  FILE *cyfp;  int cytype;  int nfields;  int nframes;  int iget;  int iuse;  int iput;  YfFrame_t *frame;  int dthr16;  int deintl;  int nointlmax, deintlmin;  unsigned int deintlframes;  unsigned int deintldist[100];  union {    struct {			/* use in 1st try */      unsigned long dist[NOISEMAX+1];      unsigned long total;      unsigned int level0, level;    } noise;    struct {			/* use in retry */      char buff[32];      char *p;    } cy;  } u;  struct {    unsigned long odiff;	/* odd field (or non-intarlaced frame) diff */    unsigned long ediff;	/* even field diff (only when interlaced) */    long eoediff;		/* previous even - odd - even diff */    unsigned long diffdist[NOISEMAX+1];  } framestat[0];} YfTask_t;DEFINE_STD_YFTASKCLASS(yuvkineco);DECLARE_YFTASKCLASS(yuvycsnoise);static const char *do_usage(void){  return "[-{u|s}] [-F OutputFPSCODE] [-S YCSNoiseThreashold] [-n NoiseLevel] "    "[-c CycleSearchThreashold] [-i DeinterlacePixelsPermil] "    "{[-C OutputCycleListName] | -[ON] InputCycleListName}";}static YfTaskCore_t *do_init(int argc, char **argv, const YfTaskCore_t *h0){  int fpscode;  int nframes, nfields;  YfTask_t *h;  int c;  int cytype = 0;  char *cyname = NULL;  char *ycsthres = NULL;  YfTaskCore_t *hycs = NULL;  int dthr16 = DEFAULTDTHR16;  int noiselevel = DEFAULTNOISE;  int deintlval = DEFAULTDEINTL;  int output_interlace = 0;  fpscode = h0->fpscode;  while ((c = getopt(argc, argv, "usF:S:n:c:i:C:O:N:")) != -1) {    switch (c) {    case 'u':      output_interlace = 1;      break;    case 's':      output_interlace = 2;      break;    case 'F':      fpscode = atoi(optarg);      break;    case 'S':      ycsthres = optarg;      break;    case 'n':      noiselevel = atoi(optarg);      break;    case 'c':      dthr16 = atoi(optarg);      break;    case 'i':      deintlval = atoi(optarg);      break;    case 'C':    case 'O':    case 'N':      cytype = c;      cyname = optarg;      break;    default:      return NULL;    }  }  if (cytype != 'N' && (h0->fpscode < 3 || 5 < h0->fpscode)) {    WERROR("unsupported input fps");    return NULL;  }  if (fpscode < 1 || h0->fpscode < fpscode) {    WERROR("illeagal output fpscode");    return NULL;  }  if (y4m_si_get_interlace(&h0->si) == Y4M_ILACE_BOTTOM_FIRST) {    WERROR("unsupported field order");    return NULL;  }  if (ycsthres) {    char ycssopt[] = "-S";    char *ycsargv[] = { argv[0], ycssopt, ycsthres, NULL, };    optind = 1;    if (!(hycs = YfAddNewTask(&yuvycsnoise,			   (sizeof ycsargv / sizeof ycsargv[0]) - 1,			   ycsargv, h0)))      return NULL;  }  nframes = ((cytype && cytype != 'C')? 2:	     (h0->fpscode == 3)? 49: 9);  nfields = ((y4m_si_get_interlace(&h0->si) == Y4M_UNKNOWN)?	     (MAXHALFHEIGHT < h0->height): y4m_si_get_interlace(&h0->si)) + 1;  if (deintlval < 0 || nfields == 1 || (cytype && cytype != 'C'))    deintlval = -1;  else if (2 * DEINTLRESO < deintlval)    deintlval = 2 * DEINTLRESO;  if (dthr16 < 0)    dthr16 = 0;  else if (32 < dthr16)    dthr16 = 32;  if (noiselevel < 0)    noiselevel = 0;  else if (255 < noiselevel)    noiselevel = 255;  h = (YfTask_t *)    YfAllocateTask(&yuvkineco,		   (sizeof *h +		    ((((!cytype || cytype == 'C')? (sizeof h->framestat[0]):		       0) + FRAMEBYTES(y4m_si_get_chroma(&h0->si), h0->width, h0->height)) * nframes) +		    ((0 <= deintlval)? FRAMEBYTES(y4m_si_get_chroma(&h0->si), h0->width, h0->height): 0)),		   (hycs? hycs: h0));  if (!h)    return NULL;  if (output_interlace == 2 &&      (y4m_si_get_interlace(&h0->si) != Y4M_ILACE_TOP_FIRST ||       CHDIV(y4m_si_get_chroma(&h0->si)) != 2))    output_interlace = 3;  y4m_si_set_interlace(&h->_.si, ((output_interlace == 1)? Y4M_UNKNOWN:				  (output_interlace == 2)? Y4M_ILACE_TOP_FIRST:				  Y4M_ILACE_NONE));  h->_.fpscode = fpscode;  h->fpscode0  = h0->fpscode;  h->cytype    = cytype;  h->nfields   = nfields;  h->nframes   = nframes;  h->frame     = (YfFrame_t *)(h->framestat +			       (nframes * (!cytype || cytype == 'C')));  h->dthr16    = dthr16;  h->deintl    = deintlval * DATABYTES(y4m_si_get_chroma(&h0->si), h0->width, h0->height) / (2*DEINTLRESO);  h->nointlmax = -1;  h->deintlmin = 0x7fffffff;  h->u.noise.level0 = h->u.noise.level = noiselevel;  if (0 <= h->deintl)    nframes++;  while (0 <= --nframes)    YfInitFrame((YfFrame_t *)((char *)h->frame +			      (nframes * FRAMEBYTES(y4m_si_get_chroma(&h0->si), h0->width, h0->height))),		&h->_);  if (!cytype)    goto RETURN;  if ((h->cyfp = fopen(cyname, ((cytype == 'C')? "w": "r"))) == NULL) {    perror(cyname);    goto ERROR_RETURN;  }  if (cytype == 'C') {    fprintf(h->cyfp, "# 2-3 pull down cycle list\n""# Generated by 'yuvkineco%s -F%d%s%s -n%d -c%d -i%d -C %s'\n""#\n""# Each character in list mean how each frame processed:\n""#   O,o:    output\n""#   D,d:    deinterlaced and output\n""#   X,x:    bottom field replaced by previous one and output\n""#   M,m:    bottom field replaced by previous one and deinterlaced and output\n""#   _:      dropped\n""# Lower case characters mean output but might drop if framerate was lower.\n""#\n""# You can edit this list by hand and retry yuvkineco.\n""# When edit, you can use characters in addition to above:\n""#   E,e:    always deinterlace\n""#   Y,y:    always replace bottom field by previous one\n""#   N,n:    always replace bottom field by previous one and deinterlace\n""#   T,t:    duplicate top field\n""#   B,b:    duplicate bottom field\n""# Upper case characters mean always output.\n""# Lower case characters mean output or drop according to framerate.\n""#\n""# Use this list with old input to generator yuvkineco,\n""# do 'yuvkineco -F fpscode -O %s',\n""# with output new,\n""# do 'yuvkineco -F fpscode -N %s'.\n""#\n""# When used as '-O %s':\n""#   O,o:        output\n""#   D,d,E,e:    deinterlace and output\n""#   X,x,Y,y:    replace bottom field by previous one and output\n""#   M,m,N,n:    replace bottom field by previous one and deinterlace and output\n""#   T,t:        duplicate top field and output\n""#   B,b:        duplicate bottom field and output\n""#   _:          drop\n""#\n""# When used as '-N %s':\n""#   O,o,X,x,D,d,M,m:    output\n""#   E,e:        deinterlace and output\n""#   Y,y:        replace bottom field by previous one and output\n""#   N,n:        replace bottom field by previous one and deinterlace and output\n""#   T,t:        duplicate top field and output\n""#   B,b:        duplicate bottom field and output\n""#   _:          ignore\n""#\n""SIZE:%dx%d OLD_FPS:%d NEW_FPS:%d # DON'T CHANGE THIS LINE!!!",	    ((output_interlace == 1)? " -u": (2 <= output_interlace)? " -s": ""), fpscode,	    (ycsthres? " -S": ""), (ycsthres? ycsthres: ""),	    noiselevel, dthr16, deintlval,	    cyname, cyname, cyname, cyname, cyname,	    h0->width, h0->height, h0->fpscode, fpscode);  } else {    int width, height, oldfps, newfps;    char buff[128];    h->u.cy.p = h->u.cy.buff;    buff[sizeof buff - 1] = buff[sizeof buff - 2] = '\0';    while (fgets(buff, sizeof buff, h->cyfp)) {      if (sscanf(buff, "SIZE:%dx%d OLD_FPS:%d NEW_FPS:%d ",		 &width, &height, &oldfps, &newfps) == 4) {	if (width != h0->width || height != h0->height ||	    ((h->cytype == 'O')? oldfps: newfps) != h0->fpscode) {	  WERROR("input and cycle list not match.");	  goto ERROR;	}	if (h->cytype == 'O' && newfps < fpscode) {	  WERROR("output fpscode greater than specified at 1st try.");	  goto ERROR;	}	goto RETURN;      }    }    WERROR("broken cycle list.");  ERROR:    fclose(h->cyfp);    goto ERROR_RETURN;  } RETURN:  return (YfTaskCore_t *)h; ERROR_RETURN:  if (0 <= h->deintl)    h->nframes++;  while (0 <= --h->nframes)    YfFiniFrame((YfFrame_t *)((char *)h->frame +			      (h->nframes * FRAMEBYTES(y4m_si_get_chroma(&h0->si), h0->width, h0->height))));  YfFreeTask((YfTaskCore_t *)h);  return NULL;}static voiddumpnoise(YfTask_t *h, FILE *fp){  int i;  char buf[256];  if (!h->u.noise.total)    return;  buf[0] = '\0';  buf_debug(buf, fp, "#\n");  buf_debug(buf, fp, "# noise level: %u (# of sample: %lu);  noise distribution:\n",	    h->u.noise.level, h->u.noise.total);  buf_debug(buf, fp, "#");  for (i = 0; i <= NOISEMAX; i++)    buf_debug(buf, fp, " %lu",	      (unsigned long)((((uint64_t)h->u.noise.dist[i] * 1000) +			       h->u.noise.total - 1) / h->u.noise.total));  buf_debug(buf, fp, "\n");  if (0 <= h->deintl) {    int bytes = DATABYTES(y4m_si_get_chroma(&h->_.si), h->_.width, h->_.height);    buf_debug(buf, fp, "# deinterlaced frames: %u;  pixels/frame distribution:",	      h->deintlframes);    for (i = 0; i < sizeof h->deintldist / sizeof h->deintldist[0]; i++) {      if (!(i % 10)) {	buf_debug(buf, fp, "\n");	buf_debug(buf, fp, "# %3d:", i);      }      buf_debug(buf, fp, "%7u", h->deintldist[i]);    }    buf_debug(buf, fp, "\n");    buf_debug(buf, fp, "# maximum permil of non-interlaced frames: %3d\n",	      h->nointlmax * (2 * DEINTLRESO) / bytes);    buf_debug(buf, fp, "# minimum permil of   deinterlaced frames: %3d\n",	      ((h->deintlmin == 0x7fffffff)? -1:	       (h->deintlmin * (2 * DEINTLRESO) / bytes)));  }}static voiddo_fini(YfTaskCore_t *handle){  YfTask_t *h = (YfTask_t *)handle;  while (h->iuse < h->iget)    do_frame((YfTaskCore_t *)h, NULL, NULL);  if (1 < verbose)    dumpnoise(h, NULL);  if (h->cytype == 'C') {    putc('\n', h->cyfp);    dumpnoise(h, h->cyfp);    fclose(h->cyfp);  }  if (0 <= h->deintl)    h->nframes++;  while (0 <= --h->nframes)    YfFiniFrame((YfFrame_t *)((char *)h->frame +			      (h->nframes * FRAMEBYTES(y4m_si_get_chroma(&h->_.si), h->_.width, h->_.height))));  YfFreeTask((YfTaskCore_t *)h);}static voidputcy(YfTask_t *h, int c){  MPEG_timecode_t tc;  int f;  f = mpeg_timecode(&tc, h->iuse, h->fpscode0, 0.);  if (f <= 0) {    putc('\n', h->cyfp);    if (tc.s == 0) {      if (tc.m % 10 == 0)	dumpnoise(h, h->cyfp);      fputs("#\n""#    OLD                NEW            0.... 5.... 10....15.... 20....25....\n",	    h->cyfp);    }    fprintf(h->cyfp, "%06d/%02d:%02d:%02d:%02d ", h->iuse, tc.h, tc.m, tc.s, tc.f);    mpeg_timecode(&tc, h->iput, h->_.fpscode, 0.);    fprintf(h->cyfp, "%06d/%02d:%02d:%02d:%02d", h->iput, tc.h, tc.m, tc.s, tc.f);  }  if (f < 0) {    int i;    f = -f;    for (i = -1; i <= f; i++)      putc(' ', h->cyfp);  }  if (f % 10 == 0)    putc(' ', h->cyfp);  if (f %  5 == 0)    putc(' ', h->cyfp);  if (c != '_' &&      h->framestat[h->iuse % h->nframes].eoediff == -9999999)    c += 'X' - 'O';  putc(c, h->cyfp);}static intdeinterlace(YfTask_t *h, unsigned char *data, int width, int height, int noise){  int pln, i, j, n = 0;  for (pln = 0; pln < 3; pln++) {    for (i = 1; i < height - 1; i += 2) {      for (j = 0; j < width; j++) {	int ymin = data[((i - 1) * width) + j];	int ynow = data[((i    ) * width) + j];	int ymax = data[((i + 1) * width) + j];	int ynxt = data[((i + 2) * width) + j];	if (ymax < ymin) {	  int ytmp = ymax; ymax = ymin; ymin = ytmp;	}	ymin -= noise;	ymax += noise;	if ((ynow < ymin && ynxt < ymin ) || (ymax < ynow && ymax < ynxt ))	  n++;	else if (!(ynow < ymin || ymax < ynow))	  continue;#if 0	if (i < height - 3) {	  int ynx2 = data[((i + 3) * width) + j];	  if ((ynx2 < ynxt && ynxt < ymin) || (ymax < ynxt && ynxt < ynx2))	    continue;	}#endif	ynow = (ymin + ymax) / 2;	data[((i    ) * width) + j] = ynow;	if (i < height - 3) {#if 0	  int ynx2 = data[((i + 4) * width) + j];	  if ((ynx2 < ymin && ynxt < ymin) || (ymax < ynx2 && ymax < ynxt))#endif	    continue;	}	data[((i + 2) * width) + j] = ynow;

⌨️ 快捷键说明

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