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 int DecodeAudio ( decoder_t
*, block_t
* );
158 static void Flush( decoder_t
* );
159 static int ProcessHeaders( decoder_t
* );
160 static int ProcessInitialHeader ( decoder_t
*, ogg_packet
* );
161 static block_t
*ProcessPacket( decoder_t
*, ogg_packet
*, block_t
* );
163 static block_t
*DecodePacket( decoder_t
*, ogg_packet
*, int, vlc_tick_t
);
165 /*****************************************************************************
166 * OpenDecoder: probe the decoder and return score
167 *****************************************************************************/
168 static int OpenDecoder( vlc_object_t
*p_this
)
170 decoder_t
*p_dec
= (decoder_t
*)p_this
;
171 decoder_sys_t
*p_sys
;
173 if( p_dec
->fmt_in
.i_codec
!= VLC_CODEC_OPUS
)
176 /* Allocate the memory needed to store the decoder's structure */
177 if( ( p_dec
->p_sys
= p_sys
= malloc(sizeof(decoder_sys_t
)) ) == NULL
)
179 p_sys
->b_has_headers
= false;
181 date_Set( &p_sys
->end_date
, VLC_TICK_INVALID
);
183 /* Set output properties */
184 p_dec
->fmt_out
.i_codec
= VLC_CODEC_FL32
;
186 p_dec
->pf_decode
= DecodeAudio
;
187 p_dec
->pf_flush
= Flush
;
194 /****************************************************************************
195 * DecodeBlock: the whole thing
196 ****************************************************************************
197 * This function must be fed with ogg packets.
198 ****************************************************************************/
199 static block_t
*DecodeBlock( decoder_t
*p_dec
, block_t
*p_block
)
201 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
202 ogg_packet oggpacket
;
204 /* Block to Ogg packet */
205 oggpacket
.packet
= p_block
->p_buffer
;
206 oggpacket
.bytes
= p_block
->i_buffer
;
208 oggpacket
.granulepos
= -1;
211 oggpacket
.packetno
= 0;
213 /* Check for headers */
214 if( !p_sys
->b_has_headers
)
216 if( ProcessHeaders( p_dec
) )
218 block_Release( p_block
);
221 p_sys
->b_has_headers
= true;
224 return ProcessPacket( p_dec
, &oggpacket
, p_block
);
227 static int DecodeAudio( decoder_t
*p_dec
, block_t
*p_block
)
229 if( p_block
== NULL
) /* No Drain */
230 return VLCDEC_SUCCESS
;
232 p_block
= DecodeBlock( p_dec
, p_block
);
233 if( p_block
!= NULL
)
234 decoder_QueueAudio( p_dec
, p_block
);
235 return VLCDEC_SUCCESS
;
238 /*****************************************************************************
239 * ProcessHeaders: process Opus headers.
240 *****************************************************************************/
241 static int ProcessHeaders( decoder_t
*p_dec
)
243 ogg_packet oggpacket
;
245 unsigned pi_size
[XIPH_MAX_HEADER_COUNT
];
246 void *pp_data
[XIPH_MAX_HEADER_COUNT
];
249 int i_extra
= p_dec
->fmt_in
.i_extra
;
250 uint8_t *p_extra
= p_dec
->fmt_in
.p_extra
;
252 /* If we have no header (e.g. from RTP), make one. */
253 bool b_dummy_header
= false;
255 (i_extra
> 10 && memcmp( &p_extra
[2], "OpusHead", 8 )) ) /* Borked muxers */
258 opus_prepare_header( p_dec
->fmt_in
.audio
.i_channels
,
259 p_dec
->fmt_in
.audio
.i_rate
, &header
);
260 if( opus_write_header( &p_extra
, &i_extra
, &header
,
261 opus_get_version_string() ) )
263 b_dummy_header
= true;
266 if( xiph_SplitHeaders( pi_size
, pp_data
, &i_count
,
281 oggpacket
.granulepos
= -1;
283 oggpacket
.packetno
= 0;
285 /* Take care of the initial Opus header */
286 oggpacket
.b_o_s
= 1; /* yes this actually is a b_o_s packet :) */
287 oggpacket
.bytes
= pi_size
[0];
288 oggpacket
.packet
= pp_data
[0];
289 int ret
= ProcessInitialHeader( p_dec
, &oggpacket
);
291 if (ret
!= VLC_SUCCESS
)
292 msg_Err( p_dec
, "initial Opus header is corrupted" );
300 /*****************************************************************************
301 * ProcessInitialHeader: processes the inital Opus header packet.
302 *****************************************************************************/
303 static int ProcessInitialHeader( decoder_t
*p_dec
, ogg_packet
*p_oggpacket
)
306 unsigned char* p_stream_map
;
307 unsigned char new_stream_map
[8];
308 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
310 OpusHeader
*p_header
= &p_sys
->header
;
312 if( !opus_header_parse((unsigned char *)p_oggpacket
->packet
,p_oggpacket
->bytes
,p_header
) )
314 msg_Err( p_dec
, "cannot read Opus header" );
317 msg_Dbg( p_dec
, "Opus audio with %d channels", p_header
->channels
);
319 if((p_header
->channels
>2 && p_header
->channel_mapping
==0) ||
320 (p_header
->channels
>8 && p_header
->channel_mapping
==1) ||
321 (p_header
->channels
>18 && p_header
->channel_mapping
==2) ||
322 p_header
->channel_mapping
>2)
324 msg_Err( p_dec
, "Unsupported channel mapping" );
327 if (p_header
->channel_mapping
== 2)
329 int i_order
= floor(sqrt(p_header
->channels
));
330 int i_nondiegetic
= p_header
->channels
- i_order
* i_order
;
331 if (i_nondiegetic
!= 0 && i_nondiegetic
!= 2)
333 msg_Err( p_dec
, "Unsupported ambisonic channel mapping" );
338 /* Setup the format */
339 p_dec
->fmt_out
.audio
.i_channels
= p_header
->channels
;
340 p_dec
->fmt_out
.audio
.i_rate
= 48000;
342 if (p_header
->channel_mapping
<= 1)
344 p_dec
->fmt_out
.audio
.i_physical_channels
=
345 pi_channels_maps
[p_header
->channels
];
347 if( p_header
->channels
>2 )
349 static const uint32_t *pi_ch
[6] = { pi_3channels_in
, pi_4channels_in
,
350 pi_5channels_in
, pi_6channels_in
,
351 pi_7channels_in
, pi_8channels_in
};
352 uint8_t pi_chan_table
[AOUT_CHAN_MAX
];
354 aout_CheckChannelReorder( pi_ch
[p_header
->channels
-3], NULL
,
355 p_dec
->fmt_out
.audio
.i_physical_channels
,
357 for(int i
=0;i
<p_header
->channels
;i
++)
358 new_stream_map
[pi_chan_table
[i
]]=p_header
->stream_map
[i
];
360 p_stream_map
= new_stream_map
;
363 p_stream_map
= p_header
->stream_map
;
365 else //p_header->channel_mapping == 2
367 p_dec
->fmt_out
.audio
.channel_type
= AUDIO_CHANNEL_TYPE_AMBISONICS
;
368 p_stream_map
= p_header
->stream_map
;
371 /* Opus decoder init */
372 p_sys
->p_st
= opus_multistream_decoder_create( 48000, p_header
->channels
,
373 p_header
->nb_streams
, p_header
->nb_coupled
,
376 if( !p_sys
->p_st
|| err
!=OPUS_OK
)
378 msg_Err( p_dec
, "decoder initialization failed" );
383 if( opus_multistream_decoder_ctl( p_sys
->p_st
,OPUS_SET_GAIN(p_header
->gain
) ) != OPUS_OK
)
385 msg_Err( p_dec
, "OPUS_SET_GAIN failed" );
386 opus_multistream_decoder_destroy( p_sys
->p_st
);
391 date_Init( &p_sys
->end_date
, 48000, 1 );
396 /*****************************************************************************
398 *****************************************************************************/
399 static void Flush( decoder_t
*p_dec
)
401 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
403 date_Set( &p_sys
->end_date
, VLC_TICK_INVALID
);
406 /*****************************************************************************
407 * ProcessPacket: processes a Opus packet.
408 *****************************************************************************/
409 static block_t
*ProcessPacket( decoder_t
*p_dec
, ogg_packet
*p_oggpacket
,
412 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
414 if( p_block
->i_flags
& (BLOCK_FLAG_CORRUPTED
|BLOCK_FLAG_DISCONTINUITY
) )
417 if( p_block
->i_flags
& BLOCK_FLAG_CORRUPTED
)
419 block_Release( p_block
);
424 /* Date management */
425 if( p_block
->i_pts
!= VLC_TICK_INVALID
&&
426 p_block
->i_pts
!= date_Get( &p_sys
->end_date
) )
428 date_Set( &p_sys
->end_date
, p_block
->i_pts
);
431 if( date_Get( &p_sys
->end_date
) == VLC_TICK_INVALID
)
433 /* We've just started the stream, wait for the first PTS. */
434 block_Release( p_block
);
439 vlc_tick_t i_max_duration
= (p_block
->i_flags
& BLOCK_FLAG_END_OF_SEQUENCE
) ?
440 p_block
->i_length
: 0;
442 block_t
*p_aout_buffer
= DecodePacket( p_dec
, p_oggpacket
,
443 p_block
->i_nb_samples
,
446 block_Release( p_block
);
447 return p_aout_buffer
;
450 /*****************************************************************************
451 * DecodePacket: decodes a Opus packet.
452 *****************************************************************************/
453 static block_t
*DecodePacket( decoder_t
*p_dec
, ogg_packet
*p_oggpacket
,
454 int i_nb_samples
, vlc_tick_t i_duration
)
456 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
458 if( !p_oggpacket
->bytes
)
462 spp
=opus_packet_get_nb_frames(p_oggpacket
->packet
,p_oggpacket
->bytes
);
463 if(spp
>0)spp
*=opus_packet_get_samples_per_frame(p_oggpacket
->packet
,48000);
464 if(spp
<120||spp
>120*48)return NULL
;
466 /* Since the information isn't always available at the demux level
467 * use the packet's sample number */
471 if( decoder_UpdateAudioFormat( p_dec
) )
473 block_t
*p_aout_buffer
=decoder_NewAudioBuffer( p_dec
, spp
);
474 if ( !p_aout_buffer
)
476 msg_Err(p_dec
, "Oops: No new buffer was returned!");
480 spp
=opus_multistream_decode_float(p_sys
->p_st
, p_oggpacket
->packet
,
481 p_oggpacket
->bytes
, (float *)p_aout_buffer
->p_buffer
, spp
, 0);
484 if( i_duration
> 0 && spp
> 0 &&
485 i_duration
< vlc_tick_from_samples(i_nb_samples
, 48000) )
487 i_end_trim
= spp
- VLC_CLIP(samples_from_vlc_tick(i_duration
, 48000), 0, spp
);
490 if( spp
< 0 || i_nb_samples
<= 0 || i_end_trim
>= i_nb_samples
)
492 block_Release(p_aout_buffer
);
494 msg_Err( p_dec
, "Error: corrupted stream?" );
498 p_aout_buffer
->i_buffer
= (i_nb_samples
- i_end_trim
) *
499 p_sys
->header
.channels
* sizeof(float);
501 if( spp
> i_nb_samples
)
503 memmove(p_aout_buffer
->p_buffer
,
504 p_aout_buffer
->p_buffer
505 + (spp
- i_nb_samples
)*p_sys
->header
.channels
*sizeof(float),
506 p_aout_buffer
->i_buffer
);
508 i_nb_samples
-= i_end_trim
;
510 #ifndef OPUS_SET_GAIN
511 if(p_sys
->header
.gain
!=0)
513 float gain
= pow(10., p_sys
->header
.gain
/5120.);
514 float *buf
=(float *)p_aout_buffer
->p_buffer
;
515 for( int i
= 0; i
< i_nb_samples
*p_sys
->header
.channels
; i
++)
519 p_aout_buffer
->i_nb_samples
= i_nb_samples
;
520 p_aout_buffer
->i_pts
= date_Get( &p_sys
->end_date
);
521 p_aout_buffer
->i_length
= date_Increment( &p_sys
->end_date
, i_nb_samples
)
522 - p_aout_buffer
->i_pts
;
523 return p_aout_buffer
;
526 /*****************************************************************************
527 * CloseDecoder: Opus decoder destruction
528 *****************************************************************************/
529 static void CloseDecoder( vlc_object_t
*p_this
)
531 decoder_t
* p_dec
= (decoder_t
*)p_this
;
532 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
534 if( p_sys
->p_st
) opus_multistream_decoder_destroy(p_sys
->p_st
);
541 /* only ever encode 20 ms at a time, going longer doesn't yield much compression
542 gain, shorter does have a compression loss, and doesn't matter so much in
543 Ogg, unless you really need low latency, which would also require muxing one
545 static const unsigned OPUS_FRAME_SIZE
= 960; /* 48000 * 20 / 1000 */
551 unsigned i_nb_samples
;
557 static unsigned fill_buffer(encoder_t
*enc
, unsigned src_start
, block_t
*src
,
560 encoder_sys_t
*p_sys
= enc
->p_sys
;
561 const unsigned channels
= enc
->fmt_out
.audio
.i_channels
;
562 const float *src_buf
= ((const float *) src
->p_buffer
) + src_start
;
563 float *dest_buf
= p_sys
->buffer
+ (p_sys
->i_nb_samples
* channels
);
564 const unsigned len
= samples
* channels
;
566 memcpy(dest_buf
, src_buf
, len
* sizeof(float));
568 p_sys
->i_nb_samples
+= samples
;
571 src
->i_nb_samples
-= samples
;
575 static block_t
*Encode(encoder_t
*enc
, block_t
*buf
)
577 encoder_sys_t
*sys
= enc
->p_sys
;
582 vlc_tick_t i_pts
= buf
->i_pts
-
583 vlc_tick_from_samples( sys
->i_samples_delay
,
584 enc
->fmt_in
.audio
.i_rate
);
586 sys
->i_samples_delay
+= buf
->i_nb_samples
;
588 block_t
*result
= NULL
;
589 unsigned src_start
= 0;
590 unsigned padding_start
= 0;
591 /* The maximum Opus frame size is 1275 bytes + TOC sequence length. */
592 const unsigned OPUS_MAX_ENCODED_BYTES
= ((1275 + 3) * sys
->nb_streams
) - 2;
594 while (sys
->i_nb_samples
+ buf
->i_nb_samples
>= OPUS_FRAME_SIZE
)
596 block_t
*out_block
= block_Alloc(OPUS_MAX_ENCODED_BYTES
);
598 /* add padding to beginning */
601 const size_t leftover_space
= OPUS_FRAME_SIZE
- sys
->i_nb_samples
;
602 padding_start
= fill_buffer(enc
, padding_start
, sys
->padding
,
603 __MIN(sys
->padding
->i_nb_samples
, leftover_space
));
604 if (sys
->padding
->i_nb_samples
<= 0)
606 block_Release(sys
->padding
);
611 /* padding may have been freed either before or inside previous
615 const size_t leftover_space
= OPUS_FRAME_SIZE
- sys
->i_nb_samples
;
616 src_start
= fill_buffer(enc
, src_start
, buf
,
617 __MIN(buf
->i_nb_samples
, leftover_space
));
620 opus_int32 bytes_encoded
= opus_multistream_encode_float(sys
->enc
, sys
->buffer
,
621 OPUS_FRAME_SIZE
, out_block
->p_buffer
, out_block
->i_buffer
);
623 if (bytes_encoded
< 0)
625 block_Release(out_block
);
629 out_block
->i_length
= vlc_tick_from_samples( OPUS_FRAME_SIZE
,
630 enc
->fmt_in
.audio
.i_rate
);
632 out_block
->i_dts
= out_block
->i_pts
= i_pts
;
634 sys
->i_samples_delay
-= OPUS_FRAME_SIZE
;
636 i_pts
+= out_block
->i_length
;
638 sys
->i_nb_samples
= 0;
640 out_block
->i_buffer
= bytes_encoded
;
641 block_ChainAppend(&result
, out_block
);
645 /* put leftover samples at beginning of buffer */
646 if (buf
->i_nb_samples
> 0)
647 fill_buffer(enc
, src_start
, buf
, buf
->i_nb_samples
);
652 static int OpenEncoder(vlc_object_t
*p_this
)
654 encoder_t
*enc
= (encoder_t
*)p_this
;
656 if (enc
->fmt_out
.i_codec
!= VLC_CODEC_OPUS
)
659 encoder_sys_t
*sys
= malloc(sizeof(*sys
));
663 int status
= VLC_SUCCESS
;
667 enc
->pf_encode_audio
= Encode
;
668 enc
->fmt_in
.i_codec
= VLC_CODEC_FL32
;
669 enc
->fmt_in
.audio
.i_rate
= /* Only 48kHz */
670 enc
->fmt_out
.audio
.i_rate
= 48000;
671 enc
->fmt_out
.audio
.i_channels
= enc
->fmt_in
.audio
.i_channels
;
675 opus_prepare_header(enc
->fmt_out
.audio
.i_channels
,
676 enc
->fmt_out
.audio
.i_rate
, &header
);
678 /* needed for max encoded size calculation */
679 sys
->nb_streams
= header
.nb_streams
;
683 opus_multistream_surround_encoder_create(enc
->fmt_in
.audio
.i_rate
,
684 enc
->fmt_in
.audio
.i_channels
, header
.channel_mapping
,
685 &header
.nb_streams
, &header
.nb_coupled
, header
.stream_map
,
686 OPUS_APPLICATION_AUDIO
, &err
);
690 msg_Err(enc
, "Could not create encoder: error %d", err
);
692 status
= VLC_EGENERIC
;
698 if( enc
->fmt_out
.i_bitrate
)
699 opus_multistream_encoder_ctl(sys
->enc
, OPUS_SET_BITRATE( enc
->fmt_out
.i_bitrate
));
701 /* Buffer for incoming audio, since opus only accepts frame sizes that are
702 multiples of 2.5ms */
704 sys
->buffer
= vlc_alloc(header
.channels
, sizeof(float) * OPUS_FRAME_SIZE
);
710 sys
->i_nb_samples
= 0;
712 sys
->i_samples_delay
= 0;
713 int ret
= opus_multistream_encoder_ctl(sys
->enc
,
714 OPUS_GET_LOOKAHEAD(&sys
->i_samples_delay
));
716 msg_Err(enc
, "Unable to get number of lookahead samples: %s\n",
719 header
.preskip
= sys
->i_samples_delay
;
721 /* Now that we have preskip, we can write the header to extradata */
722 if (opus_write_header((uint8_t **) &enc
->fmt_out
.p_extra
,
723 &enc
->fmt_out
.i_extra
, &header
, opus_get_version_string()))
725 msg_Err(enc
, "Failed to write header.");
730 if (sys
->i_samples_delay
> 0)
732 const unsigned padding_samples
= sys
->i_samples_delay
*
733 enc
->fmt_out
.audio
.i_channels
;
734 sys
->padding
= block_Alloc(padding_samples
* sizeof(float));
739 sys
->padding
->i_nb_samples
= sys
->i_samples_delay
;
740 float *pad_ptr
= (float *) sys
->padding
->p_buffer
;
741 memset(pad_ptr
, 0, padding_samples
* sizeof(float));
752 opus_multistream_encoder_destroy(sys
->enc
);
758 static void CloseEncoder(vlc_object_t
*p_this
)
760 encoder_t
*enc
= (encoder_t
*)p_this
;
761 encoder_sys_t
*sys
= enc
->p_sys
;
763 opus_multistream_encoder_destroy(sys
->enc
);
765 block_Release(sys
->padding
);
769 #endif /* ENABLE_SOUT */