[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