]> git.sesse.net Git - vlc/commitdiff
* modules/codec/dts.c: removed s/pdif hack from DTS audio parser.
authorGildas Bazin <gbazin@videolan.org>
Mon, 2 Feb 2004 23:49:46 +0000 (23:49 +0000)
committerGildas Bazin <gbazin@videolan.org>
Mon, 2 Feb 2004 23:49:46 +0000 (23:49 +0000)
   support for 14bits big endian bitstreams as well as 16bits little endian bitstreams.
* modules/audio_filter/converter/dtstospdif.c: accumulate DTS frames from parser until we have enough to fill an S/PDIF frame.

modules/audio_filter/converter/dtstospdif.c
modules/codec/dts.c

index 238cbc1354197c94b1def045428ef2f78dc1d2a8..50f43ff25b8ed7738f9e10f1d1cfebe59066d48a 100644 (file)
@@ -2,7 +2,7 @@
  * dtstospdif.c : encapsulates DTS frames into S/PDIF packets
  *****************************************************************************
  * Copyright (C) 2003 VideoLAN
- * $Id: dtstospdif.c,v 1.1 2003/03/09 20:07:47 jlj Exp $
+ * $Id: dtstospdif.c,v 1.2 2004/02/02 23:49:46 gbazin Exp $
  *
  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
  *
 #include "audio_output.h"
 #include "aout_internal.h"
 
+/*****************************************************************************
+ * Local structures
+ *****************************************************************************/
+struct aout_filter_sys_t
+{
+    /* 3 DTS frames have to be packed into an S/PDIF frame.
+     * We accumulate DTS frames from the decoder until we have enough to
+     * send. */
+
+    uint8_t *p_buf;
+
+    int i_frames;
+    unsigned int i_frame_size;
+};
+
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
 static int  Create    ( vlc_object_t * );
+static void Close     ( vlc_object_t * );
 static void DoWork    ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
                         aout_buffer_t * );
 
@@ -49,7 +65,7 @@ static void DoWork    ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
 vlc_module_begin();
     set_description( _("audio filter for DTS->S/PDIF encapsulation") );
     set_capability( "audio filter", 10 );
-    set_callbacks( Create, NULL );
+    set_callbacks( Create, Close );
 vlc_module_end();
 
 /*****************************************************************************
@@ -65,22 +81,68 @@ static int Create( vlc_object_t *p_this )
         return -1;
     }
 
+    /* Allocate the memory needed to store the module's structure */
+    p_filter->p_sys = malloc( sizeof(struct aout_filter_sys_t) );
+    if( p_filter->p_sys == NULL )
+    {
+        msg_Err( p_filter, "out of memory" );
+        return VLC_ENOMEM;
+    }
+    memset( p_filter->p_sys, 0, sizeof(struct aout_filter_sys_t) );
+    p_filter->p_sys->p_buf = 0;
+
     p_filter->pf_do_work = DoWork;
-    p_filter->b_in_place = 0;
+    p_filter->b_in_place = 1;
 
     return 0;
 }
 
+/*****************************************************************************
+ * Close: free our resources
+ *****************************************************************************/
+static void Close( vlc_object_t * p_this )
+{
+    aout_filter_t * p_filter = (aout_filter_t *)p_this;
+    if( p_filter->p_sys->i_frame_size ) free( p_filter->p_sys->p_buf );
+    free( p_filter->p_sys );
+}
+
 /*****************************************************************************
  * DoWork: convert a buffer
  *****************************************************************************/
 static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
                     aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
 {
-    uint16_t i_fz = (p_in_buf->i_nb_samples / 3) * 4;
-    uint16_t i_frame, i_length = p_in_buf->i_nb_bytes / 3;
+    uint16_t i_fz = p_in_buf->i_nb_samples * 4;
+    uint16_t i_frame, i_length = p_in_buf->i_nb_bytes;
     static const uint8_t p_sync[6] = { 0x72, 0xF8, 0x1F, 0x4E, 0x00, 0x00 };
 
+    if( p_in_buf->i_nb_bytes != p_filter->p_sys->i_frame_size )
+    {
+        /* Frame size changed, reset everything */
+        p_filter->p_sys->i_frame_size = p_in_buf->i_nb_bytes;
+        p_filter->p_sys->p_buf = realloc( p_filter->p_sys->p_buf,
+                                          p_in_buf->i_nb_bytes * 3 );
+        p_filter->p_sys->i_frames = 0;
+    }
+
+    /* Backup frame */
+    p_filter->p_vlc->pf_memcpy( p_filter->p_sys->p_buf + p_in_buf->i_nb_bytes *
+                                p_filter->p_sys->i_frames, p_in_buf->p_buffer,
+                                p_in_buf->i_nb_bytes );
+
+    p_filter->p_sys->i_frames++;
+
+    if( p_filter->p_sys->i_frames < 3 )
+    {
+        /* Not enough data */
+        p_out_buf->i_nb_samples = 0;
+        p_out_buf->i_nb_bytes = 0;
+        return;
+    }
+
+    p_filter->p_sys->i_frames = 0;
+
     for( i_frame = 0; i_frame < 3; i_frame++ )
     {
 #ifndef HAVE_SWAB
@@ -88,7 +150,7 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
         byte_t * p_tmp;
 #endif
         byte_t * p_out = p_out_buf->p_buffer + (i_frame * i_fz);
-        byte_t * p_in = p_in_buf->p_buffer + (i_frame * i_length);
+        byte_t * p_in = p_filter->p_sys->p_buf + (i_frame * i_length);
 
         /* Copy the S/PDIF headers. */
         memcpy( p_out, p_sync, 6 );
@@ -119,6 +181,6 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
                                     i_fz - i_length - 8 );
     }
 
