| rev |
line source |
|
nengel@1
|
1 /*
|
|
nengel@1
|
2 * H264 decoder main
|
|
nengel@1
|
3 */
|
|
nengel@1
|
4
|
|
nengel@1
|
5 #include "config.h"
|
|
nengel@1
|
6 #include "libavcodec/h264.h"
|
|
nengel@1
|
7
|
|
nengel@1
|
8 #include <string.h>
|
|
nengel@1
|
9 #include <stdlib.h>
|
|
nengel@1
|
10 #include <errno.h>
|
|
nengel@1
|
11 #include <signal.h>
|
|
nengel@1
|
12 #include <unistd.h>
|
|
nengel@1
|
13 #include <getopt.h>
|
|
nengel@1
|
14 #include <fcntl.h>
|
|
nengel@1
|
15
|
|
nengel@1
|
16 #include <sys/types.h>
|
|
nengel@1
|
17 #include <sys/time.h>
|
|
nengel@1
|
18 #include <sys/resource.h>
|
|
nengel@1
|
19 #include <time.h>
|
|
nengel@1
|
20
|
|
nengel@1
|
21 #include <assert.h>
|
|
nengel@1
|
22
|
|
nengel@1
|
23
|
|
nengel@1
|
24 static const char program_name[] = "h264dec";
|
|
nengel@1
|
25 static const int program_birth_year = 2010;
|
|
nengel@1
|
26
|
|
nengel@1
|
27 static const char *file_name;
|
|
nengel@1
|
28 static int ifile, ofile;
|
|
nengel@1
|
29 static int no_arch =0;
|
|
nengel@1
|
30 static int parallel = 1;
|
|
nengel@1
|
31 static int frame_width = 0;
|
|
nengel@1
|
32 static int frame_height = 0;
|
|
nengel@1
|
33
|
|
nengel@1
|
34 static void av_exit(int ret)
|
|
nengel@1
|
35 {
|
|
nengel@1
|
36 //do some free calls
|
|
nengel@1
|
37 #undef exit
|
|
nengel@1
|
38 exit(ret);
|
|
nengel@1
|
39 }
|
|
nengel@1
|
40
|
|
nengel@1
|
41 static void opt_input_file(const char *filename)
|
|
nengel@1
|
42 {
|
|
nengel@1
|
43 /* open the input file */
|
|
nengel@1
|
44 ifile = open(filename, O_RDONLY, 0666);
|
|
nengel@1
|
45 if (ifile < 0){
|
|
nengel@1
|
46 fprintf(stderr, "Failed to open %s\n", filename);
|
|
nengel@1
|
47 av_exit(-1);
|
|
nengel@1
|
48 }
|
|
nengel@1
|
49
|
|
nengel@1
|
50 //parse first frame to get resolution (other information available but not used)
|
|
nengel@1
|
51 H264Slice slice;
|
|
nengel@1
|
52 PictureInfo pi;
|
|
nengel@1
|
53 GetBitContext gb = {0,};
|
|
nengel@1
|
54 ParserContext *pc;
|
|
nengel@1
|
55 NalContext *nc;
|
|
nengel@1
|
56
|
|
nengel@1
|
57 pc = get_parse_context(ifile);
|
|
nengel@1
|
58 nc = get_nal_context(0, 0);
|
|
nengel@1
|
59
|
|
nengel@1
|
60 memset(&slice, 0, sizeof(H264Slice));
|
|
nengel@1
|
61 slice.current_picture_info=π
|
|
nengel@1
|
62
|
|
nengel@1
|
63 av_read_frame_internal(pc, &gb);
|
|
nengel@1
|
64 decode_nal_units(nc, &slice, &gb);
|
|
nengel@1
|
65
|
|
nengel@1
|
66 frame_width = nc->width;
|
|
nengel@1
|
67 frame_height= nc->height;
|
|
nengel@1
|
68
|
|
nengel@1
|
69 //clean up
|
|
nengel@1
|
70 av_freep(&gb.raw);
|
|
nengel@1
|
71 if (gb.rbsp)
|
|
nengel@1
|
72 av_freep(&gb.rbsp);
|
|
nengel@1
|
73 free_parse_context(pc);
|
|
nengel@1
|
74 free_nal_context(nc);
|
|
nengel@1
|
75
|
|
nengel@1
|
76 //rewind file
|
|
nengel@1
|
77 int offset;
|
|
nengel@1
|
78 if ( (offset=lseek(ifile, 0, SEEK_SET)) ){
|
|
nengel@1
|
79 fprintf(stderr, "Rewind input file %s failed at offset %d\n", filename, offset);
|
|
nengel@1
|
80 }
|
|
nengel@1
|
81
|
|
nengel@1
|
82 }
|
|
nengel@1
|
83
|
|
nengel@1
|
84 static void opt_output_file(const char *filename)
|
|
nengel@1
|
85 {
|
|
nengel@1
|
86 if (filename){
|
|
nengel@1
|
87 if (!strcmp(filename, "-"))
|
|
nengel@1
|
88 filename = "pipe:";
|
|
nengel@1
|
89
|
|
nengel@1
|
90 ofile = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0666);
|
|
nengel@1
|
91 }else{
|
|
nengel@1
|
92 ofile =0;
|
|
nengel@1
|
93 }
|
|
nengel@1
|
94 }
|
|
nengel@1
|
95
|
|
nengel@1
|
96 static void show_usage(void)
|
|
nengel@1
|
97 {
|
|
nengel@1
|
98 printf("usage: ffmpeg [options] -i infile }...\n");
|
|
nengel@1
|
99 printf("\n");
|
|
nengel@1
|
100 }
|
|
nengel@1
|
101
|
|
nengel@1
|
102 static struct option long_options[] = {
|
|
nengel@1
|
103 {"static-sched", 0, 0, 0},
|
|
nengel@1
|
104 {"static-mbd", 0, 0, 0},
|
|
nengel@1
|
105 {"numamap", 0, 0, 0},
|
|
nengel@1
|
106 {"no-mbd", 0, 0, 0},
|
|
nengel@1
|
107 {"static-3d", 0, 0, 0},
|
|
nengel@1
|
108 {"slice-bufs", 1, 0, 0},
|
|
nengel@1
|
109 {"smt", 0, 0, 0},
|
|
nengel@1
|
110 {"noarch", 0, 0, 'a'},
|
|
nengel@1
|
111 {"display", 0, 0, 'd'},
|
|
nengel@1
|
112 {"fullscreen", 0, 0, 'f'},
|
|
nengel@1
|
113 {"numframes", 1, 0, 'n'},
|
|
nengel@1
|
114 {"use-ppe-ed", 1, 0, 'p'},
|
|
nengel@1
|
115 {"sequential", 0, 0, 's'},
|
|
nengel@1
|
116 {"threads", 1, 0, 't'},
|
|
nengel@1
|
117 {"verbose", 1, 0, 'v'},
|
|
nengel@1
|
118 {"wave-order", 1, 0, 'w'},
|
|
nengel@1
|
119 {"smb-size", 1, 0, 'z'},
|
|
nengel@1
|
120 {"pipe-bufs", 1, 0, 'e'},
|
|
nengel@1
|
121 {0, 0, 0, 0}
|
|
nengel@1
|
122 };
|
|
nengel@1
|
123
|
|
nengel@1
|
124 static h264_options cli_opts;
|
|
nengel@1
|
125 static void parse_cmd(int argc, char **argv)
|
|
nengel@1
|
126 {
|
|
nengel@1
|
127 int c;
|
|
nengel@1
|
128 int digit_optind = 0;
|
|
nengel@1
|
129 int option_index = 0;
|
|
nengel@1
|
130 char ofile_name[1024];
|
|
nengel@1
|
131 extern char *optarg;
|
|
nengel@1
|
132 extern int optind, optopt;
|
|
nengel@1
|
133
|
|
nengel@1
|
134 cli_opts.statsched =0;
|
|
nengel@1
|
135 cli_opts.numamap =0;
|
|
nengel@1
|
136 cli_opts.statmbd =0;
|
|
nengel@1
|
137 cli_opts.no_mbd= 0;
|
|
nengel@1
|
138 cli_opts.numframes = INT_MAX;
|
|
nengel@1
|
139 cli_opts.display=0;
|
|
nengel@1
|
140 cli_opts.fullscreen=0;
|
|
nengel@1
|
141 cli_opts.verbose=0;
|
|
nengel@1
|
142 cli_opts.ppe_ed=0;
|
|
nengel@1
|
143 cli_opts.profile=0;
|
|
nengel@1
|
144 cli_opts.threads = 1;
|
|
nengel@1
|
145 cli_opts.smb_size[0] = cli_opts.smb_size[1] = 1;
|
|
nengel@1
|
146 cli_opts.wave_order=0;
|
|
nengel@1
|
147 cli_opts.static_3d=0;
|
|
nengel@1
|
148 cli_opts.pipe_bufs=8;
|
|
nengel@1
|
149 cli_opts.slice_bufs=1;
|
|
nengel@1
|
150 cli_opts.smt= 0;
|
|
nengel@1
|
151 while ((c = getopt_long(argc, argv, "ade:fi:n:o:p:st:vwz:", long_options, &option_index)) != -1 ){
|
|
nengel@1
|
152 int this_option_optind = optind ? optind : 1;
|
|
nengel@1
|
153
|
|
nengel@1
|
154 switch (c){
|
|
nengel@1
|
155 case 0:
|
|
nengel@1
|
156 if (option_index==0){
|
|
nengel@1
|
157 cli_opts.statsched=1;
|
|
nengel@1
|
158 }else if (option_index==1){
|
|
nengel@1
|
159 cli_opts.statmbd= 1;
|
|
nengel@1
|
160 }else if (option_index==2){
|
|
nengel@1
|
161 cli_opts.numamap= 1;
|
|
nengel@1
|
162 }else if (option_index==3){
|
|
nengel@1
|
163 cli_opts.no_mbd= 1;
|
|
nengel@1
|
164 }else if (option_index==4){
|
|
nengel@1
|
165 cli_opts.static_3d= 1;
|
|
nengel@1
|
166 }else if (option_index==5){
|
|
nengel@1
|
167 cli_opts.slice_bufs= (unsigned) atoi(optarg);
|
|
nengel@1
|
168 }else if (option_index==6){
|
|
nengel@1
|
169 cli_opts.smt= 1;
|
|
nengel@1
|
170 }
|
|
nengel@1
|
171 break;
|
|
nengel@1
|
172 case '0':
|
|
nengel@1
|
173 case '1':
|
|
nengel@1
|
174 case '2':
|
|
nengel@1
|
175 if (digit_optind != 0 && digit_optind != this_option_optind)
|
|
nengel@1
|
176 printf("digits occur in two different argv-elements.\n");
|
|
nengel@1
|
177 digit_optind = this_option_optind;
|
|
nengel@1
|
178 printf("option %c\n", c);
|
|
nengel@1
|
179 break;
|
|
nengel@1
|
180 case 'a':
|
|
nengel@1
|
181 no_arch=1;
|
|
nengel@1
|
182 break;
|
|
nengel@1
|
183 case 'd':
|
|
nengel@1
|
184 cli_opts.display=1;
|
|
nengel@1
|
185 break;
|
|
nengel@1
|
186 case 'f':
|
|
nengel@1
|
187 cli_opts.fullscreen=1;
|
|
nengel@1
|
188 break;
|
|
nengel@1
|
189 case 'i':
|
|
nengel@1
|
190 file_name = (const char *)optarg;
|
|
nengel@1
|
191 opt_input_file(file_name);
|
|
nengel@1
|
192 break;
|
|
nengel@1
|
193 case 'n':
|
|
nengel@1
|
194 cli_opts.numframes = (unsigned) atoi(optarg);
|
|
nengel@1
|
195 break;
|
|
nengel@1
|
196 case 'o':
|
|
nengel@1
|
197 strcpy(ofile_name, optarg);
|
|
nengel@1
|
198 opt_output_file(ofile_name);
|
|
nengel@1
|
199 break;
|
|
nengel@1
|
200 case 'p':
|
|
nengel@1
|
201 cli_opts.profile = (unsigned) atoi(optarg);
|
|
nengel@1
|
202 break;
|
|
nengel@1
|
203 case 's':
|
|
nengel@1
|
204 cli_opts.threads = 0;
|
|
nengel@1
|
205 parallel = 0;
|
|
nengel@1
|
206 break;
|
|
nengel@1
|
207 case 't':
|
|
nengel@1
|
208 cli_opts.threads = atoi(optarg);
|
|
nengel@1
|
209 if (cli_opts.threads<=0){
|
|
nengel@1
|
210 fprintf(stderr, "Option -%c requires thread numbers > 0\n", c);
|
|
nengel@1
|
211 av_exit(-1);
|
|
nengel@1
|
212 }
|
|
nengel@1
|
213 break;
|
|
nengel@1
|
214 case 'v':
|
|
nengel@1
|
215 cli_opts.verbose = 1;
|
|
nengel@1
|
216 break;
|
|
nengel@1
|
217 case 'w':
|
|
nengel@1
|
218 cli_opts.wave_order = 1;
|
|
nengel@1
|
219 break;
|
|
nengel@1
|
220 case 'z': // only useful in ompss
|
|
nengel@1
|
221 if (argc < optind +1){
|
|
nengel@1
|
222 fprintf(stderr, "Option -%c (--smb-size) requires 2 arguments\n", c);
|
|
nengel@1
|
223 av_exit(-1);
|
|
nengel@1
|
224 }
|
|
nengel@1
|
225 optind--;
|
|
nengel@1
|
226 for (int i=0; i<2; i++){
|
|
nengel@1
|
227 cli_opts.smb_size[i] = atoi(argv[optind++]);
|
|
nengel@1
|
228 if (!(cli_opts.smb_size > 0)){
|
|
nengel@1
|
229 fprintf(stderr, "Option -%c (--smb-size) requires dimensions > 0\n", c);
|
|
nengel@1
|
230 av_exit(-1);
|
|
nengel@1
|
231 }
|
|
nengel@1
|
232 }
|
|
nengel@1
|
233 break;
|
|
nengel@1
|
234 case 'e':
|
|
nengel@1
|
235 cli_opts.pipe_bufs = atoi(optarg);
|
|
nengel@1
|
236 break;
|
|
nengel@1
|
237 case ':':
|
|
nengel@1
|
238 fprintf(stderr, "Option -%c requires an operand\n", optopt);
|
|
nengel@1
|
239 av_exit(-1);
|
|
nengel@1
|
240 break;
|
|
nengel@1
|
241 case '?':
|
|
nengel@1
|
242 fprintf(stderr, "Unrecognized option: -%c\n", optopt);
|
|
nengel@1
|
243 av_exit(-1);
|
|
nengel@1
|
244 break;
|
|
nengel@1
|
245 }
|
|
nengel@1
|
246 }
|
|
nengel@1
|
247
|
|
nengel@1
|
248 }
|
|
nengel@1
|
249
|
|
nengel@1
|
250 int main(int argc, char **argv)
|
|
nengel@1
|
251 {
|
|
nengel@1
|
252 /* parse options */
|
|
nengel@1
|
253 parse_cmd(argc, argv);
|
|
nengel@1
|
254
|
|
nengel@1
|
255 if(!ifile ) {
|
|
nengel@1
|
256 show_usage();
|
|
nengel@1
|
257 av_exit(1);
|
|
nengel@1
|
258 }
|
|
nengel@1
|
259
|
|
nengel@1
|
260 H264Context *h = get_h264dec_context(file_name, ifile, ofile, frame_width, frame_height, &cli_opts);
|
|
nengel@1
|
261 #if OMPSS
|
|
nengel@1
|
262 if (h264_decode_ompss( h ) < 0)
|
|
nengel@1
|
263 av_exit(-1);
|
|
nengel@1
|
264 #else
|
|
nengel@1
|
265 if (parallel){
|
|
nengel@1
|
266 if (ARCH_CELL && !no_arch){
|
|
nengel@1
|
267 if (h264_decode_cell( h ) < 0)
|
|
nengel@1
|
268 av_exit(-1);
|
|
nengel@1
|
269 }else{
|
|
nengel@1
|
270 if (h264_decode_pthread( h ) < 0)
|
|
nengel@1
|
271 av_exit(1);
|
|
nengel@1
|
272 }
|
|
nengel@1
|
273 }else{
|
|
nengel@1
|
274 if (ARCH_CELL && !no_arch){
|
|
nengel@1
|
275 if (h264_decode_cell_seq( h ) < 0)
|
|
nengel@1
|
276 av_exit(1);
|
|
nengel@1
|
277 }else{
|
|
nengel@1
|
278 if (h264_decode_seq( h ) < 0)
|
|
nengel@1
|
279 av_exit(1);
|
|
nengel@1
|
280 }
|
|
nengel@1
|
281 }
|
|
nengel@1
|
282 #endif
|
|
nengel@1
|
283 free_h264dec_context(h);
|
|
nengel@1
|
284 close(ifile);
|
|
nengel@1
|
285 close(ofile);
|
|
nengel@1
|
286
|
|
nengel@1
|
287 return 0;
|
|
nengel@1
|
288 }
|