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