[FFmpeg-devel] [PATCH 5/6] lavc/vp6: Implement "slice" threading for VP6A decode

Ben Jackson ben at ben.com
Sat Sep 15 19:32:43 CEST 2012


The YUV channels of VP6 are encoded in a highly linear fashion which does
not have any slice-like concept to thread.  The alpha channel of VP6A is
fairly independent of the YUV and comprises 40% of the work.  This patch
uses the THREAD_SLICE capability to split the YUV and A decodes into
separate threads.

Two bugs are fixed by splitting YUV and alpha state:
- qscale_table from VP6A decode was for alpha channel instead of YUV
- alpha channel filtering settings were overwritten by YUV header parse

Signed-off-by: Ben Jackson <ben at ben.com>
---
 libavcodec/vp56.c   |  103 +++++++++++++++++-------------
 libavcodec/vp56.h   |    5 +-
 libavcodec/vp6.c    |   21 ++++++-
 tests/ref/fate/vp6a |  172 +++++++++++++++++++++++++-------------------------
 4 files changed, 168 insertions(+), 133 deletions(-)

diff --git a/libavcodec/vp56.c b/libavcodec/vp56.c
index 7d771f3..0eb9314 100644
--- a/libavcodec/vp56.c
+++ b/libavcodec/vp56.c
@@ -449,9 +449,9 @@ static void vp56_decode_mb(VP56Context *s, int row, int col, int is_alpha)
     }
 }
 
-static int vp56_size_changed(AVCodecContext *avctx)
+static int vp56_size_changed(VP56Context *s)
 {
-    VP56Context *s = avctx->priv_data;
+    AVCodecContext *avctx = s->avctx;
     int stride = s->framep[VP56_FRAME_CURRENT]->linesize[0];
     int i;
 
@@ -483,9 +483,14 @@ static int vp56_size_changed(AVCodecContext *avctx)
     if (s->flip < 0)
         s->edge_emu_buffer += 15 * stride;
 
+    if (s->alpha_context)
+        return vp56_size_changed(s->alpha_context);
+
     return 0;
 }
 
