oggparsevorbis.c 11.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/**
      Copyright (C) 2005  Michael Ahlberg, Måns Rullgård

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

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

      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
      NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
      HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
      WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      DEALINGS IN THE SOFTWARE.
**/

#include <stdlib.h>
26 27
#include "libavutil/avstring.h"
#include "libavutil/bswap.h"
28
#include "libavutil/dict.h"
29
#include "libavcodec/get_bits.h"
30
#include "libavcodec/bytestream.h"
31
#include "libavcodec/vorbis_parser.h"
32
#include "avformat.h"
33
#include "internal.h"
34
#include "oggdec.h"
35
#include "vorbiscomment.h"
36

37 38 39 40 41 42 43 44 45 46 47 48
static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val)
{
    int i, cnum, h, m, s, ms, keylen = strlen(key);
    AVChapter *chapter = NULL;

    if (keylen < 9 || sscanf(key, "CHAPTER%02d", &cnum) != 1)
        return 0;

    if (keylen == 9) {
        if (sscanf(val, "%02d:%02d:%02d.%03d", &h, &m, &s, &ms) < 4)
            return 0;

49
        avpriv_new_chapter(as, cnum, (AVRational){1,1000},
50 51 52 53 54 55 56 57 58 59 60 61
                       ms + 1000*(s + 60*(m + 60*h)),
                       AV_NOPTS_VALUE, NULL);
        av_free(val);
    } else if (!strcmp(key+9, "NAME")) {
        for(i = 0; i < as->nb_chapters; i++)
            if (as->chapters[i]->id == cnum) {
                chapter = as->chapters[i];
                break;
            }
        if (!chapter)
            return 0;

62 63
        av_dict_set(&chapter->metadata, "title", val,
                         AV_DICT_DONT_STRDUP_VAL);
64 65 66 67 68 69 70
    } else
        return 0;

    av_free(key);
    return 1;
}

71
int
72
ff_vorbis_comment(AVFormatContext * as, AVDictionary **m, const uint8_t *buf, int size)
73
{
Baptiste Coudurier's avatar
Baptiste Coudurier committed
74 75
    const uint8_t *p = buf;
    const uint8_t *end = buf + size;
76 77
    unsigned n, j;
    int s;
78

79
    if (size < 8) /* must have vendor_length and user_comment_list_length */
80 81
        return -1;

82
    s = bytestream_get_le32(&p);
83

84
    if (end - p - 4 < s || s < 0)
85 86 87 88
        return -1;

    p += s;

89
    n = bytestream_get_le32(&p);
90

91
    while (end - p >= 4 && n > 0) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
92
        const char *t, *v;
93 94
        int tl, vl;

95
        s = bytestream_get_le32(&p);
96

97
        if (end - p < s || s < 0)
98 99 100 101 102 103
            break;

        t = p;
        p += s;
        n--;

Måns Rullgård's avatar
Måns Rullgård committed
104
        v = memchr(t, '=', s);
105 106 107 108 109 110 111
        if (!v)
            continue;

        tl = v - t;
        vl = s - tl - 1;
        v++;

Måns Rullgård's avatar
Måns Rullgård committed
112
        if (tl && vl) {
113 114 115 116 117 118 119 120 121 122
            char *tt, *ct;

            tt = av_malloc(tl + 1);
            ct = av_malloc(vl + 1);
            if (!tt || !ct) {
                av_freep(&tt);
                av_freep(&ct);
                av_log(as, AV_LOG_WARNING, "out-of-memory error. skipping VorbisComment tag.\n");
                continue;
            }
123 124

            for (j = 0; j < tl; j++)
Måns Rullgård's avatar
Måns Rullgård committed
125
                tt[j] = toupper(t[j]);
126 127
            tt[tl] = 0;

Måns Rullgård's avatar
Måns Rullgård committed
128
            memcpy(ct, v, vl);
129 130
            ct[vl] = 0;

131
            if (!ogm_chapter(as, tt, ct))
132 133 134
                av_dict_set(m, tt, ct,
                                   AV_DICT_DONT_STRDUP_KEY |
                                   AV_DICT_DONT_STRDUP_VAL);
135 136 137
        }
    }

138
    if (p != end)
139
        av_log(as, AV_LOG_INFO, "%ti bytes of comment header remain\n", end-p);
140
    if (n > 0)
Måns Rullgård's avatar
Måns Rullgård committed
141 142
        av_log(as, AV_LOG_INFO,
               "truncated comment header, %i comments not found\n", n);
