oggparseogm.c 5.2 KB
Newer Older
mru's avatar
mru committed
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 28
#include "libavutil/intreadwrite.h"
#include "libavcodec/bitstream.h"
#include "libavcodec/bytestream.h"
mru's avatar
mru committed
29
#include "avformat.h"
diego's avatar
diego committed
30
#include "oggdec.h"
31
#include "riff.h"
mru's avatar
mru committed
32 33 34 35

static int
ogm_header(AVFormatContext *s, int idx)
{
mru's avatar
mru committed
36 37
    struct ogg *ogg = s->priv_data;
    struct ogg_stream *os = ogg->streams + idx;
mru's avatar
mru committed
38
    AVStream *st = s->streams[idx];
bcoudurier's avatar
const  
bcoudurier committed
39
    const uint8_t *p = os->buf + os->pstart;
mru's avatar
mru committed
40 41 42 43 44 45 46 47 48 49 50 51
    uint64_t time_unit;
    uint64_t spu;
    uint32_t default_len;

    if(!(*p & 1))
        return 0;
    if(*p != 1)
        return 1;

    p++;

    if(*p == 'v'){
mru's avatar
mru committed
52
        int tag;
mru's avatar
mru committed
53 54
        st->codec->codec_type = CODEC_TYPE_VIDEO;
        p += 8;
mru's avatar
mru committed
55
        tag = bytestream_get_le32(&p);
56
        st->codec->codec_id = codec_get_id(codec_bmp_tags, tag);
mru's avatar
mru committed
57
        st->codec->codec_tag = tag;
reimar's avatar
reimar committed
58 59 60 61
    } else if (*p == 't') {
        st->codec->codec_type = CODEC_TYPE_SUBTITLE;
        st->codec->codec_id = CODEC_ID_TEXT;
        p += 12;
mru's avatar
mru committed
62
    } else {
mru's avatar
mru committed
63
        uint8_t acid[5];
mru's avatar
mru committed
64 65 66
        int cid;
        st->codec->codec_type = CODEC_TYPE_AUDIO;
        p += 8;
mru's avatar
mru committed
67 68 69
        bytestream_get_buffer(&p, acid, 4);
        acid[4] = 0;
        cid = strtol(acid, NULL, 16);
70
        st->codec->codec_id = codec_get_id(codec_wav_tags, cid);
jbr's avatar
jbr committed
71
        st->need_parsing = AVSTREAM_PARSE_FULL;
mru's avatar
mru committed
72 73 74 75
    }

    p += 4;                     /* useless size field */

mru's avatar
mru committed
76 77 78
    time_unit   = bytestream_get_le64(&p);
    spu         = bytestream_get_le64(&p);
    default_len = bytestream_get_le32(&p);
mru's avatar
mru committed
79 80 81 82

    p += 8;                     /* buffersize + bits_per_sample */

    if(st->codec->codec_type == CODEC_TYPE_VIDEO){
mru's avatar
mru committed
83 84
        st->codec->width = bytestream_get_le32(&p);
        st->codec->height = bytestream_get_le32(&p);
mru's avatar
mru committed
85 86 87 88
        st->codec->time_base.den = spu * 10000000;
        st->codec->time_base.num = time_unit;
        st->time_base = st->codec->time_base;
    } else {
mru's avatar
mru committed
89
        st->codec->channels = bytestream_get_le16(&p);
mru's avatar
mru committed
90
        p += 2;                 /* block_align */
mru's avatar
mru committed
91
        st->codec->bit_rate = bytestream_get_le32(&p) * 8;
mru's avatar
mru committed
92
        st->codec->sample_rate = spu * 10000000 / time_unit;
mru's avatar
mru committed
93 94
        st->time_base.num = 1;
        st->time_base.den = st->codec->sample_rate;
mru's avatar
mru committed
95 96 97 98 99 100 101 102
    }

    return 1;
}

static int
ogm_dshow_header(AVFormatContext *s, int idx)
{
mru's avatar
mru committed
103 104
    struct ogg *ogg = s->priv_data;
    struct ogg_stream *os = ogg->streams + idx;
mru's avatar
mru committed
105 106 107 108 109 110 111 112 113
    AVStream *st = s->streams[idx];
    uint8_t *p = os->buf + os->pstart;
    uint32_t t;

    if(!(*p & 1))
        return 0;
    if(*p != 1)
        return 1;

mru's avatar
mru committed
114
    t = AV_RL32(p + 96);
mru's avatar
mru committed
115 116 117

    if(t == 0x05589f80){
        st->codec->codec_type = CODEC_TYPE_VIDEO;
118
        st->codec->codec_id = codec_get_id(codec_bmp_tags, AV_RL32(p + 68));
mru's avatar
mru committed
119
        st->codec->time_base.den = 10000000;
mru's avatar
mru committed
120 121 122
        st->codec->time_base.num = AV_RL64(p + 164);
        st->codec->width = AV_RL32(p + 176);
        st->codec->height = AV_RL32(p + 180);
mru's avatar
mru committed
123 124
    } else if(t == 0x05589f81){
        st->codec->codec_type = CODEC_TYPE_AUDIO;
125
        st->codec->codec_id = codec_get_id(codec_wav_tags, AV_RL16(p + 124));
mru's avatar
mru committed
126 127 128
        st->codec->channels = AV_RL16(p + 126);
        st->codec->sample_rate = AV_RL32(p + 128);
        st->codec->bit_rate = AV_RL32(p + 132) * 8;
mru's avatar
mru committed
129 130 131 132 133 134 135 136
    }

    return 1;
}

static int
ogm_packet(AVFormatContext *s, int idx)
{
mru's avatar
mru committed
137 138
    struct ogg *ogg = s->priv_data;
    struct ogg_stream *os = ogg->streams + idx;
mru's avatar
mru committed
139 140 141
    uint8_t *p = os->buf + os->pstart;
    int lb;

142 143 144
    if(*p & 8)
        os->pflags |= PKT_FLAG_KEY;

mru's avatar
mru committed
145 146 147 148 149 150 151
    lb = ((*p & 2) << 1) | ((*p >> 6) & 3);
    os->pstart += lb + 1;
    os->psize -= lb + 1;

    return 0;
}

mru's avatar
mru committed
152
const struct ogg_codec ff_ogm_video_codec = {
mru's avatar
mru committed
153 154 155 156 157 158
    .magic = "\001video",
    .magicsize = 6,
    .header = ogm_header,
    .packet = ogm_packet
};

mru's avatar
mru committed
159
const struct ogg_codec ff_ogm_audio_codec = {
mru's avatar
mru committed
160 161 162 163 164 165
    .magic = "\001audio",
    .magicsize = 6,
    .header = ogm_header,
    .packet = ogm_packet
};

mru's avatar
mru committed
166
const struct ogg_codec ff_ogm_text_codec = {
reimar's avatar
reimar committed
167 168 169 170 171 172
    .magic = "\001text",
    .magicsize = 5,
    .header = ogm_header,
    .packet = ogm_packet
};

mru's avatar
mru committed
173
const struct ogg_codec ff_ogm_old_codec = {
mru's avatar
mru committed
174 175 176 177 178
    .magic = "\001Direct Show Samples embedded in Ogg",
    .magicsize = 35,
    .header = ogm_dshow_header,
    .packet = ogm_packet
};