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