You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02: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:
		
				
					committed by
					
						 Michael Niedermayer
						Michael Niedermayer
					
				
			
			
				
	
			
			
			
						parent
						
							8b92b792d1
						
					
				
				
					commit
					ce9fce63c5
				
			| @@ -6,6 +6,8 @@ | |||||||
| #define AVIF_WASCAPTUREFILE	0x00010000 | #define AVIF_WASCAPTUREFILE	0x00010000 | ||||||
| #define AVIF_COPYRIGHTED	0x00020000 | #define AVIF_COPYRIGHTED	0x00020000 | ||||||
|  |  | ||||||
|  | #define AVI_MAX_RIFF_SIZE       0x40000000LL | ||||||
|  |  | ||||||
| offset_t start_tag(ByteIOContext *pb, const char *tag); | offset_t start_tag(ByteIOContext *pb, const char *tag); | ||||||
| void end_tag(ByteIOContext *pb, offset_t start); | void end_tag(ByteIOContext *pb, offset_t start); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -31,7 +31,8 @@ typedef struct AVIIndex { | |||||||
| } AVIIndex; | } AVIIndex; | ||||||
|  |  | ||||||
| typedef struct { | 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]; |     int audio_strm_length[MAX_STREAMS]; | ||||||
|     AVIIndex *first, *last; |     AVIIndex *first, *last; | ||||||
| } AVIContext; | } AVIContext; | ||||||
| @@ -126,10 +127,11 @@ const CodecTag codec_bmp_tags[] = { | |||||||
|     { CODEC_ID_WMV1, MKTAG('w', 'm', 'v', '1') },  |     { CODEC_ID_WMV1, MKTAG('w', 'm', 'v', '1') },  | ||||||
|  |  | ||||||
|     { CODEC_ID_WMV2, MKTAG('W', 'M', 'V', '2') },  |     { 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', 'S', 'D') },  |     { CODEC_ID_DVVIDEO, MKTAG('D', 'V', 'S', 'D') },  | ||||||
|     { CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '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', '1') },  | ||||||
|     { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '2') },  |     { CODEC_ID_MPEG1VIDEO, MKTAG('m', 'p', 'g', '2') },  | ||||||
|     { CODEC_ID_MPEG1VIDEO, MKTAG('P', 'I', 'M', '1') },  |     { 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) | static int avi_write_header(AVFormatContext *s) | ||||||
| { | { | ||||||
|     AVIContext *avi = s->priv_data; |     AVIContext *avi = s->priv_data; | ||||||
| @@ -238,13 +251,8 @@ static int avi_write_header(AVFormatContext *s) | |||||||
|     AVCodecContext *stream, *video_enc; |     AVCodecContext *stream, *video_enc; | ||||||
|     offset_t list1, list2, strh, strf; |     offset_t list1, list2, strh, strf; | ||||||
|  |  | ||||||
|     put_tag(pb, "RIFF"); |  | ||||||
|     put_le32(pb, 0); /* file length */ |  | ||||||
|     put_tag(pb, "AVI "); |  | ||||||
|  |  | ||||||
|     /* header list */ |     /* header list */ | ||||||
|     list1 = start_tag(pb, "LIST"); |     list1 = avi_start_new_riff(avi, pb, "AVI ", "hdrl"); | ||||||
|     put_tag(pb, "hdrl"); |  | ||||||
|  |  | ||||||
|     /* avi header */ |     /* avi header */ | ||||||
|     put_tag(pb, "avih"); |     put_tag(pb, "avih"); | ||||||
| @@ -259,13 +267,6 @@ static int avi_write_header(AVFormatContext *s) | |||||||
|             video_enc = stream; |             video_enc = stream; | ||||||
|     } |     } | ||||||
|      |      | ||||||
| /*	allowing audio-only AVI file  |  | ||||||
|      |  | ||||||
|     if (!video_enc) { |  | ||||||
|         av_free(avi); |  | ||||||
|         return -1; |  | ||||||
|     } |  | ||||||
| */     |  | ||||||
|     nb_frames = 0; |     nb_frames = 0; | ||||||
|  |  | ||||||
|     if(video_enc){ |     if(video_enc){ | ||||||
| @@ -371,6 +372,14 @@ static int avi_write_header(AVFormatContext *s) | |||||||
|         end_tag(pb, strf); |         end_tag(pb, strf); | ||||||
|         end_tag(pb, list2); |         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); |     end_tag(pb, list1); | ||||||
|      |      | ||||||
| @@ -384,6 +393,63 @@ static int avi_write_header(AVFormatContext *s) | |||||||
|     return 0; |     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, | static int avi_write_packet(AVFormatContext *s, int stream_index, | ||||||
|                             uint8_t *buf, int size, int force_pts) |                             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 char tag[5]; | ||||||
|     unsigned int flags; |     unsigned int flags; | ||||||
|     AVCodecContext *enc; |     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; |     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) | static int avi_write_trailer(AVFormatContext *s) | ||||||
| { | { | ||||||
|     ByteIOContext *pb = &s->pb; |  | ||||||
|     AVIContext *avi = s->priv_data; |     AVIContext *avi = s->priv_data; | ||||||
|     offset_t file_size, idx_chunk; |     ByteIOContext *pb = &s->pb; | ||||||
|     int n, nb_frames, au_byterate, au_ssize, au_scale; |     int res = 0; | ||||||
|     AVCodecContext *stream; |  | ||||||
|     AVIIndex *idx; |  | ||||||
|  |  | ||||||
|     if (!url_is_streamed(&s->pb)) { |     if (avi->riff_start != 8) { | ||||||
|         end_tag(pb, avi->movi_list); |         int n, nb_frames; | ||||||
|  | 	offset_t file_size; | ||||||
|         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); |         file_size = url_ftell(pb); | ||||||
|         url_fseek(pb, 4, SEEK_SET); | 	url_fseek(pb, avi->odml_list - 8, SEEK_SET); | ||||||
|         put_le32(pb, (uint32_t)(file_size - 8)); | 	put_tag(pb, "LIST"); /* Making this AVI OpenDML one */ | ||||||
|  | 	url_fskip(pb, 16); | ||||||
|  |  | ||||||
|         /* Fill in frame/sample counters */ |         for (n=nb_frames=0;n<s->nb_streams;n++) { | ||||||
|         nb_frames = 0; |              AVCodecContext *stream = &s->streams[n]->codec; | ||||||
|         for(n=0;n<s->nb_streams;n++) { |              if (stream->codec_type == CODEC_TYPE_VIDEO) { | ||||||
|             if (avi->frames_hdr_strm[n] != 0) { |                  if (nb_frames < stream->frame_number) | ||||||
|                 stream = &s->streams[n]->codec; |                      nb_frames = stream->frame_number; | ||||||
|                 url_fseek(pb, avi->frames_hdr_strm[n], SEEK_SET); |              } else { | ||||||
|                 if (stream->codec_type == CODEC_TYPE_VIDEO) { |                  if (stream->codec_id == CODEC_ID_MP2 || stream->codec_id == CODEC_ID_MP3LAME) { | ||||||
|                     put_le32(pb, stream->frame_number);  |                      nb_frames += 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) { | 	put_le32(pb, nb_frames); | ||||||
|            url_fseek(pb, avi->frames_hdr_all, 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); | 	url_fseek(pb, file_size, SEEK_SET); | ||||||
|     } |     } else | ||||||
|  |         res = avi_finish_riff1(s); | ||||||
|  |  | ||||||
|     put_flush_packet(pb); |     put_flush_packet(pb); | ||||||
|     return 0; |     return res; | ||||||
| } | } | ||||||
|  |  | ||||||
| static AVOutputFormat avi_oformat = { | static AVOutputFormat avi_oformat = { | ||||||
|   | |||||||
| @@ -1,29 +1,29 @@ | |||||||
| ffmpeg regression test | ffmpeg regression test | ||||||
| dda0ba041aef50a5101884291c06d4d9 *./data/a-mpeg1.mpg | dda0ba041aef50a5101884291c06d4d9 *./data/a-mpeg1.mpg | ||||||
| 6713259d72260740bbddaea30631ea18 *./data/out.yuv | 6713259d72260740bbddaea30631ea18 *./data/out.yuv | ||||||
| 8836c5e38c7891f04e8e75836e48551e *./data/a-msmpeg4v2.avi | e608f387c4ee7227fb4d0042e528ded7 *./data/a-msmpeg4v2.avi | ||||||
| 712aa6c959d1d90a78fe98657cbff19c *./data/out.yuv | 712aa6c959d1d90a78fe98657cbff19c *./data/out.yuv | ||||||
| 8b2a7f5e105784d65426989e4fce6e94 *./data/a-msmpeg4.avi | 5957d6460c4b8fef35d68159e9cf2db0 *./data/a-msmpeg4.avi | ||||||
| 8786aa956838234fe3e48d0ef8cbd46c *./data/out.yuv | 8786aa956838234fe3e48d0ef8cbd46c *./data/out.yuv | ||||||
| a0bec32a81f9a4cd174557a49cd26430 *./data/a-wmv1.avi | 78c3826f0a813cf666d9eb36caca5831 *./data/a-wmv1.avi | ||||||
| 7261e23fd8ad1de6efee022051b936be *./data/out.yuv | 7261e23fd8ad1de6efee022051b936be *./data/out.yuv | ||||||
| 2ab9e737f91c7eaa970cf894b4e7fce5 *./data/a-wmv2.avi | 58fa570e0867f30d7503482b8690c9dc *./data/a-wmv2.avi | ||||||
| 7261e23fd8ad1de6efee022051b936be *./data/out.yuv | 7261e23fd8ad1de6efee022051b936be *./data/out.yuv | ||||||
| 82822fc90059bc16a3ec159019b38b18 *./data/a-h263.avi | 04a77cf9d7a3b4dcb394440d0bb67ea7 *./data/a-h263.avi | ||||||
| 545df74e0aa443499600faedd10a7065 *./data/out.yuv | 545df74e0aa443499600faedd10a7065 *./data/out.yuv | ||||||
| ea780b40dc689a2060303a7b4e99a768 *./data/a-h263p.avi | cf9264fe9011bb9475025d6f1d4f4d22 *./data/a-h263p.avi | ||||||
| 668ba3cb87859ca4d9a4269bad47b3f5 *./data/out.yuv | 668ba3cb87859ca4d9a4269bad47b3f5 *./data/out.yuv | ||||||
| d625bba8e06bed36d201657cf9503bd0 *./data/a-odivx.avi | fbda0de97cb28e359ca8b47aacba7d84 *./data/a-odivx.avi | ||||||
| 98bb113f0fa0d61fd3b0b1699ac6c69a *./data/out.yuv | 98bb113f0fa0d61fd3b0b1699ac6c69a *./data/out.yuv | ||||||
| 51150a51ef6ee61f82009c393a723a47 *./data/a-huffyuv.avi | 16049c232bcd37dd42b0f39ed308fe05 *./data/a-huffyuv.avi | ||||||
| 799d3db687f6cdd7a837ec156efc171f *./data/out.yuv | 799d3db687f6cdd7a837ec156efc171f *./data/out.yuv | ||||||
| 9e1358a14c690c50ac98f3fd8ec4b75f *./data/a-mpeg4-rc.avi | 78f8b142f5841d0bda2faa0467633154 *./data/a-mpeg4-rc.avi | ||||||
| 580000bfe2d4359d9aa9a9415f953b3b *./data/out.yuv | 580000bfe2d4359d9aa9a9415f953b3b *./data/out.yuv | ||||||
| b7d2c2cb5064b966b057643a80e5454b *./data/a-mpeg4-adv.avi | f3bcac88b3c5fa546af7077099ac679f *./data/a-mpeg4-adv.avi | ||||||
| 4c5e8754506ff2c53649541e4fcd2438 *./data/out.yuv | 4c5e8754506ff2c53649541e4fcd2438 *./data/out.yuv | ||||||
| 3c65a1bc6866649e666286c825bd5b96 *./data/a-mpeg1b.mpg | 3c65a1bc6866649e666286c825bd5b96 *./data/a-mpeg1b.mpg | ||||||
| da8e21c7b78b7a25558dc319524b91d8 *./data/out.yuv | da8e21c7b78b7a25558dc319524b91d8 *./data/out.yuv | ||||||
| f0625ff59a53b5dd5b04307ac9318acf *./data/a-mjpeg.avi | 2ecdef2ebfcc94e8ce90ce88c90ae8f4 *./data/a-mjpeg.avi | ||||||
| f23a9e50a559e174766ee808c48fea22 *./data/out.yuv | f23a9e50a559e174766ee808c48fea22 *./data/out.yuv | ||||||
| 4b37703d3dc03873f99603165c0fe11e *./data/a-rv10.rm | 4b37703d3dc03873f99603165c0fe11e *./data/a-rv10.rm | ||||||
| 255469fef47bee94cfb2e3385ebb736b *./data/out.yuv | 255469fef47bee94cfb2e3385ebb736b *./data/out.yuv | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| 1e53220372e509b33f484e9aa88a9dc8  test_h.avi | ed85e1199402acdaf42bc6beb45a24da  test_h.avi | ||||||
| 1a1c9fc08e5a975496d18031aa4881d7  test_l.avi | b590b710110b925ad42aeb53410ad610  test_l.avi | ||||||
| d41d8cd98f00b204e9800998ecf8427e  test_h.mpg | d41d8cd98f00b204e9800998ecf8427e  test_h.mpg | ||||||
| d41d8cd98f00b204e9800998ecf8427e  test_l.mpg | d41d8cd98f00b204e9800998ecf8427e  test_l.mpg | ||||||
| 44c65686d4478a1d5d182ff1e301e5c6  test.swf | 9c01d171b0ff749f951e0dfccad8fae8  test.swf | ||||||
| 8ea8adac163bfa0df5b5efa03ff4e2bc  test_h.asf | 8ea8adac163bfa0df5b5efa03ff4e2bc  test_h.asf | ||||||
| d5f95938040a197c592897c806a98bfb  test_l.asf | d5f95938040a197c592897c806a98bfb  test_l.asf | ||||||
| 71bfe6784e025f6eea9f92113d8c7dda  test_h.rm | 71bfe6784e025f6eea9f92113d8c7dda  test_h.rm | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user