[vlc-commits] a52tospdif: add DTS support
Rafaël Carré
git at videolan.org
Tue Jun 14 13:12:41 CEST 2016
vlc | branch: master | Rafaël Carré <funman at videolan.org> | Mon Jun 13 16:01:38 2016 +0200| [57be85206cfceb1f1b79be099d03c1d99f8e0d8b] | committer: Thomas Guillem
a52tospdif: add DTS support
Modified-By: Thomas Guillem <thomas at gllm.fr>
Signed-off-by: Thomas Guillem <thomas at gllm.fr>
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=57be85206cfceb1f1b79be099d03c1d99f8e0d8b
---
modules/audio_filter/converter/a52tospdif.c | 127 ++++++++++++++++++++-------
1 file changed, 95 insertions(+), 32 deletions(-)
diff --git a/modules/audio_filter/converter/a52tospdif.c b/modules/audio_filter/converter/a52tospdif.c
index 2e4a820..bd4175c 100644
--- a/modules/audio_filter/converter/a52tospdif.c
+++ b/modules/audio_filter/converter/a52tospdif.c
@@ -1,11 +1,14 @@
/*****************************************************************************
- * a52tospdif.c : encapsulates A/52 frames into S/PDIF packets
+ * a52tospdif.c : encapsulates A/52 and DTS frames into S/PDIF packets
*****************************************************************************
- * Copyright (C) 2002, 2006 VLC authors and VideoLAN
+ * Copyright (C) 2002, 2006-2016 VLC authors and VideoLAN
* $Id$
*
* Authors: Christophe Massiot <massiot at via.ecp.fr>
* Stéphane Borel <stef at via.ecp.fr>
+ * Rémi Denis-Courmont
+ * Rafaël Carré
+ * Thomas Guillem
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -30,6 +33,8 @@
# include "config.h"
#endif
+#include <assert.h>
+
#include <vlc_common.h>
#include <vlc_plugin.h>
@@ -48,7 +53,7 @@ static block_t *DoWork( filter_t *, block_t * );
vlc_module_begin ()
set_category( CAT_AUDIO )
set_subcategory( SUBCAT_AUDIO_MISC )
- set_description( N_("Audio filter for A/52->S/PDIF encapsulation") )
+ set_description( N_("Audio filter for A/52/DTS->S/PDIF encapsulation") )
set_capability( "audio converter", 10 )
set_callbacks( Create, NULL )
vlc_module_end ()
@@ -60,54 +65,112 @@ static int Create( vlc_object_t *p_this )
{
filter_t * p_filter = (filter_t *)p_this;
- if ( p_filter->fmt_in.audio.i_format != VLC_CODEC_A52 ||
- ( p_filter->fmt_out.audio.i_format != VLC_CODEC_SPDIFB &&
- p_filter->fmt_out.audio.i_format != VLC_CODEC_SPDIFL ) )
- {
+ if( ( p_filter->fmt_in.audio.i_format != VLC_CODEC_DTS &&
+ p_filter->fmt_in.audio.i_format != VLC_CODEC_A52 ) ||
+ ( p_filter->fmt_out.audio.i_format != VLC_CODEC_SPDIFL &&
+ p_filter->fmt_out.audio.i_format != VLC_CODEC_SPDIFB ) )
return VLC_EGENERIC;
- }
p_filter->pf_audio_filter = DoWork;
return VLC_SUCCESS;
}
+
+static uint16_t get_data_type( filter_t *p_filter, block_t *p_in )
+{
+#define IEC61937_AC3 0x01
+#define IEC61937_DTS1 0x0B
+#define IEC61937_DTS2 0x0C
+#define IEC61937_DTS3 0x0D
+
+ switch( p_filter->fmt_in.audio.i_format )
+ {
+ case VLC_CODEC_A52:
+ if( unlikely( p_in->i_buffer < 6 ) )
+ return 0;
+ return ( (p_in->p_buffer[5] & 0x7) << 8 ) /* bsmod */ | IEC61937_AC3;
+ case VLC_CODEC_DTS:
+ if( unlikely( p_in->i_buffer < 1 ) )
+ return 0;
+ switch( p_in->i_nb_samples )
+ {
+ case 512: return IEC61937_DTS1;
+ case 1024: return IEC61937_DTS2;
+ case 2048: return IEC61937_DTS3;
+ default:
+ msg_Err( p_filter, "Frame size %d not supported",
+ p_in->i_nb_samples );
+ return 0;
+ }
+ default:
+ vlc_assert_unreachable();
+ }
+ return 0;
+}
+
+static bool is_big_endian( filter_t *p_filter, block_t *p_in )
+{
+ switch( p_filter->fmt_in.audio.i_format )
+ {
+ case VLC_CODEC_A52:
+ return true;
+ case VLC_CODEC_DTS:
+ return p_in->p_buffer[0] == 0x1F || p_in->p_buffer[0] == 0x7F;
+ default:
+ vlc_assert_unreachable();
+ }
+ return 0;
+}
+
/*****************************************************************************
* DoWork: convert a buffer
*****************************************************************************/
static block_t *DoWork( filter_t * p_filter, block_t *p_in_buf )
{
- /* AC3 is natively big endian. Most SPDIF devices have the native
- * endianness of the computer system.
- * On Mac OS X however, little endian devices are also common.
- */
- static const uint8_t p_sync_le[6] = { 0x72, 0xF8, 0x1F, 0x4E, 0x01, 0x00 };
- static const uint8_t p_sync_be[6] = { 0xF8, 0x72, 0x4E, 0x1F, 0x00, 0x01 };
- uint16_t i_frame_size = p_in_buf->i_buffer / 2;
+ uint16_t i_length = p_in_buf->i_buffer;
uint8_t * p_in = p_in_buf->p_buffer;
+ block_t *p_out_buf = NULL;
+
+ uint16_t i_data_type = get_data_type( p_filter, p_in_buf );
+ if( i_data_type == 0 || ( i_length + 8 ) > AOUT_SPDIF_SIZE )
+ goto out;
- block_t *p_out_buf = block_Alloc( AOUT_SPDIF_SIZE );
+ p_out_buf = block_Alloc( AOUT_SPDIF_SIZE );
if( !p_out_buf )
goto out;
- uint8_t * p_out = p_out_buf->p_buffer;
+ uint8_t *p_out = p_out_buf->p_buffer;
/* Copy the S/PDIF headers. */
- if( p_filter->fmt_out.audio.i_format == VLC_CODEC_SPDIFB )
- {
- memcpy( p_out, p_sync_be, 6 );
- p_out[4] = p_in[5] & 0x7; /* bsmod */
- SetWBE( p_out + 6, i_frame_size << 4 );
- memcpy( &p_out[8], p_in, i_frame_size * 2 );
- }
- else
+ void (*write16)(void *, uint16_t) =
+ ( p_filter->fmt_out.audio.i_format == VLC_CODEC_SPDIFB )
+ ? SetWBE : SetWLE;
+
+ write16( &p_out[0], 0xf872 ); /* syncword 1 */
+ write16( &p_out[2], 0x4e1f ); /* syncword 2 */
+ write16( &p_out[4], i_data_type ); /* data type */
+ write16( &p_out[6], i_length * 8 ); /* length in bits */
+
+ bool b_input_big_endian = is_big_endian( p_filter, p_in_buf );
+ bool b_output_big_endian =
+ p_filter->fmt_out.audio.i_format == VLC_CODEC_SPDIFB;
+
+ if( b_input_big_endian != b_output_big_endian )
{
- memcpy( p_out, p_sync_le, 6 );
- p_out[5] = p_in[5] & 0x7; /* bsmod */
- SetWLE( p_out + 6, i_frame_size << 4 );
- swab( p_in, &p_out[8], i_frame_size * 2 );
- }
- memset( p_out + 8 + i_frame_size * 2, 0,
- AOUT_SPDIF_SIZE - i_frame_size * 2 - 8 );
+ swab( p_in, p_out + 8, i_length & ~1 );
+
+ /* If i_length is odd, we have to adjust swapping a bit... */
+ if( i_length & 1 && ( i_length + 9 ) <= AOUT_SPDIF_SIZE )
+ {
+ p_out[8 + i_length - 1] = 0;
+ p_out[8 + i_length] = p_in[i_length-1];
+ i_length++;
+ }
+ } else
+ memcpy( p_out + 8, p_in, i_length );
+
+ if( 8 + i_length < AOUT_SPDIF_SIZE ) /* padding */
+ memset( p_out + 8 + i_length, 0, AOUT_SPDIF_SIZE - i_length - 8 );
p_out_buf->i_dts = p_in_buf->i_dts;
p_out_buf->i_pts = p_in_buf->i_pts;
More information about the vlc-commits
mailing list