Coverage Report

Created: 2026-04-12 07:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/codec/opus.c
Line
Count
Source
1
/*****************************************************************************
2
 * opus.c: opus decoder/encoder module making use of libopus.
3
 *****************************************************************************
4
 * Copyright (C) 2003-2009, 2012 VLC authors and VideoLAN
5
 *
6
 * Authors: Gregory Maxwell <greg@xiph.org>
7
 * Based on speex.c by: Gildas Bazin <gbazin@videolan.org>
8
 *
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.
13
 *
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.
18
 *
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
 *****************************************************************************/
23
24
/*****************************************************************************
25
 * Preamble
26
 *****************************************************************************/
27
#ifdef HAVE_CONFIG_H
28
# include "config.h"
29
#endif
30
31
#include <vlc_common.h>
32
#include <vlc_plugin.h>
33
#include <vlc_codec.h>
34
#include <vlc_aout.h>
35
#include "../demux/xiph.h"
36
37
#include <ogg/ogg.h>
38
#include <opus.h>
39
#include <opus_multistream.h>
40
#ifdef OPUS_HAVE_OPUS_PROJECTION_H
41
# include <opus_projection.h> /* from 1.3.0 */
42
#endif
43
44
#include "opus_header.h"
45
46
#ifndef OPUS_SET_GAIN
47
#include <math.h>
48
#endif
49
50
/*****************************************************************************
51
 * Module descriptor
52
 *****************************************************************************/
53
static int  OpenDecoder   ( vlc_object_t * );
54
static void CloseDecoder  ( vlc_object_t * );
55
#ifdef ENABLE_SOUT
56
static int  OpenEncoder   ( vlc_object_t * );
57
static void CloseEncoder  ( encoder_t * );
58
#endif
59
60
116
vlc_module_begin ()
61
58
    set_subcategory( SUBCAT_INPUT_ACODEC )
62
63
58
    set_description( N_("Opus audio decoder") )
64
58
    set_capability( "audio decoder", 100 )
65
58
    set_shortname( N_("Opus") )
66
116
    set_callbacks( OpenDecoder, CloseDecoder )
67
68
58
#ifdef ENABLE_SOUT
69
58
    add_submodule ()
70
58
    set_description( N_("Opus audio encoder") )
71
58
    set_capability( "audio encoder", 150 )
72
58
    set_shortname( N_("Opus") )
73
58
    set_callback( OpenEncoder )
74
58
#endif
75
76
58
vlc_module_end ()
77
78
/*****************************************************************************
79
 * decoder_sys_t : opus decoder descriptor
80
 *****************************************************************************/
81
typedef struct
82
{
83
    /*
84
     * Input properties
85
     */
86
    bool b_has_headers;
87
88
    /*
89
     * Opus properties
90
     */
91
    OpusHeader header;
92
    OpusMSDecoder *p_st;
93
#ifdef OPUS_HAVE_OPUS_PROJECTION_H
94
    OpusProjectionDecoder *p_pr;
95
#endif
96
97
    /*
98
     * Common properties
99
     */
100
    date_t end_date;
101
} decoder_sys_t;
102
103
static const int pi_channels_maps[9] =
104
{
105
    0,
106
    AOUT_CHAN_CENTER,
107
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
108
    AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
109
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
110
     | AOUT_CHAN_REARRIGHT,
111
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
112
     | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
113
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
114
     | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
115
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
116
     | AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT
117
     | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE,
118
    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT
119
     | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
120
     | AOUT_CHAN_LFE,
121
};
122
123
/*
124
**  channel order as defined in http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9
125
*/
126
127
/* recommended vorbis channel order for 8 channels */
128
static const uint32_t pi_8channels_in[] =
129
{ AOUT_CHAN_LEFT, AOUT_CHAN_CENTER, AOUT_CHAN_RIGHT,
130
  AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT,
131
  AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT,AOUT_CHAN_LFE, 0 };
132
133
/* recommended vorbis channel order for 7 channels */
134
static const uint32_t pi_7channels_in[] =
135
{ AOUT_CHAN_LEFT, AOUT_CHAN_CENTER, AOUT_CHAN_RIGHT,
136
  AOUT_CHAN_MIDDLELEFT, AOUT_CHAN_MIDDLERIGHT,
137
  AOUT_CHAN_REARCENTER, AOUT_CHAN_LFE, 0 };
138
139
/* recommended vorbis channel order for 6 channels */
140
static const uint32_t pi_6channels_in[] =
141
{ AOUT_CHAN_LEFT, AOUT_CHAN_CENTER, AOUT_CHAN_RIGHT,
142
  AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, AOUT_CHAN_LFE, 0 };
