From ce9fce63c5d6a43ce585211930273ec69bb6bee1 Mon Sep 17 00:00:00 2001 From: Roman Shaposhnik Date: Tue, 8 Apr 2003 09:51:15 +0000 Subject: AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick ) Originally committed as revision 1741 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/avienc.c | 183 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 119 insertions(+), 64 deletions(-) (limited to 'libavformat/avienc.c') diff --git a/libavformat/avienc.c b/libavformat/avienc.c index 4911094759..5ab5bfd8a1 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -31,7 +31,8 @@ typedef struct AVIIndex { } AVIIndex; typedef struct { - offset_t movi_list, frames_hdr_all, frames_hdr_strm[MAX_STREAMS]; + offset_t riff_start, movi_list, odml_list; + offset_t frames_hdr_all, frames_hdr_strm[MAX_STREAMS]; int audio_strm_length[MAX_STREAMS]; AVIIndex *first, *last; } AVIContext; @@ -126,10 +127,11 @@ const CodecTag codec_bmp_tags[] = { { CODEC_ID_WMV1, MKTAG('w', 'm', 'v', '1') }, { CODEC_ID_WMV2, MKTAG('W', 'M', 'V', '2') }, - { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'l') }, { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'd') }, { CODEC_ID_DVVIDEO, MKTAG('D', 'V', 'S', 'D') }, { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', 'd') }, + { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 's', 'l') }, + { CODEC_ID_DVVIDEO, MKTAG('d', 'v', '2', '5') }, { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '1') }, { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '2') }, { CODEC_ID_MPEG1VIDEO, MKTAG('P', 'I', 'M', '1') }, @@ -230,6 +232,17 @@ static void parse_specific_params(AVCodecContext *stream, int *au_byterate, int } } +static offset_t avi_start_new_riff(AVIContext *avi, ByteIOContext *pb, + const char* riff_tag, const char* list_tag) +{ + offset_t loff; + avi->riff_start = start_tag(pb, "RIFF"); + put_tag(pb, riff_tag); + loff = start_tag(pb, "LIST"); + put_tag(pb, list_tag); + return loff; +} + static int avi_write_header(AVFormatContext *s) { AVIContext *avi = s->priv_data; @@ -238,13 +251,8 @@ static int avi_write_header(AVFormatContext *s) AVCodecContext *stream, *video_enc; offset_t list1, list2, strh, strf; - put_tag(pb, "RIFF"); - put_le32(pb, 0); /* file length */ - put_tag(pb, "AVI "); - /* header list */ - list1 = start_tag(pb, "LIST"); - put_tag(pb, "hdrl"); + list1 = avi_start_new_riff(avi, pb, "AVI ", "hdrl"); /* avi header */ put_tag(pb, "avih"); @@ -259,13 +267,6 @@ static int avi_write_header(AVFormatContext *s) video_enc = stream; } -/* allowing audio-only AVI file - - if (!video_enc) { - av_free(avi); - return -1; - } -*/ nb_frames = 0; if(video_enc){ @@ -371,6 +372,14 @@ static int avi_write_header(AVFormatContext *s) end_tag(pb, strf); end_tag(pb, list2); } + + /* AVI could become an OpenDML one, if it grows beyond 2Gb range */ + avi->odml_list = start_tag(pb, "JUNK"); + put_tag(pb, "odml"); + put_tag(pb, "dmlh"); + put_le32(pb, 248); + url_fskip(pb, 248); + end_tag(pb, avi->odml_list); end_tag(pb, list1); @@ -384,6 +393,63 @@ static int avi_write_header(AVFormatContext *s) return 0; } +static int avi_finish_riff1(AVFormatContext *s) +{ + ByteIOContext *pb = &s->pb; + AVIContext *avi = s->priv_data; + offset_t file_size, idx_chunk; + int n, nb_frames, au_byterate, au_ssize, au_scale; + AVCodecContext *stream; + AVIIndex *idx; + + if (!url_is_streamed(pb)) { + end_tag(pb, avi->movi_list); + + idx_chunk = start_tag(pb, "idx1"); + idx = avi->first; + while (idx != NULL) { + put_buffer(pb, idx->tag, 4); + put_le32(pb, idx->flags); + put_le32(pb, idx->pos); + put_le32(pb, idx->len); + idx = idx->next; + } + end_tag(pb, idx_chunk); + + /* update file size */ + file_size = url_ftell(pb); + end_tag(pb, avi->riff_start); + + /* Fill in frame/sample counters */ + nb_frames = 0; + for(n=0;nnb_streams;n++) { + if (avi->frames_hdr_strm[n] != 0) { + stream = &s->streams[n]->codec; + url_fseek(pb, avi->frames_hdr_strm[n], SEEK_SET); + if (stream->codec_type == CODEC_TYPE_VIDEO) { + put_le32(pb, stream->frame_number); + if (nb_frames < stream->frame_number) + nb_frames = stream->frame_number; + } else { + if (stream->codec_id == CODEC_ID_MP2 || stream->codec_id == CODEC_ID_MP3LAME) { + put_le32(pb, stream->frame_number); + nb_frames += stream->frame_number; + } else { + parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale); + put_le32(pb, avi->audio_strm_length[n] / au_ssize); + } + } + } + } + if (avi->frames_hdr_all != 0) { + url_fseek(pb, avi->frames_hdr_all, SEEK_SET); + put_le32(pb, nb_frames); + } + url_fseek(pb, file_size, SEEK_SET); + } + return 0; +} + static int avi_write_packet(AVFormatContext *s, int stream_index, uint8_t *buf, int size, int force_pts) { @@ -393,6 +459,16 @@ static int avi_write_packet(AVFormatContext *s, int stream_index, unsigned char tag[5]; unsigned int flags; AVCodecContext *enc; + + if (url_ftell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE) { + if (avi->riff_start != 8) { + end_tag(pb, avi->movi_list); + end_tag(pb, avi->riff_start); + } else + avi_finish_riff1(s); + + avi->movi_list = avi_start_new_riff(avi, pb, "AVIX", "movi"); + } enc = &s->streams[stream_index]->codec; @@ -436,61 +512,40 @@ static int avi_write_packet(AVFormatContext *s, int stream_index, static int avi_write_trailer(AVFormatContext *s) { - ByteIOContext *pb = &s->pb; AVIContext *avi = s->priv_data; - offset_t file_size, idx_chunk; - int n, nb_frames, au_byterate, au_ssize, au_scale; - AVCodecContext *stream; - AVIIndex *idx; - - if (!url_is_streamed(&s->pb)) { - end_tag(pb, avi->movi_list); + ByteIOContext *pb = &s->pb; + int res = 0; - idx_chunk = start_tag(pb, "idx1"); - idx = avi->first; - while (idx != NULL) { - put_buffer(pb, idx->tag, 4); - put_le32(pb, idx->flags); - put_le32(pb, idx->pos); - put_le32(pb, idx->len); - idx = idx->next; - } - end_tag(pb, idx_chunk); - - /* update file size */ + if (avi->riff_start != 8) { + int n, nb_frames; + offset_t file_size; + file_size = url_ftell(pb); - url_fseek(pb, 4, SEEK_SET); - put_le32(pb, (uint32_t)(file_size - 8)); - - /* Fill in frame/sample counters */ - nb_frames = 0; - for(n=0;nnb_streams;n++) { - if (avi->frames_hdr_strm[n] != 0) { - stream = &s->streams[n]->codec; - url_fseek(pb, avi->frames_hdr_strm[n], SEEK_SET); - if (stream->codec_type == CODEC_TYPE_VIDEO) { - put_le32(pb, stream->frame_number); - if (nb_frames < stream->frame_number) - nb_frames = stream->frame_number; - } else { - if (stream->codec_id == CODEC_ID_MP2 || stream->codec_id == CODEC_ID_MP3LAME) { - put_le32(pb, stream->frame_number); - nb_frames += stream->frame_number; - } else { - parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale); - put_le32(pb, avi->audio_strm_length[n] / au_ssize); - } + url_fseek(pb, avi->odml_list - 8, SEEK_SET); + put_tag(pb, "LIST"); /* Making this AVI OpenDML one */ + url_fskip(pb, 16); + + for (n=nb_frames=0;nnb_streams;n++) { + AVCodecContext *stream = &s->streams[n]->codec; + if (stream->codec_type == CODEC_TYPE_VIDEO) { + if (nb_frames < stream->frame_number) + nb_frames = stream->frame_number; + } else { + if (stream->codec_id == CODEC_ID_MP2 || stream->codec_id == CODEC_ID_MP3LAME) { + nb_frames += stream->frame_number; } } - } - if (avi->frames_hdr_all != 0) { - url_fseek(pb, avi->frames_hdr_all, SEEK_SET); - put_le32(pb, nb_frames); - } - url_fseek(pb, file_size, SEEK_SET); - } + } + put_le32(pb, nb_frames); + + end_tag(pb, avi->movi_list); + end_tag(pb, avi->riff_start); + url_fseek(pb, file_size, SEEK_SET); + } else + res = avi_finish_riff1(s); + put_flush_packet(pb); - return 0; + return res; } static AVOutputFormat avi_oformat = { -- cgit v1.2.3