From 78003a016a30c4d64779e09bb7135861db4c1b89 Mon Sep 17 00:00:00 2001
From: Parvatha Elangovan
Date: Wed, 7 Mar 2007 16:04:33 +0000
Subject: [PATCH] Added option for Digital cinema profile compliant codestream.
This can be chosen by "-cinema2K" or "-cinema4K" for a 2K and 4K compliance
respectively. The feature for tileparts has not been implemented in this
version. Modification in image_to_j2k.c Added the Digital Cinema profiles
(CINEMA2K and CINEMA4K) to the list of profiles recognized in the codestream
SIZ marker segment. Modification in openjpeg.h,j2k.c Added feature for
constant quality within bitrate defined in Digital cinema standards.
Modification in tcd.c Modified the method of generation of buffer length.
Modification in cio.c
---
ChangeLog | 7 ++
codec/image_to_j2k.c | 143 +++++++++++++++++++++++++++++++++++++----
libopenjpeg/cio.c | 2 +-
libopenjpeg/j2k.c | 98 +++++++++++++++++-----------
libopenjpeg/j2k.h | 6 ++
libopenjpeg/openjpeg.c | 2 +
libopenjpeg/openjpeg.h | 19 ++++++
libopenjpeg/tcd.c | 28 ++++++--
8 files changed, 249 insertions(+), 56 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 5ec873e2..3c55378f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -5,6 +5,13 @@ What's New for OpenJPEG
! : changed
+ : added
+March 7, 2007
++ [Parvatha] Added option for Digital cinema profile compliant codestream. This can be chosen by "-cinema2K" or "-cinema4K" for a 2K and 4K compliance respectively. The feature for tileparts has not been implemented in this version. Modification in image_to_j2k.c
++ [Parvatha] Added the Digital Cinema profiles (CINEMA2K and CINEMA4K) to the list of profiles recognized in the codestream SIZ marker segment. Modification in openjpeg.h,j2k.c
++ [Parvatha] Added feature for constant quality within bitrate defined in Digital cinema standards. Modification in tcd.c
+! [Parvatha] Modified the method of generation of buffer length. Modification in cio.c
+
+
March 1, 2007
* [FOD] Modified codec projects (*.dsp) and makefile to include the tiff library (modified codec/image_to_j2k.dsp codec/j2k_to_image.dsp and codec/makefile)
+ [GB] Zoom capability and decoder settings dialog in OPJViewer; modified JPWL library .dsp project in order to create a library with embedded JPWL functions
diff --git a/codec/image_to_j2k.c b/codec/image_to_j2k.c
index 28208c5c..014ae1d9 100644
--- a/codec/image_to_j2k.c
+++ b/codec/image_to_j2k.c
@@ -55,6 +55,8 @@
#define TIF_DFMT 14
/* ----------------------------------------------------------------------- */
+#define CINEMA_24_CS 1302083 /*Codestream length for 24fps*/
+#define CINEMA_48_CS 651041 /*Codestream length for 48fps*/
typedef struct dircnt{
/** Buffer for holding images read from Directory*/
@@ -125,8 +127,10 @@ void encode_help_display() {
fprintf(stdout,"------------\n");
fprintf(stdout,"\n");
fprintf(stdout,"Required Parameters (except with -h):\n");
+ fprintf(stdout,"One of the two options -ImgDir or -i must be used\n");
fprintf(stdout,"\n");
fprintf(stdout,"-ImgDir : Image file Directory path (example ../Images) \n");
+ fprintf(stdout," When using this option -OutFor must be used\n");
fprintf(stdout,"\n");
fprintf(stdout,"-OutFor \n");
fprintf(stdout," REQUIRED only if -ImgDir is used\n");
@@ -134,6 +138,7 @@ void encode_help_display() {
fprintf(stdout," Currently accepts PGM, PPM, PNM, PGX, BMP format\n");
fprintf(stdout,"\n");
fprintf(stdout,"-i : source file (-i source.pnm also *.pgm, *.ppm) \n");
+ fprintf(stdout," When using this option -o must be used\n");
fprintf(stdout,"\n");
fprintf(stdout,"-o : destination file (-o dest.j2k or .jp2) \n");
fprintf(stdout,"\n");
@@ -141,6 +146,12 @@ void encode_help_display() {
fprintf(stdout,"\n");
fprintf(stdout,"-h : display the help information \n ");
fprintf(stdout,"\n");
+ fprintf(stdout,"-cinema2k : Digital Cinema 2K profile compliant codestream for 2K resolution.(-cinema2k 24 or 48) \n");
+ fprintf(stdout," Need to specify the frames per second for a 2K resolution. Only 24 or 48 fps is allowed\n");
+ fprintf(stdout,"\n");
+ fprintf(stdout,"-cinema4k : Digital Cinema 4K profile compliant codestream for 4K resolution \n");
+ fprintf(stdout," Frames per second not required. Default value is 24fps\n");
+ fprintf(stdout,"\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");
@@ -403,16 +414,92 @@ char get_next_file(int imageno,dircnt_t *dirptr,img_fol_t *img_fol, opj_cparamet
}
+void cinema_setup_encoder(opj_cparameters_t *parameters,opj_image_t *image){
+ int i;
+ float temp_rate;
+
+ parameters->tile_size_on = false;
+ parameters->cp_tdx=1;
+ parameters->cp_tdy=1;
+ /*Tile and Image shall be at (0,0)*/
+ parameters->cp_tx0=0; parameters->cp_ty0=0;
+
+ /*Codeblock size= 32*32*/
+ parameters->cblockw_init = 32;
+ parameters->cblockh_init = 32;
+
+ /*The progression order shall be CPRL*/
+ strncpy(parameters->cp_prog,"CPRL",4);
+ parameters->prog_order = give_progression(parameters->cp_prog);
+ /*Tile parts not implemented*/
+
+ /* No ROI */
+ parameters->roi_compno = -1;
+
+ parameters->subsampling_dx = 1; parameters->subsampling_dy = 1;
+
+ switch (parameters->cp_cinema){
+ case CINEMA2K_24:
+ case CINEMA4K_24:
+ if (image->comps[0].w == 2048 || image->comps[0].h == 1080){
+ parameters->numresolution = 6;
+ parameters->cp_rsiz = CINEMA2K;
+ }else{
+ fprintf(stdout,"One of the image coordinates are not 2K\n");
+ }
+
+ for(i=0;itcp_numlayers;i++){
+ temp_rate = 0 ;
+ if (parameters->tcp_rates[i]== 0){
+ parameters->tcp_rates[0]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/
+ (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
+ }else{
+ temp_rate =((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/
+ (parameters->tcp_rates[i] * 8 * image->comps[0].dx * image->comps[0].dy);
+ if (temp_rate > CINEMA_24_CS ){
+ parameters->tcp_rates[i]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/
+ (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
+ }
+ }
+ }
+ break;
+
+ case CINEMA2K_48:
+ if (image->comps[0].w == 4096 || image->comps[0].h == 2160){
+ parameters->numresolution = 7;
+ parameters->cp_rsiz= CINEMA4K;
+ }else{
+ fprintf(stdout,"One of the image coordinates are not 4K\n");
+ }
+ for(i=0;itcp_numlayers;i++){
+ if (parameters->tcp_rates[i]== 0){
+ parameters->tcp_rates[0]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/
+ (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
+ }else{
+ parameters->tcp_rates[i]=((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/
+ (parameters->tcp_rates[i] * 8 * image->comps[0].dx * image->comps[0].dy);
+ if (parameters->tcp_rates[i] > CINEMA_48_CS ){
+ parameters->tcp_rates[0]= ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))/
+ (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
+ }
+ }
+ }
+ break;
+
+}
+
+ parameters->cp_disto_alloc = 1;
+}
/* ------------------------------------------------------------------------------------ */
int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters,img_fol_t *img_fol) {
int i, j,totlen;
option_t long_option[]={
- {"DCI",NO_ARG, NULL ,'z'},
- {"ImgDir",REQ_ARG, NULL ,'y'},
- {"fps",REQ_ARG, NULL ,'w'},
+ {"cinema2k",REQ_ARG, NULL ,'w'},
+ {"cinema4k",NO_ARG, NULL ,'y'},
+ {"ImgDir",REQ_ARG, NULL ,'z'},
{"TP",REQ_ARG, NULL ,'v'},
{"SOP",NO_ARG, NULL ,'S'},
{"EPH",NO_ARG, NULL ,'E'},
@@ -803,17 +890,45 @@ int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters,i
break;
/* ------------------------------------------------------ */
-
- case 'y': /* Image Directory path */
- {
- img_fol->imgdirpath = (char*)malloc(strlen(optarg) + 1);
- strcpy(img_fol->imgdirpath,optarg);
- img_fol->set_imgdir=1;
- }
- break;
-
+
+ case 'z': /* Image Directory path */
+ {
+ img_fol->imgdirpath = (char*)malloc(strlen(optarg) + 1);
+ strcpy(img_fol->imgdirpath,optarg);
+ img_fol->set_imgdir=1;
+ }
+ break;
/* ------------------------------------------------------ */
+
+ case 'w': /* Digital Cinema 2K profile compliance*/
+ {
+ int fps=0;
+ sscanf(optarg,"%d",&fps);
+ if(fps == 24){
+ parameters->cp_cinema = CINEMA2K_24;
+ }else if(fps == 48 ){
+ parameters->cp_cinema = CINEMA2K_48;
+ }else {
+ fprintf(stderr,"Incorrect value!! must be 24 or 48\n");
+ return 1;
+ }
+ fprintf(stdout,"CINEMA 2K compliant codestream\n");
+
+ }
+ break;
+
+ /* ------------------------------------------------------ */
+
+ case 'y': /* Digital Cinema 4K profile compliance*/
+ {
+ parameters->cp_cinema = CINEMA4K_24;
+ fprintf(stdout,"CINEMA 4K compliant codestream\n");
+ }
+ break;
+
+ /* ------------------------------------------------------ */
+
/* UniPG>> */
#ifdef USE_JPWL
/* ------------------------------------------------------ */
@@ -1379,6 +1494,10 @@ int main(int argc, char **argv) {
/* catch events using our callbacks and give a local context */
opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
+ if(parameters.cp_cinema){
+ cinema_setup_encoder(¶meters,image);
+ }
+
/* setup the encoder parameters using the current image and user parameters */
opj_setup_encoder(cinfo, ¶meters, image);
diff --git a/libopenjpeg/cio.c b/libopenjpeg/cio.c
index eadf71b2..6082e9be 100644
--- a/libopenjpeg/cio.c
+++ b/libopenjpeg/cio.c
@@ -58,7 +58,7 @@ opj_cio_t* OPJ_CALLCONV opj_cio_open(opj_common_ptr cinfo, unsigned char *buffer
opj_free(cio);
return NULL;
}
- cio->length = cp->tdx * cp->tdy * cp->tw * cp->th * 4;
+ cio->length = (int) (1.3 * cp->img_size);
cio->buffer = (unsigned char *)opj_malloc(cio->length);
if(!cio->buffer) {
opj_free(cio);
diff --git a/libopenjpeg/j2k.c b/libopenjpeg/j2k.c
index db291ff2..fb9aeaff 100644
--- a/libopenjpeg/j2k.c
+++ b/libopenjpeg/j2k.c
@@ -324,7 +324,7 @@ static void j2k_write_siz(opj_j2k_t *j2k) {
cio_write(cio, J2K_MS_SIZ, 2); /* SIZ */
lenp = cio_tell(cio);
cio_skip(cio, 2);
- cio_write(cio, 0, 2); /* Rsiz (capabilities) */
+ cio_write(cio, cp->rsiz, 2); /* Rsiz (capabilities) */
cio_write(cio, image->x1, 4); /* Xsiz */
cio_write(cio, image->y1, 4); /* Ysiz */
cio_write(cio, image->x0, 4); /* X0siz */
@@ -1780,7 +1780,8 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_
/*
copy user encoding parameters
*/
-
+ cp->cinema = parameters->cp_cinema;
+ cp->rsiz = parameters->cp_rsiz;
cp->disto_alloc = parameters->cp_disto_alloc;
cp->fixed_alloc = parameters->cp_fixed_alloc;
cp->fixed_quality = parameters->cp_fixed_quality;
@@ -1826,6 +1827,11 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_
cp->tdy = image->y1 - cp->ty0;
}
+ cp->img_size = 0;
+ for(i=0;inumcomps ;i++){
+ cp->img_size += (image->comps[i].w *image->comps[i].h * image->comps[i].prec);
+ }
+
/* UniPG>> */
#ifdef USE_JPWL
/*
@@ -1940,42 +1946,60 @@ void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_
} else {
tccp->roishift = 0;
}
- if (parameters->csty & J2K_CCP_CSTY_PRT) {
- int p = 0;
- for (j = tccp->numresolutions - 1; j >= 0; j--) {
- if (p < parameters->res_spec) {
- if (parameters->prcw_init[p] < 1) {
- tccp->prcw[j] = 1;
- } else {
- tccp->prcw[j] = int_floorlog2(parameters->prcw_init[p]);
- }
- if (parameters->prch_init[p] < 1) {
- tccp->prch[j] = 1;
- } else {
- tccp->prch[j] = int_floorlog2(parameters->prch_init[p]);
- }
- } else {
- int res_spec = parameters->res_spec;
- int size_prcw = parameters->prcw_init[res_spec - 1] >> (p - (res_spec - 1));
- int size_prch = parameters->prch_init[res_spec - 1] >> (p - (res_spec - 1));
- if (size_prcw < 1) {
- tccp->prcw[j] = 1;
- } else {
- tccp->prcw[j] = int_floorlog2(size_prcw);
- }
- if (size_prch < 1) {
- tccp->prch[j] = 1;
- } else {
- tccp->prch[j] = int_floorlog2(size_prch);
- }
- }
- p++;
- /*printf("\nsize precinct for level %d : %d,%d\n", j,tccp->prcw[j], tccp->prch[j]); */
+
+ if(parameters->cp_cinema)
+ {
+ //Precinct size for lowest frequency subband=128
+ tccp->prcw[0] = 7;
+ tccp->prch[0] = 7;
+ //Precinct size at all other resolutions = 256
+ for (j = 1; j < tccp->numresolutions; j++) {
+ tccp->prcw[j] = 8;
+ tccp->prch[j] = 8;
}
- } else {
- for (j = 0; j < tccp->numresolutions; j++) {
- tccp->prcw[j] = 15;
- tccp->prch[j] = 15;
+ }else{
+ if (parameters->csty & J2K_CCP_CSTY_PRT) {
+ int p = 0;
+ for (j = tccp->numresolutions - 1; j >= 0; j--) {
+ if (p < parameters->res_spec) {
+
+ if (parameters->prcw_init[p] < 1) {
+ tccp->prcw[j] = 1;
+ } else {
+ tccp->prcw[j] = int_floorlog2(parameters->prcw_init[p]);
+ }
+
+ if (parameters->prch_init[p] < 1) {
+ tccp->prch[j] = 1;
+ }else {
+ tccp->prch[j] = int_floorlog2(parameters->prch_init[p]);
+ }
+
+ } else {
+ int res_spec = parameters->res_spec;
+ int size_prcw = parameters->prcw_init[res_spec - 1] >> (p - (res_spec - 1));
+ int size_prch = parameters->prch_init[res_spec - 1] >> (p - (res_spec - 1));
+
+ if (size_prcw < 1) {
+ tccp->prcw[j] = 1;
+ } else {
+ tccp->prcw[j] = int_floorlog2(size_prcw);
+ }
+
+ if (size_prch < 1) {
+ tccp->prch[j] = 1;
+ } else {
+ tccp->prch[j] = int_floorlog2(size_prch);
+ }
+ }
+ p++;
+ /*printf("\nsize precinct for level %d : %d,%d\n", j,tccp->prcw[j], tccp->prch[j]); */
+ } //end for
+ } else {
+ for (j = 0; j < tccp->numresolutions; j++) {
+ tccp->prcw[j] = 15;
+ tccp->prch[j] = 15;
+ }
}
}
diff --git a/libopenjpeg/j2k.h b/libopenjpeg/j2k.h
index 9738bf85..5f8e0824 100644
--- a/libopenjpeg/j2k.h
+++ b/libopenjpeg/j2k.h
@@ -187,6 +187,12 @@ typedef struct opj_tcp {
Coding parameters
*/
typedef struct opj_cp {
+ /** Digital cinema profile*/
+ OPJ_CINEMA_MODE cinema;
+ /** Size of the image in bits*/
+ int img_size;
+ /** Rsiz*/
+ OPJ_RSIZ_CAPABILITIES rsiz;
/** allocation by rate/distortion */
int disto_alloc;
/** allocation by fixed layer */
diff --git a/libopenjpeg/openjpeg.c b/libopenjpeg/openjpeg.c
index b522939e..3db8a5f7 100644
--- a/libopenjpeg/openjpeg.c
+++ b/libopenjpeg/openjpeg.c
@@ -222,7 +222,9 @@ void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *paramete
if(parameters) {
memset(parameters, 0, sizeof(opj_cparameters_t));
/* default coding parameters */
+ parameters->cp_cinema = OFF;
parameters->numresolution = 6;
+ parameters->cp_rsiz = STD_RSIZ;
parameters->cblockw_init = 64;
parameters->cblockh_init = 64;
parameters->prog_order = LRCP;
diff --git a/libopenjpeg/openjpeg.h b/libopenjpeg/openjpeg.h
index ceb5df2c..d5543b92 100644
--- a/libopenjpeg/openjpeg.h
+++ b/libopenjpeg/openjpeg.h
@@ -113,6 +113,19 @@ braindamage below.
==========================================================
*/
+typedef enum RSIZ_CAPABILITIES {
+ STD_RSIZ = 0,
+ CINEMA2K = 3, /** Profile name for a 2K image*/
+ CINEMA4K = 4 /** Profile name for a 4K image*/
+} OPJ_RSIZ_CAPABILITIES;
+
+typedef enum CINEMA_MODE {
+ OFF = 0,
+ CINEMA2K_24 = 1,
+ CINEMA2K_48 = 2,
+ CINEMA4K_24 = 3
+}OPJ_CINEMA_MODE;
+
/** Progression order */
typedef enum PROG_ORDER {
PROG_UNKNOWN = -1, /**< place-holder */
@@ -204,6 +217,12 @@ typedef struct opj_poc {
Compression parameters
*/
typedef struct opj_cparameters {
+ /** Digital Cinema compliance 0-not compliant, 1-compliant*/
+ OPJ_CINEMA_MODE cp_cinema;
+ /** Progression order*/
+ char cp_prog[4];
+ /** Profile name*/
+ OPJ_RSIZ_CAPABILITIES cp_rsiz;
/** size of tile: tile_size_on = false (not in argument) or = true (in argument) */
bool tile_size_on;
/** XTOsiz */
diff --git a/libopenjpeg/tcd.c b/libopenjpeg/tcd.c
index 73c3ef5e..89658ce7 100644
--- a/libopenjpeg/tcd.c
+++ b/libopenjpeg/tcd.c
@@ -1040,13 +1040,29 @@ bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_image_in
tcd_makelayer(tcd, layno, thresh, 0);
if (cp->fixed_quality) { /* fixed_quality */
- distoachieved = (layno == 0) ?
- tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]);
- if (distoachieved < distotarget) {
- hi = thresh;
- continue;
+ if(cp->cinema){
+ l = t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, maxlen, image_info);
+ if (l == -999) {
+ lo = thresh;
+ continue;
+ }else{
+ distoachieved = layno == 0 ?
+ tcd_tile->distolayer[0] : cumdisto[layno - 1] + tcd_tile->distolayer[layno];
+ if (distoachieved < distotarget) {
+ hi=thresh; continue;
+ }else{
+ lo=thresh;
+ }
+ }
+ }else{
+ distoachieved = (layno == 0) ?
+ tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]);
+ if (distoachieved < distotarget) {
+ hi = thresh;
+ continue;
+ }
+ lo = thresh;
}
- lo = thresh;
} else {
l = t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, maxlen, image_info);
/* TODO: what to do with l ??? seek / tell ??? */