[MPlayer-dev-eng] [PATCH] af_skip to skip first audio samples

Reimar D?ffinger Reimar.Doeffinger at stud.uni-karlsruhe.de
Thu Aug 17 13:43:41 CEST 2006


Hello,
attached patch adds -af skip, e.g. -af skip=1 can be used to skip the
first second of audio. Most effective when using the same number for
-delay (this case also show best why the other changes are necessary).
af_skip.c is an svn cp of af_dummy.c.
It needs some additional changes because right now when MPlayer gets 0
as return value from decode_audio it will go on to video decoding,
thinking that audio might be at eof. This means that video decoding will
start before all audio samples have been skipped, leading to hefty A-V
desync with e.g. -af skip=10 -delay 10 that is only slowly corrected
later.
The patch adds the special -AF_RETRY return value for decode_audio to
indicate that no decoded data is available but everything is alright and
mplayer.c should just try once more.
Do you consider this solution okay? Should it be applied separately from
af_skip (before or after)?

Greetings,
Reimar Döffinger

P.S.: I know documentation is missing, I'll at it when applying at
lastest.
-------------- next part --------------
Index: libmpcodecs/dec_audio.c
===================================================================
--- libmpcodecs/dec_audio.c	(revision 19414)
+++ libmpcodecs/dec_audio.c	(working copy)
@@ -427,6 +427,9 @@
   if(sh_audio->a_buffer_len>0)
     memmove(sh_audio->a_buffer, sh_audio->a_buffer+declen, sh_audio->a_buffer_len);
   
+  if (declen > 0 && pafd->len == 0)
+    return -AF_RETRY;
+
   return maxlen;
 }
 
Index: mplayer.c
===================================================================
--- mplayer.c	(revision 19414)
+++ mplayer.c	(working copy)
@@ -3752,7 +3752,7 @@
 if(sh_audio){
   if (! ignore_start)
     audio_delay -= sh_audio->stream_delay;
-  sh_audio->delay=-audio_delay;
+  sh_audio->delay=-audio_delay - af_calc_delay(sh_audio->afilter) / 1000.0;
 }
 
 if(!sh_audio){
@@ -3834,6 +3834,8 @@
     int ret=decode_audio(sh_audio,&sh_audio->a_out_buffer[sh_audio->a_out_buffer_len],
         playsize-sh_audio->a_out_buffer_len,sh_audio->a_out_buffer_size-sh_audio->a_out_buffer_len);
     if(ret<=0) { // EOF?
+      if (ret == -AF_RETRY) // decoded fine, but filter chain need all data
+        continue;
       if (d_audio->eof) {
 	audio_eof = 1;
 	if (!sh_video && sh_audio->a_out_buffer_len == 0)
Index: libaf/Makefile
===================================================================
--- libaf/Makefile	(revision 19414)
+++ libaf/Makefile	(working copy)
@@ -18,6 +18,7 @@
      af_pan.c \
      af_resample.c \
      af_sinesuppress.c \
+     af_skip.c \
      af_sub.c \
      af_surround.c \
      af_sweep.c \
Index: libaf/af_skip.c
===================================================================
--- libaf/af_skip.c	(revision 19414)
+++ libaf/af_skip.c	(working copy)
@@ -1,21 +1,39 @@
-/* The name speaks for itself this filter is a dummy and will not blow
-   up regardless of what you do with it. */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <inttypes.h>
 
 #include "af.h"
 
+typedef struct {
+  double skip_seconds;
+  uint64_t skip_bytes;
+} af_skip_t;
+
 // Initialization and runtime control
 static int control(struct af_instance_s* af, int cmd, void* arg)
 {
+  af_skip_t *p = af->setup;
   switch(cmd){
   case AF_CONTROL_REINIT:
     memcpy(af->data,(af_data_t*)arg,sizeof(af_data_t));
     af_msg(AF_MSG_VERBOSE,"[dummy] Was reinitialized: %iHz/%ich/%s\n",
 	af->data->rate,af->data->nch,af_fmt2str_short(af->data->format));
+    p->skip_bytes = p->skip_seconds * af->data->rate * af->data->nch * af->data->bps;
+    p->skip_bytes -= p->skip_bytes % (af->data->nch * af->data->bps);
+    p->skip_seconds = p->skip_bytes / (af->data->rate * af->data->nch * af->data->bps);
+    af->delay = -p->skip_seconds * 1000;
     return AF_OK;
+  case AF_CONTROL_COMMAND_LINE:{
+    char* end;
+    p->skip_seconds = strtod(arg, &end);
+    if (*end || p->skip_seconds < 0) {
+      p->skip_seconds = 0;
+      return AF_ERROR;
+    }
+    return AF_OK;
   }
+  }
   return AF_UNKNOWN;
 }
 
@@ -24,11 +42,22 @@
 {
   if(af->data)
     free(af->data);
+  if(af->setup)
+    free(af->setup);
 }
 
 // Filter data through filter
 static af_data_t* play(struct af_instance_s* af, af_data_t* data)
 {
+  af_skip_t *p = af->setup;
+  if (data->len < p->skip_bytes) {
+    p->skip_bytes -= data->len;
+    data->len = 0;
+  } else if (p->skip_bytes > 0) {
+    data->len -= p->skip_bytes;
+    memmove(data->audio, data->audio + p->skip_bytes, data->len);
+    p->skip_bytes = 0;
+  }
   // Do something necessary to get rid of annoying warning during compile
   if(!af)
     af_msg(AF_MSG_ERROR,"EEEK: Argument af == NULL in af_dummy.c play().");
@@ -45,14 +74,17 @@
   af->data=malloc(sizeof(af_data_t));
   if(af->data == NULL)
     return AF_ERROR;
+  af->setup = calloc(1, sizeof(af_skip_t));
+  if(af->setup == NULL)
+    return AF_ERROR;
   return AF_OK;
 }
 
 // Description of this filter
-af_info_t af_info_dummy = {
-    "dummy",
-    "dummy",
-    "Anders",
+af_info_t af_info_skip = {
+    "skip first seconds of audio",
+    "skip",
+    "Reimar Doeffinger",
     "",
     AF_FLAGS_REENTRANT,
     open
Index: libaf/af.c
===================================================================
--- libaf/af.c	(revision 19414)
+++ libaf/af.c	(working copy)
@@ -31,6 +31,7 @@
 extern af_info_t af_info_center;
 extern af_info_t af_info_sinesuppress;
 extern af_info_t af_info_karaoke;
+extern af_info_t af_info_skip;
 
 static af_info_t* filter_list[]={ 
    &af_info_dummy,
@@ -61,6 +62,7 @@
    &af_info_center,
    &af_info_sinesuppress,
    &af_info_karaoke,
+   &af_info_skip,
    NULL 
 };
 
Index: libaf/af.h
===================================================================
--- libaf/af.h	(revision 19414)
+++ libaf/af.h	(working copy)
@@ -110,6 +110,7 @@
 // Return values
 */
 
+#define AF_RETRY    3
 #define AF_DETACH   2
 #define AF_OK       1
 #define AF_TRUE     1


More information about the MPlayer-dev-eng mailing list