Index: roard/codecfilter.c
===================================================================
--- roard/codecfilter.c	(revision 1065)
+++ roard/codecfilter.c	(revision 1144)
@@ -26,5 +26,6 @@
 
 struct roar_codecfilter g_codecfilter[] = {
- {-1,                     "null", "null codec filter", NULL, ROAR_CODECFILTER_NONE, NULL, NULL, NULL, NULL, NULL, NULL},
+ {-1,                     "null", "null codec filter", NULL, ROAR_CODECFILTER_NONE,
+                                          NULL, NULL, NULL, NULL, NULL, NULL, NULL},
 
 /*
@@ -35,5 +36,5 @@
 */
  {ROAR_CODEC_RIFF_WAVE, "RIFF/WAVE", "RIFF/WAVE", NULL, ROAR_CODECFILTER_READ|ROAR_CODECFILTER_WRITE,
-  cf_wave_open, cf_wave_close, NULL, cf_wave_write, cf_wave_read, NULL},
+  cf_wave_open, cf_wave_close, NULL, cf_wave_write, cf_wave_read, NULL, NULL},
 //#endif
 
@@ -51,5 +52,5 @@
   NULL,
 #endif
-  cf_alaw_read, NULL},
+  cf_alaw_read, NULL, cf_alaw_delay},
 #endif
 
@@ -67,5 +68,5 @@
   NULL,
 #endif
-  cf_mulaw_read, NULL},
+  cf_mulaw_read, NULL, cf_alaw_delay},
 #endif
 
@@ -73,5 +74,5 @@
  {ROAR_CODEC_OGG_GENERAL, "cmd",  "ogg123",
   ROAR_HAVE_BIN_OGG123 " -q -d raw -f - -", ROAR_CODECFILTER_READ,
-  cf_cmd_open, NULL, NULL, NULL, NULL, NULL},
+  cf_cmd_open, NULL, NULL, NULL, NULL, NULL, codecfilter_delay_fulldyn},
 #endif
 
@@ -83,10 +84,10 @@
  ROAR_CODECFILTER_READ,
 #endif
- cf_vorbis_open, cf_vorbis_close, NULL, cf_vorbis_write, cf_vorbis_read, NULL},
+ cf_vorbis_open, cf_vorbis_close, NULL, cf_vorbis_write, cf_vorbis_read, NULL, codecfilter_delay_fulldyn},
 #else
 #ifdef ROAR_HAVE_BIN_OGG123
  {ROAR_CODEC_OGG_VORBIS, "cmd",  "ogg123",
   ROAR_HAVE_BIN_OGG123 " -q -d raw -f - -", ROAR_CODECFILTER_READ,
-  cf_cmd_open, NULL, NULL, NULL, NULL, NULL},
+  cf_cmd_open, NULL, NULL, NULL, NULL, NULL, codecfilter_delay_fulldyn},
 #endif
 #endif
@@ -95,9 +96,9 @@
  {ROAR_CODEC_OGG_SPEEX, "fishsound",  "libfishsound Xiph Codec library",
   NULL, ROAR_CODECFILTER_READ,
-  cf_fishsound_open, cf_fishsound_close, NULL, NULL, cf_fishsound_read, NULL},
+  cf_fishsound_open, cf_fishsound_close, NULL, NULL, cf_fishsound_read, NULL, codecfilter_delay_fulldyn},
 
  {ROAR_CODEC_OGG_FLAC, "fishsound",  "libfishsound Xiph Codec library",
   NULL, ROAR_CODECFILTER_READ,
-  cf_fishsound_open, cf_fishsound_close, NULL, NULL, cf_fishsound_read, NULL},
+  cf_fishsound_open, cf_fishsound_close, NULL, NULL, cf_fishsound_read, NULL, codecfilter_delay_fulldyn},
 #endif
 