143
144
/* recommended vorbis channel order for 5 channels */
145
static const uint32_t pi_5channels_in[] =
146
{ AOUT_CHAN_LEFT, AOUT_CHAN_CENTER, AOUT_CHAN_RIGHT,
147
  AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 };
148
149
/* recommended vorbis channel order for 4 channels */
150
static const uint32_t pi_4channels_in[] =
151
{ AOUT_CHAN_LEFT, AOUT_CHAN_RIGHT, AOUT_CHAN_REARLEFT, AOUT_CHAN_REARRIGHT, 0 };
152
153
/* recommended vorbis channel order for 3 channels */
154
static const uint32_t pi_3channels_in[] =
155
{ AOUT_CHAN_LEFT, AOUT_CHAN_CENTER, AOUT_CHAN_RIGHT, 0 };
156
157
/****************************************************************************
158
 * Local prototypes
159
 ****************************************************************************/
160
161
static int  DecodeAudio ( decoder_t *, block_t * );
162
static void Flush( decoder_t * );
163
static int  ProcessHeaders( decoder_t * );
164
static int  ProcessInitialHeader ( decoder_t *, ogg_packet * );
165
static block_t *ProcessPacket( decoder_t *, ogg_packet *, block_t * );
166
167
static block_t *DecodePacket( decoder_t *, ogg_packet *, int, vlc_tick_t );
168
/*****************************************************************************
169
 * Implementation Wrappers
170
 *****************************************************************************/
171
172
static void DecoderDestroy( decoder_sys_t *p_sys )
173
459
{
174
459
#ifdef OPUS_HAVE_OPUS_PROJECTION_H
175
459
    if( p_sys->p_pr )
176
0
    {
177
0
        opus_projection_decoder_destroy( p_sys->p_pr );
178
0
        p_sys->p_pr = NULL;
179
0
    }
180
459
    else
181
459
#endif
182
459
    if( p_sys->p_st )
183
232
    {
184
232
        opus_multistream_decoder_destroy( p_sys->p_st );
185
232
        p_sys->p_st = NULL;
186
232
    }
187
459
}
188
189
#ifdef OPUS_SET_GAIN
190
static int SetDecoderGain( decoder_sys_t *p_sys, int gain )
191
232
{
192
232
# ifdef OPUS_HAVE_OPUS_PROJECTION_H
193
232
    if( p_sys->p_pr )
194
0
    {
195
0
        if( opus_projection_decoder_ctl(
196
0
                    p_sys->p_pr, OPUS_SET_GAIN(gain) ) != OPUS_OK )
197
0
            return VLC_EGENERIC;
198
0
    }
199
232
    else
200
232
# endif
201
232
    {
202
232
        if( opus_multistream_decoder_ctl(
203
232
                    p_sys->p_st, OPUS_SET_GAIN(gain) ) != OPUS_OK )
204
0
            return VLC_EGENERIC;
205
232
    }
206
232
    return VLC_SUCCESS;
207
232
}
208
#endif
209
210
static int DecoderDecodeFloat( decoder_sys_t *p_sys, const ogg_packet *p_oggpacket,
211
                               int spp, block_t *out )
212
0
{
213
0
#ifdef OPUS_HAVE_OPUS_PROJECTION_H
214
0
    if( p_sys->p_pr )
215
0
        return opus_projection_decode_float(p_sys->p_pr, p_oggpacket->packet,
216
0
                                            p_oggpacket->bytes,
217
0
                                            (float *)out->p_buffer, spp, 0);
218
0
    else
219
0
#endif
220
0
        return opus_multistream_decode_float(p_sys->p_st, p_oggpacket->packet,
221
0
                                             p_oggpacket->bytes,
222
0
                                             (float *)out->p_buffer, spp, 0);
223
0
}
224
225
static int DecoderCreate( decoder_sys_t *p_sys )
226
4.25k
{
227
4.25k
    int err;
228
4.25k
    const OpusHeader *p_header = &p_sys->header;
229
4.25k
#ifdef OPUS_HAVE_OPUS_PROJECTION_H
230
4.25k
    if( p_header->channel_mapping == 3 )
231
0
    {
232
0
        p_sys->p_pr = opus_projection_decoder_create( 48000, p_header->channels,
233
0
                        p_header->nb_streams, p_header->nb_coupled,
234
0
                        p_header->dmatrix, p_header->dmatrix_size, &err );
235
0
    }
236
4.25k
    else
237
4.25k
#endif
238
4.25k
    {
239
4.25k
        const unsigned char* p_stream_map = p_header->stream_map;
240
4.25k
        unsigned char new_stream_map[8];
241
4.25k
        if ( p_header->channel_mapping <= 1 )
242
232
        {
243
232
            if( p_header->channels > 2 )
244
33
            {
245
33
                static const uint32_t *pi_ch[6] = { pi_3channels_in, pi_4channels_in,
246
33
                                                    pi_5channels_in, pi_6channels_in,
247
33
                                                    pi_7channels_in, pi_8channels_in };
248
33
                uint8_t pi_chan_table[AOUT_CHAN_MAX];
249
250
33
                aout_CheckChannelReorder( pi_ch[p_header->channels-3], NULL,
251
33
                                          pi_channels_maps[p_header->channels],
252
33
                                          pi_chan_table );
253
227
                for( int i=0;i<p_header->channels;i++ )
254
194
                    new_stream_map[pi_chan_table[i]] = p_header->stream_map[i];
255
256
33
                p_stream_map = new_stream_map;
257
33
            }
258
232
        }
259
260
4.25k
        p_sys->p_st = opus_multistream_decoder_create( 48000, p_header->channels,
261
4.25k
                        p_header->nb_streams, p_header->nb_coupled,
262
4.25k
                        p_stream_map, &err );
263
4.25k
    }
264
4.25k
    return err == OPUS_OK ? VLC_SUCCESS : VLC_EGENERIC;
265
4.25k
}
266
267
/*****************************************************************************
268
 * OpenDecoder: probe the decoder and return score
269
 *****************************************************************************/
