#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++;
}
}
/* 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;
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;
}
return NULL;
}
+static int find_file_properties(const char *buf, int len)
+{
+ const char pattern[] = {0xa1, 0xdc, 0xab, 0x8c};
+ const char *p = search_pattern(pattern, sizeof(pattern), buf, len);
+
+ if (!p)
+ return -E_WMA_NO_GUID;
+ PARA_DEBUG_LOG("found file property guid@%0x\n", (int)(p - buf));
+ return p - buf + 16;
+}
+
/*
40 9e 69 f8 4d 5b cf 11 a8 fd 00 80 5f 5c 44 2b
*/
ahi->use_exp_vlc = ahi->flags2 & 0x0001;
ahi->use_bit_reservoir = ahi->flags2 & 0x0002;
ahi->use_variable_block_len = ahi->flags2 & 0x0004;
+
+ ret = find_file_properties(buf, ahi->header_len);
+ if (ret < 0)
+ return ret;
+ /* file property header is always 88 bytes (sans GUID) */
+ if (ret + 88 > loaded)
+ return 0;
+ start = buf + ret;
+ ahi->packet_size = read_u32(start + 76); /* min packet size */
+ /* we only support fixed packet sizes */
+ if (ahi->packet_size != read_u32(start + 80)) /* min != max */
+ return -E_BAD_ASF_FILE_PROPS;
+ if (ahi->packet_size <= ahi->block_align)
+ return -E_BAD_ASF_FILE_PROPS;
+ PARA_INFO_LOG("packet size: %u\n", ahi->packet_size);
return 1;
}
fn->min_iqs += 4096;
goto next_buffer;
}
- fn->min_iqs = 2 * (WMA_FRAME_SKIP + pwd->ahi.block_align);
+ fn->min_iqs = 2 * pwd->ahi.packet_size;
fn->private_data = pwd;
converted = pwd->ahi.header_len;
goto success;
}
- fn->min_iqs = WMA_FRAME_SKIP + pwd->ahi.block_align;
+ fn->min_iqs = pwd->ahi.packet_size;
if (fn->min_iqs > len)
goto success;
out_size = WMA_OUTPUT_BUFFER_SIZE;
btr_add_output(out, out_size, btrn);
} else
free(out);
- converted += ret + WMA_FRAME_SKIP;
+ converted += pwd->ahi.packet_size;
success:
btr_consume(btrn, converted);
return 0;