~ubuntu-branches/ubuntu/utopic/libav/utopic

« back to all changes in this revision

Viewing changes to libavformat/oggparsevorbis.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2011-03-20 12:09:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110320120931-nfhi9tiok27gxhw1
Tags: upstream-0.6.2
ImportĀ upstreamĀ versionĀ 0.6.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
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 "libavutil/avstring.h"
 
27
#include "libavutil/bswap.h"
 
28
#include "libavcodec/get_bits.h"
 
29
#include "libavcodec/bytestream.h"
 
30
#include "avformat.h"
 
31
#include "oggdec.h"
 
32
 
 
33
static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val)
 
34
{
 
35
    int i, cnum, h, m, s, ms, keylen = strlen(key);
 
36
    AVChapter *chapter = NULL;
 
37
 
 
38
    if (keylen < 9 || sscanf(key, "CHAPTER%02d", &cnum) != 1)
 
39
        return 0;
 
40
 
 
41
    if (keylen == 9) {
 
42
        if (sscanf(val, "%02d:%02d:%02d.%03d", &h, &m, &s, &ms) < 4)
 
43
            return 0;
 
44
 
 
45
        ff_new_chapter(as, cnum, (AVRational){1,1000},
 
46
                       ms + 1000*(s + 60*(m + 60*h)),
 
47
                       AV_NOPTS_VALUE, NULL);
 
48
        av_free(val);
 
49
    } else if (!strcmp(key+9, "NAME")) {
 
50
        for(i = 0; i < as->nb_chapters; i++)
 
51
            if (as->chapters[i]->id == cnum) {
 
52
                chapter = as->chapters[i];
 
53
                break;
 
54
            }
 
55
        if (!chapter)
 
56
            return 0;
 
57
 
 
58
        av_metadata_set2(&chapter->metadata, "title", val,
 
59
                         AV_METADATA_DONT_STRDUP_VAL);
 
60
    } else
 
61
        return 0;
 
62
 
 
63
    av_free(key);
 
64
    return 1;
 
65
}
 
66
 
 
67
int
 
68
ff_vorbis_comment(AVFormatContext * as, AVMetadata **m, const uint8_t *buf, int size)
 
69
{
 
70
    const uint8_t *p = buf;
 
71
    const uint8_t *end = buf + size;
 
72
    unsigned n, j;
 
73
    int s;
 
74
 
 
75
    if (size < 8) /* must have vendor_length and user_comment_list_length */
 
76
        return -1;
 
77
 
 
78
    s = bytestream_get_le32(&p);
 
79
 
 
80
    if (end - p - 4 < s || s < 0)
 
81
        return -1;
 
82
 
 
83
    p += s;
 
84
 
 
85
    n = bytestream_get_le32(&p);
 
86
 
 
87
    while (end - p >= 4 && n > 0) {
 
88
        const char *t, *v;
 
89
        int tl, vl;
 
90
 
 
91
        s = bytestream_get_le32(&p);
 
92
 
 
93
        if (end - p < s || s < 0)
 
94
            break;
 
95
 
 
96
        t = p;
 
97
        p += s;
 
98
        n--;
 
99
 
 
100
        v = memchr(t, '=', s);
 
101
        if (!v)
 
102
            continue;
 
103
 
 
104
        tl = v - t;
 
105
        vl = s - tl - 1;
 
106
        v++;
 
107
 
 
108
        if (tl && vl) {
 
109
            char *tt, *ct;
 
110
 
 
111
            tt = av_malloc(tl + 1);
 
112
            ct = av_malloc(vl + 1);
 
113
            if (!tt || !ct) {
 
114
                av_freep(&tt);
 
115
                av_freep(&ct);
 
116
                av_log(as, AV_LOG_WARNING, "out-of-memory error. skipping VorbisComment tag.\n");
 
117
                continue;
 
118
            }
 
119
 
 
120
            for (j = 0; j < tl; j++)
 
121
                tt[j] = toupper(t[j]);
 
122
            tt[tl] = 0;
 
123
 
 
124
            memcpy(ct, v, vl);
 
125
            ct[vl] = 0;
 
126
 
 
127
            if (!ogm_chapter(as, tt, ct))
 
128
                av_metadata_set2(m, tt, ct,
 
129
                                   AV_METADATA_DONT_STRDUP_KEY |
 
130
                                   AV_METADATA_DONT_STRDUP_VAL);
 
131
        }
 
132
    }
 
133
 
 
134
    if (p != end)
 
135
        av_log(as, AV_LOG_INFO, "%ti bytes of comment header remain\n", end-p);
 
136
    if (n > 0)
 
137
        av_log(as, AV_LOG_INFO,
 
138
               "truncated comment header, %i comments not found\n", n);
 
139
 
 
140
    return 0;
 
141
}
 
