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 <stdlib.h>
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
35static int
36ogm_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        if (!time_unit || !spu) {
83            av_log(s, AV_LOG_ERROR, "Invalid timing values.\n");
84            return AVERROR_INVALIDDATA;
85        }
86
87        bytestream2_skip(&p, 4);    /* default_len */
88        bytestream2_skip(&p, 8);    /* buffersize + bits_per_sample */
89
90        if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){
91            st->codec->width = bytestream2_get_le32(&p);
92            st->codec->height = bytestream2_get_le32(&p);
93            avpriv_set_pts_info(st, 64, time_unit, spu * 10000000);
94        } else {
95            st->codec->channels = bytestream2_get_le16(&p);
96            bytestream2_skip(&p, 2); /* block_align */
97            st->codec->bit_rate = bytestream2_get_le32(&p) * 8;
98            st->codec->sample_rate = spu * 10000000 / time_unit;
99            avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
100            if (size >= 56 && st->codec->codec_id == AV_CODEC_ID_AAC) {
101                bytestream2_skip(&p, 4);
102                size -= 4;
103            }
104            if (size > 52) {
105                av_assert0(FF_INPUT_BUFFER_PADDING_SIZE <= 52);
106                size -= 52;
107                ff_alloc_extradata(st->codec, size);
108                bytestream2_get_buffer(&p, st->codec->extradata, st->codec->extradata_size);
109            }
110        }
111    } else if (bytestream2_peek_byte(&p) == 3) {
112        bytestream2_skip(&p, 7);
113        if (bytestream2_get_bytes_left(&p) > 1)
114            ff_vorbis_comment(s, &st->metadata, p.buffer, bytestream2_get_bytes_left(&p) - 1, 1);
115    }
116
117    return 1;
118}
119
120static int
121ogm_dshow_header(AVFormatContext *s, int idx)
122{
123    struct ogg *ogg = s->priv_data;
124    struct ogg_stream *os = ogg->streams + idx;
125    AVStream *st = s->streams[idx];
126    uint8_t *p = os->buf + os->pstart;
127    uint32_t t;
128
129    if(!(*p & 1))
130        return 0;
131    if(*p != 1)
132        return 1;
133
134    if (os->psize < 100)
135        return AVERROR_INVALIDDATA;
136    t = AV_RL32(p + 96);
137
138    if(t == 0x05589f80){
139        if (os->psize < 184)
140            return AVERROR_INVALIDDATA;
141
142        st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
143        st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, AV_RL32(p + 68));
144        avpriv_set_pts_info(st, 64, AV_RL64(p + 164), 10000000);
145        st->codec->width = AV_RL32(p + 176);
146        st->codec->height = AV_RL32(p + 180);
147    } else if(t == 0x05589f81){
148        if (os->psize < 136)
149            return AVERROR_INVALIDDATA;
150
151        st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
152        st->codec->codec_id = ff_codec_get_id(ff_codec_wav_tags, AV_RL16(p + 124));
153        st->codec->channels = AV_RL16(p + 126);
154        st->codec->sample_rate = AV_RL32(p + 128);
155        st->codec->bit_rate = AV_RL32(p + 132) * 8;
156    }
157
158    return 1;
159}
160
161static int
162ogm_packet(AVFormatContext *s, int idx)
163{
164    struct ogg *ogg = s->priv_data;
165    struct ogg_stream *os = ogg->streams + idx;
166    uint8_t *p = os->buf + os->pstart;
167    int lb;
168
169    if(*p & 8)
170        os->pflags |= AV_PKT_FLAG_KEY;
171
172    lb = ((*p & 2) << 1) | ((*p >> 6) & 3);
173    os->pstart += lb + 1;
174    os->psize -= lb + 1;
175
176    while (lb--)
177        os->pduration += p[lb+1] << (lb*8);
178
179    return 0;
180}
181
182const struct ogg_codec ff_ogm_video_codec = {
183    .magic = "\001video",
184    .magicsize = 6,
185    .header = ogm_header,
186    .packet = ogm_packet,
187    .granule_is_start = 1,
188    .nb_header = 2,
189};
190
191const struct ogg_codec ff_ogm_audio_codec = {
192    .magic = "\001audio",
193    .magicsize = 6,
194    .header = ogm_header,
195    .packet = ogm_packet,
196    .granule_is_start = 1,
197    .nb_header = 2,
198};
199
200const struct ogg_codec ff_ogm_text_codec = {
201    .magic = "\001text",
202    .magicsize = 5,
203    .header = ogm_header,
204    .packet = ogm_packet,
205    .granule_is_start = 1,
206    .nb_header = 2,
207};
208
209const struct ogg_codec ff_ogm_old_codec = {
210    .magic = "\001Direct Show Samples embedded in Ogg",
211    .magicsize = 35,
212    .header = ogm_dshow_header,
213    .packet = ogm_packet,
214    .granule_is_start = 1,
215    .nb_header = 1,
216};
217