PR #25728 opened by michaelni
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25728
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25728.patch


>From a12c6c1163872b8dd8f61002df67ab0a5d86acae Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Tue, 3 Nov 2026 19:28:53 +0100
Subject: [PATCH 1/3] avcodec/encode: derive the last packet's padding from the
 padded frame

Fixes: wrong skip samples side data and duration on the last packet
Testcase: ffmpeg -f lavfi -i "sine=r=48000,atrim=end_sample=85" -c:a dfpwm -f 
framecrc -
(discard padding of the last packet 4011 before, 3 after)
---
 libavcodec/encode.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index 82ea3aedbb4..9a161111e77 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -257,9 +257,11 @@ static int encode_set_packet_props(AVCodecContext *avctx, 
AVPacket *avpkt, const
                 int discard_padding = AV_RL32(frame_sd->data + 4);
 
                 if (discard_padding > 0 && avctx->frame_size && 
ec->last_audio_frame) {
+                    if (!frame->duration)
+                        avpkt->duration = ff_samples_to_time_base(avctx, 
frame->nb_samples - discard_padding);
                     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);
+                    avpkt->duration = FFMIN(avpkt->duration, 
ff_samples_to_time_base(avctx, frame->nb_samples));
+                    discard_padding = frame->nb_samples - 
ff_samples_from_time_base(avctx, avpkt->duration);
                 }
 
                 if (skip_samples > 0 || discard_padding > 0) {
-- 
2.54.0


>From f0d6874e4d65d091e9341aee211283227e2a3e22 Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Tue, 3 Nov 2026 19:28:53 +0100
Subject: [PATCH 2/3] avcodec/encode: pad to the frame size when a fixed frame
 size is requested

Fixes: AV_CODEC_FLAG2_FIXED_FRAME_SIZE ignored by encoders with pad_samples
Testcase: ffmpeg -f lavfi -i "sine=r=48000,atrim=end_sample=85" -ac 2 -c:a aptx 
-flags2 +fixed_frame_size -f framecrc -
---
 libavcodec/encode.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index 9a161111e77..179a6eb37df 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -509,7 +509,8 @@ static int encode_send_frame_internal(AVCodecContext 
*avctx, const AVFrame *src)
                 ec->last_audio_frame = 1;
                 if (!(avctx->codec->capabilities & 
AV_CODEC_CAP_SMALL_LAST_FRAME) ||
                     (avctx->flags2 & AV_CODEC_FLAG2_FIXED_FRAME_SIZE)) {
-                    int pad_samples = avci->pad_samples ? avci->pad_samples : 
avctx->frame_size;
+                    int pad_samples = avci->pad_samples && !(avctx->flags2 & 
AV_CODEC_FLAG2_FIXED_FRAME_SIZE) ?
+                                      avci->pad_samples : avctx->frame_size;
                     int out_samples = (src->nb_samples + pad_samples - 1) / 
pad_samples * pad_samples;
 
                     if (out_samples != src->nb_samples) {
-- 
2.54.0


>From c163a50935e0ad637841beddb09f1bb64c897d3b Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <[email protected]>
Date: Tue, 3 Nov 2026 19:28:53 +0100
Subject: [PATCH 3/3] avcodec/pcm-dvdenc: pad the last frame to a whole block

The FATE test encodes 85 samples with and without a fixed frame size.

Fixes: up to 3 samples dropped at the end of a 24 bit stream
Testcase: ffmpeg -f lavfi -i "sine=r=48000,atrim=end_sample=85" -c:a pcm_dvd 
-sample_fmt s32 -f framecrc -
---
 libavcodec/pcm-dvdenc.c           |  5 +++--
 tests/fate/pcm.mak                |  4 ++++
 tests/ref/fate/pcm-dvd-last-block | 12 ++++++++++++
 3 files changed, 19 insertions(+), 2 deletions(-)
 create mode 100644 tests/ref/fate/pcm-dvd-last-block

diff --git a/libavcodec/pcm-dvdenc.c b/libavcodec/pcm-dvdenc.c
index 4904eea4ca5..c7400582829 100644
--- a/libavcodec/pcm-dvdenc.c
+++ b/libavcodec/pcm-dvdenc.c
@@ -25,6 +25,7 @@
 #include "bytestream.h"
 #include "codec_internal.h"
 #include "encode.h"
+#include "internal.h"
 
 typedef struct PCMDVDContext {
     uint8_t header[3];       // Header added to every frame
@@ -107,6 +108,7 @@ static av_cold int pcm_dvd_encode_init(AVCodecContext 
*avctx)
     s->header[2] = 0x80;
 
     avctx->frame_size = frame_size;
+    avctx->internal->pad_samples = s->samples_per_block;
 
     return 0;
 }
@@ -176,8 +178,7 @@ const FFCodec ff_pcm_dvd_encoder = {
     CODEC_LONG_NAME("PCM signed 16|20|24-bit big-endian for DVD-Video media"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_PCM_DVD,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME |
-                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(PCMDVDContext),
     .init           = pcm_dvd_encode_init,
     FF_CODEC_ENCODE_CB(pcm_dvd_encode_frame),
diff --git a/tests/fate/pcm.mak b/tests/fate/pcm.mak
index 60462444917..4989e2bd713 100644
--- a/tests/fate/pcm.mak
+++ b/tests/fate/pcm.mak
@@ -62,6 +62,10 @@ FATE_PCM-$(call TRANSCODE, PCM_DVD, MPEG2VOB MPEGPS, 
WAV_DEMUXER PCM_S16LE_DECOD
 fate-pcm_dvd-16-1-96000: tests/data/asynth-96000-1.wav
 fate-pcm_dvd-16-1-96000: CMD = transcode wav 
$(TARGET_PATH)/tests/data/asynth-96000-1.wav vob "-c:a pcm_dvd" "-t 0.2"
 
+FATE_PCM-$(call ALLYES, PCM_DVD_ENCODER LAVFI_INDEV SINE_FILTER ATRIM_FILTER 
ARESAMPLE_FILTER \
+                       PCM_S16$(if $(filter 
yes,$(HAVE_BIGENDIAN)),BE,LE)_DECODER FRAMECRC_MUXER PIPE_PROTOCOL) += 
fate-pcm-dvd-last-block
+fate-pcm-dvd-last-block: CMD = framecrc -auto_conversion_filters -f lavfi -i 
"sine=r=48000,atrim=end_sample=85" -c:a pcm_dvd -sample_fmt s32 -map 0:a -map 
0:a -flags2:a:1 +fixed_frame_size
+
 # PCM Blu-ray encoder/decoder roundtrip tests (s16, locally generated sources)
 FATE_PCM_BLURAY_S16 = fate-pcm-bluray-s16-mono                                \
                       fate-pcm-bluray-s16-stereo                               
\
diff --git a/tests/ref/fate/pcm-dvd-last-block 
b/tests/ref/fate/pcm-dvd-last-block
new file mode 100644
index 00000000000..92d75383a7e
--- /dev/null
+++ b/tests/ref/fate/pcm-dvd-last-block
@@ -0,0 +1,12 @@
+#tb 0: 1/48000
+#media_type 0: audio
+#codec_id 0: pcm_dvd
+#sample_rate 0: 48000
+#channel_layout_name 0: mono
+#tb 1: 1/48000
+#media_type 1: audio
+#codec_id 1: pcm_dvd
+#sample_rate 1: 48000
+#channel_layout_name 1: mono
+0,          0,          0,       85,      267, 0x7f3a49be, S=1, Skip Samples,  
     10, 0x00120003
+1,          0,          0,       85,      507, 0xa56549be, S=1, Skip Samples,  
     10, 0x01f20053
-- 
2.54.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to