1
0
mirror of https://git.ffmpeg.org/ffmpeg.git synced 2026-10-24 02:09:03 +03:00

avcodec/audio_frame_queue: add skip samples side data to output packets

Instead of reimplementing the same code on every afq user, just do it here.

Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
James Almer
2026-07-05 11:12:01 -03:00
parent 87bcbbff57
commit c31a781412
25 changed files with 88 additions and 136 deletions

View File

@@ -1412,17 +1412,9 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
s->lambda_sum += (s->nmr && s->nmr->lam_rc > 0.0f) ? s->nmr->lam_rc : s->lambda;
s->lambda_count++;
ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
&avpkt->duration);
int discard_padding = avctx->frame_size - ff_samples_from_time_base(avctx, avpkt->duration);
if (discard_padding > 0) {
uint8_t *side_data =
av_packet_new_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
if (!side_data)
return AVERROR(ENOMEM);
AV_WL32(side_data + 4, discard_padding);
}
ret = ff_af_queue_remove(&s->afq, avctx->frame_size, avpkt);
if (ret < 0)
return ret;
avpkt->flags |= AV_PKT_FLAG_KEY;

View File

@@ -1982,7 +1982,6 @@ int ff_ac3_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr)
{
AC3EncodeContext *const s = avctx->priv_data;
int discard_padding;
int ret;
/* add current frame to queue */
@@ -2025,17 +2024,9 @@ int ff_ac3_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
return ret;
ac3_output_frame(s, avpkt->data);
ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
&avpkt->duration);
discard_padding = avctx->frame_size - ff_samples_from_time_base(avctx, avpkt->duration);
if (discard_padding > 0) {
uint8_t *side_data =
av_packet_new_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
if (!side_data)
return AVERROR(ENOMEM);
AV_WL32(side_data + 4, discard_padding);
}
ret = ff_af_queue_remove(&s->afq, avctx->frame_size, avpkt);
if (ret < 0)
return ret;
*got_packet_ptr = 1;
return 0;

View File

@@ -240,7 +240,10 @@ static int aptx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
aptx_encode_samples(s, samples, avpkt->data + pos);
}
ff_af_queue_remove(&s0->afq, frame->nb_samples, &avpkt->pts, &avpkt->duration);
ret = ff_af_queue_remove(&s0->afq, frame->nb_samples, avpkt);
if (ret < 0)
return ret;
*got_packet_ptr = 1;
return 0;
}

View File

@@ -31,6 +31,7 @@ av_cold void ff_af_queue_init(AVCodecContext *avctx, AudioFrameQueue *afq)
afq->avctx = avctx;
afq->remaining_delay = avctx->initial_padding;
afq->remaining_samples = avctx->initial_padding;
afq->output_delay = avctx->initial_padding;
afq->frame_count = 0;
}
@@ -83,10 +84,10 @@ int ff_af_queue_add(AudioFrameQueue *afq, const AVFrame *f)
return 0;
}
void ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, int64_t *pts,
int64_t *duration)
int ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, AVPacket *pkt)
{
int64_t out_pts = AV_NOPTS_VALUE;
int frame_size = nb_samples;
int removed_samples = 0;
int i;
@@ -96,8 +97,8 @@ void ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, int64_t *pts,
}
if(!afq->frame_count)
av_log(afq->avctx, AV_LOG_WARNING, "Trying to remove %d samples, but the queue is empty\n", nb_samples);
if (pts)
*pts = ff_samples_to_time_base(afq->avctx, out_pts);
if (pkt)
pkt->pts = ff_samples_to_time_base(afq->avctx, out_pts);
for(i=0; nb_samples && i<afq->frame_count; i++){
int n= FFMIN(afq->frames[i].duration, nb_samples);
@@ -119,6 +120,22 @@ void ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, int64_t *pts,
afq->frames[0].pts += nb_samples;
av_log(afq->avctx, AV_LOG_DEBUG, "Trying to remove %d more samples than there are in the queue\n", nb_samples);
}
if (duration)
*duration = ff_samples_to_time_base(afq->avctx, removed_samples);
if (pkt) {
int discard_padding = frame_size - removed_samples;
pkt->duration = ff_samples_to_time_base(afq->avctx, removed_samples);
if (afq->output_delay > 0 || discard_padding > 0) {
uint8_t *side_data =
av_packet_new_side_data(pkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
if (!side_data)
return AVERROR(ENOMEM);
if (afq->output_delay) {
AV_WL32(side_data, FFMIN(afq->output_delay, removed_samples));
afq->output_delay -= removed_samples;
afq->output_delay = FFMAX(afq->output_delay, 0);
}
AV_WL32(side_data + 4, discard_padding);
}
}
return 0;
}

