]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/au.c
avfilter/vf_identity: fix typo
[ffmpeg] / libavformat / au.c
index b419c9ed955d2193c8b9799574e92ba67c1eb020..ff8f841cce56292b163219ae2b53c36ce9a318b6 100644 (file)
@@ -35,8 +35,6 @@
 
 /* if we don't know the size in advance */
 #define AU_UNKNOWN_SIZE ((uint32_t)(~0))
-/* the specification requires an annotation field of at least eight bytes */
-#define AU_DEFAULT_HEADER_SIZE (24+8)
 
 static const AVCodecTag codec_au_tags[] = {
     { AV_CODEC_ID_PCM_MULAW,  1 },
@@ -55,6 +53,8 @@ static const AVCodecTag codec_au_tags[] = {
     { AV_CODEC_ID_NONE,       0 },
 };
 
+static const AVCodecTag *const au_codec_tags[] = { codec_au_tags, NULL };
+
 #if CONFIG_AU_DEMUXER
 
 static int au_probe(const AVProbeData *p)
@@ -86,6 +86,11 @@ static int au_read_annotation(AVFormatContext *s, int size)
     av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
 
     while (size-- > 0) {
+        if (avio_feof(pb)) {
+            av_bprint_finalize(&bprint, NULL);
+            av_freep(&key);
+            return AVERROR_EOF;
+        }
         c = avio_r8(pb);
         switch(state) {
         case PARSE_KEY:
@@ -107,11 +112,11 @@ static int au_read_annotation(AVFormatContext *s, int size)
                     av_log(s, AV_LOG_ERROR, "Memory error while parsing AU metadata.\n");
                 } else {
                     av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
-                    for (i = 0; i < FF_ARRAY_ELEMS(keys) && key != NULL; i++) {
+                    for (i = 0; i < FF_ARRAY_ELEMS(keys); i++) {
                         if (av_strcasecmp(keys[i], key) == 0) {
                             av_dict_set(&(s->metadata), keys[i], value, AV_DICT_DONT_STRDUP_VAL);
-                            av_freep(&key);
                             value = NULL;
+                            break;
                         }
                     }
                 }
@@ -221,14 +226,14 @@ static int au_read_header(AVFormatContext *s)
     return 0;
 }
 
-AVInputFormat ff_au_demuxer = {
+const AVInputFormat ff_au_demuxer = {
     .name        = "au",
     .long_name   = NULL_IF_CONFIG_SMALL("Sun AU"),
     .read_probe  = au_probe,
     .read_header = au_read_header,
     .read_packet = ff_pcm_read_packet,
     .read_seek   = ff_pcm_read_seek,
-    .codec_tag   = (const AVCodecTag* const []) { codec_au_tags, 0 },
+    .codec_tag   = au_codec_tags,
 };
 
 #endif /* CONFIG_AU_DEMUXER */
@@ -241,7 +246,7 @@ typedef struct AUContext {
 
 #include "rawenc.h"
 
-static int au_get_annotations(AVFormatContext *s, char **buffer)
+static int au_get_annotations(AVFormatContext *s, AVBPrint *annotations)
 {
     static const char keys[][7] = {
         "Title",
@@ -253,23 +258,19 @@ static int au_get_annotations(AVFormatContext *s, char **buffer)
     int cnt = 0;
     AVDictionary *m = s->metadata;
     AVDictionaryEntry *t = NULL;
-    AVBPrint bprint;
-
-    av_bprint_init(&bprint, 64, AV_BPRINT_SIZE_UNLIMITED);
 
     for (int i = 0; i < FF_ARRAY_ELEMS(keys); i++) {
         t = av_dict_get(m, keys[i], NULL, 0);
         if (t != NULL) {
             if (cnt++)
-                av_bprint_chars(&bprint, '\n', 1);
-            av_bprint_append_data(&bprint, keys[i], strlen(keys[i]));
-            av_bprint_chars(&bprint, '=', 1);
-            av_bprint_append_data(&bprint, t->value, strlen(t->value));
+                av_bprint_chars(annotations, '\n', 1);
+            av_bprintf(annotations, "%s=%s", keys[i], t->value);
         }
     }
-    /* pad with 0's */
-    av_bprint_append_data(&bprint, "\0\0\0\0\0\0\0\0", 8);
-    return av_bprint_finalize(&bprint, buffer);
+    /* The specification requires the annotation field to be zero-terminated
+     * and its length to be a multiple of eight, so pad with 0's */
+    av_bprint_chars(annotations, '\0', 8);
+    return av_bprint_is_complete(annotations) ? 0 : AVERROR(ENOMEM);
 }
 
 static int au_write_header(AVFormatContext *s)
@@ -278,9 +279,7 @@ static int au_write_header(AVFormatContext *s)
     AUContext *au = s->priv_data;
     AVIOContext *pb = s->pb;
     AVCodecParameters *par = s->streams[0]->codecpar;
-    char *annotations = NULL;
-
-    au->header_size = AU_DEFAULT_HEADER_SIZE;
+    AVBPrint annotations;
 
     if (s->nb_streams != 1) {
         av_log(s, AV_LOG_ERROR, "only one stream is supported\n");
@@ -293,30 +292,24 @@ static int au_write_header(AVFormatContext *s)
         return AVERROR(EINVAL);
     }
 
-    if (av_dict_count(s->metadata) > 0) {
-        ret = au_get_annotations(s, &annotations);
-        if (ret < 0)
-            return ret;
-        if (annotations != NULL) {
-            au->header_size = (24 + strlen(annotations) + 8) & ~7;
-            if (au->header_size < AU_DEFAULT_HEADER_SIZE)
-                au->header_size = AU_DEFAULT_HEADER_SIZE;
-        }
-    }
+    av_bprint_init(&annotations, 0, INT_MAX - 24);
+    ret = au_get_annotations(s, &annotations);
+    if (ret < 0)
+        goto fail;
+    au->header_size = 24 + annotations.len & ~7;
+
     ffio_wfourcc(pb, ".snd");                   /* magic number */
     avio_wb32(pb, au->header_size);             /* header size */
     avio_wb32(pb, AU_UNKNOWN_SIZE);             /* data size */
     avio_wb32(pb, par->codec_tag);              /* codec ID */
     avio_wb32(pb, par->sample_rate);
     avio_wb32(pb, par->channels);
-    if (annotations != NULL) {
-        avio_write(pb, annotations, au->header_size - 24);
-        av_freep(&annotations);
-    } else {
-        avio_wb64(pb, 0); /* annotation field */
-    }
+    avio_write(pb, annotations.str, annotations.len & ~7);
 
-    return 0;
+fail:
+    av_bprint_finalize(&annotations, NULL);
+
+    return ret;
 }
 
 static int au_write_trailer(AVFormatContext *s)
@@ -335,7 +328,7 @@ static int au_write_trailer(AVFormatContext *s)
     return 0;
 }
 
-AVOutputFormat ff_au_muxer = {
+const AVOutputFormat ff_au_muxer = {
     .name          = "au",
     .long_name     = NULL_IF_CONFIG_SMALL("Sun AU"),
     .mime_type     = "audio/basic",
@@ -346,7 +339,7 @@ AVOutputFormat ff_au_muxer = {
     .write_header  = au_write_header,
     .write_packet  = ff_raw_write_packet,
     .write_trailer = au_write_trailer,
-    .codec_tag     = (const AVCodecTag* const []) { codec_au_tags, 0 },
+    .codec_tag     = au_codec_tags,
     .flags         = AVFMT_NOTIMESTAMPS,
 };