Statistics
| Branch: | Revision:

ffmpeg / libavformat / oggparsevorbis.c @ d7fb5a18

History | View | Annotate | Download (6.72 KB)

1 9146ca37 Måns Rullgård
/**
2
      Copyright (C) 2005  Michael Ahlberg, Måns Rullgård
3

4
      Permission is hereby granted, free of charge, to any person
5
      obtaining a copy of this software and associated documentation
6
      files (the "Software"), to deal in the Software without
7
      restriction, including without limitation the rights to use, copy,
8
      modify, merge, publish, distribute, sublicense, and/or sell copies
9
      of the Software, and to permit persons to whom the Software is
10
      furnished to do so, subject to the following conditions:
11

12
      The above copyright notice and this permission notice shall be
13
      included in all copies or substantial portions of the Software.
14

15
      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
      EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
      MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
      NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
      HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
      DEALINGS IN THE SOFTWARE.
23
**/
24
25
#include <stdlib.h>
26 245976da Diego Biurrun
#include "libavutil/avstring.h"
27
#include "libavutil/bswap.h"
28
#include "libavcodec/bitstream.h"
29
#include "libavcodec/bytestream.h"
30 9146ca37 Måns Rullgård
#include "avformat.h"
31 a0ddef24 Diego Biurrun
#include "oggdec.h"
32 9146ca37 Måns Rullgård
33 9686df2b Diego Biurrun
int
34 4bd684bc Måns Rullgård
vorbis_comment(AVFormatContext * as, uint8_t *buf, int size)
35 9146ca37 Måns Rullgård
{
36 47a0513b Baptiste Coudurier
    const uint8_t *p = buf;
37
    const uint8_t *end = buf + size;
38 f5475e1b Måns Rullgård
    unsigned s, n, j;
39 9146ca37 Måns Rullgård
40 f5475e1b Måns Rullgård
    if (size < 8) /* must have vendor_length and user_comment_list_length */
41 9146ca37 Måns Rullgård
        return -1;
42
43 0a770ae7 Måns Rullgård
    s = bytestream_get_le32(&p);
44 9146ca37 Måns Rullgård
45 972c5f9e Måns Rullgård
    if (end - p < s)
46 9146ca37 Måns Rullgård
        return -1;
47
48
    p += s;
49
50 0a770ae7 Måns Rullgård
    n = bytestream_get_le32(&p);
51 9146ca37 Måns Rullgård
52 972c5f9e Måns Rullgård
    while (p < end && n > 0) {
53 47a0513b Baptiste Coudurier
        const char *t, *v;
54 9146ca37 Måns Rullgård
        int tl, vl;
55
56 0a770ae7 Måns Rullgård
        s = bytestream_get_le32(&p);
57 9146ca37 Måns Rullgård
58 972c5f9e Måns Rullgård
        if (end - p < s)
59 9146ca37 Måns Rullgård
            break;
60
61
        t = p;
62
        p += s;
63
        n--;
64
65 4bd684bc Måns Rullgård
        v = memchr(t, '=', s);
66 9146ca37 Måns Rullgård
        if (!v)
67
            continue;
68
69
        tl = v - t;
70
        vl = s - tl - 1;
71
        v++;
72
73 4bd684bc Måns Rullgård
        if (tl && vl) {
74 9146ca37 Måns Rullgård
            char tt[tl + 1];
75
            char ct[vl + 1];
76
77
            for (j = 0; j < tl; j++)
78 4bd684bc Måns Rullgård
                tt[j] = toupper(t[j]);
79 9146ca37 Måns Rullgård
            tt[tl] = 0;
80
81 4bd684bc Måns Rullgård
            memcpy(ct, v, vl);
82 9146ca37 Måns Rullgård
            ct[vl] = 0;
83
84 115329f1 Diego Biurrun
            // took from Vorbis_I_spec
85 4bd684bc Måns Rullgård
            if (!strcmp(tt, "AUTHOR") || !strcmp(tt, "ARTIST"))
86
                av_strlcpy(as->author, ct, sizeof(as->author));
87
            else if (!strcmp(tt, "TITLE"))
88
                av_strlcpy(as->title, ct, sizeof(as->title));
89
            else if (!strcmp(tt, "COPYRIGHT"))
90
                av_strlcpy(as->copyright, ct, sizeof(as->copyright));
91
            else if (!strcmp(tt, "DESCRIPTION"))
92
                av_strlcpy(as->comment, ct, sizeof(as->comment));
93
            else if (!strcmp(tt, "GENRE"))
94
                av_strlcpy(as->genre, ct, sizeof(as->genre));
95
            else if (!strcmp(tt, "TRACKNUMBER"))
96
                as->track = atoi(ct);
97 d66c30ad Måns Rullgård
            else if (!strcmp(tt, "ALBUM"))
98
                av_strlcpy(as->album, ct, sizeof(as->album));
99 9146ca37 Måns Rullgård
        }
100
    }
101
102 972c5f9e Måns Rullgård
    if (p != end)
103
        av_log(as, AV_LOG_INFO, "%ti bytes of comment header remain\n", p-end);
104 9146ca37 Måns Rullgård
    if (n > 0)
105 4bd684bc Måns Rullgård
        av_log(as, AV_LOG_INFO,
106
               "truncated comment header, %i comments not found\n", n);
107 9146ca37 Måns Rullgård
108
    return 0;
109
}
110
111
112
/** Parse the vorbis header
113
 * Vorbis Identification header from Vorbis_I_spec.html#vorbis-spec-codec
114
 * [vorbis_version] = read 32 bits as unsigned integer | Not used
115
 * [audio_channels] = read 8 bit integer as unsigned | Used
116 115329f1 Diego Biurrun
 * [audio_sample_rate] = read 32 bits as unsigned integer | Used
117 9146ca37 Måns Rullgård
 * [bitrate_maximum] = read 32 bits as signed integer | Not used yet
118
 * [bitrate_nominal] = read 32 bits as signed integer | Not used yet
119
 * [bitrate_minimum] = read 32 bits as signed integer | Used as bitrate
120
 * [blocksize_0] = read 4 bits as unsigned integer | Not Used
121
 * [blocksize_1] = read 4 bits as unsigned integer | Not Used
122
 * [framing_flag] = read one bit | Not Used
123
 *    */
