Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 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 
26
#include "libavutil/avassert.h"
27
#include "libavutil/intreadwrite.h"
28
#include "libavcodec/get_bits.h"
29
#include "libavcodec/bytestream.h"
30
#include "avformat.h"
31
#include "internal.h"
32
#include "oggdec.h"
33
#include "riff.h"
34
 
35
static int
36
ogm_header(AVFormatContext *s, int idx)
37
{
38
    struct ogg *ogg = s->priv_data;
39
    struct ogg_stream *os = ogg->streams + idx;
40
    AVStream *st = s->streams[idx];
41
    GetByteContext p;
42
    uint64_t time_unit;
43
    uint64_t spu;
44
    uint32_t size;
45
 
46
    bytestream2_init(&p, os->buf + os->pstart, os->psize);
47
    if (!(bytestream2_peek_byte(&p) & 1))
48
        return 0;
49
 
50
    if (bytestream2_peek_byte(&p) == 1) {
51
        bytestream2_skip(&p, 1);
52
 
53
        if (bytestream2_peek_byte(&p) == 'v'){
54
            int tag;
55
            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
56
            bytestream2_skip(&p, 8);
57
            tag = bytestream2_get_le32(&p);
58
            st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag);
59
            st->codec->codec_tag = tag;
60
        } else if (bytestream2_peek_byte(&p) == 't') {
61
            st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
62
            st->codec->codec_id = AV_CODEC_ID_TEXT;
63
            bytestream2_skip(&p, 12);
64
        } else {
65
            uint8_t acid[5] = { 0 };
66
            int cid;
67
            st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
68
            bytestream2_skip(&p, 8);
69
            bytestream2_get_buffer(&p, acid, 4);
70
            acid[4] = 0;
71
            cid = strtol(acid, NULL, 16);
72
            st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, cid);
73
            // our parser completely breaks AAC in Ogg
74
            if (st->codec->codec_id != AV_CODEC_ID_AAC)
75
                st->need_parsing = AVSTREAM_PARSE_FULL;
76
        }
77
 
78
        size        = bytestream2_get_le32(&p);
79
        size        = FFMIN(size, os->psize);
80
        time_unit   = bytestream2_get_le64(&p);
81
        spu         = bytestream2_get_le64(&p);
82
        bytestream2_skip(&p, 4);    /* default_len */
83
        bytestream2_skip(&p, 8);    /* buffersize + bits_per_sample */
84
 
85
        if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
86
            st->codec->width = bytestream2_get_le32(&p);
87
            st->codec->height = bytestream2_get_le32(&p);
88
            avpriv_set_pts_info(st, 64, time_unit, spu * 10000000);
89
        } else {
90
            st->codec->channels = bytestream2_get_le16(&p);
91
            bytestream2_skip(&p, 2); /* block_align */
92
            st->codec->bit_rate = bytestream2_get_le32(&p) * 8;
93
            st->codec->sample_rate = time_unit ? spu * 10000000 / time_unit : 0;
94
            avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
95
            if (size >= 56 && st->codec->codec_id == AV_CODEC_ID_AAC) {
96
                bytestream2_skip(&p, 4);
97
                size -= 4;
98
            }
99
            if (size > 52) {
100
                av_assert0(FF_INPUT_BUFFER_PADDING_SIZE <= 52);
101
                size -= 52;
102
                ff_alloc_extradata(st->codec, size);
103
                bytestream2_get_buffer(&p, st->codec->extradata, st->codec->extradata_size);
104
            }
105
        }
106
    } else if (bytestream2_peek_byte(&p) == 3) {
107
        bytestream2_skip(&p, 7);
108
        if (bytestream2_get_bytes_left(&p) > 1)
109
            ff_vorbis_comment(s, &st->metadata, p.buffer, bytestream2_get_bytes_left(&p) - 1);
110
    }
111
 
112
    return 1;
113
}
114
 
115
static int
116
ogm_dshow_header(AVFormatContext *s, int idx)
117
{
118
    struct ogg *ogg = s->priv_data;
119
    struct ogg_stream *os = ogg->streams + idx;
120
    AVStream *st = s->streams[idx];
121
    uint8_t *p = os->buf + os->pstart;
122
    uint32_t t;
123
 
124
    if(!(*p & 1))
125
        return 0;
126
    if(*p != 1)
127
        return 1;
128
 
129
    t = AV_RL32(p + 96);
130
 
131
    if(t == 0x05589f80){
132
        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
133
        st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(p + 68));
134
        avpriv_set_pts_info(st, 64, AV_RL64(p + 164), 10000000);
135
        st->codec->width = AV_RL32(p + 176);
136
        st->codec->height = AV_RL32(p + 180);
137
    } else if(t == 0x05589f81){
138
        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
139
        st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, AV_RL16(p + 124));
140
        st->codec->channels = AV_RL16(p + 126);
141
        st->codec->sample_rate = AV_RL32(p + 128);
142
        st->codec->bit_rate = AV_RL32(p + 132) * 8;
143
    }
144
 
145
    return 1;
146
}
147
 
148
static int
149
ogm_packet(AVFormatContext *s, int idx)
150
{
151
    struct ogg *ogg = s->priv_data;
152
    struct ogg_stream *os = ogg->streams + idx;
153
    uint8_t *p = os->buf + os->pstart;
154
    int lb;
155
 
156
    if(*p & 8)
157
        os->pflags |= AV_PKT_FLAG_KEY;
158
 
159
    lb = ((*p & 2) << 1) | ((*p >> 6) & 3);
160
    os->pstart += lb + 1;
161
    os->psize -= lb + 1;
162
 
163
    while (lb--)
164
        os->pduration += p[lb+1] << (lb*8);
165
 
166
    return 0;
167
}
168
 
169
const struct ogg_codec ff_ogm_video_codec = {
170
    .magic = "\001video",
171
    .magicsize = 6,
172
    .header = ogm_header,
173
    .packet = ogm_packet,
174
    .granule_is_start = 1,
175
    .nb_header = 2,
176
};
177
 
178
const struct ogg_codec ff_ogm_audio_codec = {
179
    .magic = "\001audio",
180
    .magicsize = 6,
181
    .header = ogm_header,
182
    .packet = ogm_packet,
183
    .granule_is_start = 1,
184
    .nb_header = 2,
185
};
186
 
187
const struct ogg_codec ff_ogm_text_codec = {
188
    .magic = "\001text",
189
    .magicsize = 5,
190
    .header = ogm_header,
191
    .packet = ogm_packet,
192
    .granule_is_start = 1,
193
    .nb_header = 2,
194
};
195
 
196
const struct ogg_codec ff_ogm_old_codec = {
197
    .magic = "\001Direct Show Samples embedded in Ogg",
198
    .magicsize = 35,
199
    .header = ogm_dshow_header,
200
    .packet = ogm_packet,
201
    .granule_is_start = 1,
202
    .nb_header = 1,
203
};