Reformat whole codebase with astyle.options (#128)
[openjpeg.git] / src / bin / mj2 / opj_mj2_compress.c
1 /*
2 * Copyright (c) 2003-2004, Francois-Olivier Devaux
3 * Copyright (c) 2002-2004,  Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "opj_apps_config.h"
33 #include "openjpeg.h"
34 #include "j2k_lib.h"
35 #include "cio.h"
36 #include "j2k.h"
37 #include "jp2.h"
38 #include "mj2.h"
39 #include "mj2_convert.h"
40 #include "opj_getopt.h"
41
42 /**
43 Size of memory first allocated for MOOV box
44 */
45 #define TEMP_BUF 10000
46
47
48 /* -------------------------------------------------------------------------- */
49
50 /**
51 sample error callback expecting a FILE* client object
52 */
53 static void error_callback(const char *msg, void *client_data)
54 {
55     FILE *stream = (FILE*)client_data;
56     fprintf(stream, "[ERROR] %s", msg);
57 }
58 /**
59 sample warning callback expecting a FILE* client object
60 */
61 static void warning_callback(const char *msg, void *client_data)
62 {
63     FILE *stream = (FILE*)client_data;
64     fprintf(stream, "[WARNING] %s", msg);
65 }
66
67 /* -------------------------------------------------------------------------- */
68
69
70 static void help_display()
71 {
72     fprintf(stdout, "HELP for frames_to_mj2\n----\n\n");
73     fprintf(stdout, "- the -h option displays this help information on screen\n\n");
74
75
76     fprintf(stdout, "List of parameters for the MJ2 encoder:\n");
77     fprintf(stdout, "\n");
78     fprintf(stdout, "REMARKS:\n");
79     fprintf(stdout, "---------\n");
80     fprintf(stdout, "\n");
81     fprintf
82     (stdout, "The markers written to the main_header are : SOC SIZ COD QCD COM.\n");
83     fprintf
84     (stdout, "COD and QCD never appear in the tile_header.\n");
85     fprintf(stdout, "\n");
86     fprintf(stdout, "By default:\n");
87     fprintf(stdout, "------------\n");
88     fprintf(stdout, "\n");
89     fprintf(stdout, " * Lossless\n");
90     fprintf(stdout, " * 1 tile\n");
91     fprintf(stdout, " * Size of precinct : 2^15 x 2^15 (means 1 precinct)\n");
92     fprintf(stdout, " * Size of code-block : 64 x 64\n");
93     fprintf(stdout, " * Number of resolutions: 6\n");
94     fprintf(stdout, " * No SOP marker in the codestream\n");
95     fprintf(stdout, " * No EPH marker in the codestream\n");
96     fprintf(stdout, " * No sub-sampling in x or y direction\n");
97     fprintf(stdout, " * No mode switch activated\n");
98     fprintf(stdout, " * Progression order: LRCP\n");
99     fprintf(stdout, " * No index file\n");
100     fprintf(stdout, " * No ROI upshifted\n");
101     fprintf(stdout, " * No offset of the origin of the image\n");
102     fprintf(stdout, " * No offset of the origin of the tiles\n");
103     fprintf(stdout, " * Reversible DWT 5-3\n");
104     fprintf(stdout, "\n");
105     fprintf(stdout, "Parameters:\n");
106     fprintf(stdout, "------------\n");
107     fprintf(stdout, "\n");
108     fprintf
109     (stdout, "Required Parameters (except with -h):\n");
110     fprintf
111     (stdout, "-i : source file      (-i source.yuv) \n");
112     fprintf
113     (stdout, "-o : destination file (-o dest.mj2) \n");
114     fprintf
115     (stdout, "Optional Parameters:\n");
116     fprintf(stdout, "-h : display the help information \n");
117     fprintf(stdout,
118             "-r : different compression ratios for successive layers (-r 20,10,5)\n");
119     fprintf(stdout,
120             "     - The rate specified for each quality level is the desired \n");
121     fprintf(stdout, "       compression factor.\n");
122     fprintf(stdout, "       Example: -r 20,10,1 means quality 1: compress 20x, \n");
123     fprintf(stdout,
124             "       quality 2: compress 10x and quality 3: compress lossless\n");
125     fprintf(stdout, "       (options -r and -q cannot be used together)\n");
126
127     fprintf(stdout, "-q : different psnr for successive layers (-q 30,40,50) \n");
128     fprintf(stdout, "        (options -r and -q cannot be used together)\n");
129
130     fprintf(stdout, "-n : number of resolutions (-n 3) \n");
131     fprintf(stdout, "-b : size of code block (-b 32,32) \n");
132     fprintf(stdout, "-c : size of precinct (-c 128,128) \n");
133     fprintf(stdout, "-t : size of tile (-t 512,512) \n");
134     fprintf
135     (stdout, "-p : progression order (-p LRCP) [LRCP, RLCP, RPCL, PCRL, CPRL] \n");
136     fprintf
137     (stdout, "-s : subsampling factor (-s 2,2) [-s X,Y] \n");
138     fprintf(stdout, "     Remark: subsampling bigger than 2 can produce error\n");
139     fprintf
140     (stdout, "-S : write SOP marker before each packet \n");
141     fprintf
142     (stdout, "-E : write EPH marker after each header packet \n");
143     fprintf
144     (stdout, "-M : mode switch (-M 3) [1=BYPASS(LAZY) 2=RESET 4=RESTART(TERMALL)\n");
145     fprintf
146     (stdout, "             8=VSC 16=ERTERM(SEGTERM) 32=SEGMARK(SEGSYM)] \n");
147     fprintf
148     (stdout, "             Indicate multiple modes by adding their values. \n");
149     fprintf
150     (stdout, "             Example: RESTART(4) + RESET(2) + SEGMARK(32) = -M 38\n");
151     fprintf
152     (stdout, "-R : c=%%d,U=%%d : quantization indices upshifted \n");
153     fprintf
154     (stdout, "             for component c=%%d [%%d = 0,1,2]\n");
155     fprintf
156     (stdout, "             with a value of U=%%d [0 <= %%d <= 37] (i.e. -ROI:c=0,U=25) \n");
157     fprintf
158     (stdout, "-d : offset of the origin of the image (-d 150,300) \n");
159     fprintf
160     (stdout, "-T : offset of the origin of the tiles (-T 100,75) \n");
161     fprintf(stdout, "-I : use the irreversible DWT 9-7 (-I) \n");
162     fprintf(stdout, "-W : image width, height and the dx and dy subsampling \n");
163     fprintf(stdout, "        of the Cb and Cr components for YUV files \n");
164     fprintf(stdout,
165             "        (default is '352,288,2,2' for CIF format's 352x288 and 4:2:0)\n");
166     fprintf(stdout, "-F : video frame rate (set to 25 by default)\n");
167     fprintf(stdout, "-D : depth, precision in bits [8 .. 16]; default:8\n");
168     fprintf(stdout, "-C : comment\n");
169     fprintf(stdout, "\n");
170     fprintf(stdout, "IMPORTANT:\n");
171     fprintf(stdout, "-----------\n");
172     fprintf(stdout, "\n");
173     fprintf(stdout, "The index file has the structure below:\n");
174     fprintf(stdout, "---------------------------------------\n");
175     fprintf(stdout, "\n");
176     fprintf(stdout, "Image_height Image_width\n");
177     fprintf(stdout, "progression order\n");
178     fprintf(stdout, "Tiles_size_X Tiles_size_Y\n");
179     fprintf(stdout, "Components_nb\n");
180     fprintf(stdout, "Layers_nb\n");
181     fprintf(stdout, "decomposition_levels\n");
182     fprintf(stdout, "[Precincts_size_X_res_Nr Precincts_size_Y_res_Nr]...\n");
183     fprintf(stdout, "   [Precincts_size_X_res_0 Precincts_size_Y_res_0]\n");
184     fprintf(stdout, "Main_header_end_position\n");
185     fprintf(stdout, "Codestream_size\n");
186     fprintf(stdout,
187             "Tile_0 start_pos end_Theader end_pos TotalDisto NumPix MaxMSE\n");
188     fprintf(stdout,
189             "Tile_1   ''           ''        ''        ''       ''    ''\n");
190     fprintf(stdout, "...\n");
191     fprintf(stdout,
192             "Tile_Nt   ''           ''        ''        ''       ''    ''\n");
193     fprintf(stdout,
194             "Tpacket_0 Tile layer res. comp. prec. start_pos end_pos disto\n");
195     fprintf(stdout, "...\n");
196     fprintf(stdout,
197             "Tpacket_Np ''   ''    ''   ''    ''       ''       ''     ''\n");
198
199     fprintf(stdout, "MaxDisto\n");
200
201     fprintf(stdout, "TotalDisto\n\n");
202 }
203
204 static OPJ_PROG_ORDER give_progression(const char progression[5])
205 {
206     if (progression[0] == 'L' && progression[1] == 'R'
207             && progression[2] == 'C' && progression[3] == 'P') {
208         return LRCP;
209     } else {
210         if (progression[0] == 'R' && progression[1] == 'L'
211                 && progression[2] == 'C' && progression[3] == 'P') {
212             return RLCP;
213         } else {
214             if (progression[0] == 'R' && progression[1] == 'P'
215                     && progression[2] == 'C' && progression[3] == 'L') {
216                 return RPCL;
217             } else {
218                 if (progression[0] == 'P' && progression[1] == 'C'
219                         && progression[2] == 'R' && progression[3] == 'L') {
220                     return PCRL;
221                 } else {
222                     if (progression[0] == 'C' && progression[1] == 'P'
223                             && progression[2] == 'R' && progression[3] == 'L') {
224                         return CPRL;
225                     } else {
226                         return PROG_UNKNOWN;
227                     }
228                 }
229             }
230         }
231     }
232 }
233
234
235
236
237 int main(int argc, char **argv)
238 {
239     mj2_cparameters_t mj2_parameters;   /* MJ2 compression parameters */
240     opj_cparameters_t *j2k_parameters;  /* J2K compression parameters */
241     opj_event_mgr_t event_mgr;      /* event manager */
242     opj_cio_t *cio;
243     int value;
244     opj_mj2_t *movie;
245     opj_image_t *img;
246     int i, j;
247     char *s, S1, S2, S3;
248     unsigned char *buf;
249     int x1, y1,  len;
250     long mdat_initpos, offset;
251     FILE *mj2file;
252     int sampleno;
253     opj_cinfo_t* cinfo;
254     opj_bool bSuccess;
255     int numframes;
256     int prec = 8;/* DEFAULT */
257     double total_time = 0;
258
259     memset(&mj2_parameters, 0, sizeof(mj2_cparameters_t));
260     /* default value */
261     /* ------------- */
262     mj2_parameters.w = 352;         /* CIF default value*/
263     mj2_parameters.h = 288;         /* CIF default value*/
264     mj2_parameters.CbCr_subsampling_dx = 2; /* CIF default value*/
265     mj2_parameters.CbCr_subsampling_dy = 2; /* CIF default value*/
266     mj2_parameters.frame_rate = 25;
267     mj2_parameters.prec = 8; /* DEFAULT */
268     mj2_parameters.enumcs = ENUMCS_SYCC; /* FIXME: ENUMCS_YUV420 */
269     mj2_parameters.meth = 1; /* enumerated color space */
270
271     /*
272         configure the event callbacks (not required)
273         setting of each callback is optionnal
274     */
275     memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
276     event_mgr.error_handler = error_callback;
277     event_mgr.warning_handler = warning_callback;
278     event_mgr.info_handler = NULL;
279
280     /* set J2K encoding parameters to default values */
281     opj_set_default_encoder_parameters(&mj2_parameters.j2k_parameters);
282     j2k_parameters = &mj2_parameters.j2k_parameters;
283
284     /* Create comment for codestream */
285     if (j2k_parameters->cp_comment == NULL) {
286         const char comment[] = "Created by OpenJPEG version ";
287         const size_t clen = strlen(comment);
288         const char *version = opj_version();
289         j2k_parameters->cp_comment = (char*)malloc(clen + strlen(version) + 1);
290         sprintf(j2k_parameters->cp_comment, "%s%s", comment, version);
291     }
292
293     while (1) {
294         int c = opj_getopt(argc, argv,
295                            "i:o:r:q:f:t:n:c:b:p:s:d:P:S:E:M:R:T:C:I:W:F:D:h");
296         if (c == -1) {
297             break;
298         }
299         switch (c) {
300         case 'i': {         /* IN fill */
301             char *infile = opj_optarg;
302             s = opj_optarg;
303             while (*s) {
304                 s++;
305             }
306             s--;
307             S3 = *s;
308             s--;
309             S2 = *s;
310             s--;
311             S1 = *s;
312
313             if ((S1 == 'y' && S2 == 'u' && S3 == 'v')
314                     || (S1 == 'Y' && S2 == 'U' && S3 == 'V')) {
315                 mj2_parameters.decod_format = YUV_DFMT;
316             } else {
317                 fprintf(stderr,
318                         "!! Unrecognized format for infile : %c%c%c [accept only *.yuv] !!\n\n",
319                         S1, S2, S3);
320                 return 1;
321             }
322             strncpy(mj2_parameters.infile, infile, sizeof(mj2_parameters.infile) - 1);
323         }
324         break;
325         /* ----------------------------------------------------- */
326         case 'o': {         /* OUT fill */
327             char *outfile = opj_optarg;
328             while (*outfile) {
329                 outfile++;
330             }
331             outfile--;
332             S3 = *outfile;
333             outfile--;
334             S2 = *outfile;
335             outfile--;
336             S1 = *outfile;
337
338             outfile = opj_optarg;
339
340             if ((S1 == 'm' && S2 == 'j' && S3 == '2')
341                     || (S1 == 'M' && S2 == 'J' && S3 == '2')) {
342                 mj2_parameters.cod_format = MJ2_CFMT;
343             } else {
344                 fprintf(stderr,
345                         "Unknown output format image *.%c%c%c [only *.mj2]!! \n",
346                         S1, S2, S3);
347                 return 1;
348             }
349             strncpy(mj2_parameters.outfile, outfile, sizeof(mj2_parameters.outfile) - 1);
350         }
351         break;
352         /* ----------------------------------------------------- */
353         case 'r': {         /* rates rates/distorsion */
354             float rate;
355             s = opj_optarg;
356             while (sscanf(s, "%f", &rate) == 1) {
357                 j2k_parameters->tcp_rates[j2k_parameters->tcp_numlayers] = rate * 2;
358                 j2k_parameters->tcp_numlayers++;
359                 while (*s && *s != ',') {
360                     s++;
361                 }
362                 if (!*s) {
363                     break;
364                 }
365                 s++;
366             }
367             j2k_parameters->cp_disto_alloc = 1;
368         }
369         break;
370         /* ----------------------------------------------------- */
371         case 'q':           /* add fixed_quality */
372             s = opj_optarg;
373             while (sscanf(s, "%f",
374                           &j2k_parameters->tcp_distoratio[j2k_parameters->tcp_numlayers]) == 1) {
375                 j2k_parameters->tcp_numlayers++;
376                 while (*s && *s != ',') {
377                     s++;
378                 }
379                 if (!*s) {
380                     break;
381                 }
382                 s++;
383             }
384             j2k_parameters->cp_fixed_quality = 1;
385             break;
386         /* dda */
387         /* ----------------------------------------------------- */
388         case 'f': {         /* mod fixed_quality (before : -q) */
389             int *row = NULL, *col = NULL;
390             int numlayers = 0, numresolution = 0, matrix_width = 0;
391
392             s = opj_optarg;
393             sscanf(s, "%d", &numlayers);
394             s++;
395             if (numlayers > 9) {
396                 s++;
397             }
398
399             j2k_parameters->tcp_numlayers = numlayers;
400             numresolution = j2k_parameters->numresolution;
401             matrix_width = numresolution * 3;
402             j2k_parameters->cp_matrice = (int *) malloc(numlayers * matrix_width * sizeof(
403                                              int));
404             s = s + 2;
405
406             for (i = 0; i < numlayers; i++) {
407                 row = &j2k_parameters->cp_matrice[i * matrix_width];
408                 col = row;
409                 j2k_parameters->tcp_rates[i] = 1;
410                 sscanf(s, "%d,", &col[0]);
411                 s += 2;
412                 if (col[0] > 9) {
413                     s++;
414                 }
415                 col[1] = 0;
416                 col[2] = 0;
417                 for (j = 1; j < numresolution; j++) {
418                     col += 3;
419                     sscanf(s, "%d,%d,%d", &col[0], &col[1], &col[2]);
420                     s += 6;
421                     if (col[0] > 9) {
422                         s++;
423                     }
424                     if (col[1] > 9) {
425                         s++;
426                     }
427                     if (col[2] > 9) {
428                         s++;
429                     }
430                 }
431                 if (i < numlayers - 1) {
432                     s++;
433                 }
434             }
435             j2k_parameters->cp_fixed_alloc = 1;
436         }
437         break;
438         /* ----------------------------------------------------- */
439         case 't':           /* tiles */
440             sscanf(opj_optarg, "%d,%d", &j2k_parameters->cp_tdx, &j2k_parameters->cp_tdy);
441             j2k_parameters->tile_size_on = OPJ_TRUE;
442             break;
443         /* ----------------------------------------------------- */
444         case 'n':           /* resolution */
445             sscanf(opj_optarg, "%d", &j2k_parameters->numresolution);
446             break;
447         /* ----------------------------------------------------- */
448         case 'c': {         /* precinct dimension */
449             char sep;
450             int res_spec = 0;
451
452             char *s = opj_optarg;
453             do {
454                 sep = 0;
455                 sscanf(s, "[%d,%d]%c", &j2k_parameters->prcw_init[res_spec],
456                        &j2k_parameters->prch_init[res_spec], &sep);
457                 j2k_parameters->csty |= 0x01;
458                 res_spec++;
459                 s = strpbrk(s, "]") + 2;
460             } while (sep == ',');
461             j2k_parameters->res_spec = res_spec;
462         }
463         break;
464
465         /* ----------------------------------------------------- */
466         case 'b': {         /* code-block dimension */
467             int cblockw_init = 0, cblockh_init = 0;
468             sscanf(opj_optarg, "%d,%d", &cblockw_init, &cblockh_init);
469             if (cblockw_init * cblockh_init > 4096 || cblockw_init > 1024
470                     || cblockw_init < 4 || cblockh_init > 1024 || cblockh_init < 4) {
471                 fprintf(stderr,
472                         "!! Size of code_block error (option -b) !!\n\nRestriction :\n"
473                         "    * width*height<=4096\n    * 4<=width,height<= 1024\n\n");
474                 return 1;
475             }
476             j2k_parameters->cblockw_init = cblockw_init;
477             j2k_parameters->cblockh_init = cblockh_init;
478         }
479         break;
480         /* ----------------------------------------------------- */
481         case 'p': {         /* progression order */
482             char progression[5];
483
484             strncpy(progression, opj_optarg, 5);
485             j2k_parameters->prog_order = give_progression(progression);
486             if (j2k_parameters->prog_order == -1) {
487                 fprintf(stderr, "Unrecognized progression order "
488                         "[LRCP, RLCP, RPCL, PCRL, CPRL] !!\n");
489                 return 1;
490             }
491         }
492         break;
493         /* ----------------------------------------------------- */
494         case 's': {         /* subsampling factor */
495             if (sscanf(opj_optarg, "%d,%d", &j2k_parameters->subsampling_dx,
496                        &j2k_parameters->subsampling_dy) != 2) {
497                 fprintf(stderr, "'-s' sub-sampling argument error !  [-s dx,dy]\n");
498                 return 1;
499             }
500         }
501         break;
502         /* ----------------------------------------------------- */
503         case 'd': {         /* coordonnate of the reference grid */
504             if (sscanf(opj_optarg, "%d,%d", &j2k_parameters->image_offset_x0,
505                        &j2k_parameters->image_offset_y0) != 2) {
506                 fprintf(stderr, "-d 'coordonnate of the reference grid' argument "
507                         "error !! [-d x0,y0]\n");
508                 return 1;
509             }
510         }
511         break;
512         /* ----------------------------------------------------- */
513         case 'h':           /* Display an help description */
514             help_display();
515             return 0;
516             break;
517         /* ----------------------------------------------------- */
518         case 'P': {         /* POC */
519             int numpocs = 0;        /* number of progression order change (POC) default 0 */
520             opj_poc_t *POC = NULL;  /* POC : used in case of Progression order change */
521
522             char *s = opj_optarg;
523             POC = j2k_parameters->POC;
524
525             while (sscanf(s, "T%d=%d,%d,%d,%d,%d,%4s", &POC[numpocs].tile,
526                           &POC[numpocs].resno0, &POC[numpocs].compno0,
527                           &POC[numpocs].layno1, &POC[numpocs].resno1,
528                           &POC[numpocs].compno1, POC[numpocs].progorder) == 7) {
529                 POC[numpocs].prg1 = give_progression(POC[numpocs].progorder);
530                 numpocs++;
531                 while (*s && *s != '/') {
532                     s++;
533                 }
534                 if (!*s) {
535                     break;
536                 }
537                 s++;
538             }
539             j2k_parameters->numpocs = numpocs;
540         }
541         break;
542         /* ------------------------------------------------------ */
543         case 'S':           /* SOP marker */
544             j2k_parameters->csty |= 0x02;
545             break;
546         /* ------------------------------------------------------ */
547         case 'E':           /* EPH marker */
548             j2k_parameters->csty |= 0x04;
549             break;
550         /* ------------------------------------------------------ */
551         case 'M':           /* Mode switch pas tous au point !! */
552             if (sscanf(opj_optarg, "%d", &value) == 1) {
553                 for (i = 0; i <= 5; i++) {
554                     int cache = value & (1 << i);
555                     if (cache) {
556                         j2k_parameters->mode |= (1 << i);
557                     }
558                 }
559             }
560             break;
561         /* ------------------------------------------------------ */
562         case 'R': {         /* ROI */
563             if (sscanf(opj_optarg, "OI:c=%d,U=%d", &j2k_parameters->roi_compno,
564                        &j2k_parameters->roi_shift) != 2) {
565                 fprintf(stderr, "ROI error !! [-ROI:c='compno',U='shift']\n");
566                 return 1;
567             }
568         }
569         break;
570         /* ------------------------------------------------------ */
571         case 'T': {         /* Tile offset */
572             if (sscanf(opj_optarg, "%d,%d", &j2k_parameters->cp_tx0,
573                        &j2k_parameters->cp_ty0) != 2) {
574                 fprintf(stderr, "-T 'tile offset' argument error !! [-T X0,Y0]");
575                 return 1;
576             }
577         }
578         break;
579         /* ------------------------------------------------------ */
580         case 'C': {         /* Add a comment */
581             j2k_parameters->cp_comment = (char*)malloc(strlen(opj_optarg) + 1);
582             if (j2k_parameters->cp_comment) {
583                 strcpy(j2k_parameters->cp_comment, opj_optarg);
584             }
585         }
586         break;
587         /* ------------------------------------------------------ */
588         case 'I': {         /* reversible or not */
589             j2k_parameters->irreversible = 1;
590         }
591         break;
592         /* ------------------------------------------------------ */
593         case 'W':           /* Width and Height and Cb and Cr subsampling in case of YUV format files */
594             if (sscanf
595                     (opj_optarg, "%d,%d,%d,%d", &mj2_parameters.w, &mj2_parameters.h,
596                      &mj2_parameters.CbCr_subsampling_dx,
597                      &mj2_parameters.CbCr_subsampling_dy) != 4) {
598                 fprintf(stderr, "-W argument error");
599                 return 1;
600             }
601             break;
602         /* ------------------------------------------------------ */
603         case 'F':           /* Video frame rate */
604             if (sscanf(opj_optarg, "%d", &mj2_parameters.frame_rate) != 1) {
605                 fprintf(stderr, "-F argument error");
606                 return 1;
607             }
608             break;
609         /* ------------------------------------------------------ */
610         case 'D': /* Depth: the precision */
611             if (sscanf(opj_optarg, "%d", &prec) != 1) {
612                 prec = 0;
613             }
614             break;
615
616         default:
617             return 1;
618         }
619     }
620
621     /* Error messages */
622     /* -------------- */
623     if (!mj2_parameters.cod_format || !mj2_parameters.decod_format) {
624         fprintf(stderr,
625                 "Usage: %s -i yuv-file -o mj2-file (+ options)\n", argv[0]);
626         return 1;
627     }
628     if (prec < 1 || prec > 16) {
629         fprintf(stderr, "Error: Depth %d must be in the range 8 .. 16\n", prec);
630         return 1;
631     }
632     if ((j2k_parameters->cp_disto_alloc || j2k_parameters->cp_fixed_alloc ||
633             j2k_parameters->cp_fixed_quality)
634             && (!(j2k_parameters->cp_disto_alloc ^ j2k_parameters->cp_fixed_alloc ^
635                   j2k_parameters->cp_fixed_quality))) {
636         fprintf(stderr, "Error: options -r -q and -f cannot be used together !!\n");
637         return 1;
638     }               /* mod fixed_quality */
639
640     /* if no rate entered, lossless by default */
641     if (j2k_parameters->tcp_numlayers == 0) {
642         j2k_parameters->tcp_rates[0] = 0;   /* MOD antonin : losslessbug */
643         j2k_parameters->tcp_numlayers++;
644         j2k_parameters->cp_disto_alloc = 1;
645     }
646
647     if ((j2k_parameters->cp_tx0 > j2k_parameters->image_offset_x0) ||
648             (j2k_parameters->cp_ty0 > j2k_parameters->image_offset_y0)) {
649         fprintf(stderr,
650                 "Error: Tile offset dimension is unnappropriate --> TX0(%d)<=IMG_X0(%d) TYO(%d)<=IMG_Y0(%d) \n",
651                 j2k_parameters->cp_tx0, j2k_parameters->image_offset_x0, j2k_parameters->cp_ty0,
652                 j2k_parameters->image_offset_y0);
653         return 1;
654     }
655
656     for (i = 0; i < j2k_parameters->numpocs; i++) {
657         if (j2k_parameters->POC[i].prg == -1) {
658             fprintf(stderr,
659                     "Unrecognized progression order in option -P (POC n %d) [LRCP, RLCP, RPCL, PCRL, CPRL] !!\n",
660                     i + 1);
661         }
662     }
663
664     if (j2k_parameters->cp_tdx > mj2_parameters.Dim[0] ||
665             j2k_parameters->cp_tdy > mj2_parameters.Dim[1]) {
666         fprintf(stderr,
667                 "Error: Tile offset dimension is unnappropriate --> TX0(%d)<=IMG_X0(%d) TYO(%d)<=IMG_Y0(%d) \n",
668                 j2k_parameters->cp_tdx, mj2_parameters.Dim[0], j2k_parameters->cp_tdy,
669                 mj2_parameters.Dim[1]);
670         return 1;
671     }
672
673     /* to respect profile - 0 */
674     /* ---------------------- */
675
676     x1 = !mj2_parameters.Dim[0] ? (mj2_parameters.w - 1) *
677          j2k_parameters->subsampling_dx
678          + 1 : mj2_parameters.Dim[0] + (mj2_parameters.w - 1) *
679          j2k_parameters->subsampling_dx + 1;
680     y1 = !mj2_parameters.Dim[1] ? (mj2_parameters.h - 1) *
681          j2k_parameters->subsampling_dy
682          + 1 : mj2_parameters.Dim[1] + (mj2_parameters.h - 1) *
683          j2k_parameters->subsampling_dy + 1;
684     mj2_parameters.numcomps = 3; /* YUV files only have 3 components */
685
686     mj2_parameters.prec = prec;
687
688     j2k_parameters->tcp_mct = 0;
689
690     mj2file = fopen(mj2_parameters.outfile, "wb");
691
692     if (!mj2file) {
693         fprintf(stderr, "failed to open %s for writing\n", argv[2]);
694         return 1;
695     }
696
697     /* get a MJ2 decompressor handle */
698     cinfo = mj2_create_compress();
699     movie = (opj_mj2_t*)cinfo->mj2_handle;
700
701     /* catch events using our callbacks and give a local context */
702     opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
703
704     /* setup encoder parameters */
705     mj2_setup_encoder(movie, &mj2_parameters);
706
707     movie->tk[0].num_samples =
708         yuv_num_frames(&movie->tk[0], mj2_parameters.infile);
709
710     if (movie->tk[0].num_samples == 0) {
711         return 1;
712     }
713
714     /* One sample per chunk*/
715     movie->tk[0].chunk = (mj2_chunk_t*)
716                          malloc(movie->tk[0].num_samples * sizeof(mj2_chunk_t));
717     movie->tk[0].sample = (mj2_sample_t*)
718                           malloc(movie->tk[0].num_samples * sizeof(mj2_sample_t));
719
720     if (mj2_init_stdmovie(movie)) {
721         fprintf(stderr, "Error with movie initialization");
722         return 1;
723     }
724
725     /* Writing JP, FTYP and MDAT boxes */
726     /* Assuming that the JP and FTYP boxes won't be longer than 300 bytes:*/
727     buf = (unsigned char*)
728           malloc(300 * sizeof(unsigned char));
729
730     cio = opj_cio_open((opj_common_ptr)movie->cinfo, buf, 300);
731
732     mj2_write_jp(cio);
733     mj2_write_ftyp(movie, cio);
734
735     mdat_initpos = cio_tell(cio);
736     cio_skip(cio, 4);
737
738     cio_write(cio, MJ2_MDAT, 4);
739
740     fwrite(buf, cio_tell(cio), 1, mj2file);
741
742     offset = cio_tell(cio);
743     opj_cio_close(cio);
744     free(buf);
745
746     for (i = 0; i < movie->num_stk + movie->num_htk + movie->num_vtk; i++) {
747         if (movie->tk[i].track_type != 0) {
748             fprintf(stderr, "Unable to write sound or hint tracks\n");
749         } else {
750             mj2_tk_t *tk;
751             int buflen = 0;
752
753             tk = &movie->tk[i];
754             tk->num_chunks = tk->num_samples;
755             numframes = tk->num_samples;
756             tk->depth = prec;
757
758             fprintf(stderr, "Video Track number %d\n", i);
759
760             img = mj2_image_create(tk, j2k_parameters);
761
762             buflen = 2 * (tk->w * tk->h * 8);
763             buf = (unsigned char *) malloc(buflen * sizeof(unsigned char));
764
765             for (sampleno = 0; sampleno < numframes; sampleno++) {
766                 double init_time = opj_clock();
767                 double elapsed_time;
768
769                 if (yuvtoimage(tk, img, sampleno, j2k_parameters,
770                                mj2_parameters.infile)) {
771                     fprintf(stderr, "Error with frame number %d in YUV file\n", sampleno);
772                     return 1;
773                 }
774
775                 /* setup the encoder parameters using the current image and user parameters */
776                 opj_setup_encoder(cinfo, j2k_parameters, img);
777
778                 cio = opj_cio_open((opj_common_ptr)movie->cinfo, buf, buflen);
779
780                 cio_skip(cio, 4);
781                 cio_write(cio, JP2_JP2C, 4);    /* JP2C*/
782
783                 /* encode the image */
784                 bSuccess = opj_encode(cinfo, cio, img, NULL);
785
786                 if (!bSuccess) {
787                     opj_cio_close(cio);
788                     fprintf(stderr, "failed to encode image\n");
789                     return 1;
790                 }
791
792                 len = cio_tell(cio) - 8;
793                 cio_seek(cio, 0);
794                 cio_write(cio, len + 8, 4);
795                 opj_cio_close(cio);
796
797                 tk->sample[sampleno].sample_size = len + 8;
798                 tk->sample[sampleno].offset = offset;
799                 tk->chunk[sampleno].offset = offset;    /* There is one sample per chunk */
800                 fwrite(buf, 1, len + 8, mj2file);
801                 offset += len + 8;
802
803                 elapsed_time = opj_clock() - init_time;
804                 fprintf(stderr, "Frame number %d/%d encoded in %.2f mseconds\n",
805                         sampleno + 1, numframes, elapsed_time * 1000);
806                 total_time += elapsed_time;
807             }  /* for(sampleno */
808
809             free(buf);
810             opj_image_destroy(img);
811         }
812     }/* for(i */
813
814     fseek(mj2file, mdat_initpos, SEEK_SET);
815
816     buf = (unsigned char*) malloc(4 * sizeof(unsigned char));
817
818     /* Init a cio to write box length variable in a little endian way */
819     cio = opj_cio_open(NULL, buf, 4);
820     cio_write(cio, offset - mdat_initpos, 4);
821     fwrite(buf, 4, 1, mj2file);
822     fseek(mj2file, 0, SEEK_END);
823     free(buf);
824
825     /* Writing MOOV box */
826     buf = (unsigned char*)
827           malloc((TEMP_BUF + numframes * 20) * sizeof(unsigned char));
828     cio = opj_cio_open(movie->cinfo, buf, (TEMP_BUF + numframes * 20));
829     mj2_write_moov(movie, cio);
830     fwrite(buf, cio_tell(cio), 1, mj2file);
831     free(buf);
832
833     fprintf(stdout, "Total encoding time: %.2f s for %d frames (%.1f fps)\n",
834             total_time, numframes, (float)numframes / total_time);
835
836     /* Ending program */
837
838     fclose(mj2file);
839     /* free remaining compression structures */
840     mj2_destroy_compress(movie);
841     free(cinfo);
842
843     if (j2k_parameters->cp_comment) {
844         free(j2k_parameters->cp_comment);
845     }
846     if (j2k_parameters->cp_matrice) {
847         free(j2k_parameters->cp_matrice);
848     }
849     opj_cio_close(cio);
850
851     return 0;
852 }