avcodec: add OpenJPEG 2.x compatibility
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
		
							parent
							
								
									9cc1e644f3
								
							
						
					
					
						commit
						99eabcdd5f
					
				
							
								
								
									
										5
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| @ -1777,6 +1777,8 @@ HEADERS_LIST=" | ||||
|     machine_ioctl_bt848_h | ||||
|     machine_ioctl_meteor_h | ||||
|     malloc_h | ||||
|     openjpeg_2_1_openjpeg_h | ||||
|     openjpeg_2_0_openjpeg_h | ||||
|     openjpeg_1_5_openjpeg_h | ||||
|     OpenGL_gl3_h | ||||
|     poll_h | ||||
| @ -5434,7 +5436,8 @@ enabled libopencore_amrnb && require libopencore_amrnb opencore-amrnb/interf_dec | ||||
| enabled libopencore_amrwb && require libopencore_amrwb opencore-amrwb/dec_if.h D_IF_init -lopencore-amrwb | ||||
| enabled libopencv         && require_pkg_config opencv opencv/cxcore.h cvCreateImageHeader | ||||
| enabled libopenh264       && require_pkg_config openh264 wels/codec_api.h WelsGetCodecVersion | ||||
| enabled libopenjpeg       && { check_lib openjpeg.h opj_version -lopenmj2 -DOPJ_STATIC || | ||||
| enabled libopenjpeg       && { check_lib openjpeg-2.1/openjpeg.h opj_version -lopenjp2 -DOPJ_STATIC || | ||||
|                                check_lib openjpeg-2.0/openjpeg.h opj_version -lopenjp2 -DOPJ_STATIC || | ||||
|                                check_lib openjpeg-1.5/openjpeg.h opj_version -lopenjpeg -DOPJ_STATIC || | ||||
|                                check_lib openjpeg.h opj_version -lopenjpeg -DOPJ_STATIC || | ||||
|                                die "ERROR: libopenjpeg not found"; } | ||||
|  | ||||
| @ -36,10 +36,22 @@ | ||||
| #include "internal.h" | ||||
| #include "thread.h" | ||||
| 
 | ||||
| #if HAVE_OPENJPEG_1_5_OPENJPEG_H | ||||
| # include <openjpeg-1.5/openjpeg.h> | ||||
| #if HAVE_OPENJPEG_2_1_OPENJPEG_H | ||||
| #  include <openjpeg-2.1/openjpeg.h> | ||||
| #elif HAVE_OPENJPEG_2_0_OPENJPEG_H | ||||
| #  include <openjpeg-2.0/openjpeg.h> | ||||
| #elif HAVE_OPENJPEG_1_5_OPENJPEG_H | ||||
| #  include <openjpeg-1.5/openjpeg.h> | ||||
| #else | ||||
| # include <openjpeg.h> | ||||
| #  include <openjpeg.h> | ||||
| #endif | ||||
| 
 | ||||
| #if HAVE_OPENJPEG_2_1_OPENJPEG_H || HAVE_OPENJPEG_2_0_OPENJPEG_H | ||||
| #  define OPENJPEG_MAJOR_VERSION 2 | ||||
| #  define OPJ(x) OPJ_##x | ||||
| #else | ||||
| #  define OPENJPEG_MAJOR_VERSION 1 | ||||
| #  define OPJ(x) x | ||||
| #endif | ||||
| 
 | ||||
| #define JP2_SIG_TYPE    0x6A502020 | ||||
| @ -83,7 +95,9 @@ static const enum AVPixelFormat libopenjpeg_all_pix_fmts[]  = { | ||||
| typedef struct LibOpenJPEGContext { | ||||
|     AVClass *class; | ||||
|     opj_dparameters_t dec_params; | ||||
| #if OPENJPEG_MAJOR_VERSION == 1 | ||||
|     opj_event_mgr_t event_mgr; | ||||
| #endif // OPENJPEG_MAJOR_VERSION == 1
 | ||||
|     int lowqual; | ||||
| } LibOpenJPEGContext; | ||||
| 
 | ||||
| @ -102,6 +116,62 @@ static void info_callback(const char *msg, void *data) | ||||
|     av_log(data, AV_LOG_DEBUG, "%s", msg); | ||||
| } | ||||
| 
 | ||||
| #if OPENJPEG_MAJOR_VERSION == 2 | ||||
| typedef struct BufferReader { | ||||
|     int pos; | ||||
|     int size; | ||||
|     const uint8_t *buffer; | ||||
| } BufferReader; | ||||
| 
 | ||||
| static OPJ_SIZE_T stream_read(void *out_buffer, OPJ_SIZE_T nb_bytes, void *user_data) | ||||
| { | ||||
|     BufferReader *reader = user_data; | ||||
|     if (reader->pos == reader->size) { | ||||
|         return (OPJ_SIZE_T)-1; | ||||
|     } | ||||
|     int remaining = reader->size - reader->pos; | ||||
|     if (nb_bytes > remaining) { | ||||
|         nb_bytes = remaining; | ||||
|     } | ||||
|     memcpy(out_buffer, reader->buffer + reader->pos, nb_bytes); | ||||
|     reader->pos += (int)nb_bytes; | ||||
|     return nb_bytes; | ||||
| } | ||||
| 
 | ||||
| static OPJ_OFF_T stream_skip(OPJ_OFF_T nb_bytes, void *user_data) | ||||
| { | ||||
|     BufferReader *reader = user_data; | ||||
|     if (nb_bytes < 0) { | ||||
|         if (reader->pos == 0) { | ||||
|             return (OPJ_SIZE_T)-1; | ||||
|         } | ||||
|         if (nb_bytes + reader->pos < 0) { | ||||
|             nb_bytes = -reader->pos; | ||||
|         } | ||||
|     } else { | ||||
|         if (reader->pos == reader->size) { | ||||
|             return (OPJ_SIZE_T)-1; | ||||
|         } | ||||
|         int remaining = reader->size - reader->pos; | ||||
|         if (nb_bytes > remaining) { | ||||
|             nb_bytes = remaining; | ||||
|         } | ||||
|     } | ||||
|     reader->pos += (int)nb_bytes; | ||||
|     return nb_bytes; | ||||
| } | ||||
| 
 | ||||
| static OPJ_BOOL stream_seek(OPJ_OFF_T nb_bytes, void *user_data) | ||||
| { | ||||
|     BufferReader *reader = user_data; | ||||
|     if (nb_bytes < 0 || nb_bytes > reader->size) { | ||||
|         return OPJ_FALSE; | ||||
|     } | ||||
|     reader->pos = (int)nb_bytes; | ||||
|     return OPJ_TRUE; | ||||
| } | ||||
| #endif // OPENJPEG_MAJOR_VERSION == 2
 | ||||
| 
 | ||||
| static inline int libopenjpeg_matches_pix_fmt(const opj_image_t *image, enum AVPixelFormat pix_fmt) | ||||
| { | ||||
|     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); | ||||
| @ -145,15 +215,15 @@ static inline enum AVPixelFormat libopenjpeg_guess_pix_fmt(const opj_image_t *im | ||||
|     int possible_fmts_nb = 0; | ||||
| 
 | ||||
|     switch (image->color_space) { | ||||
|     case CLRSPC_SRGB: | ||||
|     case OPJ(CLRSPC_SRGB): | ||||
|         possible_fmts    = libopenjpeg_rgb_pix_fmts; | ||||
|         possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_rgb_pix_fmts); | ||||
|         break; | ||||
|     case CLRSPC_GRAY: | ||||
|     case OPJ(CLRSPC_GRAY): | ||||
|         possible_fmts    = libopenjpeg_gray_pix_fmts; | ||||
|         possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_gray_pix_fmts); | ||||
|         break; | ||||
|     case CLRSPC_SYCC: | ||||
|     case OPJ(CLRSPC_SYCC): | ||||
|         possible_fmts    = libopenjpeg_yuv_pix_fmts; | ||||
|         possible_fmts_nb = FF_ARRAY_ELEMS(libopenjpeg_yuv_pix_fmts); | ||||
|         break; | ||||
| @ -275,13 +345,19 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, | ||||
|     ThreadFrame frame       = { .f = data }; | ||||
|     AVFrame *picture        = data; | ||||
|     const AVPixFmtDescriptor *desc; | ||||
|     opj_dinfo_t *dec; | ||||
|     opj_cio_t *stream; | ||||
|     opj_image_t *image; | ||||
|     int width, height, ret; | ||||
|     int pixel_size = 0; | ||||
|     int ispacked   = 0; | ||||
|     int i; | ||||
|     opj_image_t *image = NULL; | ||||
| #if OPENJPEG_MAJOR_VERSION == 1 | ||||
|     opj_dinfo_t *dec = NULL; | ||||
|     opj_cio_t *stream = NULL; | ||||
| #else // OPENJPEG_MAJOR_VERSION == 2
 | ||||
|     BufferReader reader = {0, avpkt->size, avpkt->data}; | ||||
|     opj_codec_t *dec = NULL; | ||||
|     opj_stream_t *stream = NULL; | ||||
| #endif // OPENJPEG_MAJOR_VERSION == 1
 | ||||
| 
 | ||||
|     *got_frame = 0; | ||||
| 
 | ||||
| @ -289,19 +365,22 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, | ||||
|     if ((AV_RB32(buf) == 12) && | ||||
|         (AV_RB32(buf + 4) == JP2_SIG_TYPE) && | ||||
|         (AV_RB32(buf + 8) == JP2_SIG_VALUE)) { | ||||
|         dec = opj_create_decompress(CODEC_JP2); | ||||
|         dec = opj_create_decompress(OPJ(CODEC_JP2)); | ||||
|     } else { | ||||
|         /* If the AVPacket contains a jp2c box, then skip to
 | ||||
|          * the starting byte of the codestream. */ | ||||
|         if (AV_RB32(buf + 4) == AV_RB32("jp2c")) | ||||
|             buf += 8; | ||||
|         dec = opj_create_decompress(CODEC_J2K); | ||||
|         dec = opj_create_decompress(OPJ(CODEC_J2K)); | ||||
|     } | ||||
| 
 | ||||
|     if (!dec) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "Error initializing decoder.\n"); | ||||
|         return AVERROR_UNKNOWN; | ||||
|         ret = AVERROR_EXTERNAL; | ||||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
| #if OPENJPEG_MAJOR_VERSION == 1 | ||||
|     memset(&ctx->event_mgr, 0, sizeof(ctx->event_mgr)); | ||||
|     ctx->event_mgr.info_handler    = info_callback; | ||||
|     ctx->event_mgr.error_handler   = error_callback; | ||||
| @ -309,25 +388,61 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, | ||||
|     opj_set_event_mgr((opj_common_ptr) dec, &ctx->event_mgr, avctx); | ||||
|     ctx->dec_params.cp_limit_decoding = LIMIT_TO_MAIN_HEADER; | ||||
|     ctx->dec_params.cp_layer          = ctx->lowqual; | ||||
| #else // OPENJPEG_MAJOR_VERSION == 2
 | ||||
