flac: report latency in flacenc and flacdec
authorJulian Bouzas <julian.bouzas@collabora.com>
Fri, 22 Mar 2019 11:01:01 +0000 (12:01 +0100)
committerJulian Bouzas <julian.bouzas@collabora.com>
Mon, 25 Mar 2019 14:14:32 +0000 (15:14 +0100)
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
ext/flac/gstflacenc.c

index a1104dc..4583ceb 100644 (file)
@@ -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
index d31de07..6f3312a 100644 (file)
@@ -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