Statistics
| Branch: | Revision:

ffmpeg / libavformat / oggparsevorbis.c @ 66061a12

History | View | Annotate | Download (7.54 KB)

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 = CODEC_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
};