-    p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
+    p_out_buf->i_nb_samples = p_in_buf->i_nb_samples * 3;
     p_out_buf->i_nb_bytes = p_out_buf->i_nb_samples * 4;
 }
index 406e0ff804b3c3ca08d6e666ca666c89d8dd17a0..ef2b26e928b546f1b0bd29f0a5caaf9ce2cf33a2 100644 (file)
@@ -2,7 +2,7 @@
  * dts.c: parse DTS audio sync info and packetize the stream
  *****************************************************************************
  * Copyright (C) 2003 VideoLAN
- * $Id: dts.c,v 1.12 2004/01/27 19:14:07 gbazin Exp $
+ * $Id: dts.c,v 1.13 2004/02/02 23:49:46 gbazin Exp $
  *
  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
  *          Gildas Bazin <gbazin@netcourrier.com>
@@ -56,12 +56,6 @@ struct decoder_sys_t
 
     int i_frame_size, i_bit_rate;
     unsigned int i_frame_length, i_rate, i_channels, i_channels_conf;
-
-    /* This is very hacky. For DTS over S/PDIF we apparently need to send
-     * 3 frames at a time. This should likely be moved to the output stage. */
-    int i_frames_in_buf;
-    aout_buffer_t *p_aout_buffer;        /* current aout buffer being filled */
-
 };
 
 enum {
@@ -130,7 +124,6 @@ static int OpenDecoder( vlc_object_t *p_this )
     p_sys->b_packetizer = VLC_FALSE;
     p_sys->i_state = STATE_NOSYNC;
     aout_DateSet( &p_sys->end_date, 0 );
-    p_sys->i_frames_in_buf = 0;
 
     p_sys->bytestream = block_BytestreamInit( p_dec );
 
@@ -299,16 +292,6 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
 
             p_sys->i_state = STATE_NOSYNC;
 
-            if( !p_sys->b_packetizer )
-            {
-                if( p_sys->i_frames_in_buf != 3 ) break;
-                else
-                {
-                    p_sys->i_frames_in_buf = 0;
-                    p_sys->p_aout_buffer = 0;
-                }
-            }
-
             /* So p_block doesn't get re-added several times */
             *pp_block = block_BytestreamPop( &p_sys->bytestream );
 
@@ -351,7 +334,8 @@ static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
 
     p_dec->fmt_out.audio.i_rate     = p_sys->i_rate;
     p_dec->fmt_out.audio.i_channels = p_sys->i_channels;
-    p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->i_frame_size;
+    /* Hack for DTS S/PDIF filter which needs to send 3 frames at a time */
+    p_dec->fmt_out.audio.i_bytes_per_frame = p_sys->i_frame_size * 3;
     p_dec->fmt_out.audio.i_frame_length = p_sys->i_frame_length;
 
     p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf;
@@ -368,17 +352,11 @@ static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
     }
     else
     {
-        if( !p_sys->i_frames_in_buf )
-        {
-            p_sys->p_aout_buffer = GetAoutBuffer( p_dec );
-        }
-        p_buf = p_sys->p_aout_buffer ? p_sys->p_aout_buffer->p_buffer +
-            p_sys->i_frames_in_buf * p_sys->i_frame_size : NULL;
-        *pp_out_buffer = p_sys->p_aout_buffer;
+        aout_buffer_t *p_aout_buffer = GetAoutBuffer( p_dec );
+        p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL;
+        *pp_out_buffer = p_aout_buffer;
     }
 
-    p_sys->i_frames_in_buf++;
-
     return p_buf;
 }
 
@@ -390,12 +368,12 @@ static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
     decoder_sys_t *p_sys = p_dec->p_sys;
     aout_buffer_t *p_buf;
 
-    p_buf = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_frame_length * 3 );
+    p_buf = p_dec->pf_aout_buffer_new( p_dec, p_sys->i_frame_length );
     if( p_buf == NULL ) return NULL;
 
     p_buf->start_date = aout_DateGet( &p_sys->end_date );
     p_buf->end_date =
