Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: src/opus_multistream.c

Issue 28553003: Updating Opus to a pre-release of 1.1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/opus
Patch Set: Removing failing file Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/opus_encoder.c ('k') | src/opus_multistream_decoder.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* Copyright (c) 2011 Xiph.Org Foundation 1 /* Copyright (c) 2011 Xiph.Org Foundation
2 Written by Jean-Marc Valin */ 2 Written by Jean-Marc Valin */
3 /* 3 /*
4 Redistribution and use in source and binary forms, with or without 4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions 5 modification, are permitted provided that the following conditions
6 are met: 6 are met:
7 7
8 - Redistributions of source code must retain the above copyright 8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer. 9 notice, this list of conditions and the following disclaimer.
10 10
(...skipping 19 matching lines...) Expand all
30 #endif 30 #endif
31 31
32 #include "opus_multistream.h" 32 #include "opus_multistream.h"
33 #include "opus.h" 33 #include "opus.h"
34 #include "opus_private.h" 34 #include "opus_private.h"
35 #include "stack_alloc.h" 35 #include "stack_alloc.h"
36 #include <stdarg.h> 36 #include <stdarg.h>
37 #include "float_cast.h" 37 #include "float_cast.h"
38 #include "os_support.h" 38 #include "os_support.h"
39 39
40 typedef struct ChannelLayout {
41 int nb_channels;
42 int nb_streams;
43 int nb_coupled_streams;
44 unsigned char mapping[256];
45 } ChannelLayout;
46 40
47 struct OpusMSEncoder { 41 int validate_layout(const ChannelLayout *layout)
48 ChannelLayout layout;
49 int bitrate;
50 /* Encoder states go here */
51 };
52
53 struct OpusMSDecoder {
54 ChannelLayout layout;
55 /* Decoder states go here */
56 };
57
58 #ifdef FIXED_POINT
59 #define opus_encode_native opus_encode
60 #else
61 #define opus_encode_native opus_encode_float
62 #endif
63
64 static int validate_layout(const ChannelLayout *layout)
65 { 42 {
66 int i, max_channel; 43 int i, max_channel;
67 44
68 max_channel = layout->nb_streams+layout->nb_coupled_streams; 45 max_channel = layout->nb_streams+layout->nb_coupled_streams;
69 if (max_channel>255) 46 if (max_channel>255)
70 return 0; 47 return 0;
71 for (i=0;i<layout->nb_channels;i++) 48 for (i=0;i<layout->nb_channels;i++)
72 { 49 {
73 if (layout->mapping[i] >= max_channel && layout->mapping[i] != 255) 50 if (layout->mapping[i] >= max_channel && layout->mapping[i] != 255)
74 return 0; 51 return 0;
75 } 52 }
76 return 1; 53 return 1;
77 } 54 }
78 55
79 56
80 static int get_left_channel(const ChannelLayout *layout, int stream_id, int prev ) 57 int get_left_channel(const ChannelLayout *layout, int stream_id, int prev)
81 { 58 {
82 int i; 59 int i;
83 i = (prev<0) ? 0 : prev+1; 60 i = (prev<0) ? 0 : prev+1;
84 for (;i<layout->nb_channels;i++) 61 for (;i<layout->nb_channels;i++)
85 { 62 {
86 if (layout->mapping[i]==stream_id*2) 63 if (layout->mapping[i]==stream_id*2)
87 return i; 64 return i;
88 } 65 }
89 return -1; 66 return -1;
90 } 67 }
91 68
92 static int get_right_channel(const ChannelLayout *layout, int stream_id, int pre v) 69 int get_right_channel(const ChannelLayout *layout, int stream_id, int prev)
93 { 70 {
94 int i; 71 int i;
95 i = (prev<0) ? 0 : prev+1; 72 i = (prev<0) ? 0 : prev+1;
96 for (;i<layout->nb_channels;i++) 73 for (;i<layout->nb_channels;i++)
97 { 74 {
98 if (layout->mapping[i]==stream_id*2+1) 75 if (layout->mapping[i]==stream_id*2+1)
99 return i; 76 return i;
100 } 77 }
101 return -1; 78 return -1;
102 } 79 }
103 80
104 static int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev ) 81 int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev)
105 { 82 {
106 int i; 83 int i;
107 i = (prev<0) ? 0 : prev+1; 84 i = (prev<0) ? 0 : prev+1;
108 for (;i<layout->nb_channels;i++) 85 for (;i<layout->nb_channels;i++)
109 { 86 {
110 if (layout->mapping[i]==stream_id+layout->nb_coupled_streams) 87 if (layout->mapping[i]==stream_id+layout->nb_coupled_streams)
111 return i; 88 return i;
112 } 89 }
113 return -1; 90 return -1;
114 } 91 }
115 92
116 static int validate_encoder_layout(const ChannelLayout *layout)
117 {
118 int s;
119 for (s=0;s<layout->nb_streams;s++)
120 {
121 if (s < layout->nb_coupled_streams)
122 {
123 if (get_left_channel(layout, s, -1)==-1)
124 return 0;
125 if (get_right_channel(layout, s, -1)==-1)
126 return 0;
127 } else {
128 if (get_mono_channel(layout, s, -1)==-1)
129 return 0;
130 }
131 }
132 return 1;
133 }
134
135 opus_int32 opus_multistream_encoder_get_size(int nb_streams, int nb_coupled_stre ams)
136 {
137 int coupled_size;
138 int mono_size;
139
140 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0 ;
141 coupled_size = opus_encoder_get_size(2);
142 mono_size = opus_encoder_get_size(1);
143 return align(sizeof(OpusMSEncoder))
144 + nb_coupled_streams * align(coupled_size)
145 + (nb_streams-nb_coupled_streams) * align(mono_size);
146 }
147
148
149
150 int opus_multistream_encoder_init(
151 OpusMSEncoder *st,
152 opus_int32 Fs,
153 int channels,
154 int streams,
155 int coupled_streams,
156 const unsigned char *mapping,
157 int application
158 )
159 {
160 int coupled_size;
161 int mono_size;
162 int i, ret;
163 char *ptr;
164
165 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
166 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
167 return OPUS_BAD_ARG;
168
169 st->layout.nb_channels = channels;
170 st->layout.nb_streams = streams;
171 st->layout.nb_coupled_streams = coupled_streams;
172
173 for (i=0;i<st->layout.nb_channels;i++)
174 st->layout.mapping[i] = mapping[i];
175 if (!validate_layout(&st->layout) || !validate_encoder_layout(&st->layout))
176 return OPUS_BAD_ARG;
177 ptr = (char*)st + align(sizeof(OpusMSEncoder));
178 coupled_size = opus_encoder_get_size(2);
179 mono_size = opus_encoder_get_size(1);
180
181 for (i=0;i<st->layout.nb_coupled_streams;i++)
182 {
183 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 2, application);
184 if(ret!=OPUS_OK)return ret;
185 ptr += align(coupled_size);
186 }
187 for (;i<st->layout.nb_streams;i++)
188 {
189 ret = opus_encoder_init((OpusEncoder*)ptr, Fs, 1, application);
190 if(ret!=OPUS_OK)return ret;
191 ptr += align(mono_size);
192 }
193 return OPUS_OK;
194 }
195
196 OpusMSEncoder *opus_multistream_encoder_create(
197 opus_int32 Fs,
198 int channels,
199 int streams,
200 int coupled_streams,
201 const unsigned char *mapping,
202 int application,
203 int *error
204 )
205 {
206 int ret;
207 OpusMSEncoder *st;
208 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
209 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
210 {
211 if (error)
212 *error = OPUS_BAD_ARG;
213 return NULL;
214 }
215 st = (OpusMSEncoder *)opus_alloc(opus_multistream_encoder_get_size(streams, c oupled_streams));
216 if (st==NULL)
217 {
218 if (error)
219 *error = OPUS_ALLOC_FAIL;
220 return NULL;
221 }
222 ret = opus_multistream_encoder_init(st, Fs, channels, streams, coupled_stream s, mapping, application);
223 if (ret != OPUS_OK)
224 {
225 opus_free(st);
226 st = NULL;
227 }
228 if (error)
229 *error = ret;
230 return st;
231 }
232
233 typedef void (*opus_copy_channel_in_func)(
234 opus_val16 *dst,
235 int dst_stride,
236 const void *src,
237 int src_stride,
238 int src_channel,
239 int frame_size
240 );
241
242 /* Max size in case the encoder decides to return three frames */
243 #define MS_FRAME_TMP (3*1275+7)
244 static int opus_multistream_encode_native
245 (
246 OpusMSEncoder *st,
247 opus_copy_channel_in_func copy_channel_in,
248 const void *pcm,
249 int frame_size,
250 unsigned char *data,
251 opus_int32 max_data_bytes
252 )
253 {
254 opus_int32 Fs;
255 int coupled_size;
256 int mono_size;
257 int s;
258 char *ptr;
259 int tot_size;
260 VARDECL(opus_val16, buf);
261 unsigned char tmp_data[MS_FRAME_TMP];
262 OpusRepacketizer rp;
263 ALLOC_STACK;
264
265 ptr = (char*)st + align(sizeof(OpusMSEncoder));
266 opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_SAMPLE_RATE(&Fs));
267 /* Validate frame_size before using it to allocate stack space.
268 This mirrors the checks in opus_encode[_float](). */
269 if (400*frame_size != Fs && 200*frame_size != Fs &&
270 100*frame_size != Fs && 50*frame_size != Fs &&
271 25*frame_size != Fs && 50*frame_size != 3*Fs)
272 {
273 RESTORE_STACK;
274 return OPUS_BAD_ARG;
275 }
276 ALLOC(buf, 2*frame_size, opus_val16);
277 coupled_size = opus_encoder_get_size(2);
278 mono_size = opus_encoder_get_size(1);
279
280 if (max_data_bytes < 4*st->layout.nb_streams-1)
281 {
282 RESTORE_STACK;
283 return OPUS_BUFFER_TOO_SMALL;
284 }
285 /* 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);
316 len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max);
317 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_fr ames(&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)
336 static 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
357 static 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
378 int 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,
387 pcm, frame_size, data, max_data_bytes);
388 }
389
390 #ifndef DISABLE_FLOAT_API
391 int 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,
400 pcm, frame_size, data, max_data_bytes);
401 }
402 #endif
403
404 #else
405
406 int 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,
416 pcm, frame_size, data, max_data_bytes);
417 }
418
419 int 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,
428 pcm, frame_size, data, max_data_bytes);
429 }
430 #endif
431
432 int 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 {
448 int chan, s;
449 opus_int32 value = va_arg(ap, opus_int32);
450 chan = st->layout.nb_streams + st->layout.nb_coupled_streams;
451 value /= chan;
452 for (s=0;s<st->layout.nb_streams;s++)
453 {
454 OpusEncoder *enc;
455 enc = (OpusEncoder*)ptr;
456 if (s < st->layout.nb_coupled_streams)
457 ptr += align(coupled_size);
458 else
459 ptr += align(mono_size);
460 opus_encoder_ctl(enc, request, value * (s < st->layout.nb_coupled_strea ms ? 2 : 1));
461 }
462 }
463 break;
464 case OPUS_GET_BITRATE_REQUEST:
465 {
466 int s;
467 opus_int32 *value = va_arg(ap, opus_int32*);
468 *value = 0;
469 for (s=0;s<st->layout.nb_streams;s++)
470 {
471 opus_int32 rate;
472 OpusEncoder *enc;
473 enc = (OpusEncoder*)ptr;
474 if (s < st->layout.nb_coupled_streams)
475 ptr += align(coupled_size);
476 else
477 ptr += align(mono_size);
478 opus_encoder_ctl(enc, request, &rate);
479 *value += rate;
480 }
481 }
482 break;
483 case OPUS_GET_LSB_DEPTH_REQUEST:
484 case OPUS_GET_VBR_REQUEST:
485 case OPUS_GET_APPLICATION_REQUEST:
486 case OPUS_GET_BANDWIDTH_REQUEST:
487 case OPUS_GET_COMPLEXITY_REQUEST:
488 case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
489 case OPUS_GET_DTX_REQUEST:
490 case OPUS_GET_VOICE_RATIO_REQUEST:
491 case OPUS_GET_VBR_CONSTRAINT_REQUEST:
492 case OPUS_GET_SIGNAL_REQUEST:
493 case OPUS_GET_LOOKAHEAD_REQUEST:
494 case OPUS_GET_SAMPLE_RATE_REQUEST:
495 case OPUS_GET_INBAND_FEC_REQUEST:
496 {
497 OpusEncoder *enc;
498 /* For int32* GET params, just query the first stream */
499 opus_int32 *value = va_arg(ap, opus_int32*);
500 enc = (OpusEncoder*)ptr;
501 ret = opus_encoder_ctl(enc, request, value);
502 }
503 break;
504 case OPUS_GET_FINAL_RANGE_REQUEST:
505 {
506 int s;
507 opus_uint32 *value = va_arg(ap, opus_uint32*);
508 opus_uint32 tmp;
509 *value=0;
510 for (s=0;s<st->layout.nb_streams;s++)
511 {
512 OpusEncoder *enc;
513 enc = (OpusEncoder*)ptr;
514 if (s < st->layout.nb_coupled_streams)
515 ptr += align(coupled_size);
516 else
517 ptr += align(mono_size);
518 ret = opus_encoder_ctl(enc, request, &tmp);
519 if (ret != OPUS_OK) break;
520 *value ^= tmp;
521 }
522 }
523 break;
524 case OPUS_SET_LSB_DEPTH_REQUEST:
525 case OPUS_SET_COMPLEXITY_REQUEST:
526 case OPUS_SET_VBR_REQUEST:
527 case OPUS_SET_VBR_CONSTRAINT_REQUEST:
528 case OPUS_SET_BANDWIDTH_REQUEST:
529 case OPUS_SET_SIGNAL_REQUEST:
530 case OPUS_SET_APPLICATION_REQUEST:
531 case OPUS_SET_INBAND_FEC_REQUEST:
532 case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
533 case OPUS_SET_DTX_REQUEST:
534 case OPUS_SET_FORCE_MODE_REQUEST:
535 {
536 int s;
537 /* This works for int32 params */
538 opus_int32 value = va_arg(ap, opus_int32);
539 for (s=0;s<st->layout.nb_streams;s++)
540 {
541 OpusEncoder *enc;
542
543 enc = (OpusEncoder*)ptr;
544 if (s < st->layout.nb_coupled_streams)
545 ptr += align(coupled_size);
546 else
547 ptr += align(mono_size);
548 ret = opus_encoder_ctl(enc, request, value);
549 if (ret != OPUS_OK)
550 break;
551 }
552 }
553 break;
554 case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
555 {
556 int s;
557 opus_int32 stream_id;
558 OpusEncoder **value;
559 stream_id = va_arg(ap, opus_int32);
560 if (stream_id<0 || stream_id >= st->layout.nb_streams)
561 ret = OPUS_BAD_ARG;
562 value = va_arg(ap, OpusEncoder**);
563 for (s=0;s<stream_id;s++)
564 {
565 if (s < st->layout.nb_coupled_streams)
566 ptr += align(coupled_size);
567 else
568 ptr += align(mono_size);
569 }
570 *value = (OpusEncoder*)ptr;
571 }
572 break;
573 default:
574 ret = OPUS_UNIMPLEMENTED;
575 break;
576 }
577
578 va_end(ap);
579 return ret;
580 }
581
582 void opus_multistream_encoder_destroy(OpusMSEncoder *st)
583 {
584 opus_free(st);
585 }
586
587
588 /* DECODER */
589
590 opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_stre ams)
591 {
592 int coupled_size;
593 int mono_size;
594
595 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0 ;
596 coupled_size = opus_decoder_get_size(2);
597 mono_size = opus_decoder_get_size(1);
598 return align(sizeof(OpusMSDecoder))
599 + nb_coupled_streams * align(coupled_size)
600 + (nb_streams-nb_coupled_streams) * align(mono_size);
601 }
602
603 int opus_multistream_decoder_init(
604 OpusMSDecoder *st,
605 opus_int32 Fs,
606 int channels,
607 int streams,
608 int coupled_streams,
609 const unsigned char *mapping
610 )
611 {
612 int coupled_size;
613 int mono_size;
614 int i, ret;
615 char *ptr;
616
617 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
618 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
619 return OPUS_BAD_ARG;
620
621 st->layout.nb_channels = channels;
622 st->layout.nb_streams = streams;
623 st->layout.nb_coupled_streams = coupled_streams;
624
625 for (i=0;i<st->layout.nb_channels;i++)
626 st->layout.mapping[i] = mapping[i];
627 if (!validate_layout(&st->layout))
628 return OPUS_BAD_ARG;
629
630 ptr = (char*)st + align(sizeof(OpusMSDecoder));
631 coupled_size = opus_decoder_get_size(2);
632 mono_size = opus_decoder_get_size(1);
633
634 for (i=0;i<st->layout.nb_coupled_streams;i++)
635 {
636 ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
637 if(ret!=OPUS_OK)return ret;
638 ptr += align(coupled_size);
639 }
640 for (;i<st->layout.nb_streams;i++)
641 {
642 ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
643 if(ret!=OPUS_OK)return ret;
644 ptr += align(mono_size);
645 }
646 return OPUS_OK;
647 }
648
649
650 OpusMSDecoder *opus_multistream_decoder_create(
651 opus_int32 Fs,
652 int channels,
653 int streams,
654 int coupled_streams,
655 const unsigned char *mapping,
656 int *error
657 )
658 {
659 int ret;
660 OpusMSDecoder *st;
661 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
662 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
663 {
664 if (error)
665 *error = OPUS_BAD_ARG;
666 return NULL;
667 }
668 st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, c oupled_streams));
669 if (st==NULL)
670 {
671 if (error)
672 *error = OPUS_ALLOC_FAIL;
673 return NULL;
674 }
675 ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_stream s, mapping);
676 if (error)
677 *error = ret;
678 if (ret != OPUS_OK)
679 {
680 opus_free(st);
681 st = NULL;
682 }
683 return st;
684 }
685
686 typedef void (*opus_copy_channel_out_func)(
687 void *dst,
688 int dst_stride,
689 int dst_channel,
690 const opus_val16 *src,
691 int src_stride,
692 int frame_size
693 );
694
695 static int opus_multistream_decode_native(
696 OpusMSDecoder *st,
697 const unsigned char *data,
698 opus_int32 len,
699 void *pcm,
700 opus_copy_channel_out_func copy_channel_out,
701 int frame_size,
702 int decode_fec
703 )
704 {
705 opus_int32 Fs;
706 int coupled_size;
707 int mono_size;
708 int s, c;
709 char *ptr;
710 int do_plc=0;
711 VARDECL(opus_val16, buf);
712 ALLOC_STACK;
713
714 /* Limit frame_size to avoid excessive stack allocations. */
715 opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs));
716 frame_size = IMIN(frame_size, Fs/25*3);
717 ALLOC(buf, 2*frame_size, opus_val16);
718 ptr = (char*)st + align(sizeof(OpusMSDecoder));
719 coupled_size = opus_decoder_get_size(2);
720 mono_size = opus_decoder_get_size(1);
721
722 if (len==0)
723 do_plc = 1;
724 if (len < 0)
725 return OPUS_BAD_ARG;
726 if (!do_plc && len < 2*st->layout.nb_streams-1)
727 return OPUS_INVALID_PACKET;
728 for (s=0;s<st->layout.nb_streams;s++)
729 {
730 OpusDecoder *dec;
731 int packet_offset, ret;
732
733 dec = (OpusDecoder*)ptr;
734 ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(m ono_size);
735
736 if (!do_plc && len<=0)
737 {
738 RESTORE_STACK;
739 return OPUS_INVALID_PACKET;
740 }
741 packet_offset = 0;
742 ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=s t->layout.nb_streams-1, &packet_offset);
743 data += packet_offset;
744 len -= packet_offset;
745 if (ret > frame_size)
746 {
747 RESTORE_STACK;
748 return OPUS_BUFFER_TOO_SMALL;
749 }
750 if (s>0 && ret != frame_size)
751 {
752 RESTORE_STACK;
753 return OPUS_INVALID_PACKET;
754 }
755 if (ret <= 0)
756 {
757 RESTORE_STACK;
758 return ret;
759 }
760 frame_size = ret;
761 if (s < st->layout.nb_coupled_streams)
762 {
763 int chan, prev;
764 prev = -1;
765 /* Copy "left" audio to the channel(s) where it belongs */
766 while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
767 {
768 (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
769 buf, 2, frame_size);
770 prev = chan;
771 }
772 prev = -1;
773 /* Copy "right" audio to the channel(s) where it belongs */
774 while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
775 {
776 (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
777 buf+1, 2, frame_size);
778 prev = chan;
779 }
780 } else {
781 int chan, prev;
782 prev = -1;
783 /* Copy audio to the channel(s) where it belongs */
784 while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
785 {
786 (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
787 buf, 1, frame_size);
788 prev = chan;
789 }
790 }
791 }
792 /* Handle muted channels */
793 for (c=0;c<st->layout.nb_channels;c++)
794 {
795 if (st->layout.mapping[c] == 255)
796 {
797 (*copy_channel_out)(pcm, st->layout.nb_channels, c,
798 NULL, 0, frame_size);
799 }
800 }
801 RESTORE_STACK;
802 return frame_size;
803 }
804
805 #if !defined(DISABLE_FLOAT_API)
806 static void opus_copy_channel_out_float(
807 void *dst,
808 int dst_stride,
809 int dst_channel,
810 const opus_val16 *src,
811 int src_stride,
812 int frame_size
813 )
814 {
815 float *float_dst;
816 int i;
817 float_dst = (float*)dst;
818 if (src != NULL)
819 {
820 for (i=0;i<frame_size;i++)
821 #if defined(FIXED_POINT)
822 float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride];
823 #else
824 float_dst[i*dst_stride+dst_channel] = src[i*src_stride];
825 #endif
826 }
827 else
828 {
829 for (i=0;i<frame_size;i++)
830 float_dst[i*dst_stride+dst_channel] = 0;
831 }
832 }
833 #endif
834
835 static void opus_copy_channel_out_short(
836 void *dst,
837 int dst_stride,
838 int dst_channel,
839 const opus_val16 *src,
840 int src_stride,
841 int frame_size
842 )
843 {
844 opus_int16 *short_dst;
845 int i;
846 short_dst = (opus_int16*)dst;
847 if (src != NULL)
848 {
849 for (i=0;i<frame_size;i++)
850 #if defined(FIXED_POINT)
851 short_dst[i*dst_stride+dst_channel] = src[i*src_stride];
852 #else
853 short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]);
854 #endif
855 }
856 else
857 {
858 for (i=0;i<frame_size;i++)
859 short_dst[i*dst_stride+dst_channel] = 0;
860 }
861 }
862
863
864
865 #ifdef FIXED_POINT
866 int opus_multistream_decode(
867 OpusMSDecoder *st,
868 const unsigned char *data,
869 opus_int32 len,
870 opus_int16 *pcm,
871 int frame_size,
872 int decode_fec
873 )
874 {
875 return opus_multistream_decode_native(st, data, len,
876 pcm, opus_copy_channel_out_short, frame_size, decode_fec);
877 }
878
879 #ifndef DISABLE_FLOAT_API
880 int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
881 opus_int32 len, float *pcm, int frame_size, int decode_fec)
882 {
883 return opus_multistream_decode_native(st, data, len,
884 pcm, opus_copy_channel_out_float, frame_size, decode_fec);
885 }
886 #endif
887
888 #else
889
890 int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
891 opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
892 {
893 return opus_multistream_decode_native(st, data, len,
894 pcm, opus_copy_channel_out_short, frame_size, decode_fec);
895 }
896
897 int opus_multistream_decode_float(
898 OpusMSDecoder *st,
899 const unsigned char *data,
900 opus_int32 len,
901 float *pcm,
902 int frame_size,
903 int decode_fec
904 )
905 {
906 return opus_multistream_decode_native(st, data, len,
907 pcm, opus_copy_channel_out_float, frame_size, decode_fec);
908 }
909 #endif
910
911 int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
912 {
913 va_list ap;
914 int coupled_size, mono_size;
915 char *ptr;
916 int ret = OPUS_OK;
917
918 va_start(ap, request);
919
920 coupled_size = opus_decoder_get_size(2);
921 mono_size = opus_decoder_get_size(1);
922 ptr = (char*)st + align(sizeof(OpusMSDecoder));
923 switch (request)
924 {
925 case OPUS_GET_BANDWIDTH_REQUEST:
926 case OPUS_GET_SAMPLE_RATE_REQUEST:
927 case OPUS_GET_GAIN_REQUEST:
928 case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
929 {
930 OpusDecoder *dec;
931 /* For int32* GET params, just query the first stream */
932 opus_int32 *value = va_arg(ap, opus_int32*);
933 dec = (OpusDecoder*)ptr;
934 ret = opus_decoder_ctl(dec, request, value);
935 }
936 break;
937 case OPUS_GET_FINAL_RANGE_REQUEST:
938 {
939 int s;
940 opus_uint32 *value = va_arg(ap, opus_uint32*);
941 opus_uint32 tmp;
942 *value = 0;
943 for (s=0;s<st->layout.nb_streams;s++)
944 {
945 OpusDecoder *dec;
946 dec = (OpusDecoder*)ptr;
947 if (s < st->layout.nb_coupled_streams)
948 ptr += align(coupled_size);
949 else
950 ptr += align(mono_size);
951 ret = opus_decoder_ctl(dec, request, &tmp);
952 if (ret != OPUS_OK) break;
953 *value ^= tmp;
954 }
955 }
956 break;
957 case OPUS_RESET_STATE:
958 {
959 int s;
960 for (s=0;s<st->layout.nb_streams;s++)
961 {
962 OpusDecoder *dec;
963
964 dec = (OpusDecoder*)ptr;
965 if (s < st->layout.nb_coupled_streams)
966 ptr += align(coupled_size);
967 else
968 ptr += align(mono_size);
969 ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
970 if (ret != OPUS_OK)
971 break;
972 }
973 }
974 break;
975 case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
976 {
977 int s;
978 opus_int32 stream_id;
979 OpusDecoder **value;
980 stream_id = va_arg(ap, opus_int32);
981 if (stream_id<0 || stream_id >= st->layout.nb_streams)
982 ret = OPUS_BAD_ARG;
983 value = va_arg(ap, OpusDecoder**);
984 for (s=0;s<stream_id;s++)
985 {
986 if (s < st->layout.nb_coupled_streams)
987 ptr += align(coupled_size);
988 else
989 ptr += align(mono_size);
990 }
991 *value = (OpusDecoder*)ptr;
992 }
993 break;
994 case OPUS_SET_GAIN_REQUEST:
995 {
996 int s;
997 /* This works for int32 params */
998 opus_int32 value = va_arg(ap, opus_int32);
999 for (s=0;s<st->layout.nb_streams;s++)
1000 {
1001 OpusDecoder *dec;
1002
1003 dec = (OpusDecoder*)ptr;
1004 if (s < st->layout.nb_coupled_streams)
1005 ptr += align(coupled_size);
1006 else
1007 ptr += align(mono_size);
1008 ret = opus_decoder_ctl(dec, request, value);
1009 if (ret != OPUS_OK)
1010 break;
1011 }
1012 }
1013 break;
1014 default:
1015 ret = OPUS_UNIMPLEMENTED;
1016 break;
1017 }
1018
1019 va_end(ap);
1020 return ret;
1021 }
1022
1023
1024 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
1025 {
1026 opus_free(st);
1027 }
OLDNEW
« no previous file with comments | « src/opus_encoder.c ('k') | src/opus_multistream_decoder.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698