[PATCH] Prepare for detecting offset of trailing metadata in =
David Byron none
dbyron
Mon Sep 27 10:40:09 CEST 2010
=0A=
- add ff_ape_offset, call it from ff_ape_parse_tag=0A=
- validate size from APE footer against file size=0A=
- validate that APE header exists where advertised by the=0A=
APE footer=0A=
---=0A=
libavformat/apetag.c | 138 =
++++++++++++++++++++++++++++++++++++++++++-------=0A=
libavformat/apetag.h | 30 +++++++++++-=0A=
2 files changed, 147 insertions(+), 21 deletions(-)=0A=
=0A=
diff --git a/libavformat/apetag.c b/libavformat/apetag.c=0A=
index d30c132..460d510 100644=0A=
--- a/libavformat/apetag.c=0A=
+++ b/libavformat/apetag.c=0A=
@@ -65,48 +65,146 @@ static int ape_tag_read_field(AVFormatContext *s)=0A=
=0A=
void ff_ape_parse_tag(AVFormatContext *s)=0A=
{=0A=
+ int64_t ape_offset;=0A=
+ uint64_t ape_size;=0A=
+ uint32_t i, fields;=0A=
+ int ret;=0A=
+=0A=
+ ret =3D ff_ape_offset(s,-1,&ape_offset,&ape_size,&fields);=0A=
+ if (ret >=3D 0) {=0A=
+ url_fseek(s->pb, ape_offset, SEEK_SET);=0A=
+=0A=
+ for (i=3D0; i<fields; i++)=0A=
+ if (ape_tag_read_field(s) < 0) break;=0A=
+ }=0A=
+}=0A=
+=0A=
+int ff_ape_offset(AVFormatContext *s,=0A=
+ int64_t override_end_offset,=0A=
+ int64_t *ape_offset,=0A=
+ uint64_t *ape_size,=0A=
+ uint32_t *num_fields )=0A=
+{=0A=
ByteIOContext *pb =3D s->pb;=0A=
- int file_size =3D url_fsize(pb);=0A=
- uint32_t val, fields, tag_bytes;=0A=
+ int64_t file_size;=0A=
+ uint32_t flags;=0A=
+ uint32_t fields;=0A=
+ uint64_t tag_bytes; /* 32 bits from the APE footer, but=0A=
+ could be 32 bytes bigger if=0A=
+ there's a header as well so don't=0A=
+ use a 32 bit type */=0A=
+ uint32_t version;=0A=
uint8_t buf[8];=0A=
- int i;=0A=
+ int has_header;=0A=
+ int ret;=0A=
+=0A=
+ *ape_offset =3D -1;=0A=
+ *ape_size =3D 0;=0A=
+ if (num_fields)=0A=
+ *num_fields =3D 0;=0A=
+=0A=
+ if (override_end_offset =3D=3D -1) {=0A=
+ file_size =3D url_fsize(pb);=0A=
+ if (file_size < 0)=0A=
+ return file_size; /* here filesize is actually an error */=0A=
+ } else=0A=
+ file_size =3D override_end_offset;=0A=
=0A=
if (file_size < APE_TAG_FOOTER_BYTES)=0A=
- return;=0A=
+ return 0;=0A=
=0A=
- url_fseek(pb, file_size - APE_TAG_FOOTER_BYTES, SEEK_SET);=0A=
+ ret =3D url_fseek(pb, file_size - APE_TAG_FOOTER_BYTES, SEEK_SET);=0A=
+ if (ret < 0)=0A=
+ return ret;=0A=
=0A=
- get_buffer(pb, buf, 8); /* APETAGEX */=0A=
- if (strncmp(buf, "APETAGEX", 8)) {=0A=
- return;=0A=
- }=0A=
+ ret =3D get_buffer(pb, buf, 8); /* APETAGEX */=0A=
+ if (ret < 0)=0A=
+ return ret;=0A=
+=0A=
+ assert(ret =3D=3D 8);=0A=
+ if (memcmp(buf, "APETAGEX", 8))=0A=
+ return 0;=0A=
=0A=
- val =3D get_le32(pb); /* APE tag version */=0A=
- if (val > APE_TAG_VERSION) {=0A=
+ version =3D get_le32(pb); /* APE tag version */=0A=
+ if (version > APE_TAG_VERSION) {=0A=
av_log(s, AV_LOG_ERROR, "Unsupported tag version. (>=3D%d)\n", =
APE_TAG_VERSION);=0A=
- return;=0A=
+ return 0;=0A=
}=0A=
=0A=
tag_bytes =3D get_le32(pb); /* tag size */=0A=
if (tag_bytes - APE_TAG_FOOTER_BYTES > (1024 * 1024 * 16)) {=0A=
av_log(s, AV_LOG_ERROR, "Tag size is way too big\n");=0A=
- return;=0A=
+ return 0;=0A=
}=0A=
=0A=
fields =3D get_le32(pb); /* number of fields */=0A=
+ if (num_fields)=0A=
+ *num_fields =3D fields;=0A=
if (fields > 65536) {=0A=
av_log(s, AV_LOG_ERROR, "Too many tag fields (%d)\n", fields);=0A=
- return;=0A=
+ return 0;=0A=
}=0A=
=0A=
- val =3D get_le32(pb); /* flags */=0A=
- if (val & APE_TAG_FLAG_IS_HEADER) {=0A=
+ flags =3D get_le32(pb); /* flags */=0A=
+ if (flags & APE_TAG_FLAG_IS_HEADER) {=0A=
av_log(s, AV_LOG_ERROR, "APE Tag is a header\n");=0A=
- return;=0A=
+ return 0;=0A=
}=0A=
=0A=
- url_fseek(pb, file_size - tag_bytes, SEEK_SET);=0A=
+ /* We've got a legit APE tag footer but there's more to=0A=
+ do before we know how big the tag is, as well as if=0A=
+ the tag is valid */=0A=
+ has_header =3D (version =3D=3D 2000) && (flags & =
APE_TAG_FLAG_CONTAINS_HEADER);=0A=
=0A=
- for (i=3D0; i<fields; i++)=0A=
- if (ape_tag_read_field(s) < 0) break;=0A=
+ if (has_header) {=0A=
+ av_log(s, AV_LOG_VERBOSE,"%s: \"%s\": APE Tag contains =
header\n",=0A=
+ __FUNCTION__, s->filename);=0A=
+ tag_bytes +=3D 32;=0A=
+ } else {=0A=
+ av_log(s, AV_LOG_VERBOSE, "%s: \"%s\": APE Tag does not contain =
a "=0A=
+ "header\n", __FUNCTION__, s->filename);=0A=
+ }=0A=
+=0A=
+ /* It's possible that the size indicated in the tag is=0A=
+ bigger than the file. To be safe, interpret this as=0A=
+ an invalid tag and don't do anything */=0A=
+ if (tag_bytes > file_size) {=0A=
+ av_log(s, AV_LOG_WARNING, "%s: \"%s\": APE size%s is %" PRId64 =
"(0x%"=0A=
+ PRIx64 ") byte(s), but file is only %" PRId64 "(0x%" =
PRIx64=0A=
+ ") byte(s)\n", __FUNCTION__, s->filename,=0A=
+ has_header ? " (including header)" : "", tag_bytes, =
tag_bytes,=0A=
+ file_size, file_size);=0A=
+ return 0;=0A=
+ }=0A=
+=0A=
+ if (has_header) {=0A=
+ /* Read 8 bytes where the header is supposed to be=0A=
+ to make sure it says "APETAGEX" */=0A=
+ ret =3D url_fseek(pb, file_size - tag_bytes, SEEK_SET);=0A=
+ if (ret < 0)=0A=
+ return ret;=0A=
+ ret =3D get_buffer(pb, buf, 8);=0A=
+ if (ret < 0)=0A=
+ return ret;=0A=
+=0A=
+ assert(ret =3D=3D 8);=0A=
+=0A=
+ if (memcmp(buf, "APETAGEX", 8)) {=0A=
+ av_log(s, AV_LOG_WARNING, "%s: \"%s\": offset %" PRId64 =
"(0x%"=0A=
+ PRIx64 ") is not APETAGEX -- not a valid APE tag\n",=0A=
+ __FUNCTION__, s->filename, file_size - tag_bytes,=0A=
+ file_size - tag_bytes);=0A=
+ return 0;=0A=
+ }=0A=
+ }=0A=
+=0A=
+ /* Finally, the APE tag is valid */=0A=
+ *ape_size =3D tag_bytes;=0A=
+ *ape_offset =3D file_size - tag_bytes;=0A=
+=0A=
+ av_log(s, AV_LOG_VERBOSE, "%s: \"%s\": %" PRId64 " byte APE tag at "=0A=
+ "offset %" PRId64 "(0x%" PRIx64 ")\n", __FUNCTION__, =
s->filename,=0A=
+ *ape_size, *ape_offset, *ape_offset);=0A=
+=0A=
+ return 0;=0A=
}=0A=
diff --git a/libavformat/apetag.h b/libavformat/apetag.h=0A=
index 8aaef68..b7dd7aa 100644=0A=
--- a/libavformat/apetag.h=0A=
+++ b/libavformat/apetag.h=0A=
@@ -30,4 +30,32 @@=0A=
*/=0A=
void ff_ape_parse_tag(AVFormatContext *s);=0A=
=0A=
-#endif /* AVFORMAT_ID3V2_H */=0A=
+/**=0A=
+ * Determine the offset of an APE tag at the end of a file=0A=
+ *=0A=
+ * @param override_end_offset ignored if -1, otherwise=0A=
+ * consider it the offset of the end of the file=0A=
+ *=0A=
+ * @param ape_offset populated with -1 if no APE tag,=0A=
+ * otherwise the offset of the APE tag=0A=
+ *=0A=
+ * @param ape_size populated with the size of the APE tag in=0A=
+ * @p filename (or 0 if none was found)=0A=
+ *=0A=
+ * @param num_fields if not NULL, populated with the number=0A=
+ * of fields in the APE tag (0 if there is no APE tag)=0A=
+ *=0A=
+ * @retval 0 successfully determined offset of the APE tag=0A=
+ * (or that there isn't one). The stream position is=0A=
+ * undefined.=0A=
+ *=0A=
+ * @retval < 0 error looking for the offset of the APE tag.=0A=
+ * The stream position is undefined.=0A=
+ */=0A=
+int ff_ape_offset(AVFormatContext *s,=0A=
+ int64_t override_end_offset,=0A=
+ int64_t *ape_offset,=0A=
+ uint64_t *ape_size,=0A=
+ uint32_t *num_fields );=0A=
+=0A=
+#endif /* AVFORMAT_APETAG_H */=0A=
-- =0A=
1.6.0.4=0A=
=0A=
------=_NextPart_000_016F_01CB5E3E.615FC240
Content-Type: application/octet-stream;
name="0002-Prepare-for-detecting-offset-of-trailing-metadata-in.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="0002-Prepare-for-detecting-offset-of-trailing-metadata-in.patch"
More information about the ffmpeg-devel
mailing list