Commit 40becaa0 authored by Gildas Bazin's avatar Gildas Bazin

* modules/codec/dts.c: removed s/pdif hack from DTS audio parser.
   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.
parent 58391574
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dtstospdif.c : encapsulates DTS frames into S/PDIF packets * dtstospdif.c : encapsulates DTS frames into S/PDIF packets
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * 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> * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
* *
...@@ -36,10 +36,26 @@ ...@@ -36,10 +36,26 @@
#include "audio_output.h" #include "audio_output.h"
#include "aout_internal.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 * Local prototypes
*****************************************************************************/ *****************************************************************************/
static int Create ( vlc_object_t * ); static int Create ( vlc_object_t * );
static void Close ( vlc_object_t * );
static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *, static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
aout_buffer_t * ); aout_buffer_t * );
...@@ -49,7 +65,7 @@ static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *, ...@@ -49,7 +65,7 @@ static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
vlc_module_begin(); vlc_module_begin();
set_description( _("audio filter for DTS->S/PDIF encapsulation") ); set_description( _("audio filter for DTS->S/PDIF encapsulation") );
set_capability( "audio filter", 10 ); set_capability( "audio filter", 10 );
set_callbacks( Create, NULL ); set_callbacks( Create, Close );
vlc_module_end(); vlc_module_end();
/***************************************************************************** /*****************************************************************************
...@@ -65,22 +81,68 @@ static int Create( vlc_object_t *p_this ) ...@@ -65,22 +81,68 @@ static int Create( vlc_object_t *p_this )
return -1; 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->pf_do_work = DoWork;
p_filter->b_in_place = 0; p_filter->b_in_place = 1;
return 0; 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 * DoWork: convert a buffer
*****************************************************************************/ *****************************************************************************/
static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter, 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 ) 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_fz = p_in_buf->i_nb_samples * 4;
uint16_t i_frame, i_length = p_in_buf->i_nb_bytes / 3; 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 }; 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++ ) for( i_frame = 0; i_frame < 3; i_frame++ )
{ {
#ifndef HAVE_SWAB #ifndef HAVE_SWAB
...@@ -88,7 +150,7 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter, ...@@ -88,7 +150,7 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
byte_t * p_tmp; byte_t * p_tmp;
#endif #endif
byte_t * p_out = p_out_buf->p_buffer + (i_frame * i_fz); 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. */ /* Copy the S/PDIF headers. */
memcpy( p_out, p_sync, 6 ); memcpy( p_out, p_sync, 6 );
...@@ -119,6 +181,6 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter, ...@@ -119,6 +181,6 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
i_fz - i_length - 8 ); 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; p_out_buf->i_nb_bytes = p_out_buf->i_nb_samples * 4;
} }
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* dts.c: parse DTS audio sync info and packetize the stream * dts.c: parse DTS audio sync info and packetize the stream
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * 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> * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
* Gildas Bazin <gbazin@netcourrier.com> * Gildas Bazin <gbazin@netcourrier.com>
...@@ -56,12 +56,6 @@ struct decoder_sys_t ...@@ -56,12 +56,6 @@ struct decoder_sys_t
int i_frame_size, i_bit_rate; int i_frame_size, i_bit_rate;
unsigned int i_frame_length, i_rate, i_channels, i_channels_conf; 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 { enum {
...@@ -130,7 +124,6 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -130,7 +124,6 @@ static int OpenDecoder( vlc_object_t *p_this )
p_sys->b_packetizer = VLC_FALSE; p_sys->b_packetizer = VLC_FALSE;
p_sys->i_state = STATE_NOSYNC; p_sys->i_state = STATE_NOSYNC;
aout_DateSet( &p_sys->end_date, 0 ); aout_DateSet( &p_sys->end_date, 0 );
p_sys->i_frames_in_buf = 0;
p_sys->bytestream = block_BytestreamInit( p_dec ); p_sys->bytestream = block_BytestreamInit( p_dec );
...@@ -299,16 +292,6 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -299,16 +292,6 @@ static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
p_sys->i_state = STATE_NOSYNC; 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 */ /* So p_block doesn't get re-added several times */
*pp_block = block_BytestreamPop( &p_sys->bytestream ); *pp_block = block_BytestreamPop( &p_sys->bytestream );
...@@ -351,7 +334,8 @@ static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer ) ...@@ -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_rate = p_sys->i_rate;
p_dec->fmt_out.audio.i_channels = p_sys->i_channels; 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_frame_length = p_sys->i_frame_length;
p_dec->fmt_out.audio.i_original_channels = p_sys->i_channels_conf; 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 ) ...@@ -368,17 +352,11 @@ static uint8_t *GetOutBuffer( decoder_t *p_dec, void **pp_out_buffer )
} }
else else
{ {
if( !p_sys->i_frames_in_buf ) aout_buffer_t *p_aout_buffer = GetAoutBuffer( p_dec );
{ p_buf = p_aout_buffer ? p_aout_buffer->p_buffer : NULL;
p_sys->p_aout_buffer = GetAoutBuffer( p_dec ); *pp_out_buffer = p_aout_buffer;
}
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;
} }
p_sys->i_frames_in_buf++;
return p_buf; return p_buf;
} }
...@@ -390,12 +368,12 @@ static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec ) ...@@ -390,12 +368,12 @@ static aout_buffer_t *GetAoutBuffer( decoder_t *p_dec )
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
aout_buffer_t *p_buf; 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; if( p_buf == NULL ) return NULL;
p_buf->start_date = aout_DateGet( &p_sys->end_date ); p_buf->start_date = aout_DateGet( &p_sys->end_date );
p_buf->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 p_buf;
} }
...@@ -458,7 +436,18 @@ static int SyncInfo16be( const uint8_t *p_buf, ...@@ -458,7 +436,18 @@ static int SyncInfo16be( const uint8_t *p_buf,
return i_frame_size + 1; 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; unsigned char tmp, cur = 0;
int bits_in, bits_out = 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 ) ...@@ -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++ ) for( i = 0; i < i_in; i++ )
{ {
if( i%2 ) if( i%2 )
{ {
tmp = p_in[i-1]; tmp = p_in[i-i_le];
bits_in = 8; bits_in = 8;
} }
else else
{ {
tmp = p_in[i+1] & 0x3F; tmp = p_in[i+i_le] & 0x3F;
bits_in = 8 - 2; bits_in = 8 - 2;
} }
if( bits_out < 8 ) if( bits_out < 8 )
{ {
...@@ -513,12 +502,25 @@ static inline int SyncCode( const uint8_t *p_buf ) ...@@ -513,12 +502,25 @@ static inline int SyncCode( const uint8_t *p_buf )
{ {
return VLC_SUCCESS; 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 */ /* 16 bits, big endian version of the bitstream */
else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe && else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe &&
p_buf[2] == 0x80 && p_buf[3] == 0x01 ) p_buf[2] == 0x80 && p_buf[3] == 0x01 )
{ {
return VLC_SUCCESS; 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; else return VLC_EGENERIC;
} }
...@@ -538,10 +540,21 @@ static int SyncInfo( const uint8_t *p_buf, ...@@ -538,10 +540,21 @@ static int SyncInfo( const uint8_t *p_buf,
(p_buf[4] & 0xf0) == 0xf0 && p_buf[5] == 0x07 ) (p_buf[4] & 0xf0) == 0xf0 && p_buf[5] == 0x07 )
{ {
uint8_t conv_buf[12]; 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, i_frame_size = SyncInfo16be( conv_buf, &i_audio_mode, pi_sample_rate,
pi_bit_rate, pi_frame_length ); 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 */ /* 16 bits, big endian version of the bitstream */
else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe && else if( p_buf[0] == 0x7f && p_buf[1] == 0xfe &&
...@@ -550,6 +563,15 @@ static int SyncInfo( const uint8_t *p_buf, ...@@ -550,6 +563,15 @@ static int SyncInfo( const uint8_t *p_buf,
i_frame_size = SyncInfo16be( p_buf, &i_audio_mode, pi_sample_rate, i_frame_size = SyncInfo16be( p_buf, &i_audio_mode, pi_sample_rate,
pi_bit_rate, pi_frame_length ); 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; else return 0;
switch( i_audio_mode ) switch( i_audio_mode )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment