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

Side by Side Diff: src/opus_multistream_decoder.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, 1 month 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_multistream.c ('k') | src/opus_multistream_encoder.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* Copyright (c) 2011 Xiph.Org Foundation
2 Written by Jean-Marc Valin */
3 /*
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7
8 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "opus_multistream.h"
33 #include "opus.h"
34 #include "opus_private.h"
35 #include "stack_alloc.h"
36 #include <stdarg.h>
37 #include "float_cast.h"
38 #include "os_support.h"
39
40 struct OpusMSDecoder {
41 ChannelLayout layout;
42 /* Decoder states go here */
43 };
44
45
46
47
48 /* DECODER */
49
50 opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_stre ams)
51 {
52 int coupled_size;
53 int mono_size;
54
55 if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0 ;
56 coupled_size = opus_decoder_get_size(2);
57 mono_size = opus_decoder_get_size(1);
58 return align(sizeof(OpusMSDecoder))
59 + nb_coupled_streams * align(coupled_size)
60 + (nb_streams-nb_coupled_streams) * align(mono_size);
61 }
62
63 int opus_multistream_decoder_init(
64 OpusMSDecoder *st,
65 opus_int32 Fs,
66 int channels,
67 int streams,
68 int coupled_streams,
69 const unsigned char *mapping
70 )
71 {
72 int coupled_size;
73 int mono_size;
74 int i, ret;
75 char *ptr;
76
77 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
78 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
79 return OPUS_BAD_ARG;
80
81 st->layout.nb_channels = channels;
82 st->layout.nb_streams = streams;
83 st->layout.nb_coupled_streams = coupled_streams;
84
85 for (i=0;i<st->layout.nb_channels;i++)
86 st->layout.mapping[i] = mapping[i];
87 if (!validate_layout(&st->layout))
88 return OPUS_BAD_ARG;
89
90 ptr = (char*)st + align(sizeof(OpusMSDecoder));
91 coupled_size = opus_decoder_get_size(2);
92 mono_size = opus_decoder_get_size(1);
93
94 for (i=0;i<st->layout.nb_coupled_streams;i++)
95 {
96 ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
97 if(ret!=OPUS_OK)return ret;
98 ptr += align(coupled_size);
99 }
100 for (;i<st->layout.nb_streams;i++)
101 {
102 ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
103 if(ret!=OPUS_OK)return ret;
104 ptr += align(mono_size);
105 }
106 return OPUS_OK;
107 }
108
109
110 OpusMSDecoder *opus_multistream_decoder_create(
111 opus_int32 Fs,
112 int channels,
113 int streams,
114 int coupled_streams,
115 const unsigned char *mapping,
116 int *error
117 )
118 {
119 int ret;
120 OpusMSDecoder *st;
121 if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
122 (coupled_streams+streams>255) || (streams<1) || (coupled_streams<0))
123 {
124 if (error)
125 *error = OPUS_BAD_ARG;
126 return NULL;
127 }
128 st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, c oupled_streams));
129 if (st==NULL)
130 {
131 if (error)
132 *error = OPUS_ALLOC_FAIL;
133 return NULL;
134 }
135 ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_stream s, mapping);
136 if (error)
137 *error = ret;
138 if (ret != OPUS_OK)
139 {
140 opus_free(st);
141 st = NULL;
142 }
143 return st;
144 }
145
146 typedef void (*opus_copy_channel_out_func)(
147 void *dst,
148 int dst_stride,
149 int dst_channel,
150 const opus_val16 *src,
151 int src_stride,
152 int frame_size
153 );
154
155 static int opus_multistream_decode_native(
156 OpusMSDecoder *st,
157 const unsigned char *data,
158 opus_int32 len,
159 void *pcm,
160 opus_copy_channel_out_func copy_channel_out,
161 int frame_size,
162 int decode_fec,
163 int soft_clip
164 )
165 {
166 opus_int32 Fs;
167 int coupled_size;
168 int mono_size;
169 int s, c;
170 char *ptr;
171 int do_plc=0;
172 VARDECL(opus_val16, buf);
173 ALLOC_STACK;
174
175 /* Limit frame_size to avoid excessive stack allocations. */
176 opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs));
177 frame_size = IMIN(frame_size, Fs/25*3);
178 ALLOC(buf, 2*frame_size, opus_val16);
179 ptr = (char*)st + align(sizeof(OpusMSDecoder));
180 coupled_size = opus_decoder_get_size(2);
181 mono_size = opus_decoder_get_size(1);
182
183 if (len==0)
184 do_plc = 1;
185 if (len < 0)
186 return OPUS_BAD_ARG;
187 if (!do_plc && len < 2*st->layout.nb_streams-1)
188 return OPUS_INVALID_PACKET;
189 for (s=0;s<st->layout.nb_streams;s++)
190 {
191 OpusDecoder *dec;
192 int packet_offset, ret;
193
194 dec = (OpusDecoder*)ptr;
195 ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(m ono_size);
196
197 if (!do_plc && len<=0)
198 {
199 RESTORE_STACK;
200 return OPUS_INVALID_PACKET;
201 }
202 packet_offset = 0;
203 ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=s t->layout.nb_streams-1, &packet_offset, soft_clip);
204 data += packet_offset;
205 len -= packet_offset;
206 if (ret > frame_size)
207 {
208 RESTORE_STACK;
209 return OPUS_BUFFER_TOO_SMALL;
210 }
211 if (s>0 && ret != frame_size)
212 {
213 RESTORE_STACK;
214 return OPUS_INVALID_PACKET;
215 }
216 if (ret <= 0)
217 {
218 RESTORE_STACK;
219 return ret;
220 }
221 frame_size = ret;
222 if (s < st->layout.nb_coupled_streams)
223 {
224 int chan, prev;
225 prev = -1;
226 /* Copy "left" audio to the channel(s) where it belongs */
227 while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
228 {
229 (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
230 buf, 2, frame_size);
231 prev = chan;
232 }
233 prev = -1;
234 /* Copy "right" audio to the channel(s) where it belongs */
235 while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
236 {
237 (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
238 buf+1, 2, frame_size);
239 prev = chan;
240 }
241 } else {
242 int chan, prev;
243 prev = -1;
244 /* Copy audio to the channel(s) where it belongs */
245 while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
246 {
247 (*copy_channel_out)(pcm, st->layout.nb_channels, chan,
248 buf, 1, frame_size);
249 prev = chan;
250 }
251 }
252 }
253 /* Handle muted channels */
254 for (c=0;c<st->layout.nb_channels;c++)
255 {
256 if (st->layout.mapping[c] == 255)
257 {
258 (*copy_channel_out)(pcm, st->layout.nb_channels, c,
259 NULL, 0, frame_size);
260 }
261 }
262 RESTORE_STACK;
263 return frame_size;
264 }
265
266 #if !defined(DISABLE_FLOAT_API)
267 static void opus_copy_channel_out_float(
268 void *dst,
269 int dst_stride,
270 int dst_channel,
271 const opus_val16 *src,
272 int src_stride,
273 int frame_size
274 )
275 {
276 float *float_dst;
277 opus_int32 i;
278 float_dst = (float*)dst;
279 if (src != NULL)
280 {
281 for (i=0;i<frame_size;i++)
282 #if defined(FIXED_POINT)
283 float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride];
284 #else
285 float_dst[i*dst_stride+dst_channel] = src[i*src_stride];
286 #endif
287 }
288 else
289 {
290 for (i=0;i<frame_size;i++)
291 float_dst[i*dst_stride+dst_channel] = 0;
292 }
293 }
294 #endif
295
296 static void opus_copy_channel_out_short(
297 void *dst,
298 int dst_stride,
299 int dst_channel,
300 const opus_val16 *src,
301 int src_stride,
302 int frame_size
303 )
304 {
305 opus_int16 *short_dst;
306 opus_int32 i;
307 short_dst = (opus_int16*)dst;
308 if (src != NULL)
309 {
310 for (i=0;i<frame_size;i++)
311 #if defined(FIXED_POINT)
312 short_dst[i*dst_stride+dst_channel] = src[i*src_stride];
313 #else
314 short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]);
315 #endif
316 }
317 else
318 {
319 for (i=0;i<frame_size;i++)
320 short_dst[i*dst_stride+dst_channel] = 0;
321 }
322 }
323
324
325
326 #ifdef FIXED_POINT
327 int opus_multistream_decode(
328 OpusMSDecoder *st,
329 const unsigned char *data,
330 opus_int32 len,
331 opus_int16 *pcm,
332 int frame_size,
333 int decode_fec
334 )
335 {
336 return opus_multistream_decode_native(st, data, len,
337 pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0);
338 }
339
340 #ifndef DISABLE_FLOAT_API
341 int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
342 opus_int32 len, float *pcm, int frame_size, int decode_fec)
343 {
344 return opus_multistream_decode_native(st, data, len,
345 pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
346 }
347 #endif
348
349 #else
350
351 int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
352 opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
353 {
354 return opus_multistream_decode_native(st, data, len,
355 pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1);
356 }
357
358 int opus_multistream_decode_float(
359 OpusMSDecoder *st,
360 const unsigned char *data,
361 opus_int32 len,
362 float *pcm,
363 int frame_size,
364 int decode_fec
365 )
366 {
367 return opus_multistream_decode_native(st, data, len,
368 pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0);
369 }
370 #endif
371
372 int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
373 {
374 va_list ap;
375 int coupled_size, mono_size;
376 char *ptr;
377 int ret = OPUS_OK;
378
379 va_start(ap, request);
380
381 coupled_size = opus_decoder_get_size(2);
382 mono_size = opus_decoder_get_size(1);
383 ptr = (char*)st + align(sizeof(OpusMSDecoder));
384 switch (request)
385 {
386 case OPUS_GET_BANDWIDTH_REQUEST:
387 case OPUS_GET_SAMPLE_RATE_REQUEST:
388 case OPUS_GET_GAIN_REQUEST:
389 case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
390 {
391 OpusDecoder *dec;
392 /* For int32* GET params, just query the first stream */
393 opus_int32 *value = va_arg(ap, opus_int32*);
394 dec = (OpusDecoder*)ptr;
395 ret = opus_decoder_ctl(dec, request, value);
396 }
397 break;
398 case OPUS_GET_FINAL_RANGE_REQUEST:
399 {
400 int s;
401 opus_uint32 *value = va_arg(ap, opus_uint32*);
402 opus_uint32 tmp;
403 if (!value)
404 {
405 goto bad_arg;
406 }
407 *value = 0;
408 for (s=0;s<st->layout.nb_streams;s++)
409 {
410 OpusDecoder *dec;
411 dec = (OpusDecoder*)ptr;
412 if (s < st->layout.nb_coupled_streams)
413 ptr += align(coupled_size);
414 else
415 ptr += align(mono_size);
416 ret = opus_decoder_ctl(dec, request, &tmp);
417 if (ret != OPUS_OK) break;
418 *value ^= tmp;
419 }
420 }
421 break;
422 case OPUS_RESET_STATE:
423 {
424 int s;
425 for (s=0;s<st->layout.nb_streams;s++)
426 {
427 OpusDecoder *dec;
428
429 dec = (OpusDecoder*)ptr;
430 if (s < st->layout.nb_coupled_streams)
431 ptr += align(coupled_size);
432 else
433 ptr += align(mono_size);
434 ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
435 if (ret != OPUS_OK)
436 break;
437 }
438 }
439 break;
440 case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
441 {
442 int s;
443 opus_int32 stream_id;
444 OpusDecoder **value;
445 stream_id = va_arg(ap, opus_int32);
446 if (stream_id<0 || stream_id >= st->layout.nb_streams)
447 ret = OPUS_BAD_ARG;
448 value = va_arg(ap, OpusDecoder**);
449 if (!value)
450 {
451 goto bad_arg;
452 }
453 for (s=0;s<stream_id;s++)
454 {
455 if (s < st->layout.nb_coupled_streams)
456 ptr += align(coupled_size);
457 else
458 ptr += align(mono_size);
459 }
460 *value = (OpusDecoder*)ptr;
461 }
462 break;
463 case OPUS_SET_GAIN_REQUEST:
464 {
465 int s;
466 /* This works for int32 params */
467 opus_int32 value = va_arg(ap, opus_int32);
468 for (s=0;s<st->layout.nb_streams;s++)
469 {
470 OpusDecoder *dec;
471
472 dec = (OpusDecoder*)ptr;
473 if (s < st->layout.nb_coupled_streams)
474 ptr += align(coupled_size);
475 else
476 ptr += align(mono_size);
477 ret = opus_decoder_ctl(dec, request, value);
478 if (ret != OPUS_OK)
479 break;
480 }
481 }
482 break;
483 default:
484 ret = OPUS_UNIMPLEMENTED;
485 break;
486 }
487
488 va_end(ap);
489 return ret;
490 bad_arg:
491 va_end(ap);
492 return OPUS_BAD_ARG;
493 }
494
495
496 void opus_multistream_decoder_destroy(OpusMSDecoder *st)
497 {
498 opus_free(st);
499 }
OLDNEW
« no previous file with comments | « src/opus_multistream.c ('k') | src/opus_multistream_encoder.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698