lavc: add a private cap for fake-delay encoders

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.
release/6.0
Anton Khirnov 2 years ago
parent e5e29eda5a
commit d0c8ca961d
  1. 3
      libavcodec/adxenc.c
  2. 8
      libavcodec/codec_internal.h
  3. 6
      libavcodec/encode.c
  4. 4
      libavcodec/ffv1enc.c
  5. 7
      libavcodec/flacenc.c
  6. 4
      libavcodec/tests/avcodec.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,
};

@ -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

@ -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:

@ -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,
};

@ -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,
};

@ -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");

Loading…
Cancel
Save