270
static int OpenDecoder( vlc_object_t *p_this )
271
701k
{
272
701k
    decoder_t *p_dec = (decoder_t*)p_this;
273
701k
    decoder_sys_t *p_sys;
274
275
701k
    if( p_dec->fmt_in->i_codec != VLC_CODEC_OPUS )
276
700k
        return VLC_EGENERIC;
277
278
    /* Allocate the memory needed to store the decoder's structure */
279
459
    if( ( p_dec->p_sys = p_sys = malloc(sizeof(decoder_sys_t)) ) == NULL )
280
0
        return VLC_ENOMEM;
281
459
    p_sys->b_has_headers = false;
282
459
    opus_header_init(&p_sys->header);
283
284
459
    date_Set( &p_sys->end_date, VLC_TICK_INVALID );
285
286
    /* Set output properties */
287
459
    p_dec->fmt_out.i_codec = VLC_CODEC_FL32;
288
289
459
    p_dec->pf_decode    = DecodeAudio;
290
459
    p_dec->pf_flush     = Flush;
291
292
459
    p_sys->p_st = NULL;
293
459
#ifdef OPUS_HAVE_OPUS_PROJECTION_H
294
459
    p_sys->p_pr = NULL;
295
459
#endif
296
297
459
    return VLC_SUCCESS;
298
459
}
299
300
/****************************************************************************
301
 * DecodeBlock: the whole thing
302
 ****************************************************************************
303
 * This function must be fed with ogg packets.
304
 ****************************************************************************/
305
static block_t *DecodeBlock( decoder_t *p_dec, block_t *p_block )
306
679k
{
307
679k
    decoder_sys_t *p_sys = p_dec->p_sys;
308
679k
    ogg_packet oggpacket;
309
310
    /* Block to Ogg packet */
311
679k
    oggpacket.packet = p_block->p_buffer;
312
679k
    oggpacket.bytes = p_block->i_buffer;
313
314
679k
    oggpacket.granulepos = -1;
315
679k
    oggpacket.b_o_s = 0;
316
679k
    oggpacket.e_o_s = 0;
317
679k
    oggpacket.packetno = 0;
318
319
    /* Check for headers */
320
679k
    if( !p_sys->b_has_headers )
321
24.8k
    {
322
24.8k
        if( ProcessHeaders( p_dec ) )
323
24.6k
        {
324
24.6k
            block_Release( p_block );
325
24.6k
            return NULL;
326
24.6k
        }
327
232
        p_sys->b_has_headers = true;
328
232
    }
329
330
654k
    return ProcessPacket( p_dec, &oggpacket, p_block );
331
679k
}
332
333
static int DecodeAudio( decoder_t *p_dec, block_t *p_block )
334
1.39M
{
335
1.39M
    if( p_block == NULL ) /* No Drain */
336
710k
        return VLCDEC_SUCCESS;
337
338
679k
    p_block = DecodeBlock( p_dec, p_block );
339
679k
    if( p_block != NULL )
340
0
        decoder_QueueAudio( p_dec, p_block );
341
679k
    return VLCDEC_SUCCESS;
342
1.39M
}
343
344
/*****************************************************************************
345
 * ProcessHeaders: process Opus headers.
346
 *****************************************************************************/
