oggparseogm.c 5.67 KB
Newer Older
Måns Rullgård's avatar
Måns Rullgård 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
#include "libavutil/intreadwrite.h"
27
#include "libavcodec/get_bits.h"
28
#include "libavcodec/bytestream.h"
Måns Rullgård's avatar
Måns Rullgård committed
29
#include "avformat.h"
30
#include "oggdec.h"
31
#include "riff.h"
Måns Rullgård's avatar
Måns Rullgård committed
32 33 34 35

static int
ogm_header(AVFormatContext *s, int idx)
{
36 37
    struct ogg *ogg = s->priv_data;
    struct ogg_stream *os = ogg->streams + idx;
Måns Rullgård's avatar
Måns Rullgård committed
38
    AVStream *st = s->streams[idx];
Baptiste Coudurier's avatar
Baptiste Coudurier committed
39
    const uint8_t *p = os->buf + os->pstart;
Måns Rullgård's avatar
Måns Rullgård committed
40 41 42 43 44 45
    uint64_t time_unit;
    uint64_t spu;

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

David Conrad's avatar
David Conrad committed
46 47
    if(*p == 1) {
        p++;
Måns Rullgård's avatar
Måns Rullgård committed
48

David Conrad's avatar
David Conrad committed
49 50
        if(*p == 'v'){
            int tag;
51
            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
David Conrad's avatar
David Conrad committed
52 53 54 55 56
            p += 8;
            tag = bytestream_get_le32(&p);
            st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag);
            st->codec->codec_tag = tag;
        } else if (*p == 't') {
57
            st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
David Conrad's avatar
David Conrad committed
58 59 60 61 62
            st->codec->codec_id = CODEC_ID_TEXT;
            p += 12;
        } else {
            uint8_t acid[5];
            int cid;
63
            st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
David Conrad's avatar
David Conrad committed
64 65 66 67 68 69 70
            p += 8;
            bytestream_get_buffer(&p, acid, 4);
            acid[4] = 0;
            cid = strtol(acid, NULL, 16);
            st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, cid);
            st->need_parsing = AVSTREAM_PARSE_FULL;
        }
Måns Rullgård's avatar
Måns Rullgård committed
71

David Conrad's avatar
David Conrad committed
72
        p += 4;                     /* useless size field */
Måns Rullgård's avatar
Måns Rullgård committed
73

David Conrad's avatar
David Conrad committed
74 75
        time_unit   = bytestream_get_le64(&p);
        spu         = bytestream_get_le64(&p);
Mans Rullgard's avatar
Mans Rullgard committed
76
        p += 4;                     /* default_len */
David Conrad's avatar
David Conrad committed
77
        p += 8;                     /* buffersize + bits_per_sample */
Måns Rullgård's avatar
Måns Rullgård committed
78

79
        if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
David Conrad's avatar
David Conrad committed
80 81 82 83
            st->codec->width = bytestream_get_le32(&p);
            st->codec->height = bytestream_get_le32(&p);
            st->codec->time_base.den = spu * 10000000;
            st->codec->time_base.num = time_unit;
84
            av_set_pts_info(st, 64, st->codec->time_base.num, st->codec->time_base.den);
David Conrad's avatar
David Conrad committed
85 86 87 88 89
        } else {
            st->codec->channels = bytestream_get_le16(&p);
            p += 2;                 /* block_align */
            st->codec->bit_rate = bytestream_get_le32(&p) * 8;
            st->codec->sample_rate = spu * 10000000 / time_unit;
90
            av_set_pts_info(st, 64, 1, st->codec->sample_rate);
David Conrad's avatar
David Conrad committed
91
        }
David Conrad's avatar
David Conrad committed
92 93 94 95
    } else if (*p == 3) {
        if (os->psize > 8)
            ff_vorbis_comment(s, &st->metadata, p+7, os->psize-8);
    }
Måns Rullgård's avatar
Måns Rullgård committed
96 97 98 99 100 101 102

    return 1;
}

static int
ogm_dshow_header(AVFormatContext *s, int idx)
{
103 104
    struct ogg *ogg = s->priv_data;
    struct ogg_stream *os = ogg->streams + idx;
Måns Rullgård's avatar
Måns Rullgård 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;

114
    t = AV_RL32(p + 96);
Måns Rullgård's avatar
Måns Rullgård committed
115 116

    if(t == 0x05589f80){
117
        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
118
        st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(p + 68));
Måns Rullgård's avatar
Måns Rullgård committed
119
        st->codec->time_base.den = 10000000;
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);
Måns Rullgård's avatar
Måns Rullgård committed
123
    } else if(t == 0x05589f81){
124
        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
125
        st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, AV_RL16(p + 124));
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;
Måns Rullgård's avatar
Måns Rullgård committed
129 130 131 132 133 134 135 136
    }

    return 1;
}

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

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

Måns Rullgård's avatar
Måns Rullgård committed
145 146 147 148
    lb = ((*p & 2) << 1) | ((*p >> 6) & 3);
    os->pstart += lb + 1;
    os->psize -= lb + 1;

149 150 151
    while (lb--)
        os->pduration += p[lb+1] << (lb*8);

Måns Rullgård's avatar
Måns Rullgård committed
152 153 154
    return 0;
}

155
const struct ogg_codec ff_ogm_video_codec = {
Måns Rullgård's avatar
Måns Rullgård committed
156 157 158
    .magic = "\001video",
    .magicsize = 6,
    .header = ogm_header,
David Conrad's avatar
David Conrad committed
159 160
    .packet = ogm_packet,
    .granule_is_start = 1,
Måns Rullgård's avatar
Måns Rullgård committed
161 162
};

163
const struct ogg_codec ff_ogm_audio_codec = {
Måns Rullgård's avatar
Måns Rullgård committed
164 165 166
    .magic = "\001audio",
    .magicsize = 6,
    .header = ogm_header,
David Conrad's avatar
David Conrad committed
167 168
    .packet = ogm_packet,
    .granule_is_start = 1,
Måns Rullgård's avatar
Måns Rullgård committed
169 170
};

171
const struct ogg_codec ff_ogm_text_codec = {
172 173 174
    .magic = "\001text",
    .magicsize = 5,
    .header = ogm_header,
David Conrad's avatar
David Conrad committed
175 176
    .packet = ogm_packet,
    .granule_is_start = 1,
177 178
};

179
const struct ogg_codec ff_ogm_old_codec = {
Måns Rullgård's avatar
Måns Rullgård committed
180 181 182
    .magic = "\001Direct Show Samples embedded in Ogg",
    .magicsize = 35,
    .header = ogm_dshow_header,
David Conrad's avatar
David Conrad committed
183 184
    .packet = ogm_packet,
    .granule_is_start = 1,
Måns Rullgård's avatar
Måns Rullgård committed
185
};