Commit e4f4f59e authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

- XA file demux

- EA ADPCM decoder (Maxis games)
(- corner case memleak in adpcm decoder)
parent 509b4b9d
...@@ -983,7 +983,7 @@ VLC_ADD_PLUGINS([trivial_resampler ugly_resampler]) ...@@ -983,7 +983,7 @@ VLC_ADD_PLUGINS([trivial_resampler ugly_resampler])
VLC_ADD_PLUGINS([trivial_channel_mixer trivial_mixer]) VLC_ADD_PLUGINS([trivial_channel_mixer trivial_mixer])
VLC_ADD_PLUGINS([id3 playlist export sgimb m3u xtag]) VLC_ADD_PLUGINS([id3 playlist export sgimb m3u xtag])
VLC_ADD_PLUGINS([i420_rgb rawvideo blend scale image logo]) VLC_ADD_PLUGINS([i420_rgb rawvideo blend scale image logo])
VLC_ADD_PLUGINS([wav araw subtitle vobsub adpcm a52sys dtssys au]) VLC_ADD_PLUGINS([wav araw subtitle vobsub adpcm a52sys dtssys au xa])
VLC_ADD_PLUGINS([access_directory access_file access_udp access_tcp]) VLC_ADD_PLUGINS([access_directory access_file access_udp access_tcp])
VLC_ADD_PLUGINS([access_http access_mms access_ftp ipv4]) VLC_ADD_PLUGINS([access_http access_mms access_ftp ipv4])
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
* $Id$ * $Id$
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Remi Denis-Courmont <courmisch # via.ecp.fr>
* *
* 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
...@@ -54,7 +55,8 @@ enum adpcm_codec_e ...@@ -54,7 +55,8 @@ enum adpcm_codec_e
ADPCM_IMA_WAV, ADPCM_IMA_WAV,
ADPCM_MS, ADPCM_MS,
ADPCM_DK3, ADPCM_DK3,
ADPCM_DK4 ADPCM_DK4,
ADPCM_EA
}; };
struct decoder_sys_t struct decoder_sys_t
...@@ -72,6 +74,7 @@ static void DecodeAdpcmImaWav( decoder_t *, int16_t *, uint8_t * ); ...@@ -72,6 +74,7 @@ static void DecodeAdpcmImaWav( decoder_t *, int16_t *, uint8_t * );
static void DecodeAdpcmImaQT ( decoder_t *, int16_t *, uint8_t * ); static void DecodeAdpcmImaQT ( decoder_t *, int16_t *, uint8_t * );
static void DecodeAdpcmDk4 ( decoder_t *, int16_t *, uint8_t * ); static void DecodeAdpcmDk4 ( decoder_t *, int16_t *, uint8_t * );
static void DecodeAdpcmDk3 ( decoder_t *, int16_t *, uint8_t * ); static void DecodeAdpcmDk3 ( decoder_t *, int16_t *, uint8_t * );
static void DecodeAdpcmEA ( decoder_t *, int16_t *, uint8_t * );
static int pi_channels_maps[6] = static int pi_channels_maps[6] =
{ {
...@@ -135,19 +138,12 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -135,19 +138,12 @@ static int OpenDecoder( vlc_object_t *p_this )
case VLC_FOURCC('m','s',0x00,0x11): /* IMA ADPCM */ case VLC_FOURCC('m','s',0x00,0x11): /* IMA ADPCM */
case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */ case VLC_FOURCC('m','s',0x00,0x61): /* Duck DK4 ADPCM */
case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */ case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */
case VLC_FOURCC('X','A','J', 0): /* EA ADPCM */
break; break;
default: default:
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/* Allocate the memory needed to store the decoder's structure */
if( ( p_dec->p_sys = p_sys =
(decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
{
msg_Err( p_dec, "out of memory" );
return VLC_EGENERIC;
}
if( p_dec->fmt_in.audio.i_channels <= 0 || if( p_dec->fmt_in.audio.i_channels <= 0 ||
p_dec->fmt_in.audio.i_channels > 5 ) p_dec->fmt_in.audio.i_channels > 5 )
{ {
...@@ -161,6 +157,14 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -161,6 +157,14 @@ static int OpenDecoder( vlc_object_t *p_this )
return VLC_EGENERIC; return VLC_EGENERIC;
} }
/* Allocate the memory needed to store the decoder's structure */
if( ( p_dec->p_sys = p_sys =
(decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
{
msg_Err( p_dec, "out of memory" );
return VLC_ENOMEM;
}
switch( p_dec->fmt_in.i_codec ) switch( p_dec->fmt_in.i_codec )
{ {
case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */ case VLC_FOURCC('i','m','a', '4'): /* IMA ADPCM */
...@@ -178,6 +182,16 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -178,6 +182,16 @@ static int OpenDecoder( vlc_object_t *p_this )
case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */ case VLC_FOURCC('m','s',0x00,0x62): /* Duck DK3 ADPCM */
p_sys->codec = ADPCM_DK3; p_sys->codec = ADPCM_DK3;
break; break;
case VLC_FOURCC('X','A','J', 0): /* EA ADPCM */
p_sys->codec = ADPCM_EA;
p_dec->fmt_in.p_extra = calloc( 2 * p_dec->fmt_in.audio.i_channels,
sizeof( int16_t ) );
if( p_dec->fmt_in.p_extra == NULL )
{
free( p_sys );
return VLC_ENOMEM;
}
break;
} }
if( p_dec->fmt_in.audio.i_blockalign <= 0 ) if( p_dec->fmt_in.audio.i_blockalign <= 0 )
...@@ -216,6 +230,10 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -216,6 +230,10 @@ static int OpenDecoder( vlc_object_t *p_this )
p_dec->fmt_in.audio.i_channels = 2; p_dec->fmt_in.audio.i_channels = 2;
p_sys->i_samplesperblock = ( 4 * ( p_sys->i_block - 16 ) + 2 )/ 3; p_sys->i_samplesperblock = ( 4 * ( p_sys->i_block - 16 ) + 2 )/ 3;
break; break;
case ADPCM_EA:
p_sys->i_samplesperblock =
2 * (p_sys->i_block - p_dec->fmt_in.audio.i_channels) /
p_dec->fmt_in.audio.i_channels;
} }
msg_Dbg( p_dec, "format: samplerate:%dHz channels:%d bits/sample:%d " msg_Dbg( p_dec, "format: samplerate:%dHz channels:%d bits/sample:%d "
...@@ -303,6 +321,9 @@ static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -303,6 +321,9 @@ static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
DecodeAdpcmDk3( p_dec, (int16_t*)p_out->p_buffer, DecodeAdpcmDk3( p_dec, (int16_t*)p_out->p_buffer,
p_block->p_buffer ); p_block->p_buffer );
break; break;
case ADPCM_EA:
DecodeAdpcmEA( p_dec, (int16_t*)p_out->p_buffer,
p_block->p_buffer );
default: default:
break; break;
} }
...@@ -324,6 +345,8 @@ static void CloseDecoder( vlc_object_t *p_this ) ...@@ -324,6 +345,8 @@ static void CloseDecoder( vlc_object_t *p_this )
decoder_t *p_dec = (decoder_t *)p_this; decoder_t *p_dec = (decoder_t *)p_this;
decoder_sys_t *p_sys = p_dec->p_sys; decoder_sys_t *p_sys = p_dec->p_sys;
if( p_sys->codec == ADPCM_EA )
free( p_dec->fmt_in.p_extra );
free( p_sys ); free( p_sys );
} }
...@@ -693,3 +716,74 @@ static void DecodeAdpcmDk3( decoder_t *p_dec, int16_t *p_sample, ...@@ -693,3 +716,74 @@ static void DecodeAdpcmDk3( decoder_t *p_dec, int16_t *p_sample,
} }
} }
} }
/*
* EA ADPCM
*/
#define MAX_CHAN 5
static void DecodeAdpcmEA( decoder_t *p_dec, int16_t *p_sample,
uint8_t *p_buffer )
{
static const uint32_t EATable[]=
{
0x00000000, 0x000000F0, 0x000001CC, 0x00000188,
0x00000000, 0x00000000, 0xFFFFFF30, 0xFFFFFF24,
0x00000000, 0x00000001, 0x00000003, 0x00000004,
0x00000007, 0x00000008, 0x0000000A, 0x0000000B,
0x00000000, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFC
};
decoder_sys_t *p_sys = p_dec->p_sys;
uint8_t *p_end;
unsigned i_channels, c;
int16_t *prev, *cur;
int32_t c1[MAX_CHAN], c2[MAX_CHAN];
int8_t d[MAX_CHAN];
i_channels = p_dec->fmt_in.audio.i_channels;
p_end = &p_buffer[p_sys->i_block];
prev = (int16_t *)p_dec->fmt_in.p_extra;
cur = prev + i_channels;
for (c = 0; c < i_channels; c++)
{
uint8_t input;
input = p_buffer[c];
c1[c] = EATable[input >> 4];
c2[c] = EATable[(input >> 4) + 4];
d[c] = (input & 0xf) + 8;
}
for( p_buffer += i_channels; p_buffer < p_end ; p_buffer += i_channels)
{
for (c = 0; c < i_channels; c++)
{
int32_t spl;
spl = (p_buffer[c] >> 4) & 0xf;
spl = (spl << 0x1c) >> d[c];
spl = (spl + cur[c] * c1[c] + prev[c] * c2[c] + 0x80) >> 8;
CLAMP( spl, -32768, 32767 );
prev[c] = cur[c];
cur[c] = spl;
*(p_sample++) = spl;
}
for (c = 0; c < i_channels; c++)
{
int32_t spl;
spl = p_buffer[c] & 0xf;
spl = (spl << 0x1c) >> d[c];
spl = (spl + cur[c] * c1[c] + prev[c] * c2[c] + 0x80) >> 8;
CLAMP( spl, -32768, 32767 );
prev[c] = cur[c];
cur[c] = spl;
*(p_sample++) = spl;
}
}
}
...@@ -21,3 +21,4 @@ SOURCES_sgimb = sgimb.c ...@@ -21,3 +21,4 @@ SOURCES_sgimb = sgimb.c
SOURCES_mjpeg = mjpeg.c SOURCES_mjpeg = mjpeg.c
SOURCES_subtitle = subtitle.c SOURCES_subtitle = subtitle.c
SOURCES_vobsub = vobsub.c SOURCES_vobsub = vobsub.c
SOURCES_xa = xa.c
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