mirror of
https://github.com/panzi/mediaextract
synced 2024-12-17 22:54:42 +00:00
RIFF: added MTDF meta type, relaxed some conditions and moved an array to the stack
This commit is contained in:
parent
9e7244c6f1
commit
3584d2093a
70
src/riff.c
70
src/riff.c
@ -31,6 +31,8 @@
|
||||
#define CHUNK(c1,c2,c3,c4,required) CHUNK_SPEC(0,c1,c2,c3,c4,0,required)
|
||||
#define END { 0, 0, 0, 0 }
|
||||
#define BODY(...) { __VA_ARGS__, END }
|
||||
#define CHUNK_SPEC_COUNT(SPECS) ((sizeof(SPECS) / sizeof(struct riff_chunk_spec)) - 1)
|
||||
#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
|
||||
|
||||
struct riff_chunk_spec {
|
||||
uint32_t metatype;
|
||||
@ -215,6 +217,29 @@ static const struct riff_chunk_spec riff_webp_body[] = BODY(
|
||||
CHUNK('V','P','8','X', 0)
|
||||
);
|
||||
|
||||
#define MAX_CHUNK_SPEC_COUNT \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_empty_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_wav_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_avi_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_ani_fram_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_ani_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_pal_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_aud_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_dmbd_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_dmpr_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_dmcn_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_dsbc_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_dsfx_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_dmsc_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_sgt_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_sty_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_dmtl_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_dmtg_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_dmtk_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_dmbt_body), \
|
||||
MAX(CHUNK_SPEC_COUNT(riff_dmpt_body), \
|
||||
CHUNK_SPEC_COUNT(riff_webp_body)))))))))))))))))))))
|
||||
|
||||
static const struct riff_file_spec riff_file_specs[] = {
|
||||
{ RIFF('W','A','V','E', riff_wav_body ), "wav" },
|
||||
{ RIFF('A','V','I',' ', riff_avi_body ), "avi" },
|
||||
@ -238,6 +263,7 @@ static const struct riff_file_spec riff_file_specs[] = {
|
||||
{ RIFF('D','M','B','T', riff_dmbt_body), "riff" },
|
||||
{ RIFF('D','M','P','T', riff_dmpt_body), "riff" },
|
||||
{ RIFF('W','E','B','P', riff_webp_body), "webp" },
|
||||
{ RIFF('M','T','D','F', 0 ), "mtd" },
|
||||
|
||||
{ END, 0 }
|
||||
};
|
||||
@ -247,38 +273,26 @@ const uint8_t *riff_match(const uint8_t *data, size_t size,
|
||||
{
|
||||
if (spec->metatype)
|
||||
{
|
||||
if (size < 12 || MAGIC(data) != spec->metatype)
|
||||
if (size < 12 || MAGIC(data) != spec->metatype) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t chunk_size = le32toh(*(const uint32_t *)(data + 4));
|
||||
uint32_t type = MAGIC(data + 8);
|
||||
const size_t chunk_size = le32toh(*(const uint32_t *)(data + 4));
|
||||
const uint32_t type = MAGIC(data + 8);
|
||||
|
||||
if (type != spec->type)
|
||||
if (type != spec->type) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (chunk_size > size - 8)
|
||||
if (chunk_size > size - 8) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// match sub chunks
|
||||
const struct riff_chunk_spec *body = spec->body;
|
||||
uint32_t *counts = NULL;
|
||||
if (body)
|
||||
{
|
||||
size_t count = 0;
|
||||
for (const struct riff_chunk_spec *subspec = body; subspec->type; ++ subspec)
|
||||
++ count;
|
||||
uint32_t counts[MAX_CHUNK_SPEC_COUNT] = { 0 };
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
counts = (uint32_t *)calloc(count, sizeof(uint32_t));
|
||||
|
||||
if (!counts) {
|
||||
perror("parsing RIFF structure");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!body)
|
||||
{
|
||||
body = riff_empty_body;
|
||||
}
|
||||
@ -294,10 +308,7 @@ const uint8_t *riff_match(const uint8_t *data, size_t size,
|
||||
size_t subchunk_size = le32toh(*(const uint32_t *)(subdata + 4));
|
||||
|
||||
if (subchunk_size > subsize - 8)
|
||||
{
|
||||
free(counts);
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
for (size_t i = 0;; ++ i)
|
||||
{
|
||||
@ -315,7 +326,7 @@ const uint8_t *riff_match(const uint8_t *data, size_t size,
|
||||
|
||||
subdata += subchunk_size + 8;
|
||||
}
|
||||
|
||||
|
||||
for (size_t i = 0;; ++ i)
|
||||
{
|
||||
const struct riff_chunk_spec *subspec = body + i;
|
||||
@ -325,13 +336,10 @@ const uint8_t *riff_match(const uint8_t *data, size_t size,
|
||||
|
||||
if (subspec->required && counts[i] == 0)
|
||||
{
|
||||
free(counts);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
free(counts);
|
||||
|
||||
#if 0
|
||||
// If the sub chunk matching code above delivers to many false positives this code could be used
|
||||
// instead. This code is not really correct, because sub chunks could theoretically occure in any
|
||||
@ -354,7 +362,7 @@ const uint8_t *riff_match(const uint8_t *data, size_t size,
|
||||
if (size < 8 || MAGIC(data) != spec->type)
|
||||
return NULL;
|
||||
|
||||
size_t chunk_size = le32toh(*(const uint32_t *)(data + 4));
|
||||
const size_t chunk_size = le32toh(*(const uint32_t *)(data + 4));
|
||||
|
||||
if (chunk_size > size - 8)
|
||||
return NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user