1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2026-06-19 19:03:00 +02:00

avcodec/encode: take into account priming samples in the last packet duration

The generic code was setting the last packet duration based on the input frame
while ignoring the fact the encoder may have output an initial padding amount
of samples in the first (e.g. 481 for mp2, 256 for AC3, etc).

Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
James Almer
2026-06-17 21:11:42 -03:00
parent 62731e05ab
commit dedb75a810
7 changed files with 62 additions and 37 deletions
+50 -25
View File
@@ -229,6 +229,53 @@ int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame)
return 0;
}
static int encode_set_packet_props(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame)
{
AVCodecInternal *avci = avctx->internal;
EncodeContext *ec = encode_ctx(avci);
if (avpkt->pts == AV_NOPTS_VALUE) {
avpkt->pts = frame->pts;
if (avctx->codec->type == AVMEDIA_TYPE_AUDIO && avpkt->pts != AV_NOPTS_VALUE)
avpkt->pts -= ff_samples_to_time_base(avctx, avctx->initial_padding);
}
if (!avpkt->duration) {
if (frame->duration)
avpkt->duration = frame->duration;
else if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
avpkt->duration = ff_samples_to_time_base(avctx,
frame->nb_samples);
}
if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
AVFrameSideData *frame_sd = av_frame_get_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES);
if (frame_sd && frame_sd->size >= 10) {
int skip_samples = AV_RL32(frame_sd->data + 0);
int discard_padding = AV_RL32(frame_sd->data + 4);
if (discard_padding > 0 && avctx->frame_size && ec->last_audio_frame) {
avpkt->duration = av_sat_add64(avpkt->duration, ff_samples_to_time_base(avctx, avctx->initial_padding));
avpkt->duration = FFMIN(avpkt->duration, ff_samples_to_time_base(avctx, avctx->frame_size));
discard_padding = avctx->frame_size - ff_samples_from_time_base(avctx, avpkt->duration);
}
if (skip_samples > 0 || discard_padding > 0) {
uint8_t *packet_sd = av_packet_new_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
if (!packet_sd)
return AVERROR(ENOMEM);
AV_WL32A(packet_sd + 0, skip_samples);
AV_WL32A(packet_sd + 4, discard_padding);
AV_WL8 (packet_sd + 8, AV_RB8(frame_sd->data + 8));
AV_WL8 (packet_sd + 9, AV_RB8(frame_sd->data + 9));
}
}
}
}
return 0;
}
int ff_encode_reordered_opaque(AVCodecContext *avctx,
AVPacket *pkt, const AVFrame *frame)
{
@@ -265,31 +312,9 @@ int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
// encoders with delay have to set the timestamps themselves
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;
if (!avpkt->duration) {
if (frame->duration)
avpkt->duration = frame->duration;
else if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
avpkt->duration = ff_samples_to_time_base(avctx,
frame->nb_samples);
}
if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
AVFrameSideData *sd = av_frame_get_side_data(frame, AV_FRAME_DATA_SKIP_SAMPLES);
if (sd && sd->size >= 10) {
uint8_t *skip_samples = av_packet_new_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
if (!skip_samples) {
ret = AVERROR(ENOMEM);
goto unref;
}
AV_WL32A(skip_samples + 0, AV_RL32(sd->data + 0));
AV_WL32A(skip_samples + 4, AV_RL32(sd->data + 4));
AV_WB8 (skip_samples + 8, AV_RB8 (sd->data + 8));
AV_WB8 (skip_samples + 9, AV_RB8 (sd->data + 9));
}
}
}
ret = encode_set_packet_props(avctx, avpkt, frame);
if (ret < 0)
goto unref;
ret = ff_encode_reordered_opaque(avctx, avpkt, frame);
if (ret < 0)
+1 -1
View File
@@ -1,4 +1,4 @@
c57662975b92b9403341271944e2645d *tests/data/fate/autorotate.mov
bb03affe94dfbe39c8cad8eb69dc367c *tests/data/fate/autorotate.mov
197366 tests/data/fate/autorotate.mov
#extradata 0: 34, 0x9d7d073f
#tb 0: 1/15360
+1 -1
View File
@@ -6,4 +6,4 @@
0, -256, -256, 1536, 416, 0x3001fb2d
0, 1280, 1280, 1536, 418, 0xba72fc16
0, 2816, 2816, 1536, 418, 0xba72fc16
0, 4352, 4352, 3, 418, 0xba72fc16, S=1, Skip Samples, 10, 0x06070102
0, 4352, 4352, 259, 418, 0xba72fc16, S=1, Skip Samples, 10, 0x06020101
+1 -1
View File
@@ -1,4 +1,4 @@
424865418175e7b42e77d4482fed91f1 *tests/data/fate/generic-tags-remux-asf.asf
b80387bd80ec592cb99df5de8ef60732 *tests/data/fate/generic-tags-remux-asf.asf
20596 tests/data/fate/generic-tags-remux-asf.asf
#extradata 0: 4, 0x00020001
#tb 0: 1/1000
+3 -3
View File
@@ -1,5 +1,5 @@
5febd4af0b197d8d0756fcaa99c066a2 *tests/data/fate/matroska-encoding-delay.matroska
961258 tests/data/fate/matroska-encoding-delay.matroska
e0a9bc2eff3a462c6664488d9126b1f0 *tests/data/fate/matroska-encoding-delay.matroska
961246 tests/data/fate/matroska-encoding-delay.matroska
#extradata 0: 22, 0x32ea0490
#tb 0: 1/1000
#media_type 0: video
@@ -21,7 +21,7 @@
1, 86, 86, 24, 1152, 0xc9e85398
1, 110, 110, 24, 1152, 0xda1287d3
0, 120, 120, 40, 238290, 0xbe18b18f
1, 134, 134, 16, 1152, 0x1c9a6102, S=1, Skip Samples, 10, 0x03050081
1, 134, 134, 24, 1152, 0x1c9a6102
[PACKET]
codec_type=audio
stream_index=1
+3 -3
View File
@@ -1,3 +1,3 @@
3d79de7fc1c67016e864b40cdb207ff7 *tests/data/lavf/lavf.mkv
320454 tests/data/lavf/lavf.mkv
tests/data/lavf/lavf.mkv CRC=0xb05f51a3
96857fc58eceb82a0dc2c38dadd7f70b *tests/data/lavf/lavf.mkv
320453 tests/data/lavf/lavf.mkv
tests/data/lavf/lavf.mkv CRC=0x5df3232f
+3 -3
View File
@@ -1,3 +1,3 @@
2d9ed072357227c31cb68534f7483a81 *tests/data/lavf/lavf.mkv_attachment
472604 tests/data/lavf/lavf.mkv_attachment
tests/data/lavf/lavf.mkv_attachment CRC=0xb05f51a3
96d4bab2f4ee95236480afbee2b64f77 *tests/data/lavf/lavf.mkv_attachment
472603 tests/data/lavf/lavf.mkv_attachment
tests/data/lavf/lavf.mkv_attachment CRC=0x5df3232f