MJ2 module: Add two components to mj2.h: meth, enumcs ; Define or reset all component...
[openjpeg.git] / mj2 / frames_to_mj2.c
index 6b1fd536a4589da120169f9f49c79424d1b5a12a..f689b00d4ceb4ac420dc3f7ef473d34935873bbd 100644 (file)
@@ -43,6 +43,10 @@ Size of memory first allocated for MOOV box
 */
 #define TEMP_BUF 10000 
 
+#define ENUMCS_GRAY 16
+#define ENUMCS_SRGB 17
+#define ENUMCS_SYCC 18
+
 /* -------------------------------------------------------------------------- */
 
 /**
@@ -111,60 +115,60 @@ void help_display()
   fprintf
     (stdout,"Required Parameters (except with -h):\n");
   fprintf
-    (stdout,"-i           : source file  (-i source.yuv) \n");
+    (stdout,"-i : source file      (-i source.yuv) \n");
   fprintf
-    (stdout,"-o           : destination file (-o dest.mj2) \n");
+    (stdout,"-o : destination file (-o dest.mj2) \n");
   fprintf
     (stdout,"Optional Parameters:\n");
-  fprintf(stdout,"-h           : display the help information \n");
-  fprintf(stdout,"-r           : different compression ratios for successive layers (-r 20,10,5)\n ");
-  fprintf(stdout,"              - The rate specified for each quality level is the desired \n");
-  fprintf(stdout,"                compression factor.\n");
-  fprintf(stdout,"                Example: -r 20,10,1 means quality 1: compress 20x, \n");
-  fprintf(stdout,"                  quality 2: compress 10x and quality 3: compress lossless\n");
-  fprintf(stdout,"               (options -r and -q cannot be used together)\n ");
-  
-  fprintf(stdout,"-q           : different psnr for successive layers (-q 30,40,50) \n ");
+  fprintf(stdout,"-h : display the help information \n");
+  fprintf(stdout,"-r : different compression ratios for successive layers (-r 20,10,5)\n");
+  fprintf(stdout,"     - The rate specified for each quality level is the desired \n");
+  fprintf(stdout,"       compression factor.\n");
+  fprintf(stdout,"       Example: -r 20,10,1 means quality 1: compress 20x, \n");
+  fprintf(stdout,"       quality 2: compress 10x and quality 3: compress lossless\n");
+  fprintf(stdout,"       (options -r and -q cannot be used together)\n");
   
-  fprintf(stdout,"               (options -r and -q cannot be used together)\n ");
+  fprintf(stdout,"-q : different psnr for successive layers (-q 30,40,50) \n");
+  fprintf(stdout,"        (options -r and -q cannot be used together)\n");
   
-  fprintf(stdout,"-n           : number of resolutions (-n 3) \n");
-  fprintf(stdout,"-b           : size of code block (-b 32,32) \n");
-  fprintf(stdout,"-c           : size of precinct (-c 128,128) \n");
-  fprintf(stdout,"-t           : size of tile (-t 512,512) \n");
+  fprintf(stdout,"-n : number of resolutions (-n 3) \n");
+  fprintf(stdout,"-b : size of code block (-b 32,32) \n");
+  fprintf(stdout,"-c : size of precinct (-c 128,128) \n");
+  fprintf(stdout,"-t : size of tile (-t 512,512) \n");
   fprintf
-    (stdout,"-p           : progression order (-p LRCP) [LRCP, RLCP, RPCL, PCRL, CPRL] \n");
+    (stdout,"-p : progression order (-p LRCP) [LRCP, RLCP, RPCL, PCRL, CPRL] \n");
   fprintf
-    (stdout,"-s           : subsampling factor (-s 2,2) [-s X,Y] \n");
-  fprintf(stdout,"          Remark: subsampling bigger than 2 can produce error\n");
+    (stdout,"-s : subsampling factor (-s 2,2) [-s X,Y] \n");
+  fprintf(stdout,"     Remark: subsampling bigger than 2 can produce error\n");
   fprintf
-    (stdout,"-SOP         : write SOP marker before each packet \n");
+    (stdout,"-S : write SOP marker before each packet \n");
   fprintf
-    (stdout,"-EPH         : write EPH marker after each header packet \n");
+    (stdout,"-E : write EPH marker after each header packet \n");
   fprintf
-    (stdout,"-M           : mode switch (-M 3) [1=BYPASS(LAZY) 2=RESET 4=RESTART(TERMALL)\n");
+    (stdout,"-M : mode switch (-M 3) [1=BYPASS(LAZY) 2=RESET 4=RESTART(TERMALL)\n");
   fprintf
-    (stdout,"                 8=VSC 16=ERTERM(SEGTERM) 32=SEGMARK(SEGSYM)] \n");
+    (stdout,"             8=VSC 16=ERTERM(SEGTERM) 32=SEGMARK(SEGSYM)] \n");
   fprintf
-    (stdout,"                 Indicate multiple modes by adding their values. \n");
+    (stdout,"             Indicate multiple modes by adding their values. \n");
   fprintf
-    (stdout,"                 ex: RESTART(4) + RESET(2) + SEGMARK(32) = -M 38\n");
+    (stdout,"             Example: RESTART(4) + RESET(2) + SEGMARK(32) = -M 38\n");
   fprintf
-    (stdout,"-ROI         : c=%%d,U=%%d : quantization indices upshifted \n");
+    (stdout,"-R : c=%%d,U=%%d : quantization indices upshifted \n");
   fprintf
-    (stdout,"               for component c=%%d [%%d = 0,1,2]\n");
+    (stdout,"             for component c=%%d [%%d = 0,1,2]\n");
   fprintf
-    (stdout,"               with a value of U=%%d [0 <= %%d <= 37] (i.e. -ROI:c=0,U=25) \n");
+    (stdout,"             with a value of U=%%d [0 <= %%d <= 37] (i.e. -ROI:c=0,U=25) \n");
   fprintf
-    (stdout,"-d           : offset of the origin of the image (-d 150,300) \n");
+    (stdout,"-d : offset of the origin of the image (-d 150,300) \n");
   fprintf
-    (stdout,"-T           : offset of the origin of the tiles (-T 100,75) \n");
-  fprintf(stdout,"-I           : use the irreversible DWT 9-7 (-I) \n");
-  fprintf(stdout,"-W           : image width, height and the dx and dy subsampling \n");
-  fprintf(stdout,"               of the Cb and Cr components for YUV files \n");
-  fprintf(stdout,"               (default is '352,288,2,2' for CIF format's 352x288 and 4:2:0)\n");
-  fprintf(stdout,"-F           : video frame rate (set to 25 by default)\n");
-  
+    (stdout,"-T : offset of the origin of the tiles (-T 100,75) \n");
+  fprintf(stdout,"-I : use the irreversible DWT 9-7 (-I) \n");
+  fprintf(stdout,"-W : image width, height and the dx and dy subsampling \n");
+  fprintf(stdout,"        of the Cb and Cr components for YUV files \n");
+  fprintf(stdout,"        (default is '352,288,2,2' for CIF format's 352x288 and 4:2:0)\n");
+  fprintf(stdout,"-F : video frame rate (set to 25 by default)\n");
+  fprintf(stdout,"-D : depth, precision in bits [8 .. 16]; default:8\n");
+  fprintf(stdout,"-C : comment\n");
   fprintf(stdout,"\n");
   fprintf(stdout,"IMPORTANT:\n");
   fprintf(stdout,"-----------\n");
@@ -235,33 +239,37 @@ int main(int argc, char **argv)
        opj_event_mgr_t event_mgr;              /* event manager */
        opj_cio_t *cio;
        int value;
