Coverage Report

Created: 2026-10-17 07:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/demux/ogg.c
Line
Count
Source
1
/*****************************************************************************
2
 * ogg.c : ogg stream demux module for vlc
3
 *****************************************************************************
4
 * Copyright (C) 2001-2007 VLC authors and VideoLAN
5
 *
6
 * Authors: Gildas Bazin <gbazin@netcourrier.com>
7
 *          Andre Pang <Andre.Pang@csiro.au> (Annodex support)
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
#ifdef HAVE_LIBVORBIS
32
  #include <vorbis/codec.h>
33
#endif
34
35
#include <vlc_common.h>
36
#include <vlc_arrays.h>
37
#include <vlc_plugin.h>
38
#include <vlc_access.h>
39
#include <vlc_demux.h>
40
#include <vlc_meta.h>
41
#include <vlc_input.h>
42
#include <vlc_replay_gain.h>
43
44
#include <ogg/ogg.h>
45
46
#include <vlc_codecs.h>
47
#include <vlc_bits.h>
48
#include "xiph.h"
49
#include "xiph_metadata.h"
50
#include "ogg.h"
51
#include "oggseek.h"
52
#include "ogg_granule.h"
53
#include "opus.h"
54
55
#include <limits.h>
56
57
/*****************************************************************************
58
 * Module descriptor
59
 *****************************************************************************/
60
static int  Open ( vlc_object_t * );
61
static void Close( vlc_object_t * );
62
63
174
vlc_module_begin ()
64
87
    set_shortname ( "OGG" )
65
87
    set_description( N_("OGG demuxer" ) )
66
87
    set_subcategory( SUBCAT_INPUT_DEMUX )
67
87
    set_capability( "demux", 50 )
68
174
    set_callbacks( Open, Close )
69
87
    add_shortcut( "ogg" )
70
87
    add_file_extension("oga")
71
87
    add_file_extension("ogg")
72
87
    add_file_extension("ogm")
73
87
    add_file_extension("ogv")
74
87
    add_file_extension("ogx")
75
87
    add_file_extension("opus")
76
87
    add_file_extension("spx")
77
87
vlc_module_end ()
78
79
80
/*****************************************************************************
81
 * Definitions of structures and functions used by this plugins
82
 *****************************************************************************/
83
84
/* OggDS headers for the new header format (used in ogm files) */
85
typedef struct
86
{
87
    ogg_int32_t width;
88
    ogg_int32_t height;
89
} stream_header_video_t;
90
91
typedef struct
92
{
93
    ogg_int16_t channels;
94
    ogg_int16_t padding;
95
    ogg_int16_t blockalign;
96
    ogg_int32_t avgbytespersec;
97
} stream_header_audio_t;
98
99
typedef struct
100
{
101
    char        streamtype[8];
102
    char        subtype[4];
103
104
    ogg_int32_t size;                               /* size of the structure */
105
106
    ogg_int64_t time_unit;                              /* in reference time */
107
    ogg_int64_t samples_per_unit;
108
    ogg_int32_t default_len;                                /* in media time */
109
110
    ogg_int32_t buffersize;
111
    ogg_int16_t bits_per_sample;
112
    ogg_int16_t padding;
113
114
    union
115
    {
116
        /* Video specific */
117
        stream_header_video_t video;
118
        /* Audio specific */
119
        stream_header_audio_t audio;
120
    } sh;
121
} stream_header_t;
122
123
662
#define VORBIS_HEADER_IDENTIFICATION 1
124
1.31k
#define VORBIS_HEADER_COMMENT        2
125
1.94k
#define VORBIS_HEADER_SETUP          3
126
1.57k
#define VORBIS_HEADER_TO_FLAG(i)     (1 << (i - 1))
127
#define VORBIS_HEADERS_VALID(p_stream) \
128
68.8k
    ((p_stream->special.vorbis.i_headers_flags & 0x07) == 0x07) // 0b111
129
130
/*****************************************************************************
131
 * Local prototypes
132
 *****************************************************************************/
133
static int  Demux  ( demux_t * );
134
static int  Control( demux_t *, int, va_list );
135
136
/* Bitstream manipulation */
137
static int  Ogg_ReadPage     ( demux_t *, ogg_page * );
138
static void Ogg_DecodePacket ( demux_t *, logical_stream_t *, ogg_packet *, bool );
139
static unsigned Ogg_OpusPacketDuration( ogg_packet * );
140
static void Ogg_QueueBlocks( demux_t *, logical_stream_t *, block_t *, vlc_tick_t, bool );
141
static void Ogg_SendQueuedBlock( demux_t *, logical_stream_t * );
142
143
static inline bool Ogg_HasQueuedBlocks( const logical_stream_t *p_stream )
144
756k
{
145
756k
    return ( p_stream->queue.p_blocks != NULL );
146
756k
}
147
148
static void Ogg_CreateES( demux_t *p_demux, bool );
149
static int Ogg_BeginningOfStream( demux_t *p_demux );
150
static int Ogg_FindLogicalStreams( demux_t *p_demux );
151
static int Ogg_ConfigureStream( demux_t *p_demux, ogg_packet oggpacket, logical_stream_t * );
152
static void Ogg_EndOfStream( demux_t *p_demux );
153
154
/* */
155
static void Ogg_LogicalStreamInit( logical_stream_t *p_stream );
156
static void Ogg_LogicalStreamDelete( demux_t *p_demux, logical_stream_t *p_stream );
157
static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t *p_stream );
158
static void Ogg_ResetStream( logical_stream_t *p_stream );
159
160
/* */
161
static void Ogg_ExtractMeta( demux_t *p_demux, es_format_t *p_fmt, const uint8_t *p_headers, size_t i_headers );
162
163
/* Logical bitstream headers */
164
static bool Ogg_ReadDaalaHeader( logical_stream_t *, ogg_packet * );
165
static bool Ogg_ReadTheoraHeader( logical_stream_t *, ogg_packet * );
166
static bool Ogg_ReadVorbisHeader( logical_stream_t *, ogg_packet * );
167
static bool Ogg_ReadSpeexHeader( logical_stream_t *, ogg_packet * );
168
static void Ogg_ReadOpusHeader( logical_stream_t *, ogg_packet * );
169
static bool Ogg_ReadKateHeader( logical_stream_t *, ogg_packet * );
170
static bool Ogg_ReadFlacStreamInfo( demux_t *, logical_stream_t *, ogg_packet * );
171
static void Ogg_ReadAnnodexHeader( demux_t *, logical_stream_t *, ogg_packet * );
172
static bool Ogg_ReadDiracHeader( logical_stream_t *, ogg_packet * );
173
static bool Ogg_ReadVP8Header( demux_t *, logical_stream_t *, ogg_packet * );
174
static void Ogg_ReadSkeletonHeader( demux_t *, logical_stream_t *, ogg_packet * );
175
static bool Ogg_ReadOggSpotsHeader( logical_stream_t *, ogg_packet * );
176
177
/* Skeleton */
178
static void Ogg_ReadSkeletonBones( demux_t *, ogg_packet * );
179
static void Ogg_ReadSkeletonIndex( demux_t *, ogg_packet * );
180
static void Ogg_FreeSkeleton( ogg_skeleton_t * );
181
static void Ogg_ApplySkeleton( logical_stream_t * );
182
183
/* Special decoding */
184
static void Ogg_CleanSpecificData( logical_stream_t * );
185
#ifdef HAVE_LIBVORBIS
186
static bool Ogg_VorbisValidBlocksize( long );
187
static void Ogg_DecodeVorbisHeader( logical_stream_t *, ogg_packet *, int );
188
#endif
189
190
static vlc_tick_t Ogg_GetDecoderPreroll( logical_stream_t *p_stream )
191
0
{
192
0
    if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
193
0
        return vlc_tick_from_samples( 80 * 48, 48000 );
194
0
    return 0;
195
0
}
196
197
static void fill_channels_info(audio_format_t *audio)
198
781
{
199
781
    static const int pi_channels_map[9] =
200
781
    {
201
781
        0,
202
781
        AOUT_CHAN_CENTER,
203
781
        AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
204
781
        AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
205
781
        AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
206
781
            | AOUT_CHAN_REARRIGHT,
207
781
        AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
208
781
            | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
209
781
        AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
210
781
            | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE,
211
781
        AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
212
781
            | AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT
213
781
            | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE,
214
781
        AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT
215
781
            | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT
216
781
            | AOUT_CHAN_LFE,
217
781
    };
218
219
781
    unsigned chans = audio->i_channels;
220
781
    if (chans < ARRAY_SIZE(pi_channels_map))
221
781
        audio->i_physical_channels = pi_channels_map[chans];
222
781
}
223
224
/*****************************************************************************
225
 * Open: initializes ogg demux structures
226
 *****************************************************************************/
227
static int Open( vlc_object_t * p_this )
228
107
{
229
107
    demux_t *p_demux = (demux_t *)p_this;
230
107
    demux_sys_t    *p_sys;
231
107
    const uint8_t  *p_peek;
232
233
    /* Check if we are dealing with an ogg stream */
234
107
    if( vlc_stream_Peek( p_demux->s, &p_peek, 4 ) < 4 ) return VLC_EGENERIC;
235
107
    if( !p_demux->obj.force && memcmp( p_peek, "OggS", 4 ) )
236
20
    {
237
20
        char *psz_mime = stream_ContentType( p_demux->s );
238
20
        if( !psz_mime )
239
20
        {
240
20
            return VLC_EGENERIC;
241
20
        }
242
0
        else if ( strcmp( psz_mime, "application/ogg" ) &&
243
0
                  strcmp( psz_mime, "video/ogg" ) &&
244
0
                  strcmp( psz_mime, "audio/ogg" ) )
245
0
        {
246
0
            free( psz_mime );
247
0
            return VLC_EGENERIC;
248
0
        }
249
0
        free( psz_mime );
250
0
    }
251
252
    /* */
253
87
    p_demux->p_sys = p_sys = calloc( 1, sizeof( demux_sys_t ) );
254
87
    if( !p_sys )
255
0
        return VLC_ENOMEM;
256
257
87
    p_sys->i_length = 0;
258
87
    p_sys->b_preparsing_done = false;
259
260
    /* Set exported functions */
261
87
    p_demux->pf_demux = Demux;
262
87
    p_demux->pf_control = Control;
263
264
    /* Initialize the Ogg physical bitstream parser */
265
87
    ogg_sync_init( &p_sys->oy );
266
267
    /* */
268
87
    TAB_INIT( p_sys->i_seekpoints, p_sys->pp_seekpoints );
269
270
    /* Enforce exclusive mode, only one track can be selected at once. */
271
87
    es_out_Control( p_demux->out, ES_OUT_SET_ES_CAT_POLICY, AUDIO_ES,
272
87
                    ES_OUT_ES_POLICY_EXCLUSIVE );
273
274
766
    while ( !p_sys->b_preparsing_done && p_demux->pf_demux( p_demux ) > 0 )
275
679
    {}
276
87
    if ( p_sys->b_preparsing_done && p_demux->b_preparsing )
277
0
        Ogg_CreateES( p_demux, true );
278
279
87
    return VLC_SUCCESS;
280
87
}
281
282
/*****************************************************************************
283
 * Close: frees unused data
284
 *****************************************************************************/
285
static void Close( vlc_object_t *p_this )
286
87
{
287
87
    demux_t *p_demux = (demux_t *)p_this;
288
87
    demux_sys_t *p_sys = p_demux->p_sys  ;
289
290
    /* Cleanup the bitstream parser */
291
87
    ogg_sync_clear( &p_sys->oy );
292
293
87
    Ogg_EndOfStream( p_demux );
294
295
87
    if( p_sys->p_old_stream )
296
14
        Ogg_LogicalStreamDelete( p_demux, p_sys->p_old_stream );
297
298
87
    free( p_sys );
299
87
}
300
301
static vlc_tick_t Ogg_GetLastDTS( demux_t * p_demux )
302
753
{
303
753
    demux_sys_t *p_sys = p_demux->p_sys;
304
305
753
    vlc_tick_t i_dts = VLC_TICK_INVALID;
306
1.68k
    for( int i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
307
930
    {
308
930
        logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
309
930
        if ( p_stream->b_initializing )
310
33
            continue;
311
897
        if( p_stream->i_pcr > i_dts )
312
293
            i_dts = p_stream->i_pcr;
313
897
    }
314
315
753
    return i_dts;
316
753
}
317
318
static vlc_tick_t Ogg_GeneratePCR( demux_t * p_demux, bool b_drain )
319
177k
{
320
177k
    demux_sys_t *p_sys = p_demux->p_sys;
321
    /* We will consider the lowest PCR among tracks, because the audio core badly
322
     * handles PCR rewind (mute)
323
     */
324
177k
    vlc_tick_t i_pcr_candidate = VLC_TICK_INVALID;
325
476k
    for( int i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
326
299k
    {
327
299k
        logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
328
299k
        if( p_stream->fmt.i_cat == SPU_ES )
329
24.7k
            continue;
330
274k
        if( p_stream->fmt.i_codec == VLC_CODEC_OGGSPOTS )
331
0
            continue;
332
274k
        if( p_stream->i_pcr == VLC_TICK_INVALID )
333
89.5k
            continue;
334
184k
        if ( (!b_drain && p_stream->b_finished) || p_stream->b_initializing )
335
30.8k
            continue;
336
154k
        if( i_pcr_candidate == VLC_TICK_INVALID ||
337
46.9k
            p_stream->i_pcr < i_pcr_candidate )
338
120k
        {
339
120k
            i_pcr_candidate = p_stream->i_pcr;
340
120k
        }
341
154k
    }
342
343
177k
    return i_pcr_candidate;
344
177k
}
345
346
static void Ogg_OutputQueues( demux_t *p_demux, bool b_drain )
347
14.2k
{
348
14.2k
    demux_sys_t *p_sys = p_demux->p_sys;
349
14.2k
    vlc_tick_t i_pcr;
350
351
    /* Generate First PCR */
352
14.2k
    if( p_sys->i_pcr == VLC_TICK_INVALID )
353
3.46k
    {
354
3.46k
        i_pcr = Ogg_GeneratePCR( p_demux, b_drain );
355
3.46k
        if( i_pcr != VLC_TICK_INVALID && i_pcr != p_sys->i_pcr )
356
453
        {
357
453
            p_sys->i_pcr = i_pcr;
358
453
            if( likely( !p_sys->b_slave ) )
359
453
                es_out_SetPCR( p_demux->out, p_sys->i_pcr );
360
453
        }
361
3.46k
    }
362
363
14.2k
    if( p_sys->i_pcr != VLC_TICK_INVALID )
364
11.2k
    {
365
11.2k
        bool b_continue;
366
11.2k
        do
367
174k
        {
368
174k
            b_continue = false;
369
466k
            for( int i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
370
292k
            {
371
292k
                logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
372
292k
                if( Ogg_HasQueuedBlocks( p_stream ) )
373
172k
                    Ogg_SendQueuedBlock( p_demux, p_stream );
374
292k
                b_continue |= Ogg_HasQueuedBlocks( p_stream );
375
292k
            }
376
377
            /* Generate Current PCR */
378
174k
            i_pcr = Ogg_GeneratePCR( p_demux, b_drain );
379
174k
            if( i_pcr != VLC_TICK_INVALID && i_pcr != p_sys->i_pcr )
380
46.9k
            {
381
46.9k
                p_sys->i_pcr = i_pcr;
382
46.9k
                if( likely( !p_sys->b_slave ) )
383
46.9k
                    es_out_SetPCR( p_demux->out, p_sys->i_pcr );
384
46.9k
            }
385
174k
        } while ( b_continue );
386
11.2k
    }
387
14.2k
}
388
389
390
/*****************************************************************************
391
 * Demux: reads and demuxes data packets
392
 *****************************************************************************
393
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
394
 *****************************************************************************/
395
static int Demux( demux_t * p_demux )
396
16.5k
{
397
16.5k
    demux_sys_t *p_sys = p_demux->p_sys;
398
16.5k
    ogg_packet  oggpacket;
399
16.5k
    int         i_stream;
400
16.5k
    bool b_canseek;
401
402
16.5k
    int i_active_streams = p_sys->i_streams;
403
80.3k
    for ( int i=0; i < p_sys->i_streams; i++ )
404
63.7k
    {
405
63.7k
        if ( p_sys->pp_stream[i]->b_finished )
406
2.90k
            i_active_streams--;
407
63.7k
    }
408
409
16.5k
    if ( i_active_streams == 0 )
410
861
    {
411
861
        if ( p_sys->i_streams ) /* All finished */
412
753
        {
413
753
            msg_Dbg( p_demux, "end of a group of %d logical streams", p_sys->i_streams );
414
415
753
            Ogg_OutputQueues( p_demux, true );
416
417
753
            vlc_tick_t i_lastdts = Ogg_GetLastDTS( p_demux );
418
419
            /* We keep the ES to try reusing it in Ogg_BeginningOfStream
420
             * only 1 ES is supported (common case for ogg web radio) */
421
753
            if( p_sys->i_streams == 1 && p_sys->i_declared_streams == 1 && p_sys->pp_stream[0]->p_es )
422
467
            {
423
467
                if( p_sys->p_old_stream ) /* if no setupEs has reused */
424
0
                    Ogg_LogicalStreamDelete( p_demux, p_sys->p_old_stream );
425
467
                p_sys->p_old_stream = p_sys->pp_stream[0];
426
467
                TAB_CLEAN( p_sys->i_streams, p_sys->pp_stream );
427
467
            }
428
429
753
            Ogg_EndOfStream( p_demux );
430
753
            p_sys->b_chained_boundary = true;
431
432
753
            if( i_lastdts != VLC_TICK_INVALID )
433
274
            {
434
274
                p_sys->i_nzpcr_offset = i_lastdts - VLC_TICK_0;
435
274
                if( likely( !p_sys->b_slave ) )
436
274
                    es_out_SetPCR( p_demux->out, i_lastdts );
437
274
            }
438
753
            p_sys->i_pcr = VLC_TICK_INVALID;
439
753
        }
440
441
861
        if( Ogg_BeginningOfStream( p_demux ) != VLC_SUCCESS )
442
45
            return VLC_DEMUXER_EOF;
443
444
816
        msg_Dbg( p_demux, "beginning of a group of logical streams" );
445
446
816
        if ( !p_sys->b_chained_boundary )
447
75
        {
448
            /* Find the real duration */
449
75
            vlc_stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_canseek );
450
75
            if ( b_canseek )
451
75
                Oggseek_ProbeEnd( p_demux );
452
75
        }
453
741
        else
454
741
        {
455
741
            p_sys->b_chained_boundary = false;
456
741
        }
457
816
    }
458
459
16.5k
    if ( p_sys->b_preparsing_done && !p_sys->b_es_created )
460
677
        Ogg_CreateES( p_demux, false );
461
462
    /*
463
     * The first data page of a physical stream is stored in the relevant logical stream
464
     * in Ogg_FindLogicalStreams. Therefore, we must not read a page and only update the
465
     * stream it belongs to if we haven't processed this first page yet. If we do, we
466
     * will only process that first page whenever we find the second page for this stream.
467
     * While this is fine for Vorbis and Theora, which are continuous codecs, which means
468
     * the second page will arrive real quick, this is not fine for Kate, whose second
469
     * data page will typically arrive much later.
470
     * This means it is now possible to seek right at the start of a stream where the last
471
     * logical stream is Kate, without having to wait for the second data page to unblock
472
     * the first one, which is the one that triggers the 'no more headers to backup' code.
473
     * And, as we all know, seeking without having backed up all headers is bad, since the
474
     * codec will fail to initialize if it's missing its headers.
475
     */
476
16.5k
    if( !p_sys->b_page_waiting)
477
15.8k
    {
478
        /*
479
         * Demux an ogg page from the stream
480
         */
481
15.8k
        if( Ogg_ReadPage( p_demux, &p_sys->current_page ) != VLC_SUCCESS )
482
74
            return VLC_DEMUXER_EOF; /* EOF */
483
        /* Test for End of Stream */
484
15.7k
        if( ogg_page_eos( &p_sys->current_page ) )
485
2.87k
        {
486
            /* If we delayed restarting encoders/SET_ES_FMT for more
487
             * skeleton provided configuration */
488
2.87k
            if ( p_sys->p_skelstream )
489
0
            {
490
0
                if ( p_sys->p_skelstream->i_serial_no == ogg_page_serialno(&p_sys->current_page) )
491
0
                {
492
0
                    msg_Dbg( p_demux, "End of Skeleton" );
493
0
                    p_sys->b_preparsing_done = true;
494
0
                    for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
495
0
                    {
496
0
                        logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
497
0
                        Ogg_ApplySkeleton( p_stream );
498
0
                    }
499
0
                }
500
0
            }
501
502
6.71k
            for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
503
5.06k
            {
504
5.06k
                if ( p_sys->pp_stream[i_stream]->i_serial_no == ogg_page_serialno( &p_sys->current_page ) )
505
1.22k
                {
506
1.22k
                    p_sys->pp_stream[i_stream]->b_finished = true;
507
1.22k
                    break;
508
1.22k
                }
509
5.06k
            }
510
2.87k
        }
511
15.7k
    }
512
513
26.6k
    for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
514
25.0k
    {
515
25.0k
        logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
516
517
        /* if we've just pulled page, look for the right logical stream */
518
25.0k
        if( !p_sys->b_page_waiting )
519
24.1k
        {
520
24.1k
            if( p_sys->i_streams == 1 && p_sys->i_declared_streams == 1 &&
521
11.7k
                ogg_page_serialno( &p_sys->current_page ) != p_stream->os.serialno )
522
3.92k
            {
523
3.92k
                msg_Err( p_demux, "Broken Ogg stream (serialno) mismatch" );
524
3.92k
                Ogg_ResetStream( p_stream );
525
3.92k
                if( p_stream->i_pcr != VLC_TICK_INVALID )
526
0
                    p_sys->i_nzpcr_offset = p_stream->i_pcr - VLC_TICK_0;
527
3.92k
                ogg_stream_reset_serialno( &p_stream->os, ogg_page_serialno( &p_sys->current_page ) );
528
3.92k
            }
529
530
            /* Does fail if serialno differs */
531
24.1k
            if( ogg_stream_pagein( &p_stream->os, &p_sys->current_page ) != 0 )
532
9.31k
            {
533
9.31k
                continue;
534
9.31k
            }
535
24.1k
        }
536
537
538
15.7k
        if( ogg_page_granulepos( &p_sys->current_page  ) == 0 && !p_stream->b_oggds )
539
5.06k
            p_stream->page_type = OGGPAGE_HEADER;
540
10.6k
        else if( p_stream->page_type == OGGPAGE_HEADER )
541
2.74k
            p_stream->page_type = OGGPAGE_FIRST;
542
7.90k
        else
543
7.90k
            p_stream->page_type = OGGPAGE_OTHER;
544
545
15.7k
        if( p_stream->page_type == OGGPAGE_FIRST && p_stream->fmt.i_codec == VLC_CODEC_OPUS )
546
72
            p_stream->i_skip_frames = p_stream->i_pre_skip;
547
548
        /* clear the finished flag if pages after eos (ex: after a seek) */
549
15.7k
        if ( ! ogg_page_eos( &p_sys->current_page ) && p_sys->p_skelstream != p_stream )
550
12.6k
            p_stream->b_finished = false;
551
552
15.7k
        DemuxDebug(
553
15.7k
            if ( p_stream->fmt.i_cat == VIDEO_ES )
554
15.7k
                msg_Dbg(p_demux, "DEMUX READ pageno %ld g%"PRId64" (%d packets) cont %d %ld bytes",
555
15.7k
                    ogg_page_pageno( &p_sys->current_page ),
556
15.7k
                    ogg_page_granulepos( &p_sys->current_page ),
557
15.7k
                    ogg_page_packets( &p_sys->current_page ),
558
15.7k
                    ogg_page_continued(&p_sys->current_page),
559
15.7k
                    p_sys->current_page.body_len )
560
15.7k
        );
561
562
254k
        while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
563
239k
        {
564
            /* Read info from any secondary header packets, if there are any */
565
239k
            if( p_stream->i_secondary_header_packets > 0 )
566
0
            {
567
0
                if( p_stream->fmt.i_codec == VLC_CODEC_THEORA &&
568
0
                        oggpacket.bytes >= 7 &&
569
0
                        ! memcmp( oggpacket.packet, "\x80theora", 7 ) )
570
0
                {
571
0
                    Ogg_ReadTheoraHeader( p_stream, &oggpacket );
572
0
                    p_stream->i_secondary_header_packets = 0;
573
0
                }
574
0
                else if( p_stream->fmt.i_codec == VLC_CODEC_DAALA &&
575
0
                        oggpacket.bytes >= 6 &&
576
0
                        ! memcmp( oggpacket.packet, "\x80""daala", 6 ) )
577
0
                {
578
0
                    Ogg_ReadDaalaHeader( p_stream, &oggpacket );
579
0
                    p_stream->i_secondary_header_packets = 0;
580
0
                }
581
0
                else if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS &&
582
0
                        oggpacket.bytes >= 7 &&
583
0
                        ! memcmp( oggpacket.packet, "\x01vorbis", 7 ) )
584
0
                {
585
0
                    es_format_Change( &p_stream->fmt, AUDIO_ES, VLC_CODEC_VORBIS );
586
0
                    Ogg_ReadVorbisHeader( p_stream, &oggpacket );
587
0
                    p_stream->i_secondary_header_packets = 0;
588
0
                }
589
590
                /* update start of data pointer */
591
0
                p_stream->i_data_start = vlc_stream_Tell( p_demux->s );
592
0
            }
593
594
239k
            Ogg_DecodePacket( p_demux, p_stream, &oggpacket, ogg_page_eos( &p_sys->current_page ) );
595
239k
        }
596
597
598
15.7k
        if( !p_sys->b_page_waiting )
599
14.8k
            break;
600
15.7k
    }
601
602
    /* if a page was waiting, it's now processed */
603
16.4k
    p_sys->b_page_waiting = false;
604
605
16.4k
    if ( p_sys->p_skelstream && !p_sys->p_skelstream->b_finished )
606
0
        p_sys->b_preparsing_done = false;
607
16.4k
    else
608
16.4k
        p_sys->b_preparsing_done = true;
609
610
16.4k
    if( p_sys->b_preparsing_done )
611
16.4k
    {
612
38.3k
        for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
613
24.0k
        {
614
24.0k
            logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
615
24.0k
            if ( p_stream->b_initializing )
616
2.18k
            {
617
                /* We have 1 or more streams needing more than 1 page for preparsing */
618
2.18k
                p_sys->b_preparsing_done = false;
619
2.18k
                break;
620
2.18k
            }
621
24.0k
        }
622
16.4k
    }
623
624
16.4k
    if( p_sys->b_preparsing_done && p_sys->b_es_created )
625
13.5k
        Ogg_OutputQueues( p_demux, false );
626
627
16.4k
    return VLC_DEMUXER_SUCCESS;
628
16.5k
}
629
630
static void Ogg_ResetStream( logical_stream_t *p_stream )
631
3.92k
{
632
3.92k
#ifdef HAVE_LIBVORBIS
633
3.92k
    if ( p_stream->fmt.i_codec == VLC_CODEC_VORBIS )
634
1.31k
    {
635
1.31k
        p_stream->special.vorbis.i_prev_blocksize = 0;
636
1.31k
    }
637
3.92k
#endif
638
3.92k
    if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
639
109
    {
640
641
        /* For Opus, trash the first 80 ms of decoded output as
642
               well, to avoid blowing out speakers if we get unlucky.
643
               Opus predicts content from prior frames, which can go
644
               badly if we seek right where the stream goes from very
645
               quiet to very loud. It will converge after a bit. */
646
109
        if( p_stream->i_skip_frames < p_stream->i_pre_skip )
647
6
            p_stream->i_skip_frames = __MAX( 80*48, p_stream->i_pre_skip );
648
109
    }
649
    /* we'll trash all the data until we find the next pcr */
650
3.92k
    p_stream->i_pcr = VLC_TICK_INVALID;
651
3.92k
    p_stream->i_next_block_flags = 0;
652
3.92k
    p_stream->b_interpolation_failed = false;
653
3.92k
    date_Set( &p_stream->dts, VLC_TICK_INVALID );
654
3.92k
    ogg_stream_reset( &p_stream->os );
655
3.92k
    block_ChainRelease( p_stream->queue.p_blocks );
656
3.92k
    p_stream->queue.p_blocks = NULL;
657
3.92k
    p_stream->queue.pp_append = &p_stream->queue.p_blocks;
658
3.92k
}
659
660
static void Ogg_PreparePostSeek( demux_sys_t *p_sys )
661
0
{
662
0
    for( int i = 0; i < p_sys->i_streams; i++ )
663
0
    {
664
0
        Ogg_ResetStream( p_sys->pp_stream[i] );
665
0
        p_sys->pp_stream[i]->i_next_block_flags = BLOCK_FLAG_DISCONTINUITY;
666
0
    }
667
668
0
    ogg_sync_reset( &p_sys->oy );
669
0
    p_sys->i_pcr = VLC_TICK_INVALID;
670
0
}
671
672
static logical_stream_t * Ogg_GetSelectedStream( demux_t *p_demux )
673
0
{
674
0
    demux_sys_t *p_sys = p_demux->p_sys;
675
0
    logical_stream_t *p_stream = NULL;
676
0
    for( int i=0; i<p_sys->i_streams; i++ )
677
0
    {
678
0
        logical_stream_t *p_candidate = p_sys->pp_stream[i];
679
0
        if ( !p_candidate->p_es ) continue;
680
681
0
        bool b_selected = false;
682
0
        es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
683
0
                        p_candidate->p_es, &b_selected );
684
0
        if ( !b_selected ) continue;
685
686
0
        if ( !p_stream && p_candidate->fmt.i_cat == AUDIO_ES )
687
0
        {
688
0
            p_stream = p_candidate;
689
0
            continue; /* Try to find video anyway */
690
0
        }
691
692
0
        if ( p_candidate->fmt.i_cat == VIDEO_ES )
693
0
        {
694
0
            p_stream = p_candidate;
695
0
            break;
696
0
        }
697
0
    }
698
0
    return p_stream;
699
0
}
700
701
/*****************************************************************************
702
 * Control:
703
 *****************************************************************************/
