Web lists-archives.com

Re: [MPlayer-dev-eng] [PATCH] mplayer: fix buffer handling during channel change.




Le primidi 21 floréal, an CCXXIII, Reimar Döffinger a écrit :
> Even just dropping the remaining data seems safer/better.
> This is a horrible hack and the variable should be moved into the
> context instead (so it can be properly reset on seek for example),
> but doesn't this work:

It does. See the attached patch for a version with the variable moved to the
context.

I have looked at the seek() function, it does not seem to flush anything
about the audio buffers, so I did not add a reset of the
a_buffer_format_change field.

Thanks for your help.

Regards,

-- 
  Nicolas George
>From c4afaba791372c62e46be9966b32b852f2ff1756 Mon Sep 17 00:00:00 2001
From: Nicolas George <george@xxxxxxxx>
Date: Tue, 12 May 2015 15:01:55 +0200
Subject: [PATCH] mplayer: fix buffer handling during channel change.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Without this change, when changing from, for example, stereo
to 5.1, there may be a little stereo data left in the output
buffer when the audio output is reinitialized with the new
format. If that little stereo data is not a multiple of 6 samples
it causes a shift in the mapping of the 5.1 channels.

With this patch, decoded audio data in new format is not filtered
as long as there are still samples in old format that have not
yet been sent to the AO driver.

Based on a suggestion by Reimar Döffinger.
---
 libmpdemux/stheader.h |  3 +++
 mplayer.c             | 15 ++++++++-------
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/libmpdemux/stheader.h b/libmpdemux/stheader.h
index 9cbcd4c..d7601b6 100644
--- a/libmpdemux/stheader.h
+++ b/libmpdemux/stheader.h
@@ -68,6 +68,9 @@ typedef struct sh_audio {
   char* a_buffer;
   int a_buffer_len;
   int a_buffer_size;
+  int a_buffer_format_change; // audio data in the input buffer is subject
+                              // to a format change but data in the old
+                              // format is still present in the out buffer
   // output buffers:
   char* a_out_buffer;
   int a_out_buffer_len;
diff --git a/mplayer.c b/mplayer.c
index 0068b84..9da8888 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -2135,7 +2135,6 @@ static int fill_audio_out_buffers(void)
     int playflags = 0;
     int audio_eof = 0;
     int bytes_to_write;
-    int format_change = 0;
     int timeout = 0;
     sh_audio_t *const sh_audio = mpctx->sh_audio;
 
@@ -2174,11 +2173,11 @@ static int fill_audio_out_buffers(void)
         // Fill buffer if needed:
         current_module = "decode_audio";
         t = GetTimer();
-        if (!format_change) {
+        if (!sh_audio->a_buffer_format_change) {
             res = mp_decode_audio(sh_audio, playsize);
-            format_change = res == -2;
+            sh_audio->a_buffer_format_change = res == -2;
         }
-        if (!format_change && res < 0) // EOF or error
+        if (!sh_audio->a_buffer_format_change && res < 0) // EOF or error
             if (mpctx->d_audio->eof) {
                 audio_eof = 1;
                 if (sh_audio->a_out_buffer_len == 0)
@@ -2189,7 +2188,7 @@ static int fill_audio_out_buffers(void)
         audio_time_usage += tt;
         if (playsize > sh_audio->a_out_buffer_len) {
             playsize = sh_audio->a_out_buffer_len;
-            if (audio_eof || format_change)
+            if (audio_eof || sh_audio->a_buffer_format_change)
                 playflags |= AOPLAY_FINAL_CHUNK;
         }
         if (!playsize)
@@ -2209,19 +2208,21 @@ static int fill_audio_out_buffers(void)
             memmove(sh_audio->a_out_buffer, &sh_audio->a_out_buffer[playsize],
                     sh_audio->a_out_buffer_len);
             mpctx->delay += playback_speed * playsize / (double)ao_data.bps;
-        } else if ((format_change || audio_eof) && mpctx->audio_out->get_delay() < .04) {
+        } else if ((sh_audio->a_buffer_format_change || audio_eof) &&
+                   mpctx->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, MSGTR_AudioOutputTruncated);
             sh_audio->a_out_buffer_len = 0;
         }
     }
-    if (format_change) {
+    if (sh_audio->a_buffer_format_change && !sh_audio->a_out_buffer_len) {
         uninit_player(INITIALIZED_AO);
         af_uninit(sh_audio->afilter);
         free(sh_audio->afilter);
         sh_audio->afilter = NULL;
         reinit_audio_chain();
+        sh_audio->a_buffer_format_change = 0;
     }
     return 1;
 }
-- 
2.1.4

_______________________________________________
MPlayer-dev-eng mailing list
MPlayer-dev-eng@xxxxxxxxxxxx
https://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng