Add tools/y4m2yuv.c.
[daala.git] / tools / y4m2yuv.c
1 /*Daala video codec
2 Copyright (c) 2002-2012 Daala project contributors.  All rights reserved.
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6
7 - Redistributions of source code must retain the above copyright notice, this
8   list of conditions and the following disclaimer.
9
10 - Redistributions in binary form must reproduce the above copyright notice,
11   this list of conditions and the following disclaimer in the documentation
12   and/or other materials provided with the distribution.
13
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #if !defined(_LARGEFILE_SOURCE)
30 # define _LARGEFILE_SOURCE
31 #endif
32 #if !defined(_LARGEFILE64_SOURCE)
33 # define _LARGEFILE64_SOURCE
34 #endif
35 #if !defined(_FILE_OFFSET_BITS)
36 # define _FILE_OFFSET_BITS 64
37 #endif
38 #if !defined(_BSD_SOURCE)
39 # define _BSD_SOURCE
40 # define _DEFAULT_SOURCE
41 #endif
42 #include <stdint.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <errno.h>
47 #include <limits.h>
48 #if !defined(_WIN32)
49 # include <getopt.h>
50 #else
51 # include <fcntl.h>
52 # include <io.h>
53 # include "getopt.h"
54 #endif
55 #include "vidinput.h"
56
57 /*Helper macro to validate fwrite/fread operations*/
58 #define CHECK_IO(func,ptr,size,nmemb,stream)      \
59   if(func(ptr,size,nmemb,stream)<(size_t)nmemb){  \
60     fprintf(stderr,#func"() error\n");            \
61     return 1;                                     \
62   }
63
64 static const char *output_filename=NULL;
65
66 const char *OPTSTRING="ho:";
67 struct option OPTIONS[]={
68   {"help",no_argument,NULL,'h'},
69   {"output",required_argument,NULL,'o'},
70   {NULL,0,NULL,0}
71 };
72
73 static void usage(const char *_argv0){
74   fprintf(stderr,
75    "Usage: %s [options] -o <filename.yuv> <input.y4m>\n\n"
76    "Options: \n\n"
77    "  -h --help                       Display this help and exit.\n"
78    "  -o --output <filename.yuv>      Output file name (required).\n",
79    _argv0);
80 }
81
82 int main(int _argc,char **_argv){
83   video_input vid;
84   video_input_info info;
85   video_input_ycbcr ycbcr;
86   FILE *fout;
87   FILE *fin;
88   const char *input_filename;
89   int i;
90   int xdec;
91   int ydec;
92   int pli;
93   int xstride;
94   int y;
95 #ifdef _WIN32
96   /*We need to set stdin/stdout to binary mode.
97     Damn Windows.*/
98   /*Beware the evil ifdef.
99     We avoid these where we can, but this one we cannot.
100     Don't add any more, you'll probably go to hell if you do.*/
101   _setmode(_fileno(stdin),_O_BINARY);
102   _setmode(_fileno(stdout),_O_BINARY);
103 #endif
104   for(;;){
105     int long_option_index;
106     int c;
107     c=getopt_long(_argc,_argv,OPTSTRING,OPTIONS,&long_option_index);
108     if(c==EOF)break;
109     switch(c){
110       case 'h':{
111         usage(_argv[0]);
112         return EXIT_SUCCESS;
113       }
114       case 'o':{
115         output_filename=optarg;
116         break;
117       }
118       default:{
119         usage(_argv[0]);
120         return EXIT_FAILURE;
121       }
122     }
123   }
124   if(_argc<3){
125     usage(_argv[0]);
126     return EXIT_FAILURE;
127   }
128   input_filename=_argv[optind];
129   if(input_filename==NULL){
130     fprintf(stderr,"No input file specified. Run with -h for help.\n");
131     return EXIT_FAILURE;
132   }
133   fin=strcmp(input_filename,"-")==0?stdin:fopen(input_filename,"rb");
134   if(fin==NULL){
135     fprintf(stderr,"Could not open input file \"%s\": %s\n",
136      input_filename,strerror(errno));
137     return EXIT_FAILURE;
138   }
139   if(video_input_open(&vid,fin)<0)return EXIT_FAILURE;
140   if(output_filename==NULL){
141     fprintf(stderr,"No output file specified. Run with -h for help.\n");
142     return EXIT_FAILURE;
143   }
144   video_input_get_info(&vid,&info);
145   fout=strcmp(output_filename,"-")==0?
146     stdout:fopen(output_filename,"w");
147   xstride = info.depth > 8 ? 2 : 1;
148   for(i=0;video_input_fetch_frame(&vid,ycbcr,NULL)>0;i++){
149     for(pli=0;pli<3;pli++) {
150       xdec=pli&&!(info.pixel_fmt&1);
151       ydec=pli&&!(info.pixel_fmt&2);
152       for (y = info.pic_y >> ydec;
153        y < (info.pic_y + info.pic_h + ydec) >> ydec; y++) {
154         CHECK_IO(fwrite,ycbcr[pli].data + y*ycbcr[pli].stride +
155          (info.pic_x >> xdec)*xstride, xstride,
156          (info.pic_w + xdec) >> xdec, fout);
157       }
158     }
159   }
160   if(fout!=stdout){
161     fclose(fout);
162   }
163   video_input_close(&vid);
164   return EXIT_SUCCESS;
165 }