704
static int Control( demux_t *p_demux, int i_query, va_list args )
705
0
{
706
0
    demux_sys_t *p_sys  = p_demux->p_sys;
707
0
    vlc_meta_t *p_meta;
708
0
    vlc_tick_t i64;
709
0
    double f;
710
0
    bool *pb_bool, b, acc;
711
0
    logical_stream_t *p_stream;
712
713
0
    switch( i_query )
714
0
    {
715
0
        case DEMUX_CAN_SEEK:
716
0
            return vlc_stream_vaControl( p_demux->s, i_query, args );
717
718
0
        case DEMUX_GET_META:
719
0
            p_meta = va_arg( args, vlc_meta_t * );
720
0
            if( p_sys->p_meta )
721
0
                vlc_meta_Merge( p_meta, p_sys->p_meta );
722
0
            return VLC_SUCCESS;
723
724
0
        case DEMUX_HAS_UNSUPPORTED_META:
725
0
            pb_bool = va_arg( args, bool* );
726
0
            *pb_bool = true;
727
0
            return VLC_SUCCESS;
728
729
0
        case DEMUX_SET_NEXT_DEMUX_TIME:
730
0
            p_sys->b_slave = true;
731
0
            return VLC_EGENERIC;
732
733
0
        case DEMUX_GET_TIME:
734
0
            if( p_sys->i_pcr != VLC_TICK_INVALID || p_sys->b_slave )
735
0
            {
736
0
                *va_arg( args, vlc_tick_t * ) = p_sys->i_pcr;
737
0
                return VLC_SUCCESS;
738
0
            }
739
0
            return VLC_EGENERIC;
740
741
0
        case DEMUX_SET_TIME:
742
0
        {
743
0
            i64 = va_arg( args, vlc_tick_t );
744
0
            acc = va_arg( args, int );
745
0
            p_stream = Ogg_GetSelectedStream( p_demux );
746
0
            if ( !p_stream )
747
0
            {
748
0
                msg_Err( p_demux, "No selected seekable stream found" );
749
0
                return VLC_EGENERIC;
750
0
            }
751
0
            vlc_stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b );
752
0
            vlc_tick_t i_preroll = Ogg_GetDecoderPreroll( p_stream );
753
0
            if( i_preroll > i64 )
754
0
                i_preroll = i64;
755
0
            if ( Oggseek_BlindSeektoAbsoluteTime( p_demux, p_stream, VLC_TICK_0 + i64 - i_preroll, b ) != -1 )
756
0
            {
757
0
                Ogg_PreparePostSeek( p_sys );
758
0
                if( acc )
759
0
                    es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
760
0
                                    VLC_TICK_0 + i64 );
761
0
                return VLC_SUCCESS;
762
0
            }
763
0
            else
764
0
                return VLC_EGENERIC;
765
0
        }
766
767
0
        case DEMUX_GET_ATTACHMENTS:
768
0
        {
769
0
            input_attachment_t ***ppp_attach =
770
0
                va_arg( args, input_attachment_t *** );
771
0
            int *pi_int = va_arg( args, int * );
772
773
0
            if( p_sys->i_attachments <= 0 )
774
0
                return VLC_EGENERIC;
775
776
0
            *ppp_attach = vlc_alloc( p_sys->i_attachments, sizeof(input_attachment_t*) );
777
0
            if (!*ppp_attach)
778
0
                return VLC_ENOMEM;
779
0
            *pi_int = p_sys->i_attachments;
780
0
            for( int i = 0; i < p_sys->i_attachments; i++ )
781
0
                (*ppp_attach)[i] = vlc_input_attachment_Hold( p_sys->attachments[i] );
782
0
            return VLC_SUCCESS;
783
0
        }
784
785
0
        case DEMUX_GET_POSITION: {
786
0
            double pos = 0.;
787
0
            uint64_t size;
788
789
0
            if( p_sys->i_length > 0 && p_sys->i_pcr != VLC_TICK_INVALID )
790
0
            {
791
0
                pos = (double) p_sys->i_pcr / (double) p_sys->i_length;
792
0
            }
793
0
            else if( vlc_stream_GetSize( p_demux->s, &size ) == 0 && size > 0 )
794
0
            {
795
0
                uint64_t offset = vlc_stream_Tell( p_demux->s );
796
0
                pos = (double) offset / (double) size;
797
0
            }
798
799
0
            *va_arg( args, double * ) = pos;
800
0
            return VLC_SUCCESS;
801
0
        }
802
803
0
        case DEMUX_SET_POSITION:
804
            /* forbid seeking if we haven't initialized all logical bitstreams yet;
805
               if we allowed, some headers would not get backed up and decoder init
806
               would fail, making that logical stream unusable */
807
0
            for ( int i=0; i< p_sys->i_streams; i++ )
808
0
            {
809
0
                if ( p_sys->pp_stream[i]->b_initializing )
810
0
                    return VLC_EGENERIC;
811
0
            }
812
813
0
            p_stream = Ogg_GetSelectedStream( p_demux );
814
0
            if ( !p_stream )
815
0
            {
816
0
                msg_Err( p_demux, "No selected seekable stream found" );
817
0
                return VLC_EGENERIC;
818
0
            }
819
820
0
            vlc_stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b );
821
822
0
            f = va_arg( args, double );
823
0
            acc = va_arg( args, int );
824
0
            if ( p_sys->i_length <= 0 || !b /* || ! STREAM_CAN_FASTSEEK */ )
825
0
            {
826
0
                int ret = Oggseek_BlindSeektoPosition( p_demux, p_stream, f, b );
827
0
                if( ret == VLC_SUCCESS )
828
0
                    Ogg_PreparePostSeek( p_sys );
829
0
                return ret;
830
0
            }
831
832
0
            assert( p_sys->i_length > 0 );
833
0
            i64 = f * p_sys->i_length;
834
0
            vlc_tick_t i_preroll = Ogg_GetDecoderPreroll( p_stream );
835
0
            if( i_preroll > i64 )
836
0
                i_preroll = i64;
837
0
            if ( Oggseek_SeektoAbsolutetime( p_demux, p_stream, VLC_TICK_0 + i64 - i_preroll ) >= 0 )
838
0
            {
839
0
                Ogg_PreparePostSeek( p_sys );
840
0
                if( acc )
841
0
                    es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
842
0
                                    VLC_TICK_0 + i64 );
843
0
                return VLC_SUCCESS;
844
0
            }
845
846
0
            return VLC_EGENERIC;
847
848
0
        case DEMUX_GET_LENGTH:
849
0
            if ( p_sys->i_length < 0 )
850
0
                return demux_vaControlHelper( p_demux->s, 0, -1, p_sys->i_bitrate,
851
0
                                              1, i_query, args );
852
0
            *va_arg( args, vlc_tick_t * ) = p_sys->i_length;
853
0
            return VLC_SUCCESS;
854
855
0
        case DEMUX_GET_TITLE_INFO:
856
0
        {
857
0
            input_title_t ***ppp_title = va_arg( args, input_title_t *** );
858
0
            int *pi_int = va_arg( args, int* );
859
0
            int *pi_title_offset = va_arg( args, int* );
860
0
            int *pi_seekpoint_offset = va_arg( args, int* );
861
862
0
            if( p_sys->i_seekpoints == 0 )
863
0
                return VLC_EGENERIC;
864
865
0
            *pi_int = 1;
866
0
            input_title_t **titles = malloc(sizeof(*titles));
867
0
            if (titles == NULL)
868
0
                return VLC_ENOMEM;
869
870
0
            titles[0] = vlc_input_title_New();
871
0
            if (titles[0] == NULL)
872
0
            {
873
0
                free(titles);
874
0
                return VLC_ENOMEM;
875
0
            }
876
877
0
            for( int i = 0; i < p_sys->i_seekpoints; i++ )
878
0
            {
879
0
                seekpoint_t *p_seekpoint_copy = vlc_seekpoint_Duplicate( p_sys->pp_seekpoints[i] );
880
0
                if (unlikely(p_seekpoint_copy == NULL))
881
0
                {
882
0
                    for (int j = 0; j < i; ++j)
883
0
                    {
884
0
                        vlc_seekpoint_Delete(titles[0]->seekpoint[i]);
885
0
                    }
886
0
                    vlc_input_title_Delete(titles[0]);
887
0
                    free(titles);
888
0
                    return VLC_ENOMEM;
889
0
                }
890
0
                TAB_APPEND(titles[0]->i_seekpoint, titles[0]->seekpoint, p_seekpoint_copy);
891
0
            }
892
0
            *ppp_title = titles;
893
0
            *pi_title_offset = 0;
894
0
            *pi_seekpoint_offset = 0;
895
0
            return VLC_SUCCESS;
896
0
        }
897
0
        case DEMUX_SET_TITLE:
898
0
        {
899
0
            const int i_title = va_arg( args, int );
900
0
            if( i_title > 1 )
901
0
                return VLC_EGENERIC;
902
0
            return VLC_SUCCESS;
903
0
        }
904
0
        case DEMUX_SET_SEEKPOINT:
905
0
        {
906
0
            const int i_seekpoint = va_arg( args, int );
907
0
            if( i_seekpoint > p_sys->i_seekpoints )
908
0
                return VLC_EGENERIC;
909
910
0
            for ( int i=0; i< p_sys->i_streams; i++ )
911
0
            {
912
0
                if ( p_sys->pp_stream[i]->b_initializing )
913
0
                    return VLC_EGENERIC;
914
0
            }
915
916
0
            i64 = p_sys->pp_seekpoints[i_seekpoint]->i_time_offset;
917
918
0
            p_stream = Ogg_GetSelectedStream( p_demux );
919
0
            if ( !p_stream )
920
0
            {
921
0
                msg_Err( p_demux, "No selected seekable stream found" );
922
0
                return VLC_EGENERIC;
923
0
            }
924
925
0
            vlc_stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b );
926
0
            if ( Oggseek_BlindSeektoAbsoluteTime( p_demux, p_stream, VLC_TICK_0 + i64, b ) != -1 )
927
0
            {
928
0
                Ogg_PreparePostSeek( p_sys );
929
0
                es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
930
0
                                VLC_TICK_0 + i64 );
931
0
                p_sys->updates |= INPUT_UPDATE_SEEKPOINT;
932
0
                p_sys->cur_seekpoint = i_seekpoint;
933
0
                return VLC_SUCCESS;
934
0
            }
935
0
            else
936
0
                return VLC_EGENERIC;
937
0
        }
938
0
        case DEMUX_TEST_AND_CLEAR_FLAGS:
939
0
        {
940
0
            unsigned *restrict flags = va_arg( args, unsigned * );
941
0
            *flags &= p_sys->updates;
942
0
            p_sys->updates &= ~*flags;
943
0
            return VLC_SUCCESS;
944
0
        }
945
0
        case DEMUX_GET_TITLE:
946
0
            *va_arg( args, int * ) = 0;
947
0
            return VLC_SUCCESS;
948
0
        case DEMUX_GET_SEEKPOINT:
949
0
            *va_arg( args, int * ) = p_sys->cur_seekpoint;
950
0
            return VLC_SUCCESS;
951
952
0
        default:
953
0
            return demux_vaControlHelper( p_demux->s, 0, -1, p_sys->i_bitrate,
954
0
                                           1, i_query, args );
955
0
    }
956
0
}
957
958
/****************************************************************************
959
 * Ogg_ReadPage: Read a full Ogg page from the physical bitstream.
960
 ****************************************************************************
961
 * Returns VLC_SUCCESS if a page has been read. An error might happen if we
962
 * are at the end of stream.
963
 ****************************************************************************/
964
static int Ogg_ReadPage( demux_t *p_demux, ogg_page *p_oggpage )
965
19.0k
{
966
19.0k
    demux_sys_t *p_ogg = p_demux->p_sys  ;
967
19.0k
    int i_read = 0;
968
19.0k
    char *p_buffer;
969
970
29.1k
    while( ogg_sync_pageout( &p_ogg->oy, p_oggpage ) != 1 )
971
10.1k
    {
972
10.1k
        p_buffer = ogg_sync_buffer( &p_ogg->oy, OGGSEEK_BYTES_TO_READ );
973
10.1k
        if( !p_buffer )
974
0
            return VLC_EGENERIC;
975
976
10.1k
        i_read = vlc_stream_Read( p_demux->s, p_buffer, OGGSEEK_BYTES_TO_READ );
977
10.1k
        if( i_read <= 0 )
978
103
            return VLC_EGENERIC;
979
980
10.0k
        ogg_sync_wrote( &p_ogg->oy, i_read );
981
10.0k
    }
982
983
18.9k
    return VLC_SUCCESS;
984
19.0k
}
985
986
static void Ogg_SetNextFrame( demux_t *p_demux, logical_stream_t *p_stream,
987
                              ogg_packet *p_oggpacket )
988
233k
{
989
233k
    VLC_UNUSED(p_demux);
990
233k
    ogg_int64_t i_granule = p_oggpacket->granulepos;
991
992
233k
    if( Ogg_GranuleIsValid( p_stream, i_granule ) )
993
8.36k
    {
994
8.36k
        vlc_tick_t i_endtime = Ogg_GranuleToTime( p_stream, i_granule, false, false );
995
8.36k
        assert( !p_stream->b_contiguous || i_endtime != VLC_TICK_INVALID );
996
8.36k
        if( i_endtime != VLC_TICK_INVALID )
997
8.36k
        {
998
8.36k
            date_Set( &p_stream->dts, i_endtime );
999
8.36k
            return;
1000
8.36k
        }
1001
8.36k
    }
1002
1003
    /* Do Interpolation if can't compute directly from granule */
1004
225k
    if( date_Get( &p_stream->dts ) != VLC_TICK_INVALID )
1005
76.7k
    {
1006
76.7k
        if( p_stream->fmt.i_cat == VIDEO_ES )
1007
4.95k
        {
1008
4.95k
            date_Increment( &p_stream->dts, 1 );
1009
4.95k
        }
1010
71.7k
        else if( p_stream->fmt.i_cat == AUDIO_ES )
1011
70.8k
        {
1012
70.8k
            int64_t i_samples = 0;
1013
70.8k
            switch( p_stream->fmt.i_codec )
1014
70.8k
            {
1015
279
                case VLC_CODEC_OPUS:
1016
279
                    i_samples = Ogg_OpusPacketDuration( p_oggpacket );
1017
279
                    break;
1018
6.06k
                case VLC_CODEC_SPEEX:
1019
6.06k
                    i_samples = p_stream->special.speex.i_framesize *
1020
6.06k
                                p_stream->special.speex.i_framesperpacket;
1021
6.06k
                    break;
1022
0
#ifdef HAVE_LIBVORBIS
1023
250k
# define Vbs p_stream->special.vorbis
1024
59.4k
                case VLC_CODEC_VORBIS:
1025
59.4k
                    if( Vbs.p_info && VORBIS_HEADERS_VALID(p_stream) )
1026
47.9k
                    {
1027
47.9k
                        long i_blocksize = vorbis_packet_blocksize( Vbs.p_info, p_oggpacket );
1028
                        /* duration in samples per channel */
1029
47.9k
                        if( Ogg_VorbisValidBlocksize( i_blocksize ) )
1030
47.7k
                        {
1031
47.7k
                            if ( Ogg_VorbisValidBlocksize( Vbs.i_prev_blocksize ) )
1032
47.5k
                                i_samples = ( i_blocksize + Vbs.i_prev_blocksize ) / 4;
1033
143
                            else
1034
143
                                i_samples = i_blocksize / 2;
1035
47.7k
                        }
1036
47.9k
                        Vbs.i_prev_blocksize = i_blocksize;
1037
47.9k
                    }
1038
59.4k
                    break;
1039
0
# undef Vbs
1040
0
#endif
1041
5.01k
                default:
1042
5.01k
                    if( p_stream->fmt.i_bitrate )
1043
0
                    {
1044
0
                        i_samples = 8 * p_oggpacket->bytes * p_stream->dts.i_divider_num;
1045
0
                        i_samples /= p_stream->fmt.i_bitrate / p_stream->dts.i_divider_den;
1046
0
                    }
1047
5.01k
                    break;
1048
70.8k
            }
1049
70.8k
            if( i_samples == 0 )
1050
16.7k
                p_stream->b_interpolation_failed = true;
1051
54.0k
            else
1052
54.0k
                date_Increment( &p_stream->dts, i_samples );
1053
70.8k
        }
1054
76.7k
    }
1055
225k
}
1056
1057
static vlc_tick_t Ogg_FixupOutputQueue( demux_t *p_demux, logical_stream_t *p_stream,
1058
                                        vlc_tick_t i_enddts, bool b_eos )
