Commit 00906ea8 authored by Gildas Bazin's avatar Gildas Bazin

* modules/codec/lpcm.c: support for 20/24 bits LPCM.

* modules/audio_filter/converter/s16tofloat32*, modules/audio_filter/format.c: s24l/s24b conversion routines.
parent 3c53e7b2
/***************************************************************************** /*****************************************************************************
* audio_output.h : audio output interface * audio_output.h : audio output interface
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002-2005 VideoLAN
* $Id$ * $Id$
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
...@@ -40,9 +40,11 @@ ...@@ -40,9 +40,11 @@
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
# define AOUT_FMT_S16_NE VLC_FOURCC('s','1','6','b') # define AOUT_FMT_S16_NE VLC_FOURCC('s','1','6','b')
# define AOUT_FMT_U16_NE VLC_FOURCC('u','1','6','b') # define AOUT_FMT_U16_NE VLC_FOURCC('u','1','6','b')
# define AOUT_FMT_S24_NE VLC_FOURCC('s','2','4','b')
#else #else
# define AOUT_FMT_S16_NE VLC_FOURCC('s','1','6','l') # define AOUT_FMT_S16_NE VLC_FOURCC('s','1','6','l')
# define AOUT_FMT_U16_NE VLC_FOURCC('u','1','6','l') # define AOUT_FMT_U16_NE VLC_FOURCC('u','1','6','l')
# define AOUT_FMT_S24_NE VLC_FOURCC('s','2','4','l')
#endif #endif
#define AOUT_FMT_NON_LINEAR( p_format ) \ #define AOUT_FMT_NON_LINEAR( p_format ) \
......
/***************************************************************************** /*****************************************************************************
* s16tofloat32.c : converter from signed 16 bits integer to float32 * s16tofloat32.c : converter from signed 16 bits integer to float32
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002-2005 VideoLAN
* $Id$ * $Id$
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
...@@ -38,6 +38,8 @@ static int Create ( vlc_object_t * ); ...@@ -38,6 +38,8 @@ static int Create ( 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 * );
static void DoWork24 ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
aout_buffer_t * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
...@@ -59,7 +61,8 @@ static int Create( vlc_object_t *p_this ) ...@@ -59,7 +61,8 @@ static int Create( vlc_object_t *p_this )
{ {
aout_filter_t * p_filter = (aout_filter_t *)p_this; aout_filter_t * p_filter = (aout_filter_t *)p_this;
if ( p_filter->input.i_format != AOUT_FMT_S16_NE if ( ( p_filter->input.i_format != AOUT_FMT_S16_NE &&
p_filter->input.i_format != AOUT_FMT_S24_NE )
|| p_filter->output.i_format != VLC_FOURCC('f','l','3','2') ) || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') )
{ {
return -1; return -1;
...@@ -70,7 +73,11 @@ static int Create( vlc_object_t *p_this ) ...@@ -70,7 +73,11 @@ static int Create( vlc_object_t *p_this )
return -1; return -1;
} }
if( p_filter->input.i_format == AOUT_FMT_S24_NE )
p_filter->pf_do_work = DoWork24;
else
p_filter->pf_do_work = DoWork; p_filter->pf_do_work = DoWork;
p_filter->b_in_place = VLC_TRUE; p_filter->b_in_place = VLC_TRUE;
return 0; return 0;
...@@ -109,3 +116,27 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter, ...@@ -109,3 +116,27 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 2; p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 2;
} }
static void DoWork24( aout_instance_t * p_aout, aout_filter_t * p_filter,
aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
{
int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
/* We start from the end because b_in_place is true */
uint8_t * p_in = (uint8_t *)p_in_buf->p_buffer + (i - 1) * 3;
float * p_out = (float *)p_out_buf->p_buffer + i - 1;
while( i-- )
{
#ifdef WORDS_BIGENDIAN
*p_out = ((float)( (((int32_t)*(int16_t *)(p_in)) << 8) + p_in[2]))
#else
*p_out = ((float)( (((int32_t)*(int16_t *)(p_in+1)) << 8) + p_in[0]))
#endif
/ 8388608.0;
p_in -= 3; p_out--;
}
p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 4 / 3;
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* s16tofloat32swab.c : converter from signed 16 bits integer to float32 * s16tofloat32swab.c : converter from signed 16 bits integer to float32
* with endianness change * with endianness change
***************************************************************************** *****************************************************************************
* Copyright (C) 2002 VideoLAN * Copyright (C) 2002-2005 VideoLAN
* $Id$ * $Id$
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
...@@ -49,6 +49,8 @@ static int Create ( vlc_object_t * ); ...@@ -49,6 +49,8 @@ static int Create ( 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 * );
static void DoWork24 ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
aout_buffer_t * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
...@@ -87,6 +89,17 @@ static int Create( vlc_object_t *p_this ) ...@@ -87,6 +89,17 @@ static int Create( vlc_object_t *p_this )
return 0; return 0;
} }
if ( (p_filter->input.i_format == VLC_FOURCC('s','2','4','l') ||
p_filter->input.i_format == VLC_FOURCC('s','2','4','b'))
&& p_filter->output.i_format == VLC_FOURCC('f','l','3','2')
&& p_filter->input.i_format != AOUT_FMT_S24_NE )
{
p_filter->pf_do_work = DoWork24;
p_filter->b_in_place = VLC_TRUE;
return 0;
}
return -1; return -1;
} }
...@@ -139,3 +152,33 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter, ...@@ -139,3 +152,33 @@ static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 2; p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 2;
} }
static void DoWork24( aout_instance_t * p_aout, aout_filter_t * p_filter,
aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
{
int i = p_in_buf->i_nb_samples * aout_FormatNbChannels( &p_filter->input );
/* We start from the end because b_in_place is true */
uint8_t * p_in = (uint8_t *)p_in_buf->p_buffer + (i - 1) * 3;
float * p_out = (float *)p_out_buf->p_buffer + i - 1;
byte_t p_tmp[3];
while( i-- )
{
p_tmp[0] = p_in[2];
p_tmp[1] = p_in[1];
p_tmp[2] = p_in[0];
#ifdef WORDS_BIGENDIAN
*p_out = ((float)( (((int32_t)*(int16_t *)(p_tmp)) << 8) + p_tmp[2]))
#else
*p_out = ((float)( (((int32_t)*(int16_t *)(p_tmp+1)) << 8) + p_tmp[0]))
#endif
/ 8388608.0;
p_in -= 3; p_out--;
}
p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes * 4 / 3;
}
This diff is collapsed.
/***************************************************************************** /*****************************************************************************
* lpcm.c: lpcm decoder/packetizer module * lpcm.c: lpcm decoder/packetizer module
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2003 VideoLAN * Copyright (C) 1999-2005 VideoLAN
* $Id$ * $Id$
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* Henri Fallon <henri@videolan.org> * Henri Fallon <henri@videolan.org>
* Christophe Massiot <massiot@via.ecp.fr> * Christophe Massiot <massiot@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com> * Gildas Bazin <gbazin@videolan.org>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -118,7 +118,16 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -118,7 +118,16 @@ static int OpenDecoder( vlc_object_t *p_this )
/* Set output properties */ /* Set output properties */
p_dec->fmt_out.i_cat = AUDIO_ES; p_dec->fmt_out.i_cat = AUDIO_ES;
if( p_dec->fmt_out.audio.i_bitspersample == 24 )
{
p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b');
}
else
{
p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b'); p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b');
p_dec->fmt_out.audio.i_bitspersample = 16;
}
/* Set callback */ /* Set callback */
p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **)) p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
...@@ -154,7 +163,7 @@ static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block ) ...@@ -154,7 +163,7 @@ static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block )
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
block_t *p_block; block_t *p_block;
unsigned int i_rate = 0, i_original_channels = 0, i_channels = 0; unsigned int i_rate = 0, i_original_channels = 0, i_channels = 0;
int i_frame_length; int i_frame_length, i_bitspersample;
uint8_t i_header; uint8_t i_header;
if( !pp_block || !*pp_block ) return NULL; if( !pp_block || !*pp_block ) return NULL;
...@@ -242,6 +251,26 @@ static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block ) ...@@ -242,6 +251,26 @@ static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block )
break; break;
} }
switch ( (i_header >> 6) & 0x3 )
{
case 2:
p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b');
p_dec->fmt_out.audio.i_bitspersample = 24;
i_bitspersample = 24;
break;
case 1:
p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b');
p_dec->fmt_out.audio.i_bitspersample = 24;
i_bitspersample = 20;
break;
case 0:
default:
p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b');
p_dec->fmt_out.audio.i_bitspersample = 16;
i_bitspersample = 16;
break;
}
/* Check frame sync and drop it. */ /* Check frame sync and drop it. */
if( p_block->p_buffer[5] != 0x80 ) if( p_block->p_buffer[5] != 0x80 )
{ {
...@@ -263,10 +292,11 @@ static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block ) ...@@ -263,10 +292,11 @@ static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block )
= i_original_channels & AOUT_CHAN_PHYSMASK; = i_original_channels & AOUT_CHAN_PHYSMASK;
i_frame_length = (p_block->i_buffer - LPCM_HEADER_LEN) / i_frame_length = (p_block->i_buffer - LPCM_HEADER_LEN) /
( p_dec->fmt_out.audio.i_channels * 2 ); p_dec->fmt_out.audio.i_channels * 8 / i_bitspersample;
if( p_sys->b_packetizer ) if( p_sys->b_packetizer )
{ {
p_dec->fmt_out.i_codec = VLC_FOURCC('l','p','c','m');
p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date ); p_block->i_pts = p_block->i_dts = aout_DateGet( &p_sys->end_date );
p_block->i_length = p_block->i_length =
aout_DateIncrement( &p_sys->end_date, i_frame_length ) - aout_DateIncrement( &p_sys->end_date, i_frame_length ) -
...@@ -285,9 +315,71 @@ static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block ) ...@@ -285,9 +315,71 @@ static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block )
p_aout_buffer->end_date = p_aout_buffer->end_date =
aout_DateIncrement( &p_sys->end_date, i_frame_length ); aout_DateIncrement( &p_sys->end_date, i_frame_length );
p_block->p_buffer += LPCM_HEADER_LEN;
p_block->i_buffer -= LPCM_HEADER_LEN;
/* 20/24 bits LPCM use special packing */
if( i_bitspersample == 24 )
{
uint8_t *p_out = p_aout_buffer->p_buffer;
while( p_block->i_buffer / 12 )
{
/* Sample 1 */
p_out[0] = p_block->p_buffer[0];
p_out[1] = p_block->p_buffer[1];
p_out[2] = p_block->p_buffer[8];
/* Sample 2 */
p_out[3] = p_block->p_buffer[2];
p_out[4] = p_block->p_buffer[3];
p_out[5] = p_block->p_buffer[9];
/* Sample 3 */
p_out[6] = p_block->p_buffer[4];
p_out[7] = p_block->p_buffer[5];
p_out[8] = p_block->p_buffer[10];
/* Sample 4 */
p_out[9] = p_block->p_buffer[6];
p_out[10] = p_block->p_buffer[7];
p_out[11] = p_block->p_buffer[11];
p_block->i_buffer -= 12;
p_block->p_buffer += 12;
p_out += 12;
}
}
else if( i_bitspersample == 20 )
{
uint8_t *p_out = p_aout_buffer->p_buffer;
while( p_block->i_buffer / 10 )
{
/* Sample 1 */
p_out[0] = p_block->p_buffer[0];
p_out[1] = p_block->p_buffer[1];
p_out[2] = p_block->p_buffer[8] & 0xF0;
/* Sample 2 */
p_out[3] = p_block->p_buffer[2];
p_out[4] = p_block->p_buffer[3];
p_out[5] = p_block->p_buffer[8] << 4;
/* Sample 3 */
p_out[6] = p_block->p_buffer[4];
p_out[7] = p_block->p_buffer[5];
p_out[8] = p_block->p_buffer[9] & 0xF0;
/* Sample 4 */
p_out[9] = p_block->p_buffer[6];
p_out[10] = p_block->p_buffer[7];
p_out[11] = p_block->p_buffer[9] << 4;
p_block->i_buffer -= 10;
p_block->p_buffer += 10;
p_out += 12;
}
}
else
{
memcpy( p_aout_buffer->p_buffer, memcpy( p_aout_buffer->p_buffer,
p_block->p_buffer + LPCM_HEADER_LEN, p_block->p_buffer, p_block->i_buffer );
p_block->i_buffer - LPCM_HEADER_LEN ); }
block_Release( p_block ); block_Release( p_block );
return p_aout_buffer; return p_aout_buffer;
......
/***************************************************************************** /*****************************************************************************
* common.c : audio output management of common data structures * common.c : audio output management of common data structures
***************************************************************************** *****************************************************************************
* Copyright (C) 2002-2004 VideoLAN * Copyright (C) 2002-2005 VideoLAN
* $Id$ * $Id$
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
...@@ -129,6 +129,13 @@ void aout_FormatPrepare( audio_sample_format_t * p_format ) ...@@ -129,6 +129,13 @@ void aout_FormatPrepare( audio_sample_format_t * p_format )
i_result = 2; i_result = 2;
break; break;
case VLC_FOURCC('u','2','4','l'):
case VLC_FOURCC('s','2','4','l'):
case VLC_FOURCC('u','2','4','b'):
case VLC_FOURCC('s','2','4','b'):
i_result = 3;
break;
case VLC_FOURCC('f','l','3','2'): case VLC_FOURCC('f','l','3','2'):
case VLC_FOURCC('f','i','3','2'): case VLC_FOURCC('f','i','3','2'):
i_result = 4; i_result = 4;
......
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