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