1059
974
{
1060
974
    demux_sys_t *p_sys = p_demux->p_sys;
1061
1062
    // PASS 1, set number of samples
1063
974
    unsigned i_total_samples = 0;
1064
37.7k
    for( block_t *p_block = p_stream->queue.p_blocks; p_block; p_block = p_block->p_next )
1065
36.8k
    {
1066
36.8k
        if( p_block->i_flags & BLOCK_FLAG_HEADER )
1067
272
            continue;
1068
1069
36.5k
        ogg_packet dumb_packet;
1070
1071
36.5k
        switch( p_stream->fmt.i_codec )
1072
36.5k
        {
1073
4.95k
            case VLC_CODEC_SPEEX:
1074
4.95k
                p_block->i_nb_samples = p_stream->special.speex.i_framesize *
1075
4.95k
                                        p_stream->special.speex.i_framesperpacket;
1076
4.95k
                break;
1077
389
            case VLC_CODEC_OPUS:
1078
389
                dumb_packet.bytes = p_block->i_buffer;
1079
389
                dumb_packet.packet = p_block->p_buffer;
1080
                /* Less complicated than Vorbis case below as packets samples count
1081
                 * is known for every packet */
1082
389
                p_block->i_nb_samples = Ogg_OpusPacketDuration( &dumb_packet );
1083
389
                break;
1084
0
#ifdef HAVE_LIBVORBIS
1085
9.35k
            case VLC_CODEC_VORBIS:
1086
9.35k
            {
1087
9.35k
                if( !VORBIS_HEADERS_VALID(p_stream) )
1088
5.59k
                {
1089
5.59k
                    msg_Err( p_demux, "missing vorbis headers, can't compute block size" );
1090
5.59k
                    break;
1091
5.59k
                }
1092
1093
3.76k
                if( p_block->p_next == NULL )
1094
202
                    break;
1095
1096
                /* Vorbis Hell
1097
                   Samples are computed from N..N+1 window
1098
                   We can set samples for packets up to N-1
1099
                   Last packet is granule pos - total... but
1100
                   that would be too easy without truncation
1101
                   and beginning of stream cases.
1102
                   If that's BOS, we need to truncate on start (negative samples)
1103
                   If that's EOS, we need to truncate the end to match granule.
1104
                   If that's both single page and not starting zero.. we're ***** */
1105
3.55k
                dumb_packet.bytes = p_block->i_buffer;
1106
3.55k
                dumb_packet.packet = p_block->p_buffer;
1107
3.55k
                long i_blocksize = vorbis_packet_blocksize( p_stream->special.vorbis.p_info,
1108
3.55k
                                                            &dumb_packet );
1109
3.55k
                dumb_packet.bytes = p_block->p_next->i_buffer;
1110
3.55k
                dumb_packet.packet = p_block->p_next->p_buffer;
1111
3.55k
                long i_nextblocksize = vorbis_packet_blocksize( p_stream->special.vorbis.p_info,
1112
3.55k
                                                                &dumb_packet );
1113
                /* The spec has 3 specific cases depending on long/short prev/next blocksizes
1114
                   ranging weights from 1/4 to 3/4... but everyone does A/4 + B/4 */
1115
3.55k
                if( Ogg_VorbisValidBlocksize( i_blocksize ) && Ogg_VorbisValidBlocksize( i_nextblocksize ) )
1116
3.34k
                    p_block->i_nb_samples = (i_blocksize + i_nextblocksize) / 4;
1117
3.55k
                break;
1118
3.76k
            }
1119
0
#endif
1120
21.8k
            default:
1121
21.8k
                if( p_stream->fmt.i_cat == VIDEO_ES )
1122
888
                    p_block->i_nb_samples = 1;
1123
21.8k
                break;
1124
36.5k
        }
1125
36.5k
        i_total_samples += p_block->i_nb_samples;
1126
36.5k
    }
1127
1128
    // PASS 2
1129
974
    if( i_enddts != VLC_TICK_INVALID )
1130
974
    {
1131
974
        date_t d = p_stream->dts;
1132
974
        date_Set( &d, i_enddts );
1133
974
        i_enddts = date_Decrement( &d, i_total_samples );
1134
974
        if( i_enddts < VLC_TICK_0 )
1135
149
            i_enddts = VLC_TICK_0;
1136
974
        vlc_tick_t difftopos = ( date_Get( &d ) < VLC_TICK_0 )
1137
974
                             ? VLC_TICK_0 - date_Get( &d )
1138
974
                             : 0;
1139
        /* enforce positive values in date_t so we don't run
1140
         * into impossible increment on INVALID */
1141
974
        date_Set( &d, date_Get( &d ) + difftopos );
1142
1143
974
        assert(date_Get( &d ) != VLC_TICK_INVALID);
1144
1145
        /* truncate end */
1146
974
        if( b_eos && date_Get( &d ) < VLC_TICK_0 )
1147
0
            date_Set( &d, VLC_TICK_0 );
1148
1149
37.7k
        for( block_t *p_block = p_stream->queue.p_blocks; p_block; p_block = p_block->p_next )
1150
36.8k
        {
1151
36.8k
            if( p_block->i_flags & BLOCK_FLAG_HEADER )
1152
272
                continue;
1153
36.5k
            p_block->i_dts = date_Get( &d ) - difftopos;
1154
1155
            /* truncate start */
1156
36.5k
            if( !b_eos && p_block->i_dts < VLC_TICK_0 )
1157
428
                p_block->i_dts = VLC_TICK_0;
1158
1159
            /* Last page in the stream case, truncate end */
1160
36.5k
            if( b_eos && p_block->p_next == NULL )
1161
296
                p_block->i_dts = __MIN(p_block->i_dts, i_enddts);
1162
1163
36.5k
            if( p_sys->i_nzpcr_offset )
1164
7.18k
                p_block->i_dts += p_sys->i_nzpcr_offset;
1165
1166
36.5k
            if( p_stream->fmt.i_cat == AUDIO_ES )
1167
15.9k
                p_block->i_pts = p_block->i_dts;
1168
36.5k
            date_Increment( &d, p_block->i_nb_samples );
1169
36.5k
        }
1170
1171
974
    } /* else can't do anything, no timestamped blocks in stream */
1172
1173
974
    return ( i_enddts != VLC_TICK_INVALID )? p_sys->i_nzpcr_offset + i_enddts : i_enddts;
1174
974
}
1175
1176
static void Ogg_QueueBlocks( demux_t *p_demux, logical_stream_t *p_stream,
1177
                             block_t *p_block, vlc_tick_t i_enddts, bool b_eos )
1178
233k
{
1179
233k
    demux_sys_t *p_sys = p_demux->p_sys;
1180
233k
    VLC_UNUSED(p_sys);
1181
1182
233k
    if( p_block == NULL )
1183
0
    {
1184
0
        assert( p_block != NULL );
1185
0
        return;
1186
0
    }
1187
1188
233k
    block_ChainLastAppend( &p_stream->queue.pp_append, p_block );
1189
1190
    /* If we can have or compute block start from granule, it is set.
1191
     * Otherwise the end dts will be used for reverse calculation */
1192
233k
    if( p_stream->i_pcr == VLC_TICK_INVALID && i_enddts != VLC_TICK_INVALID && p_block->i_dts != VLC_TICK_INVALID )
1193
974
    {
1194
        /* fixup queue */
1195
974
        p_stream->i_pcr = Ogg_FixupOutputQueue( p_demux, p_stream, i_enddts, b_eos );
1196
974
    }
1197
1198
233k
    DemuxDebug( msg_Dbg( p_demux, "%4.4s block queued > dts %"PRId64" spcr %"PRId64" pcr %"PRId64,
1199
233k
                         (char*)&p_stream->fmt.i_codec, p_block->i_dts, p_stream->i_pcr, p_sys->i_pcr ); )
1200
233k
}
1201
1202
static void Ogg_SendQueuedBlock( demux_t *p_demux, logical_stream_t *p_stream )
1203
172k
{
1204
172k
    demux_sys_t *p_sys = p_demux->p_sys;
1205
1206
172k
    if( Ogg_HasQueuedBlocks( p_stream ) )
1207
172k
    {
1208
172k
        block_t *p_queued = p_stream->queue.p_blocks;
1209
172k
        p_stream->queue.p_blocks = p_queued->p_next;
1210
172k
        p_queued->p_next = NULL;
1211
1212
172k
        if( p_queued->i_dts == VLC_TICK_INVALID )
1213
81.5k
            p_queued->i_dts = p_queued->i_pts;
1214
1215
172k
        if( p_queued->i_flags & BLOCK_FLAG_HEADER )
1216
2.81k
        {
1217
2.81k
            if( p_sys->i_nzpcr_offset > 0 || /* Don't send metadata from chained streams */
1218
2.06k
                p_stream->fmt.i_extra > 0 )  /* Don't send metadata if configured by extradata */
1219
2.80k
            {
1220
2.80k
                block_Release( p_queued );
1221
2.80k
                goto end;
1222
2.80k
            }
1223
8
            p_queued->i_flags &= ~BLOCK_FLAG_HEADER;
1224
8
        }
1225
1226
169k
        unsigned i_toskip = 0;
1227
169k
        if( p_stream->i_skip_frames > 0 )
1228
23
        {
1229
23
            if( p_sys->i_nzpcr_offset > 0 )
1230
23
            {
1231
                /* not preskip handling on chained streams */
1232
23
                p_stream->i_skip_frames = 0;
1233
23
            }
1234
0
            else
1235
0
            {
1236
0
                i_toskip = __MIN( p_stream->i_skip_frames, p_queued->i_nb_samples );
1237
0
                p_stream->i_skip_frames -= i_toskip;
1238
0
                p_queued->i_nb_samples -= i_toskip;
1239
0
                if( p_queued->i_nb_samples == 0 )
1240
0
                    p_queued->i_flags |= BLOCK_FLAG_PREROLL;
1241
0
            }
1242
23
        }
1243
1244
169k
        p_queued->i_flags |= p_stream->i_next_block_flags;
1245
169k
        p_stream->i_next_block_flags = 0;
1246
169k
        p_stream->i_pcr = p_queued->i_dts;
1247
1248
169k
        DemuxDebug( msg_Dbg( p_demux, "%4.4s block sent > dts %"PRId64" pts %"PRId64" spcr %"PRId64" pcr %"PRId64
1249
169k
                             " samples (%d/%d)",
1250
169k
                             (char*)&p_stream->fmt.i_codec, p_queued->i_dts,
1251
169k
                             p_queued->i_pts, p_stream->i_pcr, p_sys->i_pcr,
1252
169k
                             p_queued->i_nb_samples, i_toskip ); );
1253
1254
169k
        assert( p_sys->i_pcr != VLC_TICK_INVALID );
1255
1256
169k
        if( p_stream->p_es )
1257
131k
            es_out_Send( p_demux->out, p_stream->p_es, p_queued );
1258
37.2k
        else
1259
37.2k
            block_Release( p_queued );
1260
169k
    }
1261
1262
172k
end:
1263
172k
    if( p_stream->queue.p_blocks == NULL )
1264
8.71k
        p_stream->queue.pp_append = &p_stream->queue.p_blocks;
1265
172k
}
1266
1267
static bool Ogg_IsHeaderPacket( const logical_stream_t *p_stream,
1268
                                const ogg_packet *p_oggpacket )
1269
238k
{
1270
238k
    if ( p_stream->b_oggds )
1271
21.9k
    {
1272
21.9k
        return p_oggpacket->bytes > 0 &&
1273
19.7k
               (p_oggpacket->packet[0] & PACKET_TYPE_HEADER);
1274
21.9k
    }
1275
216k
    else return ( p_oggpacket->granulepos == 0 && p_stream->i_first_frame_index > 0 );
1276
238k
}
1277
1278
/****************************************************************************
1279
 * Ogg_DecodePacket: Decode an Ogg packet.
1280
 ****************************************************************************/
1281
static void Ogg_DecodePacket( demux_t *p_demux,
1282
                              logical_stream_t *p_stream,
1283
                              ogg_packet *p_oggpacket, bool b_eos )
1284
239k
{
1285
239k
    demux_sys_t *p_sys = p_demux->p_sys;
1286
239k
    block_t *p_block;
1287
239k
    bool b_selected;
1288
239k
    long i_header_len = 0;
1289
1290
239k
    if( p_oggpacket->bytes >= 7 &&
1291
50.1k
        ! memcmp ( p_oggpacket->packet, "Annodex", 7 ) )
1292
0
    {
1293
        /* it's an Annodex packet -- skip it (do nothing) */
1294
0
        return;
1295
0
    }
1296
239k
    else if( p_oggpacket->bytes >= 7 &&
1297
50.1k
        ! memcmp ( p_oggpacket->packet, "AnxData", 7 ) )
1298
0
    {
1299
        /* it's an AnxData packet -- skip it (do nothing) */
1300
0
        return;
1301
0
    }
1302
239k
    else if( p_oggpacket->bytes >= 8 &&
1303
50.1k
        ! memcmp ( p_oggpacket->packet, "fisbone", 8 ) )
1304
5
    {
1305
5
        Ogg_ReadSkeletonBones( p_demux, p_oggpacket );
1306
5
        return;
1307
5
    }
1308
239k
    else if( p_oggpacket->bytes >= 6 &&
1309
50.1k
        ! memcmp ( p_oggpacket->packet, "index", 6 ) )
1310
0
    {
1311
0
        Ogg_ReadSkeletonIndex( p_demux, p_oggpacket );
1312
0
        return;
1313
0
    }
1314
239k
    else if ( p_stream == p_sys->p_skelstream ) {
1315
        // skeleton streams do not have any data packets
1316
0
        return;
1317
0
    }
1318
239k
    else if( p_stream->fmt.i_codec == VLC_CODEC_VP8 &&
1319
1
             p_oggpacket->bytes >= 7 &&
1320
1
             !memcmp( p_oggpacket->packet, "OVP80\x02\x20", 7 ) )
1321
0
    {
1322
0
        Ogg_ReadVP8Header( p_demux, p_stream, p_oggpacket );
1323
0
        return;
1324
0
    }
1325
1326
239k
    if( p_stream->fmt.i_codec == VLC_CODEC_SUBT && p_oggpacket->bytes > 0 &&
1327
20.3k
        p_oggpacket->packet[0] & PACKET_TYPE_BITS ) return;
1328
1329
    /* Check the ES is selected */
1330
238k
    if ( !p_stream->p_es )
1331
54.0k
        b_selected = true;
1332
184k
    else
1333
184k
        es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
1334
184k
                        p_stream->p_es, &b_selected );
1335
1336
238k
    if( p_stream->b_force_backup )
1337
2.85k
    {
1338
2.85k
        bool b_xiph;
1339
2.85k
        p_stream->i_packets_backup++;
1340
2.85k
        switch( p_stream->fmt.i_codec )
1341
2.85k
        {
1342
1.94k
        case VLC_CODEC_VORBIS:
1343
1.94k
#ifdef HAVE_LIBVORBIS
1344
1.94k
            Ogg_DecodeVorbisHeader( p_stream, p_oggpacket, p_stream->i_packets_backup );
1345
1.94k
#endif
1346
            /* fallthrough */
1347
2.68k
        case VLC_CODEC_THEORA:
1348
2.68k
            if( p_stream->i_packets_backup == 3 )
1349
876
                p_stream->b_force_backup = false;
1350
2.68k
            b_xiph = true;
1351
2.68k
            break;
1352
1353
0
        case VLC_CODEC_DAALA:
1354
0
            if( p_stream->i_packets_backup == 3 )
1355
0
                p_stream->b_force_backup = false;
1356
0
            b_xiph = true;
1357
0
            break;
1358
1359
14
        case VLC_CODEC_SPEEX:
1360
14
            if( p_stream->i_packets_backup == 2 + p_stream->i_extra_headers_packets )
1361
7
                p_stream->b_force_backup = false;
1362
14
            b_xiph = true;
1363
14
            break;
1364
1365
75
        case VLC_CODEC_OPUS:
1366
75
            if( p_stream->i_packets_backup == 2 )
1367
37
                p_stream->b_force_backup = false;
1368
75
            b_xiph = true;
1369
75
            break;
1370
1371
80
        case VLC_CODEC_FLAC:
1372
80
            if( p_stream->i_packets_backup == 1 + p_stream->i_extra_headers_packets )
1373
37
            {
1374
37
                p_stream->b_force_backup = false;
1375
37
            }
1376
80
            if( p_stream->special.flac.b_old )
1377
0
            {
1378
0
                Ogg_ReadFlacStreamInfo( p_demux, p_stream, p_oggpacket );
1379
0
            }
1380
80
            else if( p_stream->i_packets_backup == 1 )
1381
37
            {
1382
37
                if( p_oggpacket->bytes >= 9 ) /* Point to Flac for extradata */
1383
35
                {
1384
35
                    p_oggpacket->packet += 9;
1385
35
                    p_oggpacket->bytes -= 9;
1386
35
                }
1387
37
            }
1388
80
            b_xiph = false;
1389
80
            break;
1390
1391
0
        case VLC_CODEC_KATE:
1392
0
            if( p_stream->i_packets_backup == p_stream->special.kate.i_num_headers )
1393
0
                p_stream->b_force_backup = false;
1394
0
            b_xiph = true;
1395
0
            break;
1396
1397
0
        default:
1398
0
            p_stream->b_force_backup = false;
1399
0
            b_xiph = false;
1400
0
            break;
1401
2.85k
        }
1402
1403
        /* Backup the ogg packet (likely an header packet) */
1404
2.85k
        if( !b_xiph && p_oggpacket->bytes > 0 &&
1405
76
            (size_t)p_oggpacket->bytes < SIZE_MAX - p_stream->i_headers )
1406
76
        {
1407
76
            uint8_t *r_headers = realloc( p_stream->p_headers,
1408
76
                                          p_stream->i_headers + p_oggpacket->bytes );
1409
76
            if( likely( r_headers != NULL ) )
1410
76
            {
1411
76
                p_stream->p_headers = r_headers;
1412
76
                memcpy( r_headers + p_stream->i_headers, p_oggpacket->packet, p_oggpacket->bytes );
1413
76
                p_stream->i_headers += p_oggpacket->bytes;
1414
76
            }
1415
0
            else
1416
0
            {
1417
0
                free( p_stream->p_headers );
1418
0
                p_stream->p_headers = NULL;
1419
0
                p_stream->i_headers = 0;
1420
0
            }
1421
76
        }
1422
2.78k
        else if( b_xiph &&
1423
2.77k
                 xiph_AppendHeaders( &p_stream->i_headers, &p_stream->p_headers,
1424
2.77k
                                     p_oggpacket->bytes, p_oggpacket->packet ) )
1425
0
        {
1426
0
            free(p_stream->p_headers);
1427
0
            p_stream->i_headers = 0;
1428
0
            p_stream->p_headers = NULL;
1429
0
        }
1430
2.85k
        if( p_stream->i_headers > 0 )
1431
2.85k
        {
1432
2.85k
            if( !p_stream->b_force_backup )
1433
955
            {
1434
                /* Last header received, commit changes */
1435
955
                free( p_stream->fmt.p_extra );
1436
1437
955
                p_stream->fmt.p_extra = malloc( p_stream->i_headers );
1438
955
                if( p_stream->fmt.p_extra )
1439
955
                {
1440
955
                    memcpy( p_stream->fmt.p_extra, p_stream->p_headers,
1441
955
                            p_stream->i_headers );
1442
955
                    p_stream->fmt.i_extra = p_stream->i_headers;
1443
955
                }
1444
0
                else
1445
0
                    p_stream->fmt.i_extra = 0;
1446
1447
955
                if( p_stream->i_headers > 0 )
1448
955
                    Ogg_ExtractMeta( p_demux, & p_stream->fmt,
1449
955
                                     p_stream->p_headers, p_stream->i_headers );
1450
1451
                /* we're not at BOS anymore for this logical stream */
1452
955
                p_stream->b_initializing = false;
1453
955
            }
1454
2.85k
        }
1455
1456
2.85k
        b_selected = false; /* Discard the header packet */
1457
2.85k
    }
1458
235k
    else
1459
235k
    {
1460
235k
        p_stream->b_initializing = false;
1461
235k
    }
1462
1463
238k
    vlc_tick_t i_dts = Ogg_GranuleToTime( p_stream, p_oggpacket->granulepos, true, false );
1464
238k
    vlc_tick_t i_enddts = Ogg_GranuleToTime( p_stream, p_oggpacket->granulepos, false, false );
1465
238k
    vlc_tick_t i_expected_dts = p_stream->b_interpolation_failed ? VLC_TICK_INVALID :
1466
238k
                                date_Get( &p_stream->dts ); /* Interpolated or previous end time */
1467
238k
    if( i_dts == VLC_TICK_INVALID )
1468
235k
        i_dts = i_expected_dts;
