[FFmpeg-devel] [PATCH 1/7] lavc/libopenjpegdec: support interlaced layout
Matthieu Bouron
matthieu.bouron at gmail.com
Thu Mar 28 15:41:45 CET 2013
Fixes tickets #1102.
Interlaced layout is supported thought use of codec extradata:
avctx->extradata[0] enables interlaced layout,
avctx->extradata[1] stores field order.
---
libavcodec/libopenjpegdec.c | 99 ++++++++++++++++++++++++++++++++++++---------
1 file changed, 80 insertions(+), 19 deletions(-)
diff --git a/libavcodec/libopenjpegdec.c b/libavcodec/libopenjpegdec.c
index f8b6165..4ea0489 100644
--- a/libavcodec/libopenjpegdec.c
+++ b/libavcodec/libopenjpegdec.c
@@ -68,6 +68,12 @@ typedef struct {
AVClass *class;
opj_dparameters_t dec_params;
int lowqual;
+ AVFrame* picture;
+ uint64_t curpict;
+ int separate_fields;
+ int field_order;
+ int top_field_coded_first;
+ int width, height;
} LibOpenJPEGContext;
static inline int libopenjpeg_matches_pix_fmt(const opj_image_t *image, enum AVPixelFormat pix_fmt)
@@ -148,12 +154,13 @@ static inline int libopenjpeg_ispacked(enum AVPixelFormat pix_fmt)
return 1;
}
-static inline void libopenjpeg_copy_to_packed8(AVFrame *picture, opj_image_t *image) {
+static inline void libopenjpeg_copy_to_packed8(AVFrame *picture, opj_image_t *image, int separate_fields, int field_pos) {
uint8_t *img_ptr;
- int index, x, y, c;
+ int index, x, y, c, line;
for (y = 0; y < picture->height; y++) {
index = y*picture->width;
- img_ptr = picture->data[0] + y*picture->linesize[0];
+ line = separate_fields * (field_pos + y) + y;
+ img_ptr = picture->data[0] + line*picture->linesize[0];
for (x = 0; x < picture->width; x++, index++) {
for (c = 0; c < image->numcomps; c++) {
*img_ptr++ = image->comps[c].data[index];
@@ -162,16 +169,17 @@ static inline void libopenjpeg_copy_to_packed8(AVFrame *picture, opj_image_t *im
}
}
-static inline void libopenjpeg_copy_to_packed16(AVFrame *picture, opj_image_t *image) {
+static inline void libopenjpeg_copy_to_packed16(AVFrame *picture, opj_image_t *image, int separate_fields, int field_pos) {
uint16_t *img_ptr;
- int index, x, y, c;
+ int index, x, y, c, line;
int adjust[4];
for (x = 0; x < image->numcomps; x++)
adjust[x] = FFMAX(FFMIN(16 - image->comps[x].prec, 8), 0);
for (y = 0; y < picture->height; y++) {
index = y*picture->width;
- img_ptr = (uint16_t*) (picture->data[0] + y*picture->linesize[0]);
+ line = separate_fields * (field_pos + y) + y;
+ img_ptr = (uint16_t*) (picture->data[0] + line*picture->linesize[0]);
for (x = 0; x < picture->width; x++, index++) {
for (c = 0; c < image->numcomps; c++) {
*img_ptr++ = image->comps[c].data[index] << adjust[c];
@@ -180,7 +188,7 @@ static inline void libopenjpeg_copy_to_packed16(AVFrame *picture, opj_image_t *i
}
}
-static inline void libopenjpeg_copyto8(AVFrame *picture, opj_image_t *image) {
+static inline void libopenjpeg_copyto8(AVFrame *picture, opj_image_t *image, int separate_fields, int field_pos) {
int *comp_data;
uint8_t *img_ptr;
int index, x, y;
@@ -188,7 +196,8 @@ static inline void libopenjpeg_copyto8(AVFrame *picture, opj_image_t *image) {
for (index = 0; index < image->numcomps; index++) {
comp_data = image->comps[index].data;
for (y = 0; y < image->comps[index].h; y++) {
- img_ptr = picture->data[index] + y * picture->linesize[index];
+ int line = separate_fields * (field_pos + y) + y;
+ img_ptr = picture->data[index] + line * picture->linesize[index];
for (x = 0; x < image->comps[index].w; x++) {
*img_ptr = (uint8_t) *comp_data;
img_ptr++;
@@ -198,14 +207,15 @@ static inline void libopenjpeg_copyto8(AVFrame *picture, opj_image_t *image) {
}
}
-static inline void libopenjpeg_copyto16(AVFrame *picture, opj_image_t *image) {
+static inline void libopenjpeg_copyto16(AVFrame *picture, opj_image_t *image, int separate_fields, int field_pos) {
int *comp_data;
uint16_t *img_ptr;
int index, x, y;
for (index = 0; index < image->numcomps; index++) {
comp_data = image->comps[index].data;
for (y = 0; y < image->comps[index].h; y++) {
- img_ptr = (uint16_t*) (picture->data[index] + y * picture->linesize[index]);
+ int line = separate_fields * (field_pos + y) + y;
+ img_ptr = (uint16_t*) (picture->data[index] + line * picture->linesize[index]);
for (x = 0; x < image->comps[index].w; x++) {
*img_ptr = *comp_data;
img_ptr++;
@@ -219,10 +229,27 @@ static av_cold int libopenjpeg_decode_init(AVCodecContext *avctx)
{
LibOpenJPEGContext *ctx = avctx->priv_data;
+ if (avctx->extradata_size > 2) {
+ ctx->picture = av_frame_alloc();
+ ctx->separate_fields = avctx->extradata[0];
+ if (ctx->separate_fields) {
+ avctx->field_order = ctx->field_order = avctx->extradata[1];
+ ctx->top_field_coded_first = (ctx->field_order == AV_FIELD_TT ||
+ ctx->field_order == AV_FIELD_TB);
+ }
+ }
+
opj_set_default_decoder_parameters(&ctx->dec_params);
return 0;
}
+static av_cold int libopenjpeg_decode_uninit(AVCodecContext *avctx)
+{
+ LibOpenJPEGContext *ctx = avctx->priv_data;
+ av_frame_free(&ctx->picture);
+ return 0;
+}
+
static int libopenjpeg_decode_frame(AVCodecContext *avctx,
void *data, int *got_frame,
AVPacket *avpkt)
@@ -239,9 +266,22 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx,
int width, height, ret = -1;
int pixel_size = 0;
int ispacked = 0;
- int i;
+ int realloc_il_buffer = 0;
+ int i, field_pos, field_nb;
*got_frame = 0;
+ if (ctx->separate_fields) {
+ picture = ctx->picture;
+ frame.f = picture;
+ }
+
+ field_nb = ctx->curpict % 2;
+ field_pos = field_nb ^ !ctx->top_field_coded_first;
+
+ if (ctx->separate_fields && avctx->thread_count > 1) {
+ av_log(avctx, AV_LOG_ERROR, "Separate fields layout does not support threading. Please specify -threads 1 before input.\n");
+ return AVERROR(EINVAL);
+ }
// Check if input is a raw jpeg2k codestream or in jp2 wrapping
if ((AV_RB32(buf) == 12) &&
@@ -287,12 +327,21 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx,
width = image->x1 - image->x0;
height = image->y1 - image->y0;
+ if (ctx->separate_fields)
+ height *= 2;
+
if (av_image_check_size(width, height, 0, avctx) < 0) {
av_log(avctx, AV_LOG_ERROR,
"%dx%d dimension invalid.\n", width, height);
goto done;
}
+ if (ctx->width != width || ctx->height != height) {
+ ctx->width = width;
+ ctx->height = height;
+ realloc_il_buffer = 1;
+ }
+
avcodec_set_dimensions(avctx, width, height);
if (avctx->pix_fmt != AV_PIX_FMT_NONE)
@@ -310,8 +359,13 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx,
if (image->comps[i].prec > avctx->bits_per_raw_sample)
avctx->bits_per_raw_sample = image->comps[i].prec;
- if (ff_thread_get_buffer(avctx, &frame, 0) < 0)
- goto done;
+ if (ctx->separate_fields && realloc_il_buffer && picture->data[0])
+ av_frame_unref(picture);
+
+ if (!ctx->separate_fields ||
+ (ctx->separate_fields && (!ctx->curpict || realloc_il_buffer)))
+ if (ff_thread_get_buffer(avctx, &frame, 0) < 0)
+ goto done;
ctx->dec_params.cp_limit_decoding = NO_LIMITATION;
ctx->dec_params.cp_reduce = avctx->lowres;
@@ -341,28 +395,28 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx,
switch (pixel_size) {
case 1:
if (ispacked) {
- libopenjpeg_copy_to_packed8(picture, image);
+ libopenjpeg_copy_to_packed8(picture, image, ctx->separate_fields, field_pos);
} else {
- libopenjpeg_copyto8(picture, image);
+ libopenjpeg_copyto8(picture, image, ctx->separate_fields, field_pos);
}
break;
case 2:
if (ispacked) {
- libopenjpeg_copy_to_packed8(picture, image);
+ libopenjpeg_copy_to_packed8(picture, image, ctx->separate_fields, field_pos);
} else {
- libopenjpeg_copyto16(picture, image);
+ libopenjpeg_copyto16(picture, image, ctx->separate_fields, field_pos);
}
break;
case 3:
case 4:
if (ispacked) {
- libopenjpeg_copy_to_packed8(picture, image);
+ libopenjpeg_copy_to_packed8(picture, image, ctx->separate_fields, field_pos);
}
break;
case 6:
case 8:
if (ispacked) {
- libopenjpeg_copy_to_packed16(picture, image);
+ libopenjpeg_copy_to_packed16(picture, image, ctx->separate_fields, field_pos);
}
break;
default:
@@ -373,7 +427,13 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx,
*got_frame = 1;
ret = buf_size;
+ if (ctx->separate_fields)
+ if (field_nb)
+ av_frame_ref(data, ctx->picture);
+ else
+ *got_frame = 0;
done:
+ ctx->curpict++;
opj_image_destroy(image);
opj_destroy_decompress(dec);
return ret;
@@ -401,6 +461,7 @@ AVCodec ff_libopenjpeg_decoder = {
.priv_data_size = sizeof(LibOpenJPEGContext),
.init = libopenjpeg_decode_init,
.decode = libopenjpeg_decode_frame,
+ .close = libopenjpeg_decode_uninit,
.capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS,
.max_lowres = 31,
.long_name = NULL_IF_CONFIG_SMALL("OpenJPEG JPEG 2000"),
--
1.8.2
More information about the ffmpeg-devel
mailing list