-/*
- * Copyright (C) 2009 Andre Noll <maan@tuebingen.mpg.de>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
+/* Copyright (C) 2009 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
/** \file wma_afh.c The audio format handler for WMA files. */
#include "wma.h"
#include "fd.h"
-#define FOR_EACH_FRAME(_f, _buf, _size, _ba) for (_f = (_buf); \
- _f + (_ba) + WMA_FRAME_SKIP < (_buf) + (_size); \
- _f += (_ba) + WMA_FRAME_SKIP)
+#define FOR_EACH_FRAME(_f, _buf, _size, _ps) for (_f = (_buf); \
+ _f + (_ps) < (_buf) + (_size); \
+ _f += (_ps))
/*
* Must be called on a frame boundary, e.g. start + header_len.
* \return Frame count, superframe count via *num_superframes.
*/
-static int count_frames(const char *buf, int buf_size, int block_align,
+static int count_frames(const char *buf, int buf_size, uint32_t packet_size,
int *num_superframes)
{
int fc = 0, sfc = 0; /* frame count, superframe count */
const uint8_t *p;
- FOR_EACH_FRAME(p, (uint8_t *)buf, buf_size, block_align) {
+ FOR_EACH_FRAME(p, (uint8_t *)buf, buf_size, packet_size) {
fc += p[WMA_FRAME_SKIP] & 0x0f;
sfc++;
}
PARA_INFO_LOG("%d frames, %d superframes\n", fc, sfc);
- if (num_superframes)
- *num_superframes = sfc;
+ *num_superframes = sfc;
return fc;
}
*out++ = in;
return 1;
}
- bytes = (wma_log2(in) + 4) / 5;
+ bytes = DIV_ROUND_UP(wma_log2(in), 5);
shift = (bytes - 1) * 6;
*out++ = (256 - (256 >> bytes)) | (in >> shift);
while (shift >= 6) {
}
/* Must be called on a frame boundary. */
-static int wma_make_chunk_table(char *buf, size_t buf_size, int block_align,
+static int wma_make_chunk_table(char *buf, size_t buf_size, uint32_t packet_size,
struct afh_info *afhi)
{
const uint8_t *f, *start = (uint8_t *)buf;
afhi->chunk_table[0] = 0;
afhi->chunk_table[1] = afhi->header_len;
- num_frames = count_frames(buf, buf_size, block_align,
+ num_frames = count_frames(buf, buf_size, packet_size,
&num_superframes);
ret = -E_NO_WMA;
if (num_frames == 0 || num_superframes == 0)
frames_per_chunk = num_frames / num_superframes / 2;
PARA_INFO_LOG("%d frames per chunk\n", frames_per_chunk);
j = 1;
- FOR_EACH_FRAME(f, start, buf_size, block_align) {
+ FOR_EACH_FRAME(f, start, buf_size, packet_size) {
count += f[WMA_FRAME_SKIP] & 0x0f;
while (count > j * frames_per_chunk) {
j++;
afhi->chunk_table,
ct_size * sizeof(uint32_t));
}
- afhi->chunk_table[j] = f - start + afhi->header_len + block_align + WMA_FRAME_SKIP;
+ afhi->chunk_table[j] = f - start + afhi->header_len
+ + packet_size;
}
}
afhi->chunks_total = j;
+ set_max_chunk_size(afhi);
set_chunk_tv(frames_per_chunk, afhi->frequency, &afhi->chunk_tv);
return 1;
fail:
ahi.use_variable_block_len? "vbl" : ""
);
wma_make_chunk_table(map + ahi.header_len, numbytes - ahi.header_len,
- ahi.block_align, afhi);
+ ahi.packet_size, afhi);
read_asf_tags(map, ahi.header_len, &afhi->tags);
return 0;
}
static int convert_utf8_to_utf16(char *src, char **dst)
{
- /*
- * Without specifying LE (little endian), iconv includes a byte order
- * mark (e.g. 0xFFFE) at the beginning.
- */
- iconv_t cd = iconv_open("UTF-16LE", "UTF-8");
+ iconv_t cd;
size_t sz, inbytes, outbytes, inbytesleft, outbytesleft;
char *inbuf, *outbuf;
int ret;
if (!src || !*src) {
*dst = para_calloc(2);
- ret = 0;
- goto out;
+ return 0;
}
- if (cd == (iconv_t) -1)
+ /*
+ * Without specifying LE (little endian), iconv includes a byte order
+ * mark (e.g. 0xFFFE) at the beginning.
+ */
+ cd = iconv_open("UTF-16LE", "UTF-8");
+ if (cd == (iconv_t)-1) {
+ *dst = NULL;
return -ERRNO_TO_PARA_ERROR(errno);
+ }
inbuf = src;
/* even though src is in UTF-8, strlen() should DTRT */
inbytes = inbytesleft = strlen(src);
sz = iconv(cd, ICONV_CAST &inbuf, &inbytesleft, &outbuf, &outbytesleft);
if (sz == (size_t)-1) {
ret = -ERRNO_TO_PARA_ERROR(errno);
+ free(*dst);
+ *dst = NULL;
goto out;
}
assert(outbytes >= outbytesleft);
*dst = outbuf;
PARA_INFO_LOG("converted %s to %d UTF-16 bytes\n", src, ret);
out:
- if (ret < 0)
- free(*dst);
if (iconv_close(cd) < 0)
PARA_WARNING_LOG("iconv_close: %s\n", strerror(errno));
return ret;
struct asf_object *result)
{
const char *cr, *rating; /* orig data */
- uint16_t orig_title_bytes, orig_artist_bytes, orig_cr_bytes,
- orig_comment_bytes, orig_rating_bytes;
+ uint16_t orig_cr_bytes, orig_rating_bytes;
/* pointers to new UTF-16 tags */
char *artist = NULL, *title = NULL, *comment = NULL;
/* number of bytes in UTF-16 for the new tags */
ret = convert_utf8_to_utf16(tags->artist, &artist);
if (ret < 0)
return ret;
+ assert(artist);
artist_bytes = ret;
ret = convert_utf8_to_utf16(tags->title, &title);
if (ret < 0)
goto out;
+ assert(title);
title_bytes = ret;
ret = convert_utf8_to_utf16(tags->comment, &comment);
if (ret < 0)
goto out;
+ assert(comment);
comment_bytes = ret;
if (cdo) {
+ uint16_t orig_title_bytes, orig_artist_bytes, orig_comment_bytes;
/*
* Sizes of the five fields (stored as 16-bit numbers) are
* located after the header (16 bytes) and the cdo size (8
cr = cdo->ptr + 34 + orig_title_bytes + orig_artist_bytes;
rating = cr + orig_cr_bytes + orig_comment_bytes;
} else {
- orig_title_bytes = 2;
- orig_artist_bytes = 2;
orig_cr_bytes = 2;
- orig_comment_bytes = 2;
orig_rating_bytes = 2;
cr = null;
rating = null;
ret = convert_utf8_to_utf16(tags->album, &album);
if (ret < 0)
return ret;
+ assert(album);
album_bytes = ret;
ret = convert_utf8_to_utf16(tags->year, &year);
if (ret < 0)
goto out;
+ assert(year);
year_bytes = ret;
result->size = 16 + 8 + 2; /* GUID, size, count */
/* name_length + name + null + data type + val length + val */