1469
3.07k
    else
1470
3.07k
        date_Set( &p_stream->dts, i_dts );
1471
1472
    /* Write end granule as next start, or do interpolation */
1473
238k
    bool b_header = Ogg_IsHeaderPacket( p_stream, p_oggpacket );
1474
238k
    if( !b_header )
1475
233k
        Ogg_SetNextFrame( p_demux, p_stream, p_oggpacket );
1476
1477
238k
    if( !b_selected )
1478
2.85k
    {
1479
        /* This stream isn't currently selected so we don't need to decode it,
1480
         * but we did need to store its pcr as it might be selected later on */
1481
2.85k
        if( !b_header && !p_stream->b_initializing )
1482
511
        {
1483
511
            vlc_tick_t i_pcr = date_Get( &p_stream->dts );
1484
511
            if( i_pcr != VLC_TICK_INVALID )
1485
262
                p_stream->i_pcr = p_sys->i_nzpcr_offset + i_pcr;
1486
511
        }
1487
2.85k
        return;
1488
2.85k
    }
1489
1490
235k
    if( !( p_block = block_Alloc( p_oggpacket->bytes ) ) )
1491
0
        return;
1492
1493
    /* Set effective timestamp */
1494
235k
    if( i_dts != VLC_TICK_INVALID )
1495
82.7k
        p_block->i_dts = p_sys->i_nzpcr_offset + i_dts;
1496
1497
    /* Vorbis and Opus can trim the end of a stream using granule positions. */
1498
235k
    if( p_oggpacket->e_o_s )
1499
2.23k
    {
1500
2.23k
        vlc_tick_t i_endtime = Ogg_GranuleToTime( p_stream, p_oggpacket->granulepos, false, false );
1501
2.23k
        if( i_endtime != VLC_TICK_INVALID && i_expected_dts != VLC_TICK_INVALID )
1502
451
        {
1503
451
                p_block->i_length = i_endtime - i_expected_dts;
1504
451
                p_block->i_flags |= BLOCK_FLAG_END_OF_SEQUENCE;
1505
451
        }
1506
2.23k
    }
1507
1508
235k
    if( p_stream->fmt.i_codec == VLC_CODEC_OPUS ) /* also required for trimming */
1509
4.45k
        p_block->i_nb_samples = Ogg_OpusPacketDuration( p_oggpacket );
1510
1511
235k
    DemuxDebug( msg_Dbg(p_demux, "%4.4s block set from granule %"PRId64" to pts/pcr %"PRId64" skip %d",
1512
235k
                        (char *) &p_stream->fmt.i_codec, p_oggpacket->granulepos,
1513
235k
                        p_block->i_dts, p_stream->i_skip_frames); )
1514
1515
    /* may need to preroll after a seek or in case of preskip */
1516
1517
    /* Conditional block fixes */
1518
235k
    if ( p_stream->fmt.i_cat == VIDEO_ES )
1519
6.55k
    {
1520
6.55k
        if( Ogg_IsKeyFrame( p_stream, p_oggpacket ) )
1521
5.20k
            p_block->i_flags |= BLOCK_FLAG_TYPE_I;
1522
1523
6.55k
        if( p_stream->fmt.i_codec == VLC_CODEC_DIRAC )
1524
9
        {
1525
9
            if( p_oggpacket->granulepos > 0 )
1526
8
                p_block->i_pts = Ogg_GranuleToTime( p_stream, p_oggpacket->granulepos, true, true );
1527
9
        }
1528
6.54k
        else if( p_stream->fmt.i_codec == VLC_CODEC_THEORA )
1529
6.54k
        {
1530
6.54k
            p_block->i_pts = p_block->i_dts;
1531
6.54k
        }
1532
6.55k
    }
1533
229k
    else if( p_stream->fmt.i_cat == AUDIO_ES )
1534
207k
    {
1535
207k
        if( p_stream->b_interpolation_failed && p_oggpacket->granulepos < 0 )
1536
16.7k
            p_block->i_pts = VLC_TICK_INVALID;
1537
190k
        else
1538
190k
            p_block->i_pts = p_block->i_dts;
1539
207k
    }
1540
21.9k
    else if( p_stream->fmt.i_cat == SPU_ES )
1541
21.9k
    {
1542
21.9k
        p_block->i_length = 0;
1543
21.9k
        p_block->i_pts = p_block->i_dts;
1544
21.9k
    }
1545
1546
235k
    p_stream->b_interpolation_failed = false;
1547
1548
235k
    if( p_stream->b_oggds )
1549
21.9k
    {
1550
21.9k
        if( p_oggpacket->bytes <= 0 )
1551
2.20k
        {
1552
2.20k
            msg_Dbg( p_demux, "discarding 0 sized packet" );
1553
2.20k
            block_Release( p_block );
1554
2.20k
            return;
1555
2.20k
        }
1556
        /* We remove the header from the packet */
1557
19.7k
        i_header_len = (*p_oggpacket->packet & PACKET_LEN_BITS01) >> 6;
1558
19.7k
        i_header_len |= (*p_oggpacket->packet & PACKET_LEN_BITS2) << 1;
1559
1560
19.7k
        if( i_header_len >= p_oggpacket->bytes )
1561
0
        {
1562
0
            msg_Dbg( p_demux, "discarding invalid packet" );
1563
0
            block_Release( p_block );
1564
0
            return;
1565
0
        }
1566
1567
19.7k
        if( p_stream->fmt.i_codec == VLC_CODEC_SUBT)
1568
19.7k
        {
1569
            /* But with subtitles we need to retrieve the duration first */
1570
19.7k
            int i, lenbytes = 0;
1571
1572
19.7k
            if( i_header_len > 0 && p_oggpacket->bytes >= i_header_len + 1 )
1573
5
            {
1574
15
                for( i = 0, lenbytes = 0; i < i_header_len; i++ )
1575
10
                {
1576
10
                    lenbytes = lenbytes << 8;
1577
10
                    lenbytes += *(p_oggpacket->packet + i_header_len - i);
1578
10
                }
1579
5
            }
1580
19.7k
            if( p_oggpacket->bytes - 1 - i_header_len > 2 ||
1581
19.6k
                ( p_oggpacket->packet[i_header_len + 1] != ' ' &&
1582
19.6k
                  p_oggpacket->packet[i_header_len + 1] != 0 &&
1583
167
                  p_oggpacket->packet[i_header_len + 1] != '\n' &&
1584
34
                  p_oggpacket->packet[i_header_len + 1] != '\r' ) )
1585
72
            {
1586
72
                p_block->i_length = (vlc_tick_t)lenbytes * 1000;
1587
72
            }
1588
19.7k
        }
1589
1590
19.7k
        i_header_len++;
1591
19.7k
        if( p_block->i_buffer >= (unsigned int)i_header_len )
1592
19.7k
            p_block->i_buffer -= i_header_len;
1593
0
        else
1594
0
            p_block->i_buffer = 0;
1595
19.7k
    }
1596
1597
233k
    if( b_header )
1598
3.54k
        p_block->i_flags |= BLOCK_FLAG_HEADER;
1599
1600
233k
    memcpy( p_block->p_buffer, p_oggpacket->packet + i_header_len,
1601
233k
            p_oggpacket->bytes - i_header_len );
1602
1603
233k
    Ogg_QueueBlocks( p_demux, p_stream, p_block, i_enddts, b_eos );
1604
233k
}
1605
1606
static unsigned Ogg_OpusPacketDuration( ogg_packet *p_oggpacket )
1607
5.12k
{
1608
5.12k
    return opus_frame_duration(p_oggpacket->packet, p_oggpacket->bytes);
1609
5.12k
}
1610
1611
/****************************************************************************
1612
 * Ogg_FindLogicalStreams: Find the logical streams embedded in the physical
1613
 *                         stream and fill p_ogg.
1614
 *****************************************************************************
1615
 * The initial page of a logical stream is marked as a 'bos' page.
1616
 * Furthermore, the Ogg specification mandates that grouped bitstreams begin
1617
 * together and all of the initial pages must appear before any data pages.
1618
 *
1619
 * On success this function returns VLC_SUCCESS.
1620
 ****************************************************************************/
