summaryrefslogtreecommitdiff
path: root/libavformat/avienc.c
diff options
context:
space:
mode:
authorRoman Shaposhnik <roman@shaposhnik.org>2003-04-08 09:51:15 +0000
committerMichael Niedermayer <michaelni@gmx.at>2003-04-08 09:51:15 +0000
commitce9fce63c5d6a43ce585211930273ec69bb6bee1 (patch)
treec5ef65c1a239f191e2f875feb2c11a76583fa56c /libavformat/avienc.c
parent8b92b792d18d7dc3d258f440bb0493af4e973516 (diff)
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
Originally committed as revision 1741 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat/avienc.c')
-rw-r--r--libavformat/avienc.c183
1 files changed, 119 insertions, 64 deletions
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;n<s->nb_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;n<s->nb_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;n<s->nb_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 = {