From 039627cf487a950f0c76d0d7a26aacae3ec3552d Mon Sep 17 00:00:00 2001 From: Baptiste Coudurier Date: Sat, 13 May 2006 18:01:16 +0000 Subject: [PATCH] clean and simplify Originally committed as revision 5373 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/movenc.c | 328 ++++++++++++++++++++----------------------- 1 file changed, 155 insertions(+), 173 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 26ee17115f..b4d2267fac 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -47,7 +47,6 @@ typedef struct MOVIentry { typedef struct MOVIndex { int mode; int entry; - uint64_t mdat_size; int ents_allocated; long timescale; long time; @@ -58,6 +57,7 @@ typedef struct MOVIndex { int hasBframes; int language; int trackID; + int tag; AVCodecContext *enc; int vosLen; @@ -70,12 +70,11 @@ typedef struct MOVContext { int64_t time; int nb_streams; offset_t mdat_pos; + uint64_t mdat_size; long timescale; MOVTrack tracks[MAX_STREAMS]; } MOVContext; -static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track); - //FIXME supprt 64bit varaint with wide placeholders static offset_t updateSize (ByteIOContext *pb, offset_t pos) { @@ -225,6 +224,111 @@ static int mov_write_damr_tag(ByteIOContext *pb) return 0x11; } +static unsigned int descrLength(unsigned int len) +{ + if (len < 0x00000080) + return 2 + len; + else if (len < 0x00004000) + return 3 + len; + else if(len < 0x00200000) + return 4 + len; + else + return 5 + len; +} + +static void putDescr(ByteIOContext *pb, int tag, int size) +{ + uint32_t len; + uint8_t vals[4]; + + len = size; + vals[3] = (uint8_t)(len & 0x7f); + len >>= 7; + vals[2] = (uint8_t)((len & 0x7f) | 0x80); + len >>= 7; + vals[1] = (uint8_t)((len & 0x7f) | 0x80); + len >>= 7; + vals[0] = (uint8_t)((len & 0x7f) | 0x80); + + put_byte(pb, tag); // DescriptorTag + + if (size < 0x00000080) + { + put_byte(pb, vals[3]); + } + else if (size < 0x00004000) + { + put_byte(pb, vals[2]); + put_byte(pb, vals[3]); + } + else if (size < 0x00200000) + { + put_byte(pb, vals[1]); + put_byte(pb, vals[2]); + put_byte(pb, vals[3]); + } + else if (size < 0x10000000) + { + put_byte(pb, vals[0]); + put_byte(pb, vals[1]); + put_byte(pb, vals[2]); + put_byte(pb, vals[3]); + } +} + +static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic +{ + int decoderSpecificInfoLen; + offset_t pos = url_ftell(pb); + + decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0; + + put_be32(pb, 0); // size + put_tag(pb, "esds"); + put_be32(pb, 0); // Version + + // ES descriptor + putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) + + descrLength(1)); + put_be16(pb, track->trackID); + put_byte(pb, 0x00); // flags (= no flags) + + // DecoderConfig descriptor + putDescr(pb, 0x04, 13 + decoderSpecificInfoLen); + + // Object type indication + put_byte(pb, codec_get_tag(ff_mov_obj_type, track->enc->codec_id)); + + // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio) + // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved) + if(track->enc->codec_type == CODEC_TYPE_AUDIO) + put_byte(pb, 0x15); // flags (= Audiostream) + else + put_byte(pb, 0x11); // flags (= Visualstream) + + put_byte(pb, track->enc->rc_buffer_size>>(3+16)); // Buffersize DB (24 bits) + put_be16(pb, (track->enc->rc_buffer_size>>3)&0xFFFF); // Buffersize DB + + put_be32(pb, FFMAX(track->enc->bit_rate, track->enc->rc_max_rate)); // maxbitrate (FIXME should be max rate in any 1 sec window) + if(track->enc->rc_max_rate != track->enc->rc_min_rate || track->enc->rc_min_rate==0) + put_be32(pb, 0); // vbr + else + put_be32(pb, track->enc->rc_max_rate); // avg bitrate + + if (track->vosLen) + { + // DecoderSpecific info descriptor + putDescr(pb, 0x05, track->vosLen); + put_buffer(pb, track->vosData, track->vosLen); + } + + + // SL descriptor + putDescr(pb, 0x06, 1); + put_byte(pb, 0x02); + return updateSize (pb, pos); +} + static int mov_write_wave_tag(ByteIOContext *pb, MOVTrack* track) { offset_t pos = url_ftell(pb); @@ -270,21 +374,9 @@ static const CodecTag codec_movaudio_tags[] = { static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track) { offset_t pos = url_ftell(pb); - int tag; put_be32(pb, 0); /* size */ - - tag = track->enc->codec_tag; - if (!tag) - tag = codec_get_tag(codec_movaudio_tags, track->enc->codec_id); - // if no mac fcc found, try with Microsoft tags - if (!tag) - { - int tmp = codec_get_tag(codec_wav_tags, track->enc->codec_id); - tag = MKTAG('m', 's', ((tmp >> 8) & 0xff), (tmp & 0xff)); - } - put_le32(pb, tag); // store it byteswapped - + put_le32(pb, track->tag); // store it byteswapped put_be32(pb, 0); /* Reserved */ put_be16(pb, 0); /* Reserved */ put_be16(pb, 1); /* Data-reference index, XXX == 1 */ @@ -303,20 +395,17 @@ static int mov_write_audio_tag(ByteIOContext *pb, MOVTrack* track) put_be16(pb, 0x10); /* Reserved */ if(track->enc->codec_id == CODEC_ID_AAC || - track->enc->codec_id == CODEC_ID_MP3) - { + track->enc->codec_id == CODEC_ID_MP3) { put_be16(pb, 0xfffe); /* compression ID (vbr)*/ } - else - { + else { put_be16(pb, 0); /* compression ID (= 0) */ } put_be16(pb, 0); /* packet size (= 0) */ put_be16(pb, track->timescale); /* Time scale */ put_be16(pb, 0); /* Reserved */ - if(track->mode == MODE_MOV && track->enc->codec_id == CODEC_ID_AAC) - { + if(track->mode == MODE_MOV && track->enc->codec_id == CODEC_ID_AAC) { /* SoundDescription V1 extended info */ put_be32(pb, track->enc->frame_size); /* Samples per packet */ put_be32(pb, 1536); /* Bytes per packet */ @@ -467,111 +556,6 @@ static int mov_write_avcc_tag(ByteIOContext *pb, MOVTrack *track) return updateSize(pb, pos); } -static unsigned int descrLength(unsigned int len) -{ - if (len < 0x00000080) - return 2 + len; - else if (len < 0x00004000) - return 3 + len; - else if(len < 0x00200000) - return 4 + len; - else - return 5 + len; -} - -static void putDescr(ByteIOContext *pb, int tag, int size) -{ - uint32_t len; - uint8_t vals[4]; - - len = size; - vals[3] = (uint8_t)(len & 0x7f); - len >>= 7; - vals[2] = (uint8_t)((len & 0x7f) | 0x80); - len >>= 7; - vals[1] = (uint8_t)((len & 0x7f) | 0x80); - len >>= 7; - vals[0] = (uint8_t)((len & 0x7f) | 0x80); - - put_byte(pb, tag); // DescriptorTag - - if (size < 0x00000080) - { - put_byte(pb, vals[3]); - } - else if (size < 0x00004000) - { - put_byte(pb, vals[2]); - put_byte(pb, vals[3]); - } - else if (size < 0x00200000) - { - put_byte(pb, vals[1]); - put_byte(pb, vals[2]); - put_byte(pb, vals[3]); - } - else if (size < 0x10000000) - { - put_byte(pb, vals[0]); - put_byte(pb, vals[1]); - put_byte(pb, vals[2]); - put_byte(pb, vals[3]); - } -} - -static int mov_write_esds_tag(ByteIOContext *pb, MOVTrack* track) // Basic -{ - int decoderSpecificInfoLen; - offset_t pos = url_ftell(pb); - - decoderSpecificInfoLen = track->vosLen ? descrLength(track->vosLen):0; - - put_be32(pb, 0); // size - put_tag(pb, "esds"); - put_be32(pb, 0); // Version - - // ES descriptor - putDescr(pb, 0x03, 3 + descrLength(13 + decoderSpecificInfoLen) + - descrLength(1)); - put_be16(pb, track->trackID); - put_byte(pb, 0x00); // flags (= no flags) - - // DecoderConfig descriptor - putDescr(pb, 0x04, 13 + decoderSpecificInfoLen); - - // Object type indication - put_byte(pb, codec_get_tag(ff_mov_obj_type, track->enc->codec_id)); - - // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio) - // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved) - if(track->enc->codec_type == CODEC_TYPE_AUDIO) - put_byte(pb, 0x15); // flags (= Audiostream) - else - put_byte(pb, 0x11); // flags (= Visualstream) - - put_byte(pb, track->enc->rc_buffer_size>>(3+16)); // Buffersize DB (24 bits) - put_be16(pb, (track->enc->rc_buffer_size>>3)&0xFFFF); // Buffersize DB - - put_be32(pb, FFMAX(track->enc->bit_rate, track->enc->rc_max_rate)); // maxbitrate (FIXME should be max rate in any 1 sec window) - if(track->enc->rc_max_rate != track->enc->rc_min_rate || track->enc->rc_min_rate==0) - put_be32(pb, 0); // vbr - else - put_be32(pb, track->enc->rc_max_rate); // avg bitrate - - if (track->vosLen) - { - // DecoderSpecific info descriptor - putDescr(pb, 0x05, track->vosLen); - put_buffer(pb, track->vosData, track->vosLen); - } - - - // SL descriptor - putDescr(pb, 0x06, 1); - put_byte(pb, 0x02); - return updateSize (pb, pos); -} - static const CodecTag codec_movvideo_tags[] = { { CODEC_ID_SVQ1, MKTAG('S', 'V', 'Q', '1') }, { CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') }, @@ -587,11 +571,9 @@ static const CodecTag codec_movvideo_tags[] = { { CODEC_ID_NONE, 0 }, }; -static int mov_find_video_codec_tag(MOVTrack* track) +static int mov_find_video_codec_tag(AVFormatContext *s, MOVTrack *track) { - int tag; - - tag = track->enc->codec_tag; + int tag = track->enc->codec_tag; if (!tag) { if (track->enc->codec_id == CODEC_ID_DVVIDEO) { if (track->enc->height == 480) { /* NTSC */ @@ -612,8 +594,30 @@ static int mov_find_video_codec_tag(MOVTrack* track) } } // if no mac fcc found, try with Microsoft tags - if (!tag) + if (!tag) { tag = codec_get_tag(codec_bmp_tags, track->enc->codec_id); + if (tag) { + av_log(s, AV_LOG_INFO, "Warning, using MS style video codec tag, the file may be unplayable!\n"); + } + } + assert(tag); + return tag; +} + +static int mov_find_audio_codec_tag(AVFormatContext *s, MOVTrack *track) +{ + int tag = track->enc->codec_tag; + if (!tag) { + tag = codec_get_tag(codec_movaudio_tags, track->enc->codec_id); + } + // if no mac fcc found, try with Microsoft tags + if (!tag) { + int ms_tag = codec_get_tag(codec_wav_tags, track->enc->codec_id); + if (ms_tag) { + tag = MKTAG('m', 's', ((ms_tag >> 8) & 0xff), (ms_tag & 0xff)); + av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, the file may be unplayable!\n"); + } + } assert(tag); return tag; } @@ -622,13 +626,9 @@ static int mov_write_video_tag(ByteIOContext *pb, MOVTrack* track) { offset_t pos = url_ftell(pb); char compressor_name[32]; - int tag; put_be32(pb, 0); /* size */ - - tag = mov_find_video_codec_tag(track); - put_le32(pb, tag); // store it byteswapped - + put_le32(pb, track->tag); // store it byteswapped put_be32(pb, 0); /* Reserved */ put_be16(pb, 0); /* Reserved */ put_be16(pb, 1); /* Data-reference index */ @@ -1583,30 +1583,19 @@ static int mov_write_header(AVFormatContext *s) } for(i=0; inb_streams; i++){ - AVCodecContext *c= s->streams[i]->codec; + AVStream *st= s->streams[i]; + MOVTrack *track= &mov->tracks[i]; - if(c->codec_type == CODEC_TYPE_VIDEO){ - av_set_pts_info(s->streams[i], 64, 1, c->time_base.den); - if (!codec_get_tag(codec_movvideo_tags, c->codec_id)){ - if(!codec_get_tag(codec_bmp_tags, c->codec_id)) - return -1; - else - av_log(s, AV_LOG_INFO, "Warning, using MS style video codec tag, the file may be unplayable!\n"); - } - }else if(c->codec_type == CODEC_TYPE_AUDIO){ - av_set_pts_info(s->streams[i], 64, 1, c->sample_rate); - if (!codec_get_tag(codec_movaudio_tags, c->codec_id)){ - if(!codec_get_tag(codec_wav_tags, c->codec_id)) - return -1; - else - av_log(s, AV_LOG_INFO, "Warning, using MS style audio codec tag, the file may be unplayable!\n"); - } + track->enc = st->codec; + if(st->codec->codec_type == CODEC_TYPE_VIDEO){ + track->tag = mov_find_video_codec_tag(s, track); + av_set_pts_info(st, 64, 1, st->codec->time_base.den); + }else if(st->codec->codec_type == CODEC_TYPE_AUDIO){ + track->tag = mov_find_audio_codec_tag(s, track); + av_set_pts_info(st, 64, 1, st->codec->sample_rate); } - mov->tracks[i].language = ff_mov_iso639_to_lang(s->streams[i]->language, mov->mode != MODE_MOV); - } - - for (i=0; itracks[i].mode = mov->mode; + track->language = ff_mov_iso639_to_lang(st->language, mov->mode != MODE_MOV); + track->mode = mov->mode; } mov_write_mdat_tag(pb, mov); @@ -1621,8 +1610,8 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) { MOVContext *mov = s->priv_data; ByteIOContext *pb = &s->pb; - AVCodecContext *enc = s->streams[pkt->stream_index]->codec; - MOVTrack* trk = &mov->tracks[pkt->stream_index]; + MOVTrack *trk = &mov->tracks[pkt->stream_index]; + AVCodecContext *enc = trk->enc; int cl, id; unsigned int samplesInChunk = 0; int size= pkt->size; @@ -1698,10 +1687,9 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) if(trk->cluster[cl][id].key_frame) trk->hasKeyframes++; } - trk->enc = enc; trk->entry++; trk->sampleCount += samplesInChunk; - trk->mdat_size += size; + mov->mdat_size += size; put_buffer(pb, pkt->data, size); @@ -1714,26 +1702,20 @@ static int mov_write_trailer(AVFormatContext *s) MOVContext *mov = s->priv_data; ByteIOContext *pb = &s->pb; int res = 0; - int i; - uint64_t j; + int i, j; offset_t moov_pos = url_ftell(pb); /* Write size of mdat tag */ - for (i=0, j=0; itracks[i].ents_allocated > 0) { - j += mov->tracks[i].mdat_size; - } - } - if (j+8 <= UINT32_MAX) { + if (mov->mdat_size+8 <= UINT32_MAX) { url_fseek(pb, mov->mdat_pos, SEEK_SET); - put_be32(pb, j+8); + put_be32(pb, mov->mdat_size+8); } else { /* overwrite 'wide' placeholder atom */ url_fseek(pb, mov->mdat_pos - 8, SEEK_SET); put_be32(pb, 1); /* special value: real atom size will be 64 bit value after tag field */ put_tag(pb, "mdat"); - put_be64(pb, j+16); + put_be64(pb, mov->mdat_size+16); } url_fseek(pb, moov_pos, SEEK_SET);