- return t->stsz_sample_size;
- return t->stsz_table[sample];
-}
-
-uint32_t mp4ff_get_sample_rate(const struct mp4ff *f, const int32_t track)
-{
- return f->track[track]->sampleRate;
-}
-
-uint32_t mp4ff_get_channel_count(const struct mp4ff *f, const int32_t track)
-{
- return f->track[track]->channelCount;
-}
-
-int32_t mp4ff_num_samples(const struct mp4ff *f, const int32_t track)
-{
- int32_t i;
- int32_t total = 0;
-
- for (i = 0; i < f->track[track]->stts_entry_count; i++) {
- total += f->track[track]->stts_sample_count[i];
- }
- return total;
-}
-
-struct mp4ff *mp4ff_open_read_metaonly(struct mp4ff_callback *f)
-{
- struct mp4ff *ff = para_calloc(sizeof(struct mp4ff));
-
- ff->stream = f;
-
- parse_atoms(ff, 1);
-
- if (ff->error) {
- free(ff);
- ff = NULL;
- }
-
- return ff;
-}
-
-int32_t mp4ff_meta_get_num_items(const struct mp4ff *f)
-{
- return f->tags.count;
-}
-
-int32_t mp4ff_meta_get_by_index(const struct mp4ff *f, uint32_t index,
- char **item, char **value)
-{
- if (index >= f->tags.count) {
- *item = NULL;
- *value = NULL;
- return 0;
- } else {
- *item = para_strdup(f->tags.tags[index].item);
- *value = para_strdup(f->tags.tags[index].value);
- return 1;
- }
-}
-
-static uint32_t find_atom(struct mp4ff *f, uint64_t base, uint32_t size,
- const char *name)
-{
- uint32_t remaining = size;
- uint64_t atom_offset = base;
- for (;;) {
- char atom_name[4];
- uint32_t atom_size;
-
- set_position(f, atom_offset);
-
- if (remaining < 8)
- break;
- atom_size = read_int32(f);
- if (atom_size > remaining || atom_size < 8)
- break;
- read_data(f, atom_name, 4);
-
- if (!memcmp(atom_name, name, 4)) {
- set_position(f, atom_offset);
- return 1;
- }
-
- remaining -= atom_size;
- atom_offset += atom_size;
- }
- return 0;
-}
-
-static uint32_t find_atom_v2(struct mp4ff *f, uint64_t base, uint32_t size,
- const char *name, uint32_t extraheaders, const char *name_inside)
-{
- uint64_t first_base = (uint64_t) (-1);
- while (find_atom(f, base, size, name)) //try to find atom <name> with atom <name_inside> in it
- {
- uint64_t mybase = get_position(f);
- uint32_t mysize = read_int32(f);
-
- if (first_base == (uint64_t) (-1))
- first_base = mybase;
-
- if (mysize < 8 + extraheaders)
- break;
-
- if (find_atom (f, mybase + (8 + extraheaders),
- mysize - (8 + extraheaders), name_inside)) {
- set_position(f, mybase);
- return 2;
- }
- base += mysize;
- if (size <= mysize) {
- size = 0;
- break;
- }
- size -= mysize;
- }
-
- if (first_base != (uint64_t) (-1)) //wanted atom inside not found
- {
- set_position(f, first_base);
- return 1;
- } else
- return 0;
-}
-
-struct membuffer {
- void *data;
- unsigned written;
- unsigned allocated;
- unsigned error;
-};
-
-#define stricmp strcasecmp
-
-static struct membuffer *membuffer_create(void)
-{
- const unsigned initial_size = 256;
-
- struct membuffer *buf = para_malloc(sizeof(*buf));
- buf->data = para_malloc(initial_size);
- buf->written = 0;
- buf->allocated = initial_size;
- buf->error = buf->data == 0 ? 1 : 0;
-
- return buf;
-}
-
-static unsigned membuffer_write(struct membuffer *buf, const void *ptr, unsigned bytes)
-{
- unsigned dest_size = buf->written + bytes;
-
- if (buf->error)
- return 0;
- if (dest_size > buf->allocated) {
- do {
- buf->allocated <<= 1;
- } while (dest_size > buf->allocated);
-
- {
- void *newptr = realloc(buf->data, buf->allocated);
- if (newptr == 0) {
- free(buf->data);
- buf->data = 0;
- buf->error = 1;
- return 0;
- }
- buf->data = newptr;
- }
- }
-
- if (ptr)
- memcpy((char *) buf->data + buf->written, ptr, bytes);
- buf->written += bytes;
- return bytes;
-}
-
-static unsigned membuffer_write_atom_name(struct membuffer *buf, const char *data)
-{
- return membuffer_write(buf, data, 4) == 4 ? 1 : 0;
-}
-
-static unsigned membuffer_write_int16(struct membuffer *buf, uint16_t data)
-{
- uint8_t temp[2];
-
- write_u16_be(temp, data);
- return membuffer_write(buf, temp, 2);
-}
-
-static unsigned membuffer_write_int32(struct membuffer *buf, uint32_t data)
-{
- uint8_t temp[4];
- write_u32_be(temp, data);
- return membuffer_write(buf, temp, 4);
-}
-
-static void membuffer_write_track_tag(struct membuffer *buf, const char *name,
- uint32_t index, uint32_t total)
-{
- membuffer_write_int32(buf,
- 8 /*atom header */ + 8 /*data atom header */ +
- 8 /*flags + reserved */ + 8 /*actual data */ );
- membuffer_write_atom_name(buf, name);
- membuffer_write_int32(buf,
- 8 /*data atom header */ +
- 8 /*flags + reserved */ + 8 /*actual data */ );
- membuffer_write_atom_name(buf, "data");
- membuffer_write_int32(buf, 0); //flags
- membuffer_write_int32(buf, 0); //reserved
- membuffer_write_int16(buf, 0);
- membuffer_write_int16(buf, (uint16_t) index); //track number
- membuffer_write_int16(buf, (uint16_t) total); //total tracks
- membuffer_write_int16(buf, 0);
-}
-
-static void membuffer_write_int16_tag(struct membuffer *buf, const char *name,
- uint16_t value)
-{
- membuffer_write_int32(buf,
- 8 /*atom header */ + 8 /*data atom header */ +
- 8 /*flags + reserved */ + 2 /*actual data */ );
- membuffer_write_atom_name(buf, name);
- membuffer_write_int32(buf,
- 8 /*data atom header */ +
- 8 /*flags + reserved */ + 2 /*actual data */ );
- membuffer_write_atom_name(buf, "data");
- membuffer_write_int32(buf, 0); //flags
- membuffer_write_int32(buf, 0); //reserved
- membuffer_write_int16(buf, value); //value
-}
-
-static uint32_t myatoi(const char *param)
-{
- return param ? atoi(param) : 0;
-}
-
-static uint32_t meta_genre_to_index(const char *genrestr)
-{
- unsigned n;
- for (n = 0; n < sizeof (ID3v1GenreList) / sizeof (ID3v1GenreList[0]); n++) {
- if (!stricmp(genrestr, ID3v1GenreList[n]))
- return n + 1;
- }
- return 0;
-}
-
-struct stdmeta_entry {
- const char *atom;
- const char *name;
-};
-
-struct stdmeta_entry stdmetas[] = {
- {"\xA9" "nam", "title"},
- {"\xA9" "ART", "artist"},
- {"\xA9" "wrt", "writer"},
- {"\xA9" "alb", "album"},
- {"\xA9" "day", "date"},
- {"\xA9" "too", "tool"},
- {"\xA9" "cmt", "comment"},
- {"cpil", "compilation"},
- {"covr", "cover"},
- {"aART", "album_artist"},
-};
-
-static const char *find_standard_meta(const char *name) //returns atom name if found, 0 if not
-{
- unsigned n;
- for (n = 0; n < sizeof (stdmetas) / sizeof (stdmetas[0]); n++) {
- if (!stricmp(name, stdmetas[n].name))
- return stdmetas[n].atom;
- }
- return 0;
-}
-
-static void membuffer_write_std_tag(struct membuffer *buf, const char *name,
- const char *value)
-{
- uint32_t flags = 1;
-
- /* special check for compilation flag */
- if (strcmp(name, "cpil") == 0) {
- flags = 21;
- }
-
- membuffer_write_int32(buf,
- 8 /*atom header */ + 8 /*data atom header */ +
- 8 /*flags + reserved */ + strlen(value));
- membuffer_write_atom_name(buf, name);
- membuffer_write_int32(buf,
- 8 /*data atom header */ +
- 8 /*flags + reserved */ + strlen(value));
- membuffer_write_atom_name(buf, "data");
- membuffer_write_int32(buf, flags); //flags
- membuffer_write_int32(buf, 0); //reserved
- membuffer_write(buf, value, strlen(value));
-}
-
-static void membuffer_write_custom_tag(struct membuffer *buf, const char *name,
- const char *value)
-{
- membuffer_write_int32(buf,
- 8 /*atom header */ +
- 0x1C /*weirdo itunes atom */ +
- 12 /*name atom header */ + strlen(name) +
- 16 /*data atom header + flags */ + strlen(value));
- membuffer_write_atom_name(buf, "----");
- membuffer_write_int32(buf, 0x1C); //weirdo itunes atom
- membuffer_write_atom_name(buf, "mean");
- membuffer_write_int32(buf, 0);
- membuffer_write(buf, "com.apple.iTunes", 16);
- membuffer_write_int32(buf, 12 + strlen(name));
- membuffer_write_atom_name(buf, "name");
- membuffer_write_int32(buf, 0);
- membuffer_write(buf, name, strlen(name));
- membuffer_write_int32(buf,
- 8 /*data atom header */ +
- 8 /*flags + reserved */ + strlen(value));
- membuffer_write_atom_name(buf, "data");
- membuffer_write_int32(buf, 1); //flags
- membuffer_write_int32(buf, 0); //reserved
- membuffer_write(buf, value, strlen(value));
-}
-
-static unsigned membuffer_error(const struct membuffer *buf)
-{
- return buf->error;
-}
-
-static void membuffer_free(struct membuffer *buf)
-{
- free(buf->data);
- free(buf);
-}
-
-static unsigned membuffer_get_size(const struct membuffer *buf)
-{
- return buf->written;
-}
-
-static void *membuffer_detach(struct membuffer *buf)
-{
- void *ret;
-
- if (buf->error)
- return 0;
-
- ret = realloc(buf->data, buf->written);
-
- if (ret == 0)
- free(buf->data);
-
- buf->data = 0;
- buf->error = 1;
-
- return ret;
-}
-
-static uint32_t create_ilst(const struct mp4ff_metadata *data, void **out_buffer,
- uint32_t * out_size)
-{
- struct membuffer *buf = membuffer_create();
- unsigned metaptr;
- char *mask = para_calloc(data->count);
- {
- const char *tracknumber_ptr = 0, *totaltracks_ptr = 0;
- const char *discnumber_ptr = 0, *totaldiscs_ptr = 0;
- const char *genre_ptr = 0, *tempo_ptr = 0;
- for (metaptr = 0; metaptr < data->count; metaptr++) {
- struct mp4ff_tag *tag = &data->tags[metaptr];
- if (!stricmp(tag->item, "tracknumber") || !stricmp(tag->item, "track")) {
- if (tracknumber_ptr == 0)
- tracknumber_ptr = tag->value;
- mask[metaptr] = 1;
- } else if (!stricmp(tag->item, "totaltracks")) {
- if (totaltracks_ptr == 0)
- totaltracks_ptr = tag->value;
- mask[metaptr] = 1;
- } else if (!stricmp(tag->item, "discnumber")
- || !stricmp(tag->item, "disc")) {
- if (discnumber_ptr == 0)
- discnumber_ptr = tag->value;
- mask[metaptr] = 1;
- } else if (!stricmp(tag->item, "totaldiscs")) {
- if (totaldiscs_ptr == 0)
- totaldiscs_ptr = tag->value;
- mask[metaptr] = 1;
- } else if (!stricmp(tag->item, "genre")) {
- if (genre_ptr == 0)
- genre_ptr = tag->value;
- mask[metaptr] = 1;
- } else if (!stricmp(tag->item, "tempo")) {
- if (tempo_ptr == 0)
- tempo_ptr = tag->value;
- mask[metaptr] = 1;
- }
-
- }
-
- if (tracknumber_ptr)
- membuffer_write_track_tag(buf, "trkn",
- myatoi(tracknumber_ptr),
- myatoi(totaltracks_ptr));
- if (discnumber_ptr)
- membuffer_write_track_tag(buf, "disk",
- myatoi(discnumber_ptr),
- myatoi(totaldiscs_ptr));
- if (tempo_ptr)
- membuffer_write_int16_tag(buf, "tmpo",
- (uint16_t) myatoi(tempo_ptr));
-
- if (genre_ptr) {
- uint32_t index = meta_genre_to_index(genre_ptr);
- if (index == 0)
- membuffer_write_std_tag(buf, "©gen",
- genre_ptr);
- else
- membuffer_write_int16_tag(buf, "gnre",
- (uint16_t) index);
- }
- }
-
- for (metaptr = 0; metaptr < data->count; metaptr++) {
- if (!mask[metaptr]) {
- struct mp4ff_tag *tag = &data->tags[metaptr];
- const char *std_meta_atom = find_standard_meta(tag->item);
- if (std_meta_atom) {
- membuffer_write_std_tag(buf, std_meta_atom,
- tag->value);
- } else {
- membuffer_write_custom_tag(buf, tag->item,
- tag->value);
- }
- }
- }
-
- free(mask);
-
- if (membuffer_error(buf)) {
- membuffer_free(buf);
- return 0;
- }
-
- *out_size = membuffer_get_size(buf);
- *out_buffer = membuffer_detach(buf);
- membuffer_free(buf);
-