View File

@@ -31,6 +31,7 @@ typedef struct AudioFrame {
typedef struct AudioFrameQueue {
AVCodecContext *avctx;
int output_delay;
int remaining_delay;
int remaining_samples;
AudioFrame *frames;
@@ -74,10 +75,9 @@ int ff_af_queue_add(AudioFrameQueue *afq, const AVFrame *f);
*
* @param afq queue context
* @param nb_samples number of samples to remove from the queue
* @param[out] pts output packet pts
* @param[out] duration output packet duration
* @param[out] pkt output packet
* @return 0 on success, negative AVERROR code on failure
*/
void ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, int64_t *pts,
int64_t *duration);
int ff_af_queue_remove(AudioFrameQueue *afq, int nb_samples, AVPacket *pkt);
#endif /* AVCODEC_AUDIO_FRAME_QUEUE_H */

View File

@@ -571,11 +571,12 @@ static int ffat_encode(AVCodecContext *avctx, AVPacket *avpkt,
if ((!ret || ret == 1) && *got_packet_ptr) {
avpkt->size = out_buffers.mBuffers[0].mDataByteSize;
ff_af_queue_remove(&at->afq, out_pkt_desc.mVariableFramesInPacket ?
int ret = ff_af_queue_remove(&at->afq, out_pkt_desc.mVariableFramesInPacket ?
out_pkt_desc.mVariableFramesInPacket :
avctx->frame_size,
&avpkt->pts,
&avpkt->duration);
avpkt);
if (ret < 0)
return ret;
avpkt->flags |= AV_PKT_FLAG_KEY;
} else if (ret && ret != 1) {
av_log(avctx, AV_LOG_ERROR, "Encode error: %i\n", ret);

View File

@@ -141,7 +141,6 @@ static void aac_encode_flush(AVCodecContext *avctx)
AACENC_BufDesc in_buf = { 0 }, out_buf = { 0 };
AACENC_InArgs in_args = { 0 };
AACENC_OutArgs out_args;
int64_t pts, duration;
uint8_t dummy_in[1], dummy_out[1];
int in_buffer_identifiers[] = { IN_AUDIO_DATA, IN_METADATA_SETUP };
int in_buffer_element_sizes[] = { 2, sizeof(AACENC_MetaData) };
@@ -152,7 +151,7 @@ static void aac_encode_flush(AVCodecContext *avctx)
void *out_ptr = dummy_out;
AACENC_ERROR err;
ff_af_queue_remove(&s->afq, s->afq.frame_count, &pts, &duration);
ff_af_queue_remove(&s->afq, s->afq.frame_count, NULL);
in_buf.bufs = (void **)inBuffer;
in_buf.numBufs = s->metadata_mode == 0 ? 1 : 2;
@@ -468,7 +467,7 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
int out_buffer_identifier = OUT_BITSTREAM_DATA;
int out_buffer_size, out_buffer_element_size;
void *out_ptr;
int ret, discard_padding;
int ret;
uint8_t dummy_buf[1];
AACENC_ERROR err;
@@ -528,28 +527,9 @@ static int aac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
return 0;
/* Get the next frame pts & duration */
ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
&avpkt->duration);
discard_padding = avctx->frame_size - ff_samples_from_time_base(avctx, avpkt->duration);
// Check if subtraction resulted in an overflow
if ((discard_padding < avctx->frame_size) != (avpkt->duration > 0)) {
av_log(avctx, AV_LOG_ERROR, "discard padding overflow\n");
return AVERROR(EINVAL);
}
if (s->delay > 0 || discard_padding > 0) {
uint8_t *side_data =
av_packet_new_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, 10);
if (!side_data)
return AVERROR(ENOMEM);
if (s->delay) {
AV_WL32(side_data, FFMIN(s->delay, ff_samples_from_time_base(avctx, avpkt->duration)));
s->delay -= ff_samples_from_time_base(avctx, avpkt->duration);
s->delay = FFMAX(s->delay, 0);
}
AV_WL32(side_data + 4, discard_padding);
}
ret = ff_af_queue_remove(&s->afq, avctx->frame_size, avpkt);
if (ret < 0)
return ret;
avpkt->size = out_args.numOutBytes;
avpkt->flags |= AV_PKT_FLAG_KEY;

View File

@@ -201,7 +201,7 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
{
LAMEContext *s = avctx->priv_data;
MPADecodeHeader hdr;
int len, ret, ch, discard_padding;
int len, ret, ch;
int lame_result;
uint32_t h;
@@ -282,27 +282,9 @@ static int mp3lame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
memmove(s->buffer, s->buffer + len, s->buffer_index);
/* Get the next frame pts/duration */
ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
&avpkt->duration);
discard_padding = avctx->frame_size - ff_samples_from_time_base(avctx, avpkt->duration);
// Check if subtraction resulted in an overflow
if ((discard_padding < avctx->frame_size) != (avpkt->duration > 0)) {
av_log(avctx, AV_LOG_ERROR, "discard padding overflow\n");
return AVERROR(EINVAL);
}
if ((!s->delay_sent && avctx->initial_padding > 0) || discard_padding > 0) {
uint8_t* side_data = av_packet_new_side_data(avpkt,
AV_PKT_DATA_SKIP_SAMPLES,
10);
if (!side_data)
return AVERROR(ENOMEM);
if (!s->delay_sent) {
AV_WL32(side_data, avctx->initial_padding);
s->delay_sent = 1;
}
AV_WL32(side_data + 4, discard_padding);
}
ret = ff_af_queue_remove(&s->afq, avctx->frame_size, avpkt);
if (ret < 0)
return ret;
*got_packet_ptr = 1;
}

