Statistics
| Branch: | Revision:

ffmpeg / libavformat / oggparsevorbis.c @ 7e1720de

History | View | Annotate | Download (6.61 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
#include "avformat.h"
27
#include "bitstream.h"
28 739587bf Måns Rullgård
#include "bytestream.h"
29 9146ca37 Måns Rullgård
#include "bswap.h"
30 a0ddef24 Diego Biurrun
#include "oggdec.h"
31 d3677839 Måns Rullgård
#include "avstring.h"
32 9146ca37 Måns Rullgård
33
extern int
34 4bd684bc Måns Rullgård
vorbis_comment(AVFormatContext * as, uint8_t *buf, int size)
35 9146ca37 Måns Rullgård
{
36 f5475e1b Måns Rullgård
    uint8_t *p = buf;
37 972c5f9e Måns Rullgård
    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 9146ca37 Måns Rullgård
        char *t, *v;
54
        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 ad2b531d Måns Rullgård
typedef struct {
126
    unsigned int len[3];
127
    unsigned char *packet[3];
128
} oggvorbis_private_t;
129
130
131
static unsigned int
132
fixup_vorbis_headers(AVFormatContext * as, oggvorbis_private_t *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
    *buf = av_realloc(*buf, offset);
150
    return offset;
151
}
152
153
154 9146ca37 Måns Rullgård
static int
155
vorbis_header (AVFormatContext * s, int idx)
156
{
157
    ogg_t *ogg = s->priv_data;
158
    ogg_stream_t *os = ogg->streams + idx;
159
    AVStream *st = s->streams[idx];
160 ad2b531d Måns Rullgård
    oggvorbis_private_t *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 ad2b531d Måns Rullgård
        os->private = av_mallocz(sizeof(oggvorbis_private_t));
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 736e63ed Måns Rullgård
        uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
180
        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
ogg_codec_t vorbis_codec = {
223
    .magic = "\001vorbis",
224
    .magicsize = 7,
225
    .header = vorbis_header
226
};