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