blob: 6f3eb532d01ffdd06ddc693500978e30ce369040 [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 Valin49587512013-07-07 02:50:18 -040040#include "mathops.h"
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050041
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -040042typedef struct {
43 int nb_streams;
44 int nb_coupled_streams;
45 unsigned char mapping[8];
46} VorbisLayout;
47
48/* Index is nb_channel-1*/
49static const VorbisLayout vorbis_mappings[8] = {
50 {1, 0, {0}}, /* 1: mono */
51 {1, 1, {0, 1}}, /* 2: stereo */
52 {2, 1, {0, 2, 1}}, /* 3: 1-d surround */
53 {2, 2, {0, 1, 2, 3}}, /* 4: quadraphonic surround */
54 {3, 2, {0, 4, 1, 2, 3}}, /* 5: 5-channel surround */
55 {4, 2, {0, 4, 1, 2, 3, 5}}, /* 6: 5.1 surround */
56 {4, 3, {0, 4, 1, 2, 3, 5, 6}}, /* 7: 6.1 surround */
57 {5, 3, {0, 6, 1, 2, 3, 4, 5, 7}}, /* 8: 7.1 surround */
58};
59
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050060struct OpusMSEncoder {
Jean-Marc Valin51f4a322013-02-20 04:08:04 -050061 TonalityAnalysisState analysis;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050062 ChannelLayout layout;
Jean-Marc Valin1b723862013-04-25 21:34:04 -040063 int lfe_stream;
Jean-Marc Valin74483662012-12-17 16:23:42 -050064 int variable_duration;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -040065 int surround;
Jean-Marc Valin74483662012-12-17 16:23:42 -050066 opus_int32 bitrate_bps;
67 opus_val32 subframe_mem[3];
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050068 /* Encoder states go here */
69};
70
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -050071
72static int validate_encoder_layout(const ChannelLayout *layout)
73{
74 int s;
75 for (s=0;s<layout->nb_streams;s++)
76 {
77 if (s < layout->nb_coupled_streams)
78 {
79 if (get_left_channel(layout, s, -1)==-1)
80 return 0;
81 if (get_right_channel(layout, s, -1)==-1)
82 return 0;
83 } else {
84 if (get_mono_channel(layout, s, -1)==-1)
85 return 0;
86 }
87 }
88 return 1;
89}
90
91
92opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_streams)
93{
94 int coupled_size;
95 int mono_size;
96
97 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
98 coupled_size = opus_encoder_get_size(2);
99 mono_size = opus_encoder_get_size(1);
100 return align(sizeof(OpusMSEncoder))
101 + nb_coupled_streams * align(coupled_size)
102 + (nb_streams-nb_coupled_streams) * align(mono_size);
103}
104
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400105opus_int32 opus_multistream_surround_encoder_get_size(int channels, int mapping_family)
106{
107 int nb_streams;
108 int nb_coupled_streams;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400109 opus_int32 size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400110
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400111 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400112 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400113 if (channels==1)
114 {
115 nb_streams=1;
116 nb_coupled_streams=0;
117 } else if (channels==2)
118 {
119 nb_streams=1;
120 nb_coupled_streams=1;
121 } else
122 return 0;
123 } else if (mapping_family==1 && channels<=8 && channels>=1)
124 {
125 nb_streams=vorbis_mappings[channels-1].nb_streams;
126 nb_coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
127 } else if (mapping_family==255)
128 {
129 nb_streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400130 nb_coupled_streams=0;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400131 } else
132 return 0;
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400133 size = opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
134 if (channels>2)
135 size += align(opus_encoder_get_size(2));
136 return size;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400137}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500138
139
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400140static int opus_multistream_encoder_init_impl(
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500141 OpusMSEncoder *st,
142 opus_int32 Fs,
143 int channels,
144 int streams,
145 int coupled_streams,
146 const unsigned char *mapping,
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400147 int application,
148 int surround
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500149)
150{
151 int coupled_size;
152 int mono_size;
153 int i, ret;
154 char *ptr;
155
156 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
157 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
158 return OPUS_BAD_ARG;
159
160 st->layout.nb_channels = channels;
161 st->layout.nb_streams = streams;
162 st->layout.nb_coupled_streams = coupled_streams;
Jean-Marc Valinb0429352013-05-05 02:22:06 -0400163 st->subframe_mem[0]=st->subframe_mem[1]=st->subframe_mem[2]=0;
164 OPUS_CLEAR(&st->analysis,1);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400165 if (!surround)
166 st->lfe_stream = -1;
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500167 st->bitrate_bps = OPUS_AUTO;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500168 st->variable_duration = OPUS_FRAMESIZE_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500169 for (i=0;i<st->layout.nb_channels;i++)
170 st->layout.mapping[i] = mapping[i];
171 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
172 return OPUS_BAD_ARG;
173 ptr = (char*)st + align(sizeof(OpusMSEncoder));
174 coupled_size = opus_encoder_get_size(2);
175 mono_size = opus_encoder_get_size(1);
176
177 for (i=0;i<st->layout.nb_coupled_streams;i++)
178 {
179 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400180 if(ret!=OPUS_OK)return ret;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400181 if (i==st->lfe_stream)
182 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500183 ptr += align(coupled_size);
184 }
185 for (;i<st->layout.nb_streams;i++)
186 {
187 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400188 if (i==st->lfe_stream)
189 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_SET_LFE(1));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500190 if(ret!=OPUS_OK)return ret;
191 ptr += align(mono_size);
192 }
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400193 if (surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400194 {
195 OpusEncoder *downmix_enc;
196 downmix_enc = (OpusEncoder*)ptr;
197 ret = opus_encoder_init(downmix_enc, Fs, 2, OPUS_APPLICATION_AUDIO);
198 if(ret!=OPUS_OK)return ret;
199 }
200 st->surround = surround;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500201 return OPUS_OK;
202}
203
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400204int opus_multistream_encoder_init(
205 OpusMSEncoder *st,
206 opus_int32 Fs,
207 int channels,
208 int streams,
209 int coupled_streams,
210 const unsigned char *mapping,
211 int application
212)
213{
214 return opus_multistream_encoder_init_impl(st, Fs, channels, streams, coupled_streams, mapping, application, 0);
215}
216
217int opus_multistream_surround_encoder_init(
218 OpusMSEncoder *st,
219 opus_int32 Fs,
220 int channels,
221 int mapping_family,
222 int *streams,
223 int *coupled_streams,
224 unsigned char *mapping,
225 int application
226)
227{
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400228 if ((channels>255) || (channels<1))
229 return OPUS_BAD_ARG;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400230 st->lfe_stream = -1;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400231 if (mapping_family==0)
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400232 {
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400233 if (channels==1)
234 {
235 *streams=1;
236 *coupled_streams=0;
237 mapping[0]=0;
238 } else if (channels==2)
239 {
240 *streams=1;
241 *coupled_streams=1;
242 mapping[0]=0;
243 mapping[1]=1;
244 } else
245 return OPUS_UNIMPLEMENTED;
246 } else if (mapping_family==1 && channels<=8 && channels>=1)
247 {
248 int i;
249 *streams=vorbis_mappings[channels-1].nb_streams;
250 *coupled_streams=vorbis_mappings[channels-1].nb_coupled_streams;
251 for (i=0;i<channels;i++)
252 mapping[i] = vorbis_mappings[channels-1].mapping[i];
253 if (channels>=6)
254 st->lfe_stream = *streams-1;
255 } else if (mapping_family==255)
256 {
257 int i;
258 *streams=channels;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400259 *coupled_streams=0;
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400260 for(i=0;i<channels;i++)
261 mapping[i] = i;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400262 } else
Jean-Marc Valin7a8b1392013-04-29 18:32:27 -0400263 return OPUS_UNIMPLEMENTED;
Jean-Marc Valin337f34c2013-07-01 16:17:01 -0400264 return opus_multistream_encoder_init_impl(st, Fs, channels, *streams, *coupled_streams,
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400265 mapping, application, channels>2&&mapping_family==1);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400266}
267
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500268OpusMSEncoder *opus_multistream_encoder_create(
269 opus_int32 Fs,
270 int channels,
271 int streams,
272 int coupled_streams,
273 const unsigned char *mapping,
274 int application,
275 int *error
276)
277{
278 int ret;
279 OpusMSEncoder *st;
280 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
281 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
282 {
283 if (error)
284 *error = OPUS_BAD_ARG;
285 return NULL;
286 }
287 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, coupled_streams));
288 if (st==NULL)
289 {
290 if (error)
291 *error = OPUS_ALLOC_FAIL;
292 return NULL;
293 }
294 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_streams, mapping, application);
295 if (ret != OPUS_OK)
296 {
297 opus_free(st);
298 st = NULL;
299 }
300 if (error)
301 *error = ret;
302 return st;
303}
304
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400305OpusMSEncoder *opus_multistream_surround_encoder_create(
306 opus_int32 Fs,
307 int channels,
308 int mapping_family,
309 int *streams,
310 int *coupled_streams,
311 unsigned char *mapping,
312 int application,
313 int *error
314)
315{
316 int ret;
317 OpusMSEncoder *st;
318 if ((channels>255) || (channels<1))
319 {
320 if (error)
321 *error = OPUS_BAD_ARG;
322 return NULL;
323 }
324 st = (OpusMSEncoder *)opus_alloc(opus_multistream_surround_encoder_get_size(channels, mapping_family));
325 if (st==NULL)
326 {
327 if (error)
328 *error = OPUS_ALLOC_FAIL;
329 return NULL;
330 }
331 ret = opus_multistream_surround_encoder_init(st, Fs, channels, mapping_family, streams, coupled_streams, mapping, application);
332 if (ret != OPUS_OK)
333 {
334 opus_free(st);
335 st = NULL;
336 }
337 if (error)
338 *error = ret;
339 return st;
340}
341
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500342typedef void (*opus_copy_channel_in_func)(
343 opus_val16 *dst,
344 int dst_stride,
345 const void *src,
346 int src_stride,
347 int src_channel,
348 int frame_size
349);
350
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400351typedef void (*opus_surround_downmix_funct)(
352 opus_val16 *dst,
353 const void *src,
354 int channels,
355 int frame_size
356);
357
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400358static void surround_rate_allocation(
359 OpusMSEncoder *st,
360 opus_int32 *rate,
361 int frame_size
362 )
363{
364 int i;
365 opus_int32 channel_rate;
366 opus_int32 Fs;
367 char *ptr;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400368 int stream_offset;
369 int lfe_offset;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400370 int coupled_ratio; /* Q8 */
371 int lfe_ratio; /* Q8 */
372
373 ptr = (char*)st + align(sizeof(OpusMSEncoder));
374 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
375
Jean-Marc Valin49587512013-07-07 02:50:18 -0400376 if (st->bitrate_bps > st->layout.nb_channels*40000)
377 stream_offset = 20000;
378 else
379 stream_offset = st->bitrate_bps/st->layout.nb_channels/2;
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400380 /* We start by giving each stream (coupled or uncoupled) the same bitrate.
381 This models the main saving of coupled channels over uncoupled. */
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400382 /* The LFE stream is an exception to the above and gets fewer bits. */
383 lfe_offset = 3500;
384 /* Coupled streams get twice the mono rate after the first 20 kb/s. */
385 coupled_ratio = 512;
386 /* Should depend on the bitrate, for now we assume LFE gets 1/8 the bits of mono */
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400387 lfe_ratio = 32;
388
389 /* Compute bitrate allocation between streams */
390 if (st->bitrate_bps==OPUS_AUTO)
391 {
392 channel_rate = Fs+60*Fs/frame_size;
393 } else if (st->bitrate_bps==OPUS_BITRATE_MAX)
394 {
395 channel_rate = 300000;
396 } else {
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400397 int nb_lfe;
398 int nb_uncoupled;
399 int nb_coupled;
400 int total;
401 nb_lfe = (st->lfe_stream!=-1);
402 nb_coupled = st->layout.nb_coupled_streams;
403 nb_uncoupled = st->layout.nb_streams-nb_coupled-nb_lfe;
404 total = (nb_uncoupled<<8) /* mono */
405 + coupled_ratio*nb_coupled /* stereo */
406 + nb_lfe*lfe_ratio;
407 channel_rate = 256*(st->bitrate_bps-lfe_offset*nb_lfe-stream_offset*(nb_coupled+nb_uncoupled))/total;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400408 }
409#ifndef FIXED_POINT
410 if (st->variable_duration==OPUS_FRAMESIZE_VARIABLE && frame_size != Fs/50)
411 {
412 opus_int32 bonus;
413 bonus = 60*(Fs/frame_size-50);
414 channel_rate += bonus;
415 }
416#endif
417
418 for (i=0;i<st->layout.nb_streams;i++)
419 {
420 if (i<st->layout.nb_coupled_streams)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400421 rate[i] = stream_offset+(channel_rate*coupled_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400422 else if (i!=st->lfe_stream)
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400423 rate[i] = stream_offset+channel_rate;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400424 else
Jean-Marc Valind66bdc72013-05-06 16:03:39 -0400425 rate[i] = lfe_offset+(channel_rate*lfe_ratio>>8);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400426 }
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400427}
428
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500429/* Max size in case the encoder decides to return three frames */
430#define MS_FRAME_TMP (3*1275+7)
431static int opus_multistream_encode_native
432(
433 OpusMSEncoder *st,
434 opus_copy_channel_in_func copy_channel_in,
435 const void *pcm,
436 int frame_size,
437 unsigned char *data,
Jean-Marc Valinb3eba242012-12-20 23:11:53 -0500438 opus_int32 max_data_bytes,
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400439 int lsb_depth,
440 opus_surround_downmix_funct surround_downmix
Jean-Marc Valin10a34a52012-12-20 00:23:01 -0500441#ifndef FIXED_POINT
442 , downmix_func downmix
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500443 , const void *pcm_analysis
Jean-Marc Valin10a34a52012-12-20 00:23:01 -0500444#endif
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500445)
446{
447 opus_int32 Fs;
448 int coupled_size;
449 int mono_size;
450 int s;
451 char *ptr;
452 int tot_size;
453 VARDECL(opus_val16, buf);
454 unsigned char tmp_data[MS_FRAME_TMP];
455 OpusRepacketizer rp;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500456 opus_int32 complexity;
Pedro Becerra1af7f952013-07-11 00:00:47 -0400457#ifndef FIXED_POINT
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500458 AnalysisInfo analysis_info;
Pedro Becerra1af7f952013-07-11 00:00:47 -0400459#endif
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500460 const CELTMode *celt_mode;
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400461 opus_int32 bitrates[256];
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400462 opus_val16 bandLogE[42];
463 opus_val16 bandLogE_mono[21];
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500464 ALLOC_STACK;
465
466 ptr = (char*)st + align(sizeof(OpusMSEncoder));
467 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500468 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_COMPLEXITY(&complexity));
469 opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
Jean-Marc Valin74483662012-12-17 16:23:42 -0500470
471 if (400*frame_size < Fs)
472 {
473 RESTORE_STACK;
474 return OPUS_BAD_ARG;
475 }
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500476#ifndef FIXED_POINT
477 analysis_info.valid = 0;
478 if (complexity >= 7 && Fs==48000)
Jean-Marc Valin74483662012-12-17 16:23:42 -0500479 {
Jean-Marc Valin74483662012-12-17 16:23:42 -0500480 opus_int32 delay_compensation;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500481 int channels;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500482
483 channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
484 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
485 delay_compensation -= Fs/400;
Jean-Marc Valin74483662012-12-17 16:23:42 -0500486
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500487 frame_size = run_analysis(&st->analysis, celt_mode, pcm, pcm_analysis,
488 frame_size, st->variable_duration, channels, Fs, st->bitrate_bps, delay_compensation, lsb_depth, downmix, &analysis_info);
489 } else
490#endif
491 {
492 frame_size = frame_size_select(frame_size, st->variable_duration, Fs);
493 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500494 /* Validate frame_size before using it to allocate stack space.
495 This mirrors the checks in opus_encode[_float](). */
496 if (400*frame_size != Fs && 200*frame_size != Fs &&
497 100*frame_size != Fs && 50*frame_size != Fs &&
498 25*frame_size != Fs && 50*frame_size != 3*Fs)
499 {
500 RESTORE_STACK;
501 return OPUS_BAD_ARG;
502 }
503 ALLOC(buf, 2*frame_size, opus_val16);
504 coupled_size = opus_encoder_get_size(2);
505 mono_size = opus_encoder_get_size(1);
506
Jean-Marc Valin58d80ab2013-05-27 20:47:47 -0400507 if (st->surround)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400508 {
509 int i;
510 unsigned char dummy[512];
511 /* Temporary kludge -- remove */
512 OpusEncoder *downmix_enc;
513
514 ptr = (char*)st + align(sizeof(OpusMSEncoder));
515 for (s=0;s<st->layout.nb_streams;s++)
516 {
517 if (s < st->layout.nb_coupled_streams)
518 ptr += align(coupled_size);
519 else
520 ptr += align(mono_size);
521 }
522 downmix_enc = (OpusEncoder*)ptr;
523 surround_downmix(buf, pcm, st->layout.nb_channels, frame_size);
524 opus_encoder_ctl(downmix_enc, OPUS_SET_ENERGY_SAVE(bandLogE));
525 opus_encoder_ctl(downmix_enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
526 opus_encoder_ctl(downmix_enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
527 opus_encoder_ctl(downmix_enc, OPUS_SET_FORCE_CHANNELS(2));
528 opus_encode_native(downmix_enc, buf, frame_size, dummy, 512, lsb_depth
529#ifndef FIXED_POINT
530 , &analysis_info
531#endif
532 );
Jean-Marc Valin49587512013-07-07 02:50:18 -0400533 /* Combines the left and right mask into a centre mask. We
534 use an approximation for the log of the sum of the energies. */
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400535 for(i=0;i<21;i++)
Jean-Marc Valin49587512013-07-07 02:50:18 -0400536 {
537 opus_val16 diff;
538 diff = ABS16(SUB16(bandLogE[i], bandLogE[21+i]));
539 diff = diff + HALF16(diff);
540 diff = SHR32(HALF32(celt_exp2(-diff)), 16-DB_SHIFT);
541 bandLogE_mono[i] = MAX16(bandLogE[i], bandLogE[21+i]) + diff;
542 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400543 }
544
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500545 if (max_data_bytes < 4*st->layout.nb_streams-1)
546 {
547 RESTORE_STACK;
548 return OPUS_BUFFER_TOO_SMALL;
549 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500550
551 /* Compute bitrate allocation between streams (this could be a lot better) */
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400552 surround_rate_allocation(st, bitrates, frame_size);
553
Jean-Marc Valin74483662012-12-17 16:23:42 -0500554 ptr = (char*)st + align(sizeof(OpusMSEncoder));
555 for (s=0;s<st->layout.nb_streams;s++)
556 {
557 OpusEncoder *enc;
558 enc = (OpusEncoder*)ptr;
559 if (s < st->layout.nb_coupled_streams)
560 ptr += align(coupled_size);
561 else
562 ptr += align(mono_size);
Jean-Marc Valin1b723862013-04-25 21:34:04 -0400563 opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrates[s]));
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400564 if (st->surround)
565 {
566 opus_encoder_ctl(enc, OPUS_SET_FORCE_MODE(MODE_CELT_ONLY));
567 opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
568 if (s < st->layout.nb_coupled_streams)
569 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(2));
570 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500571 }
572
573 ptr = (char*)st + align(sizeof(OpusMSEncoder));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500574 /* Counting ToC */
575 tot_size = 0;
576 for (s=0;s<st->layout.nb_streams;s++)
577 {
578 OpusEncoder *enc;
579 int len;
580 int curr_max;
581
582 opus_repacketizer_init(&rp);
583 enc = (OpusEncoder*)ptr;
584 if (s < st->layout.nb_coupled_streams)
585 {
586 int left, right;
587 left = get_left_channel(&st->layout, s, -1);
588 right = get_right_channel(&st->layout, s, -1);
589 (*copy_channel_in)(buf, 2,
590 pcm, st->layout.nb_channels, left, frame_size);
591 (*copy_channel_in)(buf+1, 2,
592 pcm, st->layout.nb_channels, right, frame_size);
593 ptr += align(coupled_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400594 /* FIXME: This isn't correct for the coupled center channels in
595 6.1 surround configuration */
596 if (st->surround)
597 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500598 } else {
599 int chan = get_mono_channel(&st->layout, s, -1);
600 (*copy_channel_in)(buf, 1,
601 pcm, st->layout.nb_channels, chan, frame_size);
602 ptr += align(mono_size);
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400603 if (st->surround)
604 opus_encoder_ctl(enc, OPUS_SET_ENERGY_MASK(bandLogE_mono));
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500605 }
606 /* number of bytes left (+Toc) */
607 curr_max = max_data_bytes - tot_size;
608 /* Reserve three bytes for the last stream and four for the others */
609 curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
610 curr_max = IMIN(curr_max,MS_FRAME_TMP);
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500611 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth
612#ifndef FIXED_POINT
613 , &analysis_info
614#endif
615 );
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500616 if (len<0)
617 {
618 RESTORE_STACK;
619 return len;
620 }
621 /* We need to use the repacketizer to add the self-delimiting lengths
622 while taking into account the fact that the encoder can now return
623 more than one frame at a time (e.g. 60 ms CELT-only) */
624 opus_repacketizer_cat(&rp, tmp_data, len);
625 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);
626 data += len;
627 tot_size += len;
628 }
629 RESTORE_STACK;
630 return tot_size;
631
632}
633
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400634static void channel_pos(int channels, int pos[8])
635{
636 /* Position in the mix: 0 don't mix, 1: left, 2: center, 3:right */
637 if (channels==4)
638 {
639 pos[0]=1;
640 pos[1]=3;
641 pos[2]=1;
642 pos[3]=3;
643 } else if (channels==3||channels==5||channels==6)
644 {
645 pos[0]=1;
646 pos[1]=2;
647 pos[2]=3;
648 pos[3]=1;
649 pos[4]=3;
650 pos[5]=0;
651 } else if (channels==7)
652 {
653 pos[0]=1;
654 pos[1]=2;
655 pos[2]=3;
656 pos[3]=1;
657 pos[4]=3;
658 pos[5]=2;
659 pos[6]=0;
660 } else if (channels==8)
661 {
662 pos[0]=1;
663 pos[1]=2;
664 pos[2]=3;
665 pos[3]=1;
666 pos[4]=3;
667 pos[5]=1;
668 pos[6]=3;
669 pos[7]=0;
670 }
671}
672
Pedro Becerra1af7f952013-07-11 00:00:47 -0400673#if !defined(DISABLE_FLOAT_API)
674static void opus_copy_channel_in_float(
675 opus_val16 *dst,
676 int dst_stride,
677 const void *src,
678 int src_stride,
679 int src_channel,
680 int frame_size
681)
682{
683 const float *float_src;
684 opus_int32 i;
685 float_src = (const float *)src;
686 for (i=0;i<frame_size;i++)
687#if defined(FIXED_POINT)
688 dst[i*dst_stride] = FLOAT2INT16(float_src[i*src_stride+src_channel]);
689#else
690 dst[i*dst_stride] = float_src[i*src_stride+src_channel];
691#endif
692}
693
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400694static void opus_surround_downmix_float(
695 opus_val16 *dst,
696 const void *src,
697 int channels,
698 int frame_size
699)
700{
701 const float *float_src;
702 opus_int32 i;
703 int pos[8] = {0};
704 int c;
705 float_src = (const float *)src;
706
707 channel_pos(channels, pos);
708 for (i=0;i<2*frame_size;i++)
709 dst[i]=0;
710
711 for (c=0;c<channels;c++)
712 {
Jean-Marc Valin49587512013-07-07 02:50:18 -0400713 if (pos[c]==1)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400714 {
715 for (i=0;i<frame_size;i++)
716#if defined(FIXED_POINT)
717 dst[2*i] += SHR16(FLOAT2INT16(float_src[i*channels+c]),3);
718#else
719 dst[2*i] += float_src[i*channels+c];
720#endif
Jean-Marc Valin49587512013-07-07 02:50:18 -0400721 } else if (pos[c]==3)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400722 {
723 for (i=0;i<frame_size;i++)
724#if defined(FIXED_POINT)
725 dst[2*i+1] += SHR16(FLOAT2INT16(float_src[i*channels+c]),3);
726#else
727 dst[2*i+1] += float_src[i*channels+c];
728#endif
Jean-Marc Valin49587512013-07-07 02:50:18 -0400729 } else if (pos[c]==2)
730 {
731 for (i=0;i<frame_size;i++)
732 {
733#if defined(FIXED_POINT)
734 dst[2*i] += SHR32(MULT16_16(QCONST16(.70711f,15), FLOAT2INT16(float_src[i*channels+c])),3+15);
735 dst[2*i+1] += SHR32(MULT16_16(QCONST16(.70711f,15), FLOAT2INT16(float_src[i*channels+c])),3+15);
736#else
737 dst[2*i] += .707*float_src[i*channels+c];
738 dst[2*i+1] += .707*float_src[i*channels+c];
739#endif
740 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400741 }
742 }
743}
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500744#endif
745
746static void opus_copy_channel_in_short(
747 opus_val16 *dst,
748 int dst_stride,
749 const void *src,
750 int src_stride,
751 int src_channel,
752 int frame_size
753)
754{
755 const opus_int16 *short_src;
Timothy B. Terriberrya8f04b22013-03-18 14:42:44 -0700756 opus_int32 i;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500757 short_src = (const opus_int16 *)src;
758 for (i=0;i<frame_size;i++)
759#if defined(FIXED_POINT)
760 dst[i*dst_stride] = short_src[i*src_stride+src_channel];
761#else
762 dst[i*dst_stride] = (1/32768.f)*short_src[i*src_stride+src_channel];
763#endif
764}
765
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400766static void opus_surround_downmix_short(
767 opus_val16 *dst,
768 const void *src,
769 int channels,
770 int frame_size
771)
772{
773 const opus_int16 *short_src;
774 opus_int32 i;
775 int pos[8] = {0};
776 int c;
777 short_src = (const opus_int16 *)src;
778
779 channel_pos(channels, pos);
780 for (i=0;i<2*frame_size;i++)
781 dst[i]=0;
782
783 for (c=0;c<channels;c++)
784 {
Jean-Marc Valin49587512013-07-07 02:50:18 -0400785 if (pos[c]==1)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400786 {
787 for (i=0;i<frame_size;i++)
788#if defined(FIXED_POINT)
789 dst[2*i] += SHR16(short_src[i*channels+c],3);
790#else
791 dst[2*i] += (1/32768.f)*short_src[i*channels+c];
792#endif
Jean-Marc Valin49587512013-07-07 02:50:18 -0400793 } else if (pos[c]==3)
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400794 {
795 for (i=0;i<frame_size;i++)
796#if defined(FIXED_POINT)
797 dst[2*i+1] += SHR16(short_src[i*channels+c],3);
798#else
799 dst[2*i+1] += (1/32768.f)*short_src[i*channels+c];
800#endif
Jean-Marc Valin49587512013-07-07 02:50:18 -0400801 } else if (pos[c]==2)
802 {
803 for (i=0;i<frame_size;i++)
804 {
805#if defined(FIXED_POINT)
806 dst[2*i] += SHR32(MULT16_16(QCONST16(.70711f,15), short_src[i*channels+c]),3+15);
807 dst[2*i+1] += SHR32(MULT16_16(QCONST16(.70711f,15), short_src[i*channels+c]),3+15);
808#else
809 dst[2*i] += (.707f/32768.f)*short_src[i*channels+c];
810 dst[2*i+1] += (.707f/32768.f)*short_src[i*channels+c];
811#endif
812 }
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400813 }
814 }
815}
816
817
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500818#ifdef FIXED_POINT
819int opus_multistream_encode(
820 OpusMSEncoder *st,
821 const opus_val16 *pcm,
822 int frame_size,
823 unsigned char *data,
824 opus_int32 max_data_bytes
825)
826{
827 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valin2f7a3152013-07-07 01:11:23 -0400828 pcm, frame_size, data, max_data_bytes, 16, opus_surround_downmix_short);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500829}
830
831#ifndef DISABLE_FLOAT_API
832int opus_multistream_encode_float(
833 OpusMSEncoder *st,
834 const float *pcm,
835 int frame_size,
836 unsigned char *data,
837 opus_int32 max_data_bytes
838)
839{
840 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valin2f7a3152013-07-07 01:11:23 -0400841 pcm, frame_size, data, max_data_bytes, 16, opus_surround_downmix_float);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500842}
843#endif
844
845#else
846
847int opus_multistream_encode_float
848(
849 OpusMSEncoder *st,
850 const opus_val16 *pcm,
851 int frame_size,
852 unsigned char *data,
853 opus_int32 max_data_bytes
854)
855{
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500856 int channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500857 return opus_multistream_encode_native(st, opus_copy_channel_in_float,
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400858 pcm, frame_size, data, max_data_bytes, 24, opus_surround_downmix_float, downmix_float, pcm+channels*st->analysis.analysis_offset);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500859}
860
861int opus_multistream_encode(
862 OpusMSEncoder *st,
863 const opus_int16 *pcm,
864 int frame_size,
865 unsigned char *data,
866 opus_int32 max_data_bytes
867)
868{
Jean-Marc Valin51f4a322013-02-20 04:08:04 -0500869 int channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500870 return opus_multistream_encode_native(st, opus_copy_channel_in_short,
Jean-Marc Valina4dccd32013-05-04 23:54:20 -0400871 pcm, frame_size, data, max_data_bytes, 16, opus_surround_downmix_short, downmix_int, pcm+channels*st->analysis.analysis_offset);
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500872}
873#endif
874
875int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...)
876{
877 va_list ap;
878 int coupled_size, mono_size;
879 char *ptr;
880 int ret = OPUS_OK;
881
882 va_start(ap, request);
883
884 coupled_size = opus_encoder_get_size(2);
885 mono_size = opus_encoder_get_size(1);
886 ptr = (char*)st + align(sizeof(OpusMSEncoder));
887 switch (request)
888 {
889 case OPUS_SET_BITRATE_REQUEST:
890 {
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500891 opus_int32 value = va_arg(ap, opus_int32);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700892 if (value<0 && value!=OPUS_AUTO && value!=OPUS_BITRATE_MAX)
893 {
Jean-Marc Valin95561be2012-12-17 17:54:01 -0500894 goto bad_arg;
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700895 }
Jean-Marc Valin74483662012-12-17 16:23:42 -0500896 st->bitrate_bps = value;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500897 }
898 break;
899 case OPUS_GET_BITRATE_REQUEST:
900 {
901 int s;
902 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700903 if (!value)
904 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700905 goto bad_arg;
906 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500907 *value = 0;
908 for (s=0;s<st->layout.nb_streams;s++)
909 {
910 opus_int32 rate;
911 OpusEncoder *enc;
912 enc = (OpusEncoder*)ptr;
913 if (s < st->layout.nb_coupled_streams)
914 ptr += align(coupled_size);
915 else
916 ptr += align(mono_size);
917 opus_encoder_ctl(enc, request, &rate);
918 *value += rate;
919 }
920 }
921 break;
922 case OPUS_GET_LSB_DEPTH_REQUEST:
923 case OPUS_GET_VBR_REQUEST:
924 case OPUS_GET_APPLICATION_REQUEST:
925 case OPUS_GET_BANDWIDTH_REQUEST:
926 case OPUS_GET_COMPLEXITY_REQUEST:
927 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
928 case OPUS_GET_DTX_REQUEST:
929 case OPUS_GET_VOICE_RATIO_REQUEST:
930 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
931 case OPUS_GET_SIGNAL_REQUEST:
932 case OPUS_GET_LOOKAHEAD_REQUEST:
933 case OPUS_GET_SAMPLE_RATE_REQUEST:
934 case OPUS_GET_INBAND_FEC_REQUEST:
935 case OPUS_GET_FORCE_CHANNELS_REQUEST:
936 {
937 OpusEncoder *enc;
938 /* For int32* GET params, just query the first stream */
939 opus_int32 *value = va_arg(ap, opus_int32*);
940 enc = (OpusEncoder*)ptr;
941 ret = opus_encoder_ctl(enc, request, value);
942 }
943 break;
944 case OPUS_GET_FINAL_RANGE_REQUEST:
945 {
946 int s;
947 opus_uint32 *value = va_arg(ap, opus_uint32*);
948 opus_uint32 tmp;
Gregory Maxwella0d096f2013-06-29 20:33:32 -0700949 if (!value)
950 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -0700951 goto bad_arg;
952 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -0500953 *value=0;
954 for (s=0;s<st->layout.nb_streams;s++)
955 {
956 OpusEncoder *enc;
957 enc = (OpusEncoder*)ptr;
958 if (s < st->layout.nb_coupled_streams)
959 ptr += align(coupled_size);
960 else
961 ptr += align(mono_size);
962 ret = opus_encoder_ctl(enc, request, &tmp);
963 if (ret != OPUS_OK) break;
964 *value ^= tmp;
965 }
966 }
967 break;
968 case OPUS_SET_LSB_DEPTH_REQUEST:
969 case OPUS_SET_COMPLEXITY_REQUEST:
970 case OPUS_SET_VBR_REQUEST:
971 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
972 case OPUS_SET_BANDWIDTH_REQUEST:
973 case OPUS_SET_SIGNAL_REQUEST:
974 case OPUS_SET_APPLICATION_REQUEST:
975 case OPUS_SET_INBAND_FEC_REQUEST:
976 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
977 case OPUS_SET_DTX_REQUEST:
978 case OPUS_SET_FORCE_MODE_REQUEST:
979 case OPUS_SET_FORCE_CHANNELS_REQUEST:
980 {
981 int s;
982 /* This works for int32 params */
983 opus_int32 value = va_arg(ap, opus_int32);
984 for (s=0;s<st->layout.nb_streams;s++)
985 {
986 OpusEncoder *enc;
987
988 enc = (OpusEncoder*)ptr;
989 if (s < st->layout.nb_coupled_streams)
990 ptr += align(coupled_size);
991 else
992 ptr += align(mono_size);
993 ret = opus_encoder_ctl(enc, request, value);
994 if (ret != OPUS_OK)
995 break;
996 }
997 }
998 break;
999 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
1000 {
1001 int s;
1002 opus_int32 stream_id;
1003 OpusEncoder **value;
1004 stream_id = va_arg(ap, opus_int32);
1005 if (stream_id<0 || stream_id >= st->layout.nb_streams)
1006 ret = OPUS_BAD_ARG;
1007 value = va_arg(ap, OpusEncoder**);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001008 if (!value)
1009 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001010 goto bad_arg;
1011 }
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001012 for (s=0;s<stream_id;s++)
1013 {
1014 if (s < st->layout.nb_coupled_streams)
1015 ptr += align(coupled_size);
1016 else
1017 ptr += align(mono_size);
1018 }
1019 *value = (OpusEncoder*)ptr;
1020 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001021 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001022 case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001023 {
1024 opus_int32 value = va_arg(ap, opus_int32);
Jean-Marc Valin74483662012-12-17 16:23:42 -05001025 st->variable_duration = value;
1026 }
1027 break;
Jean-Marc Valin51f4a322013-02-20 04:08:04 -05001028 case OPUS_GET_EXPERT_FRAME_DURATION_REQUEST:
Jean-Marc Valin74483662012-12-17 16:23:42 -05001029 {
1030 opus_int32 *value = va_arg(ap, opus_int32*);
Gregory Maxwella0d096f2013-06-29 20:33:32 -07001031 if (!value)
1032 {
Gregory Maxwellb271dae2013-06-29 20:25:55 -07001033 goto bad_arg;
1034 }
Jean-Marc Valin74483662012-12-17 16:23:42 -05001035 *value = st->variable_duration;
1036 }
1037 break;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001038 default:
1039 ret = OPUS_UNIMPLEMENTED;
1040 break;
1041 }
1042
1043 va_end(ap);
1044 return ret;
Jean-Marc Valin74483662012-12-17 16:23:42 -05001045bad_arg:
1046 va_end(ap);
1047 return OPUS_BAD_ARG;
Jean-Marc Valinae0e2ca2012-11-07 19:57:33 -05001048}
1049
1050void opus_multistream_encoder_destroy(OpusMSEncoder *st)
1051{
1052 opus_free(st);
1053}