1 /*****************************************************************************
2 * opus.c: opus decoder/encoder module making use of libopus.
3 *****************************************************************************
4 * Copyright (C) 2003-2009, 2012 VLC authors and VideoLAN
6 * Authors: Gregory Maxwell <greg@xiph.org>
7 * Based on speex.c by: Gildas Bazin <gbazin@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_input.h>
34 #include <vlc_codec.h>
36 #include "../demux/xiph.h"
40 #include <opus_multistream.h>
42 #include "opus_header.h"
48 /*****************************************************************************
50 *****************************************************************************/
51 static int OpenDecoder ( vlc_object_t
* );
52 static void CloseDecoder ( vlc_object_t
* );
54 static int OpenEncoder ( vlc_object_t
* );
55 static void CloseEncoder ( vlc_object_t
* );
59 set_category( CAT_INPUT
)
60 set_subcategory( SUBCAT_INPUT_ACODEC
)
62 set_description( N_("Opus audio decoder") )
63 set_capability( "audio decoder", 100 )
64 set_shortname( N_("Opus") )
65 set_callbacks( OpenDecoder
, CloseDecoder
)
69 set_description( N_("Opus audio encoder") )
70 set_capability( "encoder", 150 )
71 set_shortname( N_("Opus") )
72 set_callbacks( OpenEncoder
, CloseEncoder
)
77 /*****************************************************************************
78 * decoder_sys_t : opus decoder descriptor
79 *****************************************************************************/
99 static const int pi_channels_maps
[9] =
103 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
,
104 AOUT_CHAN_CENTER
| AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
,
105 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_REARLEFT
106 | AOUT_CHAN_REARRIGHT
,
107 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
108 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
,
109 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
110 | AOUT_CHAN_REARLEFT
| AOUT_CHAN_REARRIGHT
| AOUT_CHAN_LFE
,
111 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
112 | AOUT_CHAN_REARCENTER
| AOUT_CHAN_MIDDLELEFT
113 | AOUT_CHAN_MIDDLERIGHT
| AOUT_CHAN_LFE
,
114 AOUT_CHAN_LEFT
| AOUT_CHAN_RIGHT
| AOUT_CHAN_CENTER
| AOUT_CHAN_REARLEFT
115 | AOUT_CHAN_REARRIGHT
| AOUT_CHAN_MIDDLELEFT
| AOUT_CHAN_MIDDLERIGHT
120 ** channel order as defined in http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9
123 /* recommended vorbis channel order for 8 channels */
124 static const uint32_t pi_8channels_in
[] =
125 { AOUT_CHAN_LEFT
, AOUT_CHAN_CENTER
, AOUT_CHAN_RIGHT
,
126 AOUT_CHAN_MIDDLELEFT
, AOUT_CHAN_MIDDLERIGHT
,
127 AOUT_CHAN_REARLEFT
, AOUT_CHAN_REARRIGHT
,AOUT_CHAN_LFE
, 0 };
129 /* recommended vorbis channel order for 7 channels */
130 static const uint32_t pi_7channels_in
[] =
131 { AOUT_CHAN_LEFT
, AOUT_CHAN_CENTER
, AOUT_CHAN_RIGHT
,
132 AOUT_CHAN_MIDDLELEFT
, AOUT_CHAN_MIDDLERIGHT
,
133 AOUT_CHAN_REARCENTER
, AOUT_CHAN_LFE
, 0 };
135 /* recommended vorbis channel order for 6 channels */
136 static const uint32_t pi_6channels_in
[] =
137 { AOUT_CHAN_LEFT
, AOUT_CHAN_CENTER
, AOUT_CHAN_RIGHT
,
138 AOUT_CHAN_REARLEFT
, AOUT_CHAN_REARRIGHT
, AOUT_CHAN_LFE
, 0 };
140 /* recommended vorbis channel order for 5 channels */
141 static const uint32_t pi_5channels_in
[] =
142 { AOUT_CHAN_LEFT
, AOUT_CHAN_CENTER
, AOUT_CHAN_RIGHT
,
143 AOUT_CHAN_REARLEFT
, AOUT_CHAN_REARRIGHT
, 0 };
145 /* recommended vorbis channel order for 4 channels */
146 static const uint32_t pi_4channels_in
[] =
147 { AOUT_CHAN_LEFT
, AOUT_CHAN_RIGHT
, AOUT_CHAN_REARLEFT
, AOUT_CHAN_REARRIGHT
, 0 };
149 /* recommended vorbis channel order for 3 channels */
150 static const uint32_t pi_3channels_in
[] =
151 { AOUT_CHAN_LEFT
, AOUT_CHAN_CENTER
, AOUT_CHAN_RIGHT
, 0 };
153 /****************************************************************************
155 ****************************************************************************/
157 static block_t
*Packetize ( decoder_t
*, block_t
** );
158 static int DecodeAudio ( decoder_t
*, block_t
* );
159 static void Flush( decoder_t
* );
160 static int ProcessHeaders( decoder_t
* );
161 static int ProcessInitialHeader ( decoder_t
*, ogg_packet
* );
162 static block_t
*ProcessPacket( decoder_t
*, ogg_packet
*, block_t
* );
164 static block_t
*DecodePacket( decoder_t
*, ogg_packet
*, int, int );
166 /*****************************************************************************
167 * OpenDecoder: probe the decoder and return score
168 *****************************************************************************/
169 static int OpenDecoder( vlc_object_t
*p_this
)
171 decoder_t
*p_dec
= (decoder_t
*)p_this
;
172 decoder_sys_t
*p_sys
;
174 if( p_dec
->fmt_in
.i_codec
!= VLC_CODEC_OPUS
)
177 /* Allocate the memory needed to store the decoder's structure */
178 if( ( p_dec
->p_sys
= p_sys
= malloc(sizeof(decoder_sys_t
)) ) == NULL
)
180 p_dec
->p_sys
->b_has_headers
= false;
182 date_Set( &p_sys
->end_date
, 0 );
184 /* Set output properties */
185 p_dec
->fmt_out
.i_codec
= VLC_CODEC_FL32
;
187 p_dec
->pf_decode
= DecodeAudio
;
188 p_dec
->pf_packetize
= Packetize
;
189 p_dec
->pf_flush
= Flush
;
196 /****************************************************************************
197 * DecodeBlock: the whole thing
198 ****************************************************************************
199 * This function must be fed with ogg packets.
200 ****************************************************************************/
201 static block_t
*DecodeBlock( decoder_t
*p_dec
, block_t
*p_block
)
203 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
204 ogg_packet oggpacket
;
206 /* Block to Ogg packet */
207 oggpacket
.packet
= p_block
->p_buffer
;
208 oggpacket
.bytes
= p_block
->i_buffer
;
210 oggpacket
.granulepos
= -1;
213 oggpacket
.packetno
= 0;
215 /* Check for headers */
216 if( !p_sys
->b_has_headers
)
218 if( ProcessHeaders( p_dec
) )
220 block_Release( p_block
);
223 p_sys
->b_has_headers
= true;
226 return ProcessPacket( p_dec
, &oggpacket
, p_block
);
229 static int DecodeAudio( decoder_t
*p_dec
, block_t
*p_block
)
231 if( p_block
== NULL
) /* No Drain */
232 return VLCDEC_SUCCESS
;
234 p_block
= DecodeBlock( p_dec
, p_block
);
235 if( p_block
!= NULL
)
236 decoder_QueueAudio( p_dec
, p_block
);
237 return VLCDEC_SUCCESS
;
240 static block_t
*Packetize( decoder_t
*p_dec
, block_t
**pp_block
)
242 if( pp_block
== NULL
) /* No Drain */
244 block_t
*p_block
= *pp_block
; *pp_block
= NULL
;
245 if( p_block
== NULL
)
247 return DecodeBlock( p_dec
, p_block
);
250 /*****************************************************************************
251 * ProcessHeaders: process Opus headers.
252 *****************************************************************************/
253 static int ProcessHeaders( decoder_t
*p_dec
)
255 ogg_packet oggpacket
;
257 unsigned pi_size
[XIPH_MAX_HEADER_COUNT
];
258 void *pp_data
[XIPH_MAX_HEADER_COUNT
];
261 int i_extra
= p_dec
->fmt_in
.i_extra
;
262 uint8_t *p_extra
= p_dec
->fmt_in
.p_extra
;
264 /* If we have no header (e.g. from RTP), make one. */
265 bool b_dummy_header
= false;
267 (i_extra
> 10 && memcmp( &p_extra
[2], "OpusHead", 8 )) ) /* Borked muxers */
270 opus_prepare_header( p_dec
->fmt_in
.audio
.i_channels
,
271 p_dec
->fmt_in
.audio
.i_rate
, &header
);
272 if( opus_write_header( &p_extra
, &i_extra
, &header
,
273 opus_get_version_string() ) )
275 b_dummy_header
= true;
278 if( xiph_SplitHeaders( pi_size
, pp_data
, &i_count
,
293 oggpacket
.granulepos
= -1;
295 oggpacket
.packetno
= 0;
297 /* Take care of the initial Opus header */
298 oggpacket
.b_o_s
= 1; /* yes this actually is a b_o_s packet :) */
299 oggpacket
.bytes
= pi_size
[0];
300 oggpacket
.packet
= pp_data
[0];
301 int ret
= ProcessInitialHeader( p_dec
, &oggpacket
);
303 if (ret
!= VLC_SUCCESS
)
304 msg_Err( p_dec
, "initial Opus header is corrupted" );
312 /*****************************************************************************
313 * ProcessInitialHeader: processes the inital Opus header packet.
314 *****************************************************************************/
315 static int ProcessInitialHeader( decoder_t
*p_dec
, ogg_packet
*p_oggpacket
)
318 unsigned char new_stream_map
[8];
319 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
321 OpusHeader
*p_header
= &p_sys
->header
;
323 if( !opus_header_parse((unsigned char *)p_oggpacket
->packet
,p_oggpacket
->bytes
,p_header
) )
325 msg_Err( p_dec
, "cannot read Opus header" );
328 msg_Dbg( p_dec
, "Opus audio with %d channels", p_header
->channels
);
330 if((p_header
->channels
>2 && p_header
->channel_mapping
==0) ||
331 p_header
->channels
>8 ||
332 p_header
->channel_mapping
>1)
334 msg_Err( p_dec
, "Unsupported channel mapping" );
338 /* Setup the format */
339 p_dec
->fmt_out
.audio
.i_physical_channels
=
340 pi_channels_maps
[p_header
->channels
];
341 p_dec
->fmt_out
.audio
.i_channels
= p_header
->channels
;
342 p_dec
->fmt_out
.audio
.i_rate
= 48000;
344 if( p_header
->channels
>2 )
346 static const uint32_t *pi_ch
[6] = { pi_3channels_in
, pi_4channels_in
,
347 pi_5channels_in
, pi_6channels_in
,
348 pi_7channels_in
, pi_8channels_in
};
349 uint8_t pi_chan_table
[AOUT_CHAN_MAX
];
351 aout_CheckChannelReorder( pi_ch
[p_header
->channels
-3], NULL
,
352 p_dec
->fmt_out
.audio
.i_physical_channels
,
354 for(int i
=0;i
<p_header
->channels
;i
++)
355 new_stream_map
[pi_chan_table
[i
]]=p_header
->stream_map
[i
];
357 /* Opus decoder init */
358 p_sys
->p_st
= opus_multistream_decoder_create( 48000, p_header
->channels
,
359 p_header
->nb_streams
, p_header
->nb_coupled
,
360 p_header
->channels
>2?new_stream_map
:p_header
->stream_map
,
362 if( !p_sys
->p_st
|| err
!=OPUS_OK
)
364 msg_Err( p_dec
, "decoder initialization failed" );
369 if( opus_multistream_decoder_ctl( p_sys
->p_st
,OPUS_SET_GAIN(p_header
->gain
) ) != OPUS_OK
)
371 msg_Err( p_dec
, "OPUS_SET_GAIN failed" );
372 opus_multistream_decoder_destroy( p_sys
->p_st
);
377 date_Init( &p_sys
->end_date
, 48000, 1 );
382 /*****************************************************************************
384 *****************************************************************************/
385 static void Flush( decoder_t
*p_dec
)
387 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
389 date_Set( &p_sys
->end_date
, 0 );
392 /*****************************************************************************
393 * ProcessPacket: processes a Opus packet.
394 *****************************************************************************/
395 static block_t
*ProcessPacket( decoder_t
*p_dec
, ogg_packet
*p_oggpacket
,
398 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
400 if( p_block
->i_flags
& (BLOCK_FLAG_CORRUPTED
|BLOCK_FLAG_DISCONTINUITY
) )
403 if( p_block
->i_flags
& BLOCK_FLAG_CORRUPTED
)
405 block_Release( p_block
);
410 /* Date management */
411 if( p_block
->i_pts
> VLC_TS_INVALID
&&
412 p_block
->i_pts
!= date_Get( &p_sys
->end_date
) )
414 date_Set( &p_sys
->end_date
, p_block
->i_pts
);
417 if( !date_Get( &p_sys
->end_date
) )
419 /* We've just started the stream, wait for the first PTS. */
420 block_Release( p_block
);
424 block_t
*p_aout_buffer
= DecodePacket( p_dec
, p_oggpacket
,
425 p_block
->i_nb_samples
,
426 (int)p_block
->i_length
);
428 block_Release( p_block
);
429 return p_aout_buffer
;
432 /*****************************************************************************
433 * DecodePacket: decodes a Opus packet.
434 *****************************************************************************/
435 static block_t
*DecodePacket( decoder_t
*p_dec
, ogg_packet
*p_oggpacket
,
436 int i_nb_samples
, int i_end_trim
)
438 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
440 if( !p_oggpacket
->bytes
)
444 spp
=opus_packet_get_nb_frames(p_oggpacket
->packet
,p_oggpacket
->bytes
);
445 if(spp
>0)spp
*=opus_packet_get_samples_per_frame(p_oggpacket
->packet
,48000);
446 if(spp
<120||spp
>120*48)return NULL
;
448 /* Since the information isn't always available at the demux level
449 * use the packet's sample number */
453 if( decoder_UpdateAudioFormat( p_dec
) )
455 block_t
*p_aout_buffer
=decoder_NewAudioBuffer( p_dec
, spp
);
456 if ( !p_aout_buffer
)
458 msg_Err(p_dec
, "Oops: No new buffer was returned!");
462 spp
=opus_multistream_decode_float(p_sys
->p_st
, p_oggpacket
->packet
,
463 p_oggpacket
->bytes
, (float *)p_aout_buffer
->p_buffer
, spp
, 0);
464 if( spp
< 0 || i_nb_samples
<= 0 || i_end_trim
>= i_nb_samples
)
466 block_Release(p_aout_buffer
);
468 msg_Err( p_dec
, "Error: corrupted stream?" );
472 p_aout_buffer
->i_buffer
= (i_nb_samples
- i_end_trim
) *
473 p_sys
->header
.channels
* sizeof(float);
475 if( spp
> i_nb_samples
)
477 memmove(p_aout_buffer
->p_buffer
,
478 p_aout_buffer
->p_buffer
479 + (spp
- i_nb_samples
)*p_sys
->header
.channels
*sizeof(float),
480 p_aout_buffer
->i_buffer
);
482 i_nb_samples
-= i_end_trim
;
484 #ifndef OPUS_SET_GAIN
485 if(p_sys
->header
.gain
!=0)
487 float gain
= pow(10., p_sys
->header
.gain
/5120.);
488 float *buf
=(float *)p_aout_buffer
->p_buffer
;
489 for( int i
= 0; i
< i_nb_samples
*p_sys
->header
.channels
; i
++)
493 p_aout_buffer
->i_nb_samples
= i_nb_samples
;
494 p_aout_buffer
->i_pts
= date_Get( &p_sys
->end_date
);
495 p_aout_buffer
->i_length
= date_Increment( &p_sys
->end_date
, i_nb_samples
)
496 - p_aout_buffer
->i_pts
;
497 return p_aout_buffer
;
500 /*****************************************************************************
501 * CloseDecoder: Opus decoder destruction
502 *****************************************************************************/
503 static void CloseDecoder( vlc_object_t
*p_this
)
505 decoder_t
* p_dec
= (decoder_t
*)p_this
;
506 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
508 if( p_sys
->p_st
) opus_multistream_decoder_destroy(p_sys
->p_st
);
515 /* only ever encode 20 ms at a time, going longer doesn't yield much compression
516 gain, shorter does have a compression loss, and doesn't matter so much in
517 Ogg, unless you really need low latency, which would also require muxing one
519 static const unsigned OPUS_FRAME_SIZE
= 960; /* 48000 * 20 / 1000 */
525 unsigned i_nb_samples
;
531 static unsigned fill_buffer(encoder_t
*enc
, unsigned src_start
, block_t
*src
,
534 encoder_sys_t
*p_sys
= enc
->p_sys
;
535 const unsigned channels
= enc
->fmt_out
.audio
.i_channels
;
536 const float *src_buf
= ((const float *) src
->p_buffer
) + src_start
;
537 float *dest_buf
= p_sys
->buffer
+ (p_sys
->i_nb_samples
* channels
);
538 const unsigned len
= samples
* channels
;
540 memcpy(dest_buf
, src_buf
, len
* sizeof(float));
542 p_sys
->i_nb_samples
+= samples
;
545 src
->i_nb_samples
-= samples
;
549 static block_t
*Encode(encoder_t
*enc
, block_t
*buf
)
551 encoder_sys_t
*sys
= enc
->p_sys
;
556 mtime_t i_pts
= buf
->i_pts
-
557 (mtime_t
) CLOCK_FREQ
* (mtime_t
) sys
->i_samples_delay
/
558 (mtime_t
) enc
->fmt_in
.audio
.i_rate
;
560 sys
->i_samples_delay
+= buf
->i_nb_samples
;
562 block_t
*result
= NULL
;
563 unsigned src_start
= 0;
564 unsigned padding_start
= 0;
565 /* The maximum Opus frame size is 1275 bytes + TOC sequence length. */
566 const unsigned OPUS_MAX_ENCODED_BYTES
= ((1275 + 3) * sys
->nb_streams
) - 2;
568 while (sys
->i_nb_samples
+ buf
->i_nb_samples
>= OPUS_FRAME_SIZE
)
570 block_t
*out_block
= block_Alloc(OPUS_MAX_ENCODED_BYTES
);
572 /* add padding to beginning */
575 const size_t leftover_space
= OPUS_FRAME_SIZE
- sys
->i_nb_samples
;
576 padding_start
= fill_buffer(enc
, padding_start
, sys
->padding
,
577 __MIN(sys
->padding
->i_nb_samples
, leftover_space
));
578 if (sys
->padding
->i_nb_samples
<= 0)
580 block_Release(sys
->padding
);
585 /* padding may have been freed either before or inside previous
589 const size_t leftover_space
= OPUS_FRAME_SIZE
- sys
->i_nb_samples
;
590 src_start
= fill_buffer(enc
, src_start
, buf
,
591 __MIN(buf
->i_nb_samples
, leftover_space
));
594 opus_int32 bytes_encoded
= opus_multistream_encode_float(sys
->enc
, sys
->buffer
,
595 OPUS_FRAME_SIZE
, out_block
->p_buffer
, out_block
->i_buffer
);
597 if (bytes_encoded
< 0)
599 block_Release(out_block
);
603 out_block
->i_length
= (mtime_t
) CLOCK_FREQ
*
604 (mtime_t
) OPUS_FRAME_SIZE
/ (mtime_t
) enc
->fmt_in
.audio
.i_rate
;
606 out_block
->i_dts
= out_block
->i_pts
= i_pts
;
608 sys
->i_samples_delay
-= OPUS_FRAME_SIZE
;
610 i_pts
+= out_block
->i_length
;
612 sys
->i_nb_samples
= 0;
614 out_block
->i_buffer
= bytes_encoded
;
615 block_ChainAppend(&result
, out_block
);
619 /* put leftover samples at beginning of buffer */
620 if (buf
->i_nb_samples
> 0)
621 fill_buffer(enc
, src_start
, buf
, buf
->i_nb_samples
);
626 static int OpenEncoder(vlc_object_t
*p_this
)
628 encoder_t
*enc
= (encoder_t
*)p_this
;
630 if (enc
->fmt_out
.i_codec
!= VLC_CODEC_OPUS
)
633 encoder_sys_t
*sys
= malloc(sizeof(*sys
));
637 int status
= VLC_SUCCESS
;
641 enc
->pf_encode_audio
= Encode
;
642 enc
->fmt_in
.i_codec
= VLC_CODEC_FL32
;
643 enc
->fmt_in
.audio
.i_rate
= /* Only 48kHz */
644 enc
->fmt_out
.audio
.i_rate
= 48000;
645 enc
->fmt_out
.audio
.i_channels
= enc
->fmt_in
.audio
.i_channels
;
649 opus_prepare_header(enc
->fmt_out
.audio
.i_channels
,
650 enc
->fmt_out
.audio
.i_rate
, &header
);
652 /* needed for max encoded size calculation */
653 sys
->nb_streams
= header
.nb_streams
;
657 opus_multistream_surround_encoder_create(enc
->fmt_in
.audio
.i_rate
,
658 enc
->fmt_in
.audio
.i_channels
, header
.channel_mapping
,
659 &header
.nb_streams
, &header
.nb_coupled
, header
.stream_map
,
660 OPUS_APPLICATION_AUDIO
, &err
);
664 msg_Err(enc
, "Could not create encoder: error %d", err
);
666 status
= VLC_EGENERIC
;
672 if( enc
->fmt_out
.i_bitrate
)
673 opus_multistream_encoder_ctl(sys
->enc
, OPUS_SET_BITRATE( enc
->fmt_out
.i_bitrate
));
675 /* Buffer for incoming audio, since opus only accepts frame sizes that are
676 multiples of 2.5ms */
678 sys
->buffer
= vlc_alloc(header
.channels
, sizeof(float) * OPUS_FRAME_SIZE
);
684 sys
->i_nb_samples
= 0;
686 sys
->i_samples_delay
= 0;
687 int ret
= opus_multistream_encoder_ctl(enc
->p_sys
->enc
,
688 OPUS_GET_LOOKAHEAD(&sys
->i_samples_delay
));
690 msg_Err(enc
, "Unable to get number of lookahead samples: %s\n",
693 header
.preskip
= sys
->i_samples_delay
;
695 /* Now that we have preskip, we can write the header to extradata */
696 if (opus_write_header((uint8_t **) &enc
->fmt_out
.p_extra
,
697 &enc
->fmt_out
.i_extra
, &header
, opus_get_version_string()))
699 msg_Err(enc
, "Failed to write header.");
704 if (sys
->i_samples_delay
> 0)
706 const unsigned padding_samples
= sys
->i_samples_delay
*
707 enc
->fmt_out
.audio
.i_channels
;
708 sys
->padding
= block_Alloc(padding_samples
* sizeof(float));
713 sys
->padding
->i_nb_samples
= sys
->i_samples_delay
;
714 float *pad_ptr
= (float *) sys
->padding
->p_buffer
;
715 memset(pad_ptr
, 0, padding_samples
* sizeof(float));
726 opus_multistream_encoder_destroy(sys
->enc
);
732 static void CloseEncoder(vlc_object_t
*p_this
)
734 encoder_t
*enc
= (encoder_t
*)p_this
;
735 encoder_sys_t
*sys
= enc
->p_sys
;
737 opus_multistream_encoder_destroy(sys
->enc
);
739 block_Release(sys
->padding
);
743 #endif /* ENABLE_SOUT */