apetag.c
Go to the documentation of this file.
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 "libavutil/dict.h"
25 #include "avformat.h"
26 #include "apetag.h"
27 #include "internal.h"
28 
29 #define APE_TAG_FLAG_CONTAINS_HEADER (1 << 31)
30 #define APE_TAG_FLAG_IS_HEADER (1 << 29)
31 #define APE_TAG_FLAG_IS_BINARY (1 << 1)
32 
34 {
35  AVIOContext *pb = s->pb;
36  uint8_t key[1024], *value;
37  uint32_t size, flags;
38  int i, c;
39 
40  size = avio_rl32(pb); /* field size */
41  flags = avio_rl32(pb); /* field flags */
42  for (i = 0; i < sizeof(key) - 1; i++) {
43  c = avio_r8(pb);
44  if (c < 0x20 || c > 0x7E)
45  break;
46  else
47  key[i] = c;
48  }
49  key[i] = 0;
50  if (c != 0) {
51  av_log(s, AV_LOG_WARNING, "Invalid APE tag key '%s'.\n", key);
52  return -1;
53  }
54  if (size >= UINT_MAX)
55  return -1;
56  if (flags & APE_TAG_FLAG_IS_BINARY) {
57  uint8_t filename[1024];
58  enum AVCodecID id;
60  if (!st)
61  return AVERROR(ENOMEM);
62 
63  size -= avio_get_str(pb, size, filename, sizeof(filename));
64  if (size <= 0) {
65  av_log(s, AV_LOG_WARNING, "Skipping binary tag '%s'.\n", key);
66  return 0;
67  }
68 
69  av_dict_set(&st->metadata, key, filename, 0);
70 
71  if ((id = ff_guess_image2_codec(filename)) != AV_CODEC_ID_NONE) {
72  AVPacket pkt;
73  int ret;
74 
75  ret = av_get_packet(s->pb, &pkt, size);
76  if (ret < 0) {
77  av_log(s, AV_LOG_ERROR, "Error reading cover art.\n");
78  return ret;
79  }
80 
83  st->codec->codec_id = id;
84 
85  st->attached_pic = pkt;
88  } else {
90  if (!st->codec->extradata)
91  return AVERROR(ENOMEM);
92  if (avio_read(pb, st->codec->extradata, size) != size) {
93  av_freep(&st->codec->extradata);
94  return AVERROR(EIO);
95  }
96  st->codec->extradata_size = size;
98  }
99  } else {
100  value = av_malloc(size+1);
101  if (!value)
102  return AVERROR(ENOMEM);
103  c = avio_read(pb, value, size);
104  if (c < 0) {
105  av_free(value);
106  return c;
107  }
108  value[c] = 0;
109  av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL);
110  }
111  return 0;
112 }
113 
115 {
116  AVIOContext *pb = s->pb;
117  int file_size = avio_size(pb);
118  uint32_t val, fields, tag_bytes;
119  uint8_t buf[8];
120  int64_t tag_start;
121  int i;
122 
123  if (file_size < APE_TAG_FOOTER_BYTES)
124  return 0;
125 
126  avio_seek(pb, file_size - APE_TAG_FOOTER_BYTES, SEEK_SET);
127 
128  avio_read(pb, buf, 8); /* APETAGEX */
129  if (strncmp(buf, APE_TAG_PREAMBLE, 8)) {
130  return 0;
131  }
132 
133  val = avio_rl32(pb); /* APE tag version */
134  if (val > APE_TAG_VERSION) {
135  av_log(s, AV_LOG_ERROR, "Unsupported tag version. (>=%d)\n", APE_TAG_VERSION);
136  return 0;
137  }
138 
139  tag_bytes = avio_rl32(pb); /* tag size */
140  if (tag_bytes - APE_TAG_FOOTER_BYTES > (1024 * 1024 * 16)) {
141  av_log(s, AV_LOG_ERROR, "Tag size is way too big\n");
142  return 0;
143  }
144 
145  if (tag_bytes > file_size - APE_TAG_FOOTER_BYTES) {
146  av_log(s, AV_LOG_ERROR, "Invalid tag size %u.\n", tag_bytes);
147  return 0;
148  }
149  tag_start = file_size - tag_bytes - APE_TAG_FOOTER_BYTES;
150 
151  fields = avio_rl32(pb); /* number of fields */
152  if (fields > 65536) {
153  av_log(s, AV_LOG_ERROR, "Too many tag fields (%d)\n", fields);
154  return 0;
155  }
156 
157  val = avio_rl32(pb); /* flags */
158  if (val & APE_TAG_FLAG_IS_HEADER) {
159  av_log(s, AV_LOG_ERROR, "APE Tag is a header\n");
160  return 0;
161  }
162 
163  avio_seek(pb, file_size - tag_bytes, SEEK_SET);
164 
165  for (i=0; i<fields; i++)
166  if (ape_tag_read_field(s) < 0) break;
167 
168  return tag_start;
169 }
const char * s
Definition: avisynth_c.h:668
Bytestream IO Context.
Definition: avio.h:68
int64_t avio_size(AVIOContext *s)
Get the filesize.
Definition: aviobuf.c:261
enum AVCodecID id
Definition: mxfenc.c:89
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
int index
stream index in AVFormatContext
Definition: avformat.h:644
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:199
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
Format I/O context.
Definition: avformat.h:944
Public dictionary API.
uint8_t
static AVPacket pkt
Definition: demuxing.c:56
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
int av_get_packet(AVIOContext *s, AVPacket *pkt, int size)
Allocate and read the payload of a packet and initialize its fields with default values.
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:478
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
AVCodecID
Identify the syntax and semantics of the bitstream.
AVDictionary * metadata
Definition: avformat.h:1092
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
unsigned int avio_rl32(AVIOContext *s)
Definition: aviobuf.c:579
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
int64_t ff_ape_parse_tag(AVFormatContext *s)
Read and parse an APE tag.
Definition: apetag.c:114
#define APE_TAG_PREAMBLE
Definition: apetag.h:28
int size
int flags
A combination of AV_PKT_FLAG values.
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:469
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
#define FF_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
#define AV_DICT_DONT_STRDUP_VAL
Take ownership of a value that&#39;s been allocated with av_malloc() and chilren.
Definition: dict.h:72
ret
Definition: avfilter.c:821
#define APE_TAG_VERSION
Definition: apetag.h:29
#define APE_TAG_FLAG_IS_BINARY
Definition: apetag.c:31
AVDictionary * metadata
Definition: avformat.h:711
Opaque data information usually sparse.
Definition: avutil.h:147
#define APE_TAG_FOOTER_BYTES
Definition: apetag.h:30
#define AV_DISPOSITION_ATTACHED_PIC
The stream is stored in the file as an attached picture/"cover art" (e.g.
Definition: avformat.h:627
Stream structure.
Definition: avformat.h:643
NULL
Definition: eval.c:55
enum AVMediaType codec_type
enum AVCodecID codec_id
AVIOContext * pb
I/O context.
Definition: avformat.h:977
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
void * buf
Definition: avisynth_c.h:594
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:62
double value
Definition: eval.c:82
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
synthesis window for stochastic i
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
static int flags
Definition: cpu.c:23
#define APE_TAG_FLAG_IS_HEADER
Definition: apetag.c:30
Main libavformat public API header.
static double c[64]
int disposition
AV_DISPOSITION_* bit field.
Definition: avformat.h:700
enum AVCodecID ff_guess_image2_codec(const char *filename)
Definition: img2.c:99
static int ape_tag_read_field(AVFormatContext *s)
Definition: apetag.c:33
int avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen)
Read a string from pb into buf.
Definition: aviobuf.c:633
This structure stores compressed data.
AVPacket attached_pic
For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet will contain the attached pictu...
Definition: avformat.h:725