|     if (!opj_set_error_handler(dec, error_callback, avctx) || | ||||
|         !opj_set_warning_handler(dec, warning_callback, avctx) || | ||||
|         !opj_set_info_handler(dec, info_callback, avctx)) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "Error setting decoder handlers.\n"); | ||||
|         ret = AVERROR_EXTERNAL; | ||||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
|     ctx->dec_params.cp_layer = ctx->lowqual; | ||||
|     ctx->dec_params.cp_reduce = avctx->lowres; | ||||
| #endif // OPENJPEG_MAJOR_VERSION == 1
 | ||||
| 
 | ||||
|     // Tie decoder with decoding parameters
 | ||||
|     opj_setup_decoder(dec, &ctx->dec_params); | ||||
| 
 | ||||
| #if OPENJPEG_MAJOR_VERSION == 1 | ||||
|     stream = opj_cio_open((opj_common_ptr) dec, buf, buf_size); | ||||
| #else // OPENJPEG_MAJOR_VERSION == 2
 | ||||
|     stream = opj_stream_default_create(OPJ_STREAM_READ); | ||||
| #endif // OPENJPEG_MAJOR_VERSION == 1
 | ||||
| 
 | ||||
|     if (!stream) { | ||||
|         av_log(avctx, AV_LOG_ERROR, | ||||
|                "Codestream could not be opened for reading.\n"); | ||||
|         opj_destroy_decompress(dec); | ||||
|         return AVERROR_UNKNOWN; | ||||
|         ret = AVERROR_EXTERNAL; | ||||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
| #if OPENJPEG_MAJOR_VERSION == 1 | ||||
|     // Decode the header only.
 | ||||
|     image = opj_decode_with_info(dec, stream, NULL); | ||||
|     opj_cio_close(stream); | ||||
|     stream = NULL; | ||||
|     ret = !image; | ||||
| #else // OPENJPEG_MAJOR_VERSION == 2
 | ||||
|     opj_stream_set_read_function(stream, stream_read); | ||||
|     opj_stream_set_skip_function(stream, stream_skip); | ||||
|     opj_stream_set_seek_function(stream, stream_seek); | ||||
| #if HAVE_OPENJPEG_2_1_OPENJPEG_H | ||||
|     opj_stream_set_user_data(stream, &reader, NULL); | ||||
| #elif HAVE_OPENJPEG_2_0_OPENJPEG_H | ||||
|     opj_stream_set_user_data(stream, &reader); | ||||
| #else | ||||
| #error Missing call to opj_stream_set_user_data | ||||
| #endif | ||||
|     opj_stream_set_user_data_length(stream, avpkt->size); | ||||
|     // Decode the header only.
 | ||||
|     ret = !opj_read_header(stream, dec, &image); | ||||
| #endif // OPENJPEG_MAJOR_VERSION == 1
 | ||||
| 
 | ||||
|     if (!image) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "Error decoding codestream.\n"); | ||||
|         opj_destroy_decompress(dec); | ||||
|         return AVERROR_UNKNOWN; | ||||
|     if (ret) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "Error decoding codestream header.\n"); | ||||
|         ret = AVERROR_EXTERNAL; | ||||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
|     width  = image->x1 - image->x0; | ||||
| @ -345,7 +460,8 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, | ||||
|         avctx->pix_fmt = libopenjpeg_guess_pix_fmt(image); | ||||
| 
 | ||||
