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

Matthieu Bouron matthieu.bouron at gmail.com
Sat Feb 16 13:52:31 CET 2013


Fixes tickets #1102.
---
 libavcodec/libopenjpegdec.c | 61 +++++++++++++++++++++++++++++++++------------
 1 file changed, 45 insertions(+), 16 deletions(-)

diff --git a/libavcodec/libopenjpegdec.c b/libavcodec/libopenjpegdec.c
index eeb3dd6..ad7866c 100644
--- a/libavcodec/libopenjpegdec.c
+++ b/libavcodec/libopenjpegdec.c
@@ -69,6 +69,7 @@ typedef struct {
     opj_dparameters_t dec_params;
     AVFrame image;
     int lowqual;
+    int curpict;
 } LibOpenJPEGContext;
 
 static inline int libopenjpeg_matches_pix_fmt(const opj_image_t *image, enum AVPixelFormat pix_fmt)
@@ -149,12 +150,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 field) {
     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 = picture->interlaced_frame * (field + 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];
@@ -163,16 +165,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 field) {
     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 = picture->interlaced_frame * (field + 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];
@@ -181,7 +184,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 field) {
     int *comp_data;
     uint8_t *img_ptr;
     int index, x, y;
@@ -189,7 +192,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 = picture->interlaced_frame * (field + 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++;
@@ -199,14 +203,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 field) {
     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 = picture->interlaced_frame * (field + 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++;
@@ -249,9 +254,18 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx,
     int width, height, ret = -1;
     int pixel_size = 0;
     int ispacked = 0;
+    int field;
     int i;
 
     *got_frame = 0;
+    picture->interlaced_frame = avctx->field_order > AV_FIELD_PROGRESSIVE;
+    picture->top_field_first  = avctx->field_order == AV_FIELD_TT;
+    field = ctx->curpict ^ !picture->top_field_first;
+
+    if (picture->interlaced_frame && avctx->thread_count > 1) {
+        av_log(avctx, AV_LOG_ERROR, "Interlaced 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)           &&
@@ -297,6 +311,9 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx,
     width  = image->x1 - image->x0;
     height = image->y1 - image->y0;
 
+    if (picture->interlaced_frame)
+        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);
@@ -356,28 +373,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, field);
         } else {
-            libopenjpeg_copyto8(picture, image);
+            libopenjpeg_copyto8(picture, image, field);
         }
         break;
     case 2:
         if (ispacked) {
-            libopenjpeg_copy_to_packed8(picture, image);
+            libopenjpeg_copy_to_packed8(picture, image, field);
         } else {
-            libopenjpeg_copyto16(picture, image);
+            libopenjpeg_copyto16(picture, image, field);
         }
         break;
     case 3:
     case 4:
         if (ispacked) {
-            libopenjpeg_copy_to_packed8(picture, image);
+            libopenjpeg_copy_to_packed8(picture, image, field);
         }
         break;
     case 6:
     case 8:
         if (ispacked) {
-            libopenjpeg_copy_to_packed16(picture, image);
+            libopenjpeg_copy_to_packed16(picture, image, field);
         }
         break;
     default:
@@ -389,6 +406,18 @@ static int libopenjpeg_decode_frame(AVCodecContext *avctx,
     *got_frame = 1;
     ret        = buf_size;
 
+    if (picture->interlaced_frame)
+        switch(ctx->curpict) {
+        case 0:
+            ret = 0;
+            *got_frame = 0;
+            ctx->curpict = 1;
+            break;
+        case 1:
+            ctx->curpict = 0;
+            break;
+        }
+
 done:
     opj_image_destroy(image);
     opj_destroy_decompress(dec);
-- 
1.8.1.3



More information about the ffmpeg-devel mailing list