[FFmpeg-devel] [PATCH 03/19] lavc: add a private cap for fake-delay encoders
Anton Khirnov
anton at khirnov.net
Wed Jan 25 18:55:21 EET 2023
Some encoders (ffv1, flac, adx) are marked with AV_CODEC_CAP_DELAY onky
in order to be flushed at the end, otherwise they behave as no-delay
encoders.
Add a capability to mark these encoders. Use it for setting pts
generically.
---
libavcodec/adxenc.c | 3 +--
libavcodec/codec_internal.h | 8 ++++++++
libavcodec/encode.c | 6 ++++--
libavcodec/ffv1enc.c | 4 +---
libavcodec/flacenc.c | 7 ++-----
libavcodec/tests/avcodec.c | 4 ++++
6 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c
index 153c91b852..6e12a58b16 100644
--- a/libavcodec/adxenc.c
+++ b/libavcodec/adxenc.c
@@ -183,8 +183,6 @@ static int adx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
dst += BLOCK_SIZE;
}
- avpkt->pts = frame->pts;
- avpkt->duration = frame->nb_samples;
*got_packet_ptr = 1;
return 0;
}
@@ -200,4 +198,5 @@ const FFCodec ff_adpcm_adx_encoder = {
FF_CODEC_ENCODE_CB(adx_encode_frame),
.p.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16,
AV_SAMPLE_FMT_NONE },
+ .caps_internal = FF_CODEC_CAP_EOF_FLUSH,
};
diff --git a/libavcodec/codec_internal.h b/libavcodec/codec_internal.h
index e3b77e6dea..130a7dc3cd 100644
--- a/libavcodec/codec_internal.h
+++ b/libavcodec/codec_internal.h
@@ -80,6 +80,14 @@
* Codec supports embedded ICC profiles (AV_FRAME_DATA_ICC_PROFILE).
*/
#define FF_CODEC_CAP_ICC_PROFILES (1 << 9)
+/**
+ * The encoder has AV_CODEC_CAP_DELAY set, but does not actually have delay - it
+ * only wants to be flushed at the end to update some context variables (e.g.
+ * 2pass stats) or produce a trailing packet. Besides that it immediately
+ * produces exactly one output packet per each input frame, just as no-delay
+ * encoders do.
+ */
+#define FF_CODEC_CAP_EOF_FLUSH (1 << 10)
/**
* FFCodec.codec_tags termination value
diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index fbe2c97cd6..e0b3e43840 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -211,7 +211,8 @@ int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
// set the timestamps for the simple no-delay case
// encoders with delay have to set the timestamps themselves
- if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) {
+ if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY) ||
+ (frame && (codec->caps_internal & FF_CODEC_CAP_EOF_FLUSH))) {
if (avpkt->pts == AV_NOPTS_VALUE)
avpkt->pts = frame->pts;
@@ -225,7 +226,8 @@ int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
// dts equals pts unless there is reordering
// there can be no reordering if there is no encoder delay
if (!(avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER) ||
- !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY))
+ !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY) ||
+ (codec->caps_internal & FF_CODEC_CAP_EOF_FLUSH))
avpkt->dts = avpkt->pts;
} else {
unref:
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 0237ac48eb..6649ec7e88 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -1231,8 +1231,6 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
f->picture_number++;
pkt->size = buf_p - pkt->data;
- pkt->pts =
- pkt->dts = pict->pts;
pkt->flags |= AV_PKT_FLAG_KEY * f->key_frame;
*got_packet = 1;
@@ -1301,5 +1299,5 @@ const FFCodec ff_ffv1_encoder = {
},
.p.priv_class = &ffv1_class,
- .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_EOF_FLUSH,
};
diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c
index 8aacc93e28..9a9835dfa6 100644
--- a/libavcodec/flacenc.c
+++ b/libavcodec/flacenc.c
@@ -1690,10 +1690,7 @@ static int flac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
if (out_bytes < s->min_framesize)
s->min_framesize = out_bytes;
- avpkt->pts = frame->pts;
- avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples);
-
- s->next_pts = avpkt->pts + avpkt->duration;
+ s->next_pts = frame->pts + ff_samples_to_time_base(avctx, frame->nb_samples);
av_shrink_packet(avpkt, out_bytes);
@@ -1766,5 +1763,5 @@ const FFCodec ff_flac_encoder = {
AV_SAMPLE_FMT_S32,
AV_SAMPLE_FMT_NONE },
.p.priv_class = &flac_encoder_class,
- .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
+ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_EOF_FLUSH,
};
diff --git a/libavcodec/tests/avcodec.c b/libavcodec/tests/avcodec.c
index 3288a85f64..4c1730425d 100644
--- a/libavcodec/tests/avcodec.c
+++ b/libavcodec/tests/avcodec.c
@@ -158,6 +158,10 @@ int main(void){
if (codec->capabilities & AV_CODEC_CAP_FRAME_THREADS &&
codec->capabilities & AV_CODEC_CAP_DELAY)
ERR("Frame-threaded encoder %s claims to have delay\n");
+
+ if (codec2->caps_internal & FF_CODEC_CAP_EOF_FLUSH &&
+ !(codec->capabilities & AV_CODEC_CAP_DELAY))
+ ERR("EOF_FLUSH encoder %s is not marked as having delay\n");
} else {
if ((codec->type == AVMEDIA_TYPE_SUBTITLE) != (codec2->cb_type == FF_CODEC_CB_TYPE_DECODE_SUB))
ERR("Subtitle decoder %s does not implement decode_sub callback\n");
--
2.35.1
More information about the ffmpeg-devel
mailing list