View File

@@ -281,8 +281,9 @@ static int amr_nb_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
written, s->enc_mode, avpkt->data[0]);
/* Get the next frame pts/duration */
ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
&avpkt->duration);
ret = ff_af_queue_remove(&s->afq, avctx->frame_size, avpkt);
if (ret < 0)
return ret;
avpkt->size = written;
*got_packet_ptr = 1;

View File

@@ -471,7 +471,6 @@ static int libopus_encode(AVCodecContext *avctx, AVPacket *avpkt,
const int sample_size = channels * bytes_per_sample;
const uint8_t *audio;
int ret;
int discard_padding;
if (frame) {
ret = ff_af_queue_add(&opus->afq, frame);
@@ -517,21 +516,9 @@ static int libopus_encode(AVCodecContext *avctx, AVPacket *avpkt,
av_shrink_packet(avpkt, ret);
ff_af_queue_remove(&opus->afq, opus->opts.packet_size,
&avpkt->pts, &avpkt->duration);
discard_padding = opus->opts.packet_size - ff_samples_from_time_base(avctx, avpkt->duration);
// Check if subtraction resulted in an overflow
if ((discard_padding < opus->opts.packet_size) != (avpkt->duration > 0))
return AVERROR(EINVAL);
if (discard_padding > 0) {
uint8_t* side_data = av_packet_new_side_data(avpkt,
AV_PKT_DATA_SKIP_SAMPLES,
10);
if (!side_data)
return AVERROR(ENOMEM);
AV_WL32(side_data + 4, discard_padding);
}
ret = ff_af_queue_remove(&opus->afq, opus->opts.packet_size, avpkt);
if (ret < 0)
return ret;
*got_packet_ptr = 1;

View File

@@ -105,8 +105,9 @@ static int libshine_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
s->buffer_index -= len;
memmove(s->buffer, s->buffer + len, s->buffer_index);
ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
&avpkt->duration);
ret = ff_af_queue_remove(&s->afq, avctx->frame_size, avpkt);
if (ret < 0)
return ret;
*got_packet_ptr = 1;
}

View File

@@ -296,8 +296,10 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
speex_bits_reset(&s->bits);
/* Get the next frame pts/duration */
ff_af_queue_remove(&s->afq, s->frames_per_packet * avctx->frame_size,
&avpkt->pts, &avpkt->duration);
ret = ff_af_queue_remove(&s->afq, s->frames_per_packet * avctx->frame_size,
avpkt);
if (ret < 0)
return ret;
avpkt->size = ret;
*got_packet_ptr = 1;

View File

@@ -415,19 +415,9 @@ static int libvorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
duration = av_vorbis_parse_frame(&s->vp, avpkt->data, avpkt->size);
if (duration > 0) {
int discard_padding;
ff_af_queue_remove(&s->afq, duration, &avpkt->pts, &avpkt->duration);
discard_padding = duration - ff_samples_from_time_base(avctx, avpkt->duration);
if (discard_padding > 0) {
uint8_t *side_data = av_packet_new_side_data(avpkt,
AV_PKT_DATA_SKIP_SAMPLES,
10);
if (!side_data)
return AVERROR(ENOMEM);
AV_WL32(side_data + 4, discard_padding);
}
ret = ff_af_queue_remove(&s->afq, duration, avpkt);
if (ret < 0)
return ret;
}
*got_packet_ptr = 1;

View File

@@ -2241,10 +2241,9 @@ input_and_return:
avctx->frame_num++;
if (bytes_written > 0) {
ff_af_queue_remove(&ctx->afq,
FFMIN(avctx->frame_size, ctx->afq.remaining_samples),
&avpkt->pts,
&avpkt->duration);
ret = ff_af_queue_remove(&ctx->afq, avctx->frame_size, avpkt);
if (ret < 0)
return ret;
av_shrink_packet(avpkt, bytes_written);

View File

@@ -409,8 +409,9 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
encode_block(s, avpkt->data, avpkt->size);
/* Get the next frame pts/duration */
ff_af_queue_remove(&s->afq, avctx->frame_size, &avpkt->pts,
&avpkt->duration);
ret = ff_af_queue_remove(&s->afq, avctx->frame_size, avpkt);
if (ret < 0)
return ret;
*got_packet_ptr = 1;
return 0;

View File

@@ -611,7 +611,9 @@ static int opus_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
ff_opus_psy_postencode_update(&s->psyctx, s->frame);
/* Remove samples from queue and skip if needed */
ff_af_queue_remove(&s->afq, s->packet.frames*frame_size, &avpkt->pts, &avpkt->duration);
ret = ff_af_queue_remove(&s->afq, s->packet.frames*frame_size, avpkt);
if (ret < 0)
return ret;
discard_padding = s->packet.frames*frame_size - ff_samples_from_time_base(avctx, avpkt->duration);
if (discard_padding > 0) {

View File

@@ -527,8 +527,9 @@ static int ra144_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
(NBLOCKS * BLOCKSIZE - i) * sizeof(*ractx->curr_block));
/* Get the next frame pts/duration */
ff_af_queue_remove(&ractx->afq, avctx->frame_size, &avpkt->pts,
&avpkt->duration);
ret = ff_af_queue_remove(&ractx->afq, avctx->frame_size, avpkt);
if (ret < 0)
return ret;
*got_packet_ptr = 1;
return 0;

View File

@@ -1196,7 +1196,9 @@ static int vorbis_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
flush_put_bits(&pb);
avpkt->size = put_bytes_output(&pb);
ff_af_queue_remove(&venc->afq, frame_size, &avpkt->pts, &avpkt->duration);
ret = ff_af_queue_remove(&venc->afq, frame_size, avpkt);
if (ret < 0)
return ret;
if (frame_size > avpkt->duration) {
uint8_t *side = av_packet_new_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, 10);

View File

@@ -3,7 +3,7 @@
#codec_id 0: ac3
#sample_rate 0: 44100
#channel_layout_name 0: 5.1(side)
0, -256, -256, 1536, 1114, 0x32fd276c
0, -256, -256, 1536, 1114, 0x32fd276c, S=1, Skip Samples, 10, 0x00090001
0, 1280, 1280, 1536, 1116, 0x1ac63ba7
0, 2816, 2816, 1536, 1114, 0xdde82dbc
0, 4352, 4352, 1536, 1114, 0x39313179

View File

@@ -3,7 +3,7 @@
#codec_id 0: ac3
#sample_rate 0: 44100
#channel_layout_name 0: 5.1
0, -256, -256, 1536, 1114, 0x89963331
0, -256, -256, 1536, 1114, 0x89963331, S=1, Skip Samples, 10, 0x00090001
0, 1280, 1280, 1536, 1116, 0x9eda26ff
0, 2816, 2816, 1536, 1114, 0x0734390b
0, 4352, 4352, 1536, 1114, 0xa6e33728

View File

@@ -13,7 +13,7 @@
#sample_rate 1: 44100
#channel_layout_name 1: mono
#stream#, dts, pts, duration, size, hash
1, -256, -256, 1536, 416, 180f042a77b9500f9a002cafd2f670a2
1, -256, -256, 1536, 416, 180f042a77b9500f9a002cafd2f670a2, S=1, 10, 4bce5775f7be5f45922731da9a33b4f3
0, 0, 0, 2048, 8719, bbea2a7487d61d39a0b2f2fe62a4df4a
1, 1280, 1280, 1536, 418, 77effcb2892958193be38a788328616b
0, 2048, 2048, 2048, 975, 94f30e410595452ee981d96224516504

View File

@@ -13,7 +13,7 @@
#sample_rate 1: 44100
#channel_layout_name 1: mono
#stream#, dts, pts, duration, size, hash
1, -256, -256, 1536, 416, 180f042a77b9500f9a002cafd2f670a2
1, -256, -256, 1536, 416, 180f042a77b9500f9a002cafd2f670a2, S=1, 10, 4bce5775f7be5f45922731da9a33b4f3
0, 0, 0, 2048, 8719, bbea2a7487d61d39a0b2f2fe62a4df4a
1, 1280, 1280, 1536, 418, 77effcb2892958193be38a788328616b
0, 2048, 2048, 2048, 975, 94f30e410595452ee981d96224516504

View File

@@ -3,7 +3,7 @@
#codec_id 0: ac3
#sample_rate 0: 44100
#channel_layout_name 0: mono
0, -256, -256, 1536, 416, 0x3001fb2d
0, -256, -256, 1536, 416, 0x3001fb2d, S=1, Skip Samples, 10, 0x00090001
0, 1280, 1280, 1536, 418, 0xba72fc16
0, 2816, 2816, 1536, 418, 0xba72fc16
0, 4352, 4352, 259, 418, 0xba72fc16, S=1, Skip Samples, 10, 0x06020101

View File

@@ -4,5 +4,5 @@
#codec_id 0: opus
#sample_rate 0: 48000
#channel_layout_name 0: stereo
0, -120, -120, 960, 1, 0x00fc00fc
0, -120, -120, 960, 1, 0x00fc00fc, S=1, Skip Samples, 10, 0x04b00078
0, 840, 840, 168, 1, 0x00fc00fc, S=1, Skip Samples, 10, 0x009f001b

View File

@@ -8,7 +8,7 @@
#codec_id 1: ac3
#sample_rate 1: 44100
#channel_layout_name 1: mono
1, -256, -256, 1536, 416, 0xcedecce4
1, -256, -256, 1536, 416, 0xcedecce4, S=1, Skip Samples, 10, 0x00090001
0, 0, 0, 1, 27867, 0x1426a0d6, S=1, Quality stats, 8, 0x050000a1
1, 1280, 1280, 1536, 418, 0x4ebabf82
0, 1, 1, 1, 9806, 0xbebc2826, F=0x0, S=1, Quality stats, 8, 0x050400a2