blob: c5f37a0ef94f33ac656670f682b8a835252f6464 [file] [log] [blame]
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001/* Copyright (c) 2011 Xiph.Org Foundation
2 Written by Jean-Marc Valin */
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 COPYRIGHT OWNER
19 OR 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_multistream.h"
33#include "opus.h"
34#include "opus_private.h"
35#include "stack_alloc.h"
36#include <stdarg.h>
37#include "float_cast.h"
38#include "os_support.h"
39
40struct OpusMSEncoder {
41 ChannelLayout layout;
42 int bitrate;
43 /* Encoder states go here */
44};
45
46#ifdef FIXED_POINT
47#define opus_encode_native opus_encode
48#else
49#define opus_encode_native opus_encode_float
50#endif
51
52static int validate_encoder_layout(const ChannelLayout *layout)
53{
54 int s;
55 for (s=0;s<layout->nb_streams;s++)
56 {
57 if (s < layout->nb_coupled_streams)
58 {
59 if (get_left_channel(layout, s, -1)==-1)
60 return 0;
61 if (get_right_channel(layout, s, -1)==-1)
62 return 0;
63 } else {
64 if (get_mono_channel(layout, s, -1)==-1)
65 return 0;
66 }
67 }
68 return 1;
69}
70
71
72opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
73{
74 int coupled_size;
75 int mono_size;
76
77 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
78 coupled_size = opus_encoder_get_size(2);
79 mono_size = opus_encoder_get_size(1);
80 return align(sizeof(OpusMSEncoder))
81 + nb_coupled_streams * align(coupled_size)
82 + (nb_streams-nb_coupled_streams) * align(mono_size);
83}
84
85
86
87int opus_multistream_encoder_init(
88 OpusMSEncoder *st,
89 opus_int32 Fs,
90 int channels,
91 int streams,
92 int coupled_streams,
93 const unsigned char *mapping,
94 int application
95)
96{
97 int coupled_size;
98 int mono_size;
99 int i, ret;
100 char *ptr;
101
102 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
103 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
104 return OPUS_BAD_ARG;
105
106 st->layout.nb_channels = channels;
107 st->layout.nb_streams = streams;
108 st->layout.nb_coupled_streams = coupled_streams;
109
110 for (i=0;i<st->layout.nb_channels;i++)
111 st->layout.mapping[i] = mapping[i];
112 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
113 return OPUS_BAD_ARG;
114 ptr = (char*)st + align(sizeof(OpusMSEncoder));
115 coupled_size = opus_encoder_get_size(2);
116 mono_size = opus_encoder_get_size(1);
117
118 for (i=0;i<st->layout.nb_coupled_streams;i++)
119 {
120 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
121 if(ret!=OPUS_OK)return ret;
122 ptr += align(coupled_size);
123 }
124 for (;i<st->layout.nb_streams;i++)
125 {
126 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
127 if(ret!=OPUS_OK)return ret;
128 ptr += align(mono_size);
129 }
130 return OPUS_OK;
131}
132
133OpusMSEncoder *opus_multistream_encoder_create(
134 opus_int32 Fs,
135 int channels,
136 int streams,
137 int coupled_streams,
138 const unsigned char *mapping,
139 int application,
140 int *error
141)
142{
143 int ret;
144 OpusMSEncoder *st;
145 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
146 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
147 {
148 if (error)
149 *error = OPUS_BAD_ARG;
150 return NULL;
151 }
152 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
153 if (st==NULL)
154 {
155 if (error)
156 *error = OPUS_ALLOC_FAIL;
157 return NULL;
158 }
159 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
160 if (ret != OPUS_OK)
161 {
162 opus_free(st);
163 st = NULL;
164 }
165 if (error)
166 *error = ret;
167 return st;
168}
169
170typedef void (*opus_copy_channel_in_func)(
171 opus_val16 *dst,
172 int dst_stride,
173 const void *src,
174 int src_stride,
175 int src_channel,
176 int frame_size
177);
178
179/* Max size in case the encoder decides to return three frames */
180#define MS_FRAME_TMP (3*1275+7)
181static int opus_multistream_encode_native
182(
183 OpusMSEncoder *st,
184 opus_copy_channel_in_func copy_channel_in,
185 const void *pcm,
186 int frame_size,
187 unsigned char *data,
188 opus_int32 max_data_bytes
189)
190{
191 opus_int32 Fs;
192 int coupled_size;
193 int mono_size;
194 int s;
195 char *ptr;
196 int tot_size;
197 VARDECL(opus_val16, buf);
198 unsigned char tmp_data[MS_FRAME_TMP];
199 OpusRepacketizer rp;
200 ALLOC_STACK;
201
202 ptr = (char*)st + align(sizeof(OpusMSEncoder));
203 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
204 /* Validate frame_size before using it to allocate stack space.
205 This mirrors the checks in opus_encode[_float](). */
206 if (400*frame_size != Fs && 200*frame_size != Fs &&
207 100*frame_size != Fs && 50*frame_size != Fs &&
208 25*frame_size != Fs && 50*frame_size != 3*Fs)
209 {
210 RESTORE_STACK;
211 return OPUS_BAD_ARG;
212 }
213 ALLOC(buf, 2*frame_size, opus_val16);
214 coupled_size = opus_encoder_get_size(2);
215 mono_size = opus_encoder_get_size(1);
216
217 if (max_data_bytes < 4*st->layout.nb_streams-1)
218 {
219 RESTORE_STACK;
220 return OPUS_BUFFER_TOO_SMALL;
221 }
222 /* Counting ToC */
223 tot_size = 0;
224 for (s=0;s<st->layout.nb_streams;s++)
225 {
226 OpusEncoder *enc;
227 int len;
228 int curr_max;
229
230 opus_repacketizer_init(&rp);
231 enc = (OpusEncoder*)ptr;
232 if (s < st->layout.nb_coupled_streams)
233 {
234 int left, right;
235 left = get_left_channel(&st->layout, s, -1);
236 right = get_right_channel(&st->layout, s, -1);
237 (*copy_channel_in)(buf, 2,
238 pcm, st->layout.nb_channels, left, frame_size);
239 (*copy_channel_in)(buf+1, 2,
240 pcm, st->layout.nb_channels, right, frame_size);
241 ptr += align(coupled_size);
242 } else {
243 int chan = get_mono_channel(&st->layout, s, -1);
244 (*copy_channel_in)(buf, 1,
245 pcm, st->layout.nb_channels, chan, frame_size);
246 ptr += align(mono_size);
247 }
248 /* number of bytes left (+Toc) */
249 curr_max = max_data_bytes - tot_size;
250 /* Reserve three bytes for the last stream and four for the others */
251 curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
252 curr_max = IMIN(curr_max,MS_FRAME_TMP);
253 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max);
254 if (len<0)
255 {
256 RESTORE_STACK;
257 return len;
258 }
259 /* We need to use the repacketizer to add the self-delimiting lengths
260 while taking into account the fact that the encoder can now return
261 more than one frame at a time (e.g. 60 ms CELT-only) */
262 opus_repacketizer_cat(&rp, tmp_data, len);
263 len = opus_repacketizer_out_range_impl(&rp, 0, opus_repacketizer_get_nb_frames(&rp), data, max_data_bytes-tot_size, s != st->layout.nb_streams-1);
264 data += len;
265 tot_size += len;
266 }
267 RESTORE_STACK;
268 return tot_size;
269
270}
271
272#if !defined(DISABLE_FLOAT_API)
273static void opus_copy_channel_in_float(
274 opus_val16 *dst,
275 int dst_stride,
276 const void *src,
277 int src_stride,
278 int src_channel,
279 int frame_size
280)
281{
282 const float *float_src;
283 int i;
284 float_src = (const float *)src;
285 for (i=0;i<frame_size;i++)
286#if defined(FIXED_POINT)
287 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
288#else
289 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
290#endif
291}
292#endif
293
294static void opus_copy_channel_in_short(
295 opus_val16 *dst,
296 int dst_stride,
297 const void *src,
298 int src_stride,
299 int src_channel,
300 int frame_size
301)
302{
303 const opus_int16 *short_src;
304 int i;
305 short_src = (const opus_int16 *)src;
306 for (i=0;i<frame_size;i++)
307#if defined(FIXED_POINT)
308 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
309#else
310 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
311#endif
312}
313
314#ifdef FIXED_POINT
315int opus_multistream_encode(
316 OpusMSEncoder *st,
317 const opus_val16 *pcm,
318 int frame_size,
319 unsigned char *data,
320 opus_int32 max_data_bytes
321)
322{
323 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
324 pcm, frame_size, data, max_data_bytes);
325}
326
327#ifndef DISABLE_FLOAT_API
328int opus_multistream_encode_float(
329 OpusMSEncoder *st,
330 const float *pcm,
331 int frame_size,
332 unsigned char *data,
333 opus_int32 max_data_bytes
334)
335{
336 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
337 pcm, frame_size, data, max_data_bytes);
338}
339#endif
340
341#else
342
343int opus_multistream_encode_float
344(
345 OpusMSEncoder *st,
346 const opus_val16 *pcm,
347 int frame_size,
348 unsigned char *data,
349 opus_int32 max_data_bytes
350)
351{
352 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
353 pcm, frame_size, data, max_data_bytes);
354}
355
356int opus_multistream_encode(
357 OpusMSEncoder *st,
358 const opus_int16 *pcm,
359 int frame_size,
360 unsigned char *data,
361 opus_int32 max_data_bytes
362)
363{
364 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
365 pcm, frame_size, data, max_data_bytes);
366}
367#endif
368
369int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
370{
371 va_list ap;
372 int coupled_size, mono_size;
373 char *ptr;
374 int ret = OPUS_OK;
375
376 va_start(ap, request);
377
378 coupled_size = opus_encoder_get_size(2);
379 mono_size = opus_encoder_get_size(1);
380 ptr = (char*)st + align(sizeof(OpusMSEncoder));
381 switch (request)
382 {
383 case OPUS_SET_BITRATE_REQUEST:
384 {
385 int chan, s;
386 opus_int32 value = va_arg(ap, opus_int32);
387 chan = st->layout.nb_streams + st->layout.nb_coupled_streams;
388 value /= chan;
389 for (s=0;s<st->layout.nb_streams;s++)
390 {
391 OpusEncoder *enc;
392 enc = (OpusEncoder*)ptr;
393 if (s < st->layout.nb_coupled_streams)
394 ptr += align(coupled_size);
395 else
396 ptr += align(mono_size);
397 opus_encoder_ctl(enc, request, value * (s < st->layout.nb_coupled_streams ? 2 : 1));
398 }
399 }
400 break;
401 case OPUS_GET_BITRATE_REQUEST:
402 {
403 int s;
404 opus_int32 *value = va_arg(ap, opus_int32*);
405 *value = 0;
406 for (s=0;s<st->layout.nb_streams;s++)
407 {
408 opus_int32 rate;
409 OpusEncoder *enc;
410 enc = (OpusEncoder*)ptr;
411 if (s < st->layout.nb_coupled_streams)
412 ptr += align(coupled_size);
413 else
414 ptr += align(mono_size);
415 opus_encoder_ctl(enc, request, &rate);
416 *value += rate;
417 }
418 }
419 break;
420 case OPUS_GET_LSB_DEPTH_REQUEST:
421 case OPUS_GET_VBR_REQUEST:
422 case OPUS_GET_APPLICATION_REQUEST:
423 case OPUS_GET_BANDWIDTH_REQUEST:
424 case OPUS_GET_COMPLEXITY_REQUEST:
425 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
426 case OPUS_GET_DTX_REQUEST:
427 case OPUS_GET_VOICE_RATIO_REQUEST:
428 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
429 case OPUS_GET_SIGNAL_REQUEST:
430 case OPUS_GET_LOOKAHEAD_REQUEST:
431 case OPUS_GET_SAMPLE_RATE_REQUEST:
432 case OPUS_GET_INBAND_FEC_REQUEST:
433 case OPUS_GET_FORCE_CHANNELS_REQUEST:
434 {
435 OpusEncoder *enc;
436 /* For int32* GET params, just query the first stream */
437 opus_int32 *value = va_arg(ap, opus_int32*);
438 enc = (OpusEncoder*)ptr;
439 ret = opus_encoder_ctl(enc, request, value);
440 }
441 break;
442 case OPUS_GET_FINAL_RANGE_REQUEST:
443 {
444 int s;
445 opus_uint32 *value = va_arg(ap, opus_uint32*);
446 opus_uint32 tmp;
447 *value=0;
448 for (s=0;s<st->layout.nb_streams;s++)
449 {
450 OpusEncoder *enc;
451 enc = (OpusEncoder*)ptr;
452 if (s < st->layout.nb_coupled_streams)
453 ptr += align(coupled_size);
454 else
455 ptr += align(mono_size);
456 ret = opus_encoder_ctl(enc, request, &tmp);
457 if (ret != OPUS_OK) break;
458 *value ^= tmp;
459 }
460 }
461 break;
462 case OPUS_SET_LSB_DEPTH_REQUEST:
463 case OPUS_SET_COMPLEXITY_REQUEST:
464 case OPUS_SET_VBR_REQUEST:
465 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
466 case OPUS_SET_BANDWIDTH_REQUEST:
467 case OPUS_SET_SIGNAL_REQUEST:
468 case OPUS_SET_APPLICATION_REQUEST:
469 case OPUS_SET_INBAND_FEC_REQUEST:
470 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
471 case OPUS_SET_DTX_REQUEST:
472 case OPUS_SET_FORCE_MODE_REQUEST:
473 case OPUS_SET_FORCE_CHANNELS_REQUEST:
474 {
475 int s;
476 /* This works for int32 params */
477 opus_int32 value = va_arg(ap, opus_int32);
478 for (s=0;s<st->layout.nb_streams;s++)
479 {
480 OpusEncoder *enc;
481
482 enc = (OpusEncoder*)ptr;
483 if (s < st->layout.nb_coupled_streams)
484 ptr += align(coupled_size);
485 else
486 ptr += align(mono_size);
487 ret = opus_encoder_ctl(enc, request, value);
488 if (ret != OPUS_OK)
489 break;
490 }
491 }
492 break;
493 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
494 {
495 int s;
496 opus_int32 stream_id;
497 OpusEncoder **value;
498 stream_id = va_arg(ap, opus_int32);
499 if (stream_id<0 || stream_id >= st->layout.nb_streams)
500 ret = OPUS_BAD_ARG;
501 value = va_arg(ap, OpusEncoder**);
502 for (s=0;s<stream_id;s++)
503 {
504 if (s < st->layout.nb_coupled_streams)
505 ptr += align(coupled_size);
506 else
507 ptr += align(mono_size);
508 }
509 *value = (OpusEncoder*)ptr;
510 }
511 break;
512 default:
513 ret = OPUS_UNIMPLEMENTED;
514 break;
515 }
516
517 va_end(ap);
518 return ret;
519}
520
521void opus_multistream_encoder_destroy(OpusMSEncoder *st)
522{
523 opus_free(st);
524}
525
526