@@ -105,15 +106,15 @@
  {ROAR_CODEC_MIDI_FILE, "MIDIFILE", "timidity MIDI synth",
   ROAR_HAVE_BIN_TIMIDITY " -Or1sl -s %R -o - -", ROAR_CODECFILTER_READ,
-  cf_cmd_open, NULL, NULL, NULL, NULL, NULL},
+  cf_cmd_open, NULL, NULL, NULL, NULL, NULL, codecfilter_delay_fulldyn},
 #endif
 
 #ifdef ROAR_HAVE_LIBCELT
  {ROAR_CODEC_ROAR_CELT, "RoarCELT", "RoarAudio CELT", NULL, ROAR_CODECFILTER_READ|ROAR_CODECFILTER_WRITE,
-  cf_celt_open, cf_celt_close, NULL, cf_celt_write, cf_celt_read, NULL},
+  cf_celt_open, cf_celt_close, NULL, cf_celt_write, cf_celt_read, NULL, cf_celt_delay},
 #endif
 
 #ifdef ROAR_HAVE_LIBSPEEX
  {ROAR_CODEC_ROAR_SPEEX, "RoarSpeex", "RoarAudio Speex", NULL, ROAR_CODECFILTER_READ|ROAR_CODECFILTER_WRITE,
-  cf_speex_open, cf_speex_close, NULL, cf_speex_write, cf_speex_read, NULL},
+  cf_speex_open, cf_speex_close, NULL, cf_speex_write, cf_speex_read, NULL, NULL},
 #endif
 
@@ -128,8 +129,8 @@
 #endif
   ROAR_CODECFILTER_READ,
-  cf_cmd_open, NULL, NULL, NULL, NULL, NULL},
-#endif
-
- {-1, NULL, NULL, NULL, ROAR_CODECFILTER_NONE, NULL, NULL, NULL, NULL, NULL, NULL} // end of list
+  cf_cmd_open, NULL, NULL, NULL, NULL, NULL, codecfilter_delay_fulldyn},
+#endif
+
+ {-1, NULL, NULL, NULL, ROAR_CODECFILTER_NONE, NULL, NULL, NULL, NULL, NULL, NULL, NULL} // end of list
 };
 
@@ -138,6 +139,8 @@
  int flags;
  char mode[5];
-
- printf("  Codec        Filtername   Mode - Description\n");
+ char delay[6];
+ uint_least32_t d;
+
+ printf("  Codec        Filtername   Mode Delay - Description\n");
  printf("------------------------------------------------------\n");
 
@@ -154,9 +157,23 @@
     mode[1] = 'w';
   }
+
+  *delay = 0;
+  if ( g_codecfilter[i].codec == -1 ) { // null codec filter
+   strcpy(delay, "0ms");
+  } else if ( g_codecfilter[i].delay == NULL ) {
+   strcpy(delay, "?");
+  } else {
+   if ( codecfilter_delay(NULL, i, &d) == -1 ) {
+    strcpy(delay, "dyn");
+   } else {
+    snprintf(delay, 5, "%ims", d/1000);
+   }
+  }
  
-  printf("  %-12s %-12s %-4s - %s\n",
+  printf("  %-12s %-12s %-4s %-5s - %s\n",
              roar_codec2str(g_codecfilter[i].codec),
              g_codecfilter[i].name,
              mode,
+             delay,
              g_codecfilter[i].desc
              );
@@ -253,3 +270,20 @@
 }
 
+int codecfilter_delay(CODECFILTER_USERDATA_T   inst, int codecfilter, uint_least32_t * delay) {
+ ROAR_DBG("codecfilter_delay(inst=%p, codecfilter=%i, *delay=?) = ?", inst, codecfilter);
+
+ if ( codecfilter == -1 )
+  return -1;
+
+ if ( g_codecfilter[codecfilter].delay )
+  return g_codecfilter[codecfilter].delay(inst, delay);
+
+ return -1;
+}
+
+int codecfilter_delay_fulldyn(CODECFILTER_USERDATA_T   inst, uint_least32_t * delay) {
+ *delay = 0; // just to be sure
+ return -1;
+}
+
 //ll
