コード例 #1
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
static void demux_mp4_parse_mp4a(struct demux *d)
{
	unsigned long atom_size;
	unsigned long size;

	/* Get size */
	atom_size = ATOM_LEN(d->buffer);
	stream_read(d->stream, 28);

	/* Get track properties */
	d->mp4a_channel_count = ATOM_READ16(&d->buffer[16]);
	d->mp4a_sample_size = ATOM_READ16(&d->buffer[18]);
	d->mp4a_samplerate = ATOM_READ16(&d->buffer[24]);

	/* Set track found flag */
	d->track_found = 1;

	/* Skip reserved bytes */
	atom_size -= 36;

	/* Get size of sub-atom */
	stream_read(d->stream, 8);
	size = ATOM_LEN(d->buffer);

	/* Parse "esds" atom */
	if(ATOM_CHECK(d->buffer, "esds") == 0)
	{
		demux_mp4_parse_esds(d);
		atom_size -= size;
	}

	/* Go to next atom */
	stream_seek(d->stream, atom_size, SEEK_CUR);
}
コード例 #2
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
static void demux_mp4_parse_trkn(struct demux *d)
{
	unsigned long size;

	/* Get size */
	size = ATOM_LEN(d->buffer);
	stream_read(d->stream, 8);
	size -= 8;

	/* Check sub-atom */
	if(ATOM_CHECK(d->buffer, "data") == 0 && ATOM_LEN(d->buffer) == 24)
	{
		/* Skip version and flags */
		stream_read(d->stream, 10);
		size -= 20;

		/* Read track */
		stream_read(d->stream, 2);
		d->track = ATOM_READ16(d->buffer);

		/* Read total tack */
		stream_read(d->stream, 2);
		d->total_track = ATOM_READ16(d->buffer);
	}

	/* Go to next atom */
	stream_seek(d->stream, size, SEEK_CUR);
}
コード例 #3
0
ファイル: StringTable_cbits.c プロジェクト: ajnsit/ajhc
int
lexigraphic_compare(atom_t x, atom_t y)
{
    int xl = ATOM_LEN(x);
    int yl = ATOM_LEN(y);
    return memcmp(ATOM_PTR(x),ATOM_PTR(y),xl < yl ? xl : yl) || xl - yl;
}
コード例 #4
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
static void demux_mp4_parse_udta(struct demux *d)
{
	unsigned long atom_size;
	unsigned long count = 8;
	unsigned long size;

	/* Get size of current atom */
	atom_size = ATOM_LEN(d->buffer);

	/* Get all children atoms */
	while(count < atom_size)
	{
		/* Size of sub-atom */
		stream_read(d->stream, 8);
		size = ATOM_LEN(d->buffer);

		/* Process sub-atom */
		if(ATOM_CHECK(d->buffer, "meta") == 0)
		{
			/* Parse "meta" atom */
			demux_mp4_parse_meta(d);
		}
		else
		{
			/* Ignore other sub-atoms */
			stream_seek(d->stream, size, SEEK_CUR);
		}
		count += size;
	}

	/* Finish atom reading */
	stream_seek(d->stream, atom_size-count, SEEK_CUR);
}
コード例 #5
0
ファイル: StringTable_cbits.c プロジェクト: ajnsit/ajhc
int
stringtable_get(atom_t cl, char buf[MAX_ENTRY_SIZE])
{
        assert(ATOM_VALID(cl));
        memcpy(buf,ATOM_PTR(cl),ATOM_LEN(cl));
        return ATOM_LEN(cl);
}
コード例 #6
0
ファイル: StringTable_cbits.c プロジェクト: ajnsit/ajhc
void
dump_table(void) {
        for(int i = 0; i < HASHSIZE*CUCKOO_HASHES; i++) {
                atom_t a = htable[i].atom;
                if(ATOM_VALID(a)) {
                        printf("%p %u: ",ATOM_PTR(a),ATOM_LEN(a));
                        fwrite(ATOM_PTR(a),1,ATOM_LEN(a),stdout);
                        fwrite("\n",1,1,stdout);
                }
        }
}
コード例 #7
0
ファイル: StringTable_cbits.c プロジェクト: ajnsit/ajhc
void
dump_to_file(void) {
        FILE *file = fopen("atom.dump","w");
        for(int i = 0; i < HASHSIZE*CUCKOO_HASHES; i++) {
                atom_t a = htable[i].atom;
                if(ATOM_VALID(a)) {
                        fprintf(file,"%u:",ATOM_LEN(a));
                        print_quoted(file, ATOM_PTR(a),ATOM_LEN(a));
                        fwrite("\n",1,1,file);
                }
        }
}
コード例 #8
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
static void demux_mp4_parse_txt(struct demux *d, char **str)
{
	unsigned long pos = 0;
	unsigned long count;
	unsigned long size;
	unsigned long len;

	/* Get size */
	size = ATOM_LEN(d->buffer);
	stream_read(d->stream, 8);
	size -= 8;

	/* Check sub-atom */
	if(ATOM_CHECK(d->buffer, "data") == 0)
	{
		/* Get string length */
		len = ATOM_LEN(d->buffer) - 16;

		/* Skip version and flags */
		stream_read(d->stream, 8);
		size -= 16;

		/* Free previous string */
		if(*str != NULL)
			free(*str);

		/* Allocate new string */
		*str = calloc(1, len + 1);
		if(*str != NULL)
		{
			/* Copy string */
			while(len > 0)
			{
				count = d->buffer_size;
				if(count > len)
					count = len;
				count = stream_read(d->stream, count);
				memcpy(*str + pos, d->buffer, count);
				pos += count;
				len -= count;
				size -= count;
			}
		}
	}

	/* Go to next atom */
	stream_seek(d->stream, size, SEEK_CUR);
}
コード例 #9
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
static void demux_mp4_parse_mdhd(struct demux *d)
{
	unsigned long version;
	unsigned long size;

	/* Get size */
	size = ATOM_LEN(d->buffer);

	/* Get Version */
	stream_read(d->stream, 4);
	version = ATOM_READ32(d->buffer);

	/* Go to first entry */
	size -= 12;

	if(version == 1)
	{
		stream_read(d->stream, 28);
		d->mdhd_time_scale = ATOM_READ32(&d->buffer[16]);
		d->mdhd_duration = ATOM_READ64(&d->buffer[20]);
	}
	else
	{
		stream_read(d->stream, 16);
		d->mdhd_time_scale = ATOM_READ32(&d->buffer[8]);
		d->mdhd_duration = ATOM_READ32(&d->buffer[12]);
	}

	/* Go to next atom */
	stream_seek(d->stream, size, SEEK_CUR);
}
コード例 #10
0
ファイル: StringTable_cbits.c プロジェクト: ajnsit/ajhc
static atom_t
add_string(unsigned char *cs, int len)
{
    pthread_mutex_lock(&mutex_string);
        //printf("add_string(%c,%c,%i)\n",cs[0],cs[1],len);
    assert(len >= 0);
    assert(len < MAX_ENTRY_SIZE);
    assert(next_free_offset < CHUNK_SIZE);
    if(next_free_offset + 1 > CHUNK_SIZE - MAX_ENTRY_SIZE) {
        dieif(current_chunk >= NUM_CHUNKS - 1, "No more chunks");
        current_chunk++;
        assert(!stringtable_chunks[current_chunk]);
        stringtable_chunks[current_chunk] = malloc(CHUNK_SIZE);
        dieif(!stringtable_chunks[current_chunk], "error alocating memory");
        next_free_offset = 0;
    }
    memcpy(stringtable_chunks[current_chunk] + next_free_offset, cs, len);
    atom_t r = MAKE_ATOM(current_chunk, next_free_offset, len);
    assert(CHUNK_INDEX(r) == current_chunk);
    assert(CHUNK_OFFSET(r) == next_free_offset);
    assert(ATOM_PTR(r) == stringtable_chunks[current_chunk] + next_free_offset);
    assert(ATOM_LEN(r) == len);
    next_free_offset += len;
    assert(next_free_offset < CHUNK_SIZE);
    assert(current_chunk < NUM_CHUNKS);
    pthread_mutex_unlock(&mutex_string);
    return r;
}
コード例 #11
0
ファイル: StringTable_cbits.c プロジェクト: ajnsit/ajhc
int
stringtable_find(atom_t cl, unsigned char **res)
{
        assert(ATOM_VALID(cl));
        *res = ATOM_PTR(cl);
        return ATOM_LEN(cl);
}
コード例 #12
0
ファイル: StringTable_cbits.c プロジェクト: ajnsit/ajhc
static void
hash_insert(struct hentry x) {
        assert(ATOM_VALID(x.atom));
//         fprintf(stderr,"hash_insert(%x,%p:%i,%x,%x,[%x,%x]", x.atom, ATOM_PTR(x.atom), ATOM_LEN(x.atom), x.hashes[0], x.hashes[1],HASH_INDEX(0,x.hashes[0]),HASH_INDEX(1,x.hashes[1]));
        assert(!atom_exists(x.atom));
        assert(!item_exists(ATOM_PTR(x.atom),ATOM_LEN(x.atom)));
        atom_t start = x.atom;
        for(int loop = 0; loop < DEPTH_LIMIT;loop++) {
                for(int i = 0; i < CUCKOO_HASHES; i++) {
//                        int e = HASH_INDEX(i,FHASH(x,i));
                        for(int j = 0; j < CUCKOO_BUCKETS; j++) {
                                //#struct hentry *b = &(htable[(e + j) & HASHJMASK ]);
                                //struct hentry *b = &htable[HASH_BUCKET(e,j)];
                                struct hentry *b = &htable[HASH_INDEX(i,FHASH(x,i) + j)];
                                if(!ATOM_VALID(b->atom)) {
                                        *b = x;
//                                        fprintf(stderr,")\n");
                                        return;
                                }
                                struct hentry tb = x;
                                x = *b;
                                *b = tb;
                        }
                        // struct hentry *b = &(htable[e]);
                }
                if(x.atom == start) {
                        break;
                }
        }
        grow_table();
//        fprintf(stderr,"R");
        return hash_insert(x);
}
コード例 #13
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
static void demux_mp4_parse_ilst(struct demux *d)
{
	unsigned long atom_size;
	unsigned long count = 8;
	unsigned long size;

	/* Get size of current atom */
	atom_size = ATOM_LEN(d->buffer);

	/* Get all children atoms */
	while(count < atom_size)
	{
		/* Size of sub-atom */
		stream_read(d->stream, 8);
		size = ATOM_LEN(d->buffer);

		/* Process sub-atom */
		if(ATOM_CHECK(d->buffer, "\251alb") == 0)
			demux_mp4_parse_txt(d, &d->album);
		else if(ATOM_CHECK(d->buffer, "\251ART") == 0)
			demux_mp4_parse_txt(d, &d->artist);
		else if(ATOM_CHECK(d->buffer, "\251cmt") == 0)
			demux_mp4_parse_txt(d, &d->comment);
		else if(ATOM_CHECK(d->buffer, "\251day") == 0)
			demux_mp4_parse_txt(d, &d->year);
		else if(ATOM_CHECK(d->buffer, "\251nam") == 0)
			demux_mp4_parse_txt(d, &d->title);
		else if(ATOM_CHECK(d->buffer, "\251gen") == 0)
			demux_mp4_parse_txt(d, &d->genre);
		else if(ATOM_CHECK(d->buffer, "trkn") == 0)
			demux_mp4_parse_trkn(d);
		else if(ATOM_CHECK(d->buffer, "gnre") == 0)
			demux_mp4_parse_gnre(d);
		else if(ATOM_CHECK(d->buffer, "covr") == 0)
			demux_mp4_parse_covr(d);
		else
		{
			/* Ignore other sub-atoms */
			stream_seek(d->stream, size, SEEK_CUR);
		}
		count += size;
	}

	/* Finish atom reading */
	stream_seek(d->stream, atom_size-count, SEEK_CUR);
}
コード例 #14
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
static int demux_mp4_parse_stsd(struct demux *d)
{
	unsigned long atom_size;
	unsigned long size;
	int32_t count;
	int32_t i;
	int is_mp4a = 0;

	/* Get size */
	atom_size = ATOM_LEN(d->buffer);
	stream_read(d->stream, 8);

	/* Count entries */
	count = ATOM_READ32(&d->buffer[4]);

	/* Go to first entry */
	atom_size -= 16;

	/* Parse each entries */
	for(i = 0; i < count; i++)
	{
		/* Get size of sub-atom */
		stream_read(d->stream, 8);
		size = ATOM_LEN(d->buffer);

		/* Process sub-atom */
		if(ATOM_CHECK(d->buffer, "mp4a") == 0)
		{
			/* Parse "mp4a" atom */
			demux_mp4_parse_mp4a(d);
			is_mp4a = 1;
		}
		else
		{
			stream_seek(d->stream, size, SEEK_CUR);
		}
		atom_size -= size;
	}

	/* Go to next atom */
	stream_seek(d->stream, atom_size, SEEK_CUR);

	return is_mp4a;
}
コード例 #15
0
ファイル: StringTable_cbits.c プロジェクト: ajnsit/ajhc
atom_t
stringtable_lookup(unsigned char *cs, int len)
{
//        static FILE *file = NULL;
//        if(!file)
//                file = fopen("atom.lookup","w");
//        fprintf(file,"stringtable_lookup(");
//        print_quoted(file,cs,len);
//        fprintf(file,")\n");
        pthread_mutex_lock(&mutex_hash);
        assert(len >= 0);
        assert(len < MAX_ENTRY_SIZE);
        hash_t h[CUCKOO_HASHES];
        for(uint32_t i = 0; i < CUCKOO_HASHES; i++) {
                h[i] = hashlittle(cs,len,i);
                //int e = HASH_INDEX(i,h[i]);
                for(int j = 0; j < CUCKOO_BUCKETS; j++) {
                        //struct hentry *b = &htable[(e + i) & HASHJMASK ];
                        //struct hentry *b = &htable[HASH_BUCKET(e,j)];
                        struct hentry *b = &htable[HASH_INDEX(i,h[i] + j)];
#if KEEP_HASH
                        if (ATOM_VALID(b->atom) && h[i] == b->hashes[i] && len == ATOM_LEN(b->atom) &&  !memcmp(ATOM_PTR(b->atom),cs,len)) {
                            pthread_mutex_unlock(&mutex_hash);
                            return b->atom;
                        }
#else
                        if (ATOM_VALID(b->atom) && len == ATOM_LEN(b->atom) && !memcmp(ATOM_PTR(b->atom),cs,len)) {
                            pthread_mutex_unlock(&mutex_hash);
                            return b->atom;
                        }
#endif
                }
        }
        atom_t na = add_string(cs,len);
        struct hentry hb;
        hb.atom = na;
#if KEEP_HASH
        memcpy(hb.hashes,h,sizeof hb.hashes);
#endif
        hash_insert(hb);
        pthread_mutex_unlock(&mutex_hash);
        return na;
}
コード例 #16
0
ファイル: StringTable_cbits.c プロジェクト: ajnsit/ajhc
static bool
item_exists(unsigned char *cs, int len) {
        for(int i = 0; i < HASHSIZE*CUCKOO_HASHES; i++) {
                atom_t a = htable[i].atom;
                if(ATOM_VALID(a)) {
                    if(len == ATOM_LEN(a) && !memcmp(ATOM_PTR(a),cs,len))
                        return true;
                }
        }
        return false;
}
コード例 #17
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
static void demux_mp4_parse_gnre(struct demux *d)
{
	unsigned long size;
	uint16_t genre;

	/* Get size */
	size = ATOM_LEN(d->buffer);
	stream_read(d->stream, 8);
	size -= 8;

	/* Check sub-atom */
	if(ATOM_CHECK(d->buffer, "data") == 0 && ATOM_LEN(d->buffer) == 18)
	{
		/* Skip version and flags */
		stream_read(d->stream, 8);
		size -= 16;

		/* Read genre index */
		stream_read(d->stream, 2);
		genre = ATOM_READ16(d->buffer);

		/* Check genre */
		if(genre > 0 || genre <= ID3v1_genres_count)
		{
			/* Free previous genre */
			if(d->genre != NULL)
				free(d->genre);

			/* Copy genre */
			d->genre = strdup(ID3v1_genres[genre-1]);
		}
	}

	/* Go to next atom */
	stream_seek(d->stream, size, SEEK_CUR);
}
コード例 #18
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
static void demux_mp4_parse_stsc(struct demux *d)
{
	unsigned long size;
	unsigned int i, j, count;

	/* Get size */
	size = ATOM_LEN(d->buffer);
	stream_read(d->stream, 8);

	/* Get chunk count */
	d->stsc_entry_count = ATOM_READ32(&d->buffer[4]);

	/* Go to first entry */
	size -= 16;

	/* Create chunk table */
	d->stsc_first_chunk = malloc(d->stsc_entry_count * sizeof(int32_t));
	d->stsc_samples_per_chunk = malloc(d->stsc_entry_count *
							       sizeof(int32_t));
	d->stsc_sample_desc_index = malloc(d->stsc_entry_count *
							       sizeof(int32_t));

	/* Fill table */
	for(i = 0; i < d->stsc_entry_count; i += count)
	{
		count = d->buffer_size / 12;
		if(count > d->stsc_entry_count - i)
			count = d->stsc_entry_count - i;

		stream_read(d->stream, count*12);
		for(j = 0; j < count; j++)
		{
			d->stsc_first_chunk[i+j] = ATOM_READ32(
							   &d->buffer[j*12]);
			d->stsc_samples_per_chunk[i+j] = ATOM_READ32(
						       &d->buffer[4+(j*12)]);
			d->stsc_sample_desc_index[i+j] = ATOM_READ32(
						       &d->buffer[8+(j*12)]);
		}
	}
	size -= 12 * d->stsc_entry_count;

	/* Go to next atom */
	stream_seek(d->stream, size, SEEK_CUR);
}
コード例 #19
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
static void demux_mp4_parse_stts(struct demux *d)
{
	unsigned long size;
	unsigned int i, j, count;

	/* Get size */
	size = ATOM_LEN(d->buffer);
	stream_read(d->stream, 8);

	/* Get count */
	d->stts_entry_count = ATOM_READ32(&d->buffer[4]);

	/* Go to first entry */
	size -= 16;

	/* Create stts table */
	d->stts_sample_count = malloc(d->stts_entry_count * sizeof(int32_t));
	d->stts_sample_delta = malloc(d->stts_entry_count * sizeof(int32_t));
	d->num_samples = 0;

	/* Fill table */
	for(i = 0; i < d->stts_entry_count; i += count)
	{
		count = d->buffer_size / 8;
		if(count > d->stts_entry_count - i)
			count = d->stts_entry_count - i;

		stream_read(d->stream, count*8);
		for(j = 0; j < count; j++)
		{
			d->stts_sample_count[i+j] = ATOM_READ32(
							   &d->buffer[j*8]);
			d->stts_sample_delta[i+j] = ATOM_READ32(
						       &d->buffer[4+(j*8)]);
			d->num_samples += d->stts_sample_count[i+j];
		}
	}
	size -= 8 * d->stts_entry_count;

	/* Go to next atom */
	stream_seek(d->stream, size, SEEK_CUR);
}
コード例 #20
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
static void demux_mp4_parse_stsz(struct demux *d)
{
	unsigned long size;
	unsigned int i, j, count;

	/* Get size */
	size = ATOM_LEN(d->buffer);
	stream_read(d->stream, 12);

	/* Get sample size and sample count */
	d->stsz_sample_size = ATOM_READ32(&d->buffer[4]);
	d->stsz_sample_count = ATOM_READ32(&d->buffer[8]);

	/* Go to first entry */
	size -= 20;

	/* Create sample size table */
	if(d->stsz_sample_size == 0)
	{
		d->stsz_table = malloc(d->stsz_sample_count * sizeof(int32_t));

		/* Fill table */
		for(i = 0; i < d->stsz_sample_count; i += count)
		{
			count = d->buffer_size / 4;
			if(count > d->stsz_sample_count - i)
				count = d->stsz_sample_count - i;

			stream_read(d->stream, count*4);
			for(j = 0; j < count; j++)
			{
				d->stsz_table[i+j] = ATOM_READ32(
							    &d->buffer[j*4]);
			}
		}
		size -= 4 * d->stsz_sample_count;
	}

	/* Go to next atom */
	stream_seek(d->stream, size, SEEK_CUR);
}
コード例 #21
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
static void demux_mp4_parse_stco(struct demux *d)
{
	unsigned long size;
	unsigned int i, j, count;

	/* Get size */
	size = ATOM_LEN(d->buffer);
	stream_read(d->stream, 8);

	/* Get chunk offset count */
	d->stco_entry_count = ATOM_READ32(&d->buffer[4]);

	/* Go to first entry */
	size -= 16;

	/* Create chunk offset table */
	d->stco_chunk_offset = malloc(d->stco_entry_count * sizeof(int32_t));

	/* Fill table */
	for(i = 0; i < d->stco_entry_count; i += count)
	{
		count = d->buffer_size / 4;
		if(count > d->stco_entry_count - i)
			count = d->stco_entry_count - i;

		stream_read(d->stream, count*4);
		for(j = 0; j < count; j++)
		{
			d->stco_chunk_offset[i+j] = ATOM_READ32(
							    &d->buffer[j*4]);
		}
	}
	size -= 4 * d->stco_entry_count;

	/* Go to next atom */
	stream_seek(d->stream, size, SEEK_CUR);
}
コード例 #22
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
int demux_mp4_open(struct demux **demux, struct stream_handle *stream,
		   unsigned long *samplerate, unsigned char *channels)
{
	struct demux *d;
	const unsigned char *buffer;
	unsigned long mdat_pos = 0;
	unsigned long moov_pos = 0;
	unsigned long count = 0;
	unsigned long size;

	if(stream == NULL)
		return -1;

	/* Get stream buffer */
	buffer = stream_get_buffer(stream);

	/* Read 8 first bytes for first atom header */
	if(stream_read(stream, 8) != 8)
		return -1;

	/* Check "ftyp" atom */
	if(ATOM_CHECK(buffer, "ftyp") != 0)
		return -1;
	size = ATOM_LEN(buffer);
	count = size;

	/* Allocate demux data structure */
	*demux = malloc(sizeof(struct demux));
	if(*demux == NULL)
		return -1;
	d = *demux;

	/* Init demux structure */
	memset(d, 0, sizeof(struct demux));
	d->stream = stream;
	d->buffer = buffer;
	d->buffer_size = stream_get_buffer_size(stream);
	d->size = stream_get_size(stream);

	/* Seek to next atom and get next atom header */
	stream_seek(d->stream, size, SEEK_CUR);

	/* Read all atom until "mdat" */
	while(count < d->size)
	{
		/* Get size of sub-atom */
		stream_read(d->stream, 8);
		size = ATOM_LEN(d->buffer);

		/* Process sub-atom */
		if(ATOM_CHECK(d->buffer, "moov") == 0)
		{
			/* Process "moov" */
			demux_mp4_parse_moov(d);
			moov_pos = count;
		}
		else
		{
			if(ATOM_CHECK(d->buffer, "mdat") == 0)
			{
				mdat_pos = count;
				if(moov_pos > 0)
					break;
			}

			/* Go to next atom */
			stream_seek(d->stream, size, SEEK_CUR);
		}
		/* Update read bytes count */
		count += size;
	}

	/* Check if a valid mp4 file and have found a mp4a track */
	if(mdat_pos == 0 || d->track_found == 0)
		return -1;

	/* Go to first frame */
	if(d->stsz_sample_size != 0)
		d->cur_sample_size = d->stsz_sample_size;
	else
		d->cur_sample_size = d->stsz_table[0];
	d->cur_sample = 0;
	d->cur_chunk_sample = 0;
	d->cur_chunk_idx = 0;
	d->cur_chunk = 0;
	d->cur_offset = d->stco_chunk_offset[0];

	/* Fill format */
	d->format.samplerate = d->mp4a_samplerate;
	d->format.channels = d->mp4a_channel_count;
	d->format.bitrate = d->esds_avg_bitrate / 1000;
	d->format.title = d->title;
	d->format.artist = d->artist;
	d->format.album = d->album;
	d->format.comment = d->comment;
	d->format.genre = d->genre;
	d->format.track = d->track;
	d->format.total_track = d->total_track;
	if(d->year != NULL)
		d->format.year = strtol(d->year, NULL, 10);
	d->format.picture.data = d->pic;
	d->format.picture.mime = d->pic_mime;
	d->format.picture.size = d->pic_len;

	/* Calculate stream duration */
	if(d->mdhd_time_scale != 0)
		d->format.length = d->mdhd_duration / d->mdhd_time_scale;

	/* Update samplerate and channels */
	*samplerate = d->mp4a_samplerate;
	*channels = d->mp4a_channel_count;

	return 0;
}
コード例 #23
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
static int demux_mp4_parse_esds(struct demux *d)
{
	unsigned long atom_size;
	unsigned char tag;

	/* Get size */
	atom_size = ATOM_LEN(d->buffer);

	/* Skip version and flags */
	stream_seek(d->stream, 12, SEEK_CUR);
	atom_size -= 12;

	/* Check ES_DescrTag */
	stream_read(d->stream, 1);
	tag = d->buffer[0];
	atom_size--;
	if(tag == 0x03)
	{
		/* Read length */
		if(demux_mp4_read_len(d, &atom_size) < 20)
			goto end;

		/* Skip 3 bytes */
		stream_read(d->stream, 3);
		atom_size -= 3;
	}
	else
	{
		/* Skip 2 bytes */
		stream_read(d->stream, 2);
		atom_size -= 2;
	}

	/* Check DecoderConfigDescrTab */
	stream_read(d->stream, 1);
	atom_size--;
	if(d->buffer[0] != 0x04)
		goto end;

	/* Read length */
	if(demux_mp4_read_len(d, &atom_size) < 13)
		goto end;

	/* Get esds properties */
	stream_read(d->stream, 14);
	atom_size -= 14;
	d->esds_audio_type = d->buffer[0];
	d->esds_max_bitrate = ATOM_READ32(&d->buffer[5]);
	d->esds_avg_bitrate = ATOM_READ32(&d->buffer[9]);

	/* Check DecSpecificInfoTag */
	if(d->buffer[13] != 0x05)
		goto end;

	/* Read length */
	d->esds_size = demux_mp4_read_len(d, &atom_size);

	/* Copy decoder config */
	if(d->esds_buffer)
		free(d->esds_buffer);
	d->esds_buffer = malloc(d->esds_size);
	if(d->esds_buffer != NULL)
	{
		/* Read coder config */
		stream_read(d->stream, d->esds_size);
		memcpy(d->esds_buffer, d->buffer, d->esds_size);
	}
	else
	{
		d->esds_size = 0;
	}

end:
	/* Go to next atom */
	stream_seek(d->stream, atom_size, SEEK_CUR);
	return 0;
}
コード例 #24
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
static void demux_mp4_parse_covr(struct demux *d)
{
	unsigned long pos = 0;
	unsigned long count;
	unsigned long size;
	unsigned long len;
	uint32_t flags;

	/* Get size */
	size = ATOM_LEN(d->buffer);
	stream_read(d->stream, 8);
	size -= 8;

	/* Check sub-atom */
	if(ATOM_CHECK(d->buffer, "data") == 0)
	{
		/* Get length */
		len =  ATOM_LEN(d->buffer) - 16;

		/* Get flags for type */
		stream_read(d->stream, 8);
		flags = ATOM_READ32(d->buffer);
		size -= 8;

		/* Free previous buffer */
		if(d->pic != NULL)
			free(d->pic);
		if(d->pic_mime != NULL)
			free(d->pic_mime);
		d->pic_mime = NULL;
		d->pic_len = 0;

		/* Allocate new buffer */
		d->pic = malloc(len);
		if(d->pic != NULL)
		{
			/* Copy length */
			d->pic_len = len;

			/* Copy data */
			while(len > 0)
			{
				count = d->buffer_size;
				if(count > len)
					count = len;
				count = stream_read(d->stream, count);
				memcpy(d->pic + pos, d->buffer, count);
				pos += count;
				len -= count;
				size -= count;
			}

			/* Generate mime */
			if(flags == 13)
				d->pic_mime = strdup("image/jpeg");
			else if(flags == 14)
				d->pic_mime = strdup("image/png");
		}
	}

	/* Go to next atom */
	stream_seek(d->stream, size, SEEK_CUR);
}
コード例 #25
0
ファイル: demux_mp4.c プロジェクト: izhangyr/AirCat
static void demux_mp4_parse_track(struct demux *d)
{
	unsigned long atom_size;
	unsigned long count = 8;
	unsigned long size;
	int is_mp4a = 0;

	/* Get size of current atom */
	atom_size = ATOM_LEN(d->buffer);

	/* Get all children atoms */
	while(count < atom_size)
	{
		/* Size of sub-atom */
		stream_read(d->stream, 8);
		size = ATOM_LEN(d->buffer);

		/* Process sub-atom */
		if(ATOM_CHECK(d->buffer, "mdia") == 0 ||
		   ATOM_CHECK(d->buffer, "minf") == 0 ||
		   ATOM_CHECK(d->buffer, "stbl") == 0)
		{
			/* Parse sub-atom: get mdia -> minf -> stbl */
			demux_mp4_parse_track(d);
		}
		else if(ATOM_CHECK(d->buffer, "mdhd") == 0)
		{
			/* Parse "mdhd" atom */
			demux_mp4_parse_mdhd(d);
		}
		else if(ATOM_CHECK(d->buffer, "stsd") == 0)
		{
			/* Parse "stsd" atom */
			is_mp4a = demux_mp4_parse_stsd(d);
		}
		else if(ATOM_CHECK(d->buffer, "stts") == 0 && is_mp4a)
		{
			/* Parse "stts" atom */
			demux_mp4_parse_stts(d);
		}
		else if(ATOM_CHECK(d->buffer, "stsc") == 0 && is_mp4a)
		{
			/* Parse "stsc" atom */
			demux_mp4_parse_stsc(d);
		}
		else if(ATOM_CHECK(d->buffer, "stsz") == 0 && is_mp4a)
		{
			/* Parse "stsz" atom */
			demux_mp4_parse_stsz(d);
		}
		else if(ATOM_CHECK(d->buffer, "stco") == 0 && is_mp4a)
		{
			/* Parse "stco" atom */
			demux_mp4_parse_stco(d);
		}
		else
		{
			/* Ignore other sub-atoms */
			stream_seek(d->stream, size, SEEK_CUR);
		}
		count += size;
	}

	/* Finish atom reading */
	stream_seek(d->stream, atom_size-count, SEEK_CUR);
}