blob: d94aa70516d3597cf5860a2cc8e6dc43fa515f01 [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"
Jean-Marc Valin51f4a322013-02-20 04:08:04 -050039#include "analysis.h"
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050040
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -040041typedef struct {
42 int nb_streams;
43 int nb_coupled_streams;
44 unsigned char mapping[8];
45} VorbisLayout;
46
47/* Index is nb_channel-1*/
48static const VorbisLayout vorbis_mappings[8] = {
49 {1, 0, {0}}, /* 1: mono */
50 {1, 1, {0, 1}}, /* 2: stereo */
51 {2, 1, {0, 2, 1}}, /* 3: 1-d surround */
52 {2, 2, {0, 1, 2, 3}}, /* 4: quadraphonic surround */
53 {3, 2, {0, 4, 1, 2, 3}}, /* 5: 5-channel surround */
54 {4, 2, {0, 4, 1, 2, 3, 5}}, /* 6: 5.1 surround */
55 {4, 3, {0, 4, 1, 2, 3, 5, 6}}, /* 7: 6.1 surround */
56 {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */
57};
58
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050059struct OpusMSEncoder {
Jean-Marc Valin51f4a322013-02-20 04:08:04 -050060 TonalityAnalysisState analysis;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050061 ChannelLayout layout;
Jean-Marc Valin1b723862013-04-25 21:34:04 -040062 int lfe_stream;
Jean-Marc Valin74483662012-12-17 16:23:42 -050063 int variable_duration;
64 opus_int32 bitrate_bps;
65 opus_val32 subframe_mem[3];
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050066 /* Encoder states go here */
67};
68
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050069
70static int validate_encoder_layout(const ChannelLayout *layout)
71{
72 int s;
73 for (s=0;s<layout->nb_streams;s++)
74 {
75 if (s < layout->nb_coupled_streams)
76 {
77 if (get_left_channel(layout, s, -1)==-1)
78 return 0;
79 if (get_right_channel(layout, s, -1)==-1)
80 return 0;
81 } else {
82 if (get_mono_channel(layout, s, -1)==-1)
83 return 0;
84 }
85 }
86 return 1;
87}
88
89
90opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
91{
92 int coupled_size;
93 int mono_size;
94
95 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
96 coupled_size = opus_encoder_get_size(2);
97 mono_size = opus_encoder_get_size(1);
98 return align(sizeof(OpusMSEncoder))
99 + nb_coupled_streams * align(coupled_size)
100 + (nb_streams-nb_coupled_streams) * align(mono_size);
101}
102
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400103opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
104{
105 int nb_streams;
106 int nb_coupled_streams;
107
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400108 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400109 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400110 if (channels==1)
111 {
112 nb_streams=1;
113 nb_coupled_streams=0;
114 } else if (channels==2)
115 {
116 nb_streams=1;
117 nb_coupled_streams=1;
118 } else
119 return 0;
120 } else if (mapping_family==1 && channels<=8 && channels>=1)
121 {
122 nb_streams=vorbis_mappings[channels-1].nb_streams;
123 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
124 } else if (mapping_family==255)
125 {
126 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400127 nb_coupled_streams=0;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400128 } else
129 return 0;
130 return opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
131}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500132
133
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400134static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500135 OpusMSEncoder *st,
136 opus_int32 Fs,
137 int channels,
138 int streams,
139 int coupled_streams,
140 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400141 int application,
142 int surround
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500143)
144{
145 int coupled_size;
146 int mono_size;
147 int i, ret;
148 char *ptr;
149
150 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
151 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
152 return OPUS_BAD_ARG;
153
154 st->layout.nb_channels = channels;
155 st->layout.nb_streams = streams;
156 st->layout.nb_coupled_streams = coupled_streams;
Jean-Marc Valinb0429352013-05-05 02:22:06 -0400157 st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
158 OPUS_CLEAR(&st->analysis,1);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400159 if (!surround)
160 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500161 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500162 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500163 for (i=0;i<st->layout.nb_channels;i++)
164 st->layout.mapping[i] = mapping[i];
165 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
166 return OPUS_BAD_ARG;
167 ptr = (char*)st + align(sizeof(OpusMSEncoder));
168 coupled_size = opus_encoder_get_size(2);
169 mono_size = opus_encoder_get_size(1);
170
171 for (i=0;i<st->layout.nb_coupled_streams;i++)
172 {
173 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400174 if (i==st->lfe_stream)
175 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500176 if(ret!=OPUS_OK)return ret;
177 ptr += align(coupled_size);
178 }
179 for (;i<st->layout.nb_streams;i++)
180 {
181 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400182 if (i==st->lfe_stream)
183 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500184 if(ret!=OPUS_OK)return ret;
185 ptr += align(mono_size);
186 }
187 return OPUS_OK;
188}
189
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400190int opus_multistream_encoder_init(
191 OpusMSEncoder *st,
192 opus_int32 Fs,
193 int channels,
194 int streams,
195 int coupled_streams,
196 const unsigned char *mapping,
197 int application
198)
199{
200 return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0);
201}
202
203int opus_multistream_surround_encoder_init(
204 OpusMSEncoder *st,
205 opus_int32 Fs,
206 int channels,
207 int mapping_family,
208 int *streams,
209 int *coupled_streams,
210 unsigned char *mapping,
211 int application
212)
213{
214 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400215 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400216 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400217 if (channels==1)
218 {
219 *streams=1;
220 *coupled_streams=0;
221 mapping[0]=0;
222 } else if (channels==2)
223 {
224 *streams=1;
225 *coupled_streams=1;
226 mapping[0]=0;
227 mapping[1]=1;
228 } else
229 return OPUS_UNIMPLEMENTED;
230 } else if (mapping_family==1 && channels<=8 && channels>=1)
231 {
232 int i;
233 *streams=vorbis_mappings[channels-1].nb_streams;
234 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
235 for (i=0;i<channels;i++)
236 mapping[i] = vorbis_mappings[channels-1].mapping[i];
237 if (channels>=6)
238 st->lfe_stream = *streams-1;
239 } else if (mapping_family==255)
240 {
241 int i;
242 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400243 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400244 for(i=0;i<channels;i++)
245 mapping[i] = i;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400246 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400247 return OPUS_UNIMPLEMENTED;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400248 opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams, mapping, application, 1);
249 return OPUS_OK;
250}
251
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500252OpusMSEncoder *opus_multistream_encoder_create(
253 opus_int32 Fs,
254 int channels,
255 int streams,
256 int coupled_streams,
257 const unsigned char *mapping,
258 int application,
259 int *error
260)
261{
262 int ret;
263 OpusMSEncoder *st;
264 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
265 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
266 {
267 if (error)
268 *error = OPUS_BAD_ARG;
269 return NULL;
270 }
271 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
272 if (st==NULL)
273 {
274 if (error)
275 *error = OPUS_ALLOC_FAIL;
276 return NULL;
277 }
278 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
279 if (ret != OPUS_OK)
280 {
281 opus_free(st);
282 st = NULL;
283 }
284 if (error)
285 *error = ret;
286 return st;
287}
288
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400289OpusMSEncoder *opus_multistream_surround_encoder_create(
290 opus_int32 Fs,
291 int channels,
292 int mapping_family,
293 int *streams,
294 int *coupled_streams,
295 unsigned char *mapping,
296 int application,
297 int *error
298)
299{
300 int ret;
301 OpusMSEncoder *st;
302 if ((channels>255) || (channels<1))
303 {
304 if (error)
305 *error = OPUS_BAD_ARG;
306 return NULL;
307 }
308 st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family));
309 if (st==NULL)
310 {
311 if (error)
312 *error = OPUS_ALLOC_FAIL;
313 return NULL;
314 }
315 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
316 if (ret != OPUS_OK)
317 {
318 opus_free(st);
319 st = NULL;
320 }
321 if (error)
322 *error = ret;
323 return st;
324}
325
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500326typedef void (*opus_copy_channel_in_func)(
327 opus_val16 *dst,
328 int dst_stride,
329 const void *src,
330 int src_stride,
331 int src_channel,
332 int frame_size
333);
334
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400335static void surround_rate_allocation(
336 OpusMSEncoder *st,
337 opus_int32 *rate,
338 int frame_size
339 )
340{
341 int i;
342 opus_int32 channel_rate;
343 opus_int32 Fs;
344 char *ptr;
345 int coupled_ratio; /* Q8 */
346 int lfe_ratio; /* Q8 */
347
348 ptr = (char*)st + align(sizeof(OpusMSEncoder));
349 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
350
351 /* Should depend on the bitrate, for now we assume coupled streams get 60% more bits than mono */
352 coupled_ratio = 410;
353 /* Should depend on the bitrate, for now we assume LFE gets 1/12 the bits of mono */
354 lfe_ratio = 32;
355
356 /* Compute bitrate allocation between streams */
357 if (st->bitrate_bps==OPUS_AUTO)
358 {
359 channel_rate = Fs+60*Fs/frame_size;
360 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
361 {
362 channel_rate = 300000;
363 } else {
364 int total = ((st->layout.nb_streams-st->layout.nb_coupled_streams-(st->lfe_stream!=-1))<<8) /* mono */
365 + coupled_ratio*st->layout.nb_coupled_streams /* stereo */
366 + (st->lfe_stream!=-1)*lfe_ratio;
Jean-Marc Valinb08c4ca2013-04-26 16:32:10 -0400367 channel_rate = 256*(st->bitrate_bps-2000)/total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400368 }
369#ifndef FIXED_POINT
370 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
371 {
372 opus_int32 bonus;
373 bonus = 60*(Fs/frame_size-50);
374 channel_rate += bonus;
375 }
376#endif
377
378 for (i=0;i<st->layout.nb_streams;i++)
379 {
380 if (i<st->layout.nb_coupled_streams)
381 rate[i] = channel_rate*coupled_ratio>>8;
382 else if (i!=st->lfe_stream)
383 rate[i] = channel_rate;
384 else
Jean-Marc Valinb08c4ca2013-04-26 16:32:10 -0400385 rate[i] = 2000+(channel_rate*lfe_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400386 }
387
388
389}
390
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500391/* Max size in case the encoder decides to return three frames */
392#define MS_FRAME_TMP (3*1275+7)
393static int opus_multistream_encode_native
394(
395 OpusMSEncoder *st,
396 opus_copy_channel_in_func copy_channel_in,
397 const void *pcm,
398 int frame_size,
399 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500400 opus_int32 max_data_bytes,
401 int lsb_depth
Jean-Marc Valin10a34a52012-12-20 00:23:01 -0500402#ifndef FIXED_POINT
403 , downmix_func downmix
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500404 , const void *pcm_analysis
Jean-Marc Valin10a34a52012-12-20 00:23:01 -0500405#endif
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500406)
407{
408 opus_int32 Fs;
409 int coupled_size;
410 int mono_size;
411 int s;
412 char *ptr;
413 int tot_size;
414 VARDECL(opus_val16, buf);
415 unsigned char tmp_data[MS_FRAME_TMP];
416 OpusRepacketizer rp;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500417 opus_int32 complexity;
418 AnalysisInfo analysis_info;
419 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400420 opus_int32 bitrates[256];
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500421 ALLOC_STACK;
422
423 ptr = (char*)st + align(sizeof(OpusMSEncoder));
424 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500425 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_COMPLEXITY(&complexity));
426 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500427
428 if (400*frame_size < Fs)
429 {
430 RESTORE_STACK;
431 return OPUS_BAD_ARG;
432 }
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500433#ifndef FIXED_POINT
434 analysis_info.valid = 0;
435 if (complexity >= 7 && Fs==48000)
Jean-Marc Valin74483662012-12-17 16:23:42 -0500436 {
Jean-Marc Valin74483662012-12-17 16:23:42 -0500437 opus_int32 delay_compensation;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500438 int channels;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500439
440 channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
441 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
442 delay_compensation -= Fs/400;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500443
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500444 frame_size = run_analysis(&st->analysis, celt_mode, pcm, pcm_analysis,
445 frame_size, st->variable_duration, channels, Fs, st->bitrate_bps, delay_compensation, lsb_depth, downmix, &analysis_info);
446 } else
447#endif
448 {
449 frame_size = frame_size_select(frame_size, st->variable_duration, Fs);
450 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500451 /* Validate frame_size before using it to allocate stack space.
452 This mirrors the checks in opus_encode[_float](). */
453 if (400*frame_size != Fs && 200*frame_size != Fs &&
454 100*frame_size != Fs && 50*frame_size != Fs &&
455 25*frame_size != Fs && 50*frame_size != 3*Fs)
456 {
457 RESTORE_STACK;
458 return OPUS_BAD_ARG;
459 }
460 ALLOC(buf, 2*frame_size, opus_val16);
461 coupled_size = opus_encoder_get_size(2);
462 mono_size = opus_encoder_get_size(1);
463
464 if (max_data_bytes < 4*st->layout.nb_streams-1)
465 {
466 RESTORE_STACK;
467 return OPUS_BUFFER_TOO_SMALL;
468 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500469
470 /* Compute bitrate allocation between streams (this could be a lot better) */
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400471 surround_rate_allocation(st, bitrates, frame_size);
472
Jean-Marc Valin74483662012-12-17 16:23:42 -0500473 ptr = (char*)st + align(sizeof(OpusMSEncoder));
474 for (s=0;s<st->layout.nb_streams;s++)
475 {
476 OpusEncoder *enc;
477 enc = (OpusEncoder*)ptr;
478 if (s < st->layout.nb_coupled_streams)
479 ptr += align(coupled_size);
480 else
481 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400482 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500483 }
484
485 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500486 /* Counting ToC */
487 tot_size = 0;
488 for (s=0;s<st->layout.nb_streams;s++)
489 {
490 OpusEncoder *enc;
491 int len;
492 int curr_max;
493
494 opus_repacketizer_init(&rp);
495 enc = (OpusEncoder*)ptr;
496 if (s < st->layout.nb_coupled_streams)
497 {
498 int left, right;
499 left = get_left_channel(&st->layout, s, -1);
500 right = get_right_channel(&st->layout, s, -1);
501 (*copy_channel_in)(buf, 2,
502 pcm, st->layout.nb_channels, left, frame_size);
503 (*copy_channel_in)(buf+1, 2,
504 pcm, st->layout.nb_channels, right, frame_size);
505 ptr += align(coupled_size);
506 } else {
507 int chan = get_mono_channel(&st->layout, s, -1);
508 (*copy_channel_in)(buf, 1,
509 pcm, st->layout.nb_channels, chan, frame_size);
510 ptr += align(mono_size);
511 }
512 /* number of bytes left (+Toc) */
513 curr_max = max_data_bytes - tot_size;
514 /* Reserve three bytes for the last stream and four for the others */
515 curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
516 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500517 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth
518#ifndef FIXED_POINT
519 , &analysis_info
520#endif
521 );
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500522 if (len<0)
523 {
524 RESTORE_STACK;
525 return len;
526 }
527 /* We need to use the repacketizer to add the self-delimiting lengths
528 while taking into account the fact that the encoder can now return
529 more than one frame at a time (e.g. 60 ms CELT-only) */
530 opus_repacketizer_cat(&rp, tmp_data, len);
531 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);
532 data += len;
533 tot_size += len;
534 }
535 RESTORE_STACK;
536 return tot_size;
537
538}
539
540#if !defined(DISABLE_FLOAT_API)
541static void opus_copy_channel_in_float(
542 opus_val16 *dst,
543 int dst_stride,
544 const void *src,
545 int src_stride,
546 int src_channel,
547 int frame_size
548)
549{
550 const float *float_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -0700551 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500552 float_src = (const float *)src;
553 for (i=0;i<frame_size;i++)
554#if defined(FIXED_POINT)
555 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
556#else
557 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
558#endif
559}
560#endif
561
562static void opus_copy_channel_in_short(
563 opus_val16 *dst,
564 int dst_stride,
565 const void *src,
566 int src_stride,
567 int src_channel,
568 int frame_size
569)
570{
571 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -0700572 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500573 short_src = (const opus_int16 *)src;
574 for (i=0;i<frame_size;i++)
575#if defined(FIXED_POINT)
576 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
577#else
578 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
579#endif
580}
581
582#ifdef FIXED_POINT
583int opus_multistream_encode(
584 OpusMSEncoder *st,
585 const opus_val16 *pcm,
586 int frame_size,
587 unsigned char *data,
588 opus_int32 max_data_bytes
589)
590{
591 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500592 pcm, frame_size, data, max_data_bytes, 16);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500593}
594
595#ifndef DISABLE_FLOAT_API
596int opus_multistream_encode_float(
597 OpusMSEncoder *st,
598 const float *pcm,
599 int frame_size,
600 unsigned char *data,
601 opus_int32 max_data_bytes
602)
603{
604 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500605 pcm, frame_size, data, max_data_bytes, 16);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500606}
607#endif
608
609#else
610
611int opus_multistream_encode_float
612(
613 OpusMSEncoder *st,
614 const opus_val16 *pcm,
615 int frame_size,
616 unsigned char *data,
617 opus_int32 max_data_bytes
618)
619{
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500620 int channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500621 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500622 pcm, frame_size, data, max_data_bytes, 24, downmix_float, pcm+channels*st->analysis.analysis_offset);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500623}
624
625int opus_multistream_encode(
626 OpusMSEncoder *st,
627 const opus_int16 *pcm,
628 int frame_size,
629 unsigned char *data,
630 opus_int32 max_data_bytes
631)
632{
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500633 int channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500634 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500635 pcm, frame_size, data, max_data_bytes, 16, downmix_int, pcm+channels*st->analysis.analysis_offset);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500636}
637#endif
638
639int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
640{
641 va_list ap;
642 int coupled_size, mono_size;
643 char *ptr;
644 int ret = OPUS_OK;
645
646 va_start(ap, request);
647
648 coupled_size = opus_encoder_get_size(2);
649 mono_size = opus_encoder_get_size(1);
650 ptr = (char*)st + align(sizeof(OpusMSEncoder));
651 switch (request)
652 {
653 case OPUS_SET_BITRATE_REQUEST:
654 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500655 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500656 if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
657 goto bad_arg;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500658 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500659 }
660 break;
661 case OPUS_GET_BITRATE_REQUEST:
662 {
663 int s;
664 opus_int32 *value = va_arg(ap, opus_int32*);
665 *value = 0;
666 for (s=0;s<st->layout.nb_streams;s++)
667 {
668 opus_int32 rate;
669 OpusEncoder *enc;
670 enc = (OpusEncoder*)ptr;
671 if (s < st->layout.nb_coupled_streams)
672 ptr += align(coupled_size);
673 else
674 ptr += align(mono_size);
675 opus_encoder_ctl(enc, request, &rate);
676 *value += rate;
677 }
678 }
679 break;
680 case OPUS_GET_LSB_DEPTH_REQUEST:
681 case OPUS_GET_VBR_REQUEST:
682 case OPUS_GET_APPLICATION_REQUEST:
683 case OPUS_GET_BANDWIDTH_REQUEST:
684 case OPUS_GET_COMPLEXITY_REQUEST:
685 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
686 case OPUS_GET_DTX_REQUEST:
687 case OPUS_GET_VOICE_RATIO_REQUEST:
688 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
689 case OPUS_GET_SIGNAL_REQUEST:
690 case OPUS_GET_LOOKAHEAD_REQUEST:
691 case OPUS_GET_SAMPLE_RATE_REQUEST:
692 case OPUS_GET_INBAND_FEC_REQUEST:
693 case OPUS_GET_FORCE_CHANNELS_REQUEST:
694 {
695 OpusEncoder *enc;
696 /* For int32* GET params, just query the first stream */
697 opus_int32 *value = va_arg(ap, opus_int32*);
698 enc = (OpusEncoder*)ptr;
699 ret = opus_encoder_ctl(enc, request, value);
700 }
701 break;
702 case OPUS_GET_FINAL_RANGE_REQUEST:
703 {
704 int s;
705 opus_uint32 *value = va_arg(ap, opus_uint32*);
706 opus_uint32 tmp;
707 *value=0;
708 for (s=0;s<st->layout.nb_streams;s++)
709 {
710 OpusEncoder *enc;
711 enc = (OpusEncoder*)ptr;
712 if (s < st->layout.nb_coupled_streams)
713 ptr += align(coupled_size);
714 else
715 ptr += align(mono_size);
716 ret = opus_encoder_ctl(enc, request, &tmp);
717 if (ret != OPUS_OK) break;
718 *value ^= tmp;
719 }
720 }
721 break;
722 case OPUS_SET_LSB_DEPTH_REQUEST:
723 case OPUS_SET_COMPLEXITY_REQUEST:
724 case OPUS_SET_VBR_REQUEST:
725 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
726 case OPUS_SET_BANDWIDTH_REQUEST:
727 case OPUS_SET_SIGNAL_REQUEST:
728 case OPUS_SET_APPLICATION_REQUEST:
729 case OPUS_SET_INBAND_FEC_REQUEST:
730 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
731 case OPUS_SET_DTX_REQUEST:
732 case OPUS_SET_FORCE_MODE_REQUEST:
733 case OPUS_SET_FORCE_CHANNELS_REQUEST:
734 {
735 int s;
736 /* This works for int32 params */
737 opus_int32 value = va_arg(ap, opus_int32);
738 for (s=0;s<st->layout.nb_streams;s++)
739 {
740 OpusEncoder *enc;
741
742 enc = (OpusEncoder*)ptr;
743 if (s < st->layout.nb_coupled_streams)
744 ptr += align(coupled_size);
745 else
746 ptr += align(mono_size);
747 ret = opus_encoder_ctl(enc, request, value);
748 if (ret != OPUS_OK)
749 break;
750 }
751 }
752 break;
753 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
754 {
755 int s;
756 opus_int32 stream_id;
757 OpusEncoder **value;
758 stream_id = va_arg(ap, opus_int32);
759 if (stream_id<0 || stream_id >= st->layout.nb_streams)
760 ret = OPUS_BAD_ARG;
761 value = va_arg(ap, OpusEncoder**);
762 for (s=0;s<stream_id;s++)
763 {
764 if (s < st->layout.nb_coupled_streams)
765 ptr += align(coupled_size);
766 else
767 ptr += align(mono_size);
768 }
769 *value = (OpusEncoder*)ptr;
770 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500771 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500772 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -0500773 {
774 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -0500775 st->variable_duration = value;
776 }
777 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500778 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -0500779 {
780 opus_int32 *value = va_arg(ap, opus_int32*);
781 *value = st->variable_duration;
782 }
783 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500784 default:
785 ret = OPUS_UNIMPLEMENTED;
786 break;
787 }
788
789 va_end(ap);
790 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500791bad_arg:
792 va_end(ap);
793 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500794}
795
796void opus_multistream_encoder_destroy(OpusMSEncoder *st)
797{
798 opus_free(st);
799}
800
801