-
- *chunk_sample = total + (*chunk - chunk1) * chunk1samples;
-
- return 0;
-}
-
-static int32_t mp4ff_chunk_to_offset(const mp4ff_t * f, const int32_t track,
- const int32_t chunk)
-{
- const mp4ff_track_t *p_track = f->track[track];
-
- if (p_track->stco_entry_count && (chunk > p_track->stco_entry_count)) {
- return p_track->stco_chunk_offset[p_track->stco_entry_count -
- 1];
- } else if (p_track->stco_entry_count) {
- return p_track->stco_chunk_offset[chunk - 1];
- } else {
- return 8;
- }
-
- return 0;
-}
-
-static int32_t mp4ff_sample_range_size(const mp4ff_t * f, const int32_t track,
- const int32_t chunk_sample, const int32_t sample)
-{
- int32_t i, total;
- const mp4ff_track_t *p_track = f->track[track];
-
- if (p_track->stsz_sample_size) {
- return (sample - chunk_sample) * p_track->stsz_sample_size;
- } else {
- if (sample >= p_track->stsz_sample_count)
- return 0; //error
-
- for (i = chunk_sample, total = 0; i < sample; i++) {
- total += p_track->stsz_table[i];
- }
- }
-
- return total;
-}
-static int32_t mp4ff_sample_to_offset(const mp4ff_t * f, const int32_t track,
- const int32_t sample)
-{
- int32_t chunk, chunk_sample, chunk_offset1, chunk_offset2;
-
- mp4ff_chunk_of_sample(f, track, sample, &chunk_sample, &chunk);
-
- chunk_offset1 = mp4ff_chunk_to_offset(f, track, chunk);
- chunk_offset2 = chunk_offset1 + mp4ff_sample_range_size(f,
- track, chunk_sample, sample);
- return chunk_offset2;
-}
-
-int32_t mp4ff_set_sample_position(mp4ff_t * f, const int32_t track,
- const int32_t sample)
-{
- int32_t offset;
-
- offset = mp4ff_sample_to_offset(f, track, sample);
- mp4ff_set_position(f, offset);
-
- return 0;
-}
-
-static int32_t mp4ff_audio_frame_size(const mp4ff_t * f, const int32_t track,
- const int32_t sample)
-{
- int32_t bytes;
- const mp4ff_track_t *p_track = f->track[track];
-
- if (p_track->stsz_sample_size) {
- bytes = p_track->stsz_sample_size;
- } else {
- bytes = p_track->stsz_table[sample];
- }
-
- return bytes;
-}
-
-int32_t mp4ff_read_sample_getsize(mp4ff_t * f, const int track,
- const int sample)
-{
- int32_t temp = mp4ff_audio_frame_size(f, track, sample);
- if (temp < 0)
- temp = 0;
- return temp;
-}
-
-uint32_t mp4ff_get_sample_rate(const mp4ff_t * f, const int32_t track)
-{
- return f->track[track]->sampleRate;
-}
-
-uint32_t mp4ff_get_channel_count(const mp4ff_t * f, const int32_t track)
-{
- return f->track[track]->channelCount;
-}
-
-int32_t mp4ff_num_samples(const mp4ff_t * 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;
-}
-
-mp4ff_t *mp4ff_open_read_metaonly(mp4ff_callback_t * f)
-{
- mp4ff_t *ff = malloc(sizeof (mp4ff_t));
-
- memset(ff, 0, sizeof (mp4ff_t));
-
- ff->stream = f;
-
- parse_atoms(ff, 1);
-
- if (ff->error) {
- free(ff);
- ff = NULL;
- }
-
- return ff;
-}
-
-int32_t mp4ff_meta_get_num_items(const mp4ff_t * f)
-{
- return f->tags.count;
-}
-
-int32_t mp4ff_meta_get_by_index(const mp4ff_t * f, uint32_t index,
- char **item, char **value)
-{
- if (index >= f->tags.count) {
- *item = NULL;
- *value = NULL;
- return 0;
- } else {
- *item = strdup(f->tags.tags[index].item);
- *value = strdup(f->tags.tags[index].value);
- return 1;
- }
-}
-
-static uint32_t find_atom(mp4ff_t * 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;
-
- mp4ff_set_position(f, atom_offset);
-
- if (remaining < 8)
- break;
- atom_size = mp4ff_read_int32(f);
- if (atom_size > remaining || atom_size < 8)
- break;
- mp4ff_read_data(f, atom_name, 4);
-
- if (!memcmp(atom_name, name, 4)) {
- mp4ff_set_position(f, atom_offset);
- return 1;
- }
-
- remaining -= atom_size;
- atom_offset += atom_size;
- }
- return 0;
-}
-static uint32_t find_atom_v2(mp4ff_t * 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 = mp4ff_position(f);
- uint32_t mysize = mp4ff_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)) {
- mp4ff_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
- {
- mp4ff_set_position(f, first_base);
- return 1;
- } else
- return 0;
-}
-
-typedef struct {
- void *data;
- unsigned written;
- unsigned allocated;
- unsigned error;
-} membuffer;
-
-#define stricmp strcasecmp
-
-static membuffer *membuffer_create(void)
-{
- const unsigned initial_size = 256;
-
- membuffer *buf = (membuffer *) malloc(sizeof (membuffer));
- buf->data = malloc(initial_size);
- buf->written = 0;
- buf->allocated = initial_size;
- buf->error = buf->data == 0 ? 1 : 0;
-
- return buf;
-}
-
-static unsigned membuffer_write(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(membuffer * buf, const char *data)
-{
- return membuffer_write(buf, data, 4) == 4 ? 1 : 0;
-}
-
-static unsigned membuffer_write_int16(membuffer * buf, uint16_t data)
-{
- uint8_t temp[2] = { (uint8_t) (data >> 8), (uint8_t) data };
- return membuffer_write(buf, temp, 2);
-}
-
-static unsigned membuffer_write_int32(membuffer * buf, uint32_t data)
-{
- uint8_t temp[4] = { (uint8_t) (data >> 24), (uint8_t) (data >> 16),
- (uint8_t) (data >> 8), (uint8_t) data };
- return membuffer_write(buf, temp, 4);
-}
-
-static void membuffer_write_track_tag(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(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 mp4ff_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;
-}
-
-typedef struct {
- const char *atom;
- const char *name;
-} stdmeta_entry;
-
-static 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(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(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 membuffer * buf)
-{
- return buf->error;
-}
-
-static void membuffer_free(membuffer * buf)
-{
- if (buf->data)
- free(buf->data);
- free(buf);