summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/libopus/opus_header.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/libopus/opus_header.c')
-rw-r--r--lib/rbcodec/codecs/libopus/opus_header.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libopus/opus_header.c b/lib/rbcodec/codecs/libopus/opus_header.c
new file mode 100644
index 0000000000..ed07c9ab50
--- /dev/null
+++ b/lib/rbcodec/codecs/libopus/opus_header.c
@@ -0,0 +1,286 @@
1/* Copyright (C)2012 Xiph.Org Foundation
2 File: opus_header.c
3
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
19 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28#ifdef HAVE_CONFIG_H
29# include "opus_config.h"
30#endif
31
32#include "opus_header.h"
33#include <string.h>
34#include <stdio.h>
35
36/* Header contents:
37 - "OpusHead" (64 bits)
38 - version number (8 bits)
39 - Channels C (8 bits)
40 - Pre-skip (16 bits)
41 - Sampling rate (32 bits)
42 - Gain in dB (16 bits, S7.8)
43 - Mapping (8 bits, 0=single stream (mono/stereo) 1=Vorbis mapping,
44 2..254: reserved, 255: multistream with no mapping)
45
46 - if (mapping != 0)
47 - N = totel number of streams (8 bits)
48 - M = number of paired streams (8 bits)
49 - C times channel origin
50 - if (C<2*M)
51 - stream = byte/2
52 - if (byte&0x1 == 0)
53 - left
54 else
55 - right
56 - else
57 - stream = byte-M
58*/
59
60typedef struct {
61 unsigned char *data;
62 int maxlen;
63 int pos;
64} Packet;
65
66typedef struct {
67 const unsigned char *data;
68 int maxlen;
69 int pos;
70} ROPacket;
71
72static int write_uint32(Packet *p, ogg_uint32_t val)
73{
74 if (p->pos>p->maxlen-4)
75 return 0;
76 p->data[p->pos ] = (val ) & 0xFF;
77 p->data[p->pos+1] = (val>> 8) & 0xFF;
78 p->data[p->pos+2] = (val>>16) & 0xFF;
79 p->data[p->pos+3] = (val>>24) & 0xFF;
80 p->pos += 4;
81 return 1;
82}
83
84static int write_uint16(Packet *p, ogg_uint16_t val)
85{
86 if (p->pos>p->maxlen-2)
87 return 0;
88 p->data[p->pos ] = (val ) & 0xFF;
89 p->data[p->pos+1] = (val>> 8) & 0xFF;
90 p->pos += 2;
91 return 1;
92}
93
94static int write_chars(Packet *p, const unsigned char *str, int nb_chars)
95{
96 int i;
97 if (p->pos>p->maxlen-nb_chars)
98 return 0;
99 for (i=0;i<nb_chars;i++)
100 p->data[p->pos++] = str[i];
101 return 1;
102}
103
104static int read_uint32(ROPacket *p, ogg_uint32_t *val)
105{
106 if (p->pos>p->maxlen-4)
107 return 0;
108 *val = (ogg_uint32_t)p->data[p->pos ];
109 *val |= (ogg_uint32_t)p->data[p->pos+1]<< 8;
110 *val |= (ogg_uint32_t)p->data[p->pos+2]<<16;
111 *val |= (ogg_uint32_t)p->data[p->pos+3]<<24;
112 p->pos += 4;
113 return 1;
114}
115
116static int read_uint16(ROPacket *p, ogg_uint16_t *val)
117{
118 if (p->pos>p->maxlen-2)
119 return 0;
120 *val = (ogg_uint16_t)p->data[p->pos ];
121 *val |= (ogg_uint16_t)p->data[p->pos+1]<<8;
122 p->pos += 2;
123 return 1;
124}
125
126static int read_chars(ROPacket *p, unsigned char *str, int nb_chars)
127{
128 int i;
129 if (p->pos>p->maxlen-nb_chars)
130 return 0;
131 for (i=0;i<nb_chars;i++)
132 str[i] = p->data[p->pos++];
133 return 1;
134}
135
136int opus_header_parse(const unsigned char *packet, int len, OpusHeader *h)
137{
138 int i;
139 char str[9];
140 ROPacket p;
141 unsigned char ch;
142 ogg_uint16_t shortval;
143
144 p.data = packet;
145 p.maxlen = len;
146 p.pos = 0;
147 str[8] = 0;
148 if (len<19)return 0;
149 read_chars(&p, (unsigned char*)str, 8);
150 if (memcmp(str, "OpusHead", 8)!=0)
151 return 0;
152
153 if (!read_chars(&p, &ch, 1))
154 return 0;
155 h->version = ch;
156 if((h->version&240) != 0) /* Only major version 0 supported. */
157 return 0;
158
159 if (!read_chars(&p, &ch, 1))
160 return 0;
161 h->channels = ch;
162 if (h->channels == 0)
163 return 0;
164
165 if (!read_uint16(&p, &shortval))
166 return 0;
167 h->preskip = shortval;
168
169 if (!read_uint32(&p, &h->input_sample_rate))
170 return 0;
171
172 if (!read_uint16(&p, &shortval))
173 return 0;
174 h->gain = (short)shortval;
175
176 if (!read_chars(&p, &ch, 1))
177 return 0;
178 h->channel_mapping = ch;
179
180 if (h->channel_mapping != 0)
181 {
182 if (!read_chars(&p, &ch, 1))
183 return 0;
184
185 if (ch<1)
186 return 0;
187 h->nb_streams = ch;
188
189 if (!read_chars(&p, &ch, 1))
190 return 0;
191
192 if (ch>h->nb_streams || (ch+h->nb_streams)>255)
193 return 0;
194 h->nb_coupled = ch;
195
196 /* Multi-stream support */
197 for (i=0;i<h->channels;i++)
198 {
199 if (!read_chars(&p, &h->stream_map[i], 1))
200 return 0;
201 if (h->stream_map[i]>(h->nb_streams+h->nb_coupled) && h->stream_map[i]!=255)
202 return 0;
203 }
204 } else {
205 if(h->channels>2)
206 return 0;
207 h->nb_streams = 1;
208 h->nb_coupled = h->channels>1;
209 h->stream_map[0]=0;
210 h->stream_map[1]=1;
211 }
212 /*For version 0/1 we know there won't be any more data
213 so reject any that have data past the end.*/
214 if ((h->version==0 || h->version==1) && p.pos != len)
215 return 0;
216 return 1;
217}
218
219int opus_header_to_packet(const OpusHeader *h, unsigned char *packet, int len)
220{
221 int i;
222 Packet p;
223 unsigned char ch;
224
225 p.data = packet;
226 p.maxlen = len;
227 p.pos = 0;
228 if (len<19)return 0;
229 if (!write_chars(&p, (const unsigned char*)"OpusHead", 8))
230 return 0;
231 /* Version is 1 */
232 ch = 1;
233 if (!write_chars(&p, &ch, 1))
234 return 0;
235
236 ch = h->channels;
237 if (!write_chars(&p, &ch, 1))
238 return 0;
239
240 if (!write_uint16(&p, h->preskip))
241 return 0;
242
243 if (!write_uint32(&p, h->input_sample_rate))
244 return 0;
245
246 if (!write_uint16(&p, h->gain))
247 return 0;
248
249 ch = h->channel_mapping;
250 if (!write_chars(&p, &ch, 1))
251 return 0;
252
253 if (h->channel_mapping != 0)
254 {
255 ch = h->nb_streams;
256 if (!write_chars(&p, &ch, 1))
257 return 0;
258
259 ch = h->nb_coupled;
260 if (!write_chars(&p, &ch, 1))
261 return 0;
262
263 /* Multi-stream support */
264 for (i=0;i<h->channels;i++)
265 {
266 if (!write_chars(&p, &h->stream_map[i], 1))
267 return 0;
268 }
269 }
270
271 return p.pos;
272}
273
274/* This is just here because it's a convenient file linked by both opusenc and
275 opusdec (to guarantee this maps stays in sync). */
276const int wav_permute_matrix[8][8] =
277{
278 {0}, /* 1.0 mono */
279 {0,1}, /* 2.0 stereo */
280 {0,2,1}, /* 3.0 channel ('wide') stereo */
281 {0,1,2,3}, /* 4.0 discrete quadraphonic */
282 {0,2,1,3,4}, /* 5.0 surround */
283 {0,2,1,4,5,3}, /* 5.1 surround */
284 {0,2,1,5,6,4,3}, /* 6.1 surround */
285 {0,2,1,6,7,4,5,3} /* 7.1 surround (classic theater 8-track) */
286};