travis-ci: Fix CI on macOS
[opus-tools.git] / src / opus_header.c
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 "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 = total 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
60 typedef struct {
61    unsigned char *data;
62    int maxlen;
63    int pos;
64 } Packet;
65
66 typedef struct {
67    const unsigned char *data;
68    int maxlen;
69    int pos;
70 } ROPacket;
71
72 static 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
84 static 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
94 static 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
104 static 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
116 static 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
126 static 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
136 int 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
219 int 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). */
276 const 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 };