-  opj_mj2_t *movie;
+       opj_mj2_t *movie;
        opj_image_t *img;
-  int i, j;
-  char *s, S1, S2, S3;
-  unsigned char *buf;
-  int x1, y1,  len;
-  long mdat_initpos, offset;
-  FILE *mj2file;
-  int sampleno;  
+       int i, j;
+       char *s, S1, S2, S3;
+       unsigned char *buf;
+       int x1, y1,  len;
+       long mdat_initpos, offset;
+       FILE *mj2file;
+       int sampleno;  
        opj_cinfo_t* cinfo;
-  bool bSuccess;
+       bool bSuccess;
        int numframes;
+       int prec = 0;
        double total_time = 0;  
 
+       memset(&mj2_parameters, 0, sizeof(mj2_cparameters_t));
   /* default value */
   /* ------------- */
-  mj2_parameters.Dim[0] = 0;
-  mj2_parameters.Dim[1] = 0;
-  mj2_parameters.w = 352;                      // CIF default value
-  mj2_parameters.h = 288;                      // CIF default value
-  mj2_parameters.CbCr_subsampling_dx = 2;      // CIF default value
-  mj2_parameters.CbCr_subsampling_dy = 2;      // CIF default value
-  mj2_parameters.frame_rate = 25;        
-       /*
+       mj2_parameters.w = 352;                 // CIF default value
+       mj2_parameters.h = 288;                 // CIF default value
+       mj2_parameters.CbCr_subsampling_dx = 2; // CIF default value
+       mj2_parameters.CbCr_subsampling_dy = 2; // CIF default value
+       mj2_parameters.frame_rate = 25;
+       mj2_parameters.prec = 8; /* DEFAULT */
+       mj2_parameters.enumcs = ENUMCS_SYCC; /* FIXME: ENUMCS_YUV420 */
+       mj2_parameters.meth = 1; /* enumerated color space */
+
+/*
        configure the event callbacks (not required)
        setting of each callback is optionnal
-       */
+*/
        memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
        event_mgr.error_handler = error_callback;
        event_mgr.warning_handler = warning_callback;
