blob: 1b41c651189385ad800af70eb0b4cb97f6f751df [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 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;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500252 if (st->bitrate_bps==OPUS_AUTO)
253 {
254 channel_rate = Fs+60*Fs/orig_frame_size;
255 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
256 {
257 channel_rate = 300000;
258 } else {
259 channel_rate = st->bitrate_bps/coded_channels;
260 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500261#ifndef FIXED_POINT
262 if (st->variable_duration && orig_frame_size != frame_size)
263 {
264 opus_int32 bonus;
265 bonus = 60*(48000/frame_size-48000/orig_frame_size);
266 channel_rate += bonus;
267 }
268#endif
269 ptr = (char*)st + align(sizeof(OpusMSEncoder));
270 for (s=0;s<st->layout.nb_streams;s++)
271 {
272 OpusEncoder *enc;
273 enc = (OpusEncoder*)ptr;
274 if (s < st->layout.nb_coupled_streams)
275 ptr += align(coupled_size);
276 else
277 ptr += align(mono_size);
278 opus_encoder_ctl(enc, OPUS_SET_BITRATE(channel_rate * (s < st->layout.nb_coupled_streams ? 2 : 1)));
279 }
280
281 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500282 /* Counting ToC */
283 tot_size = 0;
284 for (s=0;s<st->layout.nb_streams;s++)
285 {
286 OpusEncoder *enc;
287 int len;
288 int curr_max;
289
290 opus_repacketizer_init(&rp);
291 enc = (OpusEncoder*)ptr;
292 if (s < st->layout.nb_coupled_streams)
293 {
294 int left, right;
295 left = get_left_channel(&st->layout, s, -1);
296 right = get_right_channel(&st->layout, s, -1);
297 (*copy_channel_in)(buf, 2,
298 pcm, st->layout.nb_channels, left, frame_size);
299 (*copy_channel_in)(buf+1, 2,
300 pcm, st->layout.nb_channels, right, frame_size);
301 ptr += align(coupled_size);
302 } else {
303 int chan = get_mono_channel(&st->layout, s, -1);
304 (*copy_channel_in)(buf, 1,
305 pcm, st->layout.nb_channels, chan, frame_size);
306 ptr += align(mono_size);
307 }
308 /* number of bytes left (+Toc) */
309 curr_max = max_data_bytes - tot_size;
310 /* Reserve three bytes for the last stream and four for the others */
311 curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
312 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500313 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500314 if (len<0)
315 {
316 RESTORE_STACK;
317 return len;
318 }
319 /* We need to use the repacketizer to add the self-delimiting lengths
320 while taking into account the fact that the encoder can now return
321 more than one frame at a time (e.g. 60 ms CELT-only) */
322 opus_repacketizer_cat(&rp, tmp_data, len);
323 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);
324 data += len;
325 tot_size += len;
326 }
327 RESTORE_STACK;
328 return tot_size;
329
330}
331
332#if !defined(DISABLE_FLOAT_API)
333static void opus_copy_channel_in_float(
334 opus_val16 *dst,
335 int dst_stride,
336 const void *src,
337 int src_stride,
338 int src_channel,
339 int frame_size
340)
341{
342 const float *float_src;
343 int i;
344 float_src = (const float *)src;
345 for (i=0;i<frame_size;i++)
346#if defined(FIXED_POINT)
347 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
348#else
349 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
350#endif
351}
352#endif
353
354static void opus_copy_channel_in_short(
355 opus_val16 *dst,
356 int dst_stride,
357 const void *src,
358 int src_stride,
359 int src_channel,
360 int frame_size
361)
362{
363 const opus_int16 *short_src;
364 int i;
365 short_src = (const opus_int16 *)src;
366 for (i=0;i<frame_size;i++)
367#if defined(FIXED_POINT)
368 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
369#else
370 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
371#endif
372}
373
374#ifdef FIXED_POINT
375int opus_multistream_encode(
376 OpusMSEncoder *st,
377 const opus_val16 *pcm,
378 int frame_size,
379 unsigned char *data,
380 opus_int32 max_data_bytes
381)
382{
383 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500384 pcm, frame_size, data, max_data_bytes, 16);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500385}
386
387#ifndef DISABLE_FLOAT_API
388int opus_multistream_encode_float(
389 OpusMSEncoder *st,
390 const float *pcm,
391 int frame_size,
392 unsigned char *data,
393 opus_int32 max_data_bytes
394)
395{
396 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500397 pcm, frame_size, data, max_data_bytes, 16);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500398}
399#endif
400
401#else
402
403int opus_multistream_encode_float
404(
405 OpusMSEncoder *st,
406 const opus_val16 *pcm,
407 int frame_size,
408 unsigned char *data,
409 opus_int32 max_data_bytes
410)
411{
412 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500413 pcm, frame_size, data, max_data_bytes, 24);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500414}
415
416int opus_multistream_encode(
417 OpusMSEncoder *st,
418 const opus_int16 *pcm,
419 int frame_size,
420 unsigned char *data,
421 opus_int32 max_data_bytes
422)
423{
424 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500425 pcm, frame_size, data, max_data_bytes, 16);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500426}
427#endif
428
429int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
430{
431 va_list ap;
432 int coupled_size, mono_size;
433 char *ptr;
434 int ret = OPUS_OK;
435
436 va_start(ap, request);
437
438 coupled_size = opus_encoder_get_size(2);
439 mono_size = opus_encoder_get_size(1);
440 ptr = (char*)st + align(sizeof(OpusMSEncoder));
441 switch (request)
442 {
443 case OPUS_SET_BITRATE_REQUEST:
444 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500445 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500446 if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
447 goto bad_arg;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500448 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500449 }
450 break;
451 case OPUS_GET_BITRATE_REQUEST:
452 {
453 int s;
454 opus_int32 *value = va_arg(ap, opus_int32*);
455 *value = 0;
456 for (s=0;s<st->layout.nb_streams;s++)
457 {
458 opus_int32 rate;
459 OpusEncoder *enc;
460 enc = (OpusEncoder*)ptr;
461 if (s < st->layout.nb_coupled_streams)
462 ptr += align(coupled_size);
463 else
464 ptr += align(mono_size);
465 opus_encoder_ctl(enc, request, &rate);
466 *value += rate;
467 }
468 }
469 break;
470 case OPUS_GET_LSB_DEPTH_REQUEST:
471 case OPUS_GET_VBR_REQUEST:
472 case OPUS_GET_APPLICATION_REQUEST:
473 case OPUS_GET_BANDWIDTH_REQUEST:
474 case OPUS_GET_COMPLEXITY_REQUEST:
475 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
476 case OPUS_GET_DTX_REQUEST:
477 case OPUS_GET_VOICE_RATIO_REQUEST:
478 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
479 case OPUS_GET_SIGNAL_REQUEST:
480 case OPUS_GET_LOOKAHEAD_REQUEST:
481 case OPUS_GET_SAMPLE_RATE_REQUEST:
482 case OPUS_GET_INBAND_FEC_REQUEST:
483 case OPUS_GET_FORCE_CHANNELS_REQUEST:
484 {
485 OpusEncoder *enc;
486 /* For int32* GET params, just query the first stream */
487 opus_int32 *value = va_arg(ap, opus_int32*);
488 enc = (OpusEncoder*)ptr;
489 ret = opus_encoder_ctl(enc, request, value);
490 }
491 break;
492 case OPUS_GET_FINAL_RANGE_REQUEST:
493 {
494 int s;
495 opus_uint32 *value = va_arg(ap, opus_uint32*);
496 opus_uint32 tmp;
497 *value=0;
498 for (s=0;s<st->layout.nb_streams;s++)
499 {
500 OpusEncoder *enc;
501 enc = (OpusEncoder*)ptr;
502 if (s < st->layout.nb_coupled_streams)
503 ptr += align(coupled_size);
504 else
505 ptr += align(mono_size);
506 ret = opus_encoder_ctl(enc, request, &tmp);
507 if (ret != OPUS_OK) break;
508 *value ^= tmp;
509 }
510 }
511 break;
512 case OPUS_SET_LSB_DEPTH_REQUEST:
513 case OPUS_SET_COMPLEXITY_REQUEST:
514 case OPUS_SET_VBR_REQUEST:
515 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
516 case OPUS_SET_BANDWIDTH_REQUEST:
517 case OPUS_SET_SIGNAL_REQUEST:
518 case OPUS_SET_APPLICATION_REQUEST:
519 case OPUS_SET_INBAND_FEC_REQUEST:
520 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
521 case OPUS_SET_DTX_REQUEST:
522 case OPUS_SET_FORCE_MODE_REQUEST:
523 case OPUS_SET_FORCE_CHANNELS_REQUEST:
524 {
525 int s;
526 /* This works for int32 params */
527 opus_int32 value = va_arg(ap, opus_int32);
528 for (s=0;s<st->layout.nb_streams;s++)
529 {
530 OpusEncoder *enc;
531
532 enc = (OpusEncoder*)ptr;
533 if (s < st->layout.nb_coupled_streams)
534 ptr += align(coupled_size);
535 else
536 ptr += align(mono_size);
537 ret = opus_encoder_ctl(enc, request, value);
538 if (ret != OPUS_OK)
539 break;
540 }
541 }
542 break;
543 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
544 {
545 int s;
546 opus_int32 stream_id;
547 OpusEncoder **value;
548 stream_id = va_arg(ap, opus_int32);
549 if (stream_id<0 || stream_id >= st->layout.nb_streams)
550 ret = OPUS_BAD_ARG;
551 value = va_arg(ap, OpusEncoder**);
552 for (s=0;s<stream_id;s++)
553 {
554 if (s < st->layout.nb_coupled_streams)
555 ptr += align(coupled_size);
556 else
557 ptr += align(mono_size);
558 }
559 *value = (OpusEncoder*)ptr;
560 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500561 break;
562 case OPUS_SET_EXPERT_VARIABLE_DURATION_REQUEST:
563 {
564 opus_int32 value = va_arg(ap, opus_int32);
565 if (value<0 || value>1)
566 goto bad_arg;
567 st->variable_duration = value;
568 }
569 break;
570 case OPUS_GET_EXPERT_VARIABLE_DURATION_REQUEST:
571 {
572 opus_int32 *value = va_arg(ap, opus_int32*);
573 *value = st->variable_duration;
574 }
575 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500576 default:
577 ret = OPUS_UNIMPLEMENTED;
578 break;
579 }
580
581 va_end(ap);
582 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500583bad_arg:
584 va_end(ap);
585 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500586}
587
588void opus_multistream_encoder_destroy(OpusMSEncoder *st)
589{
590 opus_free(st);
591}
592
593