OLD | NEW |
1 /* | 1 /* |
2 * AVI muxer | 2 * AVI muxer |
3 * Copyright (c) 2000 Fabrice Bellard | 3 * Copyright (c) 2000 Fabrice Bellard |
4 * | 4 * |
5 * This file is part of FFmpeg. | 5 * This file is part of FFmpeg. |
6 * | 6 * |
7 * FFmpeg is free software; you can redistribute it and/or | 7 * FFmpeg is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Lesser General Public | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
10 * version 2.1 of the License, or (at your option) any later version. | 10 * version 2.1 of the License, or (at your option) any later version. |
11 * | 11 * |
12 * FFmpeg is distributed in the hope that it will be useful, | 12 * FFmpeg is distributed in the hope that it will be useful, |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 * Lesser General Public License for more details. | 15 * Lesser General Public License for more details. |
16 * | 16 * |
17 * You should have received a copy of the GNU Lesser General Public | 17 * You should have received a copy of the GNU Lesser General Public |
18 * License along with FFmpeg; if not, write to the Free Software | 18 * License along with FFmpeg; if not, write to the Free Software |
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 */ | 20 */ |
21 #include "avformat.h" | 21 #include "avformat.h" |
22 #include "avi.h" | 22 #include "avi.h" |
23 #include "riff.h" | 23 #include "riff.h" |
| 24 #include "libavutil/intreadwrite.h" |
24 | 25 |
25 /* | 26 /* |
26 * TODO: | 27 * TODO: |
27 * - fill all fields if non streamed (nb_frames for example) | 28 * - fill all fields if non streamed (nb_frames for example) |
28 */ | 29 */ |
29 | 30 |
30 typedef struct AVIIentry { | 31 typedef struct AVIIentry { |
31 unsigned int flags, pos, len; | 32 unsigned int flags, pos, len; |
32 } AVIIentry; | 33 } AVIIentry; |
33 | 34 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 if (len > 0) { | 108 if (len > 0) { |
108 len++; | 109 len++; |
109 put_tag(pb, tag); | 110 put_tag(pb, tag); |
110 put_le32(pb, len); | 111 put_le32(pb, len); |
111 put_strz(pb, str); | 112 put_strz(pb, str); |
112 if (len & 1) | 113 if (len & 1) |
113 put_byte(pb, 0); | 114 put_byte(pb, 0); |
114 } | 115 } |
115 } | 116 } |
116 | 117 |
117 static void avi_write_info_tag2(AVFormatContext *s, const char *fourcc, const ch
ar *key1, const char *key2) | |
118 { | |
119 AVMetadataTag *tag= av_metadata_get(s->metadata, key1, NULL, 0); | |
120 if(!tag && key2) | |
121 tag= av_metadata_get(s->metadata, key2, NULL, 0); | |
122 if(tag) | |
123 avi_write_info_tag(s->pb, fourcc, tag->value); | |
124 } | |
125 | |
126 static int avi_write_counters(AVFormatContext* s, int riff_id) | 118 static int avi_write_counters(AVFormatContext* s, int riff_id) |
127 { | 119 { |
128 ByteIOContext *pb = s->pb; | 120 ByteIOContext *pb = s->pb; |
129 AVIContext *avi = s->priv_data; | 121 AVIContext *avi = s->priv_data; |
130 int n, au_byterate, au_ssize, au_scale, nb_frames = 0; | 122 int n, au_byterate, au_ssize, au_scale, nb_frames = 0; |
131 int64_t file_size; | 123 int64_t file_size; |
132 AVCodecContext* stream; | 124 AVCodecContext* stream; |
133 | 125 |
134 file_size = url_ftell(pb); | 126 file_size = url_ftell(pb); |
135 for(n = 0; n < s->nb_streams; n++) { | 127 for(n = 0; n < s->nb_streams; n++) { |
(...skipping 21 matching lines...) Expand all Loading... |
157 return 0; | 149 return 0; |
158 } | 150 } |
159 | 151 |
160 static int avi_write_header(AVFormatContext *s) | 152 static int avi_write_header(AVFormatContext *s) |
161 { | 153 { |
162 AVIContext *avi = s->priv_data; | 154 AVIContext *avi = s->priv_data; |
163 ByteIOContext *pb = s->pb; | 155 ByteIOContext *pb = s->pb; |
164 int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale; | 156 int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale; |
165 AVCodecContext *stream, *video_enc; | 157 AVCodecContext *stream, *video_enc; |
166 int64_t list1, list2, strh, strf; | 158 int64_t list1, list2, strh, strf; |
| 159 AVMetadataTag *t = NULL; |
167 | 160 |
168 for(n=0;n<s->nb_streams;n++) { | 161 for(n=0;n<s->nb_streams;n++) { |
169 s->streams[n]->priv_data= av_mallocz(sizeof(AVIStream)); | 162 s->streams[n]->priv_data= av_mallocz(sizeof(AVIStream)); |
170 if(!s->streams[n]->priv_data) | 163 if(!s->streams[n]->priv_data) |
171 return AVERROR(ENOMEM); | 164 return AVERROR(ENOMEM); |
172 } | 165 } |
173 | 166 |
174 /* header list */ | 167 /* header list */ |
175 avi->riff_id = 0; | 168 avi->riff_id = 0; |
176 list1 = avi_start_new_riff(s, pb, "AVI ", "hdrl"); | 169 list1 = avi_start_new_riff(s, pb, "AVI ", "hdrl"); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 break; | 280 break; |
288 case CODEC_TYPE_AUDIO: | 281 case CODEC_TYPE_AUDIO: |
289 if (ff_put_wav_header(pb, stream) < 0) { | 282 if (ff_put_wav_header(pb, stream) < 0) { |
290 return -1; | 283 return -1; |
291 } | 284 } |
292 break; | 285 break; |
293 default: | 286 default: |
294 return -1; | 287 return -1; |
295 } | 288 } |
296 ff_end_tag(pb, strf); | 289 ff_end_tag(pb, strf); |
| 290 if ((t = av_metadata_get(s->streams[i]->metadata, "strn", NULL, 0))) { |
| 291 avi_write_info_tag(s->pb, t->key, t->value); |
| 292 t = NULL; |
| 293 } |
| 294 //FIXME a limitation of metadata conversion system |
| 295 else if ((t = av_metadata_get(s->streams[i]->metadata, "INAM", NULL, 0))
) { |
| 296 avi_write_info_tag(s->pb, "strn", t->value); |
| 297 t = NULL; |
| 298 } |
297 } | 299 } |
298 | 300 |
299 if (!url_is_streamed(pb)) { | 301 if (!url_is_streamed(pb)) { |
300 unsigned char tag[5]; | 302 unsigned char tag[5]; |
301 int j; | 303 int j; |
302 | 304 |
303 /* Starting to lay out AVI OpenDML master index. | 305 /* Starting to lay out AVI OpenDML master index. |
304 * We want to make it JUNK entry for now, since we'd | 306 * We want to make it JUNK entry for now, since we'd |
305 * like to get away without making AVI an OpenDML one | 307 * like to get away without making AVI an OpenDML one |
306 * for compatibility reasons. | 308 * for compatibility reasons. |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 put_le32(pb, 248); | 365 put_le32(pb, 248); |
364 for (i = 0; i < 248; i+= 4) | 366 for (i = 0; i < 248; i+= 4) |
365 put_le32(pb, 0); | 367 put_le32(pb, 0); |
366 ff_end_tag(pb, avi->odml_list); | 368 ff_end_tag(pb, avi->odml_list); |
367 } | 369 } |
368 | 370 |
369 ff_end_tag(pb, list1); | 371 ff_end_tag(pb, list1); |
370 | 372 |
371 list2 = ff_start_tag(pb, "LIST"); | 373 list2 = ff_start_tag(pb, "LIST"); |
372 put_tag(pb, "INFO"); | 374 put_tag(pb, "INFO"); |
373 avi_write_info_tag2(s, "INAM", "Title", NULL); | 375 for (i = 0; *ff_avi_tags[i]; i++) { |
374 avi_write_info_tag2(s, "IART", "Artist", "Author"); | 376 if ((t = av_metadata_get(s->metadata, ff_avi_tags[i], NULL, AV_METADATA_
MATCH_CASE))) |
375 avi_write_info_tag2(s, "ICOP", "Copyright", NULL); | 377 avi_write_info_tag(s->pb, t->key, t->value); |
376 avi_write_info_tag2(s, "ICMT", "Comment", NULL); | 378 } |
377 avi_write_info_tag2(s, "IPRD", "Album", NULL); | |
378 avi_write_info_tag2(s, "IGNR", "Genre", NULL); | |
379 avi_write_info_tag2(s, "IPRT", "Track", NULL); | |
380 if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) | |
381 avi_write_info_tag(pb, "ISFT", LIBAVFORMAT_IDENT); | |
382 ff_end_tag(pb, list2); | 379 ff_end_tag(pb, list2); |
383 | 380 |
384 /* some padding for easier tag editing */ | 381 /* some padding for easier tag editing */ |
385 list2 = ff_start_tag(pb, "JUNK"); | 382 list2 = ff_start_tag(pb, "JUNK"); |
386 for (i = 0; i < 1016; i += 4) | 383 for (i = 0; i < 1016; i += 4) |
387 put_le32(pb, 0); | 384 put_le32(pb, 0); |
388 ff_end_tag(pb, list2); | 385 ff_end_tag(pb, list2); |
389 | 386 |
390 avi->movi_list = ff_start_tag(pb, "LIST"); | 387 avi->movi_list = ff_start_tag(pb, "LIST"); |
391 put_tag(pb, "movi"); | 388 put_tag(pb, "movi"); |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 "video/x-msvideo", | 637 "video/x-msvideo", |
641 "avi", | 638 "avi", |
642 sizeof(AVIContext), | 639 sizeof(AVIContext), |
643 CODEC_ID_MP2, | 640 CODEC_ID_MP2, |
644 CODEC_ID_MPEG4, | 641 CODEC_ID_MPEG4, |
645 avi_write_header, | 642 avi_write_header, |
646 avi_write_packet, | 643 avi_write_packet, |
647 avi_write_trailer, | 644 avi_write_trailer, |
648 .codec_tag= (const AVCodecTag* const []){ff_codec_bmp_tags, ff_codec_wav_tag
s, 0}, | 645 .codec_tag= (const AVCodecTag* const []){ff_codec_bmp_tags, ff_codec_wav_tag
s, 0}, |
649 .flags= AVFMT_VARIABLE_FPS, | 646 .flags= AVFMT_VARIABLE_FPS, |
| 647 .metadata_conv = ff_avi_metadata_conv, |
650 }; | 648 }; |
OLD | NEW |