* 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 * );
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();
/*****************************************************************************
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
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 );
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;
}
* 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>
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 {
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 );
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 );
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;
}
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;
}
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;
}
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;
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 )
{
{
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;
}
(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 &&
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 )