utvideo: account for coupled lines in YUV420 format
authorKostya Shishkov <kostya.shishkov@gmail.com>
Fri, 28 Oct 2011 18:40:23 +0000 (20:40 +0200)
committerRonald S. Bultje <rsbultje@gmail.com>
Sat, 29 Oct 2011 06:51:58 +0000 (23:51 -0700)
Luma slices in YUV420 colourspace should have height in multiple of two since
they have the same line of chrominance data corresponding to pair of them.

Signed-off-by: Ronald S. Bultje <rsbultje@gmail.com>
libavcodec/utvideo.c

index aac3969..5faaa15 100644 (file)
@@ -113,6 +113,7 @@ static int decode_plane(UtvideoContext *c, int plane_no,
     VLC vlc;
     GetBitContext gb;
     int prev;
+    const int cmask = ~(!plane_no && c->avctx->pix_fmt == PIX_FMT_YUV420P);
 
     if (build_huff(src, &vlc)) {
         av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n");
@@ -128,7 +129,7 @@ static int decode_plane(UtvideoContext *c, int plane_no,
         int slice_data_start, slice_data_end, slice_size;
 
         sstart = send;
-        send   = height * (slice + 1) / c->slices;
+        send   = (height * (slice + 1) / c->slices) & cmask;
         dest   = dst + sstart * stride;
 
         // slice offset and size validation was done earlier
@@ -204,16 +205,17 @@ static void restore_rgb_planes(uint8_t *src, int step, int stride, int width, in
 }
 
 static void restore_median(uint8_t *src, int step, int stride,
-                           int width, int height, int slices)
+                           int width, int height, int slices, int rmode)
 {
     int i, j, slice;
     int A, B, C;
     uint8_t *bsrc;
     int slice_start, slice_height;
+    const int cmask = ~rmode;
 
     for (slice = 0; slice < slices; slice++) {
-        slice_start = (slice * height) / slices;
-        slice_height = ((slice + 1) * height) / slices - slice_start;
+        slice_start = ((slice * height) / slices) & cmask;
+        slice_height = ((((slice + 1) * height) / slices) & cmask) - slice_start;
 
         bsrc = src + slice_start * stride;
 
@@ -337,7 +339,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac
             if (c->frame_pred == PRED_MEDIAN)
                 restore_median(c->pic.data[0] + rgb_order[i], c->planes,
                                c->pic.linesize[0], avctx->width, avctx->height,
-                               c->slices);
+                               c->slices, 0);
         }
         restore_rgb_planes(c->pic.data[0], c->planes, c->pic.linesize[0],
                            avctx->width, avctx->height);
@@ -353,7 +355,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac
             if (c->frame_pred == PRED_MEDIAN)
                 restore_median(c->pic.data[i], 1, c->pic.linesize[i],
                                avctx->width >> !!i, avctx->height >> !!i,
-                               c->slices);
+                               c->slices, !i);
         }
         break;
     case PIX_FMT_YUV422P:
@@ -366,7 +368,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac
                 return ret;
             if (c->frame_pred == PRED_MEDIAN)
                 restore_median(c->pic.data[i], 1, c->pic.linesize[i],
-                               avctx->width >> !!i, avctx->height, c->slices);
+                               avctx->width >> !!i, avctx->height, c->slices, 0);
         }
         break;
     }