web: css whitespace fixes.
[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, ogg_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         ogg_uint16_t shortval;
93
94         p.data = packet;
95         p.maxlen = len;
96         p.pos = 0;
97         str[8] = 0;
98         if (len < 19)
99                 return -E_OPUS_HEADER;
100         read_chars(&p, (unsigned char*)str, 8);
101         if (memcmp(str, "OpusHead", 8) != 0)
102                 return -E_OPUS_HEADER;
103
104         if (!read_chars(&p, &ch, 1))
105                 return -E_OPUS_HEADER;
106         h->version = ch;
107         if((h->version & 240) != 0) /* Only major version 0 supported. */
108                 return -E_OPUS_HEADER;
109
110         if (!read_chars(&p, &ch, 1))
111                 return -E_OPUS_HEADER;
112         h->channels = ch;
113         if (h->channels == 0)
114                 return -E_OPUS_HEADER;
115
116         if (!read_uint16(&p, &shortval))
117                 return -E_OPUS_HEADER;
118         h->preskip = shortval;
119
120         if (!read_uint32(&p, &h->input_sample_rate))
121                 return -E_OPUS_HEADER;
122
123         if (!read_uint16(&p, &shortval))
124                 return -E_OPUS_HEADER;
125         h->gain = (short)shortval;
126
127         if (!read_chars(&p, &ch, 1))
128                 return -E_OPUS_HEADER;
129         channel_mapping = ch;
130
131         if (channel_mapping != 0) {
132                 if (!read_chars(&p, &ch, 1))
133                         return -E_OPUS_HEADER;
134
135                 if (ch < 1)
136                         return -E_OPUS_HEADER;
137                 h->nb_streams = ch;
138
139                 if (!read_chars(&p, &ch, 1))
140                         return -E_OPUS_HEADER;
141
142                 if (ch > h->nb_streams || (ch + h->nb_streams) > 255)
143                         return -E_OPUS_HEADER;
144                 h->nb_coupled = ch;
145
146                 /* Multi-stream support */
147                 for (i = 0; i < h->channels; i++) {
148                         if (!read_chars(&p, &h->stream_map[i], 1))
149                                 return -E_OPUS_HEADER;
150                         if (h->stream_map[i] > (h->nb_streams + h->nb_coupled)
151                                         && h->stream_map[i] != 255)
152                                 return -E_OPUS_HEADER;
153                 }
154         } else {
155                 if (h->channels > 2)
156                         return -E_OPUS_HEADER;
157                 h->nb_streams = 1;
158                 h->nb_coupled = h->channels > 1;
159                 h->stream_map[0] = 0;
160                 h->stream_map[1] = 1;
161         }
162         /*
163          * For version 0/1 we know there won't be any more data so reject any
164          * that have data past the end.
165          */
166         if ((h->version == 0 || h->version == 1) && p.pos != len)
167                 return -E_OPUS_HEADER;
168         return 1;
169 }