143

144
    ff_metadata_conv(m, NULL, ff_vorbiscomment_metadata_conv);
145

146 147 148 149 150 151 152 153
    return 0;
}


/** Parse the vorbis header
 * Vorbis Identification header from Vorbis_I_spec.html#vorbis-spec-codec
 * [vorbis_version] = read 32 bits as unsigned integer | Not used
 * [audio_channels] = read 8 bit integer as unsigned | Used
154
 * [audio_sample_rate] = read 32 bits as unsigned integer | Used
155 156 157 158 159 160 161 162
 * [bitrate_maximum] = read 32 bits as signed integer | Not used yet
 * [bitrate_nominal] = read 32 bits as signed integer | Not used yet
 * [bitrate_minimum] = read 32 bits as signed integer | Used as bitrate
 * [blocksize_0] = read 4 bits as unsigned integer | Not Used
 * [blocksize_1] = read 4 bits as unsigned integer | Not Used
 * [framing_flag] = read one bit | Not Used
 *    */

163
struct oggvorbis_private {
164 165
    unsigned int len[3];
    unsigned char *packet[3];
166 167 168
    VorbisParseContext vp;
    int64_t final_pts;
    int final_duration;
169
};
170 171 172


static unsigned int
173
fixup_vorbis_headers(AVFormatContext * as, struct oggvorbis_private *priv,
Måns Rullgård's avatar
Måns Rullgård committed
174
                     uint8_t **buf)
175 176 177 178 179 180 181 182 183 184 185
{
    int i,offset, len;
    unsigned char *ptr;

    len = priv->len[0] + priv->len[1] + priv->len[2];
    ptr = *buf = av_mallocz(len + len/255 + 64);

    ptr[0] = 2;
    offset = 1;
    offset += av_xiphlacing(&ptr[offset], priv->len[0]);
    offset += av_xiphlacing(&ptr[offset], priv->len[1]);
Måns Rullgård's avatar
Måns Rullgård committed
186
    for (i = 0; i < 3; i++) {
187 188
        memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
        offset += priv->len[i];
189
        av_freep(&priv->packet[i]);
190
    }
191
    *buf = av_realloc(*buf, offset + FF_INPUT_BUFFER_PADDING_SIZE);
192 193 194 195
    return offset;
}


196 197 198
static int
vorbis_header (AVFormatContext * s, int idx)
{
199 200
    struct ogg *ogg = s->priv_data;
    struct ogg_stream *os = ogg->streams + idx;
201
    AVStream *st = s->streams[idx];
202
    struct oggvorbis_private *priv;
203
    int pkt_type = os->buf[os->pstart];
204

205
    if (!(pkt_type & 1))
206
        return os->private ? 0 : -1;
207

208
    if (!os->private) {
209
        os->private = av_mallocz(sizeof(struct oggvorbis_private));
Måns Rullgård's avatar
Måns Rullgård committed
210
        if (!os->private)
211
            return -1;
212
    }
213

214
    if (os->psize < 1 || pkt_type > 5)
215 216
        return -1;

217
    priv = os->private;
218 219 220 221 222 223

    if (priv->packet[pkt_type>>1])
        return -1;
    if (pkt_type > 1 && !priv->packet[0] || pkt_type > 3 && !priv->packet[1])
        return -1;

224 225
    priv->len[pkt_type >> 1] = os->psize;
    priv->packet[pkt_type >> 1] = av_mallocz(os->psize);
226 227
    if (!priv->packet[pkt_type >> 1])
        return AVERROR(ENOMEM);
228
    memcpy(priv->packet[pkt_type >> 1], os->buf + os->pstart, os->psize);
229
    if (os->buf[os->pstart] == 1) {
Baptiste Coudurier's avatar
Baptiste Coudurier committed
230
        const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
231
        unsigned blocksize, bs0, bs1;
232
        int srate;
233 234 235 236

        if (os->psize != 30)
            return -1;

237 238 239
        if (bytestream_get_le32(&p) != 0) /* vorbis_version */
            return -1;

240
        st->codec->channels = bytestream_get_byte(&p);
241
        srate = bytestream_get_le32(&p);
242 243
        p += 4; // skip maximum bitrate
        st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
244 245 246 247 248 249 250 251 252 253 254 255 256
        p += 4; // skip minimum bitrate

        blocksize = bytestream_get_byte(&p);
        bs0 = blocksize & 15;
        bs1 = blocksize >> 4;

        if (bs0 > bs1)
            return -1;
        if (bs0 < 6 || bs1 > 13)
            return -1;

        if (bytestream_get_byte(&p) != 1) /* framing_flag */
            return -1;
257

258
        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
259
        st->codec->codec_id = AV_CODEC_ID_VORBIS;
260

261 262
        if (srate > 0) {
            st->codec->sample_rate = srate;
263
            avpriv_set_pts_info(st, 64, 1, srate);
264
        }
265
    } else if (os->buf[os->pstart] == 3) {
266 267 268 269 270 271 272 273 274 275
        if (os->psize > 8 &&
            ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, os->psize - 8) >= 0) {
            // drop all metadata we parsed and which is not required by libvorbis
            unsigned new_len = 7 + 4 + AV_RL32(priv->packet[1] + 7) + 4 + 1;
            if (new_len >= 16 && new_len < os->psize) {
                AV_WL32(priv->packet[1] + new_len - 5, 0);
                priv->packet[1][new_len - 1] = 1;
                priv->len[1] = new_len;
            }
        }
276
    } else {
277
        int ret;
278 279
        st->codec->extradata_size =
            fixup_vorbis_headers(s, priv, &st->codec->extradata);
280 281 282 283 284
        if ((ret = avpriv_vorbis_parse_extradata(st->codec, &priv->vp))) {
            av_freep(&st->codec->extradata);
            st->codec->extradata_size = 0;
            return ret;
        }
285 286
    }

