]> git.sesse.net Git - vlc/blobdiff - src/audio_output/aout_spdif.c
-moved warning message to debug message in spdif pass-through plugin
[vlc] / src / audio_output / aout_spdif.c
index fcb5f64d54cab0dcee47023ea84b6d792871af34..6590598d15b9444d3ea3be234d53701ce134ae4d 100644 (file)
@@ -2,7 +2,7 @@
  * aout_spdif: ac3 passthrough output
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: aout_spdif.c,v 1.3 2001/05/06 18:32:30 stef Exp $
+ * $Id: aout_spdif.c,v 1.18 2001/11/14 03:38:11 stef Exp $
  *
  * Authors: Michel Kaempf <maxx@via.ecp.fr>
  *          Stéphane Borel <stef@via.ecp.fr>
@@ -41,8 +41,6 @@
 #include "audio_output.h"
 #include "aout_common.h"
 
-#define BLANK_FRAME_MAX 1000
-
 /*****************************************************************************
  * aout_SpdifThread: audio output thread that sends raw spdif data
  *                   to an external decoder
  * This output thread is quite specific as it can only handle one fifo now.
  *
  * Note: spdif can demux up to 8 ac3 streams, and can even take
- * care of time stamps (cf ac3 spec).
+ * care of time stamps (cf ac3 spec) but I'm not sure all decoders
+ * implement it.
  *****************************************************************************/
 void aout_SpdifThread( aout_thread_t * p_aout )
 {
-    u8          pi_spdif_blank [9] =
-                    { 0x72, 0xf8, 0x1f, 0x4e, 0x01, 0x00, 0x08, 0x00, 0x77 };
-    u8          pi_blank[SPDIF_FRAME_SIZE];
-    int         i_fifo;
-    int         i_frame;
-    int         i_blank;
-
-    /* get a blank frame ready */
-    memset( pi_blank, 0, sizeof(pi_blank) );
-    memcpy( pi_blank, pi_spdif_blank, sizeof(pi_spdif_blank) );
-   
-    intf_WarnMsg( 1, "aout info: starting spdif output loop" );
-
-    /* variable used to compute the nnumber of blank frames since the
-     * last significant frame */
-    i_blank = 0;
-
-    while( !p_aout->b_die )
-    {
-        /* we leave some time for aout fifo to fill and not to stress
-         * the external decoder too much */
-        msleep( 10000 );
+  int         i_fifo;
+  mtime_t     m_frame_time = 0;
+  mtime_t     m_play;
+  mtime_t     m_old = 0;
+
 
-        /* variable to check that we send data to the decoder
-         * once per loop at least */
-        i_frame = 0;
+  intf_DbgMsg( "aout debug: starting spdif output loop" );
 
-        /* FIXME: find a way to hnadle the locks here */
-        for( i_fifo = 0 ; i_fifo < AOUT_MAX_FIFOS ; i_fifo++ )
+  while( !p_aout->b_die )
+  {
+    for( i_fifo = 0 ; i_fifo < AOUT_MAX_FIFOS ; i_fifo++ )
+    {
+      /* the loop read each fifo so that we can change the stream
+       * on the fly but mulitplexing is not handled yet so
+       * the sound will be broken is more than one fifo has data */ 
+      /* TODO: write the muliplexer :) */
+      if( p_aout->fifo[i_fifo].i_type == AOUT_ADEC_SPDIF_FIFO )
+      {
+        vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
+        if( p_aout->fifo[i_fifo].b_die )
         {
-            /* the loop read each fifo so that we can change the stream
-             * on the fly but mulitplexing is not handled yet so
-             * the sound will be broken is more than one fifo has data */ 
-            /* TODO: write the muliplexer :) */
-            if( p_aout->fifo[i_fifo].i_type == AOUT_ADEC_SPDIF_FIFO )
-            {
-//                vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
-                if( p_aout->fifo[i_fifo].b_die )
-                {
-//                    vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
-                    aout_FreeFifo( &p_aout->fifo[i_fifo] );
-                }
-                else if( !AOUT_FIFO_ISEMPTY( p_aout->fifo[i_fifo] ) )
-                {
-                    vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
-                    /* play spdif frame to the external decoder */
-                    p_aout->pf_play( p_aout,
-                                     p_aout->fifo[i_fifo].buffer +
-                                        p_aout->fifo[i_fifo].l_start_frame*
-                                        SPDIF_FRAME_SIZE,
-                                     p_aout->fifo[i_fifo].l_frame_size );
-        
-//                    vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
-                    p_aout->fifo[i_fifo].l_start_frame = 
-                        (p_aout->fifo[i_fifo].l_start_frame + 1 )
-                        & AOUT_FIFO_SIZE;
-//                    vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
-                    
-                    i_frame++;
-                    i_blank = 0;
-                }
-            }
+          vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
+
+          vlc_mutex_lock( &p_aout->fifos_lock );
+          aout_FreeFifo( &p_aout->fifo[i_fifo] );
+          vlc_mutex_unlock( &p_aout->fifos_lock );
         }
-        if( !i_frame )
+        else if( !AOUT_FIFO_ISEMPTY( p_aout->fifo[i_fifo] ) )
         {
-            /* insert blank frame for stream continuity to
-             * the external decoder */
-            p_aout->pf_play( p_aout, pi_blank, SPDIF_FRAME_SIZE );
+          /* Copy data from fifo to buffer to release the lock earlier */
+          memcpy( p_aout->buffer,
+                  (byte_t *)p_aout->fifo[i_fifo].buffer
+                          + p_aout->fifo[i_fifo].l_start_frame
+                          * SPDIF_FRAME_SIZE,
+                  SPDIF_FRAME_SIZE );
+
+          m_play = p_aout->fifo[i_fifo].date[p_aout->fifo[i_fifo].
+                       l_start_frame];
+
+          p_aout->fifo[i_fifo].l_start_frame =
+              (p_aout->fifo[i_fifo].l_start_frame + 1 )
+              & AOUT_FIFO_SIZE;
+
+          /* Compute the theorical duration of an ac3 frame */
+          m_frame_time = 1000000 * AC3_FRAME_SIZE
+                                 / p_aout->fifo[i_fifo].l_rate;
 
-            /* we kill the output if we don't have any stream */
-            if( ++i_blank > BLANK_FRAME_MAX )
+          vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
+
+          /* play spdif frame to the external decoder 
+           * the kernel driver will sleep until the
+           * dsp buffer is empty enough to accept the data */
+          if( m_play > ( mdate() - m_frame_time ) )
+          {
+            /* check continuity */
+            if( (m_play - m_old) != m_frame_time )
+            {
+              intf_DbgMsg( "aout debug: malformed frame ? (%lld)",
+                               m_play - m_old );
+              mwait( m_play - m_frame_time );
+            }
+            else
             {
-                p_aout->b_die = 1;
+              mwait( m_play - 2 * m_frame_time );
             }
+            m_old = m_play;
+
+            p_aout->pf_play( p_aout,
+                             (byte_t *)p_aout->buffer,
+                             SPDIF_FRAME_SIZE );
+          }
+          else
+          {
+            intf_DbgMsg( "aout debug: late spdif frame" );
+          }
         }
+        else
+        {
+          vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
+          msleep( m_frame_time );
+          intf_WarnMsg( 3, "aout warning: empty spdif fifo" );
+        }
+      }
     }
-    
-    intf_WarnMsg( 2, "aout info: exiting spdif loop" );
+  }
+
+  intf_DbgMsg( "aout debug: exiting spdif loop" );
+  vlc_mutex_lock( &p_aout->fifos_lock );
+
+  for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
+  {
+    aout_FreeFifo( &p_aout->fifo[i_fifo] );
+  }
+
+  vlc_mutex_unlock( &p_aout->fifos_lock );
 
-    return;
+  return;
 }