Example #1
0
/* parse root atoms */
static int32_t parse_atoms_int (mp4ff_t *f,int meta_only,int stop_on_mdat)
{
    uint64_t size;
    uint8_t atom_type = 0;
    uint8_t header_size = 0;
    int had_valid_atoms = 0;

    f->file_size = 0;

    while ((size = mp4ff_atom_read_header(f, &atom_type, &header_size)) != 0)
    {
        // FIXME: ATOM_UNKNOWN is returned both when a valid (but unknown) atom is encontered,
        // and for invalid data. They need to be handled separately.
        if (atom_type == ATOM_UNKNOWN && !had_valid_atoms && mp4ff_position(f)+size > 100) {
            return -1;
        }

        had_valid_atoms = 1;

        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 */
            if (!stop_on_mdat) {
                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;
        }

        /* parse subatoms */
		if (meta_only && !need_parse_when_meta_only(atom_type))
		{
			mp4ff_set_position(f, mp4ff_position(f)+size-header_size);
		} else if (atom_type < SUBATOMIC)
        {
            parse_sub_atoms(f, size-header_size,meta_only);
        } else {
            /* skip this atom */
            mp4ff_set_position(f, mp4ff_position(f)+size-header_size);
        }
    }

    return 0;
}
Example #2
0
static int32_t mp4ff_read_meta(mp4ff_t *f, const uint64_t size)
{
    uint64_t subsize, sumsize = 0;
    uint8_t atom_type;
    uint8_t header_size = 0;

    mp4ff_read_char(f); /* version */
    mp4ff_read_int24(f); /* flags */

    while (sumsize < (size-(header_size+4)))
    {
        subsize = mp4ff_atom_read_header(f, &atom_type, &header_size);
        if (subsize <= header_size+4)
            return 1;
        if (atom_type == ATOM_ILST)
        {
            mp4ff_parse_metadata(f, (uint32_t)(subsize-(header_size+4)));
        } else {
            mp4ff_set_position(f, mp4ff_position(f)+subsize-header_size);
        }
        sumsize += subsize;
    }

    return 0;
}
Example #3
0
static int32_t mp4ff_read_stsd(mp4ff_t *f)
{
    int32_t i;
    uint8_t header_size = 0;

    mp4ff_read_char(f); /* version */
    mp4ff_read_int24(f); /* flags */

    f->track[f->total_tracks - 1]->stsd_entry_count = mp4ff_read_int32(f);

    for (i = 0; i < f->track[f->total_tracks - 1]->stsd_entry_count; i++)
    {
        uint64_t skip = mp4ff_position(f);
        uint64_t size;
        uint8_t atom_type = 0;
        size = mp4ff_atom_read_header(f, &atom_type, &header_size);
        skip += size;

        if (atom_type == ATOM_MP4A)
        {
            f->track[f->total_tracks - 1]->type = TRACK_AUDIO;
            mp4ff_read_mp4a(f);
        } else if (atom_type == ATOM_MP4V) {
            f->track[f->total_tracks - 1]->type = TRACK_VIDEO;
        } else if (atom_type == ATOM_MP4S) {
            f->track[f->total_tracks - 1]->type = TRACK_SYSTEM;
        } else {
            f->track[f->total_tracks - 1]->type = TRACK_UNKNOWN;
        }

        mp4ff_set_position(f, skip);
    }

    return 0;
}
Example #4
0
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;
    if (atom_type == ATOM_STSZ)
    {
        /* sample size box */
        mp4ff_read_stsz(f);
    } else if (atom_type == ATOM_STTS) {
        /* time to sample box */
        mp4ff_read_stts(f);
    } else if (atom_type == ATOM_CTTS) {
        /* composition offset box */
        mp4ff_read_ctts(f);
    } else if (atom_type == ATOM_STSC) {
        /* sample to chunk box */
        mp4ff_read_stsc(f);
    } else if (atom_type == ATOM_STCO) {
        /* chunk offset box */
        mp4ff_read_stco(f);
    } else if (atom_type == ATOM_STSD) {
        /* sample description box */
        mp4ff_read_stsd(f);
    } else if (atom_type == ATOM_MVHD) {
        /* movie header box */
        mp4ff_read_mvhd(f);
    } else if (atom_type == ATOM_MDHD) {
        /* track header */
        mp4ff_read_mdhd(f);
#ifdef ITUNES_DRM
    } else if (atom_type == ATOM_FRMA) {
        /* DRM track format */
        mp4ff_read_frma(f);
    } else if (atom_type == ATOM_IVIV) {
        mp4ff_read_iviv(f, size-8);
    } else if (atom_type == ATOM_NAME) {
        mp4ff_read_name(f, size-8);
    } else if (atom_type == ATOM_PRIV) {
        mp4ff_read_priv(f, size-8);
    } else if (atom_type == ATOM_USER) {
        mp4ff_read_user(f, size-8);
    } else if (atom_type == ATOM_KEY) {
        mp4ff_read_key(f, size-8);
#endif
#ifdef USE_TAGGING
    } else if (atom_type == ATOM_META) {
        /* iTunes Metadata box */
        mp4ff_read_meta(f, size);
#endif
    }

    mp4ff_set_position(f, dest_position);


    return 0;
}
Example #5
0
/* parse root atoms */
int32_t parse_atoms(mp4ff_t *f,int meta_only)
{
    uint64_t size;
    uint8_t atom_type = 0;
    uint8_t header_size = 0;

    f->file_size = 0;

    while ((size = mp4ff_atom_read_header(f, &atom_type, &header_size)) != 0)
    {
        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;
        }

        /* parse subatoms */
		if (meta_only && !need_parse_when_meta_only(atom_type))
		{
			mp4ff_set_position(f, mp4ff_position(f)+size-header_size);
		} else if (atom_type < SUBATOMIC)
        {
            parse_sub_atoms(f, size-header_size,meta_only);
        } else {
            /* skip this atom */
            mp4ff_set_position(f, mp4ff_position(f)+size-header_size);
        }
    }

    return 0;
}
Example #6
0
/* 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)
{
    uint64_t size;
    uint8_t atom_type = 0;
    uint64_t counted_size = 0;
    uint8_t header_size = 0;

    while (counted_size < total_size)
    {
        size = mp4ff_atom_read_header(f, &atom_type, &header_size);
        counted_size += size;

        /* check for end of file */
        if (size == 0)
            break;

        /* we're starting to read a new track, update index,
         * so that all data and tables get written in the right place
         */
        if (atom_type == ATOM_TRAK)
        {
            mp4ff_track_add(f);
        }

        /* parse subatoms */
		if (meta_only && !need_parse_when_meta_only(atom_type))
		{
			mp4ff_set_position(f, mp4ff_position(f)+size-header_size);
		} else if (atom_type < SUBATOMIC)
        {
            parse_sub_atoms(f, size-header_size,meta_only);
        } else {
            mp4ff_atom_read(f, (uint32_t)size, atom_type);
        }
