From 34059c2a7262a564663f22d9260ae397cd1a6ad1 Mon Sep 17 00:00:00 2001 From: waker Date: Fri, 3 Aug 2012 21:02:05 +0200 Subject: alac: fixed samplerate detection; fixed decoder memleaks --- plugins/alac/alac.c | 29 ++++++++++++++++ plugins/alac/alac_plugin.c | 8 ++++- plugins/alac/decomp.h | 4 +++ plugins/alac/demux.c | 83 +++++++++++++++------------------------------- plugins/alac/demux.h | 2 +- 5 files changed, 68 insertions(+), 58 deletions(-) (limited to 'plugins/alac') diff --git a/plugins/alac/alac.c b/plugins/alac/alac.c index 469000da..a65270fa 100644 --- a/plugins/alac/alac.c +++ b/plugins/alac/alac.c @@ -150,12 +150,18 @@ void alac_set_info(alac_file *alac, char *inputbuffer) alac->setinfo_8a_rate = *(uint32_t*)ptr; if (!host_bigendian) _Swap32(alac->setinfo_8a_rate); + ptr += 4; allocate_buffers(alac); } +int +alac_get_samplerate(alac_file *alac) { + return alac->setinfo_8a_rate; +} + /* stream reading */ /* supports reading 1 to 16 bits, in big endian format */ @@ -1154,6 +1160,7 @@ void decode_frame(alac_file *alac, alac_file *create_alac(int samplesize, int numchannels) { alac_file *newfile = malloc(sizeof(alac_file)); + memset (newfile, 0, sizeof (alac_file)); newfile->samplesize = samplesize; newfile->numchannels = numchannels; @@ -1162,3 +1169,25 @@ alac_file *create_alac(int samplesize, int numchannels) return newfile; } +void alac_file_free (alac_file *alac) { + if (alac->predicterror_buffer_a) { + free (alac->predicterror_buffer_a); + } + if (alac->predicterror_buffer_b) { + free (alac->predicterror_buffer_b); + } + if (alac->outputsamples_buffer_a) { + free (alac->outputsamples_buffer_a); + } + if (alac->outputsamples_buffer_b) { + free (alac->outputsamples_buffer_b); + } + if (alac->uncompressed_bytes_buffer_a) { + free (alac->uncompressed_bytes_buffer_a); + } + if (alac->uncompressed_bytes_buffer_b) { + free (alac->uncompressed_bytes_buffer_b); + } + free (alac); +} + diff --git a/plugins/alac/alac_plugin.c b/plugins/alac/alac_plugin.c index 69b100ba..d1075a07 100644 --- a/plugins/alac/alac_plugin.c +++ b/plugins/alac/alac_plugin.c @@ -167,6 +167,7 @@ alacplug_init (DB_fileinfo_t *_info, DB_playItem_t *it) { info->alac = create_alac(info->demux_res.sample_size, info->demux_res.num_channels); alac_set_info(info->alac, info->demux_res.codecdata); + info->demux_res.sample_rate = alac_get_samplerate (info->alac); int totalsamples = alacplug_get_totalsamples (&info->demux_res); if (!info->file->vfs->is_streaming ()) { @@ -203,7 +204,7 @@ alacplug_free (DB_fileinfo_t *_info) { stream_destroy (info->stream); } if (info->alac) { - free (info->alac); + alac_file_free (info->alac); } free (info); } @@ -478,6 +479,11 @@ alacplug_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) { } } + alac_file *alac = create_alac(demux_res.sample_size, demux_res.num_channels); + alac_set_info(alac, demux_res.codecdata); + demux_res.sample_rate = alac_get_samplerate (alac); + alac_file_free (alac); + it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id); deadbeef->pl_add_meta (it, ":FILETYPE", "ALAC"); diff --git a/plugins/alac/decomp.h b/plugins/alac/decomp.h index 23dbc527..47b3a9a7 100644 --- a/plugins/alac/decomp.h +++ b/plugins/alac/decomp.h @@ -9,5 +9,9 @@ void decode_frame(alac_file *alac, void *outbuffer, int *outputsize); void alac_set_info(alac_file *alac, char *inputbuffer); +int alac_get_samplerate(alac_file *alac); +void alac_file_free (alac_file *alac); + + #endif /* __ALAC__DECOMP_H */ diff --git a/plugins/alac/demux.c b/plugins/alac/demux.c index 6c817f6d..b495d1a5 100644 --- a/plugins/alac/demux.c +++ b/plugins/alac/demux.c @@ -113,7 +113,7 @@ static int read_chunk_stsd(qtmovie_t *qtmovie, size_t chunk_len) { unsigned int i; uint32_t numentries; - size_t size_remaining = chunk_len - 8; /* FIXME WRONG */ + size_t size_remaining = chunk_len - 8; /* version */ stream_read_uint8(qtmovie->stream); @@ -127,100 +127,71 @@ static int read_chunk_stsd(qtmovie_t *qtmovie, size_t chunk_len) numentries = stream_read_uint32(qtmovie->stream); size_remaining -= 4; - if (numentries != 1) - { - trace ("only expecting one entry in sample description atom!\n"); - return 0; - } +// if (numentries != 1) +// { +// trace ("only expecting one entry in sample description atom!\n"); +// return 0; +// } for (i = 0; i < numentries; i++) { uint32_t entry_size; - uint16_t version; uint32_t entry_remaining; entry_size = stream_read_uint32(qtmovie->stream); qtmovie->res->format = stream_read_uint32(qtmovie->stream); + trace ("format: %c%c%c%c\n",SPLITFOURCC(qtmovie->res->format)); entry_remaining = entry_size; entry_remaining -= 8; - /* sound info: */ - stream_skip(qtmovie->stream, 6); /* reserved */ - entry_remaining -= 6; - - version = stream_read_uint16(qtmovie->stream); - if (version != 1) - trace ("unknown version??\n"); - entry_remaining -= 2; - - /* revision level */ - stream_read_uint16(qtmovie->stream); - /* vendor */ - stream_read_uint32(qtmovie->stream); - entry_remaining -= 6; + /* sound info: */ - /* EH?? spec doesn't say theres an extra 16 bits here.. but there is! */ - stream_read_uint16(qtmovie->stream); - entry_remaining -= 2; + /* reserved + data reference index + sound version + reserved */ + stream_skip(qtmovie->stream, 6 + 2 + 2 + 6); + entry_remaining -= 6 + 2 + 2 + 6; qtmovie->res->num_channels = stream_read_uint16(qtmovie->stream); - qtmovie->res->sample_size = stream_read_uint16(qtmovie->stream); entry_remaining -= 4; - /* compression id */ - stream_read_uint16(qtmovie->stream); /* packet size */ - stream_read_uint16(qtmovie->stream); - entry_remaining -= 4; - - /* sample rate - 32bit fixed point = 16bit?? */ - qtmovie->res->sample_rate = stream_read_uint16(qtmovie->stream); - entry_remaining -= 2; - - /* skip 2 */ stream_skip(qtmovie->stream, 2); - entry_remaining -= 2; + qtmovie->res->sample_rate = stream_read_uint32(qtmovie->stream); + /* reserved size */ + stream_skip(qtmovie->stream, 2); + entry_remaining -= 8; /* remaining is codec data */ - -#if 0 - qtmovie->res->codecdata_len = stream_read_uint32(qtmovie->stream); - if (qtmovie->res->codecdata_len != entry_remaining) - trace ("perhaps not? %i vs %i\n", - qtmovie->res->codecdata_len, entry_remaining); - entry_remaining -= 4; - stream_read_uint32(qtmovie->stream); /* 'alac' */ - entry_remaining -= 4; - - qtmovie->res->codecdata = malloc(qtmovie->res->codecdata_len - 8); - - stream_read(qtmovie->stream, - entry_remaining, - qtmovie->res->codecdata); - entry_remaining = 0; - -#else /* 12 = audio format atom, 8 = padding */ qtmovie->res->codecdata_len = entry_remaining + 12 + 8; - qtmovie->res->codecdata = malloc(qtmovie->res->codecdata_len); + if (qtmovie->res->codecdata_len > 64) + { + trace ("codecdata too large (%d) in stsd\n", + (int)qtmovie->res->codecdata_len); + return 0; + } + memset(qtmovie->res->codecdata, 0, qtmovie->res->codecdata_len); /* audio format atom */ +#if 0 + /* The ALAC decoder skips these bytes, so there is no need to store them, + and this code isn't endian/alignment safe */ ((unsigned int*)qtmovie->res->codecdata)[0] = 0x0c000000; ((unsigned int*)qtmovie->res->codecdata)[1] = MAKEFOURCC('a','m','r','f'); ((unsigned int*)qtmovie->res->codecdata)[2] = MAKEFOURCC('c','a','l','a'); +#endif stream_read(qtmovie->stream, entry_remaining, ((char*)qtmovie->res->codecdata) + 12); entry_remaining -= entry_remaining; -#endif if (entry_remaining) stream_skip(qtmovie->stream, entry_remaining); + qtmovie->res->format_read = 1; if (qtmovie->res->format != MAKEFOURCC('a','l','a','c')) { diff --git a/plugins/alac/demux.h b/plugins/alac/demux.h index 8447bf84..de4a3114 100644 --- a/plugins/alac/demux.h +++ b/plugins/alac/demux.h @@ -31,7 +31,7 @@ typedef struct uint32_t num_sample_byte_sizes; uint32_t codecdata_len; - void *codecdata; + char codecdata[64]; uint32_t mdat_len; #if 0 -- cgit v1.2.3