changeset 18735:93dd2847bcdc

Rewrite audio EOF handling logic fixing some problems that could cause truncation of output, set flag AOPLAY_FINAL_CHUNK in play call to tell ao there will be no more data beyond what's in current buffer.
author uau
date Fri, 16 Jun 2006 21:52:25 +0000
parents e702b1706df1
children 04a651324963
files libao2/audio_out.h mplayer.c
diffstat 2 files changed, 24 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/libao2/audio_out.h	Fri Jun 16 21:17:47 2006 +0000
+++ b/libao2/audio_out.h	Fri Jun 16 21:52:25 2006 +0000
@@ -65,6 +65,8 @@
 #define AOCONTROL_SET_PLUGIN_DRIVER 6
 #define AOCONTROL_SET_PLUGIN_LIST 7
 
+#define AOPLAY_FINAL_CHUNK 1
+
 typedef struct ao_control_vol_s {
 	float left;
 	float right;
--- a/mplayer.c	Fri Jun 16 21:17:47 2006 +0000
+++ b/mplayer.c	Fri Jun 16 21:52:25 2006 +0000
@@ -3657,6 +3657,8 @@
   unsigned int t;
   double tt;
   int playsize;
+  int playflags=0;
+  int audio_eof=0;
 
   current_module="play_audio";
   
@@ -3675,31 +3677,44 @@
   // Fill buffer if needed:
   current_module="decode_audio";   // Enter AUDIO decoder module
   t=GetTimer();
-  while(sh_audio->a_out_buffer_len<playsize &&
-        (!d_audio->eof || sh_audio->a_in_buffer_len > 0 || sh_audio->a_buffer_len > 0)){
+  while (sh_audio->a_out_buffer_len < playsize) {
     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 (d_audio->eof)
-        sh_audio->a_in_buffer_len = 0; // make sure we don't hang if something's broken
+      if (d_audio->eof) {
+	audio_eof = 1;
+	if (!sh_video && sh_audio->a_out_buffer_len == 0)
+	    eof = PT_NEXT_ENTRY;
+      }
       break;
     }
     sh_audio->a_out_buffer_len+=ret;
   }
   t=GetTimer()-t;
   tt = t*0.000001f; audio_time_usage+=tt;
-  if(playsize>sh_audio->a_out_buffer_len) playsize=sh_audio->a_out_buffer_len;
+  if (playsize > sh_audio->a_out_buffer_len) {
+      playsize = sh_audio->a_out_buffer_len;
+      if (audio_eof)
+	  playflags |= AOPLAY_FINAL_CHUNK;
+  }
+  if (!playsize)
+      break;
 
   // play audio:  
   current_module="play_audio";
-  playsize=audio_out->play(sh_audio->a_out_buffer,playsize,0);
+  playsize = audio_out->play(sh_audio->a_out_buffer, playsize, playflags);
 
   if(playsize>0){
       sh_audio->a_out_buffer_len-=playsize;
       memmove(sh_audio->a_out_buffer,&sh_audio->a_out_buffer[playsize],sh_audio->a_out_buffer_len);
       sh_audio->delay+=playback_speed*playsize/(double)ao_data.bps;
   }
-
+  else if (audio_eof && audio_out->get_delay() < .04) {
+      // Sanity check to avoid hanging in case current ao doesn't output
+      // partial chunks and doesn't check for AOPLAY_FINAL_CHUNK
+      mp_msg(MSGT_CPLAYER, MSGL_WARN, "Audio output truncated at end.\n");
+      sh_audio->a_out_buffer_len = 0;
+  }
   break;
 } // while(sh_audio)
 
@@ -3709,8 +3724,6 @@
     double a_pos = playing_audio_pts(sh_audio, d_audio, audio_out);
     print_status(a_pos, 0, 0);
   }
-  if(d_audio->eof && sh_audio->a_in_buffer_len <= 0 && sh_audio->a_buffer_len <= 0) eof = PT_NEXT_ENTRY;
-
 } else {
 
 /*========================== PLAY VIDEO ============================*/