Originally committed as revision 16424 to svn://svn.ffmpeg.org/ffmpeg/trunk
Michael Niedermayer authored on 2009/01/05 03:48:37... | ... |
@@ -400,6 +400,51 @@ enum SampleFormat { |
400 | 400 |
*/ |
401 | 401 |
#define FF_MIN_BUFFER_SIZE 16384 |
402 | 402 |
|
403 |
+ |
|
404 |
+/* |
|
405 |
+ * public Metadata API. |
|
406 |
+ * Important concepts, to keep in mind |
|
407 |
+ * 1. keys are unique, there are never 2 tags with equal keys, this is also |
|
408 |
+ * meant semantically that is a demuxer should not knowingly produce |
|
409 |
+ * several keys that are litterally different but semantically identical, |
|
410 |
+ * like key=Author5, key=Author6. |
|
411 |
+ * All authors have to be placed in the same tag for the case of Authors. |
|
412 |
+ * 2. Metadata is flat, there are no subtags, if you for whatever obscene |
|
413 |
+ * reason want to store the email address of the child of producer alice |
|
414 |
+ * and actor bob, that could have key=alice_and_bobs_childs_email_address. |
|
415 |
+ * 3. A tag whichs value is translated has the ISO 639 3-letter language code |
|
416 |
+ * with a '-' between appended. So for example Author-ger=Michael, Author-eng=Mike |
|
417 |
+ * the original/default language is in the unqualified "Author" |
|
418 |
+ * A demuxer should set a default if it sets any translated tag. |
|
419 |
+ */ |
|
420 |
+ |
|
421 |
+#define AV_METADATA_IGNORE_CASE 1 |
|
422 |
+#define AV_METADATA_IGNORE_SUFFIX 2 |
|
423 |
+ |
|
424 |
+typedef struct { |
|
425 |
+ char *key; |
|
426 |
+ char *value; |
|
427 |
+}AVMetaDataTag; |
|
428 |
+ |
|
429 |
+struct AVMetaData; |
|
430 |
+ |
|
431 |
+/** |
|
432 |
+ * gets a metadata element with matching key. |
|
433 |
+ * @param prev set to the previous matching element to find the next. |
|
434 |
+ * @param flags allows case as well as suffix insensitive comparissions. |
|
435 |
+ * @return found tag or NULL, changing key or value leads to undefined behavior. |
|
436 |
+ */ |
|
437 |
+AVMetaDataTag * |
|
438 |
+av_metadata_get(struct AVMetaData *m, const char *key, const AVMetaDataTag *prev, int flags); |
|
439 |
+ |
|
440 |
+/** |
|
441 |
+ * sets the given tag in m, overwriting an existing tag. |
|
442 |
+ * @param tag tag to add to m, key and value will be av_strduped. |
|
443 |
+ * @return >= 0 if success otherwise error code that is <0. |
|
444 |
+ */ |
|
445 |
+int av_metadata_set(struct AVMetaData **m, AVMetaDataTag tag); |
|
446 |
+ |
|
447 |
+ |
|
403 | 448 |
/** |
404 | 449 |
* motion estimation type. |
405 | 450 |
*/ |
406 | 451 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,75 @@ |
0 |
+/* |
|
1 |
+ * copyright (c) 2009 Michael Niedermayer |
|
2 |
+ * |
|
3 |
+ * This file is part of FFmpeg. |
|
4 |
+ * |
|
5 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
6 |
+ * modify it under the terms of the GNU Lesser General Public |
|
7 |
+ * License as published by the Free Software Foundation; either |
|
8 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
9 |
+ * |
|
10 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
11 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 |
+ * Lesser General Public License for more details. |
|
14 |
+ * |
|
15 |
+ * You should have received a copy of the GNU Lesser General Public |
|
16 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
17 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
18 |
+ */ |
|
19 |
+ |
|
20 |
+#include "metadata.h" |
|
21 |
+ |
|
22 |
+AVMetaDataTag * |
|
23 |
+av_metadata_get(struct AVMetaData *m, const char *key, const AVMetaDataTag *prev, int flags) |
|
24 |
+{ |
|
25 |
+ unsigned int i, j; |
|
26 |
+ |
|
27 |
+ if(!m) |
|
28 |
+ return NULL; |
|
29 |
+ |
|
30 |
+ if(prev) i= prev - m->elems + 1; |
|
31 |
+ else i= 0; |
|
32 |
+ |
|
33 |
+ for(; i<m->count; i++){ |
|
34 |
+ const char *s= m->elems[i].key; |
|
35 |
+ if(flags & AV_METADATA_IGNORE_CASE) for(j=0; toupper(s[j]) == toupper(key[j]) && key[j]; j++); |
|
36 |
+ else for(j=0; s[j] == key[j] && key[j]; j++); |
|
37 |
+ if(key[j]) |
|
38 |
+ continue; |
|
39 |
+ if(s[j] && !(flags & AV_METADATA_IGNORE_SUFFIX)) |
|
40 |
+ continue; |
|
41 |
+ return &m->elems[i]; |
|
42 |
+ } |
|
43 |
+ return NULL; |
|
44 |
+} |
|
45 |
+ |
|
46 |
+int av_metadata_set(struct AVMetaData **pm, AVMetaDataTag elem) |
|
47 |
+{ |
|
48 |
+ struct AVMetaData *m= *pm; |
|
49 |
+ AVMetaDataTag *tag= av_metadata_get(m, elem.key, NULL, 0); |
|
50 |
+ |
|
51 |
+ if(!m) |
|
52 |
+ m=*pm= av_mallocz(sizeof(*m)); |
|
53 |
+ |
|
54 |
+ if(tag){ |
|
55 |
+ av_free(tag->value); |
|
56 |
+ av_free(tag->key); |
|
57 |
+ *tag= m->elems[--m->count]; |
|
58 |
+ }else{ |
|
59 |
+ AVMetaDataTag *tmp= av_realloc(m->elems, (m->count+1) * sizeof(*m->elems)); |
|
60 |
+ if(tmp){ |
|
61 |
+ m->elems= tmp; |
|
62 |
+ }else |
|
63 |
+ return AVERROR(ENOMEM); |
|
64 |
+ } |
|
65 |
+ if(elem.value){ |
|
66 |
+ elem.key = av_strdup(elem.key ); |
|
67 |
+ elem.value= av_strdup(elem.value); |
|
68 |
+ m->elems[m->count++]= elem; |
|
69 |
+ } |
|
70 |
+ if(!m->count) |
|
71 |
+ av_freep(pm); |
|
72 |
+ |
|
73 |
+ return 0; |
|
74 |
+} |
0 | 75 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,38 @@ |
0 |
+/* |
|
1 |
+ * copyright (c) 2009 Michael Niedermayer |
|
2 |
+ * |
|
3 |
+ * This file is part of FFmpeg. |
|
4 |
+ * |
|
5 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
6 |
+ * modify it under the terms of the GNU Lesser General Public |
|
7 |
+ * License as published by the Free Software Foundation; either |
|
8 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
9 |
+ * |
|
10 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
11 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 |
+ * Lesser General Public License for more details. |
|
14 |
+ * |
|
15 |
+ * You should have received a copy of the GNU Lesser General Public |
|
16 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
17 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
18 |
+ */ |
|
19 |
+ |
|
20 |
+#ifndef AVCODEC_METADATA_H |
|
21 |
+#define AVCODEC_METADATA_H |
|
22 |
+ |
|
23 |
+/** |
|
24 |
+ * @file metadata.h |
|
25 |
+ * internal metadata API header |
|
26 |
+ * see avcodec.h or the public API! |
|
27 |
+ */ |
|
28 |
+ |
|
29 |
+ |
|
30 |
+#include "avcodec.h" |
|
31 |
+ |
|
32 |
+struct AVMetaData{ |
|
33 |
+ int count; |
|
34 |
+ AVMetaDataTag *elems; |
|
35 |
+}; |
|
36 |
+ |
|
37 |
+#endif /* AVCODEC_METADATA_H */ |
... | ... |
@@ -216,13 +216,17 @@ static void clean_index(AVFormatContext *s){ |
216 | 216 |
} |
217 | 217 |
} |
218 | 218 |
|
219 |
-static int avi_read_tag(ByteIOContext *pb, char *buf, int maxlen, unsigned int size) |
|
219 |
+static int avi_read_tag(AVFormatContext *s, const char *key, unsigned int size) |
|
220 | 220 |
{ |
221 |
+ ByteIOContext *pb = s->pb; |
|
222 |
+ uint8_t value[1024]; |
|
223 |
+ |
|
221 | 224 |
int64_t i = url_ftell(pb); |
222 | 225 |
size += (size & 1); |
223 |
- get_strz(pb, buf, maxlen); |
|
226 |
+ get_strz(pb, value, sizeof(value)); |
|
224 | 227 |
url_fseek(pb, i+size, SEEK_SET); |
225 |
- return 0; |
|
228 |
+ |
|
229 |
+ return av_metadata_set(&s->meta_data, (const AVMetaDataTag){key, value}); |
|
226 | 230 |
} |
227 | 231 |
|
228 | 232 |
static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) |
... | ... |
@@ -235,7 +239,6 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) |
235 | 235 |
int i; |
236 | 236 |
AVStream *st; |
237 | 237 |
AVIStream *ast = NULL; |
238 |
- char str_track[4]; |
|
239 | 238 |
int avih_width=0, avih_height=0; |
240 | 239 |
int amv_file_format=0; |
241 | 240 |
|
... | ... |
@@ -561,26 +564,25 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) |
561 | 561 |
url_fseek(pb, size, SEEK_CUR); |
562 | 562 |
break; |
563 | 563 |
case MKTAG('I', 'N', 'A', 'M'): |
564 |
- avi_read_tag(pb, s->title, sizeof(s->title), size); |
|
564 |
+ avi_read_tag(s, "Title", size); |
|
565 | 565 |
break; |
566 | 566 |
case MKTAG('I', 'A', 'R', 'T'): |
567 |
- avi_read_tag(pb, s->author, sizeof(s->author), size); |
|
567 |
+ avi_read_tag(s, "Artist", size); |
|
568 | 568 |
break; |
569 | 569 |
case MKTAG('I', 'C', 'O', 'P'): |
570 |
- avi_read_tag(pb, s->copyright, sizeof(s->copyright), size); |
|
570 |
+ avi_read_tag(s, "Copyright", size); |
|
571 | 571 |
break; |
572 | 572 |
case MKTAG('I', 'C', 'M', 'T'): |
573 |
- avi_read_tag(pb, s->comment, sizeof(s->comment), size); |
|
573 |
+ avi_read_tag(s, "Comment", size); |
|
574 | 574 |
break; |
575 | 575 |
case MKTAG('I', 'G', 'N', 'R'): |
576 |
- avi_read_tag(pb, s->genre, sizeof(s->genre), size); |
|
576 |
+ avi_read_tag(s, "Genre", size); |
|
577 | 577 |
break; |
578 | 578 |
case MKTAG('I', 'P', 'R', 'D'): |
579 |
- avi_read_tag(pb, s->album, sizeof(s->album), size); |
|
579 |
+ avi_read_tag(s, "Album", size); |
|
580 | 580 |
break; |
581 | 581 |
case MKTAG('I', 'P', 'R', 'T'): |
582 |
- avi_read_tag(pb, str_track, sizeof(str_track), size); |
|
583 |
- sscanf(str_track, "%d", &s->track); |
|
582 |
+ avi_read_tag(s, "Track", size); |
|
584 | 583 |
break; |
585 | 584 |
default: |
586 | 585 |
if(size > 1000000){ |
... | ... |
@@ -103,6 +103,15 @@ static void avi_write_info_tag(ByteIOContext *pb, const char *tag, const char *s |
103 | 103 |
} |
104 | 104 |
} |
105 | 105 |
|
106 |
+static void avi_write_info_tag2(AVFormatContext *s, const char *fourcc, const char *key1, const char *key2) |
|
107 |
+{ |
|
108 |
+ AVMetaDataTag *tag= av_metadata_get(s->meta_data, key1, NULL, AV_METADATA_IGNORE_CASE); |
|
109 |
+ if(!tag && key2) |
|
110 |
+ tag= av_metadata_get(s->meta_data, key2, NULL, AV_METADATA_IGNORE_CASE); |
|
111 |
+ if(tag) |
|
112 |
+ avi_write_info_tag(s->pb, fourcc, tag->value); |
|
113 |
+} |
|
114 |
+ |
|
106 | 115 |
static int avi_write_counters(AVFormatContext* s, int riff_id) |
107 | 116 |
{ |
108 | 117 |
ByteIOContext *pb = s->pb; |
... | ... |
@@ -332,17 +341,13 @@ static int avi_write_header(AVFormatContext *s) |
332 | 332 |
|
333 | 333 |
list2 = start_tag(pb, "LIST"); |
334 | 334 |
put_tag(pb, "INFO"); |
335 |
- avi_write_info_tag(pb, "INAM", s->title); |
|
336 |
- avi_write_info_tag(pb, "IART", s->author); |
|
337 |
- avi_write_info_tag(pb, "ICOP", s->copyright); |
|
338 |
- avi_write_info_tag(pb, "ICMT", s->comment); |
|
339 |
- avi_write_info_tag(pb, "IPRD", s->album); |
|
340 |
- avi_write_info_tag(pb, "IGNR", s->genre); |
|
341 |
- if (s->track) { |
|
342 |
- char str_track[4]; |
|
343 |
- snprintf(str_track, 4, "%d", s->track); |
|
344 |
- avi_write_info_tag(pb, "IPRT", str_track); |
|
345 |
- } |
|
335 |
+ avi_write_info_tag2(s, "INAM", "Title", NULL); |
|
336 |
+ avi_write_info_tag2(s, "IART", "Artist", "Author"); |
|
337 |
+ avi_write_info_tag2(s, "ICOP", "Copyright", NULL); |
|
338 |
+ avi_write_info_tag2(s, "ICMT", "Comment", NULL); |
|
339 |
+ avi_write_info_tag2(s, "IPRD", "Album", NULL); |
|
340 |
+ avi_write_info_tag2(s, "IGNR", "Genre", NULL); |
|
341 |
+ avi_write_info_tag2(s, "IPRT", "Track", NULL); |
|
346 | 342 |
if(!(s->streams[0]->codec->flags & CODEC_FLAG_BITEXACT)) |
347 | 343 |
avi_write_info_tag(pb, "ISFT", LIBAVFORMAT_IDENT); |
348 | 344 |
end_tag(pb, list2); |
... | ... |
@@ -21,6 +21,7 @@ |
21 | 21 |
#include "avformat.h" |
22 | 22 |
#include "internal.h" |
23 | 23 |
#include "libavcodec/opt.h" |
24 |
+#include "libavcodec/metadata.h" |
|
24 | 25 |
#include "libavutil/avstring.h" |
25 | 26 |
#include "riff.h" |
26 | 27 |
#include <sys/time.h> |
... | ... |
@@ -2305,6 +2306,14 @@ void av_close_input_stream(AVFormatContext *s) |
2305 | 2305 |
av_free(s->chapters[s->nb_chapters]); |
2306 | 2306 |
} |
2307 | 2307 |
av_freep(&s->chapters); |
2308 |
+ if(s->meta_data){ |
|
2309 |
+ while(s->meta_data->count--){ |
|
2310 |
+ av_freep(&s->meta_data->elems[s->meta_data->count].key); |
|
2311 |
+ av_freep(&s->meta_data->elems[s->meta_data->count].value); |
|
2312 |
+ } |
|
2313 |
+ av_freep(&s->meta_data->elems); |
|
2314 |
+ } |
|
2315 |
+ av_freep(&s->meta_data); |
|
2308 | 2316 |
av_free(s); |
2309 | 2317 |
} |
2310 | 2318 |
|