]> git.sesse.net Git - vlc/blobdiff - src/audio_output/aout_spdif.c
*check for b_die and b_error in all loops so that we don't remain stuck
[vlc] / src / audio_output / aout_spdif.c
index 6590598d15b9444d3ea3be234d53701ce134ae4d..0397df9c11faca6ae8779cd8d293e007308cacc0 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
- * aout_spdif: ac3 passthrough output
+ * aout_spdif.c: AC3 passthrough output
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: aout_spdif.c,v 1.18 2001/11/14 03:38:11 stef Exp $
+ * $Id: aout_spdif.c,v 1.27 2002/05/17 18:01:25 stef Exp $
  *
  * Authors: Michel Kaempf <maxx@via.ecp.fr>
  *          Stéphane Borel <stef@via.ecp.fr>
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
-#include "defs.h"
-
 #include <stdio.h>                                           /* "intf_msg.h" */
 #include <stdlib.h>                            /* calloc(), malloc(), free() */
 #include <string.h>                                              /* memset() */
 
-#include "config.h"
-#include "common.h"
-#include "threads.h"
-#include "mtime.h"                             /* mtime_t, mdate(), msleep() */
+#include <videolan/vlc.h>
 
-#include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
+#ifdef HAVE_UNISTD_H
+#   include <unistd.h>
+#endif
 
 #include "audio_output.h"
-#include "aout_common.h"
+#include "aout_spdif.h"
+
+/****************************************************************************
+ * iec958_build_burst: builds an iec958/spdif frame
+ ****************************************************************************/
+void iec958_build_burst( u8 * p_buf, aout_fifo_t * p_fifo )
+{
+    const u8 p_sync[6] = { 0x72, 0xF8, 0x1F, 0x4E, 0x01, 0x00 };
+    int      i_length  = p_fifo->i_frame_size;
+#ifndef HAVE_SWAB
+    /* Skip the first byte if i_length is odd */
+    u16 * p_in  = (u16 *)( p_fifo->buffer + ( i_length & 0x1 ) );
+    u16 * p_out = (u16 *)p_buf;
+#endif
+
+    /* Add the spdif headers */
+    memcpy( p_buf, p_sync, 6 );
+    p_buf[6] = ( i_length * 8 ) & 0xFF;
+    p_buf[7] = ( ( i_length * 8 ) >> 8 ) & 0xFF;
+
+#ifdef HAVE_SWAB
+    swab( p_fifo->buffer + p_fifo->i_start_frame * i_length,
+          p_buf + 8, i_length );
+#else
+    /* i_length should be even */
+    i_length &= ~0x1;
+
+    while( i_length )
+    {
+        *p_out = ( (*p_in & 0x00ff) << 16 ) | ( (*p_in & 0xff00) >> 16 );
+        p_in++;
+        p_out++;
+        i_length -= 2;
+    }
+#endif
+
+    /* Add zeroes to complete the spdif frame,
+     * they will be ignored by the decoder */
+    memset( p_buf + 8 + i_length, 0, SPDIF_FRAME_SIZE - 8 - i_length );
+}
+
 
 /*****************************************************************************
  * aout_SpdifThread: audio output thread that sends raw spdif data
  *****************************************************************************/
 void aout_SpdifThread( aout_thread_t * p_aout )
 {
-  int         i_fifo;
-  mtime_t     m_frame_time = 0;
-  mtime_t     m_play;
-  mtime_t     m_old = 0;
-
-
-  intf_DbgMsg( "aout debug: starting spdif output loop" );
+    int         i_fifo;
+    mtime_t     m_frame_time = 0;
+    mtime_t     m_play;
+    mtime_t     m_old;
 
-  while( !p_aout->b_die )
-  {
-    for( i_fifo = 0 ; i_fifo < AOUT_MAX_FIFOS ; i_fifo++ )
+    while( !p_aout->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 )
+        i_fifo = 0;
+        /* Find spdif fifo */
+        while( ( p_aout->fifo[i_fifo].i_format != AOUT_FIFO_SPDIF ) &&
+               ( i_fifo < AOUT_MAX_FIFOS ) && !p_aout->b_die )
         {
-          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 );
+            i_fifo++;
         }
-        else if( !AOUT_FIFO_ISEMPTY( p_aout->fifo[i_fifo] ) )
+
+        m_old = 0;
+
+        while( !p_aout->b_die && 
+               !p_aout->fifo[i_fifo].b_die )
         {
-          /* 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;
-
-          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 )
+            vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
+            if( !AOUT_FIFO_ISEMPTY( p_aout->fifo[i_fifo] ) )
             {
-              intf_DbgMsg( "aout debug: malformed frame ? (%lld)",
-                               m_play - m_old );
-              mwait( m_play - m_frame_time );
+                /* Copy data from fifo to buffer to release the
+                 * lock earlier */
+                iec958_build_burst( p_aout->buffer,
+                                    &p_aout->fifo[i_fifo] );
+
+                m_play = p_aout->fifo[i_fifo].date[p_aout->fifo[i_fifo].
+                             i_start_frame];
+
+                p_aout->fifo[i_fifo].i_start_frame =
+                    (p_aout->fifo[i_fifo].i_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].i_rate;
+
+                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 )
+                    {
+                        mwait( m_play - m_frame_time );
+                    }
+                    else
+                    {
+                        mwait( m_play - 2 * m_frame_time );
+                    }
+                    m_old = m_play;
+                    
+                    p_aout->pf_getbufinfo( p_aout, 0 );
+
+                    p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer,
+                                     SPDIF_FRAME_SIZE );
+                }
             }
             else
             {
-              mwait( m_play - 2 * m_frame_time );
+                intf_WarnMsg( 3, "aout warning: empty spdif fifo" );
+                while( AOUT_FIFO_ISEMPTY( p_aout->fifo[i_fifo] ) &&
+                       !p_aout->b_die && 
+                       !p_aout->fifo[i_fifo].b_die )
+
+                {
+                    vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
+                    msleep( m_frame_time );
+                    vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
+                }
             }
-            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_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 );
+        vlc_mutex_lock( &p_aout->fifos_lock );
+        aout_FreeFifo( &p_aout->fifo[i_fifo] );
+        vlc_mutex_unlock( &p_aout->fifos_lock );
+    }
 
-  return;
+    return;
 }