#if 0
        if (atom_type == ATOM_TRAK)
        {
            trace ("mp4ff_track_create_chunks_index\n");
            mp4ff_track_create_chunks_index (f, f->track[f->total_tracks-1]);
            trace ("mp4ff_track_create_samples_index\n");
            mp4ff_track_create_samples_index (f, f->track[f->total_tracks-1]);
        }
#endif
    }

    return 0;
}
Example #7
0
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;
    if (atom_type == ATOM_STSZ)
    {
        /* sample size box */
        mp4ff_read_stsz(f);
    } else if (atom_type == ATOM_STTS) {
        /* time to sample box */
        mp4ff_read_stts(f);
    } else if (atom_type == ATOM_CTTS) {
        /* composition offset box */
        mp4ff_read_ctts(f);
    } else if (atom_type == ATOM_STSC) {
        /* sample to chunk box */
        mp4ff_read_stsc(f);
    } else if (atom_type == ATOM_STCO) {
        /* chunk offset box */
        mp4ff_read_stco(f);
    } else if (atom_type == ATOM_STSD) {
        /* sample description box */
        mp4ff_read_stsd(f);
    } else if (atom_type == ATOM_MVHD) {
        /* movie header box */
        mp4ff_read_mvhd(f);
    } 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
    } else if (atom_type == ATOM_CHPL) {
        mp4ff_read_chpl(f, size);
    } else if (atom_type == ATOM_CHAP) {
        mp4ff_read_tref(f, size);
    } else if (atom_type == ATOM_TKHD) {
        mp4ff_read_tkhd(f);
    }

    mp4ff_set_position(f, dest_position);


    return 0;
}
Example #8
0
int32_t mp4ff_parse_metadata(mp4ff_t *f, const int32_t size)
{
    uint64_t subsize, sumsize = 0;
    uint8_t atom_type;
    uint8_t header_size = 0;

    while (sumsize < size)
    {
        subsize = mp4ff_atom_read_header(f, &atom_type, &header_size);
        if (subsize == 0)
            break;
        if (atom_type == ATOM_UNKNOWN)
          mp4ff_set_position(f, mp4ff_position(f)+subsize-header_size);
        else
          mp4ff_parse_tag(f, atom_type, (uint32_t)(subsize-header_size));
        sumsize += subsize;
    }

    return 0;
}
Example #9
0
static int32_t mp4ff_parse_tag(mp4ff_t *f, const uint8_t parent_atom_type, const int32_t size)
{
    uint8_t atom_type;
    uint8_t header_size = 0;
    uint64_t subsize, sumsize = 0;
    char * name = NULL;
	char * data = NULL;
	uint32_t done = 0;


    while (sumsize < size)
    {
		uint64_t destpos;
        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);
						}
						else
						{
							const char * temp = mp4ff_meta_index_to_genre(val);
							if (temp)
							{
								mp4ff_tag_add_field(&(f->tags), "genre", temp);
							}
						}
						done = 1;
					}
				} else if (parent_atom_type == ATOM_TRACK || parent_atom_type == ATOM_DISC) {
					if (!done && subsize - header_size >= 8 + 8)
					{
						uint16_t index,total;
						char temp[32];
						mp4ff_read_int16(f);
						index = mp4ff_read_int16(f);
						total = mp4ff_read_int16(f);
						mp4ff_read_int16(f);

						sprintf(temp,"%d",index);
						mp4ff_tag_add_field(&(f->tags), parent_atom_type == ATOM_TRACK ? "track" : "disc", temp);
						if (total>0)
						{
							sprintf(temp,"%d",total);
							mp4ff_tag_add_field(&(f->tags), parent_atom_type == ATOM_TRACK ? "totaltracks" : "totaldiscs", temp);
						}
						done = 1;
					}
				} else
				{
					if (data) {free(data);data = NULL;}
					data = mp4ff_read_string(f,(uint32_t)(subsize-(header_size+8)));
				}
			} 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)));
				}
			}
			mp4ff_set_position(f, destpos);
			sumsize += subsize;
		}
    }

	if (data)
	{
		if (!done)
		{
			if (name == NULL) mp4ff_set_metadata_name(f, parent_atom_type, &name);
			if (name) mp4ff_tag_add_field(&(f->tags), name, data);
		}

		free(data);
	}
	if (name) free(name);
    return 1;
}