diff options
author | Philip Langdale <philipl@overt.org> | 2020-04-10 23:32:11 +0300 |
---|---|---|
committer | Philip Langdale <philipl@overt.org> | 2020-04-16 00:54:42 +0300 |
commit | 22b25b3ea5cf5e241e8dde5ddd107a3b1e6eb7a0 (patch) | |
tree | 2b785523fa8901d1a4412a67637a131c18e9c6bc /libavcodec/decode.c | |
parent | e6fb3aba42084cd6af3a417435c444ad872ce629 (diff) |
avcodec: Add explicit capability flag for encoder flushing
Previously, there was no way to flush an encoder such that after
draining, the encoder could be used again. We generally suggested
that clients teardown and replace the encoder instance in these
situations. However, for at least some hardware encoders, the cost of
this tear down/replace cycle is very high, which can get in the way of
some use-cases - for example: segmented encoding with nvenc.
To help address that use case, we added support for calling
avcodec_flush_buffers() to nvenc and things worked in practice,
although it was not clearly documented as to whether this should work
or not. There was only one previous example of an encoder implementing
the flush callback (audiotoolboxenc) and it's unclear if that was
intentional or not. However, it was clear that calling
avocdec_flush_buffers() on any other encoder would leave the encoder in
an undefined state, and that's not great.
As part of cleaning this up, this change introduces a formal capability
flag for encoders that support flushing and ensures a flush call is a
no-op for any other encoder. This allows client code to check if it is
meaningful to call flush on an encoder before actually doing it.
I have not attempted to separate the steps taken inside
avcodec_flush_buffers() because it's not doing anything that's wrong
for an encoder. But I did add a sanity check to reject attempts to
flush a frame threaded encoder because I couldn't wrap my head around
whether that code path was actually safe or not. As this combination
doesn't exist today, we'll deal with it if it ever comes up.
Diffstat (limited to 'libavcodec/decode.c')
-rw-r--r-- | libavcodec/decode.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/libavcodec/decode.c b/libavcodec/decode.c index b7ae1fbb84..d4bdb9b1c0 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -2084,6 +2084,21 @@ void avcodec_flush_buffers(AVCodecContext *avctx) { AVCodecInternal *avci = avctx->internal; + if (av_codec_is_encoder(avctx->codec)) { + int caps = avctx->codec->capabilities; + + if (!(caps & AV_CODEC_CAP_ENCODER_FLUSH)) { + // Only encoders that explicitly declare support for it can be + // flushed. Otherwise, this is a no-op. + av_log(avctx, AV_LOG_WARNING, "Ignoring attempt to flush encoder " + "that doesn't support it\n"); + return; + } + + // We haven't implemented flushing for frame-threaded encoders. + av_assert0(!(caps & AV_CODEC_CAP_FRAME_THREADS)); + } + avci->draining = 0; avci->draining_done = 0; avci->nb_draining_errors = 0; |