1621
static logical_stream_t *Ogg_FindLogicalStream( demux_t *p_demux, ogg_page *current_page )
1622
2.33k
{
1623
2.33k
    logical_stream_t *p_stream = malloc( sizeof(logical_stream_t) );
1624
2.33k
    if( unlikely( !p_stream ) )
1625
0
        return NULL;
1626
1627
2.33k
    Ogg_LogicalStreamInit( p_stream );
1628
1629
    /* Setup the logical stream */
1630
2.33k
    p_stream->i_serial_no = ogg_page_serialno( current_page );
1631
2.33k
    ogg_stream_init( &p_stream->os, p_stream->i_serial_no );
1632
1633
2.33k
    if( ogg_page_granulepos( current_page ) == 0 && !p_stream->b_oggds )
1634
1.86k
        p_stream->page_type = OGGPAGE_HEADER;
1635
464
    else
1636
464
        p_stream->page_type = OGGPAGE_OTHER;
1637
1638
    /* Extract the initial header from the first page and verify
1639
             * the codec type of this Ogg bitstream */
1640
2.33k
    if( ogg_stream_pagein( &p_stream->os, current_page ) < 0 )
1641
0
    {
1642
        /* error. stream version mismatch perhaps */
1643
0
        msg_Err( p_demux, "error reading first page of "
1644
0
                          "Ogg bitstream data" );
1645
0
        goto failed;
1646
0
    }
1647
1648
2.33k
    ogg_packet oggpacket;
1649
2.33k
    if ( ogg_stream_packetpeek( &p_stream->os, &oggpacket ) != 1 )
1650
0
    {
1651
0
        msg_Err( p_demux, "error in ogg_stream_packetpeek" );
1652
0
        goto failed;
1653
0
    }
1654
1655
2.33k
    if ( Ogg_ConfigureStream( p_demux, oggpacket, p_stream ) != VLC_SUCCESS )
1656
692
        goto failed;
1657
1658
    /* we'll need to get all headers */
1659
1.63k
    p_stream->b_initializing &= p_stream->b_force_backup;
1660
1661
1.63k
    return p_stream;
1662
1663
692
failed:
1664
692
    Ogg_LogicalStreamDelete( p_demux, p_stream );
1665
692
    return NULL;
1666
2.33k
}
1667
1668
static int Ogg_FindLogicalStreams( demux_t *p_demux )
1669
861
{
1670
861
    demux_sys_t *p_ogg = p_demux->p_sys;
1671
1672
861
    p_ogg->i_total_bytes = stream_Size ( p_demux->s );
1673
861
    msg_Dbg( p_demux, "File length is %"PRId64" bytes", p_ogg->i_total_bytes );
1674
1675
3.19k
    while( Ogg_ReadPage( p_demux, &p_ogg->current_page ) == VLC_SUCCESS )
1676
3.16k
    {
1677
        /* All is wonderful in our fine fine little world.
1678
         * We found the beginning of our first logical stream. */
1679
3.16k
        if( !ogg_page_bos( &p_ogg->current_page ) )
1680
832
        {
1681
            /* This is the first data page, which means we are now finished
1682
             * with the initial pages. We just need to store it in the relevant
1683
             * bitstream. */
1684
1.68k
            for( int i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ )
1685
1.55k
            {
1686
1.55k
                if( ogg_stream_pagein( &p_ogg->pp_stream[i_stream]->os,
1687
1.55k
                                       &p_ogg->current_page ) == 0 )
1688
694
                {
1689
694
                    p_ogg->b_page_waiting = true;
1690
694
                    break;
1691
694
                }
1692
1.55k
            }
1693
832
            return p_ogg->i_streams ? VLC_SUCCESS : VLC_EGENERIC;
1694
832
        }
1695
1696
2.33k
        if( unlikely(p_ogg->i_declared_streams == INT_MAX) )
1697
0
            return VLC_EGENERIC;
1698
1699
         /* New BOS, so new stream */
1700
2.33k
        p_ogg->i_declared_streams++;
1701
1702
        /* Try to configure the new stream */
1703
2.33k
        logical_stream_t *p_stream = Ogg_FindLogicalStream( p_demux, &p_ogg->current_page );
1704
2.33k
        if( unlikely( !p_stream ) )
1705
692
            continue;
1706
1707
1.63k
        TAB_APPEND( p_ogg->i_streams, p_ogg->pp_stream, p_stream );
1708
        /* we'll need to get all headers */
1709
1.63k
        if ( p_stream )
1710
1.63k
            p_stream->b_initializing &= p_stream->b_force_backup;
1711
1.63k
    }
1712
1713
29
    return VLC_EGENERIC;
1714
861
}
1715
1716
static int Ogg_ConfigureStream( demux_t *p_demux, ogg_packet oggpacket, logical_stream_t *p_stream )
1717
2.33k
{
1718
2.33k
    demux_sys_t *p_ogg = p_demux->p_sys;
1719
1720
2.33k
    { // note: old indentation kept on purpose for rebases & blaming
1721
2.33k
        {
1722
2.33k
            {
1723
                /* Check for Vorbis header */
1724
2.33k
                if( oggpacket.bytes >= 7 &&
1725
1.98k
                    ! memcmp( oggpacket.packet, "\x01vorbis", 7 ) )
1726
695
                {
1727
695
                    es_format_Change( &p_stream->fmt, AUDIO_ES, VLC_CODEC_VORBIS);
1728
695
                    if ( Ogg_ReadVorbisHeader( p_stream, &oggpacket ) )
1729
695
                        msg_Dbg( p_demux, "found vorbis header" );
1730
0
                    else
1731
0
                    {
1732
0
                        msg_Dbg( p_demux, "found invalid vorbis header" );
1733
0
                        return VLC_EGENERIC;
1734
0
                    }
1735
695
                }
1736
                /* Check for Speex header */
1737
1.63k
                else if( oggpacket.bytes >= 5 &&
1738
1.28k
                    ! memcmp( oggpacket.packet, "Speex", 5 ) )
1739
62
                {
1740
62
                    es_format_Change( &p_stream->fmt, AUDIO_ES, VLC_CODEC_SPEEX );
1741
62
                    if ( Ogg_ReadSpeexHeader( p_stream, &oggpacket ) )
1742
62
                        msg_Dbg( p_demux, "found speex header, channels: %i, "
1743
55
                                "rate: %"PRIu32"/%"PRIu32",  bitrate: %i, frames: %i group %i",
1744
55
                                p_stream->fmt.audio.i_channels,
1745
55
                                p_stream->dts.i_divider_num, p_stream->dts.i_divider_den,
1746
55
                                p_stream->fmt.i_bitrate,
1747
55
                                p_stream->special.speex.i_framesize,
1748
55
                                p_stream->special.speex.i_framesperpacket );
1749
55
                    else
1750
55
                    {
1751
55
                        msg_Dbg( p_demux, "found invalid Speex header" );
1752
55
                        return VLC_EGENERIC;
1753
55
                    }
1754
62
                }
1755
                /* Check for Opus header */
1756
1.57k
                else if( oggpacket.bytes >= 8 &&
1757
1.22k
                    ! memcmp( oggpacket.packet, "OpusHead", 8 ) )
1758
70
                {
1759
70
                    es_format_Change( &p_stream->fmt, AUDIO_ES, VLC_CODEC_OPUS );
1760
70
                    Ogg_ReadOpusHeader( p_stream, &oggpacket );
1761
70
                    msg_Dbg( p_demux, "found opus header, channels: %i, "
1762
70
                             "pre-skip: %i",
1763
70
                             p_stream->fmt.audio.i_channels,
1764
70
                             (int)p_stream->i_pre_skip);
1765
70
                    p_stream->i_skip_frames = p_stream->i_pre_skip;
1766
70
                }
1767
                /* Check for OLD Flac header */
1768
1.50k
                else if( oggpacket.bytes >= 4 &&
1769
1.15k
                    ! memcmp( oggpacket.packet, "fLaC", 4 ) )
1770
0
                {
1771
0
                    msg_Dbg( p_demux, "found FLAC header" );
1772
1773
                    /* Grrrr!!!! Did they really have to put all the
1774
                     * important info in the second header packet!!!
1775
                     * (STREAMINFO metadata is in the following packet) */
1776
0
                    p_stream->b_force_backup = true;
1777
0
                    p_stream->i_extra_headers_packets = 1;
1778
0
                    p_stream->special.flac.b_old = true;
1779
0
                    date_Init( &p_stream->dts, 48000, 1 ); /* better be safe since that's delayed */
1780
0
                    es_format_Change( &p_stream->fmt, AUDIO_ES, VLC_CODEC_FLAC );
1781
0
                }
1782
                /* Check for Flac header (>= version 1.0.0) */
1783
1.50k
                else if( oggpacket.bytes >= 13 && oggpacket.packet[0] ==0x7F &&
1784
37
                    ! memcmp( &oggpacket.packet[1], "FLAC", 4 ) &&
1785
37
                    ! memcmp( &oggpacket.packet[9], "fLaC", 4 ) )
1786
37
                {
1787
37
                    int i_packets = ((int)oggpacket.packet[7]) << 8 |
1788
37
                        oggpacket.packet[8];
1789
37
                    msg_Dbg( p_demux, "found FLAC header version %i.%i "
1790
37
                             "(%i header packets)",
1791
37
                             oggpacket.packet[5], oggpacket.packet[6],
1792
37
                             i_packets );
1793
                    /* STREAMINFO is in current packet, and then
1794
                       followed by 0 or more metadata, blockheader prefixed, and first being a vorbis comment */
1795
37
                    p_stream->b_force_backup = true;
1796
37
                    p_stream->i_extra_headers_packets = i_packets;
1797
37
                    p_stream->special.flac.b_old = false;
1798
1799
37
                    es_format_Change( &p_stream->fmt, AUDIO_ES, VLC_CODEC_FLAC );
1800
37
                    oggpacket.packet += 13; oggpacket.bytes -= 13; /* Point to the streaminfo */
1801
37
                    p_stream->fmt.b_packetized = false;
1802
37
                    if ( !Ogg_ReadFlacStreamInfo( p_demux, p_stream, &oggpacket ) )
1803
0
                    {
1804
0
                        msg_Dbg( p_demux, "found invalid Flac header" );
1805
0
                        return VLC_EGENERIC;
1806
0
                    }
1807
37
                }
1808
                /* Check for Theora header */
1809
1.46k
                else if( oggpacket.bytes >= 7 &&
1810
1.11k
                         ! memcmp( oggpacket.packet, "\x80theora", 7 ) )
1811
565
                {
1812
565
                    es_format_Change( &p_stream->fmt, VIDEO_ES, VLC_CODEC_THEORA );
1813
565
                    if ( Ogg_ReadTheoraHeader( p_stream, &oggpacket ) )
1814
565
                        msg_Dbg( p_demux,
1815
0
                                 "found theora header, bitrate: %i, rate: %"PRIu32"/%"PRIu32,
1816
0
                                 p_stream->fmt.i_bitrate,
1817
0
                                 p_stream->dts.i_divider_num, p_stream->dts.i_divider_den );
1818
0
                    else
1819
0
                    {
1820
0
                        msg_Dbg( p_demux, "found invalid Theora header" );
1821
0
                        return VLC_EGENERIC;
1822
0
                    }
1823
565
                }
1824
                /* Check for Daala header */
1825
902
                else if( oggpacket.bytes >= 6 &&
1826
554
                         ! memcmp( oggpacket.packet, "\x80""daala", 6 ) )
1827
0
                {
1828
0
                    es_format_Change( &p_stream->fmt, VIDEO_ES, VLC_CODEC_DAALA );
1829
0
                    if ( Ogg_ReadDaalaHeader( p_stream, &oggpacket ) )
1830
0
                        msg_Dbg( p_demux,
1831
0
                                 "found daala header, bitrate: %i, rate: %"PRIu32"/%"PRIu32,
1832
0
                                 p_stream->fmt.i_bitrate,
1833
0
                                 p_stream->dts.i_divider_num, p_stream->dts.i_divider_den );
1834
0
                    else
1835
0
                    {
1836
0
                        msg_Dbg( p_demux, "found invalid Daala header" );
1837
0
                        return VLC_EGENERIC;
1838
0
                    }
1839
0
                }
1840
                /* Check for Dirac header */
1841
902
                else if( ( oggpacket.bytes >= 5 &&
1842
554
                           ! memcmp( oggpacket.packet, "BBCD\x00", 5 ) ) ||
1843
704
                         ( oggpacket.bytes >= 9 &&
1844
356
                           ! memcmp( oggpacket.packet, "KW-DIRAC\x00", 9 ) ) )
1845
198
                {
1846
198
                    es_format_Change( &p_stream->fmt, VIDEO_ES, VLC_CODEC_DIRAC );
1847
198
                    if( Ogg_ReadDiracHeader( p_stream, &oggpacket ) )
1848
198
                        msg_Dbg( p_demux, "found dirac header" );
1849
155
                    else
1850
155
                    {
1851
155
                        msg_Warn( p_demux, "found dirac header isn't decodable" );
1852
155
                        return VLC_EGENERIC;
1853
155
                    }
1854
198
                }
1855
                /* Check for VP8 header */
1856
704
                else if( oggpacket.bytes >= 26 &&
1857
254
                         ! memcmp( oggpacket.packet, "OVP80", 5 ) )
1858
55
                {
1859
55
                    es_format_Change( &p_stream->fmt, VIDEO_ES, VLC_CODEC_VP8 );
1860
55
                    if ( Ogg_ReadVP8Header( p_demux, p_stream, &oggpacket ) )
1861
55
                        msg_Dbg( p_demux, "found VP8 header "
1862
32
                             "fps: %"PRIu32"/%"PRIu32", width:%i; height:%i",
1863
32
                             p_stream->dts.i_divider_num, p_stream->dts.i_divider_den,
1864
32
                             p_stream->fmt.video.i_width,
1865
32
                             p_stream->fmt.video.i_height );
1866
32
                    else
1867
32
                    {
1868
32
                        msg_Dbg( p_demux, "invalid VP8 header found");
1869
32
                        return VLC_EGENERIC;
1870
32
                    }
1871
55
                }
1872
                /* Check for Annodex header */
1873
649
                else if( oggpacket.bytes >= 7 &&
1874
301
                         ! memcmp( oggpacket.packet, "Annodex", 7 ) )
1875
0
                {
1876
0
                    Ogg_ReadAnnodexHeader( p_demux, p_stream, &oggpacket );
1877
                    /* kill annodex track */
1878
0
                    return VLC_EGENERIC;
1879
0
                }
1880
                /* Check for Annodex header */
1881
649
                else if( oggpacket.bytes >= 7 &&
1882
301
                         ! memcmp( oggpacket.packet, "AnxData", 7 ) )
1883
0
                {
1884
0
                    Ogg_ReadAnnodexHeader( p_demux, p_stream, &oggpacket );
1885
0
                }
1886
                /* Check for Kate header */
1887
649
                else if( oggpacket.bytes >= 8 &&
1888
301
                    ! memcmp( &oggpacket.packet[1], "kate\0\0\0", 7 ) )
1889
0
                {
1890
0
                    es_format_Change( &p_stream->fmt, SPU_ES, VLC_CODEC_KATE );
1891
0
                    if ( Ogg_ReadKateHeader( p_stream, &oggpacket ) )
1892
0
                        msg_Dbg( p_demux, "found kate header" );
1893
0
                    else
1894
0
                    {
1895
0
                        msg_Dbg( p_demux, "invalid kate header found");
1896
0
                        return VLC_EGENERIC;
1897
0
                    }
1898
0
                }
1899
                /* Check for OggDS */
1900
649
                else if( oggpacket.bytes >= 142 &&
1901
197
                         !memcmp( &oggpacket.packet[1],
1902
197
                                   "Direct Show Samples embedded in Ogg", 35 ))
1903
0
                {
1904
                    /* Old header type */
1905
0
                    p_stream->b_oggds = true;
1906
0
                    p_stream->b_contiguous = false;
1907
                    /* Check for video header (old format) */
1908
0
                    if( GetDWLE((oggpacket.packet+96)) == 0x05589f80 &&
1909
0
                        oggpacket.bytes >= 184 )
1910
0
                    {
1911
0
                        es_format_Change( &p_stream->fmt, VIDEO_ES,
1912
0
                                          VLC_FOURCC( oggpacket.packet[68],
1913
0
                                                      oggpacket.packet[69],
1914
0
                                                      oggpacket.packet[70],
1915
0
                                                      oggpacket.packet[71] ) );
1916
0
                        msg_Dbg( p_demux, "found video header of type: %.4s",
1917
0
                                 (char *)&p_stream->fmt.i_codec );
1918
1919
0
                        unsigned num = OGGDS_RESOLUTION;
1920
0
                        unsigned den = GetQWLE(oggpacket.packet+164);
1921
0
                        vlc_ureduce( &num, &den, num, den > 0 ? den : 1, OGGDS_RESOLUTION );
1922
0
                        p_stream->fmt.video.i_frame_rate = num;
1923
0
                        p_stream->fmt.video.i_frame_rate_base = den;
1924
0
                        date_Init( &p_stream->dts, num, den );
1925
0
                        unsigned bpp = GetWLE((oggpacket.packet+182));
1926
0
                        if (p_stream->fmt.i_profile == -1 && p_stream->fmt.i_level == -1)
1927
                            // HACK: keep the bits per sample, will be lost if i_level is used.
1928
0
                            p_stream->fmt.i_level = bpp;
1929
0
                        p_stream->fmt.video.i_width =
1930
0
                            GetDWLE((oggpacket.packet+176));
1931
0
                        p_stream->fmt.video.i_height =
1932
0
                            GetDWLE((oggpacket.packet+180));
1933
0
                        p_stream->fmt.video.i_visible_width =
1934
0
                            p_stream->fmt.video.i_width;
1935
0
                        p_stream->fmt.video.i_visible_height =
1936
0
                            p_stream->fmt.video.i_height;
1937
1938
0
                        msg_Dbg( p_demux,
1939
0
                                 "fps: %u/%u, width:%i; height:%i, bitcount:%i",
1940
0
                                 p_stream->fmt.video.i_frame_rate,
1941
0
                                 p_stream->fmt.video.i_frame_rate_base,
1942
0
                                 p_stream->fmt.video.i_width,
1943
0
                                 p_stream->fmt.video.i_height,
1944
0
                                 bpp);
1945
1946
0
                        if ( !p_stream->fmt.video.i_frame_rate ||
1947
0
                             !p_stream->fmt.video.i_frame_rate_base )
1948
0
                        {
1949
0
                            return VLC_EGENERIC;
1950
0
                        }
1951
0
                    }
1952
                    /* Check for audio header (old format) */
1953
0
                    else if( GetDWLE((oggpacket.packet+96)) == 0x05589F81 )
1954
0
                    {
1955
0
                        int i_extra_size;
1956
0
                        unsigned int i_format_tag;
1957
1958
0
                        es_format_Change( &p_stream->fmt, AUDIO_ES, 0 );
1959
1960
0
                        i_extra_size = GetWLE((oggpacket.packet+140));
1961
0
                        if( i_extra_size > 0 && i_extra_size < oggpacket.bytes - 142 )
1962
0
                        {
1963
0
                            p_stream->fmt.p_extra = malloc( i_extra_size );
1964
0
                            if( p_stream->fmt.p_extra )
1965
0
                            {
1966
0
                                memcpy( p_stream->fmt.p_extra,
1967
0
                                        oggpacket.packet + 142, i_extra_size );
1968
0
                                p_stream->fmt.i_extra = i_extra_size;
1969
0
                            }
1970
0
                        }
1971
1972
0
                        i_format_tag = GetWLE((oggpacket.packet+124));
1973
0
                        p_stream->fmt.audio.i_channels =
1974
0
                            GetWLE((oggpacket.packet+126));
1975
0
                        fill_channels_info(&p_stream->fmt.audio);
1976
0
                        p_stream->fmt.audio.i_rate =
1977
0
                            GetDWLE((oggpacket.packet+128));
1978
0
                        p_stream->fmt.i_bitrate =
1979
0
                            GetDWLE((oggpacket.packet+132)) * 8;
1980
0
                        p_stream->fmt.audio.i_blockalign =
1981
0
                            GetWLE((oggpacket.packet+136));
1982
0
                        p_stream->fmt.audio.i_bitspersample =
1983
0
                            GetWLE((oggpacket.packet+138));
1984
1985
0
                        date_Init( &p_stream->dts, p_stream->fmt.audio.i_rate, 1 );
1986
1987
0
                        wf_tag_to_fourcc( i_format_tag,
1988
0
                                          &p_stream->fmt.i_codec, 0 );
1989
1990
0
                        if( p_stream->fmt.i_codec == VLC_CODEC_UNKNOWN )
1991
0
                        {
1992
0
                            p_stream->fmt.i_codec = VLC_FOURCC( 'm', 's',
1993
0
                                ( i_format_tag >> 8 ) & 0xff,
1994
0
                                i_format_tag & 0xff );
1995
0
                        }
1996
1997
0
                        msg_Dbg( p_demux, "found audio header of type: %.4s",
1998
0
                                 (char *)&p_stream->fmt.i_codec );
1999
0
                        msg_Dbg( p_demux, "audio:0x%4.4x channels:%d %dHz "
2000
0
                                 "%dbits/sample %dkb/s",
2001
0
                                 i_format_tag,
2002
0
                                 p_stream->fmt.audio.i_channels,
2003
0
                                 p_stream->fmt.audio.i_rate,
2004
0
                                 p_stream->fmt.audio.i_bitspersample,
2005
0
                                 p_stream->fmt.i_bitrate / 1024 );
2006
2007
0
                        if ( p_stream->fmt.audio.i_rate == 0 )
2008
0
                        {
2009
0
                            msg_Dbg( p_demux, "invalid oggds audio header" );
2010
0
                            return VLC_EGENERIC;
2011
0
                        }
2012
0
                    }
2013
0
                    else
2014
0
                    {
2015
0
                        msg_Dbg( p_demux, "stream %d has an old header "
2016
0
                            "but is of an unknown type", p_ogg->i_streams );
2017
0
                        return VLC_EGENERIC;
2018
0
                    }
2019
0
                }
2020
                /* Check for OggDS */
2021
649
                else if( oggpacket.bytes >= 44+1 &&
2022
199
                         (*oggpacket.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER )
2023
199
                {
2024
199
                    stream_header_t tmp;
2025
199
                    stream_header_t *st = &tmp;
2026
2027
199
                    p_stream->b_oggds = true;
2028
199
                    p_stream->b_contiguous = false;
2029
2030
199
                    memcpy( st->streamtype, &oggpacket.packet[1+0], 8 );
2031
199
                    memcpy( st->subtype, &oggpacket.packet[1+8], 4 );
2032
199
                    st->size = GetDWLE( &oggpacket.packet[1+12] );
2033
199
                    st->time_unit = GetQWLE( &oggpacket.packet[1+16] );
2034
199
                    st->samples_per_unit = GetQWLE( &oggpacket.packet[1+24] );
2035
199
                    st->default_len = GetDWLE( &oggpacket.packet[1+32] );
2036
199
                    st->buffersize = GetDWLE( &oggpacket.packet[1+36] );
2037
199
                    st->bits_per_sample = GetWLE( &oggpacket.packet[1+40] ); // (padding 2)
2038
2039
                    /* Check for video header (new format) */
2040
199
                    if( !strncmp( st->streamtype, "video", 5 ) &&
2041
0
                        oggpacket.bytes >= 52+1 )
2042
0
                    {
2043
0
                        st->sh.video.width = GetDWLE( &oggpacket.packet[1+44] );
2044
0
                        st->sh.video.height = GetDWLE( &oggpacket.packet[1+48] );
2045
2046
0
                        es_format_Change( &p_stream->fmt, VIDEO_ES, 0 );
2047
2048
                        /* We need to get rid of the header packet */
2049
0
                        ogg_stream_packetout( &p_stream->os, &oggpacket );
2050
2051
0
                        p_stream->fmt.i_codec =
2052
0
                            VLC_FOURCC( st->subtype[0], st->subtype[1],
2053
0
                                        st->subtype[2], st->subtype[3] );
2054
0
                        msg_Dbg( p_demux, "found video header of type: %.4s",
2055
0
                                 (char *)&p_stream->fmt.i_codec );
2056
2057
                        /* FIXME: no clue where it's from */
2058
0
                        if( st->time_unit <= 0 )
2059
0
                            st->time_unit = 400000;
2060
0
                        unsigned num, den;
2061
0
                        vlc_ureduce( &num, &den,
2062
0
                                     st->samples_per_unit * OGGDS_RESOLUTION,
2063
0
                                     st->time_unit,
2064
0
                                     OGGDS_RESOLUTION );
2065
0
                        date_Init( &p_stream->dts, num, den );
2066
0
                        p_stream->fmt.video.i_frame_rate = num;
2067
0
                        p_stream->fmt.video.i_frame_rate_base = den;
2068
0
                        p_stream->fmt.video.i_width = st->sh.video.width;
2069
0
                        p_stream->fmt.video.i_height = st->sh.video.height;
2070
0
                        p_stream->fmt.video.i_visible_width =
2071
0
                            p_stream->fmt.video.i_width;
2072
0
                        p_stream->fmt.video.i_visible_height =
2073
0
                            p_stream->fmt.video.i_height;
2074
2075
0
                        msg_Dbg( p_demux,
2076
0
                                 "fps: %u/%u, width:%i; height:%i, bitcount:%i",
2077
0
                                 p_stream->fmt.video.i_frame_rate,
2078
0
                                 p_stream->fmt.video.i_frame_rate_base,
2079
0
                                 p_stream->fmt.video.i_width,
2080
0
                                 p_stream->fmt.video.i_height,
2081
0
                                 st->bits_per_sample );
2082
0
                    }
2083
                    /* Check for audio header (new format) */
2084
199
                    else if( !strncmp( st->streamtype, "audio", 5 ) &&
2085
0
                             oggpacket.bytes >= 56+1 )
2086
0
                    {
2087
0
                        char p_buffer[5];
2088
0
                        int i_extra_size;
2089
0
                        int i_format_tag;
2090
2091
0
                        st->sh.audio.channels = GetWLE( &oggpacket.packet[1+44] );
2092
0
                        st->sh.audio.blockalign = GetWLE( &oggpacket.packet[1+48] );
2093
0
                        st->sh.audio.avgbytespersec = GetDWLE( &oggpacket.packet[1+52] );
2094
2095
0
                        es_format_Change( &p_stream->fmt, AUDIO_ES, 0 );
2096
2097
                        /* We need to get rid of the header packet */
2098
0
                        ogg_stream_packetout( &p_stream->os, &oggpacket );
2099
2100
0
                        i_extra_size = st->size - 56;
2101
2102
0
                        if( i_extra_size > 0 &&
2103
0
                            i_extra_size < oggpacket.bytes - 1 - 56 )
2104
0
                        {
2105
0
                            p_stream->fmt.p_extra = malloc( i_extra_size );
2106
0
                            if( p_stream->fmt.p_extra )
2107
0
                            {
2108
0
                                memcpy( p_stream->fmt.p_extra, oggpacket.packet + 57, i_extra_size );
2109
0
                                p_stream->fmt.i_extra = i_extra_size;
2110
0
                            }
2111
0
                        }
2112
2113
0
                        memcpy( p_buffer, st->subtype, 4 );
2114
0
                        p_buffer[4] = '\0';
2115
0
                        i_format_tag = strtol(p_buffer,NULL,16);
2116
0
                        p_stream->fmt.audio.i_channels = st->sh.audio.channels;
2117
0
                        fill_channels_info(&p_stream->fmt.audio);
2118
2119
0
                        unsigned num,den;
2120
0
                        vlc_ureduce( &num, &den,
2121
0
                                     st->samples_per_unit * OGGDS_RESOLUTION,
2122
0
                                     st->time_unit > 0 ? st->time_unit : OGGDS_RESOLUTION,
2123
0
                                     OGGDS_RESOLUTION );
2124
0
                        date_Init( &p_stream->dts, num, den );
2125
0
                        p_stream->fmt.audio.i_rate = num / den;
2126
0
                        p_stream->fmt.i_bitrate = st->sh.audio.avgbytespersec * 8;
2127
0
                        p_stream->fmt.audio.i_blockalign = st->sh.audio.blockalign;
2128
0
                        p_stream->fmt.audio.i_bitspersample = st->bits_per_sample;
2129
2130
0
                        wf_tag_to_fourcc( i_format_tag,
2131
0
                                          &p_stream->fmt.i_codec, 0 );
2132
2133
0
                        if( p_stream->fmt.i_codec == VLC_CODEC_UNKNOWN )
2134
0
                        {
2135
0
                            p_stream->fmt.i_codec = VLC_FOURCC( 'm', 's',
2136
0
                                ( i_format_tag >> 8 ) & 0xff,
2137
0
                                i_format_tag & 0xff );
2138
0
                        }
2139
2140
0
                        msg_Dbg( p_demux, "found audio header of type: %.4s",
2141
0
                                 (char *)&p_stream->fmt.i_codec );
2142
0
                        msg_Dbg( p_demux, "audio:0x%4.4x channels:%d %dHz "
2143
0
                                 "%dbits/sample %dkb/s",
2144
0
                                 i_format_tag,
2145
0
                                 p_stream->fmt.audio.i_channels,
2146
0
                                 p_stream->fmt.audio.i_rate,
2147
0
                                 p_stream->fmt.audio.i_bitspersample,
2148
0
                                 p_stream->fmt.i_bitrate / 1024 );
2149
0
                        if ( p_stream->fmt.audio.i_rate == 0 )
2150
0
                        {
2151
0
                            msg_Dbg( p_demux, "invalid oggds audio header" );
2152
0
                            return VLC_EGENERIC;
2153
0
                        }
2154
0
                    }
2155
                    /* Check for text (subtitles) header */
2156
199
                    else if( !strncmp(st->streamtype, "text", 4) )
2157
199
                    {
2158
                        /* We need to get rid of the header packet */
2159
199
                        ogg_stream_packetout( &p_stream->os, &oggpacket );
2160
2161
199
                        msg_Dbg( p_demux, "found text subtitle header" );
2162
199
                        es_format_Change( &p_stream->fmt, SPU_ES, VLC_CODEC_SUBT );
2163
199
                        date_Init( &p_stream->dts, 1000, 1 ); /* granulepos is in millisec */
2164
199
                    }
2165
0
                    else
2166
0
                    {
2167
0
                        msg_Dbg( p_demux, "stream %d has a header marker "
2168
0
                            "but is of an unknown type", p_ogg->i_streams );
2169
0
                        return VLC_EGENERIC;
2170
0
                    }
2171
199
                }
2172
450
                else if( oggpacket.bytes >= 8 &&
2173
102
                             ! memcmp( oggpacket.packet, "fishead\0", 8 ) )
2174
2175
0
                {
2176
                    /* Skeleton */
2177
0
                    msg_Dbg( p_demux, "stream %d is a skeleton",
2178
0
                                p_ogg->i_streams );
2179
0
                    Ogg_ReadSkeletonHeader( p_demux, p_stream, &oggpacket );
2180
0
                }
2181
                /* Check for OggSpots header */
2182
450
                else if( oggpacket.bytes >= 8 &&
2183
102
                         ! memcmp( oggpacket.packet, "SPOTS\0\0", 8 ) )
2184
0
                {
2185
0
                    if ( Ogg_ReadOggSpotsHeader( p_stream, &oggpacket ) )
2186
0
                        msg_Dbg( p_demux,
2187
0
                                 "found OggSpots header, time resolution: %u/%u",
2188
0
                                 p_stream->fmt.video.i_frame_rate,
2189
0
                                 p_stream->fmt.video.i_frame_rate_base );
2190
0
                    else
2191
0
                    {
2192
0
                        msg_Err( p_demux, "found invalid OggSpots header" );
2193
0
                        return VLC_EGENERIC;
2194
0
                    }
2195
0
                }
2196
450
                else
2197
450
                {
2198
450
                    msg_Dbg( p_demux, "stream %d is of unknown type",
2199
450
                             p_ogg->i_streams );
2200
450
                    return VLC_EGENERIC;
2201
450
                }
2202
2.33k
            }
2203
2204
1.63k
            return VLC_SUCCESS;
2205
2.33k
        }
2206
2.33k
    }
2207
2208
0
    return VLC_EGENERIC;
2209
2.33k
}
2210
2211
/****************************************************************************
2212
 * Ogg_CreateES: Creates all Elementary streams once headers are parsed
2213
 ****************************************************************************/
2214
static void Ogg_CreateES( demux_t *p_demux, bool stable_id )
2215
677
{
2216
677
    demux_sys_t *p_ogg = p_demux->p_sys;
2217
677
    logical_stream_t *p_old_stream = p_ogg->p_old_stream;
2218
677
    int i_stream;
2219
2220
1.56k
    for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
2221
883
    {
2222
883
        logical_stream_t *p_stream = p_ogg->pp_stream[i_stream];
2223
2224
883
        if ( p_stream->p_es == NULL && !p_stream->b_finished )
2225
758
        {
2226
            /* Better be safe than sorry when possible with ogm */
2227
758
            if( p_stream->fmt.i_codec == VLC_CODEC_MPGA ||
2228
758
                p_stream->fmt.i_codec == VLC_CODEC_A52 )
2229
0
                p_stream->fmt.b_packetized = false;
2230
2231
            /* Try first to reuse an old ES */
2232
758
            if( p_old_stream &&
2233
458
                p_old_stream->fmt.i_cat == p_stream->fmt.i_cat &&
2234
216
                p_old_stream->fmt.i_codec == p_stream->fmt.i_codec &&
2235
200
                p_old_stream->p_es != NULL )
2236
200
            {
2237
200
                msg_Dbg( p_demux, "will reuse old stream to avoid glitch" );
2238
2239
200
                p_stream->p_es = p_old_stream->p_es;
2240
200
                p_stream->b_finished = false;
2241
200
                p_stream->b_initializing = false;
2242
200
                p_stream->i_pre_skip = 0;
2243
200
                es_format_Clean( &p_stream->fmt_old );
2244
200
                es_format_Copy( &p_stream->fmt_old, &p_old_stream->fmt );
2245
200
                bool b_resetdecoder = Ogg_LogicalStreamResetEsFormat( p_demux, p_stream );
2246
2247
200
                p_old_stream->p_es = NULL;
2248
200
                p_old_stream = NULL;
2249
200
                if ( b_resetdecoder )
2250
78
                {
2251
78
                    es_out_Control( p_demux->out, ES_OUT_SET_ES_FMT,
2252
78
                                    p_stream->p_es, &p_stream->fmt );
2253
78
                }
2254
200
            }
2255
558
            else
2256
558
            {
2257
558
                if( stable_id )
2258
0
                {
2259
                    /* IDs are stable when ES tracks are created from the Open
2260
                     * function. Don't specify ids when tracks are added
2261
                     * midstream */
2262
0
                    p_stream->fmt.i_id = i_stream;
2263
0
                }
2264
558
                p_stream->p_es = es_out_Add( p_demux->out, &p_stream->fmt );
2265
558
            }
2266
758
        }
2267
883
    }
2268
2269
677
    if( p_ogg->p_old_stream )
2270
453
    {
2271
453
        if( p_ogg->p_old_stream->p_es )
2272
453
            msg_Dbg( p_demux, "old stream not reused" );
2273
453
        Ogg_LogicalStreamDelete( p_demux, p_ogg->p_old_stream );
2274
453
        p_ogg->p_old_stream = NULL;
2275
453
    }
2276
677
    p_ogg->b_es_created = true;
2277
677
}
2278
2279
/****************************************************************************
2280
 * Ogg_BeginningOfStream: Look for Beginning of Stream ogg pages and add
2281
 *                        Elementary streams.
2282
 ****************************************************************************/
2283
static int Ogg_BeginningOfStream( demux_t *p_demux )
2284
861
{
2285
861
    demux_sys_t *p_ogg = p_demux->p_sys  ;
2286
861
    int i_stream;
2287
2288
    /* Find the logical streams embedded in the physical stream and
2289
     * initialize our p_ogg structure. */
2290
861
    if( Ogg_FindLogicalStreams( p_demux ) != VLC_SUCCESS )
2291
45
    {
2292
45
        msg_Warn( p_demux, "couldn't find any ogg logical stream" );
2293
45
        return VLC_EGENERIC;
2294
45
    }
2295
2296
816
    p_ogg->i_bitrate = 0;
2297
2298
2.37k
    for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
2299
1.56k
    {
2300
1.56k
        logical_stream_t *p_stream = p_ogg->pp_stream[i_stream];
2301
2302
1.56k
        p_stream->p_es = NULL;
2303
2304
        /* initialise kframe index */
2305
1.56k
        p_stream->idx=NULL;
2306
2307
1.56k
        if ( p_stream->fmt.i_bitrate == 0  &&
2308
863
             ( p_stream->fmt.i_cat == VIDEO_ES ||
2309
273
               p_stream->fmt.i_cat == AUDIO_ES ) )
2310
664
            p_ogg->b_partial_bitrate = true;
2311
899
        else
2312
899
            p_ogg->i_bitrate += p_stream->fmt.i_bitrate;
2313
2314
1.56k
        p_stream->i_pcr = VLC_TICK_INVALID;
2315
1.56k
    }
2316
2317
    /* get total frame count for video stream; we will need this for seeking */
2318
816
    p_ogg->i_total_frames = 0;
2319
2320
816
    return VLC_SUCCESS;
2321
861
}
2322
2323
/****************************************************************************
2324
 * Ogg_EndOfStream: clean up the ES when an End of Stream is detected.
2325
 ****************************************************************************/
2326
static void Ogg_EndOfStream( demux_t *p_demux )
2327
840
{
2328
840
    demux_sys_t *p_ogg = p_demux->p_sys  ;
2329
840
    int i_stream;
2330
2331
2.01k
    for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
2332
1.17k
        Ogg_LogicalStreamDelete( p_demux, p_ogg->pp_stream[i_stream] );
2333
840
    free( p_ogg->pp_stream );
2334
2335
    /* Reinit p_ogg */
2336
840
    p_ogg->i_bitrate = 0;
2337
840
    p_ogg->i_streams = 0;
2338
840
    p_ogg->i_declared_streams = 0;
2339
840
    p_ogg->pp_stream = NULL;
2340
840
    p_ogg->skeleton.major = 0;
2341
840
    p_ogg->skeleton.minor = 0;
2342
840
    p_ogg->b_preparsing_done = false;
2343
840
    p_ogg->b_es_created = false;
2344
2345
    /* */
2346
840
    if( p_ogg->p_meta )
2347
119
        vlc_meta_Delete( p_ogg->p_meta );
2348
840
    p_ogg->p_meta = NULL;
2349
2350
840
    for(int i=0; i<p_ogg->i_attachments; i++)
2351
0
        vlc_input_attachment_Release( p_ogg->attachments[i] );
2352
840
    TAB_CLEAN(p_ogg->i_attachments, p_ogg->attachments);
2353
2354
840
    for ( int i=0; i < p_ogg->i_seekpoints; i++ )
2355
0
    {
2356
0
        if ( p_ogg->pp_seekpoints[i] )
2357
0
            vlc_seekpoint_Delete( p_ogg->pp_seekpoints[i] );
2358
0
    }
2359
840
    TAB_CLEAN( p_ogg->i_seekpoints, p_ogg->pp_seekpoints );
2360
840
}
2361
2362
static void Ogg_CleanSpecificData( logical_stream_t *p_stream )
2363
2.33k
{
2364
2.33k
#ifdef HAVE_LIBVORBIS
2365
2.33k
    if ( p_stream->fmt.i_codec == VLC_CODEC_VORBIS )
2366
695
    {
2367
695
        if( p_stream->special.vorbis.p_info )
2368
662
            vorbis_info_clear( p_stream->special.vorbis.p_info );
2369
695
        FREENULL( p_stream->special.vorbis.p_info );
2370
695
        if( p_stream->special.vorbis.p_comment )
2371
662
            vorbis_comment_clear( p_stream->special.vorbis.p_comment );
2372
695
        FREENULL( p_stream->special.vorbis.p_comment );
2373
695
        p_stream->special.vorbis.i_headers_flags = 0;
2374
695
    }
2375
#else
2376
    VLC_UNUSED( p_stream );
2377
#endif
2378
2.33k
}
2379
2380
static void Ogg_LogicalStreamInit( logical_stream_t *p_stream )
2381
2.33k
{
2382
2.33k
    memset( p_stream, 0, sizeof(logical_stream_t) );
2383
2.33k
    es_format_Init( &p_stream->fmt, UNKNOWN_ES, 0 );
2384
2.33k
    es_format_Init( &p_stream->fmt_old, UNKNOWN_ES, 0 );
2385
2.33k
    p_stream->i_pcr = VLC_TICK_INVALID;
2386
2.33k
    p_stream->i_first_frame_index = 1;
2387
2.33k
    p_stream->page_type = OGGPAGE_OTHER;
2388
2.33k
    date_Set( &p_stream->dts, VLC_TICK_INVALID );
2389
2.33k
    p_stream->b_initializing = true;
2390
2.33k
    p_stream->b_contiguous = true; /* default */
2391
2.33k
    p_stream->queue.pp_append = &p_stream->queue.p_blocks;
2392
2.33k
}
2393
2394
/**
2395
 * This function delete and release all data associated to a logical_stream_t
2396
 */
2397
static void Ogg_LogicalStreamDelete( demux_t *p_demux, logical_stream_t *p_stream )
2398
2.33k
{
2399
2.33k
    demux_sys_t *p_sys = p_demux->p_sys;
2400
2401
2.33k
    if( p_stream->p_es )
2402
558
        es_out_Del( p_demux->out, p_stream->p_es );
2403
2404
2.33k
    ogg_stream_clear( &p_stream->os );
2405
2.33k
    free( p_stream->p_headers );
2406
2407
2.33k
    Ogg_CleanSpecificData( p_stream );
2408
2409
2.33k
    es_format_Clean( &p_stream->fmt_old );
2410
2.33k
    es_format_Clean( &p_stream->fmt );
2411
2412
2.33k
    if ( p_stream->idx != NULL)
2413
0
    {
2414
0
        oggseek_index_entries_free( p_stream->idx );
2415
0
    }
2416
2417
2.33k
    Ogg_FreeSkeleton( p_stream->p_skel );
2418
2.33k
    p_stream->p_skel = NULL;
2419
2.33k
    if( p_sys->p_skelstream == p_stream )
2420
0
        p_sys->p_skelstream = NULL;
2421
2422
    /* Shouldn't happen */
2423
2.33k
    block_ChainRelease( p_stream->queue.p_blocks );
2424
2425
2.33k
    free( p_stream );
2426
2.33k
}
2427
/**
2428
 * This function check if a we need to reset a decoder in case we are
2429
 * reusing an old ES
2430
 */
2431
static bool Ogg_IsVorbisFormatCompatible( const es_format_t *p_new, const es_format_t *p_old )
2432
177
{
2433
177
    size_t pi_new_size[XIPH_MAX_HEADER_COUNT];
2434
177
    const void *pp_new_data[XIPH_MAX_HEADER_COUNT];
2435
177
    size_t i_new_count;
2436
2437
177
    if (xiph_SplitHeaders(pi_new_size, pp_new_data, &i_new_count, p_new->i_extra, p_new->p_extra))
2438
0
        i_new_count = 0;
2439
2440
177
    size_t pi_old_size[XIPH_MAX_HEADER_COUNT];
2441
177
    const void *pp_old_data[XIPH_MAX_HEADER_COUNT];
2442
177
    size_t i_old_count;
2443
2444
177
    if (xiph_SplitHeaders(pi_old_size, pp_old_data, &i_old_count, p_old->i_extra, p_old->p_extra))
2445
0
        i_old_count = 0;
2446
2447
177
    bool b_match = i_new_count == i_old_count;
2448
686
    for (size_t i = 0; i < i_new_count && b_match; i++)
2449
509
    {
2450
        /* Ignore vorbis comment */
2451
509
        if( i == 1 )
2452
166
            continue;
2453
343
        if( pi_new_size[i] != pi_old_size[i] ||
2454
281
            memcmp( pp_new_data[i], pp_old_data[i], pi_new_size[i] ) )
2455
68
            b_match = false;
2456
343
    }
2457
2458
177
    return b_match;
2459
177
}
2460
2461
static bool Ogg_IsOpusFormatCompatible( const es_format_t *p_new,
2462
                                        const es_format_t *p_old )
2463
7
{
2464
7
    size_t pi_new_size[XIPH_MAX_HEADER_COUNT];
2465
7
    const void *pp_new_data[XIPH_MAX_HEADER_COUNT];
2466
7
    size_t i_new_count;
2467
2468
7
    if(xiph_SplitHeaders(pi_new_size, pp_new_data, &i_new_count, p_new->i_extra, p_new->p_extra ) )
2469
0
        i_new_count = 0;
2470
2471
7
    size_t pi_old_size[XIPH_MAX_HEADER_COUNT];
2472
7
    const void *pp_old_data[XIPH_MAX_HEADER_COUNT];
2473
7
    size_t i_old_count;
2474
2475
7
    if( xiph_SplitHeaders(pi_old_size, pp_old_data, &i_old_count, p_old->i_extra, p_old->p_extra ) )
2476
0
        i_old_count = 0;
2477
7
    bool b_match = false;
2478
7
    if( i_new_count == i_old_count && i_new_count > 0 )
2479
7
    {
2480
7
        static const unsigned char default_map[2] = { 0, 1 };
2481
7
        const unsigned char *p_old_head;
2482
7
        unsigned char *p_new_head;
2483
7
        const unsigned char *p_old_map;
2484
7
        const unsigned char *p_new_map;
2485
7
        int i_old_channel_count;
2486
7
        int i_new_channel_count;
2487
7
        int i_old_stream_count;
2488
7
        int i_new_stream_count;
2489
7
        int i_old_coupled_count;
2490
7
        int i_new_coupled_count;
2491
7
        size_t i_old_map_size, i_new_map_size;
2492
7
        p_old_head = pp_old_data[0];
2493
7
        i_old_channel_count = i_old_stream_count = i_old_coupled_count = 0;
2494
7
        p_old_map = default_map;
2495
7
        i_old_map_size = ARRAY_SIZE(default_map);
2496
7
        if( pi_old_size[0] >= 19 && p_old_head[8] <= 15 )
2497
1
        {
2498
1
            i_old_channel_count = p_old_head[9];
2499
1
            switch( p_old_head[18] )
2500
1
            {
2501
0
                case 0:
2502
0
                    i_old_stream_count = 1;
2503
0
                    i_old_coupled_count = i_old_channel_count - 1;
2504
0
                    break;
2505
1
                case 1:
2506
1
                    if( pi_old_size[0] >= 21U + i_old_channel_count )
2507
1
                    {
2508
1
                        i_old_stream_count = p_old_head[19];
2509
1
                        i_old_coupled_count = p_old_head[20];
2510
1
                        p_old_map = p_old_head + 21;
2511
1
                        i_old_map_size = i_old_channel_count;
2512
1
                    }
2513
1
                    break;
2514
1
            }
2515
1
        }
2516
7
        p_new_head = (unsigned char *)pp_new_data[0];
2517
7
        i_new_channel_count = i_new_stream_count = i_new_coupled_count = 0;
2518
7
        p_new_map = default_map;
2519
7
        i_new_map_size = ARRAY_SIZE(default_map);
2520
7
        if( pi_new_size[0] >= 19 && p_new_head[8] <= 15 )
2521
5
        {
2522
5
            i_new_channel_count = p_new_head[9];
2523
5
            switch( p_new_head[18] )
2524
5
            {
2525
4
                case 0:
2526
4
                    i_new_stream_count = 1;
2527
4
                    i_new_coupled_count = i_new_channel_count - 1;
2528
4
                    break;
2529
1
                case 1:
2530
1
                    if( pi_new_size[0] >= 21U + i_new_channel_count )
2531
1
                    {
2532
1
                        i_new_stream_count = p_new_head[19];
2533
1
                        i_new_coupled_count = p_new_head[20];
2534
1
                        p_new_map = p_new_head+21;
2535
1
                        i_new_map_size = i_new_channel_count;
2536
1
                    }
2537
1
                    break;
2538
5
            }
2539
5
        }
2540
7
        b_match = i_old_channel_count == i_new_channel_count &&
2541
3
                  i_old_stream_count == i_new_stream_count &&
2542
3
                  i_old_coupled_count == i_new_coupled_count &&
2543
3
                  i_old_map_size == i_new_map_size &&
2544
3
                  memcmp(p_old_map, p_new_map,
2545
3
                      i_new_map_size*sizeof(*p_new_map)) == 0;
2546
7
    }
2547
2548
7
    return b_match;
2549
7
}
2550
2551
static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t *p_stream )
2552
200
{
2553
200
    bool b_compatible = false;
2554
200
    if( !p_stream->fmt_old.i_cat || !p_stream->fmt_old.i_codec )
2555
0
        return true;
2556
2557
    /* Only Vorbis and Opus are supported. */
2558
200
    if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS )
