mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-29 10:52:20 +00:00
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.
This commit is contained in:
parent
03a80925ef
commit
fa1749dd34
2
configure
vendored
2
configure
vendored
@ -2105,7 +2105,7 @@ vp6a_decoder_select="vp6_decoder"
|
|||||||
vp6f_decoder_select="vp6_decoder"
|
vp6f_decoder_select="vp6_decoder"
|
||||||
vp7_decoder_select="h264pred videodsp vp8dsp"
|
vp7_decoder_select="h264pred videodsp vp8dsp"
|
||||||
vp8_decoder_select="h264pred videodsp vp8dsp"
|
vp8_decoder_select="h264pred videodsp vp8dsp"
|
||||||
vp9_decoder_select="videodsp"
|
vp9_decoder_select="videodsp vp9_superframe_split_bsf"
|
||||||
webp_decoder_select="vp8_decoder"
|
webp_decoder_select="vp8_decoder"
|
||||||
wmapro_decoder_select="mdct sinewin wma_freqs"
|
wmapro_decoder_select="mdct sinewin wma_freqs"
|
||||||
wmav1_decoder_select="mdct sinewin wma_freqs"
|
wmav1_decoder_select="mdct sinewin wma_freqs"
|
||||||
|
@ -1188,14 +1188,18 @@ static int update_refs(AVCodecContext *avctx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
|
static int vp9_decode_frame(AVCodecContext *avctx, void *output,
|
||||||
int *got_frame, const uint8_t *data, int size,
|
int *got_frame, AVPacket *pkt)
|
||||||
int can_finish_setup)
|
|
||||||
{
|
{
|
||||||
VP9Context *s = avctx->priv_data;
|
VP9Context *s = avctx->priv_data;
|
||||||
|
AVFrame *frame = output;
|
||||||
|
const uint8_t *data = pkt->data;
|
||||||
|
int size = pkt->size;
|
||||||
AVFrame *f;
|
AVFrame *f;
|
||||||
int ret, tile_row, tile_col, i, ref = -1, row, col;
|
int ret, tile_row, tile_col, i, ref = -1, row, col;
|
||||||
|
|
||||||
|
s->setup_finished = 0;
|
||||||
|
|
||||||
ret = decode_frame_header(avctx, data, size, &ref);
|
ret = decode_frame_header(avctx, data, size, &ref);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
@ -1210,7 +1214,7 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
*got_frame = 1;
|
*got_frame = 1;
|
||||||
return 0;
|
return pkt->size;
|
||||||
}
|
}
|
||||||
data += ret;
|
data += ret;
|
||||||
size -= 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;
|
s->prob_ctx[s->framectxid].p = s->prob.p;
|
||||||
}
|
}
|
||||||
if ((s->parallelmode || !s->refreshctx) &&
|
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);
|
ff_thread_finish_setup(avctx);
|
||||||
s->setup_finished = 1;
|
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) {
|
if (s->pass < 2 && s->refreshctx && !s->parallelmode) {
|
||||||
ff_vp9_adapt_probs(s);
|
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);
|
ff_thread_finish_setup(avctx);
|
||||||
s->setup_finished = 1;
|
s->setup_finished = 1;
|
||||||
}
|
}
|
||||||
@ -1428,60 +1432,7 @@ fail:
|
|||||||
*got_frame = 1;
|
*got_frame = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return pkt->size;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static av_cold int vp9_decode_free(AVCodecContext *avctx)
|
static av_cold int vp9_decode_free(AVCodecContext *avctx)
|
||||||
@ -1590,10 +1541,11 @@ AVCodec ff_vp9_decoder = {
|
|||||||
.id = AV_CODEC_ID_VP9,
|
.id = AV_CODEC_ID_VP9,
|
||||||
.priv_data_size = sizeof(VP9Context),
|
.priv_data_size = sizeof(VP9Context),
|
||||||
.init = vp9_decode_init,
|
.init = vp9_decode_init,
|
||||||
.decode = vp9_decode_packet,
|
.decode = vp9_decode_frame,
|
||||||
.flush = vp9_decode_flush,
|
.flush = vp9_decode_flush,
|
||||||
.close = vp9_decode_free,
|
.close = vp9_decode_free,
|
||||||
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
|
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
|
||||||
.init_thread_copy = vp9_decode_init,
|
.init_thread_copy = vp9_decode_init,
|
||||||
.update_thread_context = vp9_decode_update_thread_context,
|
.update_thread_context = vp9_decode_update_thread_context,
|
||||||
|
.bsfs = "vp9_superframe_split",
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user