|     if (avctx->pix_fmt == AV_PIX_FMT_NONE) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "Unable to determine pixel format\n"); | ||||
|         av_log(avctx, AV_LOG_ERROR, "Unable to determine pixel format.\n"); | ||||
|         ret = AVERROR_UNKNOWN; | ||||
|         goto done; | ||||
|     } | ||||
|     for (i = 0; i < image->numcomps; i++) | ||||
| @ -355,6 +471,7 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, | ||||
|     if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) | ||||
|         goto done; | ||||
| 
 | ||||
| #if OPENJPEG_MAJOR_VERSION == 1 | ||||
|     ctx->dec_params.cp_limit_decoding = NO_LIMITATION; | ||||
|     ctx->dec_params.cp_reduce = avctx->lowres; | ||||
|     // Tie decoder with decoding parameters.
 | ||||
| @ -363,18 +480,20 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, | ||||
|     if (!stream) { | ||||
|         av_log(avctx, AV_LOG_ERROR, | ||||
|                "Codestream could not be opened for reading.\n"); | ||||
|         ret = AVERROR_UNKNOWN; | ||||
|         ret = AVERROR_EXTERNAL; | ||||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
|     opj_image_destroy(image); | ||||
|     // Decode the codestream
 | ||||
|     image = opj_decode_with_info(dec, stream, NULL); | ||||
|     opj_cio_close(stream); | ||||
|     ret = !image; | ||||
| #else // OPENJPEG_MAJOR_VERSION == 2
 | ||||
|     ret = !opj_decode(dec, stream, image); | ||||
| #endif // OPENJPEG_MAJOR_VERSION == 1
 | ||||
| 
 | ||||
|     if (!image) { | ||||
|     if (ret) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "Error decoding codestream.\n"); | ||||
|         ret = AVERROR_UNKNOWN; | ||||
|         ret = AVERROR_EXTERNAL; | ||||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
| @ -429,7 +548,13 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, | ||||
| 
 | ||||
| done: | ||||
|     opj_image_destroy(image); | ||||
| #if OPENJPEG_MAJOR_VERSION == 2 | ||||
|     opj_stream_destroy(stream); | ||||
|     opj_destroy_codec(dec); | ||||
| #else | ||||
|     opj_cio_close(stream); | ||||
|     opj_destroy_decompress(dec); | ||||
| #endif | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -34,17 +34,31 @@ | ||||
| #include "avcodec.h" | ||||
| #include "internal.h" | ||||
| 
 | ||||
| #if HAVE_OPENJPEG_1_5_OPENJPEG_H | ||||
| # include <openjpeg-1.5/openjpeg.h> | ||||
| #if HAVE_OPENJPEG_2_1_OPENJPEG_H | ||||
| #  include <openjpeg-2.1/openjpeg.h> | ||||
| #elif HAVE_OPENJPEG_2_0_OPENJPEG_H | ||||
| #  include <openjpeg-2.0/openjpeg.h> | ||||
| #elif HAVE_OPENJPEG_1_5_OPENJPEG_H | ||||
| #  include <openjpeg-1.5/openjpeg.h> | ||||
| #else | ||||
| # include <openjpeg.h> | ||||
| #  include <openjpeg.h> | ||||
| #endif | ||||
| 
 | ||||
| #if HAVE_OPENJPEG_2_1_OPENJPEG_H || HAVE_OPENJPEG_2_0_OPENJPEG_H | ||||
| #  define OPENJPEG_MAJOR_VERSION 2 | ||||
| #  define OPJ(x) OPJ_##x | ||||
| #else | ||||
| #  define OPENJPEG_MAJOR_VERSION 1 | ||||
| #  define OPJ(x) x | ||||
| #endif | ||||
| 
 | ||||
| typedef struct LibOpenJPEGContext { | ||||
|     AVClass *avclass; | ||||
|     opj_image_t *image; | ||||
|     opj_cparameters_t enc_params; | ||||
| #if OPENJPEG_MAJOR_VERSION == 1 | ||||
|     opj_event_mgr_t event_mgr; | ||||
| #endif // OPENJPEG_MAJOR_VERSION == 1
 | ||||
|     int format; | ||||
|     int profile; | ||||
|     int prog_order; | ||||
| @ -71,6 +85,78 @@ static void info_callback(const char *msg, void *data) | ||||
|     av_log(data, AV_LOG_DEBUG, "%s\n", msg); | ||||
| } | ||||
| 
 | ||||
| #if OPENJPEG_MAJOR_VERSION == 2 | ||||
| typedef struct PacketWriter { | ||||
|     int pos; | ||||
|     AVPacket *packet; | ||||
| } PacketWriter; | ||||
| 
 | ||||
| static OPJ_SIZE_T stream_write(void *out_buffer, OPJ_SIZE_T nb_bytes, void *user_data) | ||||
| { | ||||
|     PacketWriter *writer = user_data; | ||||
|     AVPacket *packet = writer->packet; | ||||
|     int remaining = packet->size - writer->pos; | ||||
|     if (nb_bytes > remaining) { | ||||
|         OPJ_SIZE_T needed = nb_bytes - remaining; | ||||
|         int max_growth = INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE - packet->size; | ||||
|         if (needed > max_growth) { | ||||
|             return (OPJ_SIZE_T)-1; | ||||
|         } | ||||
|         if (av_grow_packet(packet, (int)needed)) { | ||||
|             return (OPJ_SIZE_T)-1; | ||||
|         } | ||||
|     } | ||||
|     memcpy(packet->data + writer->pos, out_buffer, nb_bytes); | ||||
|     writer->pos += (int)nb_bytes; | ||||
|     return nb_bytes; | ||||
| } | ||||
| 
 | ||||
| static OPJ_OFF_T stream_skip(OPJ_OFF_T nb_bytes, void *user_data) | ||||
| { | ||||
|     PacketWriter *writer = user_data; | ||||
|     AVPacket *packet = writer->packet; | ||||
|     if (nb_bytes < 0) { | ||||
|         if (writer->pos == 0) { | ||||
|             return (OPJ_SIZE_T)-1; | ||||
|         } | ||||
|         if (nb_bytes + writer->pos < 0) { | ||||
|             nb_bytes = -writer->pos; | ||||
|         } | ||||
|     } else { | ||||
|         int remaining = packet->size - writer->pos; | ||||
|         if (nb_bytes > remaining) { | ||||
|             OPJ_SIZE_T needed = nb_bytes - remaining; | ||||
|             int max_growth = INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE - packet->size; | ||||
|             if (needed > max_growth) { | ||||
|                 return (OPJ_SIZE_T)-1; | ||||
|             } | ||||
|             if (av_grow_packet(packet, (int)needed)) { | ||||
|                 return (OPJ_SIZE_T)-1; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     writer->pos += (int)nb_bytes; | ||||
|     return nb_bytes; | ||||
| } | ||||
| 
 | ||||
| static OPJ_BOOL stream_seek(OPJ_OFF_T nb_bytes, void *user_data) | ||||
| { | ||||
|     PacketWriter *writer = user_data; | ||||
|     AVPacket *packet = writer->packet; | ||||
|     if (nb_bytes < 0) { | ||||
|         return OPJ_FALSE; | ||||
|     } | ||||
|     if (nb_bytes > packet->size) { | ||||
|         if (nb_bytes > INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE || | ||||
|             av_grow_packet(packet, (int)nb_bytes - packet->size)) { | ||||
|             return OPJ_FALSE; | ||||
|         } | ||||
|     } | ||||
|     writer->pos = (int)nb_bytes; | ||||
|     return OPJ_TRUE; | ||||
| } | ||||
| #endif // OPENJPEG_MAJOR_VERSION == 2
 | ||||
| 
 | ||||
| static void cinema_parameters(opj_cparameters_t *p) | ||||
| { | ||||
|     p->tile_size_on = 0; | ||||
| @ -93,7 +179,7 @@ static void cinema_parameters(opj_cparameters_t *p) | ||||
|     p->csty |= 0x01; | ||||
| 
 | ||||
|     /* The progression order shall be CPRL */ | ||||
|     p->prog_order = CPRL; | ||||
|     p->prog_order = OPJ(CPRL); | ||||
| 
 | ||||
|     /* No ROI */ | ||||
|     p->roi_compno = -1; | ||||
| @ -117,7 +203,7 @@ static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *p | ||||
|     int sub_dx[4]; | ||||
|     int sub_dy[4]; | ||||
|     int numcomps; | ||||
|     OPJ_COLOR_SPACE color_space = CLRSPC_UNKNOWN; | ||||
|     OPJ_COLOR_SPACE color_space = OPJ(CLRSPC_UNKNOWN); | ||||
| 
 | ||||
|     sub_dx[0] = sub_dx[3] = 1; | ||||
|     sub_dy[0] = sub_dy[3] = 1; | ||||
| @ -131,7 +217,7 @@ static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *p | ||||
|     case AV_PIX_FMT_YA8: | ||||
|     case AV_PIX_FMT_GRAY16: | ||||
|     case AV_PIX_FMT_YA16: | ||||
|         color_space = CLRSPC_GRAY; | ||||
|         color_space = OPJ(CLRSPC_GRAY); | ||||
|         break; | ||||
|     case AV_PIX_FMT_RGB24: | ||||
|     case AV_PIX_FMT_RGBA: | ||||
| @ -144,7 +230,7 @@ static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *p | ||||
|     case AV_PIX_FMT_GBRP14: | ||||
|     case AV_PIX_FMT_GBRP16: | ||||
|     case AV_PIX_FMT_XYZ12: | ||||
|         color_space = CLRSPC_SRGB; | ||||
|         color_space = OPJ(CLRSPC_SRGB); | ||||
|         break; | ||||
|     case AV_PIX_FMT_YUV410P: | ||||
|     case AV_PIX_FMT_YUV411P: | ||||
| @ -179,7 +265,7 @@ static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *p | ||||
|     case AV_PIX_FMT_YUVA420P16: | ||||
|     case AV_PIX_FMT_YUVA422P16: | ||||
|     case AV_PIX_FMT_YUVA444P16: | ||||
|         color_space = CLRSPC_SYCC; | ||||
|         color_space = OPJ(CLRSPC_SYCC); | ||||
|         break; | ||||
|     default: | ||||
|         av_log(avctx, AV_LOG_ERROR, | ||||
| @ -216,13 +302,57 @@ static opj_image_t *mj2_create_image(AVCodecContext *avctx, opj_cparameters_t *p | ||||
| static av_cold int libopenjpeg_encode_init(AVCodecContext *avctx) | ||||
| { | ||||
|     LibOpenJPEGContext *ctx = avctx->priv_data; | ||||
|     int err = AVERROR(ENOMEM); | ||||
|     int err = 0; | ||||
| 
 | ||||
|     opj_set_default_encoder_parameters(&ctx->enc_params); | ||||
| 
 | ||||
| #if HAVE_OPENJPEG_2_1_OPENJPEG_H | ||||
|     switch (ctx->cinema_mode) { | ||||
|     case OPJ_CINEMA2K_24: | ||||
|         ctx->enc_params.rsiz = OPJ_PROFILE_CINEMA_2K; | ||||
|         ctx->enc_params.max_cs_size = OPJ_CINEMA_24_CS; | ||||
|         ctx->enc_params.max_comp_size = OPJ_CINEMA_24_COMP; | ||||
|         break; | ||||
|     case OPJ_CINEMA2K_48: | ||||
|         ctx->enc_params.rsiz = OPJ_PROFILE_CINEMA_2K; | ||||
|         ctx->enc_params.max_cs_size = OPJ_CINEMA_48_CS; | ||||
|         ctx->enc_params.max_comp_size = OPJ_CINEMA_48_COMP; | ||||
|         break; | ||||
|     case OPJ_CINEMA4K_24: | ||||
|         ctx->enc_params.rsiz = OPJ_PROFILE_CINEMA_4K; | ||||
|         ctx->enc_params.max_cs_size = OPJ_CINEMA_24_CS; | ||||
|         ctx->enc_params.max_comp_size = OPJ_CINEMA_24_COMP; | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     switch (ctx->profile) { | ||||
|     case OPJ_CINEMA2K: | ||||
|         if (ctx->enc_params.rsiz == OPJ_PROFILE_CINEMA_4K) { | ||||
|             err = AVERROR(EINVAL); | ||||
|             break; | ||||
|         } | ||||
|         ctx->enc_params.rsiz = OPJ_PROFILE_CINEMA_2K; | ||||
|         break; | ||||
|     case OPJ_CINEMA4K: | ||||
|         if (ctx->enc_params.rsiz == OPJ_PROFILE_CINEMA_2K) { | ||||
|             err = AVERROR(EINVAL); | ||||
|             break; | ||||
|         } | ||||
|         ctx->enc_params.rsiz = OPJ_PROFILE_CINEMA_4K; | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     if (err) { | ||||
|         av_log(avctx, AV_LOG_ERROR, | ||||
|                "Invalid parameter pairing: cinema_mode and profile conflict.\n"); | ||||
|         goto fail; | ||||
|     } | ||||
| #else | ||||
|     ctx->enc_params.cp_rsiz = ctx->profile; | ||||
|     ctx->enc_params.mode = !!avctx->global_quality; | ||||
|     ctx->enc_params.cp_cinema = ctx->cinema_mode; | ||||
| #endif | ||||
| 
 | ||||
|     ctx->enc_params.mode = !!avctx->global_quality; | ||||
|     ctx->enc_params.prog_order = ctx->prog_order; | ||||
|     ctx->enc_params.numresolution = ctx->numresolution; | ||||
|     ctx->enc_params.cp_disto_alloc = ctx->disto_alloc; | ||||
| @ -458,10 +588,16 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, | ||||
| { | ||||
|     LibOpenJPEGContext *ctx = avctx->priv_data; | ||||
|     opj_image_t *image      = ctx->image; | ||||
| #if OPENJPEG_MAJOR_VERSION == 1 | ||||
|     opj_cinfo_t *compress   = NULL; | ||||
|     opj_cio_t *stream       = NULL; | ||||
|     int len; | ||||
| #else // OPENJPEG_MAJOR_VERSION == 2
 | ||||
|     opj_codec_t *compress   = NULL; | ||||
|     opj_stream_t *stream    = NULL; | ||||
| #endif // OPENJPEG_MAJOR_VERSION == 1
 | ||||
|     int cpyresult = 0; | ||||
|     int ret, len; | ||||
|     int ret; | ||||
|     AVFrame *gbrframe; | ||||
| 
 | ||||
|     switch (avctx->pix_fmt) { | ||||
| @ -553,46 +689,99 @@ static int libopenjpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
| #if OPENJPEG_MAJOR_VERSION == 2 | ||||
|     if ((ret = ff_alloc_packet2(avctx, pkt, 1024, 0)) < 0) { | ||||
|         return ret; | ||||
|     } | ||||
| #endif // OPENJPEG_MAJOR_VERSION == 2
 | ||||
| 
 | ||||
|     compress = opj_create_compress(ctx->format); | ||||
|     if (!compress) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "Error creating the compressor\n"); | ||||
|         return AVERROR(ENOMEM); | ||||
|         ret = AVERROR(ENOMEM); | ||||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
| #if OPENJPEG_MAJOR_VERSION == 1 | ||||
|     opj_setup_encoder(compress, &ctx->enc_params, image); | ||||
| 
 | ||||
|     stream = opj_cio_open((opj_common_ptr) compress, NULL, 0); | ||||
| #else // OPENJPEG_MAJOR_VERSION == 2
 | ||||
|     if (!opj_set_error_handler(compress, error_callback, avctx) || | ||||
|         !opj_set_warning_handler(compress, warning_callback, avctx) || | ||||
|         !opj_set_info_handler(compress, info_callback, avctx)) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "Error setting the compressor handlers\n"); | ||||
|         ret = AVERROR_EXTERNAL; | ||||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
|     if (!opj_setup_encoder(compress, &ctx->enc_params, image)) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "Error setting up the compressor\n"); | ||||
|         ret = AVERROR_EXTERNAL; | ||||
|         goto done; | ||||
|     } | ||||
|     stream = opj_stream_default_create(OPJ_STREAM_WRITE); | ||||
| #endif // OPENJPEG_MAJOR_VERSION == 1
 | ||||
| 
 | ||||
|     if (!stream) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "Error creating the cio stream\n"); | ||||
|         return AVERROR(ENOMEM); | ||||
|         ret = AVERROR(ENOMEM); | ||||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
| #if OPENJPEG_MAJOR_VERSION == 1 | ||||
|     memset(&ctx->event_mgr, 0, sizeof(ctx->event_mgr)); | ||||
|     ctx->event_mgr.info_handler    = info_callback; | ||||
|     ctx->event_mgr.error_handler   = error_callback; | ||||
|     ctx->event_mgr.warning_handler = warning_callback; | ||||
|     opj_set_event_mgr((opj_common_ptr) compress, &ctx->event_mgr, avctx); | ||||
| 
 | ||||
|     if (!opj_encode(compress, stream, image, NULL)) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "Error during the opj encode\n"); | ||||
|         return -1; | ||||
|         ret = AVERROR_EXTERNAL; | ||||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
|     len = cio_tell(stream); | ||||
|     if ((ret = ff_alloc_packet2(avctx, pkt, len, 0)) < 0) { | ||||
|         return ret; | ||||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
|     memcpy(pkt->data, stream->buffer, len); | ||||
| #else // OPENJPEG_MAJOR_VERSION == 2
 | ||||
|     PacketWriter writer = {0, pkt}; | ||||
|     opj_stream_set_write_function(stream, stream_write); | ||||
|     opj_stream_set_skip_function(stream, stream_skip); | ||||
|     opj_stream_set_seek_function(stream, stream_seek); | ||||
| #if HAVE_OPENJPEG_2_1_OPENJPEG_H | ||||
|     opj_stream_set_user_data(stream, &writer, NULL); | ||||
| #elif HAVE_OPENJPEG_2_0_OPENJPEG_H | ||||
|     opj_stream_set_user_data(stream, &writer); | ||||
| #else | ||||
| #error Missing call to opj_stream_set_user_data | ||||
| #endif | ||||
| 
 | ||||
|     if (!opj_start_compress(compress, ctx->image, stream) || | ||||
|         !opj_encode(compress, stream) || | ||||
|         !opj_end_compress(compress, stream)) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "Error during the opj encode\n"); | ||||
|         ret = AVERROR_EXTERNAL; | ||||
|         goto done; | ||||
|     } | ||||
| 
 | ||||
|     av_shrink_packet(pkt, writer.pos); | ||||
| #endif // OPENJPEG_MAJOR_VERSION == 1
 | ||||
| 
 | ||||
|     pkt->flags |= AV_PKT_FLAG_KEY; | ||||
|     *got_packet = 1; | ||||
|     ret = 0; | ||||
| 
 | ||||
| done: | ||||
| #if OPENJPEG_MAJOR_VERSION == 2 | ||||
|     opj_stream_destroy(stream); | ||||
|     opj_destroy_codec(compress); | ||||
| #else | ||||
|     opj_cio_close(stream); | ||||
|     stream = NULL; | ||||
|     opj_destroy_compress(compress); | ||||
|     compress = NULL; | ||||
| 
 | ||||
|     return 0; | ||||
| #endif | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static av_cold int libopenjpeg_encode_close(AVCodecContext *avctx) | ||||
| @ -607,24 +796,24 @@ static av_cold int libopenjpeg_encode_close(AVCodecContext *avctx) | ||||
| #define OFFSET(x) offsetof(LibOpenJPEGContext, x) | ||||
| #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM | ||||
| static const AVOption options[] = { | ||||
|     { "format",        "Codec Format",      OFFSET(format),        AV_OPT_TYPE_INT,   { .i64 = CODEC_JP2   }, CODEC_J2K, CODEC_JP2,   VE, "format"      }, | ||||
|     { "j2k",           NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = CODEC_J2K   }, 0,         0,           VE, "format"      }, | ||||
|     { "jp2",           NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = CODEC_JP2   }, 0,         0,           VE, "format"      }, | ||||
|     { "profile",       NULL,                OFFSET(profile),       AV_OPT_TYPE_INT,   { .i64 = STD_RSIZ    }, STD_RSIZ,  CINEMA4K,    VE, "profile"     }, | ||||
|     { "jpeg2000",      NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = STD_RSIZ    }, 0,         0,           VE, "profile"     }, | ||||
|     { "cinema2k",      NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = CINEMA2K    }, 0,         0,           VE, "profile"     }, | ||||
|     { "cinema4k",      NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = CINEMA4K    }, 0,         0,           VE, "profile"     }, | ||||
|     { "cinema_mode",   "Digital Cinema",    OFFSET(cinema_mode),   AV_OPT_TYPE_INT,   { .i64 = OFF         }, OFF,       CINEMA4K_24, VE, "cinema_mode" }, | ||||
|     { "off",           NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OFF         }, 0,         0,           VE, "cinema_mode" }, | ||||
|     { "2k_24",         NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = CINEMA2K_24 }, 0,         0,           VE, "cinema_mode" }, | ||||
|     { "2k_48",         NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = CINEMA2K_48 }, 0,         0,           VE, "cinema_mode" }, | ||||
|     { "4k_24",         NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = CINEMA4K_24 }, 0,         0,           VE, "cinema_mode" }, | ||||
|     { "prog_order",    "Progression Order", OFFSET(prog_order),    AV_OPT_TYPE_INT,   { .i64 = LRCP        }, LRCP,      CPRL,        VE, "prog_order"  }, | ||||
|     { "lrcp",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = LRCP        }, 0,         0,           VE, "prog_order"  }, | ||||
|     { "rlcp",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = RLCP        }, 0,         0,           VE, "prog_order"  }, | ||||
|     { "rpcl",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = RPCL        }, 0,         0,           VE, "prog_order"  }, | ||||
|     { "pcrl",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = PCRL        }, 0,         0,           VE, "prog_order"  }, | ||||
|     { "cprl",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = CPRL        }, 0,         0,           VE, "prog_order"  }, | ||||
|     { "format",        "Codec Format",      OFFSET(format),        AV_OPT_TYPE_INT,   { .i64 = OPJ(CODEC_JP2)   }, OPJ(CODEC_J2K), OPJ(CODEC_JP2),   VE, "format"      }, | ||||
|     { "j2k",           NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(CODEC_J2K)   }, 0,         0,           VE, "format"      }, | ||||
|     { "jp2",           NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(CODEC_JP2)   }, 0,         0,           VE, "format"      }, | ||||
|     { "profile",       NULL,                OFFSET(profile),       AV_OPT_TYPE_INT,   { .i64 = OPJ(STD_RSIZ)    }, OPJ(STD_RSIZ),  OPJ(CINEMA4K),    VE, "profile"     }, | ||||
|     { "jpeg2000",      NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(STD_RSIZ)    }, 0,         0,           VE, "profile"     }, | ||||
|     { "cinema2k",      NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(CINEMA2K)    }, 0,         0,           VE, "profile"     }, | ||||
|     { "cinema4k",      NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(CINEMA4K)    }, 0,         0,           VE, "profile"     }, | ||||
|     { "cinema_mode",   "Digital Cinema",    OFFSET(cinema_mode),   AV_OPT_TYPE_INT,   { .i64 = OPJ(OFF)         }, OPJ(OFF),       OPJ(CINEMA4K_24), VE, "cinema_mode" }, | ||||
|     { "off",           NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(OFF)         }, 0,         0,           VE, "cinema_mode" }, | ||||
|     { "2k_24",         NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(CINEMA2K_24) }, 0,         0,           VE, "cinema_mode" }, | ||||
|     { "2k_48",         NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(CINEMA2K_48) }, 0,         0,           VE, "cinema_mode" }, | ||||
|     { "4k_24",         NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(CINEMA4K_24) }, 0,         0,           VE, "cinema_mode" }, | ||||
|     { "prog_order",    "Progression Order", OFFSET(prog_order),    AV_OPT_TYPE_INT,   { .i64 = OPJ(LRCP)    }, OPJ(LRCP),  OPJ(CPRL),    VE, "prog_order"  }, | ||||
|     { "lrcp",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(LRCP)    }, 0,         0,           VE, "prog_order"  }, | ||||
|     { "rlcp",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(RLCP)    }, 0,         0,           VE, "prog_order"  }, | ||||
|     { "rpcl",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(RPCL)    }, 0,         0,           VE, "prog_order"  }, | ||||
|     { "pcrl",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(PCRL)    }, 0,         0,           VE, "prog_order"  }, | ||||
|     { "cprl",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = OPJ(CPRL)    }, 0,         0,           VE, "prog_order"  }, | ||||
|     { "numresolution", NULL,                OFFSET(numresolution), AV_OPT_TYPE_INT,   { .i64 = 6           }, 1,         INT_MAX,     VE                }, | ||||
|     { "numlayers",     NULL,                OFFSET(numlayers),     AV_OPT_TYPE_INT,   { .i64 = 1           }, 1,         10,          VE                }, | ||||
|     { "disto_alloc",   NULL,                OFFSET(disto_alloc),   AV_OPT_TYPE_INT,   { .i64 = 1           }, 0,         1,           VE                }, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user