]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/utvideo.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavcodec / utvideo.c
index 6fb384a4e46843c62959c72d79fc67f821f9032b..a45f13fa54e6c03d0ba2f2fe309dc4d93e4f4e5d 100644 (file)
@@ -31,6 +31,7 @@
 #include "bytestream.h"
 #include "get_bits.h"
 #include "dsputil.h"
+#include "thread.h"
 
 enum {
     PRED_NONE = 0,
@@ -282,6 +283,77 @@ static void restore_median(uint8_t *src, int step, int stride,
     }
 }
 
+/* UtVideo interlaced mode treats every two lines as a single one,
+ * so restoring function should take care of possible padding between
+ * two parts of the same "line".
+ */
+static void restore_median_il(uint8_t *src, int step, int stride,
+                              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 ? 3 : 1);
+    const int stride2 = stride << 1;
+
+    for (slice = 0; slice < slices; slice++) {
+        slice_start    = ((slice * height) / slices) & cmask;
+        slice_height   = ((((slice + 1) * height) / slices) & cmask) - slice_start;
+        slice_height >>= 1;
+
+        bsrc = src + slice_start * stride;
+
+        // first line - left neighbour prediction
+        bsrc[0] += 0x80;
+        A = bsrc[0];
+        for (i = step; i < width * step; i += step) {
+            bsrc[i] += A;
+            A = bsrc[i];
+        }
+        for (i = 0; i < width * step; i += step) {
+            bsrc[stride + i] += A;
+            A = bsrc[stride + i];
+        }
+        bsrc += stride2;
+        if (slice_height == 1)
+            continue;
+        // second line - first element has top predition, the rest uses median
+        C = bsrc[-stride2];
+        bsrc[0] += C;
+        A = bsrc[0];
+        for (i = step; i < width * step; i += step) {
+            B = bsrc[i - stride2];
+            bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C));
+            C = B;
+            A = bsrc[i];
+        }
+        for (i = 0; i < width * step; i += step) {
+            B = bsrc[i - stride];
+            bsrc[stride + i] += mid_pred(A, B, (uint8_t)(A + B - C));
+            C = B;
+            A = bsrc[stride + i];
+        }
+        bsrc += stride2;
+        // the rest of lines use continuous median prediction
+        for (j = 2; j < slice_height; j++) {
+            for (i = 0; i < width * step; i += step) {
+                B = bsrc[i - stride2];
+                bsrc[i] += mid_pred(A, B, (uint8_t)(A + B - C));
+                C = B;
+                A = bsrc[i];
+            }
+            for (i = 0; i < width * step; i += step) {
+                B = bsrc[i - stride];
+                bsrc[i + stride] += mid_pred(A, B, (uint8_t)(A + B - C));
+                C = B;
+                A = bsrc[i + stride];
+            }
+            bsrc += stride2;
+        }
+    }
+}
+
 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt)
 {
     const uint8_t *buf = avpkt->data;
@@ -295,15 +367,17 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac
     int ret;
 
     if (c->pic.data[0])
-        avctx->release_buffer(avctx, &c->pic);
+        ff_thread_release_buffer(avctx, &c->pic);
 
     c->pic.reference = 3;
     c->pic.buffer_hints = FF_BUFFER_HINTS_VALID;
-    if ((ret = avctx->get_buffer(avctx, &c->pic)) < 0) {
+    if ((ret = ff_thread_get_buffer(avctx, &c->pic)) < 0) {
         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
         return ret;
     }
 
+    ff_thread_finish_setup(avctx);
+
     /* parse plane structure to retrieve frame flags and validate slice offsets */
     ptr = buf;
     for (i = 0; i < c->planes; i++) {
@@ -381,10 +455,18 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac
                                c->frame_pred == PRED_LEFT);
             if (ret)
                 return ret;
-            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, !i);
+            if (c->frame_pred == PRED_MEDIAN) {
+                if (!c->interlaced) {
+                    restore_median(c->pic.data[i], 1, c->pic.linesize[i],
+                                   avctx->width >> !!i, avctx->height >> !!i,
+                                   c->slices, !i);
+                } else {
+                    restore_median_il(c->pic.data[i], 1, c->pic.linesize[i],
+                                      avctx->width  >> !!i,
+                                      avctx->height >> !!i,
+                                      c->slices, !i);
+                }
+            }
         }
         break;
     case PIX_FMT_YUV422P:
@@ -395,9 +477,17 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac
                                c->frame_pred == PRED_LEFT);
             if (ret)
                 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, 0);
+            if (c->frame_pred == PRED_MEDIAN) {
+                if (!c->interlaced) {
+                    restore_median(c->pic.data[i], 1, c->pic.linesize[i],
+                                   avctx->width >> !!i, avctx->height,
+                                   c->slices, 0);
+                } else {
+                    restore_median_il(c->pic.data[i], 1, c->pic.linesize[i],
+                                      avctx->width >> !!i, avctx->height,
+                                      c->slices, 0);
+                }
+            }
         }
         break;
     }
@@ -470,7 +560,7 @@ static av_cold int decode_end(AVCodecContext *avctx)
     UtvideoContext * const c = avctx->priv_data;
 
     if (c->pic.data[0])
-        avctx->release_buffer(avctx, &c->pic);
+        ff_thread_release_buffer(avctx, &c->pic);
 
     av_freep(&c->slice_bits);
 
@@ -485,7 +575,7 @@ AVCodec ff_utvideo_decoder = {
     .init           = decode_init,
     .close          = decode_end,
     .decode         = decode_frame,
-    .capabilities   = CODEC_CAP_DR1,
+    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS,
     .long_name      = NULL_IF_CONFIG_SMALL("Ut Video"),
 };