code originates from image_to_j2k.c provided by openjpeg Signed-off-by: Jean First <jeanfi...@gmail.com> --- libavcodec/libopenjpegenc.c | 118 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/libavcodec/libopenjpegenc.c b/libavcodec/libopenjpegenc.c index b9a8bac..8c8bf67 100644 --- a/libavcodec/libopenjpegenc.c +++ b/libavcodec/libopenjpegenc.c @@ -26,6 +26,11 @@ #define OPJ_STATIC +#define CINEMA_24_CS 1302083 /* Codestream length for 24fps */ +#define CINEMA_48_CS 651041 /* Codestream length for 48fps */ +#define COMP_24_CS 1041666 /* Maximum size per color component for 2K & 4K @ 24fps */ +#define COMP_48_CS 520833 /* Maximum size per color component for 2K @ 48fps */ + #include "libavutil/avassert.h" #include "libavutil/common.h" #include "libavutil/imgutils.h" @@ -75,6 +80,25 @@ static void info_callback(const char *msg, void *data) av_log(data, AV_LOG_DEBUG, "%s\n", msg); } +static int initialise_4K_poc(opj_poc_t *POC, int numres) +{ + POC[0].tile = 1; + POC[0].resno0 = 0; + POC[0].compno0 = 0; + POC[0].layno1 = 1; + POC[0].resno1 = numres - 1; + POC[0].compno1 = 3; + POC[0].prg1 = CPRL; + POC[1].tile = 1; + POC[1].resno0 = numres - 1; + POC[1].compno0 = 0; + POC[1].layno1 = 1; + POC[1].resno1 = numres; + POC[1].compno1 = 3; + POC[1].prg1 = CPRL; + return 2; +} + static void cinema_parameters(opj_cparameters_t *p) { p->tile_size_on = 0; @@ -110,8 +134,98 @@ static void cinema_parameters(opj_cparameters_t *p) p->irreversible = 1; } +static void cinema_setup_encoder(AVCodecContext *avctx, opj_image_t *image) +{ + LibOpenJPEGContext *ctx = avctx->priv_data; + opj_cparameters_t *parameters = &ctx->enc_params; + int i; + float temp_rate; + + switch (parameters->cp_cinema) { + case CINEMA2K_24: + case CINEMA2K_48: + if (parameters->numresolution > 6) { + parameters->numresolution = 6; + } + if (!((image->comps[0].w == 2048) || (image->comps[0].h == 1080))) { + av_log(avctx, AV_LOG_WARNING, "Image coordinates %d x %d is not 2K compliant.\nJPEG Digital Cinema Profile-3 " + "(2K profile) compliance requires that at least one of coordinates match 2048 x 1080\n", + image->comps[0].w, image->comps[0].h); + parameters->cp_rsiz = STD_RSIZ; + } + break; + + case CINEMA4K_24: + if (parameters->numresolution < 1) { + parameters->numresolution = 1; + } else if (parameters->numresolution > 7) { + parameters->numresolution = 7; + } + if (!((image->comps[0].w == 4096) || (image->comps[0].h == 2160))) { + av_log(avctx, AV_LOG_WARNING, "Image coordinates %d x %d is not 4K compliant.\nJPEG Digital Cinema Profile-4" + "(4K profile) compliance requires that at least one of coordinates match 4096 x 2160\n", + image->comps[0].w, image->comps[0].h); + parameters->cp_rsiz = STD_RSIZ; + } + parameters->numpocs = initialise_4K_poc(parameters->POC, parameters->numresolution); + break; + case OFF: + /* do nothing */ + break; + } + + switch (parameters->cp_cinema) { + case CINEMA2K_24: + case CINEMA4K_24: + for (i = 0; i < parameters->tcp_numlayers; i++) { + temp_rate = 0; + if (ctx->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)) / + (ctx->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); + } else { + parameters->tcp_rates[i] = ctx->tcp_rates[i]; + } + } + } + parameters->max_comp_size = COMP_24_CS; + break; + + case CINEMA2K_48: + for (i = 0; i < parameters->tcp_numlayers; i++) { + temp_rate = 0; + if (ctx->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 { + temp_rate = ((float) (image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec)) / + (ctx->tcp_rates[i] * 8 * image->comps[0].dx * image->comps[0].dy); + if (temp_rate > 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); + } else { + parameters->tcp_rates[i] = ctx->tcp_rates[i]; + } + } + } + parameters->max_comp_size = COMP_48_CS; + break; + case OFF: + /* do nothing */ + break; + } + parameters->cp_disto_alloc = 1; +} + static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *parameters) { + LibOpenJPEGContext *ctx = avctx->priv_data; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); opj_image_cmptparm_t cmptparm[4] = {{0}}; opj_image_t *img; @@ -208,6 +322,10 @@ static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *p img->x1 = (avctx->width - 1) * parameters->subsampling_dx + 1; img->y1 = (avctx->height - 1) * parameters->subsampling_dy + 1; + if (ctx->cinema_mode > 0) { + cinema_setup_encoder(avctx, img); + } + return img; } -- 2.2.2 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel