From 2ebdd70c214755d7d968a616ad890a8de0814347 Mon Sep 17 00:00:00 2001 From: Julian Bouzas Date: Fri, 22 Mar 2019 12:01:01 +0100 Subject: [PATCH] flac: report latency in flacenc and flacdec The FLAC specification states that the data is processed in blocks, regardless of the number of channels. Thus, The latency can be calculated using the blocksize and rate. For example a 1 second block sampled at 44.1KHz has a blocksize of 44100 --- ext/flac/gstflacdec.c | 24 ++++++++++++++++++++++++ ext/flac/gstflacenc.c | 31 ++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/ext/flac/gstflacdec.c b/ext/flac/gstflacdec.c index a1104dc6eb..4583ceb4e1 100644 --- a/ext/flac/gstflacdec.c +++ b/ext/flac/gstflacdec.c @@ -238,6 +238,22 @@ gst_flac_dec_stop (GstAudioDecoder * dec) return TRUE; } +static gint64 +gst_flac_dec_get_latency (GstFlacDec * flacdec) +{ + /* The FLAC specification states that the data is processed in blocks, + * regardless of the number of channels. Thus, The latency can be calculated + * using the blocksize and rate. For example a 1 second block sampled at + * 44.1KHz has a blocksize of 44100 */ + + /* Make sure the rate is valid */ + if (!flacdec->info.rate) + return 0; + + /* Calculate the latecy */ + return (flacdec->max_blocksize * GST_SECOND) / flacdec->info.rate; +} + static gboolean gst_flac_dec_set_format (GstAudioDecoder * dec, GstCaps * caps) { @@ -294,6 +310,7 @@ gst_flac_dec_set_format (GstAudioDecoder * dec, GstCaps * caps) } } GST_INFO_OBJECT (dec, "headers and metadata are now processed"); + return TRUE; } @@ -450,7 +467,9 @@ gst_flac_dec_metadata_cb (const FLAC__StreamDecoder * decoder, const FLAC__StreamMetadata * metadata, void *client_data) { GstFlacDec *flacdec = GST_FLAC_DEC (client_data); + GstAudioDecoder *dec = GST_AUDIO_DECODER (client_data); GstAudioChannelPosition position[8]; + guint64 curr_latency = 0, old_latency = gst_flac_dec_get_latency (flacdec); GST_LOG_OBJECT (flacdec, "metadata type: %d", metadata->type); @@ -507,6 +526,11 @@ gst_flac_dec_metadata_cb (const FLAC__StreamDecoder * decoder, default: break; } + + /* Update the latency if it has changed */ + curr_latency = gst_flac_dec_get_latency (flacdec); + if (old_latency != curr_latency) + gst_audio_decoder_set_latency (dec, curr_latency, curr_latency); } static void diff --git a/ext/flac/gstflacenc.c b/ext/flac/gstflacenc.c index d31de07d82..6f3312a58b 100644 --- a/ext/flac/gstflacenc.c +++ b/ext/flac/gstflacenc.c @@ -841,6 +841,26 @@ done: return duration; } +static gint64 +gst_flac_enc_get_latency (GstFlacEnc * flacenc) +{ + /* The FLAC specification states that the data is processed in blocks, + * regardless of the number of channels. Thus, The latency can be calculated + * using the blocksize and rate. For example a 1 second block sampled at + * 44.1KHz has a blocksize of 44100 */ + + /* Get the blocksize */ + const guint blocksize = FLAC__stream_encoder_get_blocksize (flacenc->encoder); + + /* Get the sample rate in KHz */ + const guint rate = FLAC__stream_encoder_get_sample_rate (flacenc->encoder); + if (!rate) + return 0; + + /* Calculate the latecy */ + return (blocksize * GST_SECOND) / rate; +} + static gboolean gst_flac_enc_set_format (GstAudioEncoder * enc, GstAudioInfo * info) { @@ -887,7 +907,9 @@ gst_flac_enc_set_format (GstAudioEncoder * enc, GstAudioInfo * info) if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) goto failed_to_initialize; - /* no special feedback to base class; should provide all available samples */ + /* feedback to base class */ + gst_audio_encoder_set_latency (enc, + gst_flac_enc_get_latency (flacenc), gst_flac_enc_get_latency (flacenc)); return TRUE; @@ -1440,6 +1462,8 @@ gst_flac_enc_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstFlacEnc *this = GST_FLAC_ENC (object); + GstAudioEncoder *enc = GST_AUDIO_ENCODER (object); + guint64 curr_latency = 0, old_latency = gst_flac_enc_get_latency (this); GST_OBJECT_LOCK (this); @@ -1507,6 +1531,11 @@ gst_flac_enc_set_property (GObject * object, guint prop_id, } GST_OBJECT_UNLOCK (this); + + /* Update latency if it has changed */ + curr_latency = gst_flac_enc_get_latency (this); + if (old_latency != curr_latency) + gst_audio_encoder_set_latency (enc, curr_latency, curr_latency); } static void