mirror of
https://github.com/librempeg/librempeg
synced 2024-11-23 11:39:47 +00:00
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
This commit is contained in:
parent
8b92b792d1
commit
ce9fce63c5
@ -6,6 +6,8 @@
|
||||
#define AVIF_WASCAPTUREFILE 0x00010000
|
||||
#define AVIF_COPYRIGHTED 0x00020000
|
||||
|
||||
#define AVI_MAX_RIFF_SIZE 0x40000000LL
|
||||
|
||||
offset_t start_tag(ByteIOContext *pb, const char *tag);
|
||||
void end_tag(ByteIOContext *pb, offset_t start);
|
||||
|
||||
|
@ -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;
|
||||
ByteIOContext *pb = &s->pb;
|
||||
int res = 0;
|
||||
|
||||
if (!url_is_streamed(&s->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 */
|
||||
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));
|
||||
url_fseek(pb, avi->odml_list - 8, SEEK_SET);
|
||||
put_tag(pb, "LIST"); /* Making this AVI OpenDML one */
|
||||
url_fskip(pb, 16);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
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 = {
|
||||
|
@ -1,29 +1,29 @@
|
||||
ffmpeg regression test
|
||||
dda0ba041aef50a5101884291c06d4d9 *./data/a-mpeg1.mpg
|
||||
6713259d72260740bbddaea30631ea18 *./data/out.yuv
|
||||
8836c5e38c7891f04e8e75836e48551e *./data/a-msmpeg4v2.avi
|
||||
e608f387c4ee7227fb4d0042e528ded7 *./data/a-msmpeg4v2.avi
|
||||
712aa6c959d1d90a78fe98657cbff19c *./data/out.yuv
|
||||
8b2a7f5e105784d65426989e4fce6e94 *./data/a-msmpeg4.avi
|
||||
5957d6460c4b8fef35d68159e9cf2db0 *./data/a-msmpeg4.avi
|
||||
8786aa956838234fe3e48d0ef8cbd46c *./data/out.yuv
|
||||
a0bec32a81f9a4cd174557a49cd26430 *./data/a-wmv1.avi
|
||||
78c3826f0a813cf666d9eb36caca5831 *./data/a-wmv1.avi
|
||||
7261e23fd8ad1de6efee022051b936be *./data/out.yuv
|
||||
2ab9e737f91c7eaa970cf894b4e7fce5 *./data/a-wmv2.avi
|
||||
58fa570e0867f30d7503482b8690c9dc *./data/a-wmv2.avi
|
||||
7261e23fd8ad1de6efee022051b936be *./data/out.yuv
|
||||
82822fc90059bc16a3ec159019b38b18 *./data/a-h263.avi
|
||||
04a77cf9d7a3b4dcb394440d0bb67ea7 *./data/a-h263.avi
|
||||
545df74e0aa443499600faedd10a7065 *./data/out.yuv
|
||||
ea780b40dc689a2060303a7b4e99a768 *./data/a-h263p.avi
|
||||
cf9264fe9011bb9475025d6f1d4f4d22 *./data/a-h263p.avi
|
||||
668ba3cb87859ca4d9a4269bad47b3f5 *./data/out.yuv
|
||||
d625bba8e06bed36d201657cf9503bd0 *./data/a-odivx.avi
|
||||
fbda0de97cb28e359ca8b47aacba7d84 *./data/a-odivx.avi
|
||||
98bb113f0fa0d61fd3b0b1699ac6c69a *./data/out.yuv
|
||||
51150a51ef6ee61f82009c393a723a47 *./data/a-huffyuv.avi
|
||||
16049c232bcd37dd42b0f39ed308fe05 *./data/a-huffyuv.avi
|
||||
799d3db687f6cdd7a837ec156efc171f *./data/out.yuv
|
||||
9e1358a14c690c50ac98f3fd8ec4b75f *./data/a-mpeg4-rc.avi
|
||||
78f8b142f5841d0bda2faa0467633154 *./data/a-mpeg4-rc.avi
|
||||
580000bfe2d4359d9aa9a9415f953b3b *./data/out.yuv
|
||||
b7d2c2cb5064b966b057643a80e5454b *./data/a-mpeg4-adv.avi
|
||||
f3bcac88b3c5fa546af7077099ac679f *./data/a-mpeg4-adv.avi
|
||||
4c5e8754506ff2c53649541e4fcd2438 *./data/out.yuv
|
||||
3c65a1bc6866649e666286c825bd5b96 *./data/a-mpeg1b.mpg
|
||||
da8e21c7b78b7a25558dc319524b91d8 *./data/out.yuv
|
||||
f0625ff59a53b5dd5b04307ac9318acf *./data/a-mjpeg.avi
|
||||
2ecdef2ebfcc94e8ce90ce88c90ae8f4 *./data/a-mjpeg.avi
|
||||
f23a9e50a559e174766ee808c48fea22 *./data/out.yuv
|
||||
4b37703d3dc03873f99603165c0fe11e *./data/a-rv10.rm
|
||||
255469fef47bee94cfb2e3385ebb736b *./data/out.yuv
|
||||
|
@ -1,8 +1,8 @@
|
||||
1e53220372e509b33f484e9aa88a9dc8 test_h.avi
|
||||
1a1c9fc08e5a975496d18031aa4881d7 test_l.avi
|
||||
ed85e1199402acdaf42bc6beb45a24da test_h.avi
|
||||
b590b710110b925ad42aeb53410ad610 test_l.avi
|
||||
d41d8cd98f00b204e9800998ecf8427e test_h.mpg
|
||||
d41d8cd98f00b204e9800998ecf8427e test_l.mpg
|
||||
44c65686d4478a1d5d182ff1e301e5c6 test.swf
|
||||
9c01d171b0ff749f951e0dfccad8fae8 test.swf
|
||||
8ea8adac163bfa0df5b5efa03ff4e2bc test_h.asf
|
||||
d5f95938040a197c592897c806a98bfb test_l.asf
|
||||
71bfe6784e025f6eea9f92113d8c7dda test_h.rm
|
||||
|
Loading…
Reference in New Issue
Block a user