-        aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length * 3 );
+        aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length );
 
     return p_buf;
 }
@@ -458,7 +436,18 @@ static int SyncInfo16be( const uint8_t *p_buf,
     return i_frame_size + 1;
 }
 
-static int Buf14leTO16be( uint8_t *p_out, const uint8_t *p_in, int i_in )
+static void BufLeToBe( uint8_t *p_out, const uint8_t *p_in, int i_in )
+{
+    int i;
+
+    for( i = 0; i < i_in/2; i++  )
+    {
+        p_out[i*2] = p_in[i*2+1];
+        p_out[i*2+1] = p_in[i*2];
+    }
+}
+
+static int Buf14To16( uint8_t *p_out, const uint8_t *p_in, int i_in, int i_le )
 {
     unsigned char tmp, cur = 0;
     int bits_in, bits_out = 0;
@@ -466,16 +455,16 @@ static int Buf14leTO16be( uint8_t *p_out, const uint8_t *p_in, int i_in )
 
     for( i = 0; i < i_in; i++  )
     {
-       if( i%2 )
-       {
-           tmp = p_in[i-1];
-           bits_in = 8;
-       }
-       else
-       {
-           tmp = p_in[i+1] & 0x3F;
-           bits_in = 8 - 2;
-       }
+        if( i%2 )
+        {
+            tmp = p_in[i-i_le];
+            bits_in = 8;
+        }
+        else
+        {
+            tmp = p_in[i+i_le] & 0x3F;
+            bits_in = 8 - 2;
+        }
 
         if( bits_out < 8 )
         {
@@ -513,12 +502,25 @@ static inline int SyncCode( const uint8_t *p_buf )
     {
         return VLC_SUCCESS;
     }
+    /* 14 bits, big endian version of the bitstream */
+    else if( p_buf[0] == 0x1f && p_buf[1] == 0xff &&
+             p_buf[2] == 0xe8 && p_buf[3] == 0x00 &&
+             p_buf[4] == 0x07 && (p_buf[5] & 0xf0) == 0xf0 )
+    {
+        return VLC_SUCCESS;
+    }
     /* 16 bits, big endian version of the bitstream */
     else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe &&
              p_buf[2] == 0x80 && p_buf[3] == 0x01 )
     {
         return VLC_SUCCESS;
     }
+    /* 16 bits, little endian version of the bitstream */
+    else if( p_buf[0] == 0xfe && p_buf[1] == 0x7f &&
+             p_buf[2] == 0x01 && p_buf[3] == 0x80 )
+    {
+        return VLC_SUCCESS;
+    }
     else return VLC_EGENERIC;
 }
 
@@ -538,10 +540,21 @@ static int SyncInfo( const uint8_t *p_buf,
         (p_buf[4] & 0xf0) == 0xf0 && p_buf[5] == 0x07 )
     {
         uint8_t conv_buf[12];
-       Buf14leTO16be( conv_buf, p_buf, 12 );
+        Buf14To16( conv_buf, p_buf, 12, 1 );
+        i_frame_size = SyncInfo16be( conv_buf, &i_audio_mode, pi_sample_rate,
+                                     pi_bit_rate, pi_frame_length );
+        i_frame_size = i_frame_size * 8 / 14 * 2;
+    }
+    /* 14 bits, big endian version of the bitstream */
+    else if( p_buf[0] == 0x1f && p_buf[1] == 0xff &&
+             p_buf[2] == 0xe8 && p_buf[3] == 0x00 &&
+             p_buf[4] == 0x07 && (p_buf[5] & 0xf0) == 0xf0 )
+    {
+        uint8_t conv_buf[12];
+        Buf14To16( conv_buf, p_buf, 12, 0 );
         i_frame_size = SyncInfo16be( conv_buf, &i_audio_mode, pi_sample_rate,
                                      pi_bit_rate, pi_frame_length );
-       i_frame_size = i_frame_size * 8 / 14 * 2;
+        i_frame_size = i_frame_size * 8 / 14 * 2;
     }
     /* 16 bits, big endian version of the bitstream */
     else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe &&
@@ -550,6 +563,15 @@ static int SyncInfo( const uint8_t *p_buf,
         i_frame_size = SyncInfo16be( p_buf, &i_audio_mode, pi_sample_rate,
                                      pi_bit_rate, pi_frame_length );
     }
+    /* 16 bits, little endian version of the bitstream */
+    else if( p_buf[0] == 0xfe && p_buf[1] == 0x7f &&
+             p_buf[2] == 0x01 && p_buf[3] == 0x80 )
+    {
+        uint8_t conv_buf[12];
+        BufLeToBe( conv_buf, p_buf, 12 );
+        i_frame_size = SyncInfo16be( p_buf, &i_audio_mode, pi_sample_rate,
+                                     pi_bit_rate, pi_frame_length );
+    }
     else return 0;
 
     switch( i_audio_mode )