summaryrefslogtreecommitdiff
path: root/libavcodec/vp9.c
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2016-11-13 11:24:16 +0100
committerAnton Khirnov <anton@khirnov.net>2016-12-14 09:06:45 +0100
commitfa1749dd34c55fb997c97dfc4da9383c9976ab91 (patch)
tree9650e5e9ec2b3ced73fe624eeb6f9993a927f3cb /libavcodec/vp9.c
parent03a80925effc2698d21dc0b00290eecf42dd9e68 (diff)
vp9: split superframes in the filtering stage before actual decoding
Significantly increases the efficiency of frame threading, since individual frames in a superframe can now be decoded in parallel.
Diffstat (limited to 'libavcodec/vp9.c')
-rw-r--r--libavcodec/vp9.c74
1 files changed, 13 insertions, 61 deletions
diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c
index 906218565e..48f8afe9ca 100644
--- a/libavcodec/vp9.c
+++ b/libavcodec/vp9.c
@@ -1188,14 +1188,18 @@ static int update_refs(AVCodecContext *avctx)
return 0;
}
-static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
- int *got_frame, const uint8_t *data, int size,
- int can_finish_setup)
+static int vp9_decode_frame(AVCodecContext *avctx, void *output,
+ int *got_frame, AVPacket *pkt)
{
VP9Context *s = avctx->priv_data;
+ AVFrame *frame = output;
+ const uint8_t *data = pkt->data;
+ int size = pkt->size;
AVFrame *f;
int ret, tile_row, tile_col, i, ref = -1, row, col;
+ s->setup_finished = 0;
+
ret = decode_frame_header(avctx, data, size, &ref);
if (ret < 0) {
return ret;
@@ -1210,7 +1214,7 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
if (ret < 0)
return ret;
*got_frame = 1;
- return 0;
+ return pkt->size;
}
data += ret;
size -= ret;
@@ -1261,7 +1265,7 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
s->prob_ctx[s->framectxid].p = s->prob.p;
}
if ((s->parallelmode || !s->refreshctx) &&
- can_finish_setup && avctx->active_thread_type & FF_THREAD_FRAME) {
+ avctx->active_thread_type & FF_THREAD_FRAME) {
ff_thread_finish_setup(avctx);
s->setup_finished = 1;
}
@@ -1402,7 +1406,7 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
if (s->pass < 2 && s->refreshctx && !s->parallelmode) {
ff_vp9_adapt_probs(s);
- if (can_finish_setup && avctx->active_thread_type & FF_THREAD_FRAME) {
+ if (avctx->active_thread_type & FF_THREAD_FRAME) {
ff_thread_finish_setup(avctx);
s->setup_finished = 1;
}
@@ -1428,60 +1432,7 @@ fail:
*got_frame = 1;
}
- return 0;
-}
-
-static int vp9_decode_packet(AVCodecContext *avctx, void *frame,
- int *got_frame, AVPacket *avpkt)
-{
- VP9Context *s = avctx->priv_data;
- const uint8_t *data = avpkt->data;
- int size = avpkt->size;
- int marker, ret;
-
- s->setup_finished = 0;
-
- /* Read superframe index - this is a collection of individual frames
- * that together lead to one visible frame */
- marker = data[size - 1];
- if ((marker & 0xe0) == 0xc0) {
- int nbytes = 1 + ((marker >> 3) & 0x3);
- int n_frames = 1 + (marker & 0x7);
- int idx_sz = 2 + n_frames * nbytes;
-
- if (size >= idx_sz && data[size - idx_sz] == marker) {
- const uint8_t *idx = data + size + 1 - idx_sz;
-
- while (n_frames--) {
- unsigned sz = AV_RL32(idx);
-
- if (nbytes < 4)
- sz &= (1 << (8 * nbytes)) - 1;
- idx += nbytes;
-
- if (sz > size) {
- av_log(avctx, AV_LOG_ERROR,
- "Superframe packet size too big: %u > %d\n",
- sz, size);
- return AVERROR_INVALIDDATA;
- }
-
- ret = vp9_decode_frame(avctx, frame, got_frame, data, sz,
- !n_frames);
- if (ret < 0)
- return ret;
- data += sz;
- size -= sz;
- }
- return avpkt->size;
- }
- }
-
- /* If we get here, there was no valid superframe index, i.e. this is just
- * one whole single frame. Decode it as such from the complete input buf. */
- if ((ret = vp9_decode_frame(avctx, frame, got_frame, data, size, 1)) < 0)
- return ret;
- return size;
+ return pkt->size;
}
static av_cold int vp9_decode_free(AVCodecContext *avctx)
@@ -1590,10 +1541,11 @@ AVCodec ff_vp9_decoder = {
.id = AV_CODEC_ID_VP9,
.priv_data_size = sizeof(VP9Context),
.init = vp9_decode_init,
- .decode = vp9_decode_packet,
+ .decode = vp9_decode_frame,
.flush = vp9_decode_flush,
.close = vp9_decode_free,
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
.init_thread_copy = vp9_decode_init,
.update_thread_context = vp9_decode_update_thread_context,
+ .bsfs = "vp9_superframe_split",
};