oggparsevorbis.c 11.5 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"
D
Diego Biurrun 已提交
34
#include "oggdec.h"
35
#include "vorbiscomment.h"
36

D
David Conrad 已提交
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},
D
David Conrad 已提交
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);
D
David Conrad 已提交
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
{
B
const  
Baptiste Coudurier 已提交
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) {
B
const  
Baptiste Coudurier 已提交
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
Måns Rullgård 已提交
104
        v = memchr(t, '=', s);
105 106 107 108 109 110 111
        if (!v)
            continue;

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

M
Måns Rullgård 已提交
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++)
125
                tt[j] = av_toupper(t[j]);
126 127
            tt[tl] = 0;

M
Måns Rullgård 已提交
128
            memcpy(ct, v, vl);
129 130
            ct[vl] = 0;

D
David Conrad 已提交
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
Måns Rullgård 已提交
141 142
        av_log(as, AV_LOG_INFO,
               "truncated comment header, %i comments not found\n", n);
143

A
Anton Khirnov 已提交
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
 *    */

M
Måns Rullgård 已提交
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;
M
Måns Rullgård 已提交
169
};
170 171 172


static unsigned int
M
Måns Rullgård 已提交
173
fixup_vorbis_headers(AVFormatContext * as, struct oggvorbis_private *priv,
M
Måns Rullgård 已提交
174
                     uint8_t **buf)
175
{
176
    int i, offset, len, err;
177 178 179 180 181 182 183 184 185
    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
Måns Rullgård 已提交
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 192
    if ((err = av_reallocp(buf, offset + FF_INPUT_BUFFER_PADDING_SIZE)) < 0)
        return err;
193 194 195
    return offset;
}

196
static void vorbis_cleanup(AVFormatContext *s, int idx)
197 198 199 200 201 202 203 204 205
{
    struct ogg *ogg = s->priv_data;
    struct ogg_stream *os = ogg->streams + idx;
    struct oggvorbis_private *priv = os->private;
    int i;
    if (os->private)
        for (i = 0; i < 3; i++)
            av_freep(&priv->packet[i]);
}
206

207 208 209
static int
vorbis_header (AVFormatContext * s, int idx)
{
M
Måns Rullgård 已提交
210 211
    struct ogg *ogg = s->priv_data;
    struct ogg_stream *os = ogg->streams + idx;
212
    AVStream *st = s->streams[idx];
M
Måns Rullgård 已提交
213
    struct oggvorbis_private *priv;
214
    int pkt_type = os->buf[os->pstart];
215

216
    if (!os->private) {
M
Måns Rullgård 已提交
217
        os->private = av_mallocz(sizeof(struct oggvorbis_private));
M
Måns Rullgård 已提交
218
        if (!os->private)
219 220
            return 0;
    }
221

222 223 224
    if (!(pkt_type & 1))
        return 0;

225
    if (os->psize < 1 || pkt_type > 5)
226 227
        return -1;

228
    priv = os->private;
229 230 231 232 233 234

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

235 236 237
    priv->len[pkt_type >> 1] = os->psize;
    priv->packet[pkt_type >> 1] = av_mallocz(os->psize);
    memcpy(priv->packet[pkt_type >> 1], os->buf + os->pstart, os->psize);
238
    if (os->buf[os->pstart] == 1) {
B
const  
Baptiste Coudurier 已提交
239
        const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
240
        unsigned blocksize, bs0, bs1;
241
        int srate;
242 243 244 245

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

246 247 248
        if (bytestream_get_le32(&p) != 0) /* vorbis_version */
            return -1;

249
        st->codec->channels = bytestream_get_byte(&p);
250
        srate = bytestream_get_le32(&p);
251 252
        p += 4; // skip maximum bitrate
        st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
253 254 255 256 257 258 259 260 261 262 263 264 265
        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;
266

267
        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
268
        st->codec->codec_id = AV_CODEC_ID_VORBIS;
269

270 271
        if (srate > 0) {
            st->codec->sample_rate = srate;
272
            avpriv_set_pts_info(st, 64, 1, srate);
273
        }
274
    } else if (os->buf[os->pstart] == 3) {
275 276 277 278 279 280 281 282 283 284
        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;
            }
        }
285
    } else {
286 287 288 289 290 291
        int ret = fixup_vorbis_headers(s, priv, &st->codec->extradata);
        if (ret < 0) {
            st->codec->extradata_size = 0;
            return ret;
        }
        st->codec->extradata_size = ret;
292 293 294 295 296
        if ((ret = avpriv_vorbis_parse_extradata(st->codec, &priv->vp))) {
            av_freep(&st->codec->extradata);
            st->codec->extradata_size = 0;
            return ret;
        }
297 298
    }

299
    return 1;
300 301
}

302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
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 */
    if (!os->lastpts) {
        int seg;
        uint8_t *last_pkt = os->buf + os->pstart;
        uint8_t *next_pkt = last_pkt;
        int first_duration = 0;

        avpriv_vorbis_parse_reset(&priv->vp);
        duration = 0;
        for (seg = 0; seg < os->nsegs; seg++) {
            if (os->segments[seg] < 255) {
                int d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1);
                if (d < 0) {
                    duration = os->granule;
                    break;
                }
                if (!duration)
                    first_duration = d;
                duration += d;
                last_pkt = next_pkt + os->segments[seg];
            }
            next_pkt += os->segments[seg];
        }
        os->lastpts = os->lastdts   = os->granule - duration;
        s->streams[idx]->start_time = os->lastpts + first_duration;
        if (s->streams[idx]->duration)
            s->streams[idx]->duration -= s->streams[idx]->start_time;
        s->streams[idx]->cur_dts    = AV_NOPTS_VALUE;
        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);
        if (duration <= 0) {
            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;
}

M
Måns Rullgård 已提交
371
const struct ogg_codec ff_vorbis_codec = {
372 373
    .magic = "\001vorbis",
    .magicsize = 7,
374 375
    .header = vorbis_header,
    .packet = vorbis_packet,
376
    .cleanup= vorbis_cleanup,
377
    .nb_header = 3,
378
};