142
 
 
143
 
 
144
/** Parse the vorbis header
 
145
 * Vorbis Identification header from Vorbis_I_spec.html#vorbis-spec-codec
 
146
 * [vorbis_version] = read 32 bits as unsigned integer | Not used
 
147
 * [audio_channels] = read 8 bit integer as unsigned | Used
 
148
 * [audio_sample_rate] = read 32 bits as unsigned integer | Used
 
149
 * [bitrate_maximum] = read 32 bits as signed integer | Not used yet
 
150
 * [bitrate_nominal] = read 32 bits as signed integer | Not used yet
 
151
 * [bitrate_minimum] = read 32 bits as signed integer | Used as bitrate
 
152
 * [blocksize_0] = read 4 bits as unsigned integer | Not Used
 
153
 * [blocksize_1] = read 4 bits as unsigned integer | Not Used
 
154
 * [framing_flag] = read one bit | Not Used
 
155
 *    */
 
156
 
 
157
struct oggvorbis_private {
 
158
    unsigned int len[3];
 
159
    unsigned char *packet[3];
 
160
};
 
161
 
 
162
 
 
163
static unsigned int
 
164
fixup_vorbis_headers(AVFormatContext * as, struct oggvorbis_private *priv,
 
165
                     uint8_t **buf)
 
166
{
 
167
    int i,offset, len;
 
168
    unsigned char *ptr;
 
169
 
 
170
    len = priv->len[0] + priv->len[1] + priv->len[2];
 
171
    ptr = *buf = av_mallocz(len + len/255 + 64);
 
172
 
 
173
    ptr[0] = 2;
 
174
    offset = 1;
 
175
    offset += av_xiphlacing(&ptr[offset], priv->len[0]);
 
176
    offset += av_xiphlacing(&ptr[offset], priv->len[1]);
 
177
    for (i = 0; i < 3; i++) {
 
178
        memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
 
179
        offset += priv->len[i];
 
180
        av_freep(&priv->packet[i]);
 
181
    }
 
182
    *buf = av_realloc(*buf, offset + FF_INPUT_BUFFER_PADDING_SIZE);
 
183
    return offset;
 
184
}
 
185
 
 
186
 
 
187
static int
 
188
vorbis_header (AVFormatContext * s, int idx)
 
189
{
 
190
    struct ogg *ogg = s->priv_data;
 
191
    struct ogg_stream *os = ogg->streams + idx;
 
192
    AVStream *st = s->streams[idx];
 
193
    struct oggvorbis_private *priv;
 
194
    int pkt_type = os->buf[os->pstart];
 
195
 
 
196
    if (!(pkt_type & 1))
 
197
        return 0;
 
198
 
 
199
    if (!os->private) {
 
200
        os->private = av_mallocz(sizeof(struct oggvorbis_private));
 
201
        if (!os->private)
 
202
            return 0;
 
203
    }
 
204
 
 
205
    if (os->psize < 1 || pkt_type > 5)
 
206
        return -1;
 
207
 
 
208
    priv = os->private;
 
209
    priv->len[pkt_type >> 1] = os->psize;
 
210
    priv->packet[pkt_type >> 1] = av_mallocz(os->psize);
 
211
    memcpy(priv->packet[pkt_type >> 1], os->buf + os->pstart, os->psize);
 
212
    if (os->buf[os->pstart] == 1) {
 
213
        const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
 
214
        unsigned blocksize, bs0, bs1;
 
215
 
 
216
        if (os->psize != 30)
 
217
            return -1;
 
218
 
 
219
        if (bytestream_get_le32(&p) != 0) /* vorbis_version */
 
220
            return -1;
 
221
 
 
222
        st->codec->channels = bytestream_get_byte(&p);
 
223
        st->codec->sample_rate = bytestream_get_le32(&p);
 
224
        p += 4; // skip maximum bitrate
 
225
        st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
 
226
        p += 4; // skip minimum bitrate
 
227
 
 
228
        blocksize = bytestream_get_byte(&p);
 
229
        bs0 = blocksize & 15;
 
230
        bs1 = blocksize >> 4;
 
231
 
 
232
        if (bs0 > bs1)
 
233
            return -1;
 
234
        if (bs0 < 6 || bs1 > 13)
 
235
            return -1;
 
236
 
 
237
        if (bytestream_get_byte(&p) != 1) /* framing_flag */
 
238
            return -1;
 
239
 
 
240
        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
 
241
        st->codec->codec_id = CODEC_ID_VORBIS;
 
242
 
 
243
        st->time_base.num = 1;
 
244
        st->time_base.den = st->codec->sample_rate;
 
245
    } else if (os->buf[os->pstart] == 3) {
 
246
        if (os->psize > 8)
 
247
            ff_vorbis_comment (s, &st->metadata, os->buf + os->pstart + 7, os->psize - 8);
 
248
    } else {
 
249
        st->codec->extradata_size =
 
250
            fixup_vorbis_headers(s, priv, &st->codec->extradata);
 
251
    }
 
252
 
 
253
    return 1;
 
254
}
 
255
 
 
256
const struct ogg_codec ff_vorbis_codec = {
 
257
    .magic = "\001vorbis",
 
258
    .magicsize = 7,
 
259
    .header = vorbis_header
 
260
};