347
static int ProcessHeaders( decoder_t *p_dec )
348
24.8k
{
349
24.8k
    decoder_sys_t *p_sys = p_dec->p_sys;
350
24.8k
    ogg_packet oggpacket;
351
352
24.8k
    size_t pi_size[XIPH_MAX_HEADER_COUNT];
353
24.8k
    const void *pp_data[XIPH_MAX_HEADER_COUNT];
354
24.8k
    size_t i_count;
355
356
24.8k
    size_t i_extra = p_dec->fmt_in->i_extra;
357
24.8k
    const uint8_t *p_extra = p_dec->fmt_in->p_extra;
358
24.8k
    uint8_t *p_alloc = NULL;
359
360
    /* Xiph headers as extradata */
361
24.8k
    if( i_extra > 21 && !memcmp( &p_extra[2], "OpusHead", 8 ) )
362
4.62k
    {
363
4.62k
        if( xiph_SplitHeaders( pi_size, pp_data, &i_count,
364
4.62k
                               i_extra, p_extra ) || i_count < 2 )
365
0
        {
366
            /* Borked Xiph headers */
367
0
            free( p_alloc );
368
0
            return VLC_EGENERIC;
369
0
        }
370
371
4.62k
        oggpacket.bytes  = pi_size[0];
372
4.62k
        oggpacket.packet = (unsigned char *) pp_data[0];
373
4.62k
    }
374
    /* If we have no header (e.g. from RTP), make one. */
375
20.2k
    else if( i_extra < 19 || memcmp( p_extra, "OpusHead", 8 ) )
376
20.2k
    {
377
20.2k
        OpusHeader header;
378
20.2k
        opus_header_init(&header);
379
380
20.2k
        opus_prepare_header( p_dec->fmt_in->audio.i_channels ? p_dec->fmt_in->audio.i_channels : 2,
381
20.2k
                             p_dec->fmt_in->audio.i_rate ? p_dec->fmt_in->audio.i_rate : 48000,
382
20.2k
                             &header );
383
384
        /* This is the only case where opus_write_header will try to read header.stream_map */
385
20.2k
        if( header.channel_mapping == 1 )
386
33
        {
387
            /* default mapping */
388
33
            static const unsigned char map[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
389
33
            memcpy(header.stream_map, map, sizeof(map));
390
33
        }
391
392
20.2k
        int ret = opus_write_header( &p_alloc, &i_extra, &header,
393
20.2k
                                     opus_get_version_string() );
394
20.2k
        opus_header_clean(&header);
395
20.2k
        if(ret != 0 || i_extra < 21)
396
0
        {
397
0
            free( p_alloc );
398
0
            return VLC_ENOMEM;
399
0
        }
400
20.2k
        oggpacket.bytes  = p_alloc[1]; /* Xiph header is type8/size8 */
401
20.2k
        oggpacket.packet = (unsigned char *) p_alloc + 2; /* Point directly to opus header start */
402
20.2k
    }
403
11
    else /* raw header in extradata */
404
11
    {
405
11
        oggpacket.bytes  = i_extra;
406
11
        oggpacket.packet  = (unsigned char *) p_extra;
407
11
    }
408
409
    /* Take care of the initial Opus header */
410
24.8k
    oggpacket.granulepos = -1;
411
24.8k
    oggpacket.e_o_s = 0;
412
24.8k
    oggpacket.packetno = 0;
413
24.8k
    oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */
414
24.8k
    int ret = ProcessInitialHeader( p_dec, &oggpacket );
415
416
24.8k
    if (ret != VLC_SUCCESS)
417
24.6k
    {
418
24.6k
        msg_Err( p_dec, "initial Opus header is corrupted" );
419
24.6k
        opus_header_clean( &p_sys->header );
420
24.6k
        opus_header_init( &p_sys->header );
421
24.6k
    }
422
423
24.8k
    free( p_alloc );
424
425
24.8k
    return ret;
426
24.8k
}
427
428
/*****************************************************************************
429
 * ProcessInitialHeader: processes the initial Opus header packet.
430
 *****************************************************************************/
431
static int ProcessInitialHeader( decoder_t *p_dec, ogg_packet *p_oggpacket )
432
24.8k
{
433
24.8k
    decoder_sys_t *p_sys = p_dec->p_sys;
434
24.8k
    OpusHeader *p_header = &p_sys->header;
435
436
24.8k
    if( !opus_header_parse((unsigned char *)p_oggpacket->packet,p_oggpacket->bytes,p_header) )
437
3.31k
    {
438
3.31k
        msg_Err( p_dec, "cannot read Opus header" );
439
3.31k
        return VLC_EGENERIC;
440
3.31k
    }
441
442
21.5k
    msg_Dbg( p_dec, "Opus audio with %d channels, %d samples preskip, %d samplerate",
443
21.5k
             p_header->channels, p_header->preskip, p_header->input_sample_rate );
444
445
21.5k
    if((p_header->channels>2 && p_header->channel_mapping==0) ||
446
21.5k
        (p_header->channels>8 && p_header->channel_mapping==1) ||
447
21.5k
        (p_header->channels>18 && p_header->channel_mapping==2) ||
448
21.5k
        (p_header->channels>18 && p_header->channel_mapping==3))
449
0
    {
450
0
        msg_Err( p_dec, "Unsupported channel mapping" );
451
0
        return VLC_EGENERIC;
452
0
    }
453
21.5k
    if (p_header->channel_mapping >= 2)
454
21.2k
    {
455
21.2k
        int i_order = floor(sqrt(p_header->channels));
456
21.2k
        int i_nondiegetic = p_header->channels - i_order * i_order;
457
21.2k
        msg_Dbg( p_dec, "Opus Ambisonic audio order=%d channels=%d+%d",
458
21.2k
                 i_order, p_header->channels - i_nondiegetic, i_nondiegetic);
459
21.2k
        if (i_nondiegetic != 0 && i_nondiegetic != 2)
460
17.2k
        {
461
17.2k
            msg_Err( p_dec, "Unsupported ambisonic channel mapping" );
462
17.2k
            return VLC_EGENERIC;
463
17.2k
        }
464
21.2k
    }
465
466
    /* Setup the format */
467
4.25k
    p_dec->fmt_out.audio.i_channels = p_header->channels;
468
4.25k
    p_dec->fmt_out.audio.i_rate = 48000;
469
470
4.25k
    if (p_header->channel_mapping <= 1)
471
232
    {
472
232
        p_dec->fmt_out.audio.i_physical_channels =
473
232
            pi_channels_maps[p_header->channels];
474
232
    }
475
4.02k
    else //p_header->channel_mapping >= 2
476
4.02k
    {
477
4.02k
        p_dec->fmt_out.audio.channel_type = AUDIO_CHANNEL_TYPE_AMBISONICS;
478
4.02k
    }
479
480
    /* Opus decoder init */
481
4.25k
    if( DecoderCreate( p_sys ) != VLC_SUCCESS )
482
4.02k
    {
483
4.02k
        msg_Err( p_dec, "decoder initialization failed" );
484
4.02k
        return VLC_EGENERIC;
485
4.02k
    }
486
487
232
#ifdef OPUS_SET_GAIN
488
232
    if( SetDecoderGain( p_sys, p_header->gain ) != VLC_SUCCESS )
489
0
    {
490
0
        msg_Err( p_dec, "OPUS_SET_GAIN failed" );
491
0
        DecoderDestroy( p_sys );
492
0
        return VLC_EGENERIC;
493
0
    }
494
232
#endif
495
496
232
    date_Init( &p_sys->end_date, 48000, 1 );
497
498
232
    return VLC_SUCCESS;
499
232
}
500
501
/*****************************************************************************
502
 * Flush:
503
 *****************************************************************************/
504
static void Flush( decoder_t *p_dec )
505
33
{
506
33
    decoder_sys_t *p_sys = p_dec->p_sys;
507
508
33
    date_Set( &p_sys->end_date, VLC_TICK_INVALID );
509
33
}
510
511
/*****************************************************************************
512
 * ProcessPacket: processes a Opus packet.
513
 *****************************************************************************/
514
static block_t *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
515
                               block_t *p_block )
