Patch by Anton Khirnov (gmail{wyskas}).
Originally committed as revision 21653 to svn://svn.ffmpeg.org/ffmpeg/trunk
| ... | ... |
@@ -35,8 +35,8 @@ OBJS-$(CONFIG_ASS_DEMUXER) += assdec.o |
| 35 | 35 |
OBJS-$(CONFIG_ASS_MUXER) += assenc.o |
| 36 | 36 |
OBJS-$(CONFIG_AU_DEMUXER) += au.o raw.o |
| 37 | 37 |
OBJS-$(CONFIG_AU_MUXER) += au.o |
| 38 |
-OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o riff.o |
|
| 39 |
-OBJS-$(CONFIG_AVI_MUXER) += avienc.o riff.o |
|
| 38 |
+OBJS-$(CONFIG_AVI_DEMUXER) += avidec.o riff.o avi.o |
|
| 39 |
+OBJS-$(CONFIG_AVI_MUXER) += avienc.o riff.o avi.o |
|
| 40 | 40 |
OBJS-$(CONFIG_AVISYNTH) += avisynth.o |
| 41 | 41 |
OBJS-$(CONFIG_AVM2_MUXER) += swfenc.o |
| 42 | 42 |
OBJS-$(CONFIG_AVS_DEMUXER) += avs.o vocdec.o voc.o |
| 43 | 43 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,45 @@ |
| 0 |
+/* |
|
| 1 |
+ * AVI common data |
|
| 2 |
+ * Copyright (c) 2010 Anton Khirnov |
|
| 3 |
+ * |
|
| 4 |
+ * This file is part of FFmpeg. |
|
| 5 |
+ * |
|
| 6 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
| 7 |
+ * modify it under the terms of the GNU Lesser General Public |
|
| 8 |
+ * License as published by the Free Software Foundation; either |
|
| 9 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
| 10 |
+ * |
|
| 11 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
| 12 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 13 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
| 14 |
+ * Lesser General Public License for more details. |
|
| 15 |
+ * |
|
| 16 |
+ * You should have received a copy of the GNU Lesser General Public |
|
| 17 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
| 18 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
| 19 |
+ */ |
|
| 20 |
+ |
|
| 21 |
+#include "avi.h" |
|
| 22 |
+ |
|
| 23 |
+const AVMetadataConv ff_avi_metadata_conv[] = {
|
|
| 24 |
+ { "IART", "artist" },
|
|
| 25 |
+ { "ICMT", "comment" },
|
|
| 26 |
+ { "ICOP", "copyright" },
|
|
| 27 |
+ { "ICRD", "date" },
|
|
| 28 |
+ { "IGNR", "genre" },
|
|
| 29 |
+ { "ILNG", "language" },
|
|
| 30 |
+ { "INAM", "title" },
|
|
| 31 |
+ { "IPRD", "album" },
|
|
| 32 |
+ { "IPRT", "track" },
|
|
| 33 |
+ { "ISFT", "encoder" },
|
|
| 34 |
+ { "ITCH", "encoded_by"},
|
|
| 35 |
+ { "strn", "title" },
|
|
| 36 |
+ { 0 },
|
|
| 37 |
+}; |
|
| 38 |
+ |
|
| 39 |
+const char ff_avi_tags[][5] = {
|
|
| 40 |
+ "IARL", "IART", "ICMS", "ICMT", "ICOP", "ICRD", "ICRP", "IDIM", "IDPI", |
|
| 41 |
+ "IENG", "IGNR", "IKEY", "ILGT", "ILNG", "IMED", "INAM", "IPLT", "IPRD", |
|
| 42 |
+ "IPRT", "ISBJ",/*"ISFT"*/"ISHP", "ISRC", "ISRF", "ITCH", |
|
| 43 |
+ {0}
|
|
| 44 |
+}; |
| ... | ... |
@@ -21,6 +21,8 @@ |
| 21 | 21 |
#ifndef AVFORMAT_AVI_H |
| 22 | 22 |
#define AVFORMAT_AVI_H |
| 23 | 23 |
|
| 24 |
+#include "metadata.h" |
|
| 25 |
+ |
|
| 24 | 26 |
#define AVIF_HASINDEX 0x00000010 // Index at end of file? |
| 25 | 27 |
#define AVIF_MUSTUSEINDEX 0x00000020 |
| 26 | 28 |
#define AVIF_ISINTERLEAVED 0x00000100 |
| ... | ... |
@@ -34,4 +36,11 @@ |
| 34 | 34 |
/* index flags */ |
| 35 | 35 |
#define AVIIF_INDEX 0x10 |
| 36 | 36 |
|
| 37 |
+extern const AVMetadataConv ff_avi_metadata_conv[]; |
|
| 38 |
+ |
|
| 39 |
+/** |
|
| 40 |
+ * A list of AVI info tags. |
|
| 41 |
+ */ |
|
| 42 |
+extern const char ff_avi_tags[][5]; |
|
| 43 |
+ |
|
| 37 | 44 |
#endif /* AVFORMAT_AVI_H */ |
| ... | ... |
@@ -227,10 +227,10 @@ static void clean_index(AVFormatContext *s){
|
| 227 | 227 |
} |
| 228 | 228 |
} |
| 229 | 229 |
|
| 230 |
-static int avi_read_tag(AVFormatContext *s, AVStream *st, const char *key, unsigned int size) |
|
| 230 |
+static int avi_read_tag(AVFormatContext *s, AVStream *st, uint32_t tag, uint32_t size) |
|
| 231 | 231 |
{
|
| 232 | 232 |
ByteIOContext *pb = s->pb; |
| 233 |
- char *value; |
|
| 233 |
+ char key[5] = {0}, *value;
|
|
| 234 | 234 |
|
| 235 | 235 |
size += (size & 1); |
| 236 | 236 |
|
| ... | ... |
@@ -242,6 +242,8 @@ static int avi_read_tag(AVFormatContext *s, AVStream *st, const char *key, unsig |
| 242 | 242 |
get_buffer(pb, value, size); |
| 243 | 243 |
value[size]=0; |
| 244 | 244 |
|
| 245 |
+ AV_WL32(key, tag); |
|
| 246 |
+ |
|
| 245 | 247 |
if(st) |
| 246 | 248 |
return av_metadata_set2(&st->metadata, key, value, |
| 247 | 249 |
AV_METADATA_DONT_STRDUP_VAL); |
| ... | ... |
@@ -250,6 +252,15 @@ static int avi_read_tag(AVFormatContext *s, AVStream *st, const char *key, unsig |
| 250 | 250 |
AV_METADATA_DONT_STRDUP_VAL); |
| 251 | 251 |
} |
| 252 | 252 |
|
| 253 |
+static void avi_read_info(AVFormatContext *s, uint64_t end) |
|
| 254 |
+{
|
|
| 255 |
+ while (url_ftell(s->pb) < end) {
|
|
| 256 |
+ uint32_t tag = get_le32(s->pb); |
|
| 257 |
+ uint32_t size = get_le32(s->pb); |
|
| 258 |
+ avi_read_tag(s, NULL, tag, size); |
|
| 259 |
+ } |
|
| 260 |
+} |
|
| 261 |
+ |
|
| 253 | 262 |
static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) |
| 254 | 263 |
{
|
| 255 | 264 |
AVIContext *avi = s->priv_data; |
| ... | ... |
@@ -301,6 +312,9 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) |
| 301 | 301 |
dprintf(NULL, "movi end=%"PRIx64"\n", avi->movi_end); |
| 302 | 302 |
goto end_of_header; |
| 303 | 303 |
} |
| 304 |
+ else if (tag1 == MKTAG('I', 'N', 'F', 'O'))
|
|
| 305 |
+ avi_read_info(s, list_end); |
|
| 306 |
+ |
|
| 304 | 307 |
break; |
| 305 | 308 |
case MKTAG('d', 'm', 'l', 'h'):
|
| 306 | 309 |
avi->is_odml = 1; |
| ... | ... |
@@ -606,30 +620,9 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) |
| 606 | 606 |
} |
| 607 | 607 |
url_fseek(pb, size, SEEK_CUR); |
| 608 | 608 |
break; |
| 609 |
- case MKTAG('I', 'N', 'A', 'M'):
|
|
| 610 |
- avi_read_tag(s, NULL, "Title", size); |
|
| 611 |
- break; |
|
| 612 |
- case MKTAG('I', 'A', 'R', 'T'):
|
|
| 613 |
- avi_read_tag(s, NULL, "Artist", size); |
|
| 614 |
- break; |
|
| 615 |
- case MKTAG('I', 'C', 'O', 'P'):
|
|
| 616 |
- avi_read_tag(s, NULL, "Copyright", size); |
|
| 617 |
- break; |
|
| 618 |
- case MKTAG('I', 'C', 'M', 'T'):
|
|
| 619 |
- avi_read_tag(s, NULL, "Comment", size); |
|
| 620 |
- break; |
|
| 621 |
- case MKTAG('I', 'G', 'N', 'R'):
|
|
| 622 |
- avi_read_tag(s, NULL, "Genre", size); |
|
| 623 |
- break; |
|
| 624 |
- case MKTAG('I', 'P', 'R', 'D'):
|
|
| 625 |
- avi_read_tag(s, NULL, "Album", size); |
|
| 626 |
- break; |
|
| 627 |
- case MKTAG('I', 'P', 'R', 'T'):
|
|
| 628 |
- avi_read_tag(s, NULL, "Track", size); |
|
| 629 |
- break; |
|
| 630 | 609 |
case MKTAG('s', 't', 'r', 'n'):
|
| 631 | 610 |
if(s->nb_streams){
|
| 632 |
- avi_read_tag(s, s->streams[s->nb_streams-1], "Title", size); |
|
| 611 |
+ avi_read_tag(s, s->streams[s->nb_streams-1], tag, size); |
|
| 633 | 612 |
break; |
| 634 | 613 |
} |
| 635 | 614 |
default: |
| ... | ... |
@@ -1190,4 +1183,5 @@ AVInputFormat avi_demuxer = {
|
| 1190 | 1190 |
avi_read_packet, |
| 1191 | 1191 |
avi_read_close, |
| 1192 | 1192 |
avi_read_seek, |
| 1193 |
+ .metadata_conv = ff_avi_metadata_conv, |
|
| 1193 | 1194 |
}; |
| ... | ... |
@@ -21,6 +21,7 @@ |
| 21 | 21 |
#include "avformat.h" |
| 22 | 22 |
#include "avi.h" |
| 23 | 23 |
#include "riff.h" |
| 24 |
+#include "libavutil/intreadwrite.h" |
|
| 24 | 25 |
|
| 25 | 26 |
/* |
| 26 | 27 |
* TODO: |
| ... | ... |
@@ -114,22 +115,6 @@ static void avi_write_info_tag(ByteIOContext *pb, const char *tag, const char *s |
| 114 | 114 |
} |
| 115 | 115 |
} |
| 116 | 116 |
|
| 117 |
-static void avi_write_info_tag2(AVFormatContext *s, AVStream *st, const char *fourcc, const char *key1, const char *key2) |
|
| 118 |
-{
|
|
| 119 |
- AVMetadataTag *tag; |
|
| 120 |
- if(st){
|
|
| 121 |
- tag= av_metadata_get(st->metadata, key1, NULL, 0); |
|
| 122 |
- if(!tag && key2) |
|
| 123 |
- tag= av_metadata_get(st->metadata, key2, NULL, 0); |
|
| 124 |
- }else{
|
|
| 125 |
- tag= av_metadata_get(s->metadata, key1, NULL, 0); |
|
| 126 |
- if(!tag && key2) |
|
| 127 |
- tag= av_metadata_get(s->metadata, key2, NULL, 0); |
|
| 128 |
- } |
|
| 129 |
- if(tag) |
|
| 130 |
- avi_write_info_tag(s->pb, fourcc, tag->value); |
|
| 131 |
-} |
|
| 132 |
- |
|
| 133 | 117 |
static int avi_write_counters(AVFormatContext* s, int riff_id) |
| 134 | 118 |
{
|
| 135 | 119 |
ByteIOContext *pb = s->pb; |
| ... | ... |
@@ -171,6 +156,7 @@ static int avi_write_header(AVFormatContext *s) |
| 171 | 171 |
int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale; |
| 172 | 172 |
AVCodecContext *stream, *video_enc; |
| 173 | 173 |
int64_t list1, list2, strh, strf; |
| 174 |
+ AVMetadataTag *t = NULL; |
|
| 174 | 175 |
|
| 175 | 176 |
for(n=0;n<s->nb_streams;n++) {
|
| 176 | 177 |
s->streams[n]->priv_data= av_mallocz(sizeof(AVIStream)); |
| ... | ... |
@@ -301,7 +287,15 @@ static int avi_write_header(AVFormatContext *s) |
| 301 | 301 |
return -1; |
| 302 | 302 |
} |
| 303 | 303 |
ff_end_tag(pb, strf); |
| 304 |
- avi_write_info_tag2(s, s->streams[i], "strn", "Title", "Description"); |
|
| 304 |
+ if ((t = av_metadata_get(s->streams[i]->metadata, "strn", NULL, 0))) {
|
|
| 305 |
+ avi_write_info_tag(s->pb, t->key, t->value); |
|
| 306 |
+ t = NULL; |
|
| 307 |
+ } |
|
| 308 |
+ //FIXME a limitation of metadata conversion system |
|
| 309 |
+ else if ((t = av_metadata_get(s->streams[i]->metadata, "INAM", NULL, 0))) {
|
|
| 310 |
+ avi_write_info_tag(s->pb, "strn", t->value); |
|
| 311 |
+ t = NULL; |
|
| 312 |
+ } |
|
| 305 | 313 |
} |
| 306 | 314 |
|
| 307 | 315 |
if (!url_is_streamed(pb)) {
|
| ... | ... |
@@ -378,13 +372,10 @@ static int avi_write_header(AVFormatContext *s) |
| 378 | 378 |
|
| 379 | 379 |
list2 = ff_start_tag(pb, "LIST"); |
| 380 | 380 |
put_tag(pb, "INFO"); |
| 381 |
- avi_write_info_tag2(s, NULL, "INAM", "Title", NULL); |
|
| 382 |
- avi_write_info_tag2(s, NULL, "IART", "Artist", "Author"); |
|
| 383 |
- avi_write_info_tag2(s, NULL, "ICOP", "Copyright", NULL); |
|
| 384 |
- avi_write_info_tag2(s, NULL, "ICMT", "Comment", NULL); |
|
| 385 |
- avi_write_info_tag2(s, NULL, "IPRD", "Album", NULL); |
|
| 386 |
- avi_write_info_tag2(s, NULL, "IGNR", "Genre", NULL); |
|
| 387 |
- avi_write_info_tag2(s, NULL, "IPRT", "Track", NULL); |
|
| 381 |
+ for (i = 0; *ff_avi_tags[i]; i++) {
|
|
| 382 |
+ if ((t = av_metadata_get(s->metadata, ff_avi_tags[i], NULL, AV_METADATA_MATCH_CASE))) |
|
| 383 |
+ avi_write_info_tag(s->pb, t->key, t->value); |
|
| 384 |
+ } |
|
| 388 | 385 |
if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) |
| 389 | 386 |
avi_write_info_tag(pb, "ISFT", LIBAVFORMAT_IDENT); |
| 390 | 387 |
ff_end_tag(pb, list2); |
| ... | ... |
@@ -655,4 +646,5 @@ AVOutputFormat avi_muxer = {
|
| 655 | 655 |
avi_write_trailer, |
| 656 | 656 |
.codec_tag= (const AVCodecTag* const []){ff_codec_bmp_tags, ff_codec_wav_tags, 0},
|
| 657 | 657 |
.flags= AVFMT_VARIABLE_FPS, |
| 658 |
+ .metadata_conv = ff_avi_metadata_conv, |
|
| 658 | 659 |
}; |