Mercurial > libavformat.hg
annotate avienc.c @ 5330:936a03bbd757 libavformat
Suppress ?params in the rtsp uri
Right now rtsp demuxer receives it's ffmpeg specific params encoded in the url
That made the server receiving requests with the url ending with "?udp",
"?multicast" and "?tcp". That may or may not cause problems to servers with
overly strict or overly simple uri parsers
Patch from Armand Bendanan (name.surnameATfreeDOTfr)
author | lu_zero |
---|---|
date | Sat, 24 Oct 2009 15:18:21 +0000 |
parents | 33a244b7ca65 |
children | d7c68046a431 |
rev | line source |
---|---|
0 | 1 /* |
1415
3b00fb8ef8e4
replace coder/decoder file description in libavformat by muxer/demuxer
aurel
parents:
1358
diff
changeset
|
2 * AVI muxer |
4251
77e0c7511d41
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
4250
diff
changeset
|
3 * Copyright (c) 2000 Fabrice Bellard |
0 | 4 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1332
diff
changeset
|
5 * This file is part of FFmpeg. |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1332
diff
changeset
|
6 * |
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1332
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
0 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1332
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
0 | 11 * |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1332
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
0 | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
1358
0899bfe4105c
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
1332
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
896
edbe5c3717f9
Update licensing information: The FSF changed postal address.
diego
parents:
894
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 20 */ |
21 #include "avformat.h" | |
22 #include "avi.h" | |
1172
6a5e58d2114b
move common stuff from avienc.c and wav.c to new file riff.c
mru
parents:
1169
diff
changeset
|
23 #include "riff.h" |
0 | 24 |
25 /* | |
885 | 26 * TODO: |
0 | 27 * - fill all fields if non streamed (nb_frames for example) |
28 */ | |
29 | |
119 | 30 typedef struct AVIIentry { |
31 unsigned int flags, pos, len; | |
32 } AVIIentry; | |
33 | |
34 #define AVI_INDEX_CLUSTER_SIZE 16384 | |
35 | |
0 | 36 typedef struct AVIIndex { |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3872
diff
changeset
|
37 int64_t indx_start; |
119 | 38 int entry; |
39 int ents_allocated; | |
40 AVIIentry** cluster; | |
0 | 41 } AVIIndex; |
42 | |
43 typedef struct { | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3872
diff
changeset
|
44 int64_t riff_start, movi_list, odml_list; |
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3872
diff
changeset
|
45 int64_t frames_hdr_all, frames_hdr_strm[MAX_STREAMS]; |
0 | 46 int audio_strm_length[MAX_STREAMS]; |
119 | 47 int riff_id; |
479 | 48 int packet_count[MAX_STREAMS]; |
119 | 49 |
50 AVIIndex indexes[MAX_STREAMS]; | |
0 | 51 } AVIContext; |
52 | |
885 | 53 static inline AVIIentry* avi_get_ientry(AVIIndex* idx, int ent_id) |
119 | 54 { |
55 int cl = ent_id / AVI_INDEX_CLUSTER_SIZE; | |
56 int id = ent_id % AVI_INDEX_CLUSTER_SIZE; | |
57 return &idx->cluster[cl][id]; | |
58 } | |
59 | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3872
diff
changeset
|
60 static int64_t avi_start_new_riff(AVIContext *avi, ByteIOContext *pb, |
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3872
diff
changeset
|
61 const char* riff_tag, const char* list_tag) |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
62 { |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3872
diff
changeset
|
63 int64_t loff; |
119 | 64 int i; |
885 | 65 |
119 | 66 avi->riff_id++; |
67 for (i=0; i<MAX_STREAMS; i++) | |
68 avi->indexes[i].entry = 0; | |
885 | 69 |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
70 avi->riff_start = ff_start_tag(pb, "RIFF"); |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
71 put_tag(pb, riff_tag); |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
72 loff = ff_start_tag(pb, "LIST"); |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
73 put_tag(pb, list_tag); |
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
74 return loff; |
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
75 } |
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
76 |
1332 | 77 static char* avi_stream2fourcc(char* tag, int index, enum CodecType type) |
119 | 78 { |
79 tag[0] = '0'; | |
80 tag[1] = '0' + index; | |
81 if (type == CODEC_TYPE_VIDEO) { | |
82 tag[2] = 'd'; | |
83 tag[3] = 'c'; | |
5044
2ef633b32f7a
Add support for muxing XSUB subtitles to AVI muxer.
reimar
parents:
4816
diff
changeset
|
84 } else if (type == CODEC_TYPE_SUBTITLE) { |
2ef633b32f7a
Add support for muxing XSUB subtitles to AVI muxer.
reimar
parents:
4816
diff
changeset
|
85 // note: this is not an official code |
2ef633b32f7a
Add support for muxing XSUB subtitles to AVI muxer.
reimar
parents:
4816
diff
changeset
|
86 tag[2] = 's'; |
2ef633b32f7a
Add support for muxing XSUB subtitles to AVI muxer.
reimar
parents:
4816
diff
changeset
|
87 tag[3] = 'b'; |
119 | 88 } else { |
89 tag[2] = 'w'; | |
90 tag[3] = 'b'; | |
91 } | |
92 tag[4] = '\0'; | |
93 return tag; | |
94 } | |
95 | |
1256 | 96 static void avi_write_info_tag(ByteIOContext *pb, const char *tag, const char *str) |
97 { | |
98 int len = strlen(str); | |
99 if (len > 0) { | |
100 len++; | |
101 put_tag(pb, tag); | |
102 put_le32(pb, len); | |
103 put_strz(pb, str); | |
104 if (len & 1) | |
105 put_byte(pb, 0); | |
106 } | |
107 } | |
108 | |
4149 | 109 static void avi_write_info_tag2(AVFormatContext *s, const char *fourcc, const char *key1, const char *key2) |
110 { | |
4250
2fc899894f5e
replace AV_METADATA_IGNORE_CASE flag by a new AV_METADATA_MATCH_CASE flag
aurel
parents:
4206
diff
changeset
|
111 AVMetadataTag *tag= av_metadata_get(s->metadata, key1, NULL, 0); |
4149 | 112 if(!tag && key2) |
4250
2fc899894f5e
replace AV_METADATA_IGNORE_CASE flag by a new AV_METADATA_MATCH_CASE flag
aurel
parents:
4206
diff
changeset
|
113 tag= av_metadata_get(s->metadata, key2, NULL, 0); |
4149 | 114 if(tag) |
115 avi_write_info_tag(s->pb, fourcc, tag->value); | |
116 } | |
117 | |
1267 | 118 static int avi_write_counters(AVFormatContext* s, int riff_id) |
119 { | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2227
diff
changeset
|
120 ByteIOContext *pb = s->pb; |
1267 | 121 AVIContext *avi = s->priv_data; |
122 int n, au_byterate, au_ssize, au_scale, nb_frames = 0; | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3872
diff
changeset
|
123 int64_t file_size; |
1267 | 124 AVCodecContext* stream; |
125 | |
126 file_size = url_ftell(pb); | |
127 for(n = 0; n < s->nb_streams; n++) { | |
128 assert(avi->frames_hdr_strm[n]); | |
129 stream = s->streams[n]->codec; | |
130 url_fseek(pb, avi->frames_hdr_strm[n], SEEK_SET); | |
131 ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale); | |
132 if(au_ssize == 0) { | |
133 put_le32(pb, avi->packet_count[n]); | |
134 } else { | |
135 put_le32(pb, avi->audio_strm_length[n] / au_ssize); | |
136 } | |
137 if(stream->codec_type == CODEC_TYPE_VIDEO) | |
138 nb_frames = FFMAX(nb_frames, avi->packet_count[n]); | |
139 } | |
140 if(riff_id == 1) { | |
141 assert(avi->frames_hdr_all); | |
142 url_fseek(pb, avi->frames_hdr_all, SEEK_SET); | |
143 put_le32(pb, nb_frames); | |
144 } | |
145 url_fseek(pb, file_size, SEEK_SET); | |
146 | |
147 return 0; | |
148 } | |
149 | |
0 | 150 static int avi_write_header(AVFormatContext *s) |
151 { | |
152 AVIContext *avi = s->priv_data; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2227
diff
changeset
|
153 ByteIOContext *pb = s->pb; |
0 | 154 int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale; |
155 AVCodecContext *stream, *video_enc; | |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3872
diff
changeset
|
156 int64_t list1, list2, strh, strf; |
0 | 157 |
158 /* header list */ | |
119 | 159 avi->riff_id = 0; |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
160 list1 = avi_start_new_riff(avi, pb, "AVI ", "hdrl"); |
0 | 161 |
162 /* avi header */ | |
163 put_tag(pb, "avih"); | |
164 put_le32(pb, 14 * 4); | |
165 bitrate = 0; | |
166 | |
167 video_enc = NULL; | |
168 for(n=0;n<s->nb_streams;n++) { | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
796
diff
changeset
|
169 stream = s->streams[n]->codec; |
0 | 170 bitrate += stream->bit_rate; |
171 if (stream->codec_type == CODEC_TYPE_VIDEO) | |
172 video_enc = stream; | |
173 } | |
885 | 174 |
0 | 175 nb_frames = 0; |
176 | |
36
1188ad85857a
audio only avi patch by (Andriy Rysin <arysin at bcsii dot net>)
michaelni
parents:
15
diff
changeset
|
177 if(video_enc){ |
1556 | 178 put_le32(pb, (uint32_t)(INT64_C(1000000) * video_enc->time_base.num / video_enc->time_base.den)); |
36
1188ad85857a
audio only avi patch by (Andriy Rysin <arysin at bcsii dot net>)
michaelni
parents:
15
diff
changeset
|
179 } else { |
887 | 180 put_le32(pb, 0); |
36
1188ad85857a
audio only avi patch by (Andriy Rysin <arysin at bcsii dot net>)
michaelni
parents:
15
diff
changeset
|
181 } |
0 | 182 put_le32(pb, bitrate / 8); /* XXX: not quite exact */ |
183 put_le32(pb, 0); /* padding */ | |
873
7af647503b67
Support for streaming: dont write indexes and dont signal HAS_INDEX in header. Also set filesize to max in this case.
alex
parents:
863
diff
changeset
|
184 if (url_is_streamed(pb)) |
887 | 185 put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_ISINTERLEAVED); /* flags */ |
873
7af647503b67
Support for streaming: dont write indexes and dont signal HAS_INDEX in header. Also set filesize to max in this case.
alex
parents:
863
diff
changeset
|
186 else |
887 | 187 put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */ |
0 | 188 avi->frames_hdr_all = url_ftell(pb); /* remember this offset to fill later */ |
189 put_le32(pb, nb_frames); /* nb frames, filled later */ | |
190 put_le32(pb, 0); /* initial frame */ | |
191 put_le32(pb, s->nb_streams); /* nb streams */ | |
192 put_le32(pb, 1024 * 1024); /* suggested buffer size */ | |
885 | 193 if(video_enc){ |
992 | 194 put_le32(pb, video_enc->width); |
195 put_le32(pb, video_enc->height); | |
36
1188ad85857a
audio only avi patch by (Andriy Rysin <arysin at bcsii dot net>)
michaelni
parents:
15
diff
changeset
|
196 } else { |
887 | 197 put_le32(pb, 0); |
198 put_le32(pb, 0); | |
885 | 199 } |
0 | 200 put_le32(pb, 0); /* reserved */ |
201 put_le32(pb, 0); /* reserved */ | |
202 put_le32(pb, 0); /* reserved */ | |
203 put_le32(pb, 0); /* reserved */ | |
885 | 204 |
0 | 205 /* stream list */ |
206 for(i=0;i<n;i++) { | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
207 list2 = ff_start_tag(pb, "LIST"); |
0 | 208 put_tag(pb, "strl"); |
885 | 209 |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
796
diff
changeset
|
210 stream = s->streams[i]->codec; |
0 | 211 |
212 /* stream generic header */ | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
213 strh = ff_start_tag(pb, "strh"); |
0 | 214 switch(stream->codec_type) { |
5044
2ef633b32f7a
Add support for muxing XSUB subtitles to AVI muxer.
reimar
parents:
4816
diff
changeset
|
215 case CODEC_TYPE_SUBTITLE: |
2ef633b32f7a
Add support for muxing XSUB subtitles to AVI muxer.
reimar
parents:
4816
diff
changeset
|
216 // XSUB subtitles behave like video tracks, other subtitles |
2ef633b32f7a
Add support for muxing XSUB subtitles to AVI muxer.
reimar
parents:
4816
diff
changeset
|
217 // are not (yet) supported. |
2ef633b32f7a
Add support for muxing XSUB subtitles to AVI muxer.
reimar
parents:
4816
diff
changeset
|
218 if (stream->codec_id != CODEC_ID_XSUB) break; |
781 | 219 case CODEC_TYPE_VIDEO: put_tag(pb, "vids"); break; |
220 case CODEC_TYPE_AUDIO: put_tag(pb, "auds"); break; | |
221 // case CODEC_TYPE_TEXT : put_tag(pb, "txts"); break; | |
222 case CODEC_TYPE_DATA : put_tag(pb, "dats"); break; | |
223 } | |
5044
2ef633b32f7a
Add support for muxing XSUB subtitles to AVI muxer.
reimar
parents:
4816
diff
changeset
|
224 if(stream->codec_type == CODEC_TYPE_VIDEO || |
2ef633b32f7a
Add support for muxing XSUB subtitles to AVI muxer.
reimar
parents:
4816
diff
changeset
|
225 stream->codec_id == CODEC_ID_XSUB) |
89
8e3cf4e9fc5a
rawvideo patch by (Fred Rothganger <rothgang at uiuc dot edu>)
michaelni
parents:
85
diff
changeset
|
226 put_le32(pb, stream->codec_tag); |
781 | 227 else |
228 put_le32(pb, 1); | |
229 put_le32(pb, 0); /* flags */ | |
230 put_le16(pb, 0); /* priority */ | |
231 put_le16(pb, 0); /* language */ | |
232 put_le32(pb, 0); /* initial frame */ | |
233 | |
234 ff_parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale); | |
75
78bec272ce3a
read BITMAPINFOHEADER extra stuff (huffyuv decoding fixed)
michaelni
parents:
65
diff
changeset
|
235 |
781 | 236 put_le32(pb, au_scale); /* scale */ |
237 put_le32(pb, au_byterate); /* rate */ | |
238 av_set_pts_info(s->streams[i], 64, au_scale, au_byterate); | |
239 | |
240 put_le32(pb, 0); /* start */ | |
241 avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */ | |
887 | 242 if (url_is_streamed(pb)) |
243 put_le32(pb, AVI_MAX_RIFF_SIZE); /* FIXME: this may be broken, but who cares */ | |
244 else | |
245 put_le32(pb, 0); /* length, XXX: filled later */ | |
885 | 246 |
781 | 247 /* suggested buffer size */ //FIXME set at the end to largest chunk |
248 if(stream->codec_type == CODEC_TYPE_VIDEO) | |
885 | 249 put_le32(pb, 1024 * 1024); |
781 | 250 else if(stream->codec_type == CODEC_TYPE_AUDIO) |
885 | 251 put_le32(pb, 12 * 1024); |
781 | 252 else |
885 | 253 put_le32(pb, 0); |
781 | 254 put_le32(pb, -1); /* quality */ |
255 put_le32(pb, au_ssize); /* sample size */ | |
256 put_le32(pb, 0); | |
257 put_le16(pb, stream->width); | |
258 put_le16(pb, stream->height); | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
259 ff_end_tag(pb, strh); |
0 | 260 |
781 | 261 if(stream->codec_type != CODEC_TYPE_DATA){ |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
262 strf = ff_start_tag(pb, "strf"); |
0 | 263 switch(stream->codec_type) { |
5044
2ef633b32f7a
Add support for muxing XSUB subtitles to AVI muxer.
reimar
parents:
4816
diff
changeset
|
264 case CODEC_TYPE_SUBTITLE: |
2ef633b32f7a
Add support for muxing XSUB subtitles to AVI muxer.
reimar
parents:
4816
diff
changeset
|
265 // XSUB subtitles behave like video tracks, other subtitles |
2ef633b32f7a
Add support for muxing XSUB subtitles to AVI muxer.
reimar
parents:
4816
diff
changeset
|
266 // are not (yet) supported. |
2ef633b32f7a
Add support for muxing XSUB subtitles to AVI muxer.
reimar
parents:
4816
diff
changeset
|
267 if (stream->codec_id != CODEC_ID_XSUB) break; |
0 | 268 case CODEC_TYPE_VIDEO: |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
269 ff_put_bmp_header(pb, stream, ff_codec_bmp_tags, 0); |
0 | 270 break; |
271 case CODEC_TYPE_AUDIO: | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
272 if (ff_put_wav_header(pb, stream) < 0) { |
0 | 273 return -1; |
274 } | |
275 break; | |
276 default: | |
537 | 277 return -1; |
0 | 278 } |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
279 ff_end_tag(pb, strf); |
781 | 280 } |
885 | 281 |
887 | 282 if (!url_is_streamed(pb)) { |
283 unsigned char tag[5]; | |
284 int j; | |
885 | 285 |
286 /* Starting to lay out AVI OpenDML master index. | |
887 | 287 * We want to make it JUNK entry for now, since we'd |
288 * like to get away without making AVI an OpenDML one | |
289 * for compatibility reasons. | |
290 */ | |
291 avi->indexes[i].entry = avi->indexes[i].ents_allocated = 0; | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
292 avi->indexes[i].indx_start = ff_start_tag(pb, "JUNK"); |
887 | 293 put_le16(pb, 4); /* wLongsPerEntry */ |
294 put_byte(pb, 0); /* bIndexSubType (0 == frame index) */ | |
295 put_byte(pb, 0); /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */ | |
296 put_le32(pb, 0); /* nEntriesInUse (will fill out later on) */ | |
297 put_tag(pb, avi_stream2fourcc(&tag[0], i, stream->codec_type)); | |
298 /* dwChunkId */ | |
299 put_le64(pb, 0); /* dwReserved[3] | |
300 put_le32(pb, 0); Must be 0. */ | |
301 for (j=0; j < AVI_MASTER_INDEX_SIZE * 2; j++) | |
302 put_le64(pb, 0); | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
303 ff_end_tag(pb, avi->indexes[i].indx_start); |
887 | 304 } |
885 | 305 |
3100 | 306 if( stream->codec_type == CODEC_TYPE_VIDEO |
3759
27537074f2a9
convert every muxer/demuxer to write/read sample_aspect_ratio from/to
aurel
parents:
3424
diff
changeset
|
307 && s->streams[i]->sample_aspect_ratio.num>0 |
27537074f2a9
convert every muxer/demuxer to write/read sample_aspect_ratio from/to
aurel
parents:
3424
diff
changeset
|
308 && s->streams[i]->sample_aspect_ratio.den>0){ |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
309 int vprp= ff_start_tag(pb, "vprp"); |
3759
27537074f2a9
convert every muxer/demuxer to write/read sample_aspect_ratio from/to
aurel
parents:
3424
diff
changeset
|
310 AVRational dar = av_mul_q(s->streams[i]->sample_aspect_ratio, |
3100 | 311 (AVRational){stream->width, stream->height}); |
312 int num, den; | |
313 av_reduce(&num, &den, dar.num, dar.den, 0xFFFF); | |
314 | |
315 put_le32(pb, 0); //video format = unknown | |
316 put_le32(pb, 0); //video standard= unknown | |
317 put_le32(pb, lrintf(1.0/av_q2d(stream->time_base))); | |
318 put_le32(pb, stream->width ); | |
319 put_le32(pb, stream->height); | |
3177 | 320 put_le16(pb, den); |
3100 | 321 put_le16(pb, num); |
322 put_le32(pb, stream->width ); | |
323 put_le32(pb, stream->height); | |
324 put_le32(pb, 1); //progressive FIXME | |
325 | |
326 put_le32(pb, stream->height); | |
327 put_le32(pb, stream->width ); | |
328 put_le32(pb, stream->height); | |
329 put_le32(pb, stream->width ); | |
330 put_le32(pb, 0); | |
331 put_le32(pb, 0); | |
332 | |
333 put_le32(pb, 0); | |
334 put_le32(pb, 0); | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
335 ff_end_tag(pb, vprp); |
3100 | 336 } |
337 | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
338 ff_end_tag(pb, list2); |
0 | 339 } |
885 | 340 |
119 | 341 if (!url_is_streamed(pb)) { |
342 /* AVI could become an OpenDML one, if it grows beyond 2Gb range */ | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
343 avi->odml_list = ff_start_tag(pb, "JUNK"); |
119 | 344 put_tag(pb, "odml"); |
345 put_tag(pb, "dmlh"); | |
346 put_le32(pb, 248); | |
347 for (i = 0; i < 248; i+= 4) | |
348 put_le32(pb, 0); | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
349 ff_end_tag(pb, avi->odml_list); |
119 | 350 } |
0 | 351 |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
352 ff_end_tag(pb, list1); |
885 | 353 |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
354 list2 = ff_start_tag(pb, "LIST"); |
1256 | 355 put_tag(pb, "INFO"); |
4149 | 356 avi_write_info_tag2(s, "INAM", "Title", NULL); |
357 avi_write_info_tag2(s, "IART", "Artist", "Author"); | |
358 avi_write_info_tag2(s, "ICOP", "Copyright", NULL); | |
359 avi_write_info_tag2(s, "ICMT", "Comment", NULL); | |
360 avi_write_info_tag2(s, "IPRD", "Album", NULL); | |
361 avi_write_info_tag2(s, "IGNR", "Genre", NULL); | |
362 avi_write_info_tag2(s, "IPRT", "Track", NULL); | |
1256 | 363 if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) |
364 avi_write_info_tag(pb, "ISFT", LIBAVFORMAT_IDENT); | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
365 ff_end_tag(pb, list2); |
1256 | 366 |
367 /* some padding for easier tag editing */ | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
368 list2 = ff_start_tag(pb, "JUNK"); |
1256 | 369 for (i = 0; i < 1016; i += 4) |
370 put_le32(pb, 0); | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
371 ff_end_tag(pb, list2); |
1256 | 372 |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
373 avi->movi_list = ff_start_tag(pb, "LIST"); |
0 | 374 put_tag(pb, "movi"); |
375 | |
376 put_flush_packet(pb); | |
377 | |
378 return 0; | |
379 } | |
380 | |
119 | 381 static int avi_write_ix(AVFormatContext *s) |
382 { | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2227
diff
changeset
|
383 ByteIOContext *pb = s->pb; |
119 | 384 AVIContext *avi = s->priv_data; |
1332 | 385 char tag[5]; |
386 char ix_tag[] = "ix00"; | |
119 | 387 int i, j; |
885 | 388 |
976 | 389 assert(!url_is_streamed(pb)); |
873
7af647503b67
Support for streaming: dont write indexes and dont signal HAS_INDEX in header. Also set filesize to max in this case.
alex
parents:
863
diff
changeset
|
390 |
119 | 391 if (avi->riff_id > AVI_MASTER_INDEX_SIZE) |
392 return -1; | |
885 | 393 |
119 | 394 for (i=0;i<s->nb_streams;i++) { |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3872
diff
changeset
|
395 int64_t ix, pos; |
885 | 396 |
887 | 397 avi_stream2fourcc(&tag[0], i, s->streams[i]->codec->codec_type); |
398 ix_tag[3] = '0' + i; | |
885 | 399 |
887 | 400 /* Writing AVI OpenDML leaf index chunk */ |
401 ix = url_ftell(pb); | |
402 put_tag(pb, &ix_tag[0]); /* ix?? */ | |
403 put_le32(pb, avi->indexes[i].entry * 8 + 24); | |
404 /* chunk size */ | |
119 | 405 put_le16(pb, 2); /* wLongsPerEntry */ |
887 | 406 put_byte(pb, 0); /* bIndexSubType (0 == frame index) */ |
407 put_byte(pb, 1); /* bIndexType (1 == AVI_INDEX_OF_CHUNKS) */ | |
408 put_le32(pb, avi->indexes[i].entry); | |
409 /* nEntriesInUse */ | |
410 put_tag(pb, &tag[0]); /* dwChunkId */ | |
411 put_le64(pb, avi->movi_list);/* qwBaseOffset */ | |
412 put_le32(pb, 0); /* dwReserved_3 (must be 0) */ | |
119 | 413 |
414 for (j=0; j<avi->indexes[i].entry; j++) { | |
415 AVIIentry* ie = avi_get_ientry(&avi->indexes[i], j); | |
887 | 416 put_le32(pb, ie->pos + 8); |
417 put_le32(pb, ((uint32_t)ie->len & ~0x80000000) | | |
418 (ie->flags & 0x10 ? 0 : 0x80000000)); | |
119 | 419 } |
887 | 420 put_flush_packet(pb); |
119 | 421 pos = url_ftell(pb); |
885 | 422 |
887 | 423 /* Updating one entry in the AVI OpenDML master index */ |
424 url_fseek(pb, avi->indexes[i].indx_start - 8, SEEK_SET); | |
425 put_tag(pb, "indx"); /* enabling this entry */ | |
426 url_fskip(pb, 8); | |
427 put_le32(pb, avi->riff_id); /* nEntriesInUse */ | |
428 url_fskip(pb, 16*avi->riff_id); | |
429 put_le64(pb, ix); /* qwOffset */ | |
430 put_le32(pb, pos - ix); /* dwSize */ | |
431 put_le32(pb, avi->indexes[i].entry); /* dwDuration */ | |
119 | 432 |
887 | 433 url_fseek(pb, pos, SEEK_SET); |
119 | 434 } |
435 return 0; | |
436 } | |
437 | |
438 static int avi_write_idx1(AVFormatContext *s) | |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
439 { |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2227
diff
changeset
|
440 ByteIOContext *pb = s->pb; |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
441 AVIContext *avi = s->priv_data; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3872
diff
changeset
|
442 int64_t idx_chunk; |
1267 | 443 int i; |
1332 | 444 char tag[5]; |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
445 |
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
446 if (!url_is_streamed(pb)) { |
887 | 447 AVIIentry* ie = 0, *tie; |
448 int entry[MAX_STREAMS]; | |
449 int empty, stream_id = -1; | |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
450 |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
451 idx_chunk = ff_start_tag(pb, "idx1"); |
887 | 452 memset(&entry[0], 0, sizeof(entry)); |
453 do { | |
454 empty = 1; | |
455 for (i=0; i<s->nb_streams; i++) { | |
456 if (avi->indexes[i].entry <= entry[i]) | |
457 continue; | |
885 | 458 |
887 | 459 tie = avi_get_ientry(&avi->indexes[i], entry[i]); |
460 if (empty || tie->pos < ie->pos) { | |
461 ie = tie; | |
462 stream_id = i; | |
463 } | |
464 empty = 0; | |
465 } | |
466 if (!empty) { | |
467 avi_stream2fourcc(&tag[0], stream_id, | |
468 s->streams[stream_id]->codec->codec_type); | |
469 put_tag(pb, &tag[0]); | |
470 put_le32(pb, ie->flags); | |
119 | 471 put_le32(pb, ie->pos); |
472 put_le32(pb, ie->len); | |
887 | 473 entry[stream_id]++; |
474 } | |
475 } while (!empty); | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
476 ff_end_tag(pb, idx_chunk); |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
477 |
1267 | 478 avi_write_counters(s, avi->riff_id); |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
479 } |
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
480 return 0; |
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
481 } |
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
482 |
468 | 483 static int avi_write_packet(AVFormatContext *s, AVPacket *pkt) |
0 | 484 { |
485 AVIContext *avi = s->priv_data; | |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2227
diff
changeset
|
486 ByteIOContext *pb = s->pb; |
0 | 487 unsigned char tag[5]; |
468 | 488 unsigned int flags=0; |
489 const int stream_index= pkt->stream_index; | |
820
feca73904e67
changing AVCodecContext codec -> *codec in AVStream so additions to AVCodecContext dont randomize AVStream and break binary compatibility
michael
parents:
796
diff
changeset
|
490 AVCodecContext *enc= s->streams[stream_index]->codec; |
468 | 491 int size= pkt->size; |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
492 |
1443
404048ea11bc
Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents:
1415
diff
changeset
|
493 // av_log(s, AV_LOG_DEBUG, "%"PRId64" %d %d\n", pkt->dts, avi->packet_count[stream_index], stream_index); |
724 | 494 while(enc->block_align==0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avi->packet_count[stream_index]){ |
479 | 495 AVPacket empty_packet; |
496 | |
497 av_init_packet(&empty_packet); | |
498 empty_packet.size= 0; | |
499 empty_packet.data= NULL; | |
500 empty_packet.stream_index= stream_index; | |
501 avi_write_packet(s, &empty_packet); | |
1443
404048ea11bc
Replace most of the %lld and %llx by their (cleaner) PRI*64 counterparts.
diego
parents:
1415
diff
changeset
|
502 // av_log(s, AV_LOG_DEBUG, "dup %"PRId64" %d\n", pkt->dts, avi->packet_count[stream_index]); |
479 | 503 } |
504 avi->packet_count[stream_index]++; | |
505 | |
873
7af647503b67
Support for streaming: dont write indexes and dont signal HAS_INDEX in header. Also set filesize to max in this case.
alex
parents:
863
diff
changeset
|
506 // Make sure to put an OpenDML chunk when the file size exceeds the limits |
885 | 507 if (!url_is_streamed(pb) && |
887 | 508 (url_ftell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE)) { |
885 | 509 |
119 | 510 avi_write_ix(s); |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
511 ff_end_tag(pb, avi->movi_list); |
885 | 512 |
887 | 513 if (avi->riff_id == 1) |
514 avi_write_idx1(s); | |
119 | 515 |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
516 ff_end_tag(pb, avi->riff_start); |
887 | 517 avi->movi_list = avi_start_new_riff(avi, pb, "AVIX", "movi"); |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
518 } |
885 | 519 |
119 | 520 avi_stream2fourcc(&tag[0], stream_index, enc->codec_type); |
468 | 521 if(pkt->flags&PKT_FLAG_KEY) |
522 flags = 0x10; | |
119 | 523 if (enc->codec_type == CODEC_TYPE_AUDIO) { |
0 | 524 avi->audio_strm_length[stream_index] += size; |
468 | 525 } |
0 | 526 |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2227
diff
changeset
|
527 if (!url_is_streamed(s->pb)) { |
119 | 528 AVIIndex* idx = &avi->indexes[stream_index]; |
887 | 529 int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE; |
530 int id = idx->entry % AVI_INDEX_CLUSTER_SIZE; | |
119 | 531 if (idx->ents_allocated <= idx->entry) { |
887 | 532 idx->cluster = av_realloc(idx->cluster, (cl+1)*sizeof(void*)); |
533 if (!idx->cluster) | |
534 return -1; | |
119 | 535 idx->cluster[cl] = av_malloc(AVI_INDEX_CLUSTER_SIZE*sizeof(AVIIentry)); |
887 | 536 if (!idx->cluster[cl]) |
537 return -1; | |
538 idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE; | |
539 } | |
885 | 540 |
887 | 541 idx->cluster[cl][id].flags = flags; |
119 | 542 idx->cluster[cl][id].pos = url_ftell(pb) - avi->movi_list; |
543 idx->cluster[cl][id].len = size; | |
887 | 544 idx->entry++; |
0 | 545 } |
885 | 546 |
0 | 547 put_buffer(pb, tag, 4); |
548 put_le32(pb, size); | |
468 | 549 put_buffer(pb, pkt->data, size); |
0 | 550 if (size & 1) |
551 put_byte(pb, 0); | |
552 | |
553 put_flush_packet(pb); | |
554 return 0; | |
555 } | |
556 | |
557 static int avi_write_trailer(AVFormatContext *s) | |
558 { | |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
559 AVIContext *avi = s->priv_data; |
2771
d52c718e83f9
Use dynamically allocated ByteIOContext in AVFormatContext
andoma
parents:
2227
diff
changeset
|
560 ByteIOContext *pb = s->pb; |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
561 int res = 0; |
119 | 562 int i, j, n, nb_frames; |
3973
549a09cf23fe
Remove offset_t typedef and use int64_t directly instead.
diego
parents:
3872
diff
changeset
|
563 int64_t file_size; |
0 | 564 |
1676 | 565 if (!url_is_streamed(pb)){ |
566 if (avi->riff_id == 1) { | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
567 ff_end_tag(pb, avi->movi_list); |
1676 | 568 res = avi_write_idx1(s); |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
569 ff_end_tag(pb, avi->riff_start); |
1676 | 570 } else { |
571 avi_write_ix(s); | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
572 ff_end_tag(pb, avi->movi_list); |
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
573 ff_end_tag(pb, avi->riff_start); |
119 | 574 |
1676 | 575 file_size = url_ftell(pb); |
576 url_fseek(pb, avi->odml_list - 8, SEEK_SET); | |
577 put_tag(pb, "LIST"); /* Making this AVI OpenDML one */ | |
578 url_fskip(pb, 16); | |
0 | 579 |
1676 | 580 for (n=nb_frames=0;n<s->nb_streams;n++) { |
581 AVCodecContext *stream = s->streams[n]->codec; | |
582 if (stream->codec_type == CODEC_TYPE_VIDEO) { | |
583 if (nb_frames < avi->packet_count[n]) | |
584 nb_frames = avi->packet_count[n]; | |
585 } else { | |
586 if (stream->codec_id == CODEC_ID_MP2 || stream->codec_id == CODEC_ID_MP3) { | |
587 nb_frames += avi->packet_count[n]; | |
588 } | |
0 | 589 } |
590 } | |
1676 | 591 put_le32(pb, nb_frames); |
592 url_fseek(pb, file_size, SEEK_SET); | |
593 | |
594 avi_write_counters(s, avi->riff_id); | |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
595 } |
873
7af647503b67
Support for streaming: dont write indexes and dont signal HAS_INDEX in header. Also set filesize to max in this case.
alex
parents:
863
diff
changeset
|
596 } |
119 | 597 put_flush_packet(pb); |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
598 |
119 | 599 for (i=0; i<MAX_STREAMS; i++) { |
887 | 600 for (j=0; j<avi->indexes[i].ents_allocated/AVI_INDEX_CLUSTER_SIZE; j++) |
119 | 601 av_free(avi->indexes[i].cluster[j]); |
4816 | 602 av_freep(&avi->indexes[i].cluster); |
887 | 603 avi->indexes[i].ents_allocated = avi->indexes[i].entry = 0; |
119 | 604 } |
885 | 605 |
102
c48108fe538e
AVI > 2Gb (OpenDML) generation patch by (Roman Shaposhnick <rvs at sun dot com>)
michaelni
parents:
94
diff
changeset
|
606 return res; |
0 | 607 } |
608 | |
1169 | 609 AVOutputFormat avi_muxer = { |
0 | 610 "avi", |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3177
diff
changeset
|
611 NULL_IF_CONFIG_SMALL("AVI format"), |
0 | 612 "video/x-msvideo", |
613 "avi", | |
614 sizeof(AVIContext), | |
615 CODEC_ID_MP2, | |
106
4da5d55b3690
we really shouldnt use M$* as default codec -> use MPEG4 as default
michaelni
parents:
105
diff
changeset
|
616 CODEC_ID_MPEG4, |
0 | 617 avi_write_header, |
618 avi_write_packet, | |
619 avi_write_trailer, | |
5058
33a244b7ca65
Add ff_ prefixes to exported symbols in libavformat/riff.h.
diego
parents:
5044
diff
changeset
|
620 .codec_tag= (const AVCodecTag* const []){ff_codec_bmp_tags, ff_codec_wav_tags, 0}, |
4567
963e3b76c7a6
Add AVFMT_VARIABLE_FPS to specify which muxers do not need duplicated frames.
michael
parents:
4477
diff
changeset
|
621 .flags= AVFMT_VARIABLE_FPS, |
0 | 622 }; |