2559
177
        b_compatible = Ogg_IsVorbisFormatCompatible( &p_stream->fmt, &p_stream->fmt_old );
2560
23
    else if( p_stream->fmt.i_codec == VLC_CODEC_OPUS )
2561
7
        b_compatible = Ogg_IsOpusFormatCompatible( &p_stream->fmt, &p_stream->fmt_old );
2562
16
    else if( p_stream->fmt.i_codec == VLC_CODEC_FLAC )
2563
10
        b_compatible = !p_stream->fmt.b_packetized;
2564
2565
200
    if( !b_compatible )
2566
200
        msg_Warn( p_demux, "cannot reuse old stream, resetting the decoder" );
2567
2568
200
    return !b_compatible;
2569
200
}
2570
2571
static void Ogg_ExtractComments( demux_t *p_demux, es_format_t *p_fmt,
2572
                                 const void *p_headers, size_t i_headers )
2573
855
{
2574
855
    demux_sys_t *p_ogg = p_demux->p_sys;
2575
855
    int i_cover_score = 0;
2576
855
    int i_cover_idx = 0;
2577
2578
855
    vorbis_ParseComment( p_fmt, &p_ogg->p_meta, p_headers, i_headers,
2579
855
                         &p_ogg->i_attachments, &p_ogg->attachments,
2580
855
                         &i_cover_score, &i_cover_idx,
2581
855
                         &p_ogg->i_seekpoints, &p_ogg->pp_seekpoints );
2582
2583
855
    if( p_ogg->p_meta != NULL && i_cover_idx < p_ogg->i_attachments )
2584
0
    {
2585
0
        char psz_url[128];
2586
0
        snprintf( psz_url, sizeof(psz_url), "attachment://%s",
2587
0
                  p_ogg->attachments[i_cover_idx]->psz_name );
2588
0
        vlc_meta_Set( p_ogg->p_meta, vlc_meta_ArtworkURL, psz_url );
2589
0
    }
2590
2591
855
    int i_ret = vlc_replay_gain_CopyFromMeta( &p_fmt->audio_replay_gain, p_ogg->p_meta );
2592
2593
    /* use replay gain if available; otherwise use IETF RFC7845 §5.2.1 */
2594
855
    if( i_ret != VLC_SUCCESS && p_ogg->p_meta != NULL )
2595
128
    {
2596
128
        audio_replay_gain_t *p_arg = &p_fmt->audio_replay_gain;
2597
128
        replay_gain_Reset( p_arg );
2598
2599
128
        const char *track_gain = vlc_meta_GetExtra( p_ogg->p_meta, "R128_TRACK_GAIN" );
2600
128
        if( track_gain )
2601
0
        {
2602
0
            p_arg->pb_gain[AUDIO_REPLAY_GAIN_TRACK] = true;
2603
0
            p_arg->pf_gain[AUDIO_REPLAY_GAIN_TRACK] = vlc_strtof_c( track_gain, NULL ) / 256.f;
2604
0
        }
2605
2606
128
        const char *album_gain = vlc_meta_GetExtra( p_ogg->p_meta, "R128_ALBUM_GAIN" );
2607
128
        if( album_gain )
2608
0
        {
2609
0
            p_arg->pb_gain[AUDIO_REPLAY_GAIN_ALBUM] = true;
2610
0
            p_arg->pf_gain[AUDIO_REPLAY_GAIN_ALBUM] = vlc_strtof_c( album_gain, NULL ) / 256.f;
2611
0
        }
2612
2613
128
        if( track_gain || album_gain )
2614
0
        {
2615
            /* EBU R128 uses -23 LUFS as the reference level */
2616
0
            p_arg->pb_reference_loudness = true;
2617
0
            p_arg->pf_reference_loudness = -23.f;
2618
0
        }
2619
128
    }
2620
2621
855
    if( p_ogg->i_seekpoints > 1 )
2622
0
    {
2623
0
        p_ogg->updates |= INPUT_UPDATE_TITLE_LIST;
2624
0
    }
2625
855
}
2626
2627
static inline uint32_t GetDW24BE( const uint8_t *p )
2628
33
{
2629
33
    uint32_t i = ( p[0] << 16 ) + ( p[1] << 8 ) + ( p[2] );
2630
#ifdef WORDS_BIGENDIAN
2631
    i = vlc_bswap32(i);
2632
#endif
2633
33
    return i;
2634
33
}
2635
2636
static void Ogg_ExtractFlacComments( demux_t *p_demux, es_format_t *p_fmt,
2637
                                     const uint8_t *p_headers, size_t i_headers )
2638
35
{
2639
    /* Skip Streaminfo 42 bytes / 1st page */
2640
35
    if(i_headers <= 46)
2641
2
        return;
2642
33
    p_headers += 42; i_headers -= 42;
2643
    /* Block Header 1 + 3 bytes */
2644
33
    uint32_t blocksize = GetDW24BE(&p_headers[1]);
2645
33
    if(p_headers[0] == 0x84 && blocksize <= i_headers - 4)
2646
24
    {
2647
24
        Ogg_ExtractComments( p_demux, p_fmt, &p_headers[4], i_headers - 4 );
2648
24
    }
2649
33
}
2650
2651
static void Ogg_ExtractXiphMeta( demux_t *p_demux, es_format_t *p_fmt,
2652
                                 const void *p_headers, size_t i_headers, unsigned i_skip )
2653
920
{
2654
920
    size_t pi_size[XIPH_MAX_HEADER_COUNT];
2655
920
    const void *pp_data[XIPH_MAX_HEADER_COUNT];
2656
920
    size_t i_count;
2657
2658
920
    if( xiph_SplitHeaders( pi_size, pp_data, &i_count, i_headers, p_headers ) )
2659
0
        return;
2660
    /* TODO how to handle multiple comments properly ? */
2661
920
    if( i_count >= 2 && pi_size[1] > i_skip )
2662
831
    {
2663
831
        Ogg_ExtractComments( p_demux, p_fmt,
2664
831
                             (const uint8_t *)pp_data[1] + i_skip,
2665
831
                             pi_size[1] - i_skip );
2666
831
    }
2667
920
}
2668
2669
static void Ogg_ExtractMeta( demux_t *p_demux, es_format_t *p_fmt, const uint8_t *p_headers, size_t i_headers )
2670
955
{
2671
955
    demux_sys_t *p_ogg = p_demux->p_sys;
2672
2673
955
    switch( p_fmt->i_codec )
2674
955
    {
2675
    /* 3 headers with the 2° one being the comments */
2676
633
    case VLC_CODEC_VORBIS:
2677
876
    case VLC_CODEC_THEORA:
2678
876
    case VLC_CODEC_DAALA:
2679
876
        Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 1+6 );
2680
876
        break;
2681
37
    case VLC_CODEC_OPUS:
2682
37
        Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 8 );
2683
37
        break;
2684
7
    case VLC_CODEC_SPEEX:
2685
7
        Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 0 );
2686
7
        break;
2687
0
    case VLC_CODEC_VP8:
2688
0
        Ogg_ExtractComments( p_demux, p_fmt, p_headers, i_headers );
2689
0
        break;
2690
    /* N headers with the 2° one being the comments */
2691
0
    case VLC_CODEC_KATE:
2692
        /* 1 byte for header type, 7 bytes for magic, 1 reserved zero byte */
2693
0
        Ogg_ExtractXiphMeta( p_demux, p_fmt, p_headers, i_headers, 1+7+1 );
2694
0
        break;
2695
2696
    /* TODO */
2697
35
    case VLC_CODEC_FLAC:
2698
35
        Ogg_ExtractFlacComments( p_demux, p_fmt, p_headers, i_headers );
2699
35
        break;
2700
2701
    /* No meta data */
2702
0
    case VLC_CODEC_DIRAC:
2703
0
    default:
2704
0
        break;
2705
955
    }
2706
955
    if( p_ogg->p_meta )
2707
128
        p_ogg->updates |= INPUT_UPDATE_META;
2708
955
}
2709
2710
static bool Ogg_ReadTheoraHeader( logical_stream_t *p_stream,
2711
                                  ogg_packet *p_oggpacket )
2712
565
{
2713
565
    bs_t bitstream;
2714
565
    unsigned int i_fps_numerator;
2715
565
    unsigned int i_fps_denominator;
2716
565
    int i_major;
2717
565
    int i_minor;
2718
565
    int i_subminor;
2719
565
    int i_version;
2720
2721
    /* Signal that we want to keep a backup of the theora
2722
     * stream headers. They will be used when switching between
2723
     * audio streams. */
2724
565
    p_stream->b_force_backup = true;
2725
2726
    /* Cheat and get additional info ;) */
2727
565
    bs_init( &bitstream, p_oggpacket->packet, p_oggpacket->bytes );
2728
565
    bs_skip( &bitstream, 56 );
2729
2730
565
    i_major = bs_read( &bitstream, 8 ); /* major version num */
2731
565
    i_minor = bs_read( &bitstream, 8 ); /* minor version num */
2732
565
    i_subminor = bs_read( &bitstream, 8 ); /* subminor version num */
2733
2734
565
    bs_skip( &bitstream, 16 ) /*<< 4*/; /* width */
2735
565
    bs_skip( &bitstream, 16 ) /*<< 4*/; /* height */
2736
565
    bs_skip( &bitstream, 24 ); /* frame width */
2737
565
    bs_skip( &bitstream, 24 ); /* frame height */
2738
565
    bs_skip( &bitstream, 8 ); /* x offset */
2739
565
    bs_skip( &bitstream, 8 ); /* y offset */
2740
2741
565
    i_fps_numerator = bs_read( &bitstream, 32 );
2742
565
    i_fps_denominator = bs_read( &bitstream, 32 );
2743
565
    i_fps_denominator = __MAX( i_fps_denominator, 1 );
2744
565
    bs_skip( &bitstream, 24 ); /* aspect_numerator */
2745
565
    bs_skip( &bitstream, 24 ); /* aspect_denominator */
2746
2747
565
    p_stream->fmt.video.i_frame_rate = i_fps_numerator;
2748
565
    p_stream->fmt.video.i_frame_rate_base = i_fps_denominator;
2749
2750
565
    bs_skip( &bitstream, 8 ); /* colorspace */
2751
565
    p_stream->fmt.i_bitrate = bs_read( &bitstream, 24 );
2752
565
    bs_skip( &bitstream, 6 ); /* quality */
2753
2754
    /* granule_shift = i_log( frequency_force -1 ) */
2755
565
    p_stream->i_granule_shift = bs_read( &bitstream, 5 );
2756
2757
565
    i_version = i_major * 1000000 + i_minor * 1000 + i_subminor;
2758
565
    p_stream->i_first_frame_index = (i_version >= 3002001) ? 1 : 0;
2759
565
    if ( !i_fps_denominator || !i_fps_numerator )
2760
0
        return false;
2761
565
    date_Init( &p_stream->dts, i_fps_numerator, i_fps_denominator );
2762
2763
565
    return true;
2764
565
}
2765
2766
static bool Ogg_ReadDaalaHeader( logical_stream_t *p_stream,
2767
                                 ogg_packet *p_oggpacket )
