summaryrefslogtreecommitdiff
path: root/libavformat/apetag.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat/apetag.c')
-rw-r--r--libavformat/apetag.c92
1 files changed, 50 insertions, 42 deletions
diff --git a/libavformat/apetag.c b/libavformat/apetag.c
index 22884ef6e0..7d2f0b3222 100644
--- a/libavformat/apetag.c
+++ b/libavformat/apetag.c
@@ -3,20 +3,20 @@
* Copyright (c) 2007 Benjamin Zores <ben@geexbox.org>
* based upon libdemac from Dave Chapman.
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -29,8 +29,6 @@
#include "apetag.h"
#include "internal.h"
-#define APE_TAG_VERSION 2000
-#define APE_TAG_FOOTER_BYTES 32
#define APE_TAG_FLAG_CONTAINS_HEADER (1 << 31)
#define APE_TAG_FLAG_CONTAINS_FOOTER (1 << 30)
#define APE_TAG_FLAG_IS_HEADER (1 << 29)
@@ -92,14 +90,8 @@ static int ape_tag_read_field(AVFormatContext *s)
st->attached_pic.stream_index = st->index;
st->attached_pic.flags |= AV_PKT_FLAG_KEY;
} else {
- st->codec->extradata = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
- if (!st->codec->extradata)
+ if (ff_get_extradata(st->codec, s->pb, size) < 0)
return AVERROR(ENOMEM);
- if (avio_read(pb, st->codec->extradata, size) != size) {
- av_freep(&st->codec->extradata);
- return AVERROR(EIO);
- }
- st->codec->extradata_size = size;
st->codec->codec_type = AVMEDIA_TYPE_ATTACHMENT;
}
} else {
@@ -132,7 +124,7 @@ int64_t ff_ape_parse_tag(AVFormatContext *s)
avio_seek(pb, file_size - APE_TAG_FOOTER_BYTES, SEEK_SET);
avio_read(pb, buf, 8); /* APETAGEX */
- if (strncmp(buf, "APETAGEX", 8)) {
+ if (strncmp(buf, APE_TAG_PREAMBLE, 8)) {
return 0;
}
@@ -174,43 +166,61 @@ int64_t ff_ape_parse_tag(AVFormatContext *s)
return tag_start;
}
+static int string_is_ascii(const uint8_t *str)
+{
+ while (*str && *str >= 0x20 && *str <= 0x7e ) str++;
+ return !*str;
+}
+
int ff_ape_write_tag(AVFormatContext *s)
{
AVDictionaryEntry *e = NULL;
- int64_t start, end;
- int size, count = 0;
-
- if (!s->pb->seekable)
- return 0;
+ int size, ret, count = 0;
+ AVIOContext *dyn_bc = NULL;
+ uint8_t *dyn_buf = NULL;
- start = avio_tell(s->pb);
-
- // header
- avio_write(s->pb, "APETAGEX", 8); // id
- avio_wl32 (s->pb, APE_TAG_VERSION); // version
- avio_wl32(s->pb, 0); // reserve space for size
- avio_wl32(s->pb, 0); // reserve space for tag count
+ if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0)
+ goto end;
// flags
- avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER |
+ avio_wl32(dyn_bc, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER |
APE_TAG_FLAG_IS_HEADER);
- ffio_fill(s->pb, 0, 8); // reserved
+ ffio_fill(dyn_bc, 0, 8); // reserved
while ((e = av_dict_get(s->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) {
- int val_len = strlen(e->value);
+ int val_len;
- avio_wl32(s->pb, val_len); // value length
- avio_wl32(s->pb, 0); // item flags
- avio_put_str(s->pb, e->key); // key
- avio_write(s->pb, e->value, val_len); // value
+ if (!string_is_ascii(e->key)) {
+ av_log(s, AV_LOG_WARNING, "Non ASCII keys are not allowed\n");
+ continue;
+ }
+
+ val_len = strlen(e->value);
+ avio_wl32(dyn_bc, val_len); // value length
+ avio_wl32(dyn_bc, 0); // item flags
+ avio_put_str(dyn_bc, e->key); // key
+ avio_write(dyn_bc, e->value, val_len); // value
count++;
}
+ if (!count)
+ goto end;
+
+ size = avio_close_dyn_buf(dyn_bc, &dyn_buf);
+ if (size <= 0)
+ goto end;
+ size += 20;
+
+ // header
+ avio_write(s->pb, "APETAGEX", 8); // id
+ avio_wl32(s->pb, APE_TAG_VERSION); // version
+ avio_wl32(s->pb, size);
+ avio_wl32(s->pb, count);
- size = avio_tell(s->pb) - start;
+ avio_write(s->pb, dyn_buf, size - 20);
// footer
avio_write(s->pb, "APETAGEX", 8); // id
- avio_wl32 (s->pb, APE_TAG_VERSION); // version
+ avio_wl32(s->pb, APE_TAG_VERSION); // version
avio_wl32(s->pb, size); // size
avio_wl32(s->pb, count); // tag count
@@ -218,12 +228,10 @@ int ff_ape_write_tag(AVFormatContext *s)
avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER);
ffio_fill(s->pb, 0, 8); // reserved
- // update values in the header
- end = avio_tell(s->pb);
- avio_seek(s->pb, start + 12, SEEK_SET);
- avio_wl32(s->pb, size);
- avio_wl32(s->pb, count);
- avio_seek(s->pb, end, SEEK_SET);
+end:
+ if (dyn_bc && !dyn_buf)
+ avio_close_dyn_buf(dyn_bc, &dyn_buf);
+ av_freep(&dyn_buf);
- return 0;
+ return ret;
}