blob: c5fb3669115662ae0c5cbd3b18530f7a803c97f8 [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;
Jean-Marc Valin74483662012-12-17 16:23:42 -050042 int variable_duration;
43 opus_int32 bitrate_bps;
44 opus_val32 subframe_mem[3];
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050045 /* Encoder states go here */
46};
47
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050048
49static int validate_encoder_layout(const ChannelLayout *layout)
50{
51 int s;
52 for (s=0;s<layout->nb_streams;s++)
53 {
54 if (s < layout->nb_coupled_streams)
55 {
56 if (get_left_channel(layout, s, -1)==-1)
57 return 0;
58 if (get_right_channel(layout, s, -1)==-1)
59 return 0;
60 } else {
61 if (get_mono_channel(layout, s, -1)==-1)
62 return 0;
63 }
64 }
65 return 1;
66}
67
68
69opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
70{
71 int coupled_size;
72 int mono_size;
73
74 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
75 coupled_size = opus_encoder_get_size(2);
76 mono_size = opus_encoder_get_size(1);
77 return align(sizeof(OpusMSEncoder))
78 + nb_coupled_streams * align(coupled_size)
79 + (nb_streams-nb_coupled_streams) * align(mono_size);
80}
81
82
83
84int opus_multistream_encoder_init(
85 OpusMSEncoder *st,
86 opus_int32 Fs,
87 int channels,
88 int streams,
89 int coupled_streams,
90 const unsigned char *mapping,
91 int application
92)
93{
94 int coupled_size;
95 int mono_size;
96 int i, ret;
97 char *ptr;
98
99 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
100 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
101 return OPUS_BAD_ARG;
102
103 st->layout.nb_channels = channels;
104 st->layout.nb_streams = streams;
105 st->layout.nb_coupled_streams = coupled_streams;
106
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500107 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500108 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 Valin10a34a52012-12-20 00:23:01 -0500188#ifndef FIXED_POINT
189 , downmix_func downmix
190#endif
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500191)
192{
193 opus_int32 Fs;
194 int coupled_size;
195 int mono_size;
196 int s;
197 char *ptr;
198 int tot_size;
199 VARDECL(opus_val16, buf);
200 unsigned char tmp_data[MS_FRAME_TMP];
201 OpusRepacketizer rp;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500202 int orig_frame_size;
203 int coded_channels;
204 opus_int32 channel_rate;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500205 ALLOC_STACK;
206
207 ptr = (char*)st + align(sizeof(OpusMSEncoder));
208 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500209
210 if (400*frame_size < Fs)
211 {
212 RESTORE_STACK;
213 return OPUS_BAD_ARG;
214 }
215 orig_frame_size = IMIN(frame_size,Fs/50);
216 if (st->variable_duration)
217 {
218 int LM = 3;
219 int channels;
220 opus_int32 delay_compensation;
221
222 channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
223 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
224 delay_compensation -= Fs/400;
225#ifndef FIXED_POINT
226 LM = optimize_framesize(pcm, frame_size, channels, Fs, st->bitrate_bps,
Jean-Marc Valin10a34a52012-12-20 00:23:01 -0500227 0.f, st->subframe_mem, delay_compensation, downmix);
Jean-Marc Valin74483662012-12-17 16:23:42 -0500228#endif
229 while ((Fs/400<<LM)>frame_size)
230 LM--;
231 frame_size = (Fs/400<<LM);
232 }
233
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500234 /* Validate frame_size before using it to allocate stack space.
235 This mirrors the checks in opus_encode[_float](). */
236 if (400*frame_size != Fs && 200*frame_size != Fs &&
237 100*frame_size != Fs && 50*frame_size != Fs &&
238 25*frame_size != Fs && 50*frame_size != 3*Fs)
239 {
240 RESTORE_STACK;
241 return OPUS_BAD_ARG;
242 }
243 ALLOC(buf, 2*frame_size, opus_val16);
244 coupled_size = opus_encoder_get_size(2);
245 mono_size = opus_encoder_get_size(1);
246
247 if (max_data_bytes < 4*st->layout.nb_streams-1)
248 {
249 RESTORE_STACK;
250 return OPUS_BUFFER_TOO_SMALL;
251 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500252
253 /* Compute bitrate allocation between streams (this could be a lot better) */
254 coded_channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500255 if (st->bitrate_bps==OPUS_AUTO)
256 {
257 channel_rate = Fs+60*Fs/orig_frame_size;
258 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
259 {
260 channel_rate = 300000;
261 } else {
262 channel_rate = st->bitrate_bps/coded_channels;
263 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500264#ifndef FIXED_POINT
265 if (st->variable_duration && orig_frame_size != frame_size)
266 {
267 opus_int32 bonus;
268 bonus = 60*(48000/frame_size-48000/orig_frame_size);
269 channel_rate += bonus;
270 }
271#endif
272 ptr = (char*)st + align(sizeof(OpusMSEncoder));
273 for (s=0;s<st->layout.nb_streams;s++)
274 {
275 OpusEncoder *enc;
276 enc = (OpusEncoder*)ptr;
277 if (s < st->layout.nb_coupled_streams)
278 ptr += align(coupled_size);
279 else
280 ptr += align(mono_size);
281 opus_encoder_ctl(enc, OPUS_SET_BITRATE(channel_rate * (s < st->layout.nb_coupled_streams ? 2 : 1)));
282 }
283
284 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500285 /* Counting ToC */
286 tot_size = 0;
287 for (s=0;s<st->layout.nb_streams;s++)
288 {
289 OpusEncoder *enc;
290 int len;
291 int curr_max;
292
293 opus_repacketizer_init(&rp);
294 enc = (OpusEncoder*)ptr;
295 if (s < st->layout.nb_coupled_streams)
296 {
297 int left, right;
298 left = get_left_channel(&st->layout, s, -1);
299 right = get_right_channel(&st->layout, s, -1);
300 (*copy_channel_in)(buf, 2,
301 pcm, st->layout.nb_channels, left, frame_size);
302 (*copy_channel_in)(buf+1, 2,
303 pcm, st->layout.nb_channels, right, frame_size);
304 ptr += align(coupled_size);
305 } else {
306 int chan = get_mono_channel(&st->layout, s, -1);
307 (*copy_channel_in)(buf, 1,
308 pcm, st->layout.nb_channels, chan, frame_size);
309 ptr += align(mono_size);
310 }
311 /* number of bytes left (+Toc) */
312 curr_max = max_data_bytes - tot_size;
313 /* Reserve three bytes for the last stream and four for the others */
314 curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
315 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500316 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500317 if (len<0)
318 {
319 RESTORE_STACK;
320 return len;
321 }
322 /* We need to use the repacketizer to add the self-delimiting lengths
323 while taking into account the fact that the encoder can now return
324 more than one frame at a time (e.g. 60 ms CELT-only) */
325 opus_repacketizer_cat(&rp, tmp_data, len);
326 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);
327 data += len;
328 tot_size += len;
329 }
330 RESTORE_STACK;
331 return tot_size;
332
333}
334
335#if !defined(DISABLE_FLOAT_API)
336static void opus_copy_channel_in_float(
337 opus_val16 *dst,
338 int dst_stride,
339 const void *src,
340 int src_stride,
341 int src_channel,
342 int frame_size
343)
344{
345 const float *float_src;
346 int i;
347 float_src = (const float *)src;
348 for (i=0;i<frame_size;i++)
349#if defined(FIXED_POINT)
350 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
351#else
352 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
353#endif
354}
355#endif
356
357static void opus_copy_channel_in_short(
358 opus_val16 *dst,
359 int dst_stride,
360 const void *src,
361 int src_stride,
362 int src_channel,
363 int frame_size
364)
365{
366 const opus_int16 *short_src;
367 int i;
368 short_src = (const opus_int16 *)src;
369 for (i=0;i<frame_size;i++)
370#if defined(FIXED_POINT)
371 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
372#else
373 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
374#endif
375}
376
377#ifdef FIXED_POINT
378int opus_multistream_encode(
379 OpusMSEncoder *st,
380 const opus_val16 *pcm,
381 int frame_size,
382 unsigned char *data,
383 opus_int32 max_data_bytes
384)
385{
386 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500387 pcm, frame_size, data, max_data_bytes, 16);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500388}
389
390#ifndef DISABLE_FLOAT_API
391int opus_multistream_encode_float(
392 OpusMSEncoder *st,
393 const float *pcm,
394 int frame_size,
395 unsigned char *data,
396 opus_int32 max_data_bytes
397)
398{
399 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500400 pcm, frame_size, data, max_data_bytes, 16);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500401}
402#endif
403
404#else
405
406int opus_multistream_encode_float
407(
408 OpusMSEncoder *st,
409 const opus_val16 *pcm,
410 int frame_size,
411 unsigned char *data,
412 opus_int32 max_data_bytes
413)
414{
415 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valin10a34a52012-12-20 00:23:01 -0500416 pcm, frame_size, data, max_data_bytes, 24, downmix_float);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500417}
418
419int opus_multistream_encode(
420 OpusMSEncoder *st,
421 const opus_int16 *pcm,
422 int frame_size,
423 unsigned char *data,
424 opus_int32 max_data_bytes
425)
426{
427 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valin10a34a52012-12-20 00:23:01 -0500428 pcm, frame_size, data, max_data_bytes, 16, downmix_int);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500429}
430#endif
431
432int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
433{
434 va_list ap;
435 int coupled_size, mono_size;
436 char *ptr;
437 int ret = OPUS_OK;
438
439 va_start(ap, request);
440
441 coupled_size = opus_encoder_get_size(2);
442 mono_size = opus_encoder_get_size(1);
443 ptr = (char*)st + align(sizeof(OpusMSEncoder));
444 switch (request)
445 {
446 case OPUS_SET_BITRATE_REQUEST:
447 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500448 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500449 if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
450 goto bad_arg;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500451 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500452 }
453 break;
454 case OPUS_GET_BITRATE_REQUEST:
455 {
456 int s;
457 opus_int32 *value = va_arg(ap, opus_int32*);
458 *value = 0;
459 for (s=0;s<st->layout.nb_streams;s++)
460 {
461 opus_int32 rate;
462 OpusEncoder *enc;
463 enc = (OpusEncoder*)ptr;
464 if (s < st->layout.nb_coupled_streams)
465 ptr += align(coupled_size);
466 else
467 ptr += align(mono_size);
468 opus_encoder_ctl(enc, request, &rate);
469 *value += rate;
470 }
471 }
472 break;
473 case OPUS_GET_LSB_DEPTH_REQUEST:
474 case OPUS_GET_VBR_REQUEST:
475 case OPUS_GET_APPLICATION_REQUEST:
476 case OPUS_GET_BANDWIDTH_REQUEST:
477 case OPUS_GET_COMPLEXITY_REQUEST:
478 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
479 case OPUS_GET_DTX_REQUEST:
480 case OPUS_GET_VOICE_RATIO_REQUEST:
481 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
482 case OPUS_GET_SIGNAL_REQUEST:
483 case OPUS_GET_LOOKAHEAD_REQUEST:
484 case OPUS_GET_SAMPLE_RATE_REQUEST:
485 case OPUS_GET_INBAND_FEC_REQUEST:
486 case OPUS_GET_FORCE_CHANNELS_REQUEST:
487 {
488 OpusEncoder *enc;
489 /* For int32* GET params, just query the first stream */
490 opus_int32 *value = va_arg(ap, opus_int32*);
491 enc = (OpusEncoder*)ptr;
492 ret = opus_encoder_ctl(enc, request, value);
493 }
494 break;
495 case OPUS_GET_FINAL_RANGE_REQUEST:
496 {
497 int s;
498 opus_uint32 *value = va_arg(ap, opus_uint32*);
499 opus_uint32 tmp;
500 *value=0;
501 for (s=0;s<st->layout.nb_streams;s++)
502 {
503 OpusEncoder *enc;
504 enc = (OpusEncoder*)ptr;
505 if (s < st->layout.nb_coupled_streams)
506 ptr += align(coupled_size);
507 else
508 ptr += align(mono_size);
509 ret = opus_encoder_ctl(enc, request, &tmp);
510 if (ret != OPUS_OK) break;
511 *value ^= tmp;
512 }
513 }
514 break;
515 case OPUS_SET_LSB_DEPTH_REQUEST:
516 case OPUS_SET_COMPLEXITY_REQUEST:
517 case OPUS_SET_VBR_REQUEST:
518 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
519 case OPUS_SET_BANDWIDTH_REQUEST:
520 case OPUS_SET_SIGNAL_REQUEST:
521 case OPUS_SET_APPLICATION_REQUEST:
522 case OPUS_SET_INBAND_FEC_REQUEST:
523 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
524 case OPUS_SET_DTX_REQUEST:
525 case OPUS_SET_FORCE_MODE_REQUEST:
526 case OPUS_SET_FORCE_CHANNELS_REQUEST:
527 {
528 int s;
529 /* This works for int32 params */
530 opus_int32 value = va_arg(ap, opus_int32);
531 for (s=0;s<st->layout.nb_streams;s++)
532 {
533 OpusEncoder *enc;
534
535 enc = (OpusEncoder*)ptr;
536 if (s < st->layout.nb_coupled_streams)
537 ptr += align(coupled_size);
538 else
539 ptr += align(mono_size);
540 ret = opus_encoder_ctl(enc, request, value);
541 if (ret != OPUS_OK)
542 break;
543 }
544 }
545 break;
546 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
547 {
548 int s;
549 opus_int32 stream_id;
550 OpusEncoder **value;
551 stream_id = va_arg(ap, opus_int32);
552 if (stream_id<0 || stream_id >= st->layout.nb_streams)
553 ret = OPUS_BAD_ARG;
554 value = va_arg(ap, OpusEncoder**);
555 for (s=0;s<stream_id;s++)
556 {
557 if (s < st->layout.nb_coupled_streams)
558 ptr += align(coupled_size);
559 else
560 ptr += align(mono_size);
561 }
562 *value = (OpusEncoder*)ptr;
563 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500564 break;
565 case OPUS_SET_EXPERT_VARIABLE_DURATION_REQUEST:
566 {
567 opus_int32 value = va_arg(ap, opus_int32);
568 if (value<0 || value>1)
569 goto bad_arg;
570 st->variable_duration = value;
571 }
572 break;
573 case OPUS_GET_EXPERT_VARIABLE_DURATION_REQUEST:
574 {
575 opus_int32 *value = va_arg(ap, opus_int32*);
576 *value = st->variable_duration;
577 }
578 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500579 default:
580 ret = OPUS_UNIMPLEMENTED;
581 break;
582 }
583
584 va_end(ap);
585 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500586bad_arg:
587 va_end(ap);
588 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500589}
590
591void opus_multistream_encoder_destroy(OpusMSEncoder *st)
592{
593 opus_free(st);
594}
595
596