[FFmpeg-devel] [PATCH 1/7] lavc/libopenjpegdec: support interlaced layout

Matthieu Bouron matthieu.bouron at gmail.com
Thu Mar 28 16:12:17 CET 2013


On Thu, Mar 28, 2013 at 03:41:45PM +0100, Matthieu Bouron wrote:
> 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
> 

New patch attached.
Extradata size check was incorrect in libopenjpegdec_decode_init function.

-------------- next part --------------
>From d9db03b286563b8921ee8cdc7cb21d8a6a2d7531 Mon Sep 17 00:00:00 2001
From: Matthieu Bouron <matthieu.bouron at gmail.com>
Date: Fri, 15 Feb 2013 16:01:45 +0100
Subject: [PATCH 1/7] lavc/libopenjpegdec: support interlaced layout

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..de7f671 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