516
654k
{
517
654k
    decoder_sys_t *p_sys = p_dec->p_sys;
518
519
654k
    if( p_block->i_flags & (BLOCK_FLAG_CORRUPTED|BLOCK_FLAG_DISCONTINUITY) )
520
33
    {
521
33
        Flush( p_dec );
522
33
        if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
523
0
        {
524
0
            block_Release( p_block );
525
0
            return NULL;
526
0
        }
527
33
    }
528
529
    /* Date management */
530
654k
    if( p_block->i_pts != VLC_TICK_INVALID &&
531
654k
        p_block->i_pts != date_Get( &p_sys->end_date ) )
532
653k
    {
533
653k
        date_Set( &p_sys->end_date, p_block->i_pts );
534
653k
    }
535
536
654k
    if( date_Get( &p_sys->end_date ) == VLC_TICK_INVALID )
537
0
    {
538
        /* We've just started the stream, wait for the first PTS. */
539
0
        block_Release( p_block );
540
0
        return NULL;
541
0
    }
542
543
    /* trimming info */
544
654k
    vlc_tick_t i_max_duration = (p_block->i_flags & BLOCK_FLAG_END_OF_SEQUENCE) ?
545
654k
                             p_block->i_length : 0;
546
547
654k
    block_t *p_aout_buffer = DecodePacket( p_dec, p_oggpacket,
548
654k
                                           p_block->i_nb_samples,
549
654k
                                           i_max_duration );
550
551
654k
    block_Release( p_block );
552
654k
    return p_aout_buffer;
553
654k
}
554
555
/*****************************************************************************
556
 * DecodePacket: decodes a Opus packet.
557
 *****************************************************************************/
