mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2026-08-09 09:32:43 +00:00
avcodec/ac3enc: drain the buffered samples at the end of encoding
When encoding a stream with an amount of samples multiple of a block, the last the last 256 samples would be lost as the encoders were not marked as AV_CODEC_CAP_DELAY. This can be easily reproduced with: ffmpeg -f lavfi -i sine -ac 2 -af atrim=start_sample=0:end_sample=4608 -c:a eac3 -f framecrc - Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
@@ -1982,8 +1982,19 @@ 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 */
|
||||
if (frame) {
|
||||
ret = ff_af_queue_add(&s->afq, frame);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
if (!s->afq.remaining_samples || (!s->afq.frame_alloc && !s->afq.frame_count))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->options.allow_per_frame_metadata) {
|
||||
ret = ac3_validate_metadata(s);
|
||||
if (ret)
|
||||
@@ -1993,7 +2004,7 @@ int ff_ac3_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
|
||||
if (s->bit_alloc.sr_code == 1 || s->eac3)
|
||||
ac3_adjust_frame_size(s);
|
||||
|
||||
s->encode_frame(s, frame->extended_data);
|
||||
s->encode_frame(s, frame);
|
||||
|
||||
ac3_apply_rematrixing(s);
|
||||
|
||||
@@ -2014,8 +2025,17 @@ int ff_ac3_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
|
||||
return ret;
|
||||
ac3_output_frame(s, avpkt->data);
|
||||
|
||||
if (frame->pts != AV_NOPTS_VALUE)
|
||||
avpkt->pts = frame->pts - ff_samples_to_time_base(avctx, avctx->initial_padding);
|
||||
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);
|
||||
}
|
||||
|
||||
*got_packet_ptr = 1;
|
||||
return 0;
|
||||
@@ -2157,6 +2177,7 @@ av_cold int ff_ac3_encode_close(AVCodecContext *avctx)
|
||||
|
||||
for (int ch = 0; ch < s->channels; ch++)
|
||||
av_freep(&s->planar_samples[ch]);
|
||||
av_freep(&s->input_samples[0]);
|
||||
av_freep(&s->bap_buffer);
|
||||
av_freep(&s->bap1_buffer);
|
||||
av_freep(&s->mdct_coef_buffer);
|
||||
@@ -2170,6 +2191,7 @@ av_cold int ff_ac3_encode_close(AVCodecContext *avctx)
|
||||
av_freep(&s->cpl_coord_buffer);
|
||||
av_freep(&s->fdsp);
|
||||
|
||||
ff_af_queue_close(&s->afq);
|
||||
av_tx_uninit(&s->tx);
|
||||
|
||||
return 0;
|
||||
@@ -2419,6 +2441,11 @@ static av_cold int allocate_buffers(AC3EncodeContext *s)
|
||||
if (!s->planar_samples[ch])
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
int ret = av_samples_alloc(s->input_samples, NULL, s->channels,
|
||||
AC3_BLOCK_SIZE * s->num_blocks,
|
||||
s->avctx->sample_fmt, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!FF_ALLOC_TYPED_ARRAY(s->bap_buffer, total_coefs) ||
|
||||
!FF_ALLOC_TYPED_ARRAY(s->bap1_buffer, total_coefs) ||
|
||||
@@ -2516,6 +2543,8 @@ av_cold int ff_ac3_encode_init(AVCodecContext *avctx)
|
||||
|
||||
dprint_options(s);
|
||||
|
||||
ff_af_queue_init(avctx, &s->afq);
|
||||
|
||||
ff_thread_once(&init_static_once, exponent_init);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "ac3.h"
|
||||
#include "ac3defs.h"
|
||||
#include "ac3dsp.h"
|
||||
#include "audio_frame_queue.h"
|
||||
#include "avcodec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "mathops.h"
|
||||
@@ -233,6 +234,7 @@ typedef struct AC3EncodeContext {
|
||||
int exponent_bits; ///< number of bits used for exponents
|
||||
|
||||
uint8_t *planar_samples[AC3_MAX_CHANNELS - 1];
|
||||
uint8_t *input_samples[AC3_MAX_CHANNELS - 1];
|
||||
uint8_t *bap_buffer;
|
||||
uint8_t *bap1_buffer;
|
||||
CoefType *mdct_coef_buffer;
|
||||
@@ -252,8 +254,10 @@ typedef struct AC3EncodeContext {
|
||||
uint8_t *ref_bap [AC3_MAX_CHANNELS][AC3_MAX_BLOCKS]; ///< bit allocation pointers (bap)
|
||||
int ref_bap_set; ///< indicates if ref_bap pointers have been set
|
||||
|
||||
AudioFrameQueue afq;
|
||||
|
||||
/** fixed vs. float function pointers */
|
||||
void (*encode_frame)(struct AC3EncodeContext *s, uint8_t * const *samples);
|
||||
void (*encode_frame)(struct AC3EncodeContext *s, const AVFrame *frame);
|
||||
|
||||
/* AC-3 vs. E-AC-3 function pointers */
|
||||
void (*output_frame_header)(struct AC3EncodeContext *s, struct PutBitContext *pb);
|
||||
|
||||
@@ -114,7 +114,8 @@ const FFCodec ff_ac3_fixed_encoder = {
|
||||
CODEC_LONG_NAME("ATSC A/52A (AC-3)"),
|
||||
.p.type = AVMEDIA_TYPE_AUDIO,
|
||||
.p.id = AV_CODEC_ID_AC3,
|
||||
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
|
||||
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
|
||||
AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
|
||||
.priv_data_size = sizeof(AC3EncodeContext),
|
||||
.init = ac3_fixed_encode_init,
|
||||
FF_CODEC_ENCODE_CB(ff_ac3_encode_frame),
|
||||
|
||||
@@ -116,7 +116,8 @@ const FFCodec ff_ac3_encoder = {
|
||||
CODEC_LONG_NAME("ATSC A/52A (AC-3)"),
|
||||
.p.type = AVMEDIA_TYPE_AUDIO,
|
||||
.p.id = AV_CODEC_ID_AC3,
|
||||
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
|
||||
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
|
||||
AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
|
||||
.priv_data_size = sizeof(AC3EncodeContext),
|
||||
.init = ff_ac3_float_encode_init,
|
||||
FF_CODEC_ENCODE_CB(ff_ac3_encode_frame),
|
||||
|
||||
@@ -346,9 +346,31 @@ static void compute_rematrixing_strategy(AC3EncodeContext *s)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void encode_frame(AC3EncodeContext *s, uint8_t * const *samples)
|
||||
static void copy_input_samples(AC3EncodeContext *s, const AVFrame *frame)
|
||||
{
|
||||
int end = frame ? frame->nb_samples : 0;
|
||||
|
||||
/* copy new samples and zero any remaining samples */
|
||||
if (frame) {
|
||||
av_samples_copy(s->input_samples, frame->extended_data, 0, 0,
|
||||
frame->nb_samples, s->channels,
|
||||
s->avctx->sample_fmt);
|
||||
}
|
||||
av_samples_set_silence(s->input_samples, end,
|
||||
s->avctx->frame_size - end,
|
||||
s->channels, s->avctx->sample_fmt);
|
||||
}
|
||||
|
||||
static void encode_frame(AC3EncodeContext *s, const AVFrame *frame)
|
||||
{
|
||||
uint8_t **samples;
|
||||
|
||||
if (!frame || frame->nb_samples < s->avctx->frame_size) {
|
||||
copy_input_samples(s, frame);
|
||||
samples = s->input_samples;
|
||||
} else
|
||||
samples = frame->extended_data;
|
||||
|
||||
apply_mdct(s, samples);
|
||||
|
||||
s->cpl_on = s->cpl_enabled;
|
||||
|
||||
@@ -270,7 +270,8 @@ const FFCodec ff_eac3_encoder = {
|
||||
CODEC_LONG_NAME("ATSC A/52 E-AC-3"),
|
||||
.p.type = AVMEDIA_TYPE_AUDIO,
|
||||
.p.id = AV_CODEC_ID_EAC3,
|
||||
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
|
||||
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
|
||||
AV_CODEC_CAP_SMALL_LAST_FRAME | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
|
||||
.priv_data_size = sizeof(AC3EncodeContext),
|
||||
.init = eac3_encode_init,
|
||||
FF_CODEC_ENCODE_CB(ff_ac3_encode_frame),
|
||||
|
||||
@@ -68,18 +68,14 @@ $(FATE_AC3) $(FATE_EAC3): CMP = oneoff
|
||||
FATE_AC3-$(call PCM, AC3, AC3 AC3_FIXED, PCM_S16LE_MUXER ARESAMPLE_FILTER) += $(FATE_AC3)
|
||||
FATE_EAC3-$(call PCM, EAC3, EAC3, PCM_S16LE_MUXER ARESAMPLE_FILTER) += $(FATE_EAC3)
|
||||
|
||||
FATE_AC3-$(call ENCDEC, AC3, AC3, WAV_MUXER WAV_DEMUXER ARESAMPLE_FILTER PCM_S16LE_ENCODER PIPE_PROTOCOL) += fate-ac3-encode
|
||||
fate-ac3-encode: CMD = enc_dec_pcm ac3 wav s16le $(subst $(SAMPLES),$(TARGET_SAMPLES),$(REF)) -c:a ac3 -b:a 128k
|
||||
fate-ac3-encode: CMP_SHIFT = -1024
|
||||
FATE_AC3-$(call ENCDEC, AC3, MP4 MOV, WAV_MUXER WAV_DEMUXER ARESAMPLE_FILTER PCM_S16LE_ENCODER PIPE_PROTOCOL) += fate-ac3-encode
|
||||
fate-ac3-encode: CMD = enc_dec_pcm mp4 wav s16le $(subst $(SAMPLES),$(TARGET_SAMPLES),$(REF)) -c:a ac3 -b:a 128k
|
||||
fate-ac3-encode: CMP_TARGET = 404.53
|
||||
fate-ac3-encode: SIZE_TOLERANCE = 488
|
||||
|
||||
|
||||
FATE_EAC3-$(call ENCDEC, EAC3, EAC3, WAV_MUXER WAV_DEMUXER ARESAMPLE_FILTER PCM_S16LE_ENCODER PIPE_PROTOCOL) += fate-eac3-encode
|
||||
fate-eac3-encode: CMD = enc_dec_pcm eac3 wav s16le $(subst $(SAMPLES),$(TARGET_SAMPLES),$(REF)) -c:a eac3 -b:a 128k
|
||||
fate-eac3-encode: CMP_SHIFT = -1024
|
||||
FATE_EAC3-$(call ENCDEC, EAC3, MP4 MOV, WAV_MUXER WAV_DEMUXER ARESAMPLE_FILTER PCM_S16LE_ENCODER PIPE_PROTOCOL) += fate-eac3-encode
|
||||
fate-eac3-encode: CMD = enc_dec_pcm mp4 wav s16le $(subst $(SAMPLES),$(TARGET_SAMPLES),$(REF)) -c:a eac3 -b:a 128k
|
||||
fate-eac3-encode: CMP_TARGET = 516.94
|
||||
fate-eac3-encode: SIZE_TOLERANCE = 488
|
||||
|
||||
fate-ac3-encode fate-eac3-encode: CMP = stddev
|
||||
fate-ac3-encode fate-eac3-encode: REF = $(SAMPLES)/audio-reference/luckynight_2ch_44kHz_s16.wav
|
||||
|
||||
@@ -11,3 +11,4 @@
|
||||
0, 7424, 7424, 1536, 1114, 0xfbcc27ad
|
||||
0, 8960, 8960, 1536, 1114, 0xe7ed3321
|
||||
0, 10496, 10496, 1536, 1114, 0xa1823473
|
||||
0, 12032, 12032, 256, 1116, 0x7cc628e3, S=1, Skip Samples, 10, 0x00190005
|
||||
|
||||
@@ -115,3 +115,4 @@
|
||||
0, 48, 48, 1, 28143, 0x1df268c5, S=1, Quality stats, 8, 0x050000a1
|
||||
1, 85760, 85760, 1536, 418, 0xae06ca91
|
||||
0, 49, 49, 1, 10073, 0xedb9f031, F=0x0, S=1, Quality stats, 8, 0x050400a2
|
||||
1, 87296, 87296, 256, 418, 0x0a0bdddc, S=1, Skip Samples, 10, 0x00190005
|
||||
|
||||
Reference in New Issue
Block a user