• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/ffmpeg/libavformat/
1/*
2 * APE tag handling
3 * Copyright (c) 2007 Benjamin Zores <ben@geexbox.org>
4 *  based upon libdemac from Dave Chapman.
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include "libavutil/intreadwrite.h"
24#include "avformat.h"
25#include "apetag.h"
26
27#define ENABLE_DEBUG 0
28
29#define APE_TAG_VERSION               2000
30#define APE_TAG_FOOTER_BYTES          32
31#define APE_TAG_FLAG_CONTAINS_HEADER  (1 << 31)
32#define APE_TAG_FLAG_IS_HEADER        (1 << 29)
33
34static int ape_tag_read_field(AVFormatContext *s)
35{
36    ByteIOContext *pb = s->pb;
37    uint8_t key[1024], *value;
38    uint32_t size, flags;
39    int i, c;
40
41    size = get_le32(pb);  /* field size */
42    flags = get_le32(pb); /* field flags */
43    for (i = 0; i < sizeof(key) - 1; i++) {
44        c = get_byte(pb);
45        if (c < 0x20 || c > 0x7E)
46            break;
47        else
48            key[i] = c;
49    }
50    key[i] = 0;
51    if (c != 0) {
52        av_log(s, AV_LOG_WARNING, "Invalid APE tag key '%s'.\n", key);
53        return -1;
54    }
55    if (size >= UINT_MAX)
56        return -1;
57    value = av_malloc(size+1);
58    if (!value)
59        return AVERROR(ENOMEM);
60    get_buffer(pb, value, size);
61    value[size] = 0;
62    av_metadata_set2(&s->metadata, key, value, AV_METADATA_DONT_STRDUP_VAL);
63    return 0;
64}
65
66void ff_ape_parse_tag(AVFormatContext *s)
67{
68    ByteIOContext *pb = s->pb;
69    int file_size = url_fsize(pb);
70    uint32_t val, fields, tag_bytes;
71    uint8_t buf[8];
72    int i;
73
74    if (file_size < APE_TAG_FOOTER_BYTES)
75        return;
76
77    url_fseek(pb, file_size - APE_TAG_FOOTER_BYTES, SEEK_SET);
78
79    get_buffer(pb, buf, 8);    /* APETAGEX */
80    if (strncmp(buf, "APETAGEX", 8)) {
81        return;
82    }
83
84    val = get_le32(pb);        /* APE tag version */
85    if (val > APE_TAG_VERSION) {
86        av_log(s, AV_LOG_ERROR, "Unsupported tag version. (>=%d)\n", APE_TAG_VERSION);
87        return;
88    }
89
90    tag_bytes = get_le32(pb);  /* tag size */
91    if (tag_bytes - APE_TAG_FOOTER_BYTES > (1024 * 1024 * 16)) {
92        av_log(s, AV_LOG_ERROR, "Tag size is way too big\n");
93        return;
94    }
95
96    fields = get_le32(pb);     /* number of fields */
97    if (fields > 65536) {
98        av_log(s, AV_LOG_ERROR, "Too many tag fields (%d)\n", fields);
99        return;
100    }
101
102    val = get_le32(pb);        /* flags */
103    if (val & APE_TAG_FLAG_IS_HEADER) {
104        av_log(s, AV_LOG_ERROR, "APE Tag is a header\n");
105        return;
106    }
107
108    url_fseek(pb, file_size - tag_bytes, SEEK_SET);
109
110    for (i=0; i<fields; i++)
111        if (ape_tag_read_field(s) < 0) break;
112}
113