558
static block_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
559
                              int i_nb_samples, vlc_tick_t i_duration )
560
654k
{
561
654k
    decoder_sys_t *p_sys = p_dec->p_sys;
562
563
654k
    if( !p_oggpacket->bytes )
564
823
        return NULL;
565
566
654k
    int spp;
567
654k
    spp=opus_packet_get_nb_frames(p_oggpacket->packet,p_oggpacket->bytes);
568
654k
    if(spp>0)spp*=opus_packet_get_samples_per_frame(p_oggpacket->packet,48000);
569
654k
    if(spp<120||spp>120*48)return NULL;
570
571
    /* Since the information isn't always available at the demux level
572
     * use the packet's sample number */
573
539k
    if(!i_nb_samples)
574
510k
        i_nb_samples = spp;
575
576
539k
    if( decoder_UpdateAudioFormat( p_dec ) )
577
539k
        return NULL;
578
0
    block_t *p_aout_buffer=decoder_NewAudioBuffer( p_dec, spp );
579
0
    if ( !p_aout_buffer )
580
0
    {
581
0
        msg_Err(p_dec, "Oops: No new buffer was returned!");
582
0
        return NULL;
583
0
    }
584
585
0
    spp = DecoderDecodeFloat( p_sys, p_oggpacket, spp, p_aout_buffer );
586
587
0
    int i_end_trim = 0;
588
0
    if( i_duration > 0 && spp > 0 &&
589
0
        i_duration < vlc_tick_from_samples(i_nb_samples, 48000) )
590
0
    {
591
0
        i_end_trim = spp - VLC_CLIP(samples_from_vlc_tick(i_duration, 48000), 0, spp);
592
0
    }
593
594
0
    if( spp < 0 || i_nb_samples <= 0 || i_end_trim >= i_nb_samples)
595
0
    {
596
0
        block_Release(p_aout_buffer);
597
0
        if( spp < 0 )
598
0
            msg_Err( p_dec, "Error: corrupted stream?" );
599
0
        return NULL;
600
0
    }
601
602
0
    p_aout_buffer->i_buffer = (i_nb_samples - i_end_trim) *
603
0
                              p_sys->header.channels * sizeof(float);
604
605
0
    if( spp > i_nb_samples )
606
0
    {
607
0
        memmove(p_aout_buffer->p_buffer,
608
0
            p_aout_buffer->p_buffer
609
0
            + (spp - i_nb_samples)*p_sys->header.channels*sizeof(float),
610
0
            p_aout_buffer->i_buffer);
611
0
    }
612
0
    i_nb_samples -= i_end_trim;
613
614
#ifndef OPUS_SET_GAIN
615
    if(p_sys->header.gain!=0)
616
    {
617
        float gain = pow(10., p_sys->header.gain/5120.);
618
        float *buf =(float *)p_aout_buffer->p_buffer;
619
        for( int i = 0; i < i_nb_samples*p_sys->header.channels; i++)
620
            buf[i] *= gain;
621
    }
622
#endif
623
0
    p_aout_buffer->i_nb_samples = i_nb_samples;
624
0
    p_aout_buffer->i_pts = date_Get( &p_sys->end_date );
625
0
    p_aout_buffer->i_length = date_Increment( &p_sys->end_date, i_nb_samples )
626
0
        - p_aout_buffer->i_pts;
627
0
    return p_aout_buffer;
628
0
}
629
630
/*****************************************************************************
631
 * CloseDecoder: Opus decoder destruction
632
 *****************************************************************************/
633
static void CloseDecoder( vlc_object_t *p_this )
634
459
{
635
459
    decoder_t * p_dec = (decoder_t *)p_this;
636
459
    decoder_sys_t *p_sys = p_dec->p_sys;
637
638
459
    DecoderDestroy( p_sys );
639
640
459
    opus_header_clean( &p_sys->header );
641
459
    free( p_sys );
642
459
}
643
644
#ifdef ENABLE_SOUT
645
646
/* only ever encode 20 ms at a time, going longer doesn't yield much compression
647
   gain, shorter does have a compression loss, and doesn't matter so much in
648
   Ogg, unless you really need low latency, which would also require muxing one
649
   packet per page. */
650
static const unsigned OPUS_FRAME_SIZE = 960; /* 48000 * 20 / 1000 */
651
652
typedef struct
653
{
654
    OpusMSEncoder *enc;
655
    float *buffer;
656
    unsigned i_nb_samples;
657
    int i_samples_delay;
658
    block_t *padding;
659
    int nb_streams;
660
} encoder_sys_t;
661
662
static unsigned fill_buffer(encoder_t *enc, unsigned src_start, block_t *src,
663
                            unsigned samples)
