]> git.sesse.net Git - vlc/blobdiff - modules/demux/ogg.c
demux: ogg: remove discontinuity flag
[vlc] / modules / demux / ogg.c
index 67e226a98e18cf38a0486887b7ab3615cfab207e..b11a82e2d1b95195905a0aa8510d1db9337eb454 100644 (file)
@@ -112,10 +112,11 @@ static int  Control( demux_t *, int, va_list );
 
 /* Bitstream manipulation */
 static int  Ogg_ReadPage     ( demux_t *, ogg_page * );
-static void Ogg_UpdatePCR    ( logical_stream_t *, ogg_packet * );
+static void Ogg_UpdatePCR    ( demux_t *, logical_stream_t *, ogg_packet * );
 static void Ogg_DecodePacket ( demux_t *, logical_stream_t *, ogg_packet * );
 static int  Ogg_OpusPacketDuration( logical_stream_t *, ogg_packet * );
 
+static void Ogg_CreateES( demux_t *p_demux );
 static int Ogg_BeginningOfStream( demux_t *p_demux );
 static int Ogg_FindLogicalStreams( demux_t *p_demux );
 static void Ogg_EndOfStream( demux_t *p_demux );
@@ -194,6 +195,7 @@ static int Open( vlc_object_t * p_this )
         return VLC_ENOMEM;
 
     p_sys->i_length = -1;
+    p_sys->b_preparsing_done = false;
 
     /* Set exported functions */
     p_demux->pf_demux = Demux;
@@ -205,6 +207,10 @@ static int Open( vlc_object_t * p_this )
     /* */
     TAB_INIT( p_sys->i_seekpoints, p_sys->pp_seekpoints );
 
+
+    while ( !p_sys->b_preparsing_done && p_demux->pf_demux( p_demux ) > 0 )
+    {}
+
     return VLC_SUCCESS;
 }
 
@@ -224,8 +230,6 @@ static void Close( vlc_object_t *p_this )
     if( p_sys->p_old_stream )
         Ogg_LogicalStreamDelete( p_demux, p_sys->p_old_stream );
 
-    TAB_CLEAN( p_sys->i_seekpoints, p_sys->pp_seekpoints );
-
     free( p_sys );
 }
 
@@ -262,18 +266,39 @@ static int Demux( demux_t * p_demux )
                 TAB_CLEAN( p_sys->i_streams, p_sys->pp_stream );
             }
             Ogg_EndOfStream( p_demux );
+            p_sys->b_chained_boundary = true;
         }
 
         if( Ogg_BeginningOfStream( p_demux ) != VLC_SUCCESS )
             return 0;
 
-        /* Find the real duration */
-        stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_canseek );
-        if ( b_canseek )
-            Oggseek_ProbeEnd( p_demux );
-
         msg_Dbg( p_demux, "beginning of a group of logical streams" );
-        es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 );
+
+        if ( !p_sys->b_chained_boundary )
+        {
+            /* Find the real duration */
+            stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_canseek );
+            if ( b_canseek )
+                Oggseek_ProbeEnd( p_demux );
+            es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 );
+        }
+        else
+        {
+            es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
+            p_sys->b_chained_boundary = false;
+        }
+    }
+
+    if ( p_sys->b_preparsing_done )
+    {
+        for ( int i=0; i < p_sys->i_streams; i++ )
+        {
+            if ( !p_sys->pp_stream[i]->p_es )
+            {
+                Ogg_CreateES( p_demux );
+                break;
+            }
+        }
     }
 
     /*
@@ -302,19 +327,16 @@ static int Demux( demux_t * p_demux )
         {
             /* If we delayed restarting encoders/SET_ES_FMT for more
              * skeleton provided configuration */
