opus: Use uint16_t for preskip and gain.
[paraslash.git] / opus_common.c
1 /* Copyright (C)2012 Xiph.Org Foundation
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
5 * are met:
6 *
7 * - Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 *
10 * - Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 /**
28 * \file opus_common.c Common functions of the opus decoder and audio format
29 * handler.
30 */
31
32 #include <ogg/ogg.h>
33
34 #include "para.h"
35 #include "error.h"
36 #include "opus_common.h"
37 #include "portable_io.h"
38
39 struct packet {
40 const char *data;
41 int maxlen;
42 int pos;
43 };
44
45 static int read_chars(struct packet *p, unsigned char *str, int nb_chars)
46 {
47 int i;
48
49 if (p->pos > p->maxlen - nb_chars)
50 return 0;
51 for (i = 0; i < nb_chars; i++)
52 str[i] = p->data[p->pos++];
53 return 1;
54 }
55
56 static int read_uint32(struct packet *p, ogg_uint32_t *val)
57 {
58 if (p->pos > p->maxlen - 4)
59 return 0;
60 *val = read_u32(p->data + p->pos);
61 p->pos += 4;
62 return 1;
63 }
64
65 static int read_uint16(struct packet *p, uint16_t *val)
66 {
67 if (p->pos > p->maxlen - 2)
68 return 0;
69 *val = read_u16(p->data + p->pos);
70 p->pos += 2;
71 return 1;
72 }
73
74 /**
75 * Get metadata of an opus stream.
76 *
77 * This is called from both the audio format handler (which passes ogg packet
78 * 0) and from the decoder.
79 *
80 * \param packet Start of the packet.
81 * \param len Number of bytes.
82 * \param h Result.
83 *
84 * \return Standard.
85 */
86 int opus_parse_header(const char *packet, int len, struct opus_header *h)
87 {
88 int i;
89 char str[9];
90 struct packet p;
91 unsigned char ch, channel_mapping;
92
93 p.data = packet;
94 p.maxlen = len;
95 p.pos = 0;
96 str[8] = 0;
97 if (len < 19)
98 return -E_OPUS_HEADER;
99 read_chars(&p, (unsigned char*)str, 8);
100 if (memcmp(str, "OpusHead", 8) != 0)
101 return -E_OPUS_HEADER;
102
103 if (!read_chars(&p, &ch, 1))
104 return -E_OPUS_HEADER;
105 h->version = ch;
106 if ((h->version & 240) != 0) /* Only major version 0 supported. */
107 return -E_OPUS_HEADER;
108
109 if (!read_chars(&p, &ch, 1))
110 return -E_OPUS_HEADER;
111 h->channels = ch;
112 if (h->channels == 0)
113 return -E_OPUS_HEADER;
114
115 if (!read_uint16(&p, &h->preskip))
116 return -E_OPUS_HEADER;
117
118 if (!read_uint32(&p, &h->input_sample_rate))
119 return -E_OPUS_HEADER;
120
121 if (!read_uint16(&p, &h->gain))
122 return -E_OPUS_HEADER;
123
124 if (!read_chars(&p, &ch, 1))
125 return -E_OPUS_HEADER;
126 channel_mapping = ch;
127
128 if (channel_mapping != 0) {
129 if (!read_chars(&p, &ch, 1))
130 return -E_OPUS_HEADER;
131
132 if (ch < 1)
133 return -E_OPUS_HEADER;
134 h->nb_streams = ch;
135
136 if (!read_chars(&p, &ch, 1))
137 return -E_OPUS_HEADER;
138
139 if (ch > h->nb_streams || (ch + h->nb_streams) > 255)
140 return -E_OPUS_HEADER;
141 h->nb_coupled = ch;
142
143 /* Multi-stream support */
144 for (i = 0; i < h->channels; i++) {
145 if (!read_chars(&p, &h->stream_map[i], 1))
146 return -E_OPUS_HEADER;
147 if (h->stream_map[i] > (h->nb_streams + h->nb_coupled)
148 && h->stream_map[i] != 255)
149 return -E_OPUS_HEADER;
150 }
151 } else {
152 if (h->channels > 2)
153 return -E_OPUS_HEADER;
154 h->nb_streams = 1;
155 h->nb_coupled = h->channels > 1;
156 h->stream_map[0] = 0;
157 h->stream_map[1] = 1;
158 }
159 /*
160 * For version 0/1 we know there won't be any more data so reject any
161 * that have data past the end.
162 */
163 if ((h->version == 0 || h->version == 1) && p.pos != len)
164 return -E_OPUS_HEADER;
165 return 1;
166 }