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