@@ -280,12 +288,9 @@ int main(int argc, char **argv)
                sprintf(j2k_parameters->cp_comment,"%s%s", comment, version);
        }
 
-       mj2_parameters.decod_format = 0;
-       mj2_parameters.cod_format = 0;
-
   while (1) {
     int c = getopt(argc, argv,
-      "i:o:r:q:f:t:n:c:b:p:s:d:P:S:E:M:R:T:C:I:W:F:h");
+      "i:o:r:q:f:t:n:c:b:p:s:d:P:S:E:M:R:T:C:I:W:F:D:h");
     if (c == -1)
       break;
     switch (c) {
@@ -602,6 +607,10 @@ int main(int argc, char **argv)
       }
       break;
       /* ------------------------------------------------------ */
+       case 'D': /* Depth: the precision */
+               if(sscanf(optarg, "%d", &prec) != 1) prec = 0;
+               break;
+
     default:
       return 1;
     }
@@ -657,17 +666,21 @@ int main(int argc, char **argv)
                + 1 : mj2_parameters.Dim[0] + (mj2_parameters.w - 1) * j2k_parameters->subsampling_dx + 1;
   y1 = !mj2_parameters.Dim[1] ? (mj2_parameters.h - 1) * j2k_parameters->subsampling_dy 
                + 1 : mj2_parameters.Dim[1] + (mj2_parameters.h - 1) * j2k_parameters->subsampling_dy + 1;   
-  mj2_parameters.numcomps = 3;                 /* Because YUV files only have 3 components */ 
-  mj2_parameters.prec = 8;                     /* Because in YUV files, components have 8-bit depth */
+       mj2_parameters.numcomps = 3; /* YUV files only have 3 components */ 
+
+
+       if(prec < 1 || prec > 32) prec = 8; /* DEFAULT */
+
+       mj2_parameters.prec = prec;
 
        j2k_parameters->tcp_mct = 0;
     
-  mj2file = fopen(mj2_parameters.outfile, "wb");
+       mj2file = fopen(mj2_parameters.outfile, "wb");
   
-  if (!mj2file) {
+       if (!mj2file) {
     fprintf(stderr, "failed to open %s for writing\n", argv[2]);
     return 1;
-  }
+       }
     
        /* get a MJ2 decompressor handle */
        cinfo = mj2_create_compress();
@@ -679,128 +692,151 @@ int main(int argc, char **argv)
        /* setup encoder parameters */
        mj2_setup_encoder(movie, &mj2_parameters);   
   
-  movie->tk[0].num_samples = yuv_num_frames(&movie->tk[0],mj2_parameters.infile); 
-  if (movie->tk[0].num_samples == -1) {
+       movie->tk[0].num_samples = 
+        yuv_num_frames(&movie->tk[0],mj2_parameters.infile);
+
+       if (movie->tk[0].num_samples == -1) {
                return 1;
-  }
-  
+       }
+
   // One sample per chunk
-  movie->tk[0].chunk = (mj2_chunk_t*) malloc(movie->tk[0].num_samples * sizeof(mj2_chunk_t));     
-  movie->tk[0].sample = (mj2_sample_t*) malloc(movie->tk[0].num_samples * sizeof(mj2_sample_t));
+       movie->tk[0].chunk = (mj2_chunk_t*) 
+        malloc(movie->tk[0].num_samples * sizeof(mj2_chunk_t));     
+       movie->tk[0].sample = (mj2_sample_t*) 
+        malloc(movie->tk[0].num_samples * sizeof(mj2_sample_t));
   
-  if (mj2_init_stdmovie(movie)) {
+       if (mj2_init_stdmovie(movie)) {
     fprintf(stderr, "Error with movie initialization");
     return 1;
-  };    
+       }    
   
