/*
- * Copyright (C) 2009 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2009-2011 Andre Noll <maan@systemlinux.org>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
return out - result;
}
-static void get_str16(const char *in, int len, char *out, int out_size)
+static char *get_str16(const char *in, int len)
{
const char *p = in;
- char *q = out;
+ int out_size = 0, out_len = 0;
+ char *out = NULL;
len /= 2;
- while (len-- && q + 7 + 1 < out + out_size) {
- uint32_t x = read_u16(p);
+ while (len--) {
+ uint32_t x;
+ if (out_len + 7 + 1 >= out_size) {
+ out_size = 2 * out_size + 50;
+ out = para_realloc(out, out_size);
+ }
+ x = read_u16(p);
p += 2;
- q += put_utf8(x, q);
+ out_len += put_utf8(x, out + out_len);
if (x == 0)
- return;
+ return out;
}
- *q = '\0';
+ if (out)
+ out[out_len] = '\0';
+ return out;
}
static const char comment_header[] = {
static void read_asf_tags(const char *buf, int buf_size, struct taginfo *ti)
{
- const char *p, *end = buf + buf_size;
- char tag[255];
+ const char *p, *end = buf + buf_size, *q;
+ uint16_t len1, len2, len3, len4, len5;
p = search_pattern(comment_header, sizeof(comment_header),
buf, buf_size);
- if (p) {
- int len1, len2, len3, len4, len5;
- p += 24;
- len1 = read_u16(p);
- p += 2;
- len2 = read_u16(p);
- p += 2;
- len3 = read_u16(p);
- p += 2;
- len4 = read_u16(p);
- p += 2;
- len5 = read_u16(p);
- p += 2;
- /* TODO: Check len values */
- get_str16(p, len1, tag, sizeof(tag));
- ti->title = para_strdup(tag);
- PARA_INFO_LOG("title: %s\n", tag);
- get_str16(p + len1, len2, tag, sizeof(tag));
- ti->artist = para_strdup(tag);
- PARA_INFO_LOG("artist: %s\n", tag);
- get_str16(p + len1 + len2 + len3 + len4, len5, tag, sizeof(tag));
- ti->comment = para_strdup(tag);
- PARA_INFO_LOG("comment: %s\n", tag);
- } else
+ if (!p || p + 34 >= end) {
PARA_NOTICE_LOG("comment header not found\n");
+ goto next;
+ }
+ p += 24;
+ len1 = read_u16(p);
+ p += 2;
+ len2 = read_u16(p);
+ p += 2;
+ len3 = read_u16(p);
+ p += 2;
+ len4 = read_u16(p);
+ p += 2;
+ len5 = read_u16(p);
+ p += 2;
+ if (p + len1 >= end)
+ goto next;
+ ti->title = get_str16(p, len1);
+ p += len1;
+ if (p + len2 >= end)
+ goto next;
+ ti->artist = get_str16(p, len2);
+ p += len2 + len3 + len4;
+ if (p + len5 >= end)
+ goto next;
+ ti->comment = get_str16(p, len5);
+next:
p = search_pattern(extended_content_header, sizeof(extended_content_header),
buf, buf_size);
- if (p) {
- const char *q;
-
- q = search_pattern(year_tag_header, sizeof(year_tag_header),
- p, end - p);
- if (q) {
- const char *r = q + sizeof(year_tag_header) + 6;
- get_str16(r, end - r, tag, sizeof(tag));
- ti->year = para_strdup(tag);
- PARA_INFO_LOG("year: %s\n", tag);
- }
- q = search_pattern(album_tag_header, sizeof(album_tag_header),
- p, end - p);
- if (q) {
- const char *r = q + sizeof(album_tag_header) + 6;
- get_str16(r, end - r, tag, sizeof(tag));
- ti->album = para_strdup(tag);
- PARA_INFO_LOG("album: %s\n", tag);
- }
- return;
- } else
+ if (!p) {
PARA_NOTICE_LOG("extended content header not found\n");
-
+ return;
+ }
+ q = search_pattern(year_tag_header, sizeof(year_tag_header),
+ p, end - p);
+ if (q) {
+ const char *r = q + sizeof(year_tag_header) + 6;
+ if (r < end)
+ ti->year = get_str16(r, end - r);
+ }
+ q = search_pattern(album_tag_header, sizeof(album_tag_header),
+ p, end - p);
+ if (q) {
+ const char *r = q + sizeof(album_tag_header) + 6;
+ if (r < end)
+ ti->album = get_str16(r, end - r);
+ }
}
-static void set_chunk_tv(int num_frames, int num_chunks, int frequency,
+static void set_chunk_tv(int frames_per_chunk, int frequency,
struct timeval *result)
{
- uint64_t x = (uint64_t)num_frames * 1000 * 1000
- / frequency / num_chunks;
+ uint64_t x = (uint64_t)frames_per_chunk * 2048 * 1000 * 1000
+ / frequency;
result->tv_sec = x / 1000 / 1000;
result->tv_usec = x % (1000 * 1000);
- PARA_INFO_LOG("%d chunks, chunk time: %lums\n", num_chunks,
- tv2ms(result));
+ PARA_INFO_LOG("chunk time: %lums\n", tv2ms(result));
}
/* Must be called on a frame boundary. */
struct afh_info *afhi)
{
const uint8_t *f, *start = (uint8_t *)buf;
- int i, j, frames_per_chunk, chunk_time;
+ int j, frames_per_chunk;
size_t ct_size = 250;
int ret, count = 0, num_frames, num_superframes;
goto fail;
afhi->seconds_total = num_frames * 2048 /* FIXME */
/ afhi->frequency;
- frames_per_chunk = num_frames / num_superframes;
+ frames_per_chunk = num_frames / num_superframes / 2;
PARA_INFO_LOG("%d frames per chunk\n", frames_per_chunk);
- i = 0;
j = 1;
FOR_EACH_FRAME(f, start, buf_size, block_align) {
count += f[WMA_FRAME_SKIP] & 0x0f;
}
}
afhi->chunks_total = j;
- set_chunk_tv(num_frames * 2048, j + 10 /* FIXME */, afhi->frequency, &afhi->chunk_tv);
+ set_chunk_tv(frames_per_chunk, afhi->frequency, &afhi->chunk_tv);
return 1;
fail:
free(afhi->chunk_table);
afhi->frequency = ahi.sample_rate;
afhi->channels = ahi.channels;
afhi->header_len = ahi.header_len;
- afhi->header_offset = 0;
wma_make_chunk_table(map + ahi.header_len, numbytes - ahi.header_len,
ahi.block_align, afhi);
read_asf_tags(map, ahi.header_len, &afhi->tags);