Index: roard/codecfilter_alaw.c
===================================================================
--- roard/codecfilter_alaw.c	(revision 1065)
+++ roard/codecfilter_alaw.c	(revision 1144)
@@ -87,3 +87,12 @@
 #endif
 
+#if defined(ROAR_SUPPORT_ALAW) || defined(ROAR_SUPPORT_MULAW)
+int cf_alaw_delay(CODECFILTER_USERDATA_T   inst, uint_least32_t * delay) {
+ // this codec does not create any addition latency.
+
+ *delay = 0;
+ return 0;
+}
+#endif
+
 //ll
Index: roard/codecfilter_celt.c
===================================================================
--- roard/codecfilter_celt.c	(revision 967)
+++ roard/codecfilter_celt.c	(revision 1144)
@@ -266,4 +266,22 @@
 }
 
+int cf_celt_delay(CODECFILTER_USERDATA_T   inst, uint_least32_t * delay) {
+ struct codecfilter_celt_inst * self = (struct codecfilter_celt_inst *) inst;
+
+ ROAR_DBG("cf_celt_delay(*) = ?");
+
+ if ( self == NULL ) {
+  *delay = (1000000 * 256) / ROAR_RATE_DEFAULT;
+  return 0;
+ } else {
+  *delay = (1000000 * self->frame_size) / ROAR_STREAM(self->stream)->info.rate;
+  ROAR_DBG("cf_celt_delay(*): frame_size=%i, rate=%i, *delay=%i",
+                  self->frame_size, ROAR_STREAM(self->stream)->info.rate, *delay);
+  return 0;
+ }
+
+ return -1;
+}
+
 #endif
 //ll
Index: roard/include/codecfilter.h
===================================================================
--- roard/include/codecfilter.h	(revision 992)
+++ roard/include/codecfilter.h	(revision 1144)
@@ -50,4 +50,5 @@
  int (*read )(CODECFILTER_USERDATA_T   inst, char * buf, int len);
  int (*flush)(CODECFILTER_USERDATA_T   inst);
+ int (*delay)(CODECFILTER_USERDATA_T   inst, uint_least32_t * delay);
 };
 
@@ -90,4 +91,8 @@
 int codecfilter_read (CODECFILTER_USERDATA_T   inst, int codecfilter, char * buf, int len);
 int codecfilter_flush(CODECFILTER_USERDATA_T   inst, int codecfilter);
+int codecfilter_delay(CODECFILTER_USERDATA_T   inst, int codecfilter, uint_least32_t * delay);
+
+int codecfilter_delay_fulldyn(CODECFILTER_USERDATA_T   inst, uint_least32_t * delay);
+
 
 // codecfilter without a own .h:
@@ -100,4 +105,5 @@
 int cf_alaw_read(CODECFILTER_USERDATA_T   inst, char * buf, int len);
 int cf_alaw_write(CODECFILTER_USERDATA_T   inst, char * buf, int len);
+int cf_alaw_delay(CODECFILTER_USERDATA_T   inst, uint_least32_t * delay);
 
 int cf_mulaw_open(CODECFILTER_USERDATA_T * inst, int codec,
@@ -109,5 +115,5 @@
 int cf_mulaw_read(CODECFILTER_USERDATA_T   inst, char * buf, int len);
 int cf_mulaw_write(CODECFILTER_USERDATA_T   inst, char * buf, int len);
-
+// cf_mulaw_delay() would be exactly the same as cf_alaw_delay() so it is just used by mulaw, too.
 
 #endif
Index: roard/include/codecfilter_celt.h
===================================================================
--- roard/include/codecfilter_celt.h	(revision 668)
+++ roard/include/codecfilter_celt.h	(revision 1144)
@@ -60,4 +60,6 @@
 int cf_celt_write(CODECFILTER_USERDATA_T   inst, char * buf, int len);
 
+int cf_celt_delay(CODECFILTER_USERDATA_T   inst, uint_least32_t * delay);
+
 #endif
 