664
0
{
665
0
    encoder_sys_t *p_sys = enc->p_sys;
666
0
    const unsigned channels = enc->fmt_out.audio.i_channels;
667
0
    const float *src_buf = ((const float *) src->p_buffer) + src_start;
668
0
    float *dest_buf = p_sys->buffer + (p_sys->i_nb_samples * channels);
669
0
    const unsigned len = samples * channels;
670
671
0
    memcpy(dest_buf, src_buf, len * sizeof(float));
672
673
0
    p_sys->i_nb_samples += samples;
674
0
    src_start += len;
675
676
0
    src->i_nb_samples -= samples;
677
0
    return src_start;
678
0
}
679
680
static block_t *Encode(encoder_t *enc, block_t *buf)
681
0
{
682
0
    encoder_sys_t *sys = enc->p_sys;
683
684
0
    if (!buf)
685
0
        return NULL;
686
687
0
    vlc_tick_t i_pts = buf->i_pts -
688
0
                vlc_tick_from_samples( sys->i_samples_delay,
689
0
                             enc->fmt_in.audio.i_rate );
690
691
0
    sys->i_samples_delay += buf->i_nb_samples;
692
693
0
    block_t *result = NULL;
694
0
    unsigned src_start = 0;
695
0
    unsigned padding_start = 0;
696
    /* The maximum Opus frame size is 1275 bytes + TOC sequence length. */
697
0
    const unsigned OPUS_MAX_ENCODED_BYTES = ((1275 + 3) * sys->nb_streams) - 2;
698
699
0
    while (sys->i_nb_samples + buf->i_nb_samples >= OPUS_FRAME_SIZE)
700
0
    {
701
0
        block_t *out_block = block_Alloc(OPUS_MAX_ENCODED_BYTES);
702
0
        if (unlikely(out_block == NULL))
703
0
        {
704
0
            block_ChainRelease(result);
705
0
            return NULL;
706
0
        }
707
708
        /* add padding to beginning */
709
0
        if (sys->padding)
710
0
        {
711
0
            const size_t leftover_space = OPUS_FRAME_SIZE - sys->i_nb_samples;
712
0
            padding_start = fill_buffer(enc, padding_start, sys->padding,
713
0
                    __MIN(sys->padding->i_nb_samples, leftover_space));
714
0
            if (sys->padding->i_nb_samples <= 0)
715
0
            {
716
0
                block_Release(sys->padding);
717
0
                sys->padding = NULL;
718
0
            }
719
0
        }
720
721
        /* padding may have been freed either before or inside previous
722
         * if-statement */
723
0
        if (!sys->padding)
724
0
        {
725
0
            const size_t leftover_space = OPUS_FRAME_SIZE - sys->i_nb_samples;
726
0
            src_start = fill_buffer(enc, src_start, buf,
727
0
                    __MIN(buf->i_nb_samples, leftover_space));
728
0
        }
729
730
0
        opus_int32 bytes_encoded = opus_multistream_encode_float(sys->enc, sys->buffer,
731
0
                OPUS_FRAME_SIZE, out_block->p_buffer, out_block->i_buffer);
732
733
0
        if (bytes_encoded < 0)
734
0
        {
735
0
            block_Release(out_block);
736
0
        }
737
0
        else
738
0
        {
739
0
            out_block->i_length = vlc_tick_from_samples( OPUS_FRAME_SIZE,
740
0
                                                         enc->fmt_in.audio.i_rate );
741
742
0
            out_block->i_dts = out_block->i_pts = i_pts;
743
744
0
            sys->i_samples_delay -= OPUS_FRAME_SIZE;
745
746
0
            i_pts += out_block->i_length;
747
748
0
            sys->i_nb_samples = 0;
749
750
0
            out_block->i_buffer = bytes_encoded;
751
0
            block_ChainAppend(&result, out_block);
752
0
        }
753
0
    }
754
755
    /* put leftover samples at beginning of buffer */
756
0
    if (buf->i_nb_samples > 0)
757
0
        fill_buffer(enc, src_start, buf, buf->i_nb_samples);
758
759
0
    return result;
760
0
}
761
762
static int OpenEncoder(vlc_object_t *p_this)
763
0
{
764
0
    encoder_t *enc = (encoder_t *)p_this;
765
766
0
    if (enc->fmt_out.i_codec != VLC_CODEC_OPUS)
767
0
        return VLC_EGENERIC;
768
769
0
    encoder_sys_t *sys = malloc(sizeof(*sys));
770
0
    if (!sys)
771
0
        return VLC_ENOMEM;
772
773
0
    int status = VLC_SUCCESS;
774
0
    sys->buffer = NULL;
775
0
    sys->enc = NULL;
776
777
0
    enc->fmt_in.i_codec = VLC_CODEC_FL32;
778
0
    enc->fmt_in.audio.i_rate = /* Only 48kHz */
779
0
    enc->fmt_out.audio.i_rate = 48000;
780
0
    enc->fmt_out.audio.i_channels = enc->fmt_in.audio.i_channels;
781
782
0
    OpusHeader header;
783
0
    opus_header_init(&header);
784
785
0
    opus_prepare_header(enc->fmt_out.audio.i_channels,
786
0
            enc->fmt_out.audio.i_rate, &header);
787
788
    /* needed for max encoded size calculation */
789
0
    sys->nb_streams = header.nb_streams;
790
791
0
    int err;
792
0
    sys->enc =
793
0
        opus_multistream_surround_encoder_create(enc->fmt_in.audio.i_rate,
794
0
                enc->fmt_in.audio.i_channels, header.channel_mapping,
795
0
                &header.nb_streams, &header.nb_coupled, header.stream_map,
796
0
                OPUS_APPLICATION_AUDIO, &err);
797
798
0
    if (err != OPUS_OK)
799
0
    {
800
0
        msg_Err(enc, "Could not create encoder: error %d", err);
801
0
        sys->enc = NULL;
802
0
        status = VLC_EGENERIC;
803
0
        goto error;
804
0
    }
805
806
    /* TODO: vbr, fec */
807
808
0
    if( enc->fmt_out.i_bitrate )
809
0
        opus_multistream_encoder_ctl(sys->enc, OPUS_SET_BITRATE( enc->fmt_out.i_bitrate ));
810
811
    /* Buffer for incoming audio, since opus only accepts frame sizes that are
812
       multiples of 2.5ms */
813
0
    sys->buffer = vlc_alloc(header.channels, sizeof(float) * OPUS_FRAME_SIZE);
814
0
    if (!sys->buffer) {
815
0
        status = VLC_ENOMEM;
816
0
        goto error;
817
0
    }
818
819
0
    sys->i_nb_samples = 0;
820
821
0
    sys->i_samples_delay = 0;
822
0
    int ret = opus_multistream_encoder_ctl(sys->enc,
823
0
            OPUS_GET_LOOKAHEAD(&sys->i_samples_delay));
824
0
    if (ret != OPUS_OK)
825
0
        msg_Err(enc, "Unable to get number of lookahead samples: %s\n",
826
0
                opus_strerror(ret));
827
828
0
    header.preskip = sys->i_samples_delay;
829
830
    /* Now that we have preskip, we can write the header to extradata */
831
0
    if (opus_write_header((uint8_t **) &enc->fmt_out.p_extra,
832
0
                          &enc->fmt_out.i_extra, &header, opus_get_version_string()))
833
0
    {
834
0
        status = VLC_ENOMEM;
835
0
        goto error;
836
0
    }
837
838
0
    if (sys->i_samples_delay > 0)
839
0
    {
840
0
        const unsigned padding_samples = sys->i_samples_delay *
841
0
            enc->fmt_out.audio.i_channels;
842
0
        sys->padding = block_Alloc(padding_samples * sizeof(float));
843
0
        if (!sys->padding) {
844
0
            status = VLC_ENOMEM;
845
0
            goto error;
846
0
        }
847
0
        sys->padding->i_nb_samples = sys->i_samples_delay;
848
0
        float *pad_ptr = (float *) sys->padding->p_buffer;
849
0
        memset(pad_ptr, 0, padding_samples * sizeof(float));
850
0
    }
851
0
    else
852
0
    {
853
0
        sys->padding = NULL;
854
0
    }
855
856
0
    opus_header_clean(&header);
857
858
0
    if (status != VLC_SUCCESS)
859
0
    {
860
0
        free(sys->buffer);
861
0
        opus_multistream_encoder_destroy(sys->enc);
862
0
        free(sys);
863
0
        return status;
864
0
    }
865
866
0
    static const struct vlc_encoder_operations ops =
867
0
    {
868
0
        .close = CloseEncoder,
869
0
        .encode_audio = Encode,
870
0
    };
871
0
    enc->ops = &ops;
872
0
    enc->p_sys = sys;
873
874
0
    return VLC_SUCCESS;
875
876
0
error:
877
0
    opus_header_clean(&header);
878
0
    if (sys->enc)
879
0
        opus_multistream_encoder_destroy(sys->enc);
880
0
    free(sys->buffer);
881
0
    free(sys);
882
0
    return status;
883
0
}
884
885
static void CloseEncoder(encoder_t *enc)
886
0
{
887
0
    encoder_sys_t *sys = enc->p_sys;
888
889
0
    opus_multistream_encoder_destroy(sys->enc);
890
0
    if (sys->padding)
891
0
        block_Release(sys->padding);
892
0
    free(sys->buffer);
893
0
    free(sys);
894
0
}
895
#endif /* ENABLE_SOUT */