af_lavcac3enc: fix A/V sync

The filter can buffer singificant amounts of audio.

(The proper fix is making the filter chain PTS-aware.)
This commit is contained in:
wm4 2015-06-15 14:33:48 +02:00
parent 74a73752c2
commit 30f5ba9422
1 changed files with 17 additions and 3 deletions

View File

@ -156,6 +156,13 @@ static void uninit(struct af_instance* af)
} }
} }
static void update_delay(struct af_instance *af)
{
af_ac3enc_t *s = af->priv;
af->delay = ((s->pending ? s->pending->samples : 0) + s->input->samples) /
(double)s->input->rate;
}
static int filter_frame(struct af_instance *af, struct mp_audio *audio) static int filter_frame(struct af_instance *af, struct mp_audio *audio)
{ {
af_ac3enc_t *s = af->priv; af_ac3enc_t *s = af->priv;
@ -166,6 +173,7 @@ static int filter_frame(struct af_instance *af, struct mp_audio *audio)
talloc_free(s->pending); talloc_free(s->pending);
s->pending = audio; s->pending = audio;
update_delay(af);
return 0; return 0;
} }
@ -177,22 +185,27 @@ static void swap_16(uint16_t *ptr, size_t size)
// Copy data from input frame to encode frame (because libavcodec wants a full // Copy data from input frame to encode frame (because libavcodec wants a full
// AC3 frame for encoding, while filter input frames can be smaller or larger). // AC3 frame for encoding, while filter input frames can be smaller or larger).
// Return true if the // Return true if the frame is complete.
static bool fill_buffer(af_ac3enc_t *s) static bool fill_buffer(struct af_instance *af)
{ {
af_ac3enc_t *s = af->priv;
af->delay = 0;
if (s->pending) { if (s->pending) {
int copy = MPMIN(s->in_samples - s->input->samples, s->pending->samples); int copy = MPMIN(s->in_samples - s->input->samples, s->pending->samples);
s->input->samples += copy; s->input->samples += copy;
mp_audio_copy(s->input, s->input->samples - copy, s->pending, 0, copy); mp_audio_copy(s->input, s->input->samples - copy, s->pending, 0, copy);
mp_audio_skip_samples(s->pending, copy); mp_audio_skip_samples(s->pending, copy);
} }
update_delay(af);
return s->input->samples >= s->in_samples; return s->input->samples >= s->in_samples;
} }
static int filter_out(struct af_instance *af) static int filter_out(struct af_instance *af)
{ {
af_ac3enc_t *s = af->priv; af_ac3enc_t *s = af->priv;
if (!fill_buffer(s)) if (!fill_buffer(af))
return 0; // need more input return 0; // need more input
AVFrame *frame = av_frame_alloc(); AVFrame *frame = av_frame_alloc();
@ -256,6 +269,7 @@ static int filter_out(struct af_instance *af)
swap_16((uint16_t *)(buf + header_len), s->pkt.size / 2); swap_16((uint16_t *)(buf + header_len), s->pkt.size / 2);
out->samples = frame_size / out->sstride; out->samples = frame_size / out->sstride;
af_add_output_frame(af, out); af_add_output_frame(af, out);
update_delay(af);
return 0; return 0;
} }