]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - mp4.c
mp4: Rename overlong variable in mp4ff_parse_tag().
[paraslash.git] / mp4.c
diff --git a/mp4.c b/mp4.c
index d04137a911cebf83f516a1b5abce3732b080c845..47d98bcf0403e46b1ca955efc2db45e0a4e0cf63 100644 (file)
--- a/mp4.c
+++ b/mp4.c
@@ -5,16 +5,18 @@
  * See file COPYING.
  */
 
+#include <regex.h>
+
 #include "para.h"
+#include "string.h"
 #include "mp4.h"
 
-#define USE_TAGGING
 int32_t mp4ff_total_tracks(const mp4ff_t * f)
 {
        return f->total_tracks;
 }
 
-int32_t mp4ff_read_data(mp4ff_t * f, int8_t * data, uint32_t size)
+static int32_t mp4ff_read_data(mp4ff_t * f, void *data, uint32_t size)
 {
        int32_t result = 1;
 
@@ -40,12 +42,10 @@ static int32_t mp4ff_atom_get_size(const int8_t * data)
        d = (uint8_t) data[3];
 
        result = (a << 24) | (b << 16) | (c << 8) | d;
-       //if (result > 0 && result < 8) result = 8;
-
        return (int32_t) result;
 }
 
-uint64_t mp4ff_read_int64(mp4ff_t * f)
+static uint64_t mp4ff_read_int64(mp4ff_t * f)
 {
        uint8_t data[8];
        uint64_t result = 0;
@@ -324,7 +324,7 @@ static uint8_t mp4ff_atom_name_to_type(const int8_t a, const int8_t b,
 }
 
 /* read atom header, return atom size, atom size is with header included */
-uint64_t mp4ff_atom_read_header(mp4ff_t * f, uint8_t * atom_type,
+static uint64_t mp4ff_atom_read_header(mp4ff_t * f, uint8_t * atom_type,
                                uint8_t * header_size)
 {
        uint64_t size;
@@ -343,14 +343,12 @@ uint64_t mp4ff_atom_read_header(mp4ff_t * f, uint8_t * atom_type,
                *header_size = 16;
                size = mp4ff_read_int64(f);
        }
-       //printf("%c%c%c%c\n", atom_header[4], atom_header[5], atom_header[6], atom_header[7]);
-
        *atom_type = mp4ff_atom_name_to_type(atom_header[4], atom_header[5],
                atom_header[6], atom_header[7]);
        return size;
 }
 
-int64_t mp4ff_position(const mp4ff_t * f)
+static int64_t mp4ff_position(const mp4ff_t * f)
 {
        return f->current_position;
 }
@@ -359,19 +357,14 @@ static int need_parse_when_meta_only(uint8_t atom_type)
 {
        switch (atom_type) {
        case ATOM_EDTS:
-//      case ATOM_MDIA:
-//      case ATOM_MINF:
        case ATOM_DRMS:
        case ATOM_SINF:
        case ATOM_SCHI:
-//      case ATOM_STBL:
-//      case ATOM_STSD:
        case ATOM_STTS:
        case ATOM_STSZ:
        case ATOM_STZ2:
        case ATOM_STCO:
        case ATOM_STSC:
-//      case ATOM_CTTS:
        case ATOM_FRMA:
        case ATOM_IVIV:
        case ATOM_PRIV:
@@ -381,7 +374,7 @@ static int need_parse_when_meta_only(uint8_t atom_type)
        }
 }
 
-int32_t mp4ff_set_position(mp4ff_t * f, const int64_t position)
+static int32_t mp4ff_set_position(mp4ff_t * f, const int64_t position)
 {
        f->stream->seek(f->stream->user_data, position);
        f->current_position = position;
@@ -398,20 +391,17 @@ static void mp4ff_track_add(mp4ff_t * f)
                f->error++;
                return;
        }
-
-       f->track[f->total_tracks - 1] = malloc(sizeof (mp4ff_track_t));
-
-       memset(f->track[f->total_tracks - 1], 0, sizeof (mp4ff_track_t));
+       f->track[f->total_tracks - 1] = para_calloc(sizeof (mp4ff_track_t));
 }
 
-uint8_t mp4ff_read_char(mp4ff_t * f)
+static uint8_t mp4ff_read_char(mp4ff_t * f)
 {
        uint8_t output;
        mp4ff_read_data(f, &output, 1);
        return output;
 }
 
-uint32_t mp4ff_read_int24(mp4ff_t * f)
+static uint32_t mp4ff_read_int24(mp4ff_t * f)
 {
        uint32_t result;
        uint32_t a, b, c;
@@ -426,7 +416,7 @@ uint32_t mp4ff_read_int24(mp4ff_t * f)
        return (uint32_t) result;
 }
 
-uint32_t mp4ff_read_int32(mp4ff_t * f)
+static uint32_t mp4ff_read_int32(mp4ff_t * f)
 {
        uint32_t result;
        uint32_t a, b, c, d;
@@ -455,12 +445,8 @@ static int32_t mp4ff_read_stsz(mp4ff_t * f)
        if (f->track[f->total_tracks - 1]->stsz_sample_size == 0) {
                int32_t i;
                f->track[f->total_tracks - 1]->stsz_table =
-                       (int32_t *)malloc(f->track[f->total_tracks - 1]->stsz_sample_count
+                       para_malloc(f->track[f->total_tracks - 1]->stsz_sample_count
                                * sizeof (int32_t));
-
-               if (!f->track[f->total_tracks - 1]->stsz_table)
-                       return f->error++;
-
                for (i = 0; i < f->track[f->total_tracks - 1]->stsz_sample_count
                                && !f->stream->read_error; i++) {
                        f->track[f->total_tracks - 1]->stsz_table[i] = mp4ff_read_int32(f);
@@ -487,29 +473,15 @@ static int32_t mp4ff_read_stts(mp4ff_t * f)
        mp4ff_read_int24(f);    /* flags */
        p_track->stts_entry_count = mp4ff_read_int32(f);
 
-       p_track->stts_sample_count = (int32_t *)malloc(p_track->stts_entry_count
+       p_track->stts_sample_count = para_malloc(p_track->stts_entry_count
                 * sizeof (int32_t));
-       p_track->stts_sample_delta = (int32_t *)malloc(p_track->stts_entry_count
+       p_track->stts_sample_delta = para_malloc(p_track->stts_entry_count
                * sizeof (int32_t));
-
-       if (p_track->stts_sample_count == 0 || p_track->stts_sample_delta == 0) {
-               if (p_track->stts_sample_count) {
-                       free(p_track->stts_sample_count);
-                       p_track->stts_sample_count = 0;
-               }
-               if (p_track->stts_sample_delta) {
-                       free(p_track->stts_sample_delta);
-                       p_track->stts_sample_delta = 0;
-               }
-               p_track->stts_entry_count = 0;
-               return 0;
-       } else {
-               for (i = 0; i < f->track[f->total_tracks - 1]->stts_entry_count && !f->stream->read_error; i++) {       /* CVE-2017-9254 */
-                       p_track->stts_sample_count[i] = mp4ff_read_int32(f);
-                       p_track->stts_sample_delta[i] = mp4ff_read_int32(f);
-               }
-               return 1;
+       for (i = 0; i < f->track[f->total_tracks - 1]->stts_entry_count && !f->stream->read_error; i++) { /* CVE-2017-9254 */
+               p_track->stts_sample_count[i] = mp4ff_read_int32(f);
+               p_track->stts_sample_delta[i] = mp4ff_read_int32(f);
        }
+       return 1;
 }
 
 static int32_t mp4ff_read_ctts(mp4ff_t * f)
@@ -528,29 +500,16 @@ static int32_t mp4ff_read_ctts(mp4ff_t * f)
        mp4ff_read_int24(f);    /* flags */
        p_track->ctts_entry_count = mp4ff_read_int32(f);
 
-       p_track->ctts_sample_count = (int32_t *)malloc(p_track->ctts_entry_count
+       p_track->ctts_sample_count = para_malloc(p_track->ctts_entry_count
                * sizeof (int32_t));
-       p_track->ctts_sample_offset = (int32_t *)malloc(p_track->ctts_entry_count
+       p_track->ctts_sample_offset = para_malloc(p_track->ctts_entry_count
                * sizeof (int32_t));
 
-       if (p_track->ctts_sample_count == 0 || p_track->ctts_sample_offset == 0) {
-               if (p_track->ctts_sample_count) {
-                       free(p_track->ctts_sample_count);
-                       p_track->ctts_sample_count = 0;
-               }
-               if (p_track->ctts_sample_offset) {
-                       free(p_track->ctts_sample_offset);
-                       p_track->ctts_sample_offset = 0;
-               }
-               p_track->ctts_entry_count = 0;
-               return 0;
-       } else {
-               for (i = 0; i < f->track[f->total_tracks - 1]->ctts_entry_count && !f->stream->read_error; i++) {       /* CVE-2017-9257 */
-                       p_track->ctts_sample_count[i] = mp4ff_read_int32(f);
-                       p_track->ctts_sample_offset[i] = mp4ff_read_int32(f);
-               }
-               return 1;
+       for (i = 0; i < f->track[f->total_tracks - 1]->ctts_entry_count && !f->stream->read_error; i++) { /* CVE-2017-9257 */
+               p_track->ctts_sample_count[i] = mp4ff_read_int32(f);
+               p_track->ctts_sample_offset[i] = mp4ff_read_int32(f);
        }
+       return 1;
 }
 
 static int32_t mp4ff_read_stsc(mp4ff_t * f)
@@ -565,32 +524,15 @@ static int32_t mp4ff_read_stsc(mp4ff_t * f)
        f->track[f->total_tracks - 1]->stsc_entry_count = mp4ff_read_int32(f);
 
        f->track[f->total_tracks - 1]->stsc_first_chunk =
-               (int32_t *) malloc(f->track[f->total_tracks - 1]->stsc_entry_count *
+               para_malloc(f->track[f->total_tracks - 1]->stsc_entry_count *
                sizeof (int32_t));
        f->track[f->total_tracks - 1]->stsc_samples_per_chunk =
-               (int32_t *) malloc(f->track[f->total_tracks - 1]->stsc_entry_count *
+               para_malloc(f->track[f->total_tracks - 1]->stsc_entry_count *
                sizeof (int32_t));
        f->track[f->total_tracks - 1]->stsc_sample_desc_index =
-               (int32_t *) malloc(f->track[f->total_tracks - 1]->stsc_entry_count *
+               para_malloc(f->track[f->total_tracks - 1]->stsc_entry_count *
                sizeof (int32_t));
 
-       /* CVE-2017-9219 */
-       if (!f->track[f->total_tracks - 1]->stsc_first_chunk) {
-               return f->error++;
-       }
-       if (!f->track[f->total_tracks - 1]->stsc_samples_per_chunk) {
-               free(f->track[f->total_tracks - 1]->stsc_first_chunk);
-               f->track[f->total_tracks - 1]->stsc_first_chunk = NULL;
-               return f->error++;
-       }
-       if (!f->track[f->total_tracks - 1]->stsc_sample_desc_index) {
-               free(f->track[f->total_tracks - 1]->stsc_first_chunk);
-               f->track[f->total_tracks - 1]->stsc_first_chunk = NULL;
-               free(f->track[f->total_tracks - 1]->stsc_samples_per_chunk);
-               f->track[f->total_tracks - 1]->stsc_samples_per_chunk = NULL;
-               return f->error++;
-       }
-
        for (i = 0; i < f->track[f->total_tracks - 1]->stsc_entry_count && !f->stream->read_error; i++) {       /* CVE-2017-9255 */
                f->track[f->total_tracks - 1]->stsc_first_chunk[i] =
                        mp4ff_read_int32(f);
@@ -615,13 +557,8 @@ static int32_t mp4ff_read_stco(mp4ff_t * f)
        f->track[f->total_tracks - 1]->stco_entry_count = mp4ff_read_int32(f);
 
        f->track[f->total_tracks - 1]->stco_chunk_offset =
-               (int32_t *) malloc(f->track[f->total_tracks - 1]->stco_entry_count *
+               para_malloc(f->track[f->total_tracks - 1]->stco_entry_count *
                sizeof (int32_t));
-
-       /* CVE-2017-9220 */
-       if (!f->track[f->total_tracks - 1]->stco_chunk_offset)
-               return f->error++;
-
        for (i = 0; i < f->track[f->total_tracks - 1]->stco_entry_count && !f->stream->read_error; i++) {       /* CVE-2017-9256 */
                f->track[f->total_tracks - 1]->stco_chunk_offset[i] =
                mp4ff_read_int32(f);
@@ -630,7 +567,7 @@ static int32_t mp4ff_read_stco(mp4ff_t * f)
        return 0;
 }
 
-uint16_t mp4ff_read_int16(mp4ff_t * f)
+static uint16_t mp4ff_read_int16(mp4ff_t * f)
 {
        uint32_t result;
        uint32_t a, b;
@@ -644,7 +581,7 @@ uint16_t mp4ff_read_int16(mp4ff_t * f)
        return (uint16_t) result;
 }
 
-uint32_t mp4ff_read_mp4_descr_length(mp4ff_t * f)
+static uint32_t mp4ff_read_mp4_descr_length(mp4ff_t * f)
 {
        uint8_t b;
        uint8_t numBytes = 0;
@@ -707,24 +644,19 @@ static int32_t mp4ff_read_esds(mp4ff_t * f)
        f->track[f->total_tracks - 1]->decoderConfigLen =
                mp4ff_read_mp4_descr_length(f);
 
-       if (f->track[f->total_tracks - 1]->decoderConfig)
-               free(f->track[f->total_tracks - 1]->decoderConfig);
+       free(f->track[f->total_tracks - 1]->decoderConfig);
        f->track[f->total_tracks - 1]->decoderConfig =
-               malloc(f->track[f->total_tracks - 1]->decoderConfigLen);
+               para_malloc(f->track[f->total_tracks - 1]->decoderConfigLen);
        if (f->track[f->total_tracks - 1]->decoderConfig) {
                mp4ff_read_data(f, f->track[f->total_tracks - 1]->decoderConfig,
                                f->track[f->total_tracks -
                                         1]->decoderConfigLen);
-       } else {
-               f->track[f->total_tracks - 1]->decoderConfigLen = 0;
        }
-
        /* will skip the remainder of the atom */
        return 0;
 }
 static int32_t mp4ff_read_mp4a(mp4ff_t * f)
 {
-       uint64_t size;
        int32_t i;
        uint8_t atom_type = 0;
        uint8_t header_size = 0;
@@ -750,7 +682,7 @@ static int32_t mp4ff_read_mp4a(mp4ff_t * f)
 
        mp4ff_read_int16(f);
 
-       size = mp4ff_atom_read_header(f, &atom_type, &header_size);
+       mp4ff_atom_read_header(f, &atom_type, &header_size);
        if (atom_type == ATOM_ESDS) {
                mp4ff_read_esds(f);
        }
@@ -828,7 +760,7 @@ static int32_t mp4ff_read_mvhd(mp4ff_t * f)
 }
 
 static int32_t mp4ff_tag_add_field(mp4ff_metadata_t * tags, const char *item,
-                char *value, int32_t len)
+               const char *value, int32_t len)
 {
        void *backup = (void *) tags->tags;
 
@@ -838,33 +770,18 @@ static int32_t mp4ff_tag_add_field(mp4ff_metadata_t * tags, const char *item,
        tags->tags = (mp4ff_tag_t *) realloc(tags->tags,
                (tags->count + 1) * sizeof (mp4ff_tag_t));
        if (!tags->tags) {
-               if (backup)
-                       free(backup);
+               free(backup);
                return 0;
        } else {
-               tags->tags[tags->count].item = strdup(item);
+               tags->tags[tags->count].item = para_strdup(item);
                tags->tags[tags->count].len = len;
                if (len >= 0) {
-                       tags->tags[tags->count].value = malloc(len + 1);
-                       if (tags->tags[tags->count].value != NULL) {
-                               memcpy(tags->tags[tags->count].value, value, len);
-                               tags->tags[tags->count].value[len] = 0;
-                       }
+                       tags->tags[tags->count].value = para_malloc(len + 1);
+                       memcpy(tags->tags[tags->count].value, value, len);
+                       tags->tags[tags->count].value[len] = 0;
                } else {
-                       tags->tags[tags->count].value = strdup(value);
-               }
-
-               if (!tags->tags[tags->count].item || !tags->tags[tags->count].value) {
-                       if (!tags->tags[tags->count].item)
-                               free(tags->tags[tags->count].item);
-                       if (!tags->tags[tags->count].value)
-                               free(tags->tags[tags->count].value);
-                       tags->tags[tags->count].item = NULL;
-                       tags->tags[tags->count].value = NULL;
-                       tags->tags[tags->count].len = 0;
-                       return 0;
+                       tags->tags[tags->count].value = para_strdup(value);
                }
-
                tags->count++;
                return 1;
        }
@@ -901,7 +818,7 @@ static const char *ID3v1GenreList[] = {
        "Anime", "JPop", "SynthPop",
 };
 
-const char *mp4ff_meta_index_to_genre(uint32_t idx)
+static const char *mp4ff_meta_index_to_genre(uint32_t idx)
 {
        if (idx > 0 && idx <= sizeof (ID3v1GenreList) / sizeof (ID3v1GenreList[0])) {
                return ID3v1GenreList[idx - 1];
@@ -910,22 +827,18 @@ const char *mp4ff_meta_index_to_genre(uint32_t idx)
        }
 }
 
-char *mp4ff_read_string(mp4ff_t * f, uint32_t length)
+static char *mp4ff_read_string(mp4ff_t * f, uint32_t length)
 {
-       char *str = (char *) malloc(length + 1);
-       if (str != 0) {
-               if ((uint32_t) mp4ff_read_data(f, str, length) != length) {
-                       free(str);
-                       str = 0;
-               } else {
-                       str[length] = 0;
-               }
-       }
+       char *str = para_malloc(length + 1);
+       if ((uint32_t)mp4ff_read_data(f, str, length) != length) {
+               free(str);
+               str = NULL;
+       } else
+               str[length] = 0;
        return str;
 }
 
-static int32_t mp4ff_set_metadata_name(mp4ff_t * f, const uint8_t atom_type,
-               char **name)
+static int32_t mp4ff_set_metadata_name(const uint8_t atom_type, char **name)
 {
        static char *tag_names[] = {
                "unknown", "title", "artist", "writer", "album",
@@ -1035,115 +948,105 @@ static int32_t mp4ff_set_metadata_name(mp4ff_t * f, const uint8_t atom_type,
                break;
        }
 
-       *name = strdup(tag_names[tag_idx]);
-
+       *name = para_strdup(tag_names[tag_idx]);
        return 0;
 }
 
-static int32_t mp4ff_parse_tag(mp4ff_t * f, const uint8_t parent_atom_type,
+static int32_t mp4ff_parse_tag(mp4ff_t * f, const uint8_t parent,
                const int32_t size)
 {
        uint8_t atom_type;
        uint8_t header_size = 0;
-       uint64_t subsize, sumsize = 0;
+       uint64_t subsize, sumsize;
        char *name = NULL;
        char *data = NULL;
        uint32_t done = 0;
        uint32_t len = 0;
+       uint64_t destpos;
 
-       while (sumsize < size && !f->stream->read_error) {      /* CVE-2017-9222 */
-               uint64_t destpos;
+       for (
+               sumsize = 0;
+               sumsize < size && !f->stream->read_error; /* CVE-2017-9222 */
+               mp4ff_set_position(f, destpos), sumsize += subsize
+       ) {
                subsize = mp4ff_atom_read_header(f, &atom_type, &header_size);
                destpos = mp4ff_position(f) + subsize - header_size;
-               if (!done) {
-                       if (atom_type == ATOM_DATA) {
-                               mp4ff_read_char(f);     /* version */
-                               mp4ff_read_int24(f);    /* flags */
-                               mp4ff_read_int32(f);    /* reserved */
-
-                               /* some need special attention */
-                               if (parent_atom_type == ATOM_GENRE2 || parent_atom_type == ATOM_TEMPO) {
-                                       if (subsize - header_size >= 8 + 2) {
-                                               uint16_t val = mp4ff_read_int16(f);
-
-                                               if (parent_atom_type == ATOM_TEMPO) {
-                                                       char temp[16];
-                                                       sprintf(temp,
-                                                               "%.5u BPM",
-                                                               val);
-                                                       mp4ff_tag_add_field(&(f-> tags), "tempo", temp, -1);
-                                               } else {
-                                                       const char *temp = mp4ff_meta_index_to_genre(val);
-                                                       if (temp) {
-                                                               mp4ff_tag_add_field (&(f->tags), "genre", temp, -1);
-                                                       }
-                                               }
-                                               done = 1;
-                                       }
-                               } else if (parent_atom_type == ATOM_TRACK || parent_atom_type == ATOM_DISC) {
-                                       /* if (!done && subsize - header_size >= 8 + 8) */
-                                       /* modified by AJS */
-                                       if (!done && (subsize - header_size) >= (sizeof (char) + sizeof (uint8_t) * 3 + sizeof (uint32_t) +     /* version + flags + reserved */
-                                                                                +(parent_atom_type == ATOM_TRACK ? sizeof (uint16_t) : 0)      /* leading uint16_t if ATOM_TRACK */
-                                                                                +sizeof (uint16_t)     /* track / disc */
-                                                                                +sizeof (uint16_t))    /* totaltracks / totaldiscs */) {
-                                               uint16_t index, total;
-                                               char temp[32];
-                                               mp4ff_read_int16(f);
-                                               index = mp4ff_read_int16(f);
-                                               total = mp4ff_read_int16(f);
-                                               if (parent_atom_type == ATOM_TRACK)
-                                                       mp4ff_read_int16(f);
-
-                                               sprintf(temp, "%d", index);
-                                               mp4ff_tag_add_field(&(f->tags), parent_atom_type == ATOM_TRACK ?
-                                                       "track" : "disc", temp, -1);
-                                               if (total > 0) {
-                                                       sprintf(temp, "%d",
-                                                               total);
-                                                       mp4ff_tag_add_field(& (f-> tags),
-                                                               parent_atom_type == ATOM_TRACK?
-                                                               "totaltracks" : "totaldiscs", temp, -1);
-                                               }
-                                               done = 1;
-                                       }
+               if (done)
+                       continue;
+               if (atom_type == ATOM_NAME) {
+                       mp4ff_read_char(f);     /* version */
+                       mp4ff_read_int24(f);    /* flags */
+                       free(name);
+                       name = mp4ff_read_string(f, (uint32_t) (subsize - (header_size + 4)));
+                       continue;
+               }
+               if (atom_type != ATOM_DATA)
+                       continue;
+               mp4ff_read_char(f);     /* version */
+               mp4ff_read_int24(f);    /* flags */
+               mp4ff_read_int32(f);    /* reserved */
+
+               /* some need special attention */
+               if (parent == ATOM_GENRE2 || parent == ATOM_TEMPO) {
+                       if (subsize - header_size >= 8 + 2) {
+                               uint16_t val = mp4ff_read_int16(f);
+
+                               if (parent == ATOM_TEMPO) {
+                                       char temp[16];
+                                       sprintf(temp, "%.5u BPM", val);
+                                       mp4ff_tag_add_field(&(f-> tags), "tempo", temp, -1);
                                } else {
-                                       if (data) {
-                                               free(data);
-                                               data = NULL;
-                                       }
-                                       data = mp4ff_read_string(f, (uint32_t) (subsize - (header_size + 8)));
-                                       len = (uint32_t) (subsize - (header_size + 8));
+                                       const char *temp = mp4ff_meta_index_to_genre(val);
+                                       if (temp)
+                                               mp4ff_tag_add_field (&(f->tags), "genre", temp, -1);
                                }
-                       } else if (atom_type == ATOM_NAME) {
-                               if (!done) {
-                                       mp4ff_read_char(f);     /* version */
-                                       mp4ff_read_int24(f);    /* flags */
-                                       if (name)
-                                               free(name);
-                                       name = mp4ff_read_string(f, (uint32_t) (subsize - (header_size + 4)));
+                               done = 1;
+                       }
+               } else if (parent == ATOM_TRACK || parent == ATOM_DISC) {
+                       if (subsize - header_size >= (sizeof (char) + sizeof (uint8_t) * 3 + sizeof (uint32_t) +        /* version + flags + reserved */
+                                                                +(parent == ATOM_TRACK ? sizeof (uint16_t) : 0)        /* leading uint16_t if ATOM_TRACK */
+                                                                +sizeof (uint16_t)     /* track / disc */
+                                                                +sizeof (uint16_t))    /* totaltracks / totaldiscs */) {
+                               uint16_t index, total;
+                               char temp[32];
+                               mp4ff_read_int16(f);
+                               index = mp4ff_read_int16(f);
+                               total = mp4ff_read_int16(f);
+                               if (parent == ATOM_TRACK)
+                                       mp4ff_read_int16(f);
+
+                               sprintf(temp, "%d", index);
+                               mp4ff_tag_add_field(&(f->tags), parent == ATOM_TRACK ?
+                                       "track" : "disc", temp, -1);
+                               if (total > 0) {
+                                       sprintf(temp, "%d",
+                                               total);
+                                       mp4ff_tag_add_field(& (f-> tags),
+                                               parent == ATOM_TRACK?
+                                               "totaltracks" : "totaldiscs", temp, -1);
                                }
+                               done = 1;
                        }
-                       mp4ff_set_position(f, destpos);
-                       sumsize += subsize;
+               } else {
+                       free(data);
+                       data = mp4ff_read_string(f, (uint32_t) (subsize - (header_size + 8)));
+                       len = (uint32_t) (subsize - (header_size + 8));
                }
        }
-
        if (data) {
                if (!done) {
                        if (name == NULL)
-                               mp4ff_set_metadata_name(f, parent_atom_type,
-                                                       &name);
+                               mp4ff_set_metadata_name(parent , &name);
                        if (name)
                                mp4ff_tag_add_field(&(f->tags), name, data, len);
                }
 
                free(data);
        }
-       if (name)
-               free(name);
+       free(name);
        return 1;
 }
+
 static int32_t mp4ff_read_mdhd(mp4ff_t * f)
 {
        uint32_t version;
@@ -1173,7 +1076,7 @@ static int32_t mp4ff_read_mdhd(mp4ff_t * f)
        return 1;
 }
 
-int32_t mp4ff_parse_metadata(mp4ff_t * f, const int32_t size)
+static int32_t mp4ff_parse_metadata(mp4ff_t * f, const int32_t size)
 {
        uint64_t subsize, sumsize = 0;
        uint8_t atom_type;
@@ -1215,7 +1118,7 @@ static int32_t mp4ff_read_meta(mp4ff_t * f, const uint64_t size)
        return 0;
 }
 
-int32_t mp4ff_atom_read(mp4ff_t * f, const int32_t size,
+static int32_t mp4ff_atom_read(mp4ff_t * f, const int32_t size,
                        const uint8_t atom_type)
 {
        uint64_t dest_position = mp4ff_position(f) + size - 8;
@@ -1243,11 +1146,9 @@ int32_t mp4ff_atom_read(mp4ff_t * f, const int32_t size,
        } else if (atom_type == ATOM_MDHD) {
                /* track header */
                mp4ff_read_mdhd(f);
-#ifdef USE_TAGGING
        } else if (atom_type == ATOM_META) {
                /* iTunes Metadata box */
                mp4ff_read_meta(f, size);
-#endif
        }
 
        mp4ff_set_position(f, dest_position);
@@ -1255,7 +1156,7 @@ int32_t mp4ff_atom_read(mp4ff_t * f, const int32_t size,
 }
 
 /* parse atoms that are sub atoms of other atoms */
-int32_t parse_sub_atoms(mp4ff_t * f, const uint64_t total_size, int meta_only)
+static int32_t parse_sub_atoms(mp4ff_t * f, const uint64_t total_size, int meta_only)
 {
        uint64_t size;
        uint8_t atom_type = 0;
@@ -1291,7 +1192,7 @@ int32_t parse_sub_atoms(mp4ff_t * f, const uint64_t total_size, int meta_only)
 }
 
 /* parse root atoms */
-int32_t parse_atoms(mp4ff_t * f, int meta_only)
+static int32_t parse_atoms(mp4ff_t * f, int meta_only)
 {
        uint64_t size;
        uint8_t atom_type = 0;
@@ -1305,14 +1206,7 @@ int32_t parse_atoms(mp4ff_t * f, int meta_only)
                f->file_size += size;
                f->last_atom = atom_type;
 
-               if (atom_type == ATOM_MDAT && f->moov_read) {
-                       /* moov atom is before mdat, we can stop reading when mdat is encountered */
-                       /* file position will stay at beginning of mdat data */
-//            break;
-               }
-
                if (atom_type == ATOM_MOOV && size > header_size) {
-                       f->moov_read = 1;
                        f->moov_offset = mp4ff_position(f) - header_size;
                        f->moov_size = size;
                }
@@ -1331,13 +1225,13 @@ int32_t parse_atoms(mp4ff_t * f, int meta_only)
        return 0;
 }
 
-int32_t mp4ff_get_decoder_config(const mp4ff_t * f, const int track,
+void mp4ff_get_decoder_config(const mp4ff_t * f, const int track,
                                 unsigned char **ppBuf, unsigned int *pBufSize)
 {
        if (track >= f->total_tracks) {
                *ppBuf = NULL;
                *pBufSize = 0;
-               return 1;
+               return;
        }
 
        if (f->track[track]->decoderConfig == NULL
@@ -1345,11 +1239,7 @@ int32_t mp4ff_get_decoder_config(const mp4ff_t * f, const int track,
                *ppBuf = NULL;
                *pBufSize = 0;
        } else {
-               *ppBuf = malloc(f->track[track]->decoderConfigLen);
-               if (*ppBuf == NULL) {
-                       *pBufSize = 0;
-                       return 1;
-               }
+               *ppBuf = para_malloc(f->track[track]->decoderConfigLen);
                memcpy(*ppBuf, f->track[track]->decoderConfig,
                        f->track[track]->decoderConfigLen);
                *pBufSize = f->track[track]->decoderConfigLen;
@@ -1358,9 +1248,7 @@ int32_t mp4ff_get_decoder_config(const mp4ff_t * f, const int track,
 
 mp4ff_t *mp4ff_open_read(mp4ff_callback_t * f)
 {
-       mp4ff_t *ff = malloc(sizeof (mp4ff_t));
-
-       memset(ff, 0, sizeof (mp4ff_t));
+       mp4ff_t *ff = para_calloc(sizeof(mp4ff_t));
 
        ff->stream = f;
 
@@ -1374,20 +1262,15 @@ mp4ff_t *mp4ff_open_read(mp4ff_callback_t * f)
        return ff;
 }
 
-int32_t mp4ff_tag_delete(mp4ff_metadata_t * tags)
+static int32_t mp4ff_tag_delete(mp4ff_metadata_t * tags)
 {
        uint32_t i;
 
        for (i = 0; i < tags->count; i++) {
-               if (tags->tags[i].item)
-                       free(tags->tags[i].item);
-               if (tags->tags[i].value)
-                       free(tags->tags[i].value);
+               free(tags->tags[i].item);
+               free(tags->tags[i].value);
        }
-
-       if (tags->tags)
-               free(tags->tags);
-
+       free(tags->tags);
        tags->tags = NULL;
        tags->count = 0;
 
@@ -1400,40 +1283,22 @@ void mp4ff_close(mp4ff_t * ff)
 
        for (i = 0; i < ff->total_tracks; i++) {
                if (ff->track[i]) {
-                       if (ff->track[i]->stsz_table)
-                               free(ff->track[i]->stsz_table);
-                       if (ff->track[i]->stts_sample_count)
-                               free(ff->track[i]->stts_sample_count);
-                       if (ff->track[i]->stts_sample_delta)
-                               free(ff->track[i]->stts_sample_delta);
-                       if (ff->track[i]->stsc_first_chunk)
-                               free(ff->track[i]->stsc_first_chunk);
-                       if (ff->track[i]->stsc_samples_per_chunk)
-                               free(ff->track[i]->stsc_samples_per_chunk);
-                       if (ff->track[i]->stsc_sample_desc_index)
-                               free(ff->track[i]->stsc_sample_desc_index);
-                       if (ff->track[i]->stco_chunk_offset)
-                               free(ff->track[i]->stco_chunk_offset);
-                       if (ff->track[i]->decoderConfig)
-                               free(ff->track[i]->decoderConfig);
-                       if (ff->track[i]->ctts_sample_count)
-                               free(ff->track[i]->ctts_sample_count);
-                       if (ff->track[i]->ctts_sample_offset)
-                               free(ff->track[i]->ctts_sample_offset);
-#ifdef ITUNES_DRM
-                       if (ff->track[i]->p_drms)
-                               drms_free(ff->track[i]->p_drms);
-#endif
+                       free(ff->track[i]->stsz_table);
+                       free(ff->track[i]->stts_sample_count);
+                       free(ff->track[i]->stts_sample_delta);
+                       free(ff->track[i]->stsc_first_chunk);
+                       free(ff->track[i]->stsc_samples_per_chunk);
+                       free(ff->track[i]->stsc_sample_desc_index);
+                       free(ff->track[i]->stco_chunk_offset);
+                       free(ff->track[i]->decoderConfig);
+                       free(ff->track[i]->ctts_sample_count);
+                       free(ff->track[i]->ctts_sample_offset);
                        free(ff->track[i]);
                }
        }
 
-#ifdef USE_TAGGING
        mp4ff_tag_delete(&(ff->tags));
-#endif
-
-       if (ff)
-               free(ff);
+       free(ff);
 }
 
 static int32_t mp4ff_chunk_of_sample(const mp4ff_t * f, const int32_t track,
@@ -1443,6 +1308,8 @@ static int32_t mp4ff_chunk_of_sample(const mp4ff_t * f, const int32_t track,
        int32_t chunk2entry;
        int32_t chunk1, chunk2, chunk1samples, range_samples, total = 0;
 
+       *chunk_sample = 0;
+       *chunk = 1;
        if (f->track[track] == NULL) {
                return -1;
        }
@@ -1529,39 +1396,20 @@ static int32_t mp4ff_sample_to_offset(const mp4ff_t * f, const int32_t track,
        return chunk_offset2;
 }
 
-int32_t mp4ff_set_sample_position(mp4ff_t * f, const int32_t track,
-                                 const int32_t sample)
+void 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);
+       int32_t offset = mp4ff_sample_to_offset(f, track, sample);
        mp4ff_set_position(f, offset);
-
-       return 0;
 }
 
-int32_t mp4ff_audio_frame_size(const mp4ff_t * f, const int32_t track,
-               const int32_t sample)
+int32_t mp4ff_get_sample_size(const mp4ff_t *f, int track, int sample)
 {
-       int32_t bytes;
-       const mp4ff_track_t *p_track = f->track[track];
+       const mp4ff_track_t *t = 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;
+       if (t->stsz_sample_size != 0)
+               return t->stsz_sample_size;
+       return t->stsz_table[sample];
 }
 
 uint32_t mp4ff_get_sample_rate(const mp4ff_t * f, const int32_t track)
@@ -1587,9 +1435,7 @@ int32_t mp4ff_num_samples(const mp4ff_t * f, const int32_t track)
 
 mp4ff_t *mp4ff_open_read_metaonly(mp4ff_callback_t * f)
 {
-       mp4ff_t *ff = malloc(sizeof (mp4ff_t));
-
-       memset(ff, 0, sizeof (mp4ff_t));
+       mp4ff_t *ff = para_calloc(sizeof(mp4ff_t));
 
        ff->stream = f;
 
@@ -1616,8 +1462,8 @@ int32_t mp4ff_meta_get_by_index(const mp4ff_t * f, uint32_t index,
                *value = NULL;
                return 0;
        } else {
-               *item = strdup(f->tags.tags[index].item);
-               *value = strdup(f->tags.tags[index].value);
+               *item = para_strdup(f->tags.tags[index].item);
+               *value = para_strdup(f->tags.tags[index].value);
                return 1;
        }
 }
@@ -1695,12 +1541,12 @@ typedef struct {
 
 #define stricmp strcasecmp
 
-membuffer *membuffer_create()
+static membuffer *membuffer_create(void)
 {
        const unsigned initial_size = 256;
 
-       membuffer *buf = (membuffer *) malloc(sizeof (membuffer));
-       buf->data = malloc(initial_size);
+       membuffer *buf = para_malloc(sizeof (membuffer));
+       buf->data = para_malloc(initial_size);
        buf->written = 0;
        buf->allocated = initial_size;
        buf->error = buf->data == 0 ? 1 : 0;
@@ -1708,7 +1554,7 @@ membuffer *membuffer_create()
        return buf;
 }
 
-unsigned membuffer_write(membuffer * buf, const void *ptr, unsigned bytes)
+static unsigned membuffer_write(membuffer * buf, const void *ptr, unsigned bytes)
 {
        unsigned dest_size = buf->written + bytes;
 
@@ -1737,24 +1583,22 @@ unsigned membuffer_write(membuffer * buf, const void *ptr, unsigned bytes)
        return bytes;
 }
 
-#define membuffer_write_data membuffer_write
-
-unsigned membuffer_write_atom_name(membuffer * buf, const char *data)
+static unsigned membuffer_write_atom_name(membuffer * buf, const char *data)
 {
-       return membuffer_write_data(buf, data, 4) == 4 ? 1 : 0;
+       return membuffer_write(buf, data, 4) == 4 ? 1 : 0;
 }
 
-unsigned membuffer_write_int16(membuffer * buf, uint16_t data)
+static unsigned membuffer_write_int16(membuffer * buf, uint16_t data)
 {
        uint8_t temp[2] = { (uint8_t) (data >> 8), (uint8_t) data };
-       return membuffer_write_data(buf, temp, 2);
+       return membuffer_write(buf, temp, 2);
 }
 
-unsigned membuffer_write_int32(membuffer * buf, uint32_t data)
+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_data(buf, temp, 4);
+       return membuffer_write(buf, temp, 4);
 }
 
 static void membuffer_write_track_tag(membuffer * buf, const char *name,
@@ -1797,7 +1641,7 @@ static uint32_t myatoi(const char *param)
        return param ? atoi(param) : 0;
 }
 
-uint32_t mp4ff_meta_genre_to_index(const char *genrestr)
+static uint32_t mp4ff_meta_genre_to_index(const char *genrestr)
 {
        unsigned n;
        for (n = 0; n < sizeof (ID3v1GenreList) / sizeof (ID3v1GenreList[0]); n++) {
@@ -1820,13 +1664,8 @@ static stdmeta_entry stdmetas[] = {
        {"\xA9" "day", "date"},
        {"\xA9" "too", "tool"},
        {"\xA9" "cmt", "comment"},
-//      {"\xA9" "gen","genre"},
        {"cpil", "compilation"},
-//      {"trkn","track"},
-//      {"disk","disc"},
-//      {"gnre","genre"},
        {"covr", "cover"},
-       /* added by AJS */
        {"aART", "album_artist"},
 };
 
@@ -1843,7 +1682,6 @@ static const char *find_standard_meta(const char *name)   //returns atom name if f
 static void membuffer_write_std_tag(membuffer * buf, const char *name,
                const char *value)
 {
-       /* added by AJS */
        uint32_t flags = 1;
 
        /* special check for compilation flag */
@@ -1861,7 +1699,7 @@ static void membuffer_write_std_tag(membuffer * buf, const char *name,
        membuffer_write_atom_name(buf, "data");
        membuffer_write_int32(buf, flags);      //flags
        membuffer_write_int32(buf, 0);  //reserved
-       membuffer_write_data(buf, value, strlen(value));
+       membuffer_write(buf, value, strlen(value));
 }
 
 static void membuffer_write_custom_tag(membuffer * buf, const char *name,
@@ -1876,38 +1714,37 @@ static void membuffer_write_custom_tag(membuffer * buf, const char *name,
        membuffer_write_int32(buf, 0x1C);       //weirdo itunes atom
        membuffer_write_atom_name(buf, "mean");
        membuffer_write_int32(buf, 0);
-       membuffer_write_data(buf, "com.apple.iTunes", 16);
+       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_data(buf, name, strlen(name));
+       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_data(buf, value, strlen(value));
+       membuffer_write(buf, value, strlen(value));
 }
 
-unsigned membuffer_error(const membuffer * buf)
+static unsigned membuffer_error(const membuffer * buf)
 {
        return buf->error;
 }
 
-void membuffer_free(membuffer * buf)
+static void membuffer_free(membuffer * buf)
 {
-       if (buf->data)
-               free(buf->data);
+       free(buf->data);
        free(buf);
 }
 
-unsigned membuffer_get_size(const membuffer * buf)
+static unsigned membuffer_get_size(const membuffer * buf)
 {
        return buf->written;
 }
 
-void *membuffer_detach(membuffer * buf)
+static void *membuffer_detach(membuffer * buf)
 {
        void *ret;
 
@@ -1930,9 +1767,7 @@ static uint32_t create_ilst(const mp4ff_metadata_t * data, void **out_buffer,
 {
        membuffer *buf = membuffer_create();
        unsigned metaptr;
-       char *mask = (char *) malloc(data->count);
-       memset(mask, 0, data->count);
-
+       char *mask = para_calloc(data->count);
        {
                const char *tracknumber_ptr = 0, *totaltracks_ptr = 0;
                const char *discnumber_ptr = 0, *totaldiscs_ptr = 0;
@@ -2019,32 +1854,32 @@ static uint32_t create_ilst(const mp4ff_metadata_t * data, void **out_buffer,
        return 1;
 }
 
-void membuffer_write_atom(membuffer * buf, const char *name, unsigned size,
+static void membuffer_write_atom(membuffer * buf, const char *name, unsigned size,
                          const void *data)
 {
        membuffer_write_int32(buf, size + 8);
        membuffer_write_atom_name(buf, name);
-       membuffer_write_data(buf, data, size);
+       membuffer_write(buf, data, size);
 }
 
-void *membuffer_get_ptr(const membuffer * buf)
+static void *membuffer_get_ptr(const membuffer * buf)
 {
        return buf->data;
 }
 
-void membuffer_set_error(membuffer * buf)
+static void membuffer_set_error(membuffer * buf)
 {
        buf->error = 1;
 }
 
-unsigned membuffer_transfer_from_file(membuffer * buf, mp4ff_t * src,
+static unsigned membuffer_transfer_from_file(membuffer * buf, mp4ff_t * src,
                unsigned bytes)
 {
        unsigned oldsize;
        void *bufptr;
 
        oldsize = membuffer_get_size(buf);
-       if (membuffer_write_data(buf, 0, bytes) != bytes)
+       if (membuffer_write(buf, 0, bytes) != bytes)
                return 0;
 
        bufptr = membuffer_get_ptr(buf);
@@ -2196,12 +2031,7 @@ static uint32_t modify_moov(mp4ff_t * f, const mp4ff_metadata_t * data,
                size_delta = new_ilst_size - (ilst_size - 8);
 
                *out_size = total_size + size_delta;
-               *out_buffer = malloc(*out_size);
-               if (*out_buffer == 0) {
-                       free(new_ilst_buffer);
-                       return 0;
-               }
-
+               *out_buffer = para_malloc(*out_size);
                p_out = (uint8_t *) * out_buffer;
 
                mp4ff_set_position(f, total_base);
@@ -2239,7 +2069,7 @@ static uint32_t modify_moov(mp4ff_t * f, const mp4ff_metadata_t * data,
        return 1;
 }
 
-int32_t mp4ff_write_data(mp4ff_t * f, int8_t * data, uint32_t size)
+static int32_t mp4ff_write_data(mp4ff_t * f, void *data, uint32_t size)
 {
        int32_t result = 1;
 
@@ -2250,7 +2080,7 @@ int32_t mp4ff_write_data(mp4ff_t * f, int8_t * data, uint32_t size)
        return result;
 }
 
-int32_t mp4ff_write_int32(mp4ff_t * f, const uint32_t data)
+static int32_t mp4ff_write_int32(mp4ff_t * f, const uint32_t data)
 {
        uint32_t result;
        uint32_t a, b, c, d;
@@ -2267,7 +2097,7 @@ int32_t mp4ff_write_int32(mp4ff_t * f, const uint32_t data)
        return mp4ff_write_data(f, (uint8_t *) & result, sizeof (result));
 }
 
-int32_t mp4ff_truncate(mp4ff_t * f)
+static int32_t mp4ff_truncate(mp4ff_t * f)
 {
        return f->stream->truncate(f->stream->user_data);
 }
@@ -2277,9 +2107,7 @@ int32_t mp4ff_meta_update(mp4ff_callback_t * f, const mp4ff_metadata_t * data)
        void *new_moov_data;
        uint32_t new_moov_size;
 
-       mp4ff_t *ff = malloc(sizeof (mp4ff_t));
-
-       memset(ff, 0, sizeof (mp4ff_t));
+       mp4ff_t *ff = para_calloc(sizeof(mp4ff_t));
        ff->stream = f;
        mp4ff_set_position(ff, 0);
 
@@ -2324,7 +2152,7 @@ static int32_t mp4ff_meta_find_by_name(const mp4ff_t * f, const char *item,
 
        for (i = 0; i < f->tags.count; i++) {
                if (!stricmp(f->tags.tags[i].item, item)) {
-                       *value = strdup(f->tags.tags[i].value);
+                       *value = para_strdup(f->tags.tags[i].value);
                        return 1;
                }
        }