124
125 77be08ee Måns Rullgård
struct oggvorbis_private {
126 ad2b531d Måns Rullgård
    unsigned int len[3];
127
    unsigned char *packet[3];
128 77be08ee Måns Rullgård
};
129 ad2b531d Måns Rullgård
130
131
static unsigned int
132 77be08ee Måns Rullgård
fixup_vorbis_headers(AVFormatContext * as, struct oggvorbis_private *priv,
133 19f4ceca Måns Rullgård
                     uint8_t **buf)
134 ad2b531d Måns Rullgård
{
135
    int i,offset, len;
136
    unsigned char *ptr;
137
138
    len = priv->len[0] + priv->len[1] + priv->len[2];
139
    ptr = *buf = av_mallocz(len + len/255 + 64);
140
141
    ptr[0] = 2;
142
    offset = 1;
143
    offset += av_xiphlacing(&ptr[offset], priv->len[0]);
144
    offset += av_xiphlacing(&ptr[offset], priv->len[1]);
145 4bd684bc Måns Rullgård
    for (i = 0; i < 3; i++) {
146 ad2b531d Måns Rullgård
        memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
147
        offset += priv->len[i];
148
    }
149 589790c2 Siarhei Siamashka
    *buf = av_realloc(*buf, offset + FF_INPUT_BUFFER_PADDING_SIZE);
150 ad2b531d Måns Rullgård
    return offset;
151
}
152
153
154 9146ca37 Måns Rullgård
static int
155
vorbis_header (AVFormatContext * s, int idx)
156
{
157 77be08ee Måns Rullgård
    struct ogg *ogg = s->priv_data;
158
    struct ogg_stream *os = ogg->streams + idx;
159 9146ca37 Måns Rullgård
    AVStream *st = s->streams[idx];
160 77be08ee Måns Rullgård
    struct oggvorbis_private *priv;
161 9146ca37 Måns Rullgård
162
    if (os->seq > 2)
163
        return 0;
164
165 4bd684bc Måns Rullgård
    if (os->seq == 0) {
166 77be08ee Måns Rullgård
        os->private = av_mallocz(sizeof(struct oggvorbis_private));
167 4bd684bc Måns Rullgård
        if (!os->private)
168 ad2b531d Måns Rullgård
            return 0;
169
    }
170 9146ca37 Måns Rullgård
171 f5475e1b Måns Rullgård
    if (os->psize < 1)
172
        return -1;
173
174 ad2b531d Måns Rullgård
    priv = os->private;
175
    priv->len[os->seq] = os->psize;
176
    priv->packet[os->seq] = av_mallocz(os->psize);
177
    memcpy(priv->packet[os->seq], os->buf + os->pstart, os->psize);
178 9146ca37 Måns Rullgård
    if (os->buf[os->pstart] == 1) {
179 47a0513b Baptiste Coudurier
        const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
180 736e63ed Måns Rullgård
        unsigned blocksize, bs0, bs1;
181 f5475e1b Måns Rullgård
182
        if (os->psize != 30)
183
            return -1;
184
185 736e63ed Måns Rullgård
        if (bytestream_get_le32(&p) != 0) /* vorbis_version */
186
            return -1;
187
188 739587bf Måns Rullgård
        st->codec->channels = bytestream_get_byte(&p);
189
        st->codec->sample_rate = bytestream_get_le32(&p);
190
        p += 4; // skip maximum bitrate
191
        st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
192 736e63ed Måns Rullgård
        p += 4; // skip minimum bitrate
193
194
        blocksize = bytestream_get_byte(&p);
195
        bs0 = blocksize & 15;
196
        bs1 = blocksize >> 4;
197
198
        if (bs0 > bs1)
199
            return -1;
200
        if (bs0 < 6 || bs1 > 13)
201
            return -1;
202
203
        if (bytestream_get_byte(&p) != 1) /* framing_flag */
204
            return -1;
205 9146ca37 Måns Rullgård
206 01f4895c Michael Niedermayer
        st->codec->codec_type = CODEC_TYPE_AUDIO;
207
        st->codec->codec_id = CODEC_ID_VORBIS;
208 9146ca37 Måns Rullgård
209 3644cb8f Måns Rullgård
        st->time_base.num = 1;
210
        st->time_base.den = st->codec->sample_rate;
211 9146ca37 Måns Rullgård
    } else if (os->buf[os->pstart] == 3) {
212 f5475e1b Måns Rullgård
        if (os->psize > 8)
213
            vorbis_comment (s, os->buf + os->pstart + 7, os->psize - 8);
214 ad2b531d Måns Rullgård
    } else {
215 01f4895c Michael Niedermayer
        st->codec->extradata_size =
216
            fixup_vorbis_headers(s, priv, &st->codec->extradata);
217 9146ca37 Måns Rullgård
    }
218
219
    return os->seq < 3;
220
}
221
222 77be08ee Måns Rullgård
const struct ogg_codec ff_vorbis_codec = {
223 9146ca37 Måns Rullgård
    .magic = "\001vorbis",
224
    .magicsize = 7,
225
    .header = vorbis_header
226
};