2768
0
{
2769
0
    oggpack_buffer opb;
2770
0
    uint32_t i_timebase_numerator;
2771
0
    uint32_t i_timebase_denominator;
2772
0
    int i_keyframe_granule_shift;
2773
0
    uint8_t i_major;
2774
0
    uint8_t i_minor;
2775
0
    uint8_t i_subminor;
2776
0
    int i_version;
2777
2778
    /* Signal that we want to keep a backup of the daala
2779
     * stream headers. They will be used when switching between
2780
     * audio streams. */
2781
0
    p_stream->b_force_backup = true;
2782
2783
    /* Cheat and get additional info ;) */
2784
0
    oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes );
2785
0
    oggpack_adv( &opb, 48 );
2786
2787
0
    i_major = oggpack_read( &opb, 8 ); /* major version num */
2788
0
    i_minor = oggpack_read( &opb, 8 ); /* minor version num */
2789
0
    i_subminor = oggpack_read( &opb, 8 ); /* subminor version num */
2790
2791
0
    oggpack_adv( &opb, 32 ); /* width */
2792
0
    oggpack_adv( &opb, 32 ); /* height */
2793
2794
0
    oggpack_adv( &opb, 32 ); /* aspect numerator */
2795
0
    oggpack_adv( &opb, 32 ); /* aspect denominator */
2796
0
    i_timebase_numerator = oggpack_read( &opb, 32 );
2797
2798
0
    i_timebase_denominator = oggpack_read( &opb, 32 );
2799
0
    i_timebase_denominator = __MAX( i_timebase_denominator, 1 );
2800
2801
0
    p_stream->fmt.video.i_frame_rate = i_timebase_numerator;
2802
0
    p_stream->fmt.video.i_frame_rate_base = i_timebase_denominator;
2803
2804
0
    oggpack_adv( &opb, 32 ); /* frame duration */
2805
2806
    /* granule_shift = i_log( frequency_force -1 ) */
2807
0
    i_keyframe_granule_shift = oggpack_read( &opb, 8 );
2808
0
    if ( i_keyframe_granule_shift < 0 || i_keyframe_granule_shift > 31 )
2809
0
        return false;
2810
2811
0
    p_stream->i_granule_shift = i_keyframe_granule_shift;
2812
2813
0
    i_version = i_major * 1000000 + i_minor * 1000 + i_subminor;
2814
0
    VLC_UNUSED(i_version);
2815
0
    p_stream->i_first_frame_index = 0;
2816
0
    if ( !i_timebase_numerator || !i_timebase_denominator )
2817
0
        return false;
2818
0
    date_Init( &p_stream->dts, i_timebase_numerator, i_timebase_denominator );
2819
2820
0
    return true;
2821
0
}
2822
2823
static bool Ogg_ReadVorbisHeader( logical_stream_t *p_stream,
2824
                                  ogg_packet *p_oggpacket )
2825
695
{
2826
695
    oggpack_buffer opb;
2827
2828
    /* Signal that we want to keep a backup of the vorbis
2829
     * stream headers. They will be used when switching between
2830
     * audio streams. */
2831
695
    p_stream->b_force_backup = true;
2832
2833
    /* Cheat and get additional info ;) */
2834
695
    oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2835
695
    oggpack_adv( &opb, 88 );
2836
695
    p_stream->fmt.audio.i_channels = oggpack_read( &opb, 8 );
2837
695
    fill_channels_info(&p_stream->fmt.audio);
2838
695
    p_stream->fmt.audio.i_rate = oggpack_read( &opb, 32 );
2839
695
    if( p_stream->fmt.audio.i_rate == 0 )
2840
0
        return false;
2841
695
    date_Init( &p_stream->dts, p_stream->fmt.audio.i_rate, 1 );
2842
2843
695
    oggpack_adv( &opb, 32 );
2844
695
    p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 ); /* is signed 32 */
2845
695
    if( p_stream->fmt.i_bitrate > INT32_MAX ) p_stream->fmt.i_bitrate = 0;
2846
695
    return true;
2847
695
}
2848
#ifdef HAVE_LIBVORBIS
2849
static bool Ogg_VorbisValidBlocksize( long i_blocksize )
2850
102k
{
2851
    /* non audio or broken return negative errors */
2852
102k
    return i_blocksize > 0 && i_blocksize <= 8192;
2853
102k
}
2854
2855
static void Ogg_DecodeVorbisHeader( logical_stream_t *p_stream,
2856
                                    ogg_packet *p_oggpacket, int i_number )
2857
1.94k
{
2858
1.94k
    switch( i_number )
2859
1.94k
    {
2860
662
    case VORBIS_HEADER_IDENTIFICATION:
2861
662
        p_stream->special.vorbis.p_info = calloc( 1, sizeof(vorbis_info) );
2862
662
        p_stream->special.vorbis.p_comment = malloc( sizeof(vorbis_comment) );
2863
662
        if ( !p_stream->special.vorbis.p_info || !p_stream->special.vorbis.p_comment )
2864
0
        {
2865
0
            FREENULL( p_stream->special.vorbis.p_info );
2866
0
            FREENULL( p_stream->special.vorbis.p_comment );
2867
0
            break;
2868
0
        }
2869
662
        vorbis_info_init( p_stream->special.vorbis.p_info );
2870
662
        vorbis_comment_init( p_stream->special.vorbis.p_comment );
2871
        /* fallthrough */
2872
2873
1.31k
    case VORBIS_HEADER_COMMENT:
2874
1.94k
    case VORBIS_HEADER_SETUP:
2875
1.94k
        if ( !p_stream->special.vorbis.p_info ||
2876
1.94k
             vorbis_synthesis_headerin(
2877
1.94k
                 p_stream->special.vorbis.p_info,
2878
1.94k
                 p_stream->special.vorbis.p_comment, p_oggpacket ) )
2879
371
            break;
2880
2881
1.57k
        p_stream->special.vorbis.i_headers_flags |= VORBIS_HEADER_TO_FLAG(i_number);
2882
        /* fallthrough */
2883
2884
1.57k
    default:
2885
1.57k
        break;
2886
1.94k
    }
2887
1.94k
}
2888
#endif
2889
2890
static bool Ogg_ReadSpeexHeader( logical_stream_t *p_stream,
2891
                                 ogg_packet *p_oggpacket )
2892
62
{
2893
62
    oggpack_buffer opb;
2894
2895
    /* Signal that we want to keep a backup of the speex
2896
     * stream headers. They will be used when switching between
2897
     * audio streams. */
2898
62
    p_stream->b_force_backup = true;
2899
2900
    /* Cheat and get additional info ;) */
2901
62
    oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2902
62
    oggpack_adv( &opb, 224 );
2903
62
    oggpack_adv( &opb, 32 ); /* speex_version_id */
2904
62
    oggpack_adv( &opb, 32 ); /* header_size */
2905
62
    p_stream->fmt.audio.i_rate = oggpack_read( &opb, 32 );
2906
62
    if ( !p_stream->fmt.audio.i_rate )
2907
0
        return false;
2908
62
    date_Init( &p_stream->dts, p_stream->fmt.audio.i_rate, 1 );
2909
62
    oggpack_adv( &opb, 32 ); /* mode */
2910
62
    oggpack_adv( &opb, 32 ); /* mode_bitstream_version */
2911
62
    uint32_t channels = oggpack_read( &opb, 32 );
2912
62
    if (channels > UINT8_MAX)
2913
55
        return false;
2914
7
    p_stream->fmt.audio.i_channels = channels;
2915
7
    fill_channels_info(&p_stream->fmt.audio);
2916
7
    p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );
2917
7
    p_stream->special.speex.i_framesize =
2918
7
            oggpack_read( &opb, 32 ); /* frame_size */
2919
7
    oggpack_adv( &opb, 32 ); /* vbr */
2920
7
    p_stream->special.speex.i_framesperpacket =
2921
7
            oggpack_read( &opb, 32 ); /* frames_per_packet */
2922
7
    p_stream->i_extra_headers_packets = oggpack_read( &opb, 32 ); /* extra_headers */
2923
7
    return true;
2924
62
}
2925
2926
static void Ogg_ReadOpusHeader( logical_stream_t *p_stream,
2927
                                ogg_packet *p_oggpacket )
2928
70
{
2929
70
    oggpack_buffer opb;
2930
2931
    /* Signal that we want to keep a backup of the opus
2932
     * stream headers. They will be used when switching between
2933
     * audio streams. */
2934
70
    p_stream->b_force_backup = true;
2935
2936
    /* All OggOpus streams are timestamped at 48kHz and
2937
     * can be played at 48kHz. */
2938
70
    date_Init( &p_stream->dts, 48000, 1 );
2939
70
    p_stream->fmt.i_bitrate = 0;
2940
70
    p_stream->fmt.audio.i_rate = 48000;
2941
    /* Cheat and get additional info ;) */
2942
70
    oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
2943
70
    oggpack_adv( &opb, 64 );
2944
70
    if( oggpack_read( &opb, 8 ) <= 1 ) /* version_id */
2945
42
    {
2946
42
        p_stream->fmt.audio.i_channels = oggpack_read( &opb, 8 );
2947
42
        p_stream->i_pre_skip = oggpack_read( &opb, 16 );
2948
42
        oggpack_adv( &opb, 32 + 16 ); /* Skip Input Sample Rate and Output Gain */
2949
42
        switch( oggpack_read( &opb, 8 ) ) /* mapping family */
2950
42
        {
2951
42
            case 0: /* RFC7587 */
2952
42
                if( p_stream->fmt.audio.i_channels > 2 )
2953
0
                    break;
2954
                /* fallthrough */
2955
42
            case 1: /* Vorbis */
2956
42
                if( p_stream->fmt.audio.i_channels > 8 )
2957
0
                    break;
2958
42
                fill_channels_info( &p_stream->fmt.audio );
2959
42
                break;
2960
0
            case 2: /* Ambisonic */
2961
0
            case 3: /* Ambisonic with mixing matrix */
2962
0
                p_stream->fmt.audio.channel_type = AUDIO_CHANNEL_TYPE_AMBISONICS;
2963
0
                break;
2964
0
            default:
2965
0
                break;
2966
42
        }
2967
42
    }
2968
70
}
2969
2970
static bool Ogg_ReadFlacStreamInfo( demux_t *p_demux, logical_stream_t *p_stream,
2971
                                ogg_packet *p_oggpacket )
2972
37
{
2973
    /* Parse the STREAMINFO metadata */
2974
37
    bs_t s;
2975
2976
37
    bs_init( &s, p_oggpacket->packet, p_oggpacket->bytes );
2977
2978
37
    bs_skip( &s, 1 );
2979
37
    if( p_oggpacket->bytes > 0 && bs_read( &s, 7 ) != 0 )
2980
0
    {
2981
0
        msg_Dbg( p_demux, "Invalid FLAC STREAMINFO metadata" );
2982
0
        return false;
2983
0
    }
2984
2985
37
    if( bs_read( &s, 24 ) >= 34 /*size STREAMINFO*/ )
2986
37
    {
2987
37
        bs_skip( &s, 80 );
2988
37
        p_stream->fmt.audio.i_rate = bs_read( &s, 20 );
2989
37
        p_stream->fmt.audio.i_channels = bs_read( &s, 3 ) + 1;
2990
37
        fill_channels_info(&p_stream->fmt.audio);
2991
2992
37
        msg_Dbg( p_demux, "FLAC header, channels: %"PRIu8", rate: %u",
2993
37
                 p_stream->fmt.audio.i_channels, p_stream->fmt.audio.i_rate );
2994
37
        if ( p_stream->fmt.audio.i_rate == 0 )
2995
0
            return false;
2996
37
        date_Init( &p_stream->dts, p_stream->fmt.audio.i_rate, 1 );
2997
37
    }
2998
0
    else
2999
0
    {
3000
0
        msg_Dbg( p_demux, "FLAC STREAMINFO metadata too short" );
3001
0
    }
3002
3003
    /* Fake this as the last metadata block */
3004
37
    *((uint8_t*)p_oggpacket->packet) |= 0x80;
3005
37
    return true;
3006
37
}
3007
3008
static bool Ogg_ReadKateHeader( logical_stream_t *p_stream,
3009
                                ogg_packet *p_oggpacket )
3010
0
{
3011
0
    oggpack_buffer opb;
3012
0
    uint32_t gnum;
3013
0
    uint32_t gden;
3014
0
    int n;
3015
0
    char *psz_desc;
3016
3017
    /* Signal that we want to keep a backup of the kate
3018
     * stream headers. They will be used when switching between
3019
     * kate streams. */
3020
0
    p_stream->b_force_backup = true;
3021
3022
    /* Cheat and get additional info ;) */
3023
0
    oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
3024
0
    oggpack_adv( &opb, 11*8 ); /* packet type, kate magic, version */
3025
0
    p_stream->special.kate.i_num_headers = oggpack_read( &opb, 8 );
3026
0
    oggpack_adv( &opb, 3*8 );
3027
0
    p_stream->i_granule_shift = oggpack_read( &opb, 8 );
3028
0
    oggpack_adv( &opb, 8*8 ); /* reserved */
3029
0
    gnum = oggpack_read( &opb, 32 );
3030
0
    gden = oggpack_read( &opb, 32 );
3031
0
    gden = __MAX( gden, 1 );
3032
0
    if ( !gnum || !gden )
3033
0
        return false;
3034
0
    date_Init( &p_stream->dts, gnum, gden );
3035
3036
0
    p_stream->fmt.psz_language = malloc(16);
3037
0
    if( p_stream->fmt.psz_language )
3038
0
    {
3039
0
        for( n = 0; n < 16; n++ )
3040
0
            p_stream->fmt.psz_language[n] = oggpack_read(&opb,8);
3041
0
        p_stream->fmt.psz_language[15] = 0; /* just in case */
3042
0
    }
3043
0
    else
3044
0
    {
3045
0
        for( n = 0; n < 16; n++ )
3046
0
            oggpack_read(&opb,8);
3047
0
    }
3048
0
    p_stream->fmt.psz_description = malloc(16);
3049
0
    if( p_stream->fmt.psz_description )
3050
0
    {
3051
0
        for( n = 0; n < 16; n++ )
3052
0
            p_stream->fmt.psz_description[n] = oggpack_read(&opb,8);
3053
0
        p_stream->fmt.psz_description[15] = 0; /* just in case */
3054
3055
        /* Now find a localized user readable description for this category */
3056
0
        psz_desc = strdup(FindKateCategoryName(p_stream->fmt.psz_description));
3057
0
        if( psz_desc )
3058
0
        {
3059
0
            free( p_stream->fmt.psz_description );
3060
0
            p_stream->fmt.psz_description = psz_desc;
3061
0
        }
3062
0
    }
3063
0
    else
3064
0
    {
3065
0
        for( n = 0; n < 16; n++ )
3066
0
            oggpack_read(&opb,8);
3067
0
    }
3068
3069
0
    return true;
3070
0
}
3071
3072
static bool Ogg_ReadVP8Header( demux_t *p_demux, logical_stream_t *p_stream,
3073
                               ogg_packet *p_oggpacket )
3074
55
{
3075
55
    switch( p_oggpacket->packet[5] )
3076
55
    {
3077
    /* STREAMINFO */
3078
55
    case 0x01:
3079
        /* Mapping version */
3080
55
        if ( p_oggpacket->packet[6] != 0x01 || p_oggpacket->packet[7] != 0x00 )
3081
32
            return false;
3082
23
        p_stream->i_granule_shift = 32;
3083
23
        p_stream->fmt.video.i_width = GetWBE( &p_oggpacket->packet[8] );
3084
23
        p_stream->fmt.video.i_height = GetWBE( &p_oggpacket->packet[10] );
3085
23
        p_stream->fmt.video.i_visible_width = p_stream->fmt.video.i_width;
3086
23
        p_stream->fmt.video.i_visible_height = p_stream->fmt.video.i_height;
3087
23
        p_stream->fmt.video.i_sar_num = GetDWBE( &p_oggpacket->packet[12 - 1] ) & 0x0FFF;
3088
23
        p_stream->fmt.video.i_sar_den = GetDWBE( &p_oggpacket->packet[15 - 1] ) & 0x0FFF;
3089
23
        p_stream->fmt.video.i_frame_rate = GetDWBE( &p_oggpacket->packet[18] );
3090
23
        p_stream->fmt.video.i_frame_rate_base = GetDWBE( &p_oggpacket->packet[22] );
3091
23
        if ( !p_stream->fmt.video.i_frame_rate || !p_stream->fmt.video.i_frame_rate_base )
3092
0
            return false;
3093
23
        date_Init( &p_stream->dts, p_stream->fmt.video.i_frame_rate,
3094
23
                                   p_stream->fmt.video.i_frame_rate_base );
3095
23
        return true;
3096
    /* METADATA */
3097
0
    case 0x02:
3098
0
        Ogg_ExtractMeta( p_demux, & p_stream->fmt,
3099
0
                         p_oggpacket->packet + 7, p_oggpacket->bytes - 7 );
3100
0
        return true;
3101
0
    default:
3102
0
        return false;
3103
55
    }
3104
55
}
3105
3106
#define CMPVALUE(str) \
3107
0
    (bytes >= (sizeof(str)-1) && !strncmp((const char *)p_value, str, sizeof(str)-1))
3108
3109
static void Ogg_ApplyContentType( logical_stream_t *p_stream,
3110
                                  const uint8_t *p_value, size_t bytes,
3111
                                  bool *b_force_backup )
3112
0
{
3113
0
    if( p_stream->fmt.i_cat != UNKNOWN_ES || bytes == 0 )
3114
0
        return;
3115
3116
0
    if( CMPVALUE("audio/x-wav") )
3117
0
    {
3118
        /* n.b. WAVs are unsupported right now */
3119
0
        es_format_Change( &p_stream->fmt, UNKNOWN_ES, 0 );
3120
0
        free( p_stream->fmt.psz_description );
3121
0
        p_stream->fmt.psz_description = strdup("WAV Audio (Unsupported)");
3122
0
    }
3123
0
    else if( CMPVALUE("audio/x-vorbis") ||
3124
0
             CMPVALUE("audio/vorbis") )
3125
0
    {
3126
0
        es_format_Change( &p_stream->fmt, AUDIO_ES, VLC_CODEC_VORBIS );
3127
3128
0
        *b_force_backup = true;
3129
0
    }
3130
0
    else if( CMPVALUE("audio/x-speex") ||
3131
0
             CMPVALUE("audio/speex") )
3132
0
    {
3133
0
        es_format_Change( &p_stream->fmt, AUDIO_ES, VLC_CODEC_SPEEX );
3134
3135
0
        *b_force_backup = true;
3136
0
    }
3137
0
    else if( CMPVALUE("audio/flac") )
3138
0
    {
3139
0
        es_format_Change( &p_stream->fmt, AUDIO_ES, VLC_CODEC_FLAC );
3140
3141
0
        *b_force_backup = true;
3142
0
    }
3143
0
    else if( CMPVALUE("video/x-theora") ||
3144
0
             CMPVALUE("video/theora") )
3145
0
    {
3146
0
        es_format_Change( &p_stream->fmt, VIDEO_ES, VLC_CODEC_THEORA );
3147
3148
0
        *b_force_backup = true;
3149
0
    }
3150
0
    else if( CMPVALUE("video/x-daala") ||
3151
0
             CMPVALUE("video/daala") )
3152
0
    {
3153
0
        es_format_Change( &p_stream->fmt, VIDEO_ES, VLC_CODEC_DAALA );
3154
3155
0
        *b_force_backup = true;
3156
0
    }
3157
0
    else if( CMPVALUE("video/x-xvid") )
3158
0
    {
3159
0
        es_format_Change( &p_stream->fmt, VIDEO_ES, VLC_FOURCC( 'x','v','i','d' ) );
3160
3161
0
        *b_force_backup = true;
3162
0
    }
3163
0
    else if( CMPVALUE("video/mpeg") )
3164
0
    {
3165
        /* n.b. MPEG streams are unsupported right now */
3166
0
        es_format_Change( &p_stream->fmt, VIDEO_ES, VLC_CODEC_MPGV );
3167
0
    }
3168
0
    else if( CMPVALUE("application/kate") )
3169
0
    {
3170
        /* ??? */
3171
0
        es_format_Change( &p_stream->fmt, UNKNOWN_ES, 0 );
3172
0
        p_stream->fmt.psz_description = strdup("OGG Kate Overlay (Unsupported)");
3173
0
    }
3174
0
    else if( CMPVALUE("video/x-vp8") )
3175
0
    {
3176
0
        es_format_Change( &p_stream->fmt, VIDEO_ES, VLC_CODEC_VP8 );
3177
0
    }
3178
0
}
3179
3180
static void Ogg_ReadAnnodexHeader( demux_t *p_demux,
3181
                                   logical_stream_t *p_stream,
3182
                                   ogg_packet *p_oggpacket )
3183
0
{
3184
0
    if( p_oggpacket->bytes >= 28 &&
3185
0
        !memcmp( p_oggpacket->packet, "Annodex", 7 ) )
3186
0
    {
3187
0
        oggpack_buffer opb;
3188
3189
0
        uint16_t major_version;
3190
0
        uint16_t minor_version;
3191
0
        uint64_t timebase_numerator;
3192
0
        uint64_t timebase_denominator;
3193
3194
0
        Ogg_ReadTheoraHeader( p_stream, p_oggpacket );
3195
3196
0
        oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes);
3197
0
        oggpack_adv( &opb, 8*8 ); /* "Annodex\0" header */
3198
0
        major_version = oggpack_read( &opb, 2*8 ); /* major version */
3199
0
        minor_version = oggpack_read( &opb, 2*8 ); /* minor version */
3200
0
        timebase_numerator = GetQWLE( &p_oggpacket->packet[16] );
3201
0
        timebase_denominator = GetQWLE( &p_oggpacket->packet[24] );
3202
3203
0
        msg_Dbg( p_demux, "Annodex info: version %"PRIu16".%"PRIu16" "
3204
0
                          "Timebase  %"PRId64" / %"PRId64,
3205
0
                          major_version, minor_version,
3206
0
                          timebase_numerator, timebase_denominator );
3207
0
    }