-            if ( p_sys->p_skelstream && p_sys->p_skelstream->i_serial_no == ogg_page_serialno(&p_sys->current_page) )
+            if ( p_sys->p_skelstream )
             {
-                msg_Dbg( p_demux, "End of Skeleton" );
-                for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
+                if ( p_sys->p_skelstream->i_serial_no == ogg_page_serialno(&p_sys->current_page) )
                 {
-                    logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
-                    if ( p_stream->b_have_updated_format  )
+                    msg_Dbg( p_demux, "End of Skeleton" );
+                    p_sys->b_preparsing_done = true;
+                    for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
                     {
-                        p_stream->b_have_updated_format = false;
-                        if ( p_stream->p_skel ) Ogg_ApplySkeleton( p_stream );
-                        msg_Dbg( p_demux, "Resetting format for stream %d", i_stream );
-                        es_out_Control( p_demux->out, ES_OUT_SET_ES_FMT,
-                                        p_stream->p_es, &p_stream->fmt );
+                        logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
+                        Ogg_ApplySkeleton( p_stream );
                     }
                 }
             }
@@ -369,12 +391,12 @@ static int Demux( demux_t * p_demux )
 
         DemuxDebug(
             if ( p_stream->fmt.i_cat == VIDEO_ES )
-                msg_Dbg(p_demux, "DEMUX READ pageno %ld g%"PRId64" (%d packets) cont %d %ld bytes eos %d ",
+                msg_Dbg(p_demux, "DEMUX READ pageno %ld g%"PRId64" (%d packets) cont %d %ld bytes",
                     ogg_page_pageno( &p_sys->current_page ),
                     ogg_page_granulepos( &p_sys->current_page ),
                     ogg_page_packets( &p_sys->current_page ),
                     ogg_page_continued(&p_sys->current_page),
-                    p_sys->current_page.body_len, p_sys->i_eos )
+                    p_sys->current_page.body_len )
         );
 
         while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
@@ -422,7 +444,7 @@ static int Demux( demux_t * p_demux )
                 {
                     /* If synchro is re-initialized we need to drop all the packets
                          * until we find a new dated one. */
-                    Ogg_UpdatePCR( p_stream, &oggpacket );
+                    Ogg_UpdatePCR( p_demux, p_stream, &oggpacket );
                 }
 
                 if( p_stream->i_pcr >= 0 )
@@ -512,11 +534,22 @@ static int Demux( demux_t * p_demux )
     /* if a page was waiting, it's now processed */
     p_sys->b_page_waiting = false;
 
+    if ( p_sys->p_skelstream && !p_sys->p_skelstream->b_finished )
+        p_sys->b_preparsing_done = false;
+    else
+        p_sys->b_preparsing_done = true;
+
     p_sys->i_pcr = -1;
     for( i_stream = 0; i_stream < p_sys->i_streams; i_stream++ )
     {
         logical_stream_t *p_stream = p_sys->pp_stream[i_stream];
 
+        if ( p_sys->b_preparsing_done && p_stream->b_initializing )
+        {
+            /* We have 1 or more streams needing more than 1 page for preparsing */
+            p_sys->b_preparsing_done = false;
+        }
+
         if( p_stream->fmt.i_cat == SPU_ES )
             continue;
         if( p_stream->i_interpolated_pcr < 0 )
@@ -683,7 +716,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
             }
 
             assert( p_sys->i_length > 0 );
