1 /* ***** BEGIN LICENSE BLOCK *****
2 *
3 * $Id: encmain.cpp,v 1.86 2008/10/29 02:42:06 asuraparaju Exp $ $Name: Dirac_1_0_2 $
4 *
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 *
7 * The contents of this file are subject to the Mozilla Public License
8 * Version 1.1 (the "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
14 * the specific language governing rights and limitations under the License.
15 *
16 * The Original Code is BBC Research and Development code.
17 *
18 * The Initial Developer of the Original Code is the British Broadcasting
19 * Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 2004.
21 * All Rights Reserved.
22 *
23 * Contributor(s): Thomas Davies (Original Author),
24 * Scott R Ladd,
25 * Anuradha Suraparaju,
26 * Andrew Kennedy,
27 * David Flynn,
28 * Johannes Reinhardt,
29 * Myo Tun (Brunel University)
30 *
31 * Alternatively, the contents of this file may be used under the terms of
32 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
33 * Public License Version 2.1 (the "LGPL"), in which case the provisions of
34 * the GPL or the LGPL are applicable instead of those above. If you wish to
35 * allow use of your version of this file only under the terms of the either
36 * the GPL or LGPL and not to allow others to use your version of this file
37 * under the MPL, indicate your decision by deleting the provisions above
38 * and replace them with the notice and other provisions required by the GPL
39 * or LGPL. If you do not delete the provisions above, a recipient may use
40 * your version of this file under the terms of any one of the MPL, the GPL
41 * or the LGPL.
42 * ***** END LICENSE BLOCK ***** */
43
44 #include <time.h>
45 #include <iostream>
46 #include <limits>
47 #include <fstream>
48 #include <set>
49 #include <cmath>
50 #include <ctime>
51 #include <cassert>
52 #include <string>
53 #include <libdirac_encoder/dirac_encoder.h>
54 #include <sys/types.h>
55 #include <sys/stat.h>
56 #include <fcntl.h>
57 #include <cstdlib>
58 #include <cstring>
59 #include <climits>
60
61 using namespace std;
62
63 const int VIDEO_BUFFER_SIZE = 32*1024*1024;
64 unsigned char video_buf[VIDEO_BUFFER_SIZE];
65
display_help()66 static void display_help()
67 {
68 cout << "\nDIRAC wavelet video coder.";
69 cout << "\n";
70 cout << "\nUsage: progname -<flag1> [<flag1_val>] ... <input> <output>";
71 cout << "\nIn case of multiple assignment to the same parameter, the last holds.";
72 cout << "\n";
73 cout << "\nName Type Default Value Description";
74 cout << "\n==== ==== ============= =========== ";
75 cout << "\nQSIF525 bool false Use QSIF compression presets";
76 cout << "\nQCIF bool false Use QCIF compression presets";
77 cout << "\nSIF525 bool false Use SIF compression presets";
78 cout << "\nCIF bool false Use CIF compression presets";
79 cout << "\n4CIF bool false Use 4CIF compression presets";
80 cout << "\n4SIF525 bool false Use 4SIF compression presets";
81 cout << "\nSD480I60 bool false Use SD-480 compression presets";
82 cout << "\nSD576I50 bool false Use SD-576 compression presets";
83 cout << "\nHD720P60 bool false Use HD-720P60 compression presets";
84 cout << "\nHD720P50 bool false Use HD-720P50 compression presets";
85 cout << "\nHD1080I60 bool false Use HD-1080I60 compression presets";
86 cout << "\nHD1080I50 bool false Use HD-1080I50 compression presets";
87 cout << "\nHD1080P60 bool false Use HD-1080P60 compression presets";
88 cout << "\nHD1080P50 bool false Use HD-1080P50 compression presets";
89 cout << "\nUHDTV4K60 bool false Use UHDTV 4K60 compression presets";
90 cout << "\nUHDTV4K50 bool false Use UHDTV 4K50 compression presets";
91 cout << "\nUHDTV8K60 bool false Use UHDTV 8K60 compression presets";
92 cout << "\nUHDTV8K50 bool false Use UHDTV 8K50 compression presets";
93 cout << "\nDC2K24 bool false Use DIGITAL CINEMA 2K compression presets";
94 cout << "\nDC4K24 bool false Use DIGITAL CINEMA 4K compression presets";
95 cout << "\nfull_search ulong ulong 0UL 0UL Use full search motion estimation";
96 cout << "\ncombined_me bool false Use a combination of all 3 components to do ME";
97 cout << "\nwidth ulong Preset Width of frame";
98 cout << "\nheight ulong Preset Length of frame";
99 cout << "\nheight ulong Preset Length of frame";
100 cout << "\ncformat string YUV444P Chroma Sampling Format (YUV444P YUV422P YUV420P)";
101 cout << "\nfr ulong Preset Frame rate(s) (e.n or e/n format)";
102 cout << "\nsource_sampling string progressive source material type either progressive or interlaced";
103 cout << "\nstart ulong 0UL Frame number to start encoding from";
104 cout << "\nstop ulong EOF Frame number after which encoding finishes";
105 cout << "\nfield_coding bool false Set picture coding type to field coding. Default coding type is by frames";
106 cout << "\nL1_sep ulong 0UL Separation of L1 frames";
107 cout << "\nnum_L1 ulong 0UL Number of L1 frames";
108 cout << "\nxblen ulong 0UL Overlapping block horizontal length";
109 cout << "\nyblen ulong 0UL Overlapping block vertical length";
110 cout << "\nxbsep ulong 0UL Overlapping block horizontal separation";
111 cout << "\nybsep ulong 0UL Overlapping block vertical separation";
112 cout << "\ncpd ulong 0UL Perceptual weighting - vertical cycles per deg.";
113 cout << "\nqf float 0.0F Overall quality factor (>0, typically: 7=medium, 9=high)";
114 cout << "\ntargetrate ulong 0UL Target Bit Rate in Kbps";
115 cout << "\nlossless bool false Lossless coding (overrides qf)";
116 cout << "\niwlt_filter string DD13_7 Intra frame Transform Filter (DD9_7 LEGALL5_3 DD13_7 HAAR0 HAAR1 FIDELITY DAUB9_7)";
117 cout << "\nrwlt_filter string DD13_7 Inter frame Transform Filter (DD9_7 LEGALL5_3 DD13_7 HAAR0 HAAR1 FIDELITY DAUB9_7)";
118 cout << "\nwlt_depth ulong 4 Transform Depth";
119 cout << "\nmulti_quants bool false Use multiple quantisers";
120 cout << "\nmv_prec string false MV Pixel Precision (1, 1/2, 1/4, 1/8)";
121 cout << "\nno_spartition bool false Do not use spatial partitioning while coding transform data";
122 cout << "\nprefilter string/int NO_PF 0 Prefilter input giving filter name (NO_PF, CWM, RECTLP, DIAGLP) and strength (0-10)";
123 cout << "\nuse_vlc bool false Use VLC for entropy coding of coefficients";
124 cout << "\nlocal bool false Write diagnostics & locally decoded video";
125 cout << "\nverbose bool false Verbose mode";
126 cout << "\nh|help bool false Display help message";
127 cout << "\ninput string [ required ] Input file name";
128 cout << "\noutput string [ required ] Output file name [May not be '-']";
129 cout << endl;
130 }
131
132
133
WritePicData(std::ofstream & fdata,dirac_encoder_t * encoder)134 bool WritePicData (std::ofstream &fdata, dirac_encoder_t *encoder)
135 {
136 dirac_sourceparams_t &sparams = encoder->enc_ctx.src_params;
137 dirac_framebuf_t &fbuf = encoder->dec_buf;
138 bool ret_stat = true;
139
140 if (encoder->decoded_frame_avail)
141 {
142 ios::iostate oldExceptions = fdata.exceptions();
143 fdata.exceptions (ios::failbit | ios::badbit);
144 try
145 {
146 assert (fbuf.buf[0] != 0);
147 fdata.write ((char *)fbuf.buf[0], sparams.width*sparams.height);
148 assert (fbuf.buf[1] != 0);
149 assert (fbuf.buf[2] != 0);
150 fdata.write ((char *)fbuf.buf[1],
151 sparams.chroma_width*sparams.chroma_height);
152 fdata.write ((char *)fbuf.buf[2],
153 sparams.chroma_width*sparams.chroma_height);
154 }
155 catch (...)
156 {
157 std::cout << "Incomplete frame " << std::endl;
158 ret_stat = false;
159 }
160 fdata.exceptions (oldExceptions);
161 }
162 return ret_stat;
163 }
164
WriteDiagnosticsHeader(std::ofstream & fdata,dirac_encoder_t * encoder)165 bool WriteDiagnosticsHeader (std::ofstream &fdata, dirac_encoder_t *encoder)
166 {
167 bool ret_stat = true;
168 dirac_sourceparams_t &srcparams = encoder->enc_ctx.src_params;
169 ios::iostate oldExceptions = fdata.exceptions();
170 fdata.exceptions (ios::failbit | ios::badbit);
171
172 try
173 {
174 fdata << srcparams.chroma << std::endl;
175 fdata << srcparams.width << std::endl;
176 fdata << srcparams.height << std::endl;
177 fdata << srcparams.source_sampling << std::endl;
178 fdata << srcparams.topfieldfirst << std::endl;
179 fdata << srcparams.frame_rate.numerator << std::endl;
180 fdata << srcparams.frame_rate.denominator << std::endl;
181 fdata << srcparams.pix_asr.numerator << std::endl;
182 fdata << srcparams.pix_asr.denominator << std::endl;
183 fdata << encoder->enc_ctx.enc_params.picture_coding_mode << std::endl;
184 }
185
186 catch (...)
187 {
188 std::cerr << "Error writing sequence info in diagnostics file." << std::endl;
189 ret_stat = false;
190 }
191 fdata.exceptions (oldExceptions);
192 return ret_stat;
193 }
194
WriteDiagnosticsData(std::ofstream & fdata,dirac_encoder_t * encoder)195 bool WriteDiagnosticsData (std::ofstream &fdata, dirac_encoder_t *encoder)
196 {
197 dirac_instr_t &instr = encoder->instr;
198 bool ret_stat = true;
199
200 if (encoder->instr_data_avail)
201 {
202 ios::iostate oldExceptions = fdata.exceptions();
203 fdata.exceptions (ios::failbit | ios::badbit);
204 try
205 {
206 fdata << std::endl << "[frame:" << instr.pnum << "]";
207 if (instr.ptype == INTRA_PICTURE)
208 {
209 fdata << ">intra" << std::endl;
210 return true;
211 }
212
213 fdata << ">mo_comp";
214 fdata << std::endl << std::endl << instr.num_refs << " ";
215 for (int i=0; i<instr.num_refs; ++i)
216 {
217 fdata << instr.refs[i] << " ";
218 }
219 fdata << instr.ybsep << " " << instr.xbsep << " ";
220 fdata << instr.sb_ylen << " " << instr.sb_xlen << " ";
221 fdata << instr.mv_ylen << " " << instr.mv_xlen
222 << std::endl << std::endl ;
223 for (int j=0; j<instr.sb_ylen; j++)
224 {
225 for (int i=0; i<instr.sb_xlen; i++)
226 fdata << instr.sb_split_mode[j*instr.sb_xlen + i] << " ";
227 fdata << std::endl;
228 }
229 fdata << std::endl;
230
231 for (int j=0; j<instr.sb_ylen; j++)
232 {
233 for (int i=0; i<instr.sb_xlen; i++)
234 fdata << instr.sb_costs[j*instr.sb_xlen + i] << " ";
235 fdata << std::endl;
236 }
237 fdata << std::endl;
238
239 for (int j=0; j<instr.mv_ylen; j++)
240 {
241 for (int i=0; i<instr.mv_xlen; i++)
242 fdata << instr.pred_mode[j*instr.mv_xlen + i] << " ";
243 fdata << std::endl;
244 }
245 fdata << std::endl;
246
247 for (int j=0; j<instr.mv_ylen; j++)
248 {
249 for (int i=0; i<instr.mv_xlen; i++)
250 fdata << instr.intra_costs[j*instr.mv_xlen + i] << " ";
251 fdata << std::endl;
252 }
253 fdata << std::endl;
254
255 if (instr.num_refs > 1)
256 {
257 for (int j=0; j<instr.mv_ylen; j++)
258 {
259 for (int i=0; i<instr.mv_xlen; i++)
260 {
261 fdata << instr.bipred_costs[j*instr.mv_xlen + i].SAD
262 <<" " << instr.bipred_costs[j*instr.mv_xlen + i].mvcost
263 << " ";;
264 }
265 fdata << std::endl;
266 }
267 }
268 fdata << std::endl;
269
270 for (int j=0; j<instr.mv_ylen; j++)
271 {
272 for (int i=0; i<instr.mv_xlen; i++)
273 fdata << instr.dc_ycomp[j*instr.mv_xlen + i] << " ";
274 fdata << std::endl;
275 }
276
277 // FIXME: always expects 3 components
278 fdata << std::endl;
279 for (int j=0; j<instr.mv_ylen; j++)
280 {
281 for (int i=0; i<instr.mv_xlen; i++)
282 fdata << instr.dc_ucomp[j*instr.mv_xlen + i] << " ";
283 fdata << std::endl;
284 }
285 fdata << std::endl;
286 for (int j=0; j<instr.mv_ylen; j++)
287 {
288 for (int i=0; i<instr.mv_xlen; i++)
289 fdata << instr.dc_vcomp[j*instr.mv_xlen + i] << " ";
290 fdata << std::endl;
291 }
292
293 for (int k = 0; k < instr.num_refs; k++)
294 {
295 fdata << std::endl;
296 for (int j=0; j<instr.mv_ylen; j++)
297 {
298 for (int i=0; i<instr.mv_xlen; i++)
299 {
300 fdata << instr.mv[k][j*instr.mv_xlen + i].x
301 <<" " << instr.mv[k][j*instr.mv_xlen + i].y
302 << " ";;
303 }
304 fdata << std::endl;
305 }
306 fdata << std::endl;
307 for (int j=0; j<instr.mv_ylen; j++)
308 {
309 for (int i=0; i<instr.mv_xlen; i++)
310 {
311 fdata << instr.pred_costs[k][j*instr.mv_xlen + i].SAD
312 <<" " << instr.pred_costs[k][j*instr.mv_xlen + i].mvcost
313 << " ";;
314 }
315 fdata << std::endl;
316 }
317 fdata << std::endl;
318 }
319 }
320 catch (...)
321 {
322 std::cout << "Error writing diagnostics data" << std::endl;
323 ret_stat = false;
324 }
325 fdata.exceptions (oldExceptions);
326 }
327 return ret_stat;
328 }
329
ReadPicData(std::ifstream & fdata,unsigned char * buffer,int frame_size)330 bool ReadPicData (std::ifstream &fdata, unsigned char *buffer, int frame_size)
331 {
332 bool ret_stat = true;
333
334 ios::iostate oldExceptions = fdata.exceptions();
335 fdata.exceptions (ios::failbit | ios::badbit);
336 try
337 {
338 fdata.read ((char *)buffer, frame_size);
339 }
340 catch (...)
341 {
342 ret_stat = false;
343 }
344 fdata.exceptions (oldExceptions);
345 return ret_stat;
346 }
347
Skip(std::ifstream & fdata,int start_frame,int frame_size)348 bool Skip (std::ifstream &fdata, int start_frame, int frame_size)
349 {
350 bool ret_stat = true;
351 ios::iostate oldExceptions = fdata.exceptions();
352 fdata.exceptions (ios::failbit | ios::badbit);
353 try
354 {
355 unsigned char* buffer = new unsigned char[frame_size];
356 for (int i=0; i<start_frame; ++i)
357 ReadPicData(fdata, buffer, frame_size);
358 delete[] buffer;
359 }
360 catch (...)
361 {
362 std::cerr << "Skipping of first "<< start_frame << " frames failed"
363 << std::endl;
364 ret_stat = false;
365 }
366 fdata.exceptions (oldExceptions);
367 return ret_stat;
368 }
369
GetFrameBufferSize(const dirac_encoder_context_t & enc_ctx)370 int GetFrameBufferSize (const dirac_encoder_context_t &enc_ctx)
371 {
372 int xl = enc_ctx.src_params.width;
373 int yl = enc_ctx.src_params.height;
374
375 int size;
376
377 switch (enc_ctx.src_params.chroma)
378 {
379 case format420:
380 size = (xl*yl*3)/2;
381 break;
382 case format422:
383 size = (xl*yl)*2;
384 break;
385 case format444:
386 size = (xl*yl)*3;
387 break;
388 default:
389 size = xl * yl;
390 break;
391 }
392 return size;
393 }
ChromaToString(dirac_chroma_t chroma)394 const string ChromaToString (dirac_chroma_t chroma)
395 {
396 switch (chroma)
397 {
398 case format422:
399 return string("YUV422P");
400
401 case format444:
402 return string("YUV444P");
403
404 case format420:
405 return string("YUV420P");
406
407 default:
408 break;
409 }
410
411 return string("Unknown");
412 }
413
PrefilterToString(dirac_prefilter_t pf)414 const string PrefilterToString(dirac_prefilter_t pf)
415 {
416 switch (pf)
417 {
418 case CWM:
419 return string("CWM");
420 case RECTLP:
421 return string("RECTLP");
422 case DIAGLP:
423 return string("DIAGLP");
424 default:
425 return string("NO_PF");
426 };
427
428 }
429
StringToChroma(const char * chroma)430 dirac_chroma_t StringToChroma (const char* chroma)
431 {
432 if (strcmp(chroma, "YUV444P") == 0)
433 return format444;
434 else if (strcmp(chroma, "YUV422P") == 0)
435 return format422;
436 else if (strcmp(chroma, "YUV420P") == 0)
437 return format420;
438 else
439 return formatNK;
440 }
441
MvPrecisionToString(MVPrecisionType mv_type)442 const string MvPrecisionToString (MVPrecisionType mv_type)
443 {
444 switch (mv_type)
445 {
446 case MV_PRECISION_PIXEL:
447 return string("Pixel");
448 case MV_PRECISION_HALF_PIXEL:
449 return string("Half Pixel");
450 case MV_PRECISION_QUARTER_PIXEL:
451 return string("Quarter Pixel");
452 case MV_PRECISION_EIGHTH_PIXEL:
453 return string("Eighth Pixel");
454 default:
455 return string("Undefined");
456 }
457 }
458
TransformFilterToString(WltFilter wf)459 const string TransformFilterToString (WltFilter wf)
460 {
461 switch (wf)
462 {
463 case DD9_7:
464 return string("DD9_7");
465 case LEGALL5_3:
466 return string("LEGALL5_3");
467 case DD13_7:
468 return string("DD13_7");
469 case HAAR0:
470 return string("HAAR0");
471 case HAAR1:
472 return string("HAAR1");
473 case FIDELITY:
474 return string("FIDELITY");
475 case DAUB9_7:
476 return string("DAUB9_7");
477 default:
478 return string("Undefined");
479 }
480 }
481
StringToTransformFilter(string wf)482 WltFilter StringToTransformFilter (string wf)
483 {
484 if( wf=="DD9_7" )
485 return DD9_7;
486 else if( wf=="LEGALL5_3" )
487 return LEGALL5_3;
488 else if( wf=="DD13_7" )
489 return DD13_7;
490 else if( wf=="HAAR0" )
491 return HAAR0;
492 else if( wf=="HAAR1" )
493 return HAAR1;
494 else if( wf=="FIDELITY" )
495 return FIDELITY;
496 else if( wf=="DAUB9_7" )
497 return DAUB9_7;
498 else
499 return filterNK;
500 }
501
display_codec_params(dirac_encoder_context_t & enc_ctx)502 void display_codec_params(dirac_encoder_context_t &enc_ctx)
503 {
504 std::cout << "Source parameters : " << std::endl;
505 std::cout << "\theight=" << enc_ctx.src_params.height;
506 std::cout << " width=" << enc_ctx.src_params.width << std::endl;
507 std::cout << "\tchroma=" << ChromaToString(enc_ctx.src_params.chroma) << std::endl;
508 std::cout << "\tframe rate=" << enc_ctx.src_params.frame_rate.numerator;
509 std::cout << "/" << enc_ctx.src_params.frame_rate.denominator << std::endl;
510 std::cout << "Encoder parameters : " << std::endl;
511 std::cout << "\tquality factor=" << enc_ctx.enc_params.qf << std::endl;
512 std::cout << "\tGOP parameters : num_L1=" << enc_ctx.enc_params.num_L1;
513 if (enc_ctx.enc_params.num_L1 != 0)
514 {
515 std::cout << " L1_sep=" << enc_ctx.enc_params.L1_sep << std::endl;
516 std::cout << "\tBlock parameters : xblen=" << enc_ctx.enc_params.xblen;
517 std::cout << " yblen=" << enc_ctx.enc_params.yblen;
518 std::cout << " xbsep=" << enc_ctx.enc_params.xbsep;
519 std::cout << " ybsep=" << enc_ctx.enc_params.ybsep << std::endl;
520 std::cout << " \tMV Precision=" << MvPrecisionToString(enc_ctx.enc_params.mv_precision) << std::endl;
521 std::cout << " \tInter Frame Transform Filter=" << TransformFilterToString(enc_ctx.enc_params.inter_wlt_filter) << std::endl;
522 }
523 else
524 std::cout << " (I-frame only coding)" << std::endl;
525 std::cout << " \tIntra Frame Transform Filter=" << TransformFilterToString(enc_ctx.enc_params.intra_wlt_filter) << std::endl;
526 std::cout << " \tWavelet depth=" << enc_ctx.enc_params.wlt_depth << std::endl;
527 std::cout << " \tSpatial Partitioning=" << (enc_ctx.enc_params.spatial_partition ? "true" : "false") << std::endl;
528 std::cout << " \tMultiple Quantisers=" << (enc_ctx.enc_params.multi_quants ? "true" : "false") << std::endl;
529 std::cout << " \tPrefilter=" << PrefilterToString(enc_ctx.enc_params.prefilter) << std::endl;
530 std::cout << " \tField coding=" << (enc_ctx.enc_params.picture_coding_mode == 1? "true" : "false") << std::endl;
531 std::cout << " \tLossless Coding=" << (enc_ctx.enc_params.lossless ? "true" : "false") << std::endl;
532 std::cout << " \tEntropy Coding=" << (enc_ctx.enc_params.using_ac ? "Arithmetic Coding" : "Variable Length Coding") << std::endl;
533 }
534
535 int start_pos = 0;
536 int end_pos = -1;
537 bool verbose = false;
538 bool nolocal = true;
539 int fields_factor = 1;
540
parse_command_line(dirac_encoder_context_t & enc_ctx,int argc,char ** argv)541 bool parse_command_line(dirac_encoder_context_t& enc_ctx, int argc, char **argv)
542 {
543 /********** command line parameter parsing*********/
544
545 // An array indicating whether a parameter has been parsed
546 bool* parsed = new bool[argc];
547
548 // Program name has been parsed
549 parsed[0] = true;
550
551 // No other parameters
552 for (int i=1 ; i<argc ; ++i )
553 parsed[i] = false;
554
555 // The start and end-points of the parts of the file to be coded
556 // (end_pos set to -1 means code to the end)
557
558 memset (&enc_ctx, 0, sizeof(dirac_encoder_context_t));
559
560 //Now do the options
561 // Checking for presets. Assume custom by default
562 dirac_encoder_presets_t preset = VIDEO_FORMAT_CUSTOM;
563 for (int i = 1; i < argc; i++)
564 {
565 if ( strcmp(argv[i], "-help") == 0 ||
566 strcmp(argv[i], "-h") == 0)
567 {
568 display_help();
569 exit(EXIT_SUCCESS);
570 }
571 else if ( strcmp (argv[i], "-QSIF525") == 0 )
572 {
573 preset = VIDEO_FORMAT_QSIF525;
574 parsed[i] = true;
575 }
576 else if ( strcmp (argv[i], "-QCIF") == 0 )
577 {
578 preset = VIDEO_FORMAT_QCIF;
579 parsed[i] = true;
580 }
581 else if ( strcmp (argv[i], "-SIF525") == 0 )
582 {
583 preset = VIDEO_FORMAT_SIF525;
584 parsed[i] = true;
585 }
586 else if ( strcmp (argv[i], "-CIF") == 0 )
587 {
588 preset = VIDEO_FORMAT_CIF;
589 parsed[i] = true;
590 }
591 else if ( strcmp (argv[i], "-4CIF") == 0 )
592 {
593 preset = VIDEO_FORMAT_4CIF;
594 parsed[i] = true;
595 }
596 else if ( strcmp (argv[i], "-4SIF525") == 0 )
597 {
598 preset = VIDEO_FORMAT_4SIF525;
599 parsed[i] = true;
600 }
601 else if ( strcmp (argv[i], "-SD480I60") == 0 )
602 {
603 preset = VIDEO_FORMAT_SD_480I60;
604 parsed[i] = true;
605 }
606 else if ( strcmp (argv[i], "-SD576I50") == 0 )
607 {
608 preset = VIDEO_FORMAT_SD_576I50;
609 parsed[i] = true;
610 }
611 else if ( strcmp (argv[i], "-HD720P60") == 0 )
612 {
613 preset = VIDEO_FORMAT_HD_720P60;
614 parsed[i] = true;
615 }
616 else if ( strcmp (argv[i], "-HD720P50") == 0 )
617 {
618 preset = VIDEO_FORMAT_HD_720P50;
619 parsed[i] = true;
620 }
621 else if ( strcmp (argv[i], "-HD1080I60") == 0 )
622 {
623 preset = VIDEO_FORMAT_HD_1080I60;
624 parsed[i] = true;
625 }
626 else if ( strcmp (argv[i], "-HD1080I50") == 0 )
627 {
628 preset = VIDEO_FORMAT_HD_1080I50;
629 parsed[i] = true;
630 }
631 else if ( strcmp (argv[i], "-HD1080P60") == 0 )
632 {
633 preset = VIDEO_FORMAT_HD_1080P60;
634 parsed[i] = true;
635 }
636 else if ( strcmp (argv[i], "-HD1080P50") == 0 )
637 {
638 preset = VIDEO_FORMAT_HD_1080P50;
639 parsed[i] = true;
640 }
641 else if ( strcmp (argv[i], "-UHDTV4K60") == 0 )
642 {
643 preset = VIDEO_FORMAT_UHDTV_4K60;
644 parsed[i] = true;
645 }
646 else if ( strcmp (argv[i], "-UHDTV4K50") == 0 )
647 {
648 preset = VIDEO_FORMAT_UHDTV_4K50;
649 parsed[i] = true;
650 }
651 else if ( strcmp (argv[i], "-UHDTV8K60") == 0 )
652 {
653 preset = VIDEO_FORMAT_UHDTV_8K60;
654 parsed[i] = true;
655 }
656 else if ( strcmp (argv[i], "-UHDTV8K50") == 0 )
657 {
658 preset = VIDEO_FORMAT_UHDTV_8K50;
659 parsed[i] = true;
660 }
661 else if ( strcmp (argv[i], "-DC2K24") == 0 )
662 {
663 preset = VIDEO_FORMAT_DIGI_CINEMA_2K24;
664 parsed[i] = true;
665 }
666 else if ( strcmp (argv[i], "-DC4K24") == 0 )
667 {
668 preset = VIDEO_FORMAT_DIGI_CINEMA_4K24;
669 parsed[i] = true;
670 }
671 }
672
673 // initialise the encoder context
674 dirac_encoder_context_init (&enc_ctx, preset);
675
676 //now go over again and override video format presets with other values
677 for(int i=1; i < argc; )
678 {
679 if ( strcmp(argv[i], "-width") == 0 )
680 {
681 parsed[i] = true;
682 i++;
683 enc_ctx.src_params.width =
684 strtoul(argv[i],NULL,10);
685 parsed[i] = true;
686 }
687 else if ( strcmp(argv[i], "-height") == 0 )
688 {
689 parsed[i] = true;
690 i++;
691 enc_ctx.src_params.height =
692 strtoul(argv[i],NULL,10);
693 parsed[i] = true;
694 }
695 else if ( strcmp(argv[i], "-cformat") == 0 )
696 {
697 parsed[i] = true;
698 i++;
699 enc_ctx.src_params.chroma = StringToChroma (argv[i]);
700 if (enc_ctx.src_params.chroma == formatNK)
701 {
702 cerr << "Unsupported chroma format" << argv[i] << endl;
703 parsed[i] = false;
704 }
705 else
706 parsed[i] = true;
707 }
708 else if ( strcmp(argv[i], "-fr") == 0 )
709 {
710 parsed[i] = true;
711 i++;
712 if(strncmp(argv[i], "59.94", 5)==0)
713 {
714 parsed[i] = true;
715 enc_ctx.src_params.frame_rate.numerator=60000;
716 enc_ctx.src_params.frame_rate.denominator=1001;
717 }
718 else if(strncmp(argv[i], "23.98", 5)==0)
719 {
720 parsed[i] = true;
721 enc_ctx.src_params.frame_rate.numerator=24000;
722 enc_ctx.src_params.frame_rate.denominator=1001;
723 }
724 else if(strncmp(argv[i], "29.97", 5)==0)
725 {
726 parsed[i] = true;
727 enc_ctx.src_params.frame_rate.numerator=30000;
728 enc_ctx.src_params.frame_rate.denominator=1001;
729 }
730 //test for decimal format
731 else if(strcspn(argv[i], ".")!=strlen(argv[i]))
732 {
733 parsed[i] = true;
734 // look for whole number
735 char* num_token = strtok(argv[i], ".");
736 int whole = strtoul(num_token,NULL,10);
737 int decimal=0;
738 int decimal_length=0;
739
740 // look for decimal part
741 num_token = strtok(NULL, "");
742 if(num_token)
743 {
744 decimal_length=strlen(num_token);
745 decimal=strtoul(num_token, NULL, 10);
746 }
747 // calculate amount to raise to whole number
748 int multiply = (int)std::pow(10.0, decimal_length);
749 enc_ctx.src_params.frame_rate.numerator =
750 decimal == 0 ? whole : (multiply*whole)+decimal;
751 enc_ctx.src_params.frame_rate.denominator =
752 decimal == 0 ? 1 : multiply;
753
754 }
755 else
756 {
757 parsed[i] = true;
758 // assume e/d format
759 char* token = strtok(argv[i], "/");
760 enc_ctx.src_params.frame_rate.numerator =
761 strtoul(token,NULL,10);
762 enc_ctx.src_params.frame_rate.denominator = 1;
763
764 token = strtok(NULL, "");
765 if(token)
766 enc_ctx.src_params.frame_rate.denominator =
767 strtoul(token, NULL, 10);
768 }
769 }
770 else if ( strcmp(argv[i], "-source_sampling") == 0 )
771 {
772 parsed[i] = true;
773 i++;
774 parsed[i]= true;
775 if (!strcmp(argv[i], "progressive"))
776 enc_ctx.src_params.source_sampling = 0;
777 else if (!strcmp(argv[i], "interlaced"))
778 enc_ctx.src_params.source_sampling = 1;
779 else
780 {
781 cerr << "source_sampling should either be interlaced or progressive" << endl;
782 parsed[i] = false;
783 }
784 }
785 i++;
786 }
787
788 // finally, set the encoding paramters
789
790 // For small pictures, set better (more expensive) parameters
791 if (enc_ctx.src_params.width*enc_ctx.src_params.height<(702*480*2)/3){
792 enc_ctx.enc_params.mv_precision = MV_PRECISION_QUARTER_PIXEL;
793 enc_ctx.enc_params.xblen = 12;
794 enc_ctx.enc_params.yblen = 12;
795 enc_ctx.enc_params.xbsep = 8;
796 enc_ctx.enc_params.ybsep = 8;
797 }
798
799 for (int i=0; i<argc; ){
800 if ( strcmp(argv[i], "-field_coding") == 0 )
801 {
802 parsed[i] = true;
803 enc_ctx.enc_params.picture_coding_mode = 1;
804 fields_factor = 2;
805 }
806 else if ( strcmp(argv[i], "-qf") == 0 )
807 {
808 parsed[i] = true;
809 i++;
810 enc_ctx.enc_params.qf = atof(argv[i]);
811 parsed[i] = true;
812 }
813 else if ( strcmp(argv[i], "-full_search") == 0 )
814 {
815 parsed[i] = true;
816 enc_ctx.enc_params.full_search = 1;
817 i++;
818
819 enc_ctx.enc_params.x_range_me = strtoul(argv[i],NULL,10);
820 parsed[i] = true;
821
822 i++;
823 enc_ctx.enc_params.y_range_me = strtoul(argv[i],NULL,10);
824 parsed[i] = true;
825
826 }
827 else if ( strcmp(argv[i], "-combined_me") == 0 )
828 {
829 parsed[i] = true;
830 enc_ctx.enc_params.combined_me = 1;
831 }
832 else if ( strcmp(argv[i], "-targetrate") == 0 )
833 {
834 parsed[i] = true;
835 i++;
836 enc_ctx.enc_params.trate = strtoul(argv[i],NULL,10);
837 parsed[i] = true;
838 }
839 else if ( strcmp(argv[i], "-lossless") == 0 )
840 {
841 parsed[i] = true;
842 enc_ctx.enc_params.lossless = true;
843 }
844 else if ( strcmp(argv[i], "-L1_sep") == 0 )
845 {
846 parsed[i] = true;
847 i++;
848 enc_ctx.enc_params.L1_sep =
849 strtoul(argv[i],NULL,10);
850 parsed[i] = true;
851 }
852 else if ( strcmp(argv[i], "-num_L1") == 0 )
853 {
854 parsed[i] = true;
855 i++;
856 enc_ctx.enc_params.num_L1 =
857 strtoul(argv[i],NULL,10);
858 parsed[i] = true;
859 }
860 else if ( strcmp(argv[i], "-xblen") == 0 )
861 {
862 parsed[i] = true;
863 i++;
864 enc_ctx.enc_params.xblen =
865 strtoul(argv[i],NULL,10);
866 parsed[i] = true;
867 }
868 else if ( strcmp(argv[i], "-yblen") == 0 )
869 {
870 parsed[i] = true;
871 i++;
872 enc_ctx.enc_params.yblen =
873 strtoul(argv[i],NULL,10);
874 parsed[i] = true;
875 }
876 else if ( strcmp(argv[i], "-xbsep") == 0 )
877 {
878 parsed[i] = true;
879 i++;
880 enc_ctx.enc_params.xbsep =
881 strtoul(argv[i],NULL,10);
882 parsed[i] = true;
883 }
884 else if ( strcmp(argv[i], "-ybsep") == 0 )
885 {
886 parsed[i] = true;
887 i++;
888 enc_ctx.enc_params.ybsep =
889 strtoul(argv[i],NULL,10);
890 parsed[i] = true;
891 }
892 else if ( strcmp(argv[i], "-cpd") == 0 )
893 {
894 parsed[i] = true;
895 i++;
896 enc_ctx.enc_params.cpd =
897 strtoul(argv[i],NULL,10);
898 parsed[i] = true;
899 }
900 else if ( strcmp(argv[i], "-use_vlc") == 0 )
901 {
902 parsed[i] = true;
903 enc_ctx.enc_params.using_ac = false;
904 }
905 else if ( strcmp(argv[i], "-verbose") == 0 )
906 {
907 parsed[i] = true;
908 verbose = true;
909 }
910 else if ( strcmp(argv[i], "-local") == 0 )
911 {
912 parsed[i] = true;
913 nolocal = false;
914 }
915 else if ( strcmp(argv[i], "-start") == 0 )
916 {
917 parsed[i] = true;
918 i++;
919 start_pos = strtoul(argv[i],NULL,10);
920 parsed[i] = true;
921 }
922 else if ( strcmp(argv[i], "-stop") == 0 )
923 {
924 parsed[i] = true;
925 i++;
926 end_pos = strtoul(argv[i],NULL,10);
927 parsed[i] = true;
928 }
929 else if ( strcmp(argv[i], "-multi_quants") == 0 )
930 {
931 parsed[i] = true;
932 enc_ctx.enc_params.multi_quants = true;
933 }
934 else if ( strcmp(argv[i], "-no_spartition") == 0 )
935 {
936 parsed[i] = true;
937 enc_ctx.enc_params.spatial_partition = false;
938 }
939 else if ( strcmp(argv[i], "-prefilter") == 0 )
940 {
941 parsed[i] = true;
942 i++;
943 if(strcmp(argv[i], "DIAGLP")==0)
944 {
945 parsed[i] = true;
946 enc_ctx.enc_params.prefilter = DIAGLP;
947 i++;
948 enc_ctx.enc_params.prefilter_strength =
949 strtoul(argv[i],NULL,10);
950 parsed[i] = true;
951 }
952 else if(strcmp(argv[i], "RECTLP")==0)
953 {
954 parsed[i] = true;
955 enc_ctx.enc_params.prefilter = RECTLP;
956 i++;
957 enc_ctx.enc_params.prefilter_strength =
958 strtoul(argv[i],NULL,10);
959 parsed[i] = true;
960 }
961 else if(strcmp(argv[i], "CWM")==0)
962 {
963 parsed[i] = true;
964 enc_ctx.enc_params.prefilter = CWM;
965 i++;
966 enc_ctx.enc_params.prefilter_strength =
967 strtoul(argv[i],NULL,10);
968 parsed[i] = true;
969 }
970 else if(strcmp(argv[i], "NO_PF")==0)
971 {
972 parsed[i] = true;
973 enc_ctx.enc_params.prefilter = NO_PF;
974 i++;
975 enc_ctx.enc_params.prefilter_strength =
976 strtoul(argv[i],NULL,10);
977 parsed[i] = true;
978 }
979 }
980 else if ( strcmp(argv[i], "-wlt_depth") == 0 )
981 {
982 parsed[i] = true;
983 i++;
984 enc_ctx.enc_params.wlt_depth = strtoul(argv[i],NULL,10);
985 #if defined(HAVE_MMX)
986 if(enc_ctx.enc_params.wlt_depth > 4)
987 cerr << "Exceeds maximum transform depth ";
988 else
989 parsed[i] = true;
990 #else
991 parsed[i] = true;
992 #endif
993 }
994 else if ( strcmp(argv[i], "-iwlt_filter") == 0 )
995 {
996 parsed[i] = true;
997 i++;
998 WltFilter wf = StringToTransformFilter(string(argv[i]));
999 if (wf == filterNK)
1000 cerr << "Unrecognised Intra Wavelet Filter " << argv[i];
1001 else
1002 parsed[i] = true;
1003 enc_ctx.enc_params.intra_wlt_filter = wf;
1004 }
1005 else if ( strcmp(argv[i], "-rwlt_filter") == 0 )
1006 {
1007 parsed[i] = true;
1008 i++;
1009 WltFilter wf = StringToTransformFilter(argv[i]);
1010 if (wf == filterNK)
1011 cerr << "Unrecognised Intra Wavelet Filter " << argv[i];
1012 else
1013 parsed[i] = true;
1014 enc_ctx.enc_params.inter_wlt_filter = wf;
1015 }
1016 else if ( strcmp(argv[i], "-mv_prec") == 0 )
1017 {
1018 parsed[i]=true;
1019 ++i;
1020 if(strcmp(argv[i], "1/2")==0)
1021 {
1022 parsed[i] = true;
1023 enc_ctx.enc_params.mv_precision = MV_PRECISION_HALF_PIXEL;
1024 }
1025 else if(strcmp(argv[i], "1/4")==0)
1026 {
1027 parsed[i] = true;
1028 enc_ctx.enc_params.mv_precision = MV_PRECISION_QUARTER_PIXEL;
1029 }
1030 else if(strcmp(argv[i], "1/8")==0)
1031 {
1032 parsed[i] = true;
1033 enc_ctx.enc_params.mv_precision = MV_PRECISION_EIGHTH_PIXEL;
1034 }
1035 else if(strncmp(argv[i], "1", 3)==0)
1036 {
1037 parsed[i] = true;
1038 enc_ctx.enc_params.mv_precision = MV_PRECISION_PIXEL;
1039 }
1040 }
1041 i++;
1042 }//opt
1043
1044 // FIXME: currently only supporting vlc coding for iframe-only
1045 // sequences
1046 if (enc_ctx.enc_params.num_L1 != 0 && enc_ctx.enc_params.using_ac == 0)
1047 {
1048 std::cerr<<std::endl<<"Entropy coding of coefficient data using VLC currently enabled for i-frame only sequences only"<<std::endl;
1049 return false;
1050 }
1051
1052 // check we have parsed everything
1053 bool all_parsed = true;
1054 for (int i=0 ; i<argc-2 ; ++i)
1055 {
1056 if ( !parsed[i] )
1057 {
1058 all_parsed = false;
1059 std::cerr<<std::endl<<"Unknown option "<<argv[i];
1060 }
1061 }
1062 if ( !all_parsed )
1063 {
1064 display_help();
1065 return false;
1066 }
1067
1068 /* check that we have been suplied with input and output files */
1069 if(argc < 2 || parsed[argc-2] || parsed[argc-1]) {
1070 display_help();
1071 std::cerr<<std::endl<<"Insufficient arguments"<<std::endl;
1072 return false;
1073 }
1074
1075
1076 delete[] parsed;
1077
1078 return true;
1079 }
1080
main(int argc,char * argv[])1081 int main (int argc, char* argv[])
1082 {
1083 // the variables we'll read parameters into
1084 dirac_encoder_context_t enc_ctx;
1085
1086 if (!parse_command_line(enc_ctx, argc, argv))
1087 return EXIT_FAILURE;
1088
1089 //output name for the bitstream
1090 string input,output;
1091
1092 /*********************************************************************************/
1093
1094 // last two arguments must be file names
1095 if (argv[argc-1][0] == '-')
1096 {
1097 display_help();
1098 exit(1);
1099 }
1100
1101 if (argv[argc-2][0] == '-')
1102 input = "/dev/stdin";
1103 else
1104 input = argv[argc-2];
1105
1106 output=argv[argc-1];
1107
1108 //check we have real inputs
1109 if ((input.length() == 0) || (output.length() ==0))
1110 {
1111 display_help();
1112 exit(1);
1113 }
1114
1115
1116 if ( input==output )
1117 {
1118 std::cerr << "Input and output file names must be different" << std::endl;
1119 exit(1);
1120 }
1121
1122 if ( verbose )
1123 display_codec_params(enc_ctx);
1124
1125
1126
1127 /********************************************************************/
1128 //next do picture file stuff
1129
1130 // Open uncompressed data file
1131 std::string input_name_yuv = input;
1132 std::ifstream
1133 ip_pic_ptr (input_name_yuv.c_str(), std::ios::in | std::ios::binary);
1134 if (!ip_pic_ptr)
1135 {
1136 std::cerr << std::endl <<
1137 "Can't open input data file: " << input_name_yuv << std::endl;
1138 return EXIT_FAILURE;
1139 }
1140
1141
1142
1143 /********************************************************************/
1144 //open the bitstream file
1145 std::ofstream outfile(output.c_str(),std::ios::out | std::ios::binary); //bitstream output
1146
1147 // open the decoded ouput file
1148 std::ofstream *outyuv = NULL, *outimt = NULL;
1149
1150 if (nolocal == false)
1151 {
1152 std::string output_name_yuv = output + ".localdec.yuv";
1153 std::string output_name_imt = output + ".imt";
1154
1155 outyuv = new std::ofstream(output_name_yuv.c_str(),std::ios::out | std::ios::binary);
1156
1157 // open the diagnostics ouput file
1158 outimt = new std::ofstream(output_name_imt.c_str(),std::ios::out | std::ios::binary);
1159 }
1160
1161 /********************************************************************/
1162 //do the work!!
1163
1164 // Determine buffer size
1165 int frame_size = GetFrameBufferSize (enc_ctx);
1166 unsigned char *frame_buf = new unsigned char [frame_size];
1167
1168 if ( end_pos == -1 )
1169 end_pos = INT_MAX;
1170
1171 /* don't try and skip frames if they aren't any to skip, eg
1172 * this won't work on nonseekable filehandles. */
1173 if (start_pos && !Skip( ip_pic_ptr, start_pos, frame_size ))
1174 {
1175 return EXIT_FAILURE;
1176 };
1177
1178 dirac_encoder_t *encoder;
1179
1180 if (nolocal)
1181 {
1182 enc_ctx.decode_flag = 0;
1183 enc_ctx.instr_flag = 0;
1184 }
1185 else
1186 {
1187 enc_ctx.decode_flag = 1;
1188 enc_ctx.instr_flag = 1;
1189 }
1190
1191 encoder = dirac_encoder_init( &enc_ctx, verbose );
1192
1193 if (!encoder)
1194 {
1195 std::cerr << "Unrecoverable Error: dirac_encoder_init failed. "
1196 << std::endl;
1197 return EXIT_FAILURE;
1198 }
1199
1200
1201 if (outimt)
1202 WriteDiagnosticsHeader ( *outimt, encoder );
1203
1204
1205 int frames_loaded = 0;
1206 dirac_encoder_state_t state;
1207
1208 clock_t start_t, stop_t;
1209 start_t = clock();
1210
1211 bool go = true;
1212 do
1213 {
1214 if (frames_loaded <= (end_pos - start_pos) &&
1215 ReadPicData( ip_pic_ptr, frame_buf, frame_size ) == true)
1216 {
1217 if (dirac_encoder_load( encoder, frame_buf, frame_size ) < 0)
1218 {
1219 std::cerr << "dirac_encoder_load failed: Unrecoverable Encoder Error. Quitting..."
1220 << std::endl;
1221 return EXIT_FAILURE;
1222 }
1223 frames_loaded++;
1224 }
1225 else
1226 {
1227 // push end of stream
1228 dirac_encoder_end_sequence( encoder );
1229 }
1230 do
1231 {
1232 encoder->enc_buf.buffer = video_buf;
1233 encoder->enc_buf.size = VIDEO_BUFFER_SIZE;
1234 state = dirac_encoder_output ( encoder );
1235 switch (state)
1236 {
1237 case ENC_STATE_AVAIL:
1238 assert (encoder->enc_buf.size > 0);
1239
1240 outfile.write((char *)encoder->enc_buf.buffer,
1241 encoder->enc_buf.size);
1242 break;
1243
1244 case ENC_STATE_BUFFER:
1245 break;
1246 case ENC_STATE_EOS:
1247 outfile.write((char *)encoder->enc_buf.buffer,
1248 encoder->enc_buf.size);
1249 go = false;
1250 break;
1251 case ENC_STATE_INVALID:
1252 std::cerr << "Invalid state. Unrecoverable Encoder Error. Quitting..."
1253 << std::endl;
1254 return EXIT_FAILURE;
1255 default:
1256 std::cerr << "Unknown Encoder state" << endl;
1257 break;
1258 }
1259
1260 WritePicData (*outyuv, encoder);
1261 WriteDiagnosticsData (*outimt, encoder);
1262
1263 } while (state == ENC_STATE_AVAIL);
1264
1265 } while (go);
1266
1267 stop_t = clock();
1268
1269 if ( verbose )
1270 std::cout << "The resulting bit-rate at "
1271 << (double)encoder->enc_ctx.src_params.frame_rate.numerator/
1272 encoder->enc_ctx.src_params.frame_rate.denominator
1273 << "Hz is " << encoder->enc_seqstats.bit_rate
1274 << " bits/sec." << std::endl;
1275
1276 if ( verbose )
1277 {
1278 std::cout<<"Time per frame: "<<
1279 (double)(stop_t-start_t)/(double)(CLOCKS_PER_SEC*frames_loaded);
1280 std::cout<<std::endl<<std::endl;
1281 }
1282 /********************************************************************/
1283
1284 // close the encoder
1285 dirac_encoder_close( encoder );
1286 // close the bitstream file
1287 outfile.close();
1288 // close the decoded output file
1289 if (outyuv)
1290 {
1291 outyuv->close();
1292 delete outyuv;
1293 }
1294
1295 // close the decoded output header file
1296 if (outimt)
1297 {
1298 outimt->close();
1299 delete outimt;
1300 }
1301 // close the pic data file
1302 ip_pic_ptr.close();
1303
1304 // delete frame buffer
1305 delete [] frame_buf;
1306
1307 return EXIT_SUCCESS;
1308
1309
1310 }
1311