3208
0
    else if( p_oggpacket->bytes >= 42 &&
3209
0
             !memcmp( p_oggpacket->packet, "AnxData", 7 ) )
3210
0
    {
3211
0
        uint64_t granule_rate_numerator;
3212
0
        uint64_t granule_rate_denominator;
3213
3214
        /* Read in Annodex header fields */
3215
3216
0
        granule_rate_numerator = GetQWLE( &p_oggpacket->packet[8] );
3217
0
        granule_rate_denominator = GetQWLE( &p_oggpacket->packet[16] );
3218
0
        p_stream->i_secondary_header_packets =
3219
0
            GetDWLE( &p_oggpacket->packet[24] );
3220
3221
        /* we are guaranteed that the first header field will be
3222
         * the content-type (by the Annodex standard) */
3223
0
        long value_size = 0;
3224
0
        if( !strncasecmp( (char*)(&p_oggpacket->packet[28]), "Content-Type: ", 14 ) )
3225
0
        {
3226
0
            uint8_t *p = memchr( &p_oggpacket->packet[42], '\r',
3227
0
                                 p_oggpacket->bytes - 42 );
3228
0
            value_size = p ? p - &p_oggpacket->packet[42] : p_oggpacket->bytes - 42;
3229
0
        }
3230
3231
0
        char debug_string[32] = {0};
3232
0
        strncpy(debug_string, (const char*)&p_oggpacket->packet[42], __MIN(value_size, 31));
3233
0
        msg_Dbg( p_demux, "AnxData packet info: %"PRId64" / %"PRId64", %d, ``%s''",
3234
0
                 granule_rate_numerator, granule_rate_denominator,
3235
0
                 p_stream->i_secondary_header_packets, debug_string );
3236
3237
0
        if( granule_rate_numerator && granule_rate_denominator )
3238
0
            date_Init( &p_stream->dts, granule_rate_numerator, granule_rate_denominator );
3239
3240
        /* What type of file do we have? */
3241
0
        Ogg_ApplyContentType( p_stream, &p_oggpacket->packet[42], value_size,
3242
0
                              &p_stream->b_force_backup );
3243
0
    }
3244
0
}
3245
3246
static void Ogg_ReadSkeletonHeader( demux_t *p_demux, logical_stream_t *p_stream,
3247
                                    ogg_packet *p_oggpacket )
3248
0
{
3249
0
    demux_sys_t *p_sys = p_demux->p_sys;
3250
0
    if( p_oggpacket->bytes < 24 )
3251
0
        return;
3252
3253
0
    p_sys->p_skelstream = p_stream;
3254
    /* There can be only 1 skeleton for streams */
3255
0
    p_sys->skeleton.major = GetWLE( &p_oggpacket->packet[8] );
3256
0
    p_sys->skeleton.minor = GetWLE( &p_oggpacket->packet[10] );
3257
0
    uint64_t presentationtime_num = GetQWLE( &p_oggpacket->packet[12] );
3258
0
    uint64_t presentationtime_den = GetQWLE( &p_oggpacket->packet[20] );
3259
0
    if ( presentationtime_num != 0 && presentationtime_den != 0 )
3260
0
    {
3261
0
        int64_t presentationtime_gcd = GCD(presentationtime_num, presentationtime_den);
3262
0
        if ( presentationtime_gcd > 1 )
3263
0
        {
3264
0
            presentationtime_num = presentationtime_num / presentationtime_gcd;
3265
0
            presentationtime_den = presentationtime_den / presentationtime_gcd;
3266
0
        }
3267
0
        if ( presentationtime_num <= UINT32_MAX && presentationtime_den <= UINT32_MAX )
3268
0
            date_Init( &p_stream->dts, presentationtime_num, presentationtime_den );
3269
0
    }
3270
0
    if ( asprintf( & p_stream->fmt.psz_description,
3271
0
                   "OGG Skeleton version %" PRIu16 ".%" PRIu16,
3272
0
                   p_sys->skeleton.major, p_sys->skeleton.minor ) < 0 )
3273
0
        p_stream->fmt.psz_description = NULL;
3274
0
}
3275
3276
static void Ogg_ReadSkeletonBones( demux_t *p_demux, ogg_packet *p_oggpacket )
3277
5
{
3278
5
    demux_sys_t *p_sys = p_demux->p_sys;
3279
3280
5
    if ( p_sys->skeleton.major < 3 || p_oggpacket->bytes < 52 ) return;
3281
3282
    /* Find the matching stream for this skeleton data */
3283
0
    ogg_int32_t i_serialno = GetDWLE( &p_oggpacket->packet[12] );
3284
0
    logical_stream_t *p_target_stream = NULL;
3285
0
    for ( int i=0; i< p_sys->i_streams; i++ )
3286
0
    {
3287
0
        if ( p_sys->pp_stream[i]->i_serial_no == i_serialno )
3288
0
        {
3289
0
            p_target_stream = p_sys->pp_stream[i];
3290
0
            break;
3291
0
        }
3292
0
    }
3293
0
    if ( !p_target_stream ) return;
3294
3295
0
    ogg_skeleton_t *p_skel = p_target_stream->p_skel;
3296
0
    if ( !p_skel )
3297
0
    {
3298
0
        p_skel = malloc( sizeof( ogg_skeleton_t ) );
3299
0
        if ( !p_skel ) return;
3300
0
        TAB_INIT( p_skel->i_messages, p_skel->ppsz_messages );
3301
0
        p_skel->p_index = NULL;
3302
0
        p_target_stream->p_skel = p_skel;
3303
0
    }
3304
3305
0
    const unsigned char *p_messages = p_oggpacket->packet + 8 + GetDWLE( &p_oggpacket->packet[8] );
3306
0
    const unsigned char *p_boundary = p_oggpacket->packet + p_oggpacket->bytes;
3307
0
    const unsigned char *p = p_messages;
3308
0
    while ( p <= p_boundary - 1 && p > p_oggpacket->packet )
3309
0
    {
3310
0
        if ( *p == 0x0D && *(p+1) == 0x0A )
3311
0
        {
3312
0
            char *psz_message = strndup( (const char *) p_messages,
3313
0
                                         p - p_messages );
3314
0
            if ( psz_message )
3315
0
            {
3316
0
                msg_Dbg( p_demux, "stream %" PRId32 " [%s]", i_serialno, psz_message );
3317
0
                TAB_APPEND( p_skel->i_messages, p_skel->ppsz_messages, psz_message );
3318
0
            }
3319
0
            if ( p < p_boundary - 1 ) p_messages = p + 2;
3320
0
        }
3321
0
        p++;
3322
0
    }
3323
3324
0
}
3325
3326
/* Unpacks the 7bit variable encoding used in skeleton indexes */
3327
unsigned const char * Read7BitsVariableLE( unsigned const char *p_begin,
3328
                                           unsigned const char *p_end,
3329
                                           uint64_t *pi_value )
3330
0
{
3331
0
    int i_shift = 0;
3332
0
    int64_t i_read = 0;
3333
0
    *pi_value = 0;
3334
3335
0
    while ( p_begin < p_end )
3336
0
    {
3337
0
        i_read = *p_begin & 0x7F; /* High bit is start of integer */
3338
0
        *pi_value = *pi_value | ( i_read << i_shift );
3339
0
        i_shift += 7;
3340
0
        if ( (*p_begin++ & 0x80) == 0x80 ) break; /* see prev */
3341
0
    }
3342
3343
0
    *pi_value = GetQWLE( pi_value );
3344
0
    return p_begin;
3345
0
}
3346
3347
static void Ogg_ReadSkeletonIndex( demux_t *p_demux, ogg_packet *p_oggpacket )
3348
0
{
3349
0
    demux_sys_t *p_sys = p_demux->p_sys;
3350
3351
0
    if( p_sys->skeleton.major < 4
3352
0
         || p_oggpacket->bytes < 44 /* Need at least 1 index value (42+1+1) */
3353
0
    ) return;
3354
3355
    /* Find the matching stream for this skeleton data */
3356
0
    int32_t i_serialno = GetDWLE( &p_oggpacket->packet[6] );
3357
0
    logical_stream_t *p_stream = NULL;
3358
0
    for ( int i=0; i< p_sys->i_streams; i++ )
3359
0
    {
3360
0
        if( p_sys->pp_stream[i]->i_serial_no == i_serialno )
3361
0
        {
3362
0
            p_stream = p_sys->pp_stream[i];
3363
0
            break;
3364
0
        }
3365
0
    }
3366
0
    if ( !p_stream || !p_stream->p_skel ) return;
3367
0
    uint64_t i_keypoints = GetQWLE( &p_oggpacket->packet[10] );
3368
0
    msg_Dbg( p_demux, "%" PRIi64 " index data for %" PRIi32, i_keypoints, i_serialno );
3369
0
    if ( !i_keypoints ) return;
3370
3371
0
    p_stream->p_skel->i_indexstampden = GetQWLE( &p_oggpacket->packet[18] );
3372
0
    p_stream->p_skel->i_indexfirstnum = GetQWLE( &p_oggpacket->packet[24] );
3373
0
    p_stream->p_skel->i_indexlastnum = GetQWLE( &p_oggpacket->packet[32] );
3374
0
    unsigned const char *p_fwdbyte = &p_oggpacket->packet[42];
3375
0
    unsigned const char *p_boundary = p_oggpacket->packet + p_oggpacket->bytes;
3376
0
    uint64_t i_keypoints_found = 0;
3377
3378
0
    while( p_fwdbyte < p_boundary && i_keypoints_found < i_keypoints )
3379
0
    {
3380
0
        uint64_t i_val;
3381
0
        p_fwdbyte = Read7BitsVariableLE( p_fwdbyte, p_boundary, &i_val );
3382
0
        p_fwdbyte = Read7BitsVariableLE( p_fwdbyte, p_boundary, &i_val );
3383
0
        i_keypoints_found++;
3384
0
    }
3385
3386
0
    if ( i_keypoints_found != i_keypoints )
3387
0
    {
3388
0
        msg_Warn( p_demux, "Invalid Index: missing entries" );
3389
0
        return;
3390
0
    }
3391
3392
0
    p_stream->p_skel->p_index = malloc( p_oggpacket->bytes - 42 );
3393
0
    if ( !p_stream->p_skel->p_index ) return;
3394
0
    memcpy( p_stream->p_skel->p_index, &p_oggpacket->packet[42],
3395
0
            p_oggpacket->bytes - 42 );
3396
0
    p_stream->p_skel->i_index = i_keypoints_found;
3397
0
    p_stream->p_skel->i_index_size = p_oggpacket->bytes - 42;
3398
0
}
3399
3400
static void Ogg_FreeSkeleton( ogg_skeleton_t *p_skel )
3401
2.33k
{
3402
2.33k
    if ( !p_skel ) return;
3403
0
    for ( int i=0; i< p_skel->i_messages; i++ )
3404
0
        free( p_skel->ppsz_messages[i] );
3405
0
    TAB_CLEAN( p_skel->i_messages, p_skel->ppsz_messages );
3406
0
    free( p_skel->p_index );
3407
0
    free( p_skel );
3408
0
}
3409
3410
static void Ogg_ApplySkeleton( logical_stream_t *p_stream )
3411
0
{
3412
0
    if ( !p_stream->p_skel ) return;
3413
0
    for ( int i=0; i< p_stream->p_skel->i_messages; i++ )
3414
0
    {
3415
0
        const char *psz_message = p_stream->p_skel->ppsz_messages[i];
3416
0
        if ( ! strncmp( "Name: ", psz_message, 6 ) )
3417
0
        {
3418
0
            free( p_stream->fmt.psz_description );
3419
0
            p_stream->fmt.psz_description = strdup( psz_message + 6 );
3420
0
        }
3421
0
        else if ( ! strncmp("Content-Type: ", psz_message, 14 ) )
3422
0
        {
3423
0
            bool b_foo;
3424
0
            psz_message += 14;
3425
0
            Ogg_ApplyContentType( p_stream, (const uint8_t *)psz_message,
3426
0
                                  strlen(psz_message), &b_foo );
3427
0
        }
3428
0
    }
3429
0
}
3430
3431
/* Return true if there's a skeleton exact match */
3432
bool Ogg_GetBoundsUsingSkeletonIndex( logical_stream_t *p_stream, vlc_tick_t i_time,
3433
                                      int64_t *pi_lower, int64_t *pi_upper )
3434
0
{
3435
0
    if ( !p_stream || !p_stream->p_skel || !p_stream->p_skel->p_index ||
3436
0
         i_time == VLC_TICK_INVALID )
3437
0
        return false;
3438
3439
0
    i_time -= VLC_TICK_0;
3440
3441
    /* Validate range */
3442
0
    if ( i_time < p_stream->p_skel->i_indexfirstnum
3443
0
                * p_stream->p_skel->i_indexstampden ||
3444
0
         i_time > p_stream->p_skel->i_indexlastnum
3445
0
                * p_stream->p_skel->i_indexstampden ) return false;
3446
3447
    /* Then Lookup its index */
3448
0
    unsigned const char *p_fwdbyte = p_stream->p_skel->p_index;
3449
0
    unsigned const char *p_end = p_fwdbyte + p_stream->p_skel->i_index_size;
3450
0
    struct
3451
0
    {
3452
0
        int64_t i_pos;
3453
0
        vlc_tick_t i_time;
3454
0
    } current = { 0, 0 }, prev = { -1, -1 };
3455
3456
0
    uint64_t i_keypoints_found = 0;
3457
3458
0
    while( p_fwdbyte < p_end
3459
0
           && i_keypoints_found < p_stream->p_skel->i_index )
3460
0
    {
3461
0
        uint64_t i_val;
3462
0
        p_fwdbyte = Read7BitsVariableLE( p_fwdbyte, p_end, &i_val );
3463
0
        current.i_pos += i_val;
3464
0
        p_fwdbyte = Read7BitsVariableLE( p_fwdbyte, p_end, &i_val );
3465
0
        current.i_time += i_val * p_stream->p_skel->i_indexstampden;
3466
0
        if ( current.i_pos < 0 || current.i_time < 0 ) break;
3467
3468
0
        i_keypoints_found++;
3469
3470
0
        if ( i_time <= current.i_time )
3471
0
        {
3472
0
            *pi_lower = prev.i_pos;
3473
0
            *pi_upper = current.i_pos;
3474
0
            return ( i_time == current.i_time );
3475
0
        }
3476
0
        prev = current;
3477
0
    }
3478
0
    return false;
3479
0
}
3480
3481
static uint32_t dirac_uint( bs_t *p_bs )
3482
1.63k
{
3483
1.63k
    uint32_t u_count = 0, u_value = 0;
3484
3485
6.71k
    while( !bs_eof( p_bs ) && !bs_read( p_bs, 1 ) )
3486
5.08k
    {
3487
5.08k
        u_count++;
3488
5.08k
        u_value <<= 1;
3489
5.08k
        u_value |= bs_read( p_bs, 1 );
3490
5.08k
    }
3491
3492
1.63k
    return (1<<u_count) - 1 + u_value;
3493
1.63k
}
3494
3495
static int dirac_bool( bs_t *p_bs )
3496
792
{
3497
792
    return bs_read( p_bs, 1 );
3498
792
}
3499
3500
static bool Ogg_ReadDiracHeader( logical_stream_t *p_stream,
3501
                                 ogg_packet *p_oggpacket )
3502
198
{
3503
198
    p_stream->special.dirac.b_old = (p_oggpacket->packet[0] == 'K');
3504
3505
198
    static const struct {
3506
198
        uint32_t u_n /* numerator */, u_d /* denominator */;
3507
198
    } p_dirac_frate_tbl[] = { /* table 10.3 */
3508
198
        {1,1}, /* this first value is never used */
3509
198
        {24000,1001}, {24,1}, {25,1}, {30000,1001}, {30,1},
3510
198
        {50,1}, {60000,1001}, {60,1}, {15000,1001}, {25,2},
3511
198
    };
3512
198
    static const size_t u_dirac_frate_tbl = ARRAY_SIZE(p_dirac_frate_tbl);
3513
3514
198
    static const uint32_t pu_dirac_vidfmt_frate[] = { /* table C.1 */
3515
198
        1, 9, 10, 9, 10, 9, 10, 4, 3, 7, 6, 4, 3, 7, 6, 2, 2, 7, 6, 7, 6,
3516
198
    };
3517
198
    static const size_t u_dirac_vidfmt_frate = ARRAY_SIZE(pu_dirac_vidfmt_frate);
3518
3519
198
    bs_t bs;
3520
3521
    /* Backing up stream headers is not required -- seqhdrs are repeated
3522
     * throughout the stream at suitable decoding start points */
3523
198
    p_stream->b_force_backup = false;
3524
3525
    /* read in useful bits from sequence header */
3526
198
    bs_init( &bs, p_oggpacket->packet, p_oggpacket->bytes );
3527
198
    bs_skip( &bs, 13*8); /* parse_info_header */
3528
198
    dirac_uint( &bs ); /* major_version */
3529
198
    dirac_uint( &bs ); /* minor_version */
3530
198
    dirac_uint( &bs ); /* profile */
3531
198
    dirac_uint( &bs ); /* level */
3532
3533
198
    uint32_t u_video_format = dirac_uint( &bs ); /* index */
3534
198
    if( u_video_format >= u_dirac_vidfmt_frate )
3535
0
    {
3536
        /* don't know how to parse this ogg dirac stream */
3537
0
        return false;
3538
0
    }
3539
3540
198
    if( dirac_bool( &bs ) )
3541
27
    {
3542
27
        dirac_uint( &bs ); /* frame_width */
3543
27
        dirac_uint( &bs ); /* frame_height */
3544
27
    }
3545
3546
198
    if( dirac_bool( &bs ) )
3547
70
    {
3548
70
        dirac_uint( &bs ); /* chroma_format */
3549
70
    }
3550
3551
198
    if( dirac_bool( &bs ) )
3552
108
    {
3553
108
        p_stream->special.dirac.b_interlaced = dirac_uint( &bs ); /* scan_format */
3554
108
    }
3555
90
    else
3556
90
        p_stream->special.dirac.b_interlaced = false;
3557
3558
198
    uint32_t u_n = p_dirac_frate_tbl[pu_dirac_vidfmt_frate[u_video_format]].u_n;
3559
198
    uint32_t u_d = p_dirac_frate_tbl[pu_dirac_vidfmt_frate[u_video_format]].u_d;
3560
198
    u_d = __MAX( u_d, 1 );
3561
198
    if( dirac_bool( &bs ) )
3562
155
    {
3563
155
        uint32_t u_frame_rate_index = dirac_uint( &bs );
3564
155
        if( u_frame_rate_index >= u_dirac_frate_tbl )
3565
27
        {
3566
            /* something is wrong with this stream */
3567
27
            return false;
3568
27
        }
3569
128
        u_n = p_dirac_frate_tbl[u_frame_rate_index].u_n;
3570
128
        u_d = p_dirac_frate_tbl[u_frame_rate_index].u_d;
3571
128
        if( u_frame_rate_index == 0 )
3572
128
        {
3573
128
            u_n = dirac_uint( &bs ); /* frame_rate_numerator */
3574
128
            u_d = dirac_uint( &bs ); /* frame_rate_denominator */
3575
128
        }
3576
128
    }
3577
3578
171
    if( !u_n || !u_d )
3579
128
        return false;
3580
3581
    /*
3582
     * NB, OggDirac granulepos values are in units of 2*picturerate
3583
     * When picture_coding_mode = 0 (progressive),
3584
     * pt increments by two for each picture in display order.
3585
     * When picture_coding_mode = 1 (interlace),
3586
     * pt increments by one for each field in display order. */
3587
43
    date_Init( &p_stream->dts, 2 * u_n, u_d );
3588
3589
43
    return true;
3590
171
}
3591
3592
static bool Ogg_ReadOggSpotsHeader( logical_stream_t *p_stream,
3593
                                    ogg_packet *p_oggpacket )
3594
0
{
3595
0
    uint64_t i_granulerate_numerator;
3596
0
    uint64_t i_granulerate_denominator;
3597
0
    int i_major;
3598
0
    int i_minor;
3599
3600
0
    es_format_Change( &p_stream->fmt, VIDEO_ES, VLC_CODEC_OGGSPOTS );
3601
3602
    /* Signal that we want to keep a backup of the OggSpots
3603
     * stream headers. They will be used when switching between
3604
     * audio streams. */
3605
0
    p_stream->b_force_backup = true;
3606
3607
    /* Cheat and get additional info ;) */
3608
0
    if ( p_oggpacket->bytes != 52 )
3609
0
    {
3610
        /* The OggSpots header is always 52 bytes */
3611
0
        return false;
3612
0
    }
3613
3614
0
    i_major = GetWLE( &p_oggpacket->packet[ 8] ); /* major version num */
3615
0
    i_minor = GetWLE( &p_oggpacket->packet[10] ); /* minor version num */
3616
0
    if ( i_major != 0 || i_minor != 1 )
3617
0
    {
3618
0
        return false;
3619
0
    }
3620
3621
    /* Granule rate */
3622
0
    i_granulerate_numerator   = GetQWLE( &p_oggpacket->packet[12] );
3623
0
    i_granulerate_denominator = GetQWLE( &p_oggpacket->packet[20] );
3624
0
    if ( i_granulerate_numerator == 0 || i_granulerate_denominator == 0 )
3625
0
    {
3626
0
        return false;
3627
0
    }
3628
3629
    /* The OggSpots spec contained an error and there are implementations out
3630
     * there that used the wrong value. So we detect that case and switch
3631
     * numerator and denominator in that case */
3632
0
    if ( i_granulerate_numerator == 1 && i_granulerate_denominator == 30 )
3633
0
    {
3634
0
        i_granulerate_numerator   = 30;
3635
0
        i_granulerate_denominator = 1;
3636
0
    }
3637
3638
    /* Normalize granulerate */
3639
0
    vlc_ureduce(&p_stream->fmt.video.i_frame_rate,
3640
0
                &p_stream->fmt.video.i_frame_rate_base,
3641
0
                i_granulerate_numerator, i_granulerate_denominator, 0);
3642
3643
0
    date_Init( &p_stream->dts, p_stream->fmt.video.i_frame_rate,
3644
0
                               p_stream->fmt.video.i_frame_rate_base );
3645
3646
0
    p_stream->i_granule_shift = p_oggpacket->packet[28];
3647
3648
    return true;
3649
0
}