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