summaryrefslogtreecommitdiff
path: root/plugins/alac
diff options
context:
space:
mode:
authorGravatar waker <wakeroid@gmail.com>2012-08-03 21:02:05 +0200
committerGravatar waker <wakeroid@gmail.com>2012-08-03 21:02:05 +0200
commit34059c2a7262a564663f22d9260ae397cd1a6ad1 (patch)
tree8a11f4431726bcd7af4732623be91198563acd81 /plugins/alac
parent803ef0b70f08347df8c3d64c9b952d4c50d1be14 (diff)
alac: fixed samplerate detection; fixed decoder memleaks
Diffstat (limited to 'plugins/alac')
-rw-r--r--plugins/alac/alac.c29
-rw-r--r--plugins/alac/alac_plugin.c8
-rw-r--r--plugins/alac/decomp.h4
-rw-r--r--plugins/alac/demux.c83
-rw-r--r--plugins/alac/demux.h2
5 files changed, 68 insertions, 58 deletions
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