OpenJPEG can decode in lower resolution or decode only a number of enhancement layers.
Unified · Split
| @@ -24,6 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | * JPEG 2000 decoder using libopenjpeg |
| 25 | 25 | */ |
| 26 | 26 | |
| 27 | +#include "libavutil/opt.h" | |
| 27 | 28 | #include "libavutil/imgutils.h" |
| 28 | 29 | #include "avcodec.h" |
| 29 | 30 | #include "libavutil/intreadwrite.h" |
| @@ -35,8 +36,11 @@ · 5 unmodified lines | ||
| 35 | 36 | #define JP2_SIG_VALUE 0x0D0A870A |
| 36 | 37 | |
| 37 | 38 | typedef struct { |
| 39 | + AVClass *class; | |
| 38 | 40 | opj_dparameters_t dec_params; |
| 39 | 41 | AVFrame image; |
| 42 | + int lowres; | |
| 43 | + int lowqual; | |
| 40 | 44 | } LibOpenJPEGContext; |
| 41 | 45 | |
| 42 | 46 | static int check_image_attributes(opj_image_t *image) |
| @@ -104,6 +108,8 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, · 61 unmodified lines | ||
| 104 | 108 | opj_set_event_mgr((opj_common_ptr)dec, NULL, NULL); |
| 105 | 109 | |
| 106 | 110 | ctx->dec_params.cp_limit_decoding = LIMIT_TO_MAIN_HEADER; |
| 111 | + ctx->dec_params.cp_reduce = ctx->lowres; | |
| 112 | + ctx->dec_params.cp_layer = ctx->lowqual; | |
| 107 | 113 | // Tie decoder with decoding parameters |
| 108 | 114 | opj_setup_decoder(dec, &ctx->dec_params); |
| 109 | 115 | stream = opj_cio_open((opj_common_ptr)dec, buf, buf_size); |
| @@ -123,6 +129,12 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx, · 13 unmodified lines | ||
| 123 | 129 | } |
| 124 | 130 | width = image->x1 - image->x0; |
| 125 | 131 | height = image->y1 - image->y0; |
| 132 | + | |
| 133 | + if (ctx->lowres) { | |
| 134 | + width = (width + (1 << ctx->lowres) - 1) >> ctx->lowres; | |
| 135 | + height = (height + (1 << ctx->lowres) - 1) >> ctx->lowres; | |
| 136 | + } | |
| 137 | + | |
| 126 | 138 | if(av_image_check_size(width, height, 0, avctx) < 0) { |
| 127 | 139 | av_log(avctx, AV_LOG_ERROR, "%dx%d dimension invalid.\n", width, height); |
| 128 | 140 | goto done; |
| @@ -208,6 +220,21 @@ static av_cold int libopenjpeg_decode_close(AVCodecContext *avctx) · 79 unmodified lines | ||
| 208 | 220 | return 0 ; |
| 209 | 221 | } |
| 210 | 222 | |
| 223 | +#define OFFSET(x) offsetof(LibOpenJPEGContext, x) | |
| 224 | +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM | |
| 225 | + | |
| 226 | +static const AVOption options[] = { | |
| 227 | + { "lowqual", "Limit the number of layers used for decoding", OFFSET(lowqual), AV_OPT_TYPE_INT, { 0 }, 0, INT_MAX, VD }, | |
| 228 | + { "lowres", "Lower the decoding resolution by a power of two", OFFSET(lowres), AV_OPT_TYPE_INT, { 0 }, 0, INT_MAX, VD }, | |
| 229 | + { NULL }, | |
| 230 | +}; | |
| 231 | + | |
| 232 | +static const AVClass class = { | |
| 233 | + .class_name = "libopenjpeg", | |
| 234 | + .item_name = av_default_item_name, | |
| 235 | + .option = options, | |
| 236 | + .version = LIBAVUTIL_VERSION_INT, | |
| 237 | +}; | |
| 211 | 238 | |
| 212 | 239 | AVCodec ff_libopenjpeg_decoder = { |
| 213 | 240 | .name = "libopenjpeg", |
| @@ -219,5 +246,6 @@ AVCodec ff_libopenjpeg_decoder = { · 5 unmodified lines | ||
| 219 | 246 | .decode = libopenjpeg_decode_frame, |
| 220 | 247 | .capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, |
| 221 | 248 | .long_name = NULL_IF_CONFIG_SMALL("OpenJPEG based JPEG 2000 decoder"), |
| 249 | + .priv_class = &class, | |
| 222 | 250 | .init_thread_copy = ONLY_IF_THREADS_ENABLED(libopenjpeg_decode_init_thread_copy), |
| 223 | 251 | }; |