예제 #1
0
int apply_to_blocks2(void *_ctx,int _padding,plane_start_func _start,
 const block_func *_blocks,int _nfuncs,plane_finish_func _finish,int _plmask,
 int _argc,const char **_argv){
  int ai;
  for(ai=1;ai<_argc;ai++){
    video_input vid;
    video_input_info info;
    video_input_ycbcr ycbcr;
    FILE *fin;
    int pli;
    fin=fopen(_argv[ai],"rb");
    if(fin==NULL){
      fprintf(stderr,"Could not open '%s' for reading.\n",_argv[ai]);
      return EXIT_FAILURE;
    }
    if(video_input_open(&vid,fin)<0){
      fprintf(stderr,"Error reading video info from '%s'.\n",_argv[ai]);
      return EXIT_FAILURE;
    }
    video_input_get_info(&vid,&info);
    if(video_input_fetch_frame(&vid,ycbcr,NULL)<0){
      fprintf(stderr,"Error reading first frame from '%s'.\n",_argv[ai]);
      return EXIT_FAILURE;
    }
    for(pli=0;pli<3;pli++){
      if(_plmask&1<<pli){
        int x0;
        int y0;
        int nxblocks;
        int nyblocks;
        int ret;
        get_intra_dims(&info,pli,_padding,&x0,&y0,&nxblocks,&nyblocks);
        if(_start!=NULL){
          ret=(*_start)(_ctx,_argv[ai],&info,pli,nxblocks,nyblocks);
          if(ret)return ret;
        }
        if(_blocks!=NULL){
          int f;
          for(f=0;f<_nfuncs;f++){
            if(_blocks[f]!=NULL){
              const unsigned char *data;
              int                  stride;
              int                  bj;
              int                  bi;
              data=ycbcr[pli].data;
              stride=ycbcr[pli].stride;
                for(bj=0;bj<nyblocks;bj++){
                  int y;
                  y=y0+B_SZ*bj;
                  for(bi=0;bi<nxblocks;bi++){
                    int x;
                    x=x0+B_SZ*bi;
                    (*_blocks[f])(_ctx,&data[stride*y+x],stride,bi,bj);
                  }
                }
              }
           }
        }
        if(_finish!=NULL){
          ret=(*_finish)(_ctx);
          if(ret)return ret;
        }
      }
    }
    video_input_close(&vid);
  }
  return EXIT_SUCCESS;
}
예제 #2
0
int main(int _argc,char *_argv[]) {
    video_input  vid1;
    video_input_info info1;
    video_input  vid2;
    video_input_info info2;
    int64_t  gsqerr;
    int64_t  gnpixels;
    int64_t  gplsqerr[3];
    int64_t  gplnpixels[3];
    int          frameno;
    FILE        *fin;
    int          long_option_index;
    int          c;
#ifdef _WIN32
    /*We need to set stdin/stdout to binary mode on windows.
      Beware the evil ifdef.
      We avoid these where we can, but this one we cannot.
      Don't add any more, you'll probably go to hell if you do.*/
    _setmode(_fileno(stdin),_O_BINARY);
#endif
    /*Process option arguments.*/
    while((c=getopt_long(_argc,_argv,optstring,options,&long_option_index))!=EOF) {
        switch(c) {
        case 'f':
            show_frame_type=1;
            break;
        case 's':
            summary_only=1;
            break;
        case 'y':
            luma_only=1;
            break;
        default:
            usage(_argv);
            break;
        }
    }
    if(optind+2!=_argc) {
        usage(_argv);
        exit(1);
    }
    fin=strcmp(_argv[optind],"-")==0?stdin:fopen(_argv[optind],"rb");
    if(fin==NULL) {
        fprintf(stderr,"Unable to open '%s' for extraction.\n",_argv[optind]);
        exit(1);
    }
    fprintf(stderr,"Opening %s...\n",_argv[optind]);
    if(video_input_open(&vid1,fin)<0)exit(1);
    video_input_get_info(&vid1,&info1);
    fin=strcmp(_argv[optind+1],"-")==0?stdin:fopen(_argv[optind+1],"rb");
    if(fin==NULL) {
        fprintf(stderr,"Unable to open '%s' for extraction.\n",_argv[optind+1]);
        exit(1);
    }
    fprintf(stderr,"Opening %s...\n",_argv[optind+1]);
    if(video_input_open(&vid2,fin)<0)exit(1);
    video_input_get_info(&vid2,&info2);
    /*Check to make sure these videos are compatible.*/
    if(info1.pic_w!=info2.pic_w||info1.pic_h!=info2.pic_h) {
        fprintf(stderr,"Video resolution does not match.\n");
        exit(1);
    }
    if(info1.pixel_fmt!=info2.pixel_fmt) {
        fprintf(stderr,"Pixel formats do not match.\n");
        exit(1);
    }
    if((info1.pic_x&!(info1.pixel_fmt&1))!=(info2.pic_x&!(info2.pixel_fmt&1))||
            (info1.pic_y&!(info1.pixel_fmt&2))!=(info2.pic_y&!(info2.pixel_fmt&2))) {
        fprintf(stderr,"Chroma subsampling offsets do not match.\n");
        exit(1);
    }
    if(info1.fps_n*(int64_t)info2.fps_d!=
            info2.fps_n*(int64_t)info1.fps_d) {
        fprintf(stderr,"Warning: framerates do not match.\n");
    }
    if(info1.par_n*(int64_t)info2.par_d!=
            info2.par_n*(int64_t)info1.par_d) {
        fprintf(stderr,"Warning: aspect ratios do not match.\n");
    }
    gsqerr=gplsqerr[0]=gplsqerr[1]=gplsqerr[2]=0;
    gnpixels=gplnpixels[0]=gplnpixels[1]=gplnpixels[2]=0;
    for(frameno=0;; frameno++) {
        video_input_ycbcr f1;
        video_input_ycbcr f2;
        int64_t     plsqerr[3];
        long            plnpixels[3];
        int64_t     sqerr;
        long            npixels;
        int             ret1;
        int             ret2;
        int             pli;
        int             nplanes;
        ret1=video_input_fetch_frame(&vid1,f1,NULL);
        ret2=video_input_fetch_frame(&vid2,f2,NULL);
        if(ret1==0&&ret2==0)break;
        else if(ret1<0||ret2<0)break;
        else if(ret1==0) {
            fprintf(stderr,"%s ended before %s.\n",
                    _argv[optind],_argv[optind+1]);
            break;
        }
        else if(ret2==0) {
            fprintf(stderr,"%s ended before %s.\n",
                    _argv[optind+1],_argv[optind]);
            break;
        }
        /*Okay, we got one frame from each.*/
        sqerr=0;
        npixels=0;
        nplanes = luma_only ? 1 : 3;
        for(pli=0; pli<nplanes; pli++) {
            int xdec;
            int ydec;
            int y1;
            int y2;
            xdec=pli&&!(info1.pixel_fmt&1);
            ydec=pli&&!(info1.pixel_fmt&2);
            plsqerr[pli]=0;
            plnpixels[pli]=0;
            for (y1 = info1.pic_y >> ydec, y2 = info2.pic_y >> ydec;
                    y1 < (info1.pic_y + info1.pic_h + ydec) >> ydec; y1++, y2++) {
                int x1;
                int x2;
                for (x1 = info1.pic_x >> xdec, x2 = info2.pic_x >> xdec;
                        x1 < (info1.pic_x + info1.pic_w + xdec) >> xdec; x1++, x2++) {
                    int d;
                    d=*(f1[pli].data+y1*f1[pli].stride+x1)-
                      *(f2[pli].data+y2*f2[pli].stride+x2);
                    plsqerr[pli]+=d*d;
                    plnpixels[pli]++;
                }
            }
            sqerr+=plsqerr[pli];
            gplsqerr[pli]+=plsqerr[pli];
            npixels+=plnpixels[pli];
            gplnpixels[pli]+=plnpixels[pli];
        }
        if(!summary_only) {
            if(!luma_only) {
                printf("%08i: %-7G  (Y': %-7G  Cb: %-7G  Cr: %-7G)\n",frameno,
                       10*(log10(255*255)+log10(npixels)-log10(sqerr)),
                       10*(log10(255*255)+log10(plnpixels[0])-log10(plsqerr[0])),
                       10*(log10(255*255)+log10(plnpixels[1])-log10(plsqerr[1])),
                       10*(log10(255*255)+log10(plnpixels[2])-log10(plsqerr[2])));
            }
            else {
                printf("%08i: %-7G\n",frameno,
                       10*(log10(255*255)+log10(plnpixels[0])-log10(plsqerr[0])));
            }
        }
        gsqerr+=sqerr;
        gnpixels+=npixels;
    }
    if(!luma_only) {
        printf("Total: %-7G  (Y': %-7G  Cb: %-7G  Cr: %-7G)\n",
               10*(log10(255*255)+log10(gnpixels)-log10(gsqerr)),
               10*(log10(255*255)+log10(gplnpixels[0])-log10(gplsqerr[0])),
               10*(log10(255*255)+log10(gplnpixels[1])-log10(gplsqerr[1])),
               10*(log10(255*255)+log10(gplnpixels[2])-log10(gplsqerr[2])));
    }
    else {
        printf("Total: %-7G\n",
               10*(log10(255*255)+log10(gplnpixels[0])-log10(gplsqerr[0])));
    }
    video_input_close(&vid1);
    video_input_close(&vid2);
    return 0;
}
예제 #3
0
int main(int _argc, char **_argv) {
  const char *optstring = "";
  const struct option long_options[] = {
    { "output-mono-y4m", no_argument, NULL, 0 },
    { NULL, 0, NULL, 0 }
  };
  FILE *fin;
  FILE *fout;
  video_input vid;
  video_input_info info;
  int frameno;
  int pli;
  int w[3];
  int h[3];
  int xdec[3];
  int ydec[3];
  unsigned char *blank;
  int long_option_index;
  int c;
  int output_mono_y4m;

  output_mono_y4m = 0;
  while ((c = getopt_long(_argc, _argv, optstring, long_options,
   &long_option_index)) != EOF) {
    switch (c) {
      case 0: {
        if (strcmp(long_options[long_option_index].name,
         "output-mono-y4m") == 0) {
          output_mono_y4m = 1;
        }
        break;
      }
      default: {
        usage(_argv);
        exit(EXIT_FAILURE);
      }
    }
  }
  if (optind+2 != _argc) {
    usage(_argv);
    exit(EXIT_FAILURE);
  }
  fin = strcmp(_argv[optind], "-") == 0 ? stdin : fopen(_argv[optind], "rb");
  if (fin == NULL) {
    fprintf(stderr, "Unable to open '%s' for extraction.\n", _argv[optind]);
    exit(EXIT_FAILURE);
  }
  fprintf(stderr, "Opening %s as input...\n", _argv[optind]);
  if (video_input_open(&vid, fin) < 0) exit(EXIT_FAILURE);
  video_input_get_info(&vid, &info);
  fout = strcmp(_argv[optind+1], "-") == 0 ? stdout : fopen(_argv[optind+1],
   "wb");
  if (fout == NULL) {
    fprintf(stderr, "Error opening output file \"%s\".\n", _argv[optind+1]);
    return 1;
  }
  for (pli = 0; pli < 3; pli++) {
    xdec[pli] = pli && !(info.pixel_fmt&1);
    ydec[pli] = pli && !(info.pixel_fmt&2);
    w[pli] = info.pic_w >> xdec[pli];
    h[pli] = info.pic_h >> ydec[pli];
  }
  blank = malloc(w[0]*h[0]);
  memset(blank, 128, w[0]*h[0]);
  fprintf(fout, "YUV4MPEG2 W%i H%i F%i:%i Ip A%i:%i%s\n",
   info.pic_w, info.pic_h, (unsigned)info.fps_n,
   (unsigned)info.fps_d, info.par_n, info.par_d,
   output_mono_y4m ? " Cmono" : CHROMA_TAGS[ydec[1] ? xdec[1] ? 0 : 2 : 3]);
  for (frameno = 0;; frameno++) {
    video_input_ycbcr in;
    int ret = 0;
    char tag[5];
    unsigned char *src;
    int src_stride;
    int y;
    ret = video_input_fetch_frame(&vid, in, tag);
    if (ret == 0) break;
    src = in[0].data;
    src_stride = in[0].stride;
    fprintf(fout, "FRAME\n");
    for (y = 0; y < h[0]; y++) {
      if (fwrite(src + (y + info.pic_y)*src_stride + info.pic_x, w[0], 1,
       fout) < 1) {
        fprintf(stderr, "Error writing to output.\n");
        return EXIT_FAILURE;
      }
    }
    if (!output_mono_y4m) {
      for (pli = 1; pli < 3; pli++) {
        if (fwrite(blank, w[pli]*h[pli], 1, fout) < 1) {
          fprintf(stderr, "Error writing to output.\n");
          return EXIT_FAILURE;
        }
      }
    }
    fprintf(stderr, "Completed frame %d.\n", frameno);
  }
  video_input_close(&vid);
  if (fout != stdout) fclose(fout);
  return EXIT_SUCCESS;
}
예제 #4
0
int main(int _argc,char **_argv){
  video_input vid;
  video_input_info info;
  video_input_ycbcr ycbcr;
  FILE *fout;
  FILE *fin;
  const char *input_filename;
  int i;
  int xdec;
  int ydec;
  int pli;
  int xstride;
  int y;
#ifdef _WIN32
  /*We need to set stdin/stdout to binary mode.
    Damn Windows.*/
  /*Beware the evil ifdef.
    We avoid these where we can, but this one we cannot.
    Don't add any more, you'll probably go to hell if you do.*/
  _setmode(_fileno(stdin),_O_BINARY);
  _setmode(_fileno(stdout),_O_BINARY);
#endif
  for(;;){
    int long_option_index;
    int c;
    c=getopt_long(_argc,_argv,OPTSTRING,OPTIONS,&long_option_index);
    if(c==EOF)break;
    switch(c){
      case 'h':{
        usage(_argv[0]);
        return EXIT_SUCCESS;
      }
      case 'o':{
        output_filename=optarg;
        break;
      }
      default:{
        usage(_argv[0]);
        return EXIT_FAILURE;
      }
    }
  }
  if(_argc<3){
    usage(_argv[0]);
    return EXIT_FAILURE;
  }
  input_filename=_argv[optind];
  if(input_filename==NULL){
    fprintf(stderr,"No input file specified. Run with -h for help.\n");
    return EXIT_FAILURE;
  }
  fin=strcmp(input_filename,"-")==0?stdin:fopen(input_filename,"rb");
  if(fin==NULL){
    fprintf(stderr,"Could not open input file \"%s\": %s\n",
     input_filename,strerror(errno));
    return EXIT_FAILURE;
  }
  if(video_input_open(&vid,fin)<0)return EXIT_FAILURE;
  if(output_filename==NULL){
    fprintf(stderr,"No output file specified. Run with -h for help.\n");
    return EXIT_FAILURE;
  }
  video_input_get_info(&vid,&info);
  fout=strcmp(output_filename,"-")==0?
    stdout:fopen(output_filename,"w");
  xstride = info.depth > 8 ? 2 : 1;
  for(i=0;video_input_fetch_frame(&vid,ycbcr,NULL)>0;i++){
    for(pli=0;pli<3;pli++) {
      xdec=pli&&!(info.pixel_fmt&1);
      ydec=pli&&!(info.pixel_fmt&2);
      for (y = info.pic_y >> ydec;
       y < (info.pic_y + info.pic_h + ydec) >> ydec; y++) {
        CHECK_IO(fwrite,ycbcr[pli].data + y*ycbcr[pli].stride +
         (info.pic_x >> xdec)*xstride, xstride,
         (info.pic_w + xdec) >> xdec, fout);
      }
    }
  }
  if(fout!=stdout){
    fclose(fout);
  }
  video_input_close(&vid);
  return EXIT_SUCCESS;
}
예제 #5
0
파일: cfl_stats.c 프로젝트: emannion/daala
static int cfl_apply_to_blocks(void *_ctx,int _ctx_sz,int _plmask,int _padding,
 plane_start_func _start,int _nfuncs,const block_func *_funcs,
 plane_finish_func _finish,int _argc,const char *_argv[]){
  int ai;
#pragma omp parallel for schedule(dynamic)
  for(ai=1;ai<_argc;ai++){
    FILE *fin;
    video_input vid;
    video_input_info info;
    video_input_ycbcr ycbcr;
    int pli;
    int tid;
    unsigned char *ctx;
    fin=fopen(_argv[ai],"rb");
    if(fin==NULL){
      fprintf(stderr,"Could not open '%s' for reading.\n",_argv[ai]);
      continue;
    }
    if(video_input_open(&vid,fin)<0){
      fprintf(stderr,"Error reading video info from '%s'.\n",_argv[ai]);
      continue;
    }
    video_input_get_info(&vid,&info);
    if(video_input_fetch_frame(&vid,ycbcr,NULL)<0){
      fprintf(stderr,"Error reading first frame from '%s'.\n",_argv[ai]);
      continue;
    }
    tid=OD_OMP_GET_THREAD;
    ctx=((unsigned char *)_ctx)+tid*_ctx_sz;
#if OUTPUT_PLANES
    {
      char *names[]={"y","cb","cr"};
      for (pli=0;pli<3;pli++) {
        int w;
        int h;
        int u;
        int v;
        int x0;
        int y0;
        const unsigned char *data;
        w=info.pic_w>>(pli!=0);
        h=info.pic_h>>(pli!=0);
        x0=info.pic_x>>(pli!=0);
        y0=info.pic_y>>(pli!=0);
        data=ycbcr[pli].data;
        fprintf(stderr,"%s=[",names[pli]);
        for (v=0;v<h;v++) {
          for (u=0;u<w;u++) {
            if (u>0) {
              fprintf(stderr,",");
            }
            fprintf(stderr,"%i",data[(v+y0)*w+u+x0]);
          }
          if (v<h) {
            fprintf(stderr,";");
          }
        }
        fprintf(stderr,"];\n");
      }
    }
#endif
    for(pli=0;pli<3;pli++){
      if(_plmask&1<<pli){
        int x0;
        int y0;
        int nxblocks;
        int nyblocks;
        cfl_get_intra_dims(&info,pli,_padding,&x0,&y0,&nxblocks,&nyblocks);
        if(_start!=NULL){
          (*_start)(ctx,_argv[ai],&info,pli,nxblocks,nyblocks);
        }
        if(_funcs!=NULL){
          int f;
          for(f=0;f<_nfuncs;f++){
            if(_funcs[f]!=NULL){
              const unsigned char *data;
              int                  stride;
              int                  bj;
              int                  bi;
              data=ycbcr[pli].data;
              stride=ycbcr[pli].stride;
              for(bj=0;bj<nyblocks;bj++){
                int y;
                y=y0+(bj<<B_SZ_LOG-(pli!=0));
                for(bi=0;bi<nxblocks;bi++){
                  int x;
                  x=x0+(bi<<B_SZ_LOG-(pli!=0));
                  (*_funcs[f])(ctx,&data[stride*y+x],stride,bi,bj);
                }
              }
            }
          }
        }
        if(_finish!=NULL){
          (*_finish)(ctx);
        }
      }
    }
    video_input_close(&vid);
  }
  return EXIT_SUCCESS;
}
예제 #6
0
static void process_files(trans_ctx *_ctx,
                          cov_state *_cov,
                          int _argc,
                          const char *_argv[]){

  int ai;
#pragma omp parallel for schedule(dynamic)
  for(ai=1;ai<_argc;ai++){
    FILE *fin;
    video_input vid;
    video_input_info info;
    video_input_ycbcr ycbcr;
    int tid;
    cov_state *cov;
    int x0,y0,x1,y1;

    fin=fopen(_argv[ai],"rb");
    if(fin==NULL){
      fprintf(stderr,"Could not open '%s' for reading.\n",_argv[ai]);
      continue;
    }
    if(video_input_open(&vid,fin)<0){
      fprintf(stderr,"Error reading video info from '%s'.\n",_argv[ai]);
      continue;
    }
    video_input_get_info(&vid,&info);
    if(video_input_fetch_frame(&vid,ycbcr,NULL)<0){
      fprintf(stderr,"Error reading first frame from '%s'.\n",_argv[ai]);
      continue;
    }
    tid=OD_OMP_GET_THREAD;
    cov=_cov+tid;
    x0 = info.pic_x;
    y0 = info.pic_y;
    x1 = x0 + info.pic_w;
    y1 = y0 + info.pic_h;

    fprintf(stderr,"%s\n",_argv[ai]);

    /* map */
    {
      int                  stride=ycbcr[0].stride;
      const unsigned char *data=ycbcr[0].data;

#if COMPUTE_NATHAN
      /* block-based full covariance computation (unlord style) */

      int nxblocks=info.pic_w>>BLOCKSIZE_LOG;
      int nyblocks=info.pic_h>>BLOCKSIZE_LOG;
      trans_ctx *ctx=_ctx+tid;

# if USE_2D
      unsigned char        buf[SUPPORT][SUPPORT];
      int                  x,y,i,j;
      image_ctx_init(&ctx->img,_argv[ai],nxblocks,nyblocks);
      for(y=0;y<nyblocks*BLOCKSIZE-SUPPORT+1;y++){
        for(x=0;x<nxblocks*BLOCKSIZE-SUPPORT+1;x++){
          for(j=0;j<SUPPORT;j++){
            for(i=0;i<SUPPORT;i++){
              buf[j][i]=data[(y0+y+j)*stride+(x0+x+i)];
            }
          }
          trans_data_add(&ctx->td,(unsigned char *)buf);
        }
      }
# else
      unsigned char        buf[SUPPORT];
      int                  x,y,z;
      image_ctx_init(&ctx->img,_argv[ai],nxblocks,nyblocks);
      /* add the rows */
      for(y=0;y<nyblocks*BLOCKSIZE;y++){
        for(x=0;x<nxblocks*BLOCKSIZE-SUPPORT+1;x++){
          for(z=0;z<SUPPORT;z++){
            buf[z]=data[(y+y0)*stride+x+x0+z];
          }
          trans_data_add(&ctx->td,buf);
        }
      }
      /* add the columns */
      for(y=0;y<nyblocks*BLOCKSIZE-SUPPORT+1;y++){
        for(x=0;x<nxblocks*BLOCKSIZE;x++){
          for(z=0;z<SUPPORT;z++){
            buf[z]=data[(y0+y+z)*stride+x+x0];
          }
          trans_data_add(&ctx->td,buf);
        }
      }

# endif
#endif

      /* Direct computation of collapsed covariance matrix (monty style) */
#if USE_2D
      cov_accumulate_2d(cov,data+y0*stride+x0,stride,x1-x0,y1-y0);
#else
      {
        int x,y;

        for(y=y0;y<y1;y++)
          cov_accumulate_1d(cov,data+y*stride+x0,1,x1-x0);
        for(x=x0;x<x1;x++)
          cov_accumulate_1d(cov,data+y0*stride+x,stride,y1-y0);
      }
#endif

    }

    video_input_close(&vid);
  }
}
예제 #7
0
파일: upsample.c 프로젝트: fidalco/daala
int main(int _argc, char **_argv) {
  const char *optstring = "";
  const struct option long_options[] = {
    { NULL, 0, NULL, 0 }
  };
  FILE *fin;
  FILE *fout;
  video_input vid;
  video_input_info info;
  int frameno;
  int pli;
  int xdec[3];
  int ydec[3];
  int w[3];
  int h[3];
  int long_option_index;
  int c;
  od_state state;
  daala_info dinfo;

  while ((c = getopt_long(_argc, _argv, optstring, long_options,
   &long_option_index)) != EOF) {
    switch (c) {
      default: {
        usage(_argv);
        exit(EXIT_FAILURE);
      }
    }
  }
  if (optind+2 != _argc) {
    usage(_argv);
    exit(EXIT_FAILURE);
  }
  fin = strcmp(_argv[optind], "-") == 0 ? stdin : fopen(_argv[optind], "rb");
  if (fin == NULL) {
    fprintf(stderr, "Unable to open '%s' for extraction.\n", _argv[optind]);
    exit(EXIT_FAILURE);
  }
  fprintf(stderr, "Opening %s as input...\n", _argv[optind]);
  if (video_input_open(&vid, fin) < 0) exit(EXIT_FAILURE);
  video_input_get_info(&vid, &info);

  daala_info_init(&dinfo);
  for (pli = 0; pli < 3; pli++) {
    xdec[pli] = pli && !(info.pixel_fmt&1);
    ydec[pli] = pli && !(info.pixel_fmt&2);
    h[pli] = info.pic_h >> ydec[pli];
    w[pli] = info.pic_w >> xdec[pli];

    dinfo.plane_info[pli].xdec = xdec[pli];
    dinfo.plane_info[pli].ydec = ydec[pli];
  }
  dinfo.nplanes = 3;
  dinfo.pic_height = h[0];
  dinfo.pic_width = w[0];

  od_state_init(&state, &dinfo);

  fout = strcmp(_argv[optind+1], "-") == 0 ? stdout : fopen(_argv[optind+1],
   "wb");
  if (fout == NULL) {
    fprintf(stderr, "Error opening output file \"%s\".\n", _argv[optind+1]);
    return 1;
  }
  fprintf(fout, "YUV4MPEG2 W%i H%i F%i:%i Ip A%i:%i%s\n",
   info.pic_w*2, info.pic_h*2, (unsigned)info.fps_n,
   (unsigned)info.fps_d, info.par_n, info.par_d,
   CHROMA_TAGS[ydec[1] ? xdec[1] ? 0 : 2 : 3]);
  for (frameno = 0;; frameno++) {
    video_input_ycbcr in;
    int ret = 0;
    char tag[5];
    od_img *simg = &state.io_imgs[OD_FRAME_REC];
    od_img *dimg = &state.ref_imgs[0];
    int x, y;
    ret = video_input_fetch_frame(&vid, in, tag);
    if (ret == 0) break;
    for (pli = 0; pli < 3; pli++) {
      od_img_plane *siplane = simg->planes + pli;
      unsigned char *src = siplane->data;
      int src_stride = siplane->ystride;
      int plane_width = simg->width >> xdec[pli];
      int plane_height = simg->height >> ydec[pli];
      for (y = 0; y < h[pli]; y++) {
        for (x = 0; x < w[pli]; x++) {
          int cy = y + (int)(info.pic_y >> ydec[pli]);
          int cx = x + (int)(info.pic_x >> xdec[pli]);
          src[y*src_stride + x] = in[pli].data[cy*in[pli].stride + cx];
        }
      }
      /*From od_img_plane_copy_pad8*/
      /*Right side.*/
      for (x = w[pli]; x < plane_width; x++) {
        src = siplane->data + x - 1;
        for (y = 0; y < h[pli]; y++) {
          src[1] = (2*src[0] + (src - (src_stride & -(y > 0)))[0]
           + (src + (src_stride & -(y + 1 < h[pli])))[0] + 2) >> 2;
          src += src_stride;
        }
      }
      /*Bottom.*/
      src = siplane->data + src_stride*h[pli];
      for (y = h[pli]; y < plane_height; y++) {
        for (x = 0; x < plane_width; x++) {
          src[x] = (2*(src - src_stride)[x] + (src - src_stride)[x - (x > 0)]
           + (src - src_stride)[x + (x + 1 < plane_width)] + 2) >> 2;
        }
        src += src_stride;
      }
    }
    od_state_upsample8(&state, dimg, simg);
    fprintf(fout, "FRAME\n");
    for (pli = 0; pli < 3; pli++) {
      od_img_plane *diplane = dimg->planes + pli;
      unsigned char *dst = diplane->data;
      for (y = 0; y < 2*h[pli]; y++) {
        if (fwrite(dst + diplane->ystride*y, 2*w[pli], 1, fout) < 1) {
          fprintf(stderr, "Error writing to output.\n");
          return EXIT_FAILURE;
        }
      }
    }
    fprintf(stderr, "Completed frame %d.\n", frameno);
  }
  video_input_close(&vid);
  if (fout != stdout) fclose(fout);
  return EXIT_SUCCESS;
}