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=ambisonics, 3=projection ambisonics, 4..239: reserved,
45 240..254: experiments, 255: multistream with no mapping)
46
47 - if (mapping != 0)
48 - N = total number of streams (8 bits)
49 - M = number of paired streams (8 bits)
50 - if (mapping != a projection family)
51 - C times channel origin
52 - if (C<2*M)
53 - stream = byte/2
54 - if (byte&0x1 == 0)
55 - left
56 else
57 - right
58 - else
59 - stream = byte-M
60 - else
61 - D demixing matrix (C*(N+M)*16 bits)
62 */
63
64 typedef struct {
65 unsigned char *data;
66 int maxlen;
67 int pos;
68 } Packet;
69
write_uint32(Packet * p,opus_uint32 val)70 static int write_uint32(Packet *p, opus_uint32 val)
71 {
72 if (p->pos>p->maxlen-4)
73 return 0;
74 p->data[p->pos ] = (val ) & 0xFF;
75 p->data[p->pos+1] = (val>> 8) & 0xFF;
76 p->data[p->pos+2] = (val>>16) & 0xFF;
77 p->data[p->pos+3] = (val>>24) & 0xFF;
78 p->pos += 4;
79 return 1;
80 }
81
write_uint16(Packet * p,opus_uint16 val)82 static int write_uint16(Packet *p, opus_uint16 val)
83 {
84 if (p->pos>p->maxlen-2)
85 return 0;
86 p->data[p->pos ] = (val ) & 0xFF;
87 p->data[p->pos+1] = (val>> 8) & 0xFF;
88 p->pos += 2;
89 return 1;
90 }
91
write_chars(Packet * p,const unsigned char * str,int nb_chars)92 static int write_chars(Packet *p, const unsigned char *str, int nb_chars)
93 {
94 int i;
95 if (p->pos>p->maxlen-nb_chars)
96 return 0;
97 for (i=0;i<nb_chars;i++)
98 p->data[p->pos++] = str[i];
99 return 1;
100 }
101
write_matrix_chars(Packet * p,const OpusGenericEncoder * st)102 static int write_matrix_chars(Packet *p, const OpusGenericEncoder *st)
103 {
104 #ifdef OPUS_HAVE_OPUS_PROJECTION_H
105 opus_int32 size;
106 int ret;
107 ret=opeint_encoder_ctl(st, OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE(&size));
108 if (ret != OPUS_OK) return 0;
109 if (size>p->maxlen-p->pos) return 0;
110 ret=opeint_encoder_ctl(st, OPUS_PROJECTION_GET_DEMIXING_MATRIX(&p->data[p->pos], size));
111 if (ret != OPUS_OK) return 0;
112 p->pos += size;
113 return 1;
114 #else
115 (void)p;
116 (void)st;
117 return 0;
118 #endif
119 }
120
opeint_opus_header_get_size(const OpusHeader * h)121 int opeint_opus_header_get_size(const OpusHeader *h)
122 {
123 int len=0;
124 if (opeint_use_projection(h->channel_mapping))
125 {
126 /* 19 bytes from fixed header,
127 * 2 bytes for nb_streams & nb_coupled,
128 * 2 bytes per cell of demixing matrix, where:
129 * rows=channels, cols=nb_streams+nb_coupled
130 */
131 len=21+(h->channels*(h->nb_streams+h->nb_coupled)*2);
132 }
133 else
134 {
135 /* 19 bytes from fixed header,
136 * 2 bytes for nb_streams & nb_coupled,
137 * 1 byte per channel
138 */
139 len=21+h->channels;
140 }
141 return len;
142 }
143
opeint_opus_header_to_packet(const OpusHeader * h,unsigned char * packet,int len,const OpusGenericEncoder * st)144 int opeint_opus_header_to_packet(const OpusHeader *h, unsigned char *packet, int len, const OpusGenericEncoder *st)
145 {
146 int i;
147 Packet p;
148 unsigned char ch;
149
150 p.data = packet;
151 p.maxlen = len;
152 p.pos = 0;
153 if (len<19)return 0;
154 if (!write_chars(&p, (const unsigned char*)"OpusHead", 8))
155 return 0;
156 /* Version is 1 */
157 ch = 1;
158 if (!write_chars(&p, &ch, 1))
159 return 0;
160
161 ch = h->channels;
162 if (!write_chars(&p, &ch, 1))
163 return 0;
164
165 if (!write_uint16(&p, h->preskip))
166 return 0;
167
168 if (!write_uint32(&p, h->input_sample_rate))
169 return 0;
170
171 if (opeint_use_projection(h->channel_mapping))
172 {
173 #ifdef OPUS_HAVE_OPUS_PROJECTION_H
174 opus_int32 matrix_gain;
175 int ret;
176 ret=opeint_encoder_ctl(st, OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN(&matrix_gain));
177 if (ret != OPUS_OK) return 0;
178 if (!write_uint16(&p, h->gain + matrix_gain))
179 return 0;
180 #else
181 return 0;
182 #endif
183 }
184 else
185 {
186 if (!write_uint16(&p, h->gain))
187 return 0;
188 }
189
190 ch = h->channel_mapping;
191 if (!write_chars(&p, &ch, 1))
192 return 0;
193
194 if (h->channel_mapping != 0)
195 {
196 ch = h->nb_streams;
197 if (!write_chars(&p, &ch, 1))
198 return 0;
199
200 ch = h->nb_coupled;
201 if (!write_chars(&p, &ch, 1))
202 return 0;
203
204 /* Multi-stream support */
205 if (opeint_use_projection(h->channel_mapping))
206 {
207 if (!write_matrix_chars(&p, st))
208 return 0;
209 }
210 else
211 {
212 for (i=0;i<h->channels;i++)
213 {
214 if (!write_chars(&p, &h->stream_map[i], 1))
215 return 0;
216 }
217 }
218 }
219
220 return p.pos;
221 }
222
223 /*
224 Comments will be stored in the Vorbis style.
225 It is described in the "Structure" section of
226 http://www.xiph.org/ogg/vorbis/doc/v-comment.html
227
228 However, Opus and other non-vorbis formats omit the "framing_bit".
229
230 The comment header is decoded as follows:
231 1) [vendor_length] = read an unsigned integer of 32 bits
232 2) [vendor_string] = read a UTF-8 vector as [vendor_length] octets
233 3) [user_comment_list_length] = read an unsigned integer of 32 bits
234 4) iterate [user_comment_list_length] times {
235 5) [length] = read an unsigned integer of 32 bits
236 6) this iteration's user comment = read a UTF-8 vector as [length] octets
237 }
238 7) done.
239 */
240
241 #define readint(buf, base) (((buf[base+3]<<24)&0xff000000)| \
242 ((buf[base+2]<<16)&0xff0000)| \
243 ((buf[base+1]<<8)&0xff00)| \
244 (buf[base]&0xff))
245 #define writeint(buf, base, val) do{ buf[base+3]=((val)>>24)&0xff; \
246 buf[base+2]=((val)>>16)&0xff; \
247 buf[base+1]=((val)>>8)&0xff; \
248 buf[base]=(val)&0xff; \
249 }while(0)
250
opeint_comment_init(char ** comments,int * length,const char * vendor_string)251 void opeint_comment_init(char **comments, int* length, const char *vendor_string)
252 {
253 /*The 'vendor' field should be the actual encoding library used.*/
254 int vendor_length=strlen(vendor_string);
255 int user_comment_list_length=0;
256 int len=8+4+vendor_length+4;
257 char *p=(char*)malloc(len);
258 if (p == NULL) {
259 len=0;
260 } else {
261 memcpy(p, "OpusTags", 8);
262 writeint(p, 8, vendor_length);
263 memcpy(p+12, vendor_string, vendor_length);
264 writeint(p, 12+vendor_length, user_comment_list_length);
265 }
266 *length=len;
267 *comments=p;
268 }
269
opeint_comment_add(char ** comments,int * length,const char * tag,const char * val)270 int opeint_comment_add(char **comments, int* length, const char *tag, const char *val)
271 {
272 char* p=*comments;
273 int vendor_length=readint(p, 8);
274 int user_comment_list_length=readint(p, 8+4+vendor_length);
275 int tag_len=(tag?strlen(tag)+1:0);
276 int val_len=strlen(val);
277 int len=(*length)+4+tag_len+val_len;
278
279 p=(char*)realloc(p, len);
280 if (p == NULL) return 1;
281
282 writeint(p, *length, tag_len+val_len); /* length of comment */
283 if(tag){
284 memcpy(p+*length+4, tag, tag_len); /* comment tag */
285 (p+*length+4)[tag_len-1] = '='; /* separator */
286 }
287 memcpy(p+*length+4+tag_len, val, val_len); /* comment */
288 writeint(p, 8+4+vendor_length, user_comment_list_length+1);
289 *comments=p;
290 *length=len;
291 return 0;
292 }
293
opeint_comment_pad(char ** comments,int * length,int amount)294 void opeint_comment_pad(char **comments, int* length, int amount)
295 {
296 if(amount>0){
297 int i;
298 int newlen;
299 char* p=*comments;
300 /*Make sure there is at least amount worth of padding free, and
301 round up to the maximum that fits in the current ogg segments.*/
302 newlen=(*length+amount+255)/255*255-1;
303 p=realloc(p,newlen);
304 if (p == NULL) return;
305 for(i=*length;i<newlen;i++)p[i]=0;
306 *comments=p;
307 *length=newlen;
308 }
309 }
310
311 #undef readint
312 #undef writeint
313
314