-  // Writing JP, FTYP and MDAT boxes 
-  buf = (unsigned char*) malloc (300 * sizeof(unsigned char)); // Assuming that the JP and FTYP
-  // boxes won't be longer than 300 bytes
+// Writing JP, FTYP and MDAT boxes 
+// Assuming that the JP and FTYP boxes won't be longer than 300 bytes:
+       buf = (unsigned char*) 
+        malloc (300 * sizeof(unsigned char));
+
        cio = opj_cio_open((opj_common_ptr)movie->cinfo, buf, 300);
-  mj2_write_jp(cio);
-  mj2_write_ftyp(movie, cio);
-  mdat_initpos = cio_tell(cio);
-  cio_skip(cio, 4);
-  cio_write(cio, MJ2_MDAT, 4); 
-  fwrite(buf,cio_tell(cio),1,mj2file);
-  offset = cio_tell(cio);
-  opj_cio_close(cio);
-  free(buf);
-
-  for (i = 0; i < movie->num_stk + movie->num_htk + movie->num_vtk; i++) {
-    if (movie->tk[i].track_type != 0) {
-      fprintf(stderr, "Unable to write sound or hint tracks\n");
-    } else {
-      mj2_tk_t *tk;
-                       int buflen = 0;
-      
-      tk = &movie->tk[i];     
-      tk->num_chunks = tk->num_samples;
-                       numframes = tk->num_samples;
-
-      fprintf(stderr, "Video Track number %d\n", i + 1);
-                       
-                       img = mj2_image_create(tk, j2k_parameters);          
-                       buflen = 2 * (tk->w * tk->h * 8);
-                       buf = (unsigned char *) malloc(buflen*sizeof(unsigned char));   
-
-      for (sampleno = 0; sampleno < numframes; sampleno++) {           
-                               double init_time = opj_clock();
-                               double elapsed_time;
-                               if (yuvtoimage(tk, img, sampleno, j2k_parameters, mj2_parameters.infile)) {
-                                       fprintf(stderr, "Error with frame number %d in YUV file\n", sampleno);
-                                       return 1;
-                               }
 
-                               /* setup the encoder parameters using the current image and user parameters */
-                               opj_setup_encoder(cinfo, j2k_parameters, img);
+       mj2_write_jp(cio);
+       mj2_write_ftyp(movie, cio);
+
+       mdat_initpos = cio_tell(cio);
+       cio_skip(cio, 4);
+
+       cio_write(cio, MJ2_MDAT, 4);    
+
+       fwrite(buf,cio_tell(cio),1,mj2file);
+
+       offset = cio_tell(cio);
+       opj_cio_close(cio);
+       free(buf);
+
+       for(i = 0; i < movie->num_stk + movie->num_htk + movie->num_vtk; i++) 
+   {
+    if(movie->tk[i].track_type != 0) 
+  {
+       fprintf(stderr, "Unable to write sound or hint tracks\n");
+  }
+       else 
+  {
+       mj2_tk_t *tk;
+       int buflen = 0;
+  
+       tk = &movie->tk[i];     
+       tk->num_chunks = tk->num_samples;
+       numframes = tk->num_samples;
+       tk->depth = prec; 
+
+       fprintf(stderr, "Video Track number %d\n", i);
+
+       img = mj2_image_create(tk, j2k_parameters);          
+
+       buflen = 2 * (tk->w * tk->h * 8);
+       buf = (unsigned char *) malloc(buflen*sizeof(unsigned char));   
+
+       for(sampleno = 0; sampleno < numframes; sampleno++) 
+ {
+       double init_time = opj_clock();
+       double elapsed_time;
 
-                               cio = opj_cio_open((opj_common_ptr)movie->cinfo, buf, buflen);
+               if(yuvtoimage(tk, img, sampleno, j2k_parameters, 
+                       mj2_parameters.infile))
+          {
+               fprintf(stderr, "Error with frame number %d in YUV file\n", sampleno);
+               return 1;
+          }
+
+/* setup the encoder parameters using the current image and user parameters */
+       opj_setup_encoder(cinfo, j2k_parameters, img);
+
+       cio = opj_cio_open((opj_common_ptr)movie->cinfo, buf, buflen);
                                                                
-                               cio_skip(cio, 4);
-                               cio_write(cio, JP2_JP2C, 4);    // JP2C
-
-                               /* encode the image */
-                               bSuccess = opj_encode(cinfo, cio, img, NULL);
-                               if (!bSuccess) {
-                                       opj_cio_close(cio);
-                                       fprintf(stderr, "failed to encode image\n");
-                                       return 1;
-                               }
+       cio_skip(cio, 4);
+       cio_write(cio, JP2_JP2C, 4);    // JP2C
 
-                               len = cio_tell(cio) - 8;
-                               cio_seek(cio, 0);
-                               cio_write(cio, len+8,4);
-                               opj_cio_close(cio);
-                               tk->sample[sampleno].sample_size = len+8;                               
-                               tk->sample[sampleno].offset = offset;
-                               tk->chunk[sampleno].offset = offset;    // There is one sample per chunk 
-                               fwrite(buf, 1, len+8, mj2file);                         
-                               offset += len+8;                                
-                               elapsed_time = opj_clock()-init_time;
-                               fprintf(stderr, "Frame number %d/%d encoded in %.2f mseconds\n", sampleno + 1, numframes, elapsed_time*1000);
-                               total_time += elapsed_time;
+/* encode the image */
+       bSuccess = opj_encode(cinfo, cio, img, NULL);
 
-      }
-                       /* free buffer data */
-                       free(buf);
-                       /* free image data */
-                       opj_image_destroy(img);
-    }
+       if (!bSuccess) {
+       opj_cio_close(cio);
+       fprintf(stderr, "failed to encode image\n");
+       return 1;
+       }
+
+       len = cio_tell(cio) - 8;
+       cio_seek(cio, 0);
+       cio_write(cio, len+8,4);
+       opj_cio_close(cio);
+
+       tk->sample[sampleno].sample_size = len+8;                               
+       tk->sample[sampleno].offset = offset;
+       tk->chunk[sampleno].offset = offset;    // There is one sample per chunk 
+       fwrite(buf, 1, len+8, mj2file);                         
+       offset += len+8;                                
+
+       elapsed_time = opj_clock()-init_time;
+       fprintf(stderr, "Frame number %d/%d encoded in %.2f mseconds\n", 
+               sampleno + 1, numframes, elapsed_time*1000);
+       total_time += elapsed_time;
+ }     /* for(sampleno */
+
+       free(buf);
+       opj_image_destroy(img);
   }
+   }/* for(i */
   
-  fseek(mj2file, mdat_initpos, SEEK_SET);
+       fseek(mj2file, mdat_initpos, SEEK_SET);
        
-  buf = (unsigned char*) malloc(4*sizeof(unsigned char));
+       buf = (unsigned char*) malloc(4*sizeof(unsigned char));
 
-       // Init a cio to write box length variable in a little endian way 
+// Init a cio to write box length variable in a little endian way 
        cio = opj_cio_open(NULL, buf, 4);
-  cio_write(cio, offset - mdat_initpos, 4);
-  fwrite(buf, 4, 1, mj2file);
-  fseek(mj2file,0,SEEK_END);
-  free(buf);
-
-  // Writing MOOV box 
-       buf = (unsigned char*) malloc ((TEMP_BUF+numframes*20) * sizeof(unsigned char));
+       cio_write(cio, offset - mdat_initpos, 4);
+       fwrite(buf, 4, 1, mj2file);
+       fseek(mj2file,0,SEEK_END);
+       free(buf);
+
+// Writing MOOV box 
+       buf = (unsigned char*) 
+        malloc ((TEMP_BUF+numframes*20) * sizeof(unsigned char));
        cio = opj_cio_open(movie->cinfo, buf, (TEMP_BUF+numframes*20));
        mj2_write_moov(movie, cio);
-  fwrite(buf,cio_tell(cio),1,mj2file);
-  free(buf);
+       fwrite(buf,cio_tell(cio),1,mj2file);
+       free(buf);
+
+       fprintf(stdout,"Total encoding time: %.2f s for %d frames (%.1f fps)\n",
+        total_time, numframes, (float)numframes/total_time);
 
-       fprintf(stdout,"Total encoding time: %.2f s for %d frames (%.1f fps)\n", total_time, numframes, (float)numframes/total_time);
-  
   // Ending program 
   
-  fclose(mj2file);
-       /* free remaining compression structures */
+       fclose(mj2file);
+/* free remaining compression structures */
        mj2_destroy_compress(movie);
        free(cinfo);
-       /* free user parameters structure */
-  if(j2k_parameters->cp_comment) free(j2k_parameters->cp_comment);
+
+       if(j2k_parameters->cp_comment) free(j2k_parameters->cp_comment);
        if(j2k_parameters->cp_matrice) free(j2k_parameters->cp_matrice);
        opj_cio_close(cio);
 
-  return 0;
+       return 0;
 }
-
-