-            i64 = (mtime_t)(1000000.0 * p_sys->i_length * f );
+            i64 = CLOCK_FREQ * p_sys->i_length * f;
             Ogg_ResetStreamHelper( p_sys );
             if ( Oggseek_SeektoAbsolutetime( p_demux, p_stream, i64 ) >= 0 )
             {
@@ -716,7 +749,9 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
                 input_title_t *p_title = (*ppp_title)[0] = vlc_input_title_New();
                 for( int i = 0; i < p_sys->i_seekpoints; i++ )
                 {
-                    TAB_APPEND( p_title->i_seekpoint, p_title->seekpoint, p_sys->pp_seekpoints[i] );
+                    seekpoint_t *p_seekpoint_copy = vlc_seekpoint_Duplicate( p_sys->pp_seekpoints[i] );
+                    if ( likely( p_seekpoint_copy ) )
+                        TAB_APPEND( p_title->i_seekpoint, p_title->seekpoint, p_seekpoint_copy );
                 }
                 *pi_title_offset = 0;
                 *pi_seekpoint_offset = 0;
@@ -801,9 +836,10 @@ static int Ogg_ReadPage( demux_t *p_demux, ogg_page *p_oggpage )
  * Ogg_UpdatePCR: update the PCR (90kHz program clock reference) for the
  *                current stream.
  ****************************************************************************/
-static void Ogg_UpdatePCR( logical_stream_t *p_stream,
+static void Ogg_UpdatePCR( demux_t *p_demux, logical_stream_t *p_stream,
                            ogg_packet *p_oggpacket )
 {
+    demux_sys_t *p_ogg = p_demux->p_sys;
     p_stream->i_end_trim = 0;
 
     /* Convert the granulepos into a pcr */
@@ -838,10 +874,13 @@ static void Ogg_UpdatePCR( logical_stream_t *p_stream,
                 sample -= p_stream->i_pre_skip;
             else
                 sample = 0;
-            p_stream->i_pcr = sample * INT64_C(1000000) / p_stream->f_rate;
+            p_stream->i_pcr = sample * CLOCK_FREQ / p_stream->f_rate;
         }
 
-        p_stream->i_pcr += VLC_TS_0;
+        if ( !p_ogg->i_pcr_offset )
+            p_stream->i_pcr += VLC_TS_0;
+        else
+            p_stream->i_pcr += p_ogg->i_pcr_offset;
         p_stream->i_interpolated_pcr = p_stream->i_pcr;
     }
     else
@@ -853,7 +892,7 @@ static void Ogg_UpdatePCR( logical_stream_t *p_stream,
          * If we can't then don't touch the old value. */
         if( p_stream->fmt.i_cat == VIDEO_ES )
             /* 1 frame per packet */
-            p_stream->i_interpolated_pcr += (INT64_C(1000000) / p_stream->f_rate);
+            p_stream->i_interpolated_pcr += (CLOCK_FREQ / p_stream->f_rate);
         else if( p_stream->fmt.i_codec == VLC_CODEC_OPUS &&
                  p_stream->i_previous_granulepos >= 0 &&
                  ( duration =
@@ -868,13 +907,15 @@ static void Ogg_UpdatePCR( logical_stream_t *p_stream,
             else
                 sample = 0;
             p_stream->i_interpolated_pcr =
-                VLC_TS_0 + sample * INT64_C(1000000) / p_stream->f_rate;
+                VLC_TS_0 + sample * CLOCK_FREQ / p_stream->f_rate;
+            p_stream->i_interpolated_pcr += p_ogg->i_pcr_offset;
         }
         else if( p_stream->fmt.i_bitrate )
         {
             p_stream->i_interpolated_pcr +=
-                ( p_oggpacket->bytes * INT64_C(1000000) /
+                ( p_oggpacket->bytes * CLOCK_FREQ /
                   p_stream->fmt.i_bitrate / 8 );
+            p_stream->i_interpolated_pcr += p_ogg->i_pcr_offset;
         }
     }
     p_stream->i_previous_granulepos = p_oggpacket->granulepos;
@@ -922,8 +963,11 @@ static void Ogg_DecodePacket( demux_t *p_demux,
         p_oggpacket->packet[0] & PACKET_TYPE_BITS ) return;
 
     /* Check the ES is selected */
-    es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
-                    p_stream->p_es, &b_selected );
+    if ( !p_stream->p_es )
+        b_selected = true;
+    else
+        es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE,
+                        p_stream->p_es, &b_selected );
 
     if( p_stream->b_force_backup )
     {
@@ -1020,25 +1064,6 @@ static void Ogg_DecodePacket( demux_t *p_demux,
                 else
                     p_stream->fmt.i_extra = 0;
 
-                if( Ogg_LogicalStreamResetEsFormat( p_demux, p_stream ) )
-                {
-                    if ( p_ogg->p_skelstream )
-                    {
-                        /* We delay until eos is reached on skeleton.
-                         * There should only be headers, as no data page is
-                         * allowed before skeleton's eos.
-                         * Skeleton data is appended to fmt on skeleton eos.
-                         */
-                        p_stream->b_have_updated_format = true;
-                    }
-                    else
-                    {
-                        /* Otherwise we set config from first headers */
-                        es_out_Control( p_demux->out, ES_OUT_SET_ES_FMT,
-                                        p_stream->p_es, &p_stream->fmt );
-                    }
-                }
-
                 if( p_stream->i_headers > 0 )
                     Ogg_ExtractMeta( p_demux, & p_stream->fmt,
                                      p_stream->p_headers, p_stream->i_headers );
@@ -1050,6 +1075,8 @@ static void Ogg_DecodePacket( demux_t *p_demux,
 
         b_selected = false; /* Discard the header packet */
     }
+    else
+        p_stream->b_initializing = false;
 
     /* Convert the pcr into a pts */
     if( p_stream->fmt.i_codec == VLC_CODEC_VORBIS ||
@@ -1059,19 +1086,7 @@ static void Ogg_DecodePacket( demux_t *p_demux,
     {
         if( p_stream->i_pcr >= 0 )
         {
-            /* This is for streams where the granulepos of the header packets
-             * doesn't match these of the data packets (eg. ogg web radios). */
-            if( p_stream->i_previous_pcr == 0 &&
-                p_stream->i_pcr  > 3 * DEFAULT_PTS_DELAY )
-            {
-
-                /* Call the pace control */
-                es_out_Control( p_demux->out, ES_OUT_SET_PCR,
-                                VLC_TS_0 + p_stream->i_pcr );
-            }
-
             p_stream->i_previous_pcr = p_stream->i_pcr;
-
             /* The granulepos is the end date of the sample */
             i_pts = p_stream->i_pcr;
         }
@@ -1079,24 +1094,7 @@ static void Ogg_DecodePacket( demux_t *p_demux,
 
     /* Convert the granulepos into the next pcr */
     i_interpolated_pts = p_stream->i_interpolated_pcr;
-    Ogg_UpdatePCR( p_stream, p_oggpacket );
-
-    /* SPU streams are typically discontinuous, do not mind large gaps */
-    if( p_stream->fmt.i_cat != SPU_ES )
-    {
-        if( p_stream->i_pcr >= 0 )
-        {
-            /* This is for streams where the granulepos of the header packets
-             * doesn't match these of the data packets (eg. ogg web radios). */
-            if( p_stream->i_previous_pcr == 0 &&
-                p_stream->i_pcr  > 3 * DEFAULT_PTS_DELAY )
-            {
-
-                /* Call the pace control */
-                es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_stream->i_pcr );
-            }
-        }
-    }
+    Ogg_UpdatePCR( p_demux, p_stream, p_oggpacket );
 
     if( p_stream->fmt.i_codec != VLC_CODEC_VORBIS &&
         p_stream->fmt.i_codec != VLC_CODEC_SPEEX &&
@@ -1141,7 +1139,7 @@ static void Ogg_DecodePacket( demux_t *p_demux,
                 {
                     i_pts = VLC_TS_0 + (p_stream->i_previous_granulepos
                         - p_block->i_nb_samples - p_stream->i_pre_skip) *
-                        INT64_C(1000000) / p_stream->f_rate;
+                        CLOCK_FREQ / p_stream->f_rate;
                 }
                 p_stream->i_skip_frames = 0;
             }
@@ -1196,7 +1194,7 @@ static void Ogg_DecodePacket( demux_t *p_demux,
 
         /* granulepos for dirac is possibly broken, this value should be ignored */
         if( -1 != p_oggpacket->granulepos )
-            p_block->i_pts = u_pnum * INT64_C(1000000) / p_stream->f_rate / 2;
+            p_block->i_pts = u_pnum * CLOCK_FREQ / p_stream->f_rate / 2;
     }
     else
     {
@@ -1254,6 +1252,7 @@ static void Ogg_DecodePacket( demux_t *p_demux,
             p_block->i_buffer = 0;
     }
 
+
     if( p_stream->fmt.i_codec == VLC_CODEC_TARKIN )
     {
         /* FIXME: the biggest hack I've ever done */
@@ -1265,7 +1264,18 @@ static void Ogg_DecodePacket( demux_t *p_demux,
     memcpy( p_block->p_buffer, p_oggpacket->packet + i_header_len,
             p_oggpacket->bytes - i_header_len );
 
-    es_out_Send( p_demux->out, p_stream->p_es, p_block );
+    if ( p_stream->p_es )
+    {
+        /* Because ES creation is delayed for preparsing */
+        if ( p_stream->p_preparse_block )
+        {
+            es_out_Send( p_demux->out, p_stream->p_es, p_stream->p_preparse_block );
+            p_stream->p_preparse_block = NULL;
+        }
+        es_out_Send( p_demux->out, p_stream->p_es, p_block );
+    }
+    else
+        block_ChainAppend( & p_stream->p_preparse_block, p_block );
 }
 
 /* Re-implemented to avoid linking against libopus from the demuxer. */
@@ -1351,6 +1361,7 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
 
                 es_format_Init( &p_stream->fmt, 0, 0 );
                 es_format_Init( &p_stream->fmt_old, 0, 0 );
+                p_stream->b_initializing = true;
 
                 /* Setup the logical stream */
                 p_stream->i_serial_no = ogg_page_serialno( &p_ogg->current_page );
@@ -1680,7 +1691,7 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
                             p_stream->fmt.i_extra = i_extra_size;
                             p_stream->fmt.p_extra = malloc( p_stream->fmt.i_extra );
                             if( p_stream->fmt.p_extra )
-                                memcpy( p_stream->fmt.p_extra, st + 1,
+                                memcpy( p_stream->fmt.p_extra, oggpacket.packet + 57,
                                         p_stream->fmt.i_extra );
                             else
                                 p_stream->fmt.i_extra = 0;
@@ -1756,7 +1767,7 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
                 }
 
                 /* we'll need to get all headers */
-                p_ogg->pp_stream[i_stream]->b_initializing |= p_ogg->pp_stream[i_stream]->b_force_backup;
+                p_ogg->pp_stream[i_stream]->b_initializing &= p_ogg->pp_stream[i_stream]->b_force_backup;
 
                 if( Ogg_ReadPage( p_demux, &p_ogg->current_page ) != VLC_SUCCESS )
                     return VLC_EGENERIC;
@@ -1782,6 +1793,67 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
     return VLC_EGENERIC;
 }
 
+/****************************************************************************
+ * Ogg_CreateES: Creates all Elementary streams once headers are parsed
+ ****************************************************************************/
+static void Ogg_CreateES( demux_t *p_demux )
+{
+    demux_sys_t *p_ogg = p_demux->p_sys;
+    logical_stream_t *p_old_stream = p_ogg->p_old_stream;
+    int i_stream;
+
+    for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ )
+    {
+        logical_stream_t *p_stream = p_ogg->pp_stream[i_stream];
+
+        if ( p_stream->p_es == NULL )
+        {
+            /* Better be safe than sorry when possible with ogm */
+            if( p_stream->fmt.i_codec == VLC_CODEC_MPGA ||
+                p_stream->fmt.i_codec == VLC_CODEC_A52 )
+                p_stream->fmt.b_packetized = false;
+
+            /* Try first to reuse an old ES */
+            if( p_old_stream &&
+                p_old_stream->fmt.i_cat == p_stream->fmt.i_cat &&
+                p_old_stream->fmt.i_codec == p_stream->fmt.i_codec )
+            {
+                msg_Dbg( p_demux, "will reuse old stream to avoid glitch" );
+
+                p_stream->p_es = p_old_stream->p_es;
+                p_stream->b_finished = false;
+                p_stream->b_reinit = false;
+                p_stream->b_initializing = false;
+                es_format_Copy( &p_stream->fmt_old, &p_old_stream->fmt );
+
+                p_old_stream->p_es = NULL;
+                p_old_stream = NULL;
+                es_out_Control( p_demux->out, ES_OUT_SET_ES_FMT,
+                                p_stream->p_es, &p_stream->fmt );
+            }
+            else
+            {
+                p_stream->p_es = es_out_Add( p_demux->out, &p_stream->fmt );
+            }
+
+            // TODO: something to do here ?
+            if( p_stream->fmt.i_codec == VLC_CODEC_CMML )
+            {
+                /* Set the CMML stream active */
+                es_out_Control( p_demux->out, ES_OUT_SET_ES, p_stream->p_es );
+            }
+        }
+    }
+
+    if( p_ogg->p_old_stream )
+    {
+        if( p_ogg->p_old_stream->p_es )
+            msg_Dbg( p_demux, "old stream not reused" );
+        Ogg_LogicalStreamDelete( p_demux, p_ogg->p_old_stream );
+        p_ogg->p_old_stream = NULL;
+    }
+}
+
 /****************************************************************************
  * Ogg_BeginningOfStream: Look for Beginning of Stream ogg pages and add
  *                        Elementary streams.
@@ -1789,7 +1861,6 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
 static int Ogg_BeginningOfStream( demux_t *p_demux )
 {
     demux_sys_t *p_ogg = p_demux->p_sys  ;
-    logical_stream_t *p_old_stream = p_ogg->p_old_stream;
     int i_stream;
 
     /* Find the logical streams embedded in the physical stream and
@@ -1811,37 +1882,6 @@ static int Ogg_BeginningOfStream( demux_t *p_demux )
         /* initialise kframe index */
         p_stream->idx=NULL;
 
-        /* Try first to reuse an old ES */
-        if( p_old_stream &&
-            p_old_stream->fmt.i_cat == p_stream->fmt.i_cat &&
-            p_old_stream->fmt.i_codec == p_stream->fmt.i_codec )
-        {
-            msg_Dbg( p_demux, "will reuse old stream to avoid glitch" );
-
-            p_stream->p_es = p_old_stream->p_es;
-            es_format_Copy( &p_stream->fmt_old, &p_old_stream->fmt );
-
-            p_old_stream->p_es = NULL;
-            p_old_stream = NULL;
-        }
-
-        if( !p_stream->p_es )
-        {
-            /* Better be safe than sorry when possible with ogm */
-            if( p_stream->fmt.i_codec == VLC_CODEC_MPGA ||
-                p_stream->fmt.i_codec == VLC_CODEC_A52 )
-                p_stream->fmt.b_packetized = false;
-
-            p_stream->p_es = es_out_Add( p_demux->out, &p_stream->fmt );
-        }
-
-        // TODO: something to do here ?
-        if( p_stream->fmt.i_codec == VLC_CODEC_CMML )
-        {
-            /* Set the CMML stream active */
-            es_out_Control( p_demux->out, ES_OUT_SET_ES, p_stream->p_es );
-        }
-
         if ( p_stream->fmt.i_bitrate == 0  &&
              ( p_stream->fmt.i_cat == VIDEO_ES ||
                p_stream->fmt.i_cat == AUDIO_ES ) )
@@ -1854,15 +1894,6 @@ static int Ogg_BeginningOfStream( demux_t *p_demux )
         p_stream->b_reinit = false;
     }
 
-    if( p_ogg->p_old_stream )
-    {
-        if( p_ogg->p_old_stream->p_es )
-            msg_Dbg( p_demux, "old stream not reused" );
-        Ogg_LogicalStreamDelete( p_demux, p_ogg->p_old_stream );
-        p_ogg->p_old_stream = NULL;
-    }
-
-
     /* get total frame count for video stream; we will need this for seeking */
     p_ogg->i_total_frames = 0;
 
@@ -1887,11 +1918,21 @@ static void Ogg_EndOfStream( demux_t *p_demux )
     p_ogg->pp_stream = NULL;
     p_ogg->skeleton.major = 0;
     p_ogg->skeleton.minor = 0;
+    p_ogg->b_preparsing_done = false;
+    p_ogg->i_pcr_offset = p_ogg->i_pcr;
 
     /* */
     if( p_ogg->p_meta )
         vlc_meta_Delete( p_ogg->p_meta );
     p_ogg->p_meta = NULL;
+
+    for ( int i=0; i < p_ogg->i_seekpoints; i++ )
+    {
+        if ( p_ogg->pp_seekpoints[i] )
+            vlc_seekpoint_Delete( p_ogg->pp_seekpoints[i] );
+    }
+    TAB_CLEAN( p_ogg->i_seekpoints, p_ogg->pp_seekpoints );
+    p_ogg->i_seekpoints = 0;
 }
 
 /**
@@ -1918,6 +1959,13 @@ static void Ogg_LogicalStreamDelete( demux_t *p_demux, logical_stream_t *p_strea
     if ( p_demux->p_sys->p_skelstream == p_stream )
         p_demux->p_sys->p_skelstream = NULL;
 
+    /* Shouldn't happen */
+    if ( unlikely( p_stream->p_preparse_block ) )
+    {
+        block_ChainRelease( p_stream->p_preparse_block );
+        p_stream->p_preparse_block = NULL;
+    }
+
     free( p_stream );
 }
 /**
@@ -2184,6 +2232,7 @@ static void Ogg_ReadTheoraHeader( logical_stream_t *p_stream,
 
     i_fps_numerator = bs_read( &bitstream, 32 );
     i_fps_denominator = bs_read( &bitstream, 32 );
+    i_fps_denominator = __MAX( i_fps_denominator, 1 );
     bs_read( &bitstream, 24 ); /* aspect_numerator */
     bs_read( &bitstream, 24 ); /* aspect_denominator */
 
@@ -2597,7 +2646,7 @@ static void Ogg_ReadSkeletonBones( demux_t *p_demux, ogg_packet *p_oggpacket )
 
 /* Unpacks the 7bit variable encoding used in skeleton indexes */
 unsigned const char * Read7BitsVariableLE( unsigned const char *p_begin,
-                                           unsigned const char const *p_end,
+                                           unsigned const char *p_end,
                                            uint64_t *pi_value )
 {
     int i_shift = 0;
@@ -2642,7 +2691,7 @@ static void Ogg_ReadSkeletonIndex( demux_t *p_demux, ogg_packet *p_oggpacket )
     p_stream->p_skel->i_indexfirstnum = GetQWLE( &p_oggpacket->packet[24] );
     p_stream->p_skel->i_indexlastnum = GetQWLE( &p_oggpacket->packet[32] );
     unsigned const char *p_fwdbyte = &p_oggpacket->packet[42];
-    unsigned const char const *p_boundary = p_oggpacket->packet + p_oggpacket->bytes;
+    unsigned const char *p_boundary = p_oggpacket->packet + p_oggpacket->bytes;
     uint64_t i_offset = 0;
     uint64_t i_time = 0;
     uint64_t i_keypoints_found = 0;