287
    return 1;
288 289
}

290 291 292 293 294 295 296 297 298 299 300
static int vorbis_packet(AVFormatContext *s, int idx)
{
    struct ogg *ogg = s->priv_data;
    struct ogg_stream *os = ogg->streams + idx;
    struct oggvorbis_private *priv = os->private;
    int duration;

    /* first packet handling
       here we parse the duration of each packet in the first page and compare
       the total duration to the page granule to find the encoder delay and
       set the first timestamp */
301
    if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
302
        int seg, d;
303 304 305 306 307
        uint8_t *last_pkt = os->buf + os->pstart;
        uint8_t *next_pkt = last_pkt;

        avpriv_vorbis_parse_reset(&priv->vp);
        duration = 0;
308 309 310 311 312 313 314 315 316
        seg = os->segp;
        d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1);
        if (d < 0) {
            os->pflags |= AV_PKT_FLAG_CORRUPT;
            return 0;
        }
        duration += d;
        last_pkt = next_pkt =  next_pkt + os->psize;
        for (; seg < os->nsegs; seg++) {
317 318 319 320 321 322 323 324 325 326 327
            if (os->segments[seg] < 255) {
                int d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1);
                if (d < 0) {
                    duration = os->granule;
                    break;
                }
                duration += d;
                last_pkt = next_pkt + os->segments[seg];
            }
            next_pkt += os->segments[seg];
        }
328
        os->lastpts = os->lastdts   = os->granule - duration;
329
        if(s->streams[idx]->start_time == AV_NOPTS_VALUE) {
330
            s->streams[idx]->start_time = FFMAX(os->lastpts, 0);
331 332 333
            if (s->streams[idx]->duration)
                s->streams[idx]->duration -= s->streams[idx]->start_time;
        }
334 335 336 337 338 339 340
        priv->final_pts             = AV_NOPTS_VALUE;
        avpriv_vorbis_parse_reset(&priv->vp);
    }

    /* parse packet duration */
    if (os->psize > 0) {
        duration = avpriv_vorbis_parse_frame(&priv->vp, os->buf + os->pstart, 1);
341
        if (duration < 0) {
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
            os->pflags |= AV_PKT_FLAG_CORRUPT;
            return 0;
        }
        os->pduration = duration;
    }

    /* final packet handling
       here we save the pts of the first packet in the final page, sum up all
       packet durations in the final page except for the last one, and compare
       to the page granule to find the duration of the final packet */
    if (os->flags & OGG_FLAG_EOS) {
        if (os->lastpts != AV_NOPTS_VALUE) {
            priv->final_pts = os->lastpts;
            priv->final_duration = 0;
        }
        if (os->segp == os->nsegs)
            os->pduration = os->granule - priv->final_pts - priv->final_duration;
        priv->final_duration += os->pduration;
    }

    return 0;
}

365
const struct ogg_codec ff_vorbis_codec = {
366 367
    .magic = "\001vorbis",
    .magicsize = 7,
368 369
    .header = vorbis_header,
    .packet = vorbis_packet,
370
    .nb_header = 3,
371
};