+static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *, int, int);
+
 int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
                          AVPacket *avpkt)
 {
@@ -493,8 +498,8 @@ int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
     VP56Context *s = avctx->priv_data;
     AVFrame *p = 0;
     int remaining_buf_size = avpkt->size;
-    int is_alpha, av_uninit(alpha_offset);
-    int i;
+    int av_uninit(alpha_offset);
+    int i, res;
 
     /* select a current frame from the unused frames */
     for (i = 0; i < 4; ++i) {
@@ -505,6 +510,8 @@ int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
     }
     av_assert0(p != 0);
     s->framep[VP56_FRAME_CURRENT] = p;
+    if (s->alpha_context)
+        s->alpha_context->framep[VP56_FRAME_CURRENT] = p;
 
     if (s->has_alpha) {
         if (remaining_buf_size < 3)
@@ -515,30 +522,17 @@ int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
             return -1;
     }
 
-    for (is_alpha=0; is_alpha < 1+s->has_alpha; is_alpha++) {
-        int mb_row, mb_col, mb_row_flip, mb_offset = 0;
-        int block, y, uv, stride_y, stride_uv;
-        int res;
-
-        s->modelp = &s->models[is_alpha];
-
         res = s->parse_header(s, buf, remaining_buf_size);
         if (!res)
             return -1;
 
         if (res == 2) {
-            int i;
             for (i = 0; i < 4; i++) {
                 if (s->frames[i].data[0])
                     avctx->release_buffer(avctx, &s->frames[i]);
             }
-            if (is_alpha) {
-                avcodec_set_dimensions(avctx, 0, 0);
-                return -1;
-            }
         }
 
-        if (!is_alpha) {
             p->reference = 3;
             if (avctx->get_buffer(avctx, p) < 0) {
                 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
@@ -546,11 +540,53 @@ int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
             }
 
             if (res == 2)
-                if (vp56_size_changed(avctx)) {
+                if (vp56_size_changed(s)) {
                     avctx->release_buffer(avctx, p);
                     return -1;
                 }
+
+    if (s->has_alpha) {
+        buf += alpha_offset;
+        remaining_buf_size -= alpha_offset;
+
+        res = s->alpha_context->parse_header(s->alpha_context, buf, remaining_buf_size);
+        if (res != 1) {
+            avctx->release_buffer(avctx, p);
+            return -1;
         }
+    }
+
+    avctx->execute2(avctx, ff_vp56_decode_mbs, 0, 0, s->has_alpha + 1);
+
+    /* release frames that aren't in use */
+    for (i = 0; i < 4; ++i) {
+        AVFrame *victim = &s->frames[i];
+        if (!victim->data[0])
+            continue;
+        if (victim != s->framep[VP56_FRAME_PREVIOUS] &&
+            victim != s->framep[VP56_FRAME_GOLDEN] &&
+            (!s->has_alpha || victim != s->alpha_context->framep[VP56_FRAME_GOLDEN]))
+            avctx->release_buffer(avctx, victim);
+    }
+
+    p->qstride = 0;
+    p->qscale_table = s->qscale_table;
+    p->qscale_type = FF_QSCALE_TYPE_VP56;
+    *(AVFrame*)data = *p;
+    *data_size = sizeof(AVFrame);
+
+    return avpkt->size;
+}
+
+static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *data,
+                              int jobnr, int threadnr)
+{
+    VP56Context *s0 = avctx->priv_data;
+    int is_alpha = (jobnr == 1);
+    VP56Context *s = is_alpha ? s0->alpha_context : s0;
+    AVFrame *const p = s->framep[VP56_FRAME_CURRENT];
+    int mb_row, mb_col, mb_row_flip, mb_offset = 0;
+    int block, y, uv, stride_y, stride_uv;
 
         if (p->key_frame) {
             p->pict_type = AV_PICTURE_TYPE_I;
@@ -634,35 +670,9 @@ int ff_vp56_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
             s->framep[VP56_FRAME_GOLDEN] = p;
         }
 
-        if (s->has_alpha) {
-            FFSWAP(AVFrame *, s->framep[VP56_FRAME_GOLDEN],
-                              s->framep[VP56_FRAME_GOLDEN2]);
-            buf += alpha_offset;
-            remaining_buf_size -= alpha_offset;
-        }
-    }
-
     FFSWAP(AVFrame *, s->framep[VP56_FRAME_CURRENT],
                       s->framep[VP56_FRAME_PREVIOUS]);
-
-    /* release frames that aren't in use */
-    for (i = 0; i < 4; ++i) {
-        AVFrame *victim = &s->frames[i];
-        if (!victim->data[0])
-            continue;
-        if (victim != s->framep[VP56_FRAME_PREVIOUS] &&
-            victim != s->framep[VP56_FRAME_GOLDEN] &&
-            (!s->has_alpha || victim != s->framep[VP56_FRAME_GOLDEN2]))
-            avctx->release_buffer(avctx, victim);
-    }
-
-    p->qstride = 0;
-    p->qscale_table = s->qscale_table;
-    p->qscale_type = FF_QSCALE_TYPE_VP56;
-    *(AVFrame*)data = *p;
-    *data_size = sizeof(AVFrame);
-
-    return avpkt->size;
+    return 0;
 }
 
 av_cold void ff_vp56_init(AVCodecContext *avctx, int flip, int has_alpha)
@@ -702,6 +712,9 @@ av_cold void ff_vp56_init_context(AVCodecContext *avctx, VP56Context *s,
     s->filter = NULL;
 
     s->has_alpha = has_alpha;
+
+    s->modelp = &s->model;
+
     if (flip) {
         s->flip = -1;
         s->frbi = 2;
diff --git a/libavcodec/vp56.h b/libavcodec/vp56.h
index 7a32342..44bd229 100644
--- a/libavcodec/vp56.h
+++ b/libavcodec/vp56.h
@@ -161,8 +161,11 @@ struct vp56_context {
     VP56ParseCoeffModels parse_coeff_models;
     VP56ParseHeader parse_header;
 
+    /* for "slice" parallelism between YUV and A */
+    VP56Context *alpha_context;
+
     VP56Model *modelp;
-    VP56Model models[2];
+    VP56Model model;
 
     /* huffman decoding */
     int use_huffman;
diff --git a/libavcodec/vp6.c b/libavcodec/vp6.c
index c8a1917..bafa2b4 100644
--- a/libavcodec/vp6.c
+++ b/libavcodec/vp6.c
@@ -599,6 +599,18 @@ static av_cold int vp6_decode_init(AVCodecContext *avctx)
     ff_vp56_init(avctx, avctx->codec->id == AV_CODEC_ID_VP6,
                         avctx->codec->id == AV_CODEC_ID_VP6A);
     vp6_decode_init_context(s);
+
+    if (s->has_alpha) {
+        int i;
+
+        s->alpha_context = av_mallocz(sizeof(VP56Context));
+        ff_vp56_init_context(avctx, s->alpha_context,
+                             s->flip == -1, s->has_alpha);
+        vp6_decode_init_context(s->alpha_context);
+        for (i = 0; i < 6; ++i)
+            s->alpha_context->framep[i] = s->framep[i];
+    }
+
     return 0;
 }
 
@@ -622,6 +634,13 @@ static av_cold int vp6_decode_free(AVCodecContext *avctx)
 
     ff_vp56_free(avctx);
     vp6_decode_free_context(s);
+
+    if (s->alpha_context) {
+        ff_vp56_free_context(s->alpha_context);
+        vp6_decode_free_context(s->alpha_context);
+        av_free(s->alpha_context);
+    }
+
     return 0;
 }
 
@@ -672,6 +691,6 @@ AVCodec ff_vp6a_decoder = {
     .init           = vp6_decode_init,
     .close          = vp6_decode_free,
     .decode         = ff_vp56_decode_frame,
-    .capabilities   = CODEC_CAP_DR1,
+    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_SLICE_THREADS,
     .long_name      = NULL_IF_CONFIG_SMALL("On2 VP6 (Flash version, with alpha channel)"),
 };
diff --git a/tests/ref/fate/vp6a b/tests/ref/fate/vp6a
index de0518b..1f2ddd9 100644
--- a/tests/ref/fate/vp6a
+++ b/tests/ref/fate/vp6a
@@ -1,94 +1,94 @@
 #tb 0: 1/4
 0,          0,          0,        1,   135000, 0x9dceed6d
-0,          1,          1,        1,   135000, 0xcb87787f
-0,          2,          2,        1,   135000, 0xdb4361ce
-0,          3,          3,        1,   135000, 0xb8fd81c2
-0,          4,          4,        1,   135000, 0xbf86a7af
-0,          5,          5,        1,   135000, 0x2e7787e3
-0,          6,          6,        1,   135000, 0x6cec6ebd
-0,          7,          7,        1,   135000, 0xa4d08c07
-0,          8,          8,        1,   135000, 0x1be48faf
-0,          9,          9,        1,   135000, 0xf3cd8ede
-0,         10,         10,        1,   135000, 0x33ec8a49
-0,         11,         11,        1,   135000, 0x11e887ec
-0,         12,         12,        1,   135000, 0x3e215c25
-0,         13,         13,        1,   135000, 0x1a2cb3f8
-0,         14,         14,        1,   135000, 0x7fb0e48a
-0,         15,         15,        1,   135000, 0x749f3738
-0,         16,         16,        1,   135000, 0x686e78e9
-0,         17,         17,        1,   135000, 0x29515bc7
-0,         18,         18,        1,   135000, 0x987126bd
-0,         19,         19,        1,   135000, 0xdf77bb13
-0,         20,         20,        1,   135000, 0x5fb1468a
-0,         21,         21,        1,   135000, 0x06ea50ea
-0,         22,         22,        1,   135000, 0x7bd9c715
-0,         23,         23,        1,   135000, 0xdd6e6831
-0,         24,         24,        1,   135000, 0x0ee3760f
-0,         25,         25,        1,   135000, 0xc7984dc8
-0,         26,         26,        1,   135000, 0x7e385bff
-0,         27,         27,        1,   135000, 0xae155ab9
-0,         28,         28,        1,   135000, 0xc05ee8f7
-0,         29,         29,        1,   135000, 0x93de3392
-0,         30,         30,        1,   135000, 0xfe45b38b
-0,         31,         31,        1,   135000, 0xeb5ed72c
-0,         32,         32,        1,   135000, 0x0794cb57
-0,         33,         33,        1,   135000, 0x2578c6e5
-0,         34,         34,        1,   135000, 0x78486707
-0,         35,         35,        1,   135000, 0x41e1f0e6
-0,         36,         36,        1,   135000, 0x4508eb76
-0,         37,         37,        1,   135000, 0xd8c087f3
-0,         38,         38,        1,   135000, 0x1a8db89a
-0,         39,         39,        1,   135000, 0x6dbd90c6
-0,         40,         40,        1,   135000, 0x0845e400
-0,         41,         41,        1,   135000, 0xe8b02fc2
-0,         42,         42,        1,   135000, 0x8007d813
-0,         43,         43,        1,   135000, 0xdfb04e69
-0,         44,         44,        1,   135000, 0x5746cf71
-0,         45,         45,        1,   135000, 0xe510299f
-0,         46,         46,        1,   135000, 0xeea0c829
-0,         47,         47,        1,   135000, 0x7c0578ab
+0,          1,          1,        1,   135000, 0x47e5778d
+0,          2,          2,        1,   135000, 0x5de36599
+0,          3,          3,        1,   135000, 0x540d8079
+0,          4,          4,        1,   135000, 0xba9ea534
+0,          5,          5,        1,   135000, 0xa75088f8
+0,          6,          6,        1,   135000, 0x7d867559
+0,          7,          7,        1,   135000, 0xcc678fee
+0,          8,          8,        1,   135000, 0x79c590b9
+0,          9,          9,        1,   135000, 0x87789918
+0,         10,         10,        1,   135000, 0xaa939213
+0,         11,         11,        1,   135000, 0x3912916d
+0,         12,         12,        1,   135000, 0x41305d0b
+0,         13,         13,        1,   135000, 0x2686b5dd
+0,         14,         14,        1,   135000, 0xa69ae422
+0,         15,         15,        1,   135000, 0x998a3478
+0,         16,         16,        1,   135000, 0x5842768d
+0,         17,         17,        1,   135000, 0xf6a85b16
+0,         18,         18,        1,   135000, 0x7a5b2708
+0,         19,         19,        1,   135000, 0x8b2abb63
+0,         20,         20,        1,   135000, 0x7dc8468b
+0,         21,         21,        1,   135000, 0x04d85001
+0,         22,         22,        1,   135000, 0x83e3c647
+0,         23,         23,        1,   135000, 0xcddd687e
+0,         24,         24,        1,   135000, 0x818e785e
+0,         25,         25,        1,   135000, 0x3a915080
+0,         26,         26,        1,   135000, 0x953d603d
+0,         27,         27,        1,   135000, 0x79005ebf
+0,         28,         28,        1,   135000, 0x80afec75
+0,         29,         29,        1,   135000, 0xfc8e376b
+0,         30,         30,        1,   135000, 0xf957b7ef
+0,         31,         31,        1,   135000, 0xe878da44
+0,         32,         32,        1,   135000, 0xe68ecca3
+0,         33,         33,        1,   135000, 0x1a2cc7d3
+0,         34,         34,        1,   135000, 0x4f346a69
+0,         35,         35,        1,   135000, 0x7a0cf4ac
+0,         36,         36,        1,   135000, 0x6d4eee7a
+0,         37,         37,        1,   135000, 0xf0688cbd
+0,         38,         38,        1,   135000, 0xca4abbbc
+0,         39,         39,        1,   135000, 0x87669519
+0,         40,         40,        1,   135000, 0xd090e9d7
+0,         41,         41,        1,   135000, 0xd7f536c1
+0,         42,         42,        1,   135000, 0x353ede54
+0,         43,         43,        1,   135000, 0xbc8f5358
+0,         44,         44,        1,   135000, 0xb52cd59a
+0,         45,         45,        1,   135000, 0x0b882eba
+0,         46,         46,        1,   135000, 0xc544cd54
+0,         47,         47,        1,   135000, 0x31ca7e73
 0,         48,         48,        1,   135000, 0xb1569ce9
-0,         49,         49,        1,   135000, 0x6c233986
-0,         50,         50,        1,   135000, 0x95b77f3d
-0,         51,         51,        1,   135000, 0xfc368d80
-0,         52,         52,        1,   135000, 0x5c73b064
-0,         53,         53,        1,   135000, 0x2206da8d
-0,         54,         54,        1,   135000, 0x62bb599e
-0,         55,         55,        1,   135000, 0x15a68991
-0,         56,         56,        1,   135000, 0x5f5eb810
+0,         49,         49,        1,   135000, 0x8bf4394f
+0,         50,         50,        1,   135000, 0xf413812a
+0,         51,         51,        1,   135000, 0xf2fa90ab
+0,         52,         52,        1,   135000, 0xdcd8b265
+0,         53,         53,        1,   135000, 0xa89cdba1
+0,         54,         54,        1,   135000, 0x212b59a5
+0,         55,         55,        1,   135000, 0x10c589c3
+0,         56,         56,        1,   135000, 0x432ab5b4
 0,         57,         57,        1,   135000, 0x85a9634a
-0,         58,         58,        1,   135000, 0xf24b5c1a
-0,         59,         59,        1,   135000, 0x38034850
-0,         60,         60,        1,   135000, 0x48fd3599
-0,         61,         61,        1,   135000, 0xb9d62408
-0,         62,         62,        1,   135000, 0xaf202a21
-0,         63,         63,        1,   135000, 0x341aa582
-0,         64,         64,        1,   135000, 0x90cdc9bb
-0,         65,         65,        1,   135000, 0x0b52f319
-0,         66,         66,        1,   135000, 0xce61aa5e
-0,         67,         67,        1,   135000, 0x988acb45
-0,         68,         68,        1,   135000, 0xcd353664
-0,         69,         69,        1,   135000, 0xa80c8ce9
-0,         70,         70,        1,   135000, 0x15dce784
-0,         71,         71,        1,   135000, 0x16bd4519
-0,         72,         72,        1,   135000, 0x571712f3
-0,         73,         73,        1,   135000, 0x6b109f1e
+0,         58,         58,        1,   135000, 0x10db5b87
+0,         59,         59,        1,   135000, 0x583145d9
+0,         60,         60,        1,   135000, 0x7d3a33bd
+0,         61,         61,        1,   135000, 0xcf592423
+0,         62,         62,        1,   135000, 0xb59728e5
+0,         63,         63,        1,   135000, 0x1eeca660
+0,         64,         64,        1,   135000, 0xff7bcc34
+0,         65,         65,        1,   135000, 0x0ef8f271
+0,         66,         66,        1,   135000, 0x8c9ca8ee
+0,         67,         67,        1,   135000, 0x8a7ece34
+0,         68,         68,        1,   135000, 0x7d4c3b5d
+0,         69,         69,        1,   135000, 0x99118f21
+0,         70,         70,        1,   135000, 0xd97fe7e2
+0,         71,         71,        1,   135000, 0xf93842f1
+0,         72,         72,        1,   135000, 0x35c912e8
+0,         73,         73,        1,   135000, 0x14e59e97
 0,         74,         74,        1,   135000, 0x8e4c19aa
-0,         75,         75,        1,   135000, 0x4132bd4c
-0,         76,         76,        1,   135000, 0x5babafe2
-0,         77,         77,        1,   135000, 0xddef6313
-0,         78,         78,        1,   135000, 0x76d6b48b
-0,         79,         79,        1,   135000, 0x929e7702
-0,         80,         80,        1,   135000, 0x33f5e4a1
+0,         75,         75,        1,   135000, 0x4adfbc53
+0,         76,         76,        1,   135000, 0x0613adde
+0,         77,         77,        1,   135000, 0x8db264ab
+0,         78,         78,        1,   135000, 0x3948b619
+0,         79,         79,        1,   135000, 0x843d7c02
+0,         80,         80,        1,   135000, 0x534fea34
 0,         81,         81,        1,   135000, 0xdb7041bf
-0,         82,         82,        1,   135000, 0xbc761e04
-0,         83,         83,        1,   135000, 0x0b2a81e6
-0,         84,         84,        1,   135000, 0xf6fd20ea
-0,         85,         85,        1,   135000, 0x1894a26c
-0,         86,         86,        1,   135000, 0xb25e216f
-0,         87,         87,        1,   135000, 0x83bb02ee
-0,         88,         88,        1,   135000, 0x6952a3c3
-0,         89,         89,        1,   135000, 0x372184d6
-0,         90,         90,        1,   135000, 0x2ac47afe
+0,         82,         82,        1,   135000, 0xd0ce1cce
+0,         83,         83,        1,   135000, 0x3c008335
+0,         84,         84,        1,   135000, 0xb699208f
+0,         85,         85,        1,   135000, 0xe07da3ca
+0,         86,         86,        1,   135000, 0x26331f41
+0,         87,         87,        1,   135000, 0x4e19fe83
+0,         88,         88,        1,   135000, 0xaa9a9e45
+0,         89,         89,        1,   135000, 0x336b7ed0
+0,         90,         90,        1,   135000, 0xc9bf7611
 0,         91,         91,        1,   135000, 0x14c33a35
 0,         92,         92,        1,   135000, 0xdc08470e
-- 
1.6.3.GIT



More information about the ffmpeg-devel mailing list