X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Fogg.c;h=6b044fc3269e6cb36750c4c831342f67344842f8;hb=6f768ab47bc2afdcb20b4a5e39e620f7f58e2256;hp=6196ebabf1fd12b1a265e43bed08ca2f64992239;hpb=f90b7fec4f984a41ada5cef87e7fe39a393b558a;p=vlc diff --git a/modules/demux/ogg.c b/modules/demux/ogg.c index 6196ebabf1..6b044fc326 100644 --- a/modules/demux/ogg.c +++ b/modules/demux/ogg.c @@ -43,6 +43,7 @@ #include "vorbis.h" #include "kate_categories.h" #include "ogg.h" +#include "oggseek.h" /***************************************************************************** * Module descriptor @@ -104,7 +105,6 @@ typedef struct } sh; } stream_header_t; -#define OGG_BLOCK_SIZE 4096 /* Some defines from OggDS */ #define PACKET_TYPE_HEADER 0x01 @@ -214,9 +214,9 @@ static void Close( vlc_object_t *p_this ) static int Demux( demux_t * p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; - ogg_page oggpage; ogg_packet oggpacket; int i_stream; + bool b_skipping = false; if( p_sys->i_eos == p_sys->i_streams ) @@ -261,11 +261,11 @@ static int Demux( demux_t * p_demux ) /* * Demux an ogg page from the stream */ - if( Ogg_ReadPage( p_demux, &oggpage ) != VLC_SUCCESS ) + if( Ogg_ReadPage( p_demux, &p_sys->current_page ) != VLC_SUCCESS ) return 0; /* EOF */ /* Test for End of Stream */ - if( ogg_page_eos( &oggpage ) ) + if( ogg_page_eos( &p_sys->current_page ) ) p_sys->i_eos++; } @@ -278,10 +278,10 @@ static int Demux( demux_t * p_demux ) if( !p_sys->b_page_waiting ) { if( p_sys->i_streams == 1 && - ogg_page_serialno( &oggpage ) != p_stream->os.serialno ) + ogg_page_serialno( &p_sys->current_page ) != p_stream->os.serialno ) { msg_Err( p_demux, "Broken Ogg stream (serialno) mismatch" ); - ogg_stream_reset_serialno( &p_stream->os, ogg_page_serialno( &oggpage ) ); + ogg_stream_reset_serialno( &p_stream->os, ogg_page_serialno( &p_sys->current_page ) ); p_stream->b_reinit = true; p_stream->i_pcr = -1; @@ -289,8 +289,11 @@ static int Demux( demux_t * p_demux ) es_out_Control( p_demux->out, ES_OUT_RESET_PCR ); } - if( ogg_stream_pagein( &p_stream->os, &oggpage ) != 0 ) + if( ogg_stream_pagein( &p_stream->os, &p_sys->current_page ) != 0 ) + { continue; + } + } while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 ) @@ -316,8 +319,17 @@ static int Demux( demux_t * p_demux ) { p_stream->i_secondary_header_packets = 0; } + + /* update start of data pointer */ + p_stream->i_data_start = stream_Tell( p_demux->s ); + } + /* If any streams have i_skip_frames, only decode (pre-roll) + * for those streams */ + if ( b_skipping && p_stream->i_skip_frames == 0 ) continue; + + if( p_stream->b_reinit ) { /* If synchro is re-initialized we need to drop all the packets @@ -376,7 +388,7 @@ static int Demux( demux_t * p_demux ) p_sys->i_pcr = p_stream->i_interpolated_pcr; } - if( p_sys->i_pcr >= 0 ) + if( p_sys->i_pcr >= 0 && ! b_skipping ) es_out_Control( p_demux->out, ES_OUT_SET_PCR, VLC_TS_0 + p_sys->i_pcr ); return 1; @@ -457,9 +469,9 @@ static int Ogg_ReadPage( demux_t *p_demux, ogg_page *p_oggpage ) while( ogg_sync_pageout( &p_ogg->oy, p_oggpage ) != 1 ) { - p_buffer = ogg_sync_buffer( &p_ogg->oy, OGG_BLOCK_SIZE ); + p_buffer = ogg_sync_buffer( &p_ogg->oy, OGGSEEK_BYTES_TO_READ ); - i_read = stream_Read( p_demux->s, p_buffer, OGG_BLOCK_SIZE ); + i_read = stream_Read( p_demux->s, p_buffer, OGGSEEK_BYTES_TO_READ ); if( i_read <= 0 ) return VLC_EGENERIC; @@ -488,7 +500,7 @@ static void Ogg_UpdatePCR( logical_stream_t *p_stream, ( iframe << p_stream->i_granule_shift ); p_stream->i_pcr = ( iframe + pframe - p_stream->i_keyframe_offset ) - * INT64_C(1000000) / p_stream->f_rate; + * INT64_C(1000000) / p_stream->f_rate; } else if( p_stream->fmt.i_codec == VLC_CODEC_DIRAC ) { @@ -729,6 +741,15 @@ static void Ogg_DecodePacket( demux_t *p_demux, if( !( p_block = block_New( p_demux, p_oggpacket->bytes ) ) ) return; + + /* may need to preroll video frames after a seek */ + if ( p_stream->i_skip_frames > 0 ) + { + p_block->i_flags |= BLOCK_FLAG_PREROLL; + p_stream->i_skip_frames--; + } + + /* Normalize PTS */ if( i_pts == 0 ) i_pts = VLC_TS_0; else if( i_pts == -1 && i_interpolated_pts == 0 ) i_pts = VLC_TS_0; @@ -759,6 +780,8 @@ static void Ogg_DecodePacket( demux_t *p_demux, p_block->i_dts = p_stream->i_pcr; p_block->i_pts = VLC_TS_INVALID; /* NB, OggDirac granulepos values are in units of 2*picturerate */ + + /* 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; } @@ -839,17 +862,21 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux ) { demux_sys_t *p_ogg = p_demux->p_sys ; ogg_packet oggpacket; - ogg_page oggpage; int i_stream; - while( Ogg_ReadPage( p_demux, &oggpage ) == VLC_SUCCESS ) + p_ogg->i_total_length = stream_Size ( p_demux->s ); + msg_Dbg( p_demux, "File length is %"PRId64" bytes", p_ogg->i_total_length ); + + + while( Ogg_ReadPage( p_demux, &p_ogg->current_page ) == VLC_SUCCESS ) { - if( ogg_page_bos( &oggpage ) ) + + if( ogg_page_bos( &p_ogg->current_page ) ) { /* All is wonderful in our fine fine little world. * We found the beginning of our first logical stream. */ - while( ogg_page_bos( &oggpage ) ) + while( ogg_page_bos( &p_ogg->current_page ) ) { logical_stream_t *p_stream; @@ -864,17 +891,20 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux ) p_stream->i_secondary_header_packets = 0; p_stream->i_keyframe_offset = 0; + p_stream->i_skip_frames = 0; + + p_stream->i_data_start = 0; es_format_Init( &p_stream->fmt, 0, 0 ); es_format_Init( &p_stream->fmt_old, 0, 0 ); /* Setup the logical stream */ - p_stream->i_serial_no = ogg_page_serialno( &oggpage ); + p_stream->i_serial_no = ogg_page_serialno( &p_ogg->current_page ); ogg_stream_init( &p_stream->os, p_stream->i_serial_no ); /* Extract the initial header from the first page and verify * the codec type of this Ogg bitstream */ - if( ogg_stream_pagein( &p_stream->os, &oggpage ) < 0 ) + if( ogg_stream_pagein( &p_stream->os, &p_ogg->current_page ) < 0 ) { /* error. stream version mismatch perhaps */ msg_Err( p_demux, "error reading first page of " @@ -947,12 +977,12 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux ) } /* Check for Dirac header */ else if( ( oggpacket.bytes >= 5 && - ! memcmp( oggpacket.packet, "BBCD\x00", 5 ) ) || - ( oggpacket.bytes >= 9 && - ! memcmp( oggpacket.packet, "KW-DIRAC\x00", 9 ) ) ) - { - if( Ogg_ReadDiracHeader( p_stream, &oggpacket ) ) - msg_Dbg( p_demux, "found dirac header" ); + ! memcmp( oggpacket.packet, "BBCD\x00", 5 ) ) || + ( oggpacket.bytes >= 9 && + ! memcmp( oggpacket.packet, "KW-DIRAC\x00", 9 ) ) ) + { + if( Ogg_ReadDiracHeader( p_stream, &oggpacket ) ) + msg_Dbg( p_demux, "found dirac header" ); else { msg_Warn( p_demux, "found dirac header isn't decodable" ); @@ -1254,7 +1284,7 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux ) p_ogg->i_streams--; } - if( Ogg_ReadPage( p_demux, &oggpage ) != VLC_SUCCESS ) + if( Ogg_ReadPage( p_demux, &p_ogg->current_page ) != VLC_SUCCESS ) return VLC_EGENERIC; } @@ -1274,7 +1304,7 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux ) for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ ) { if( ogg_stream_pagein( &p_ogg->pp_stream[i_stream]->os, - &oggpage ) == 0 ) + &p_ogg->current_page ) == 0 ) { p_ogg->b_page_waiting = true; break; @@ -1314,6 +1344,9 @@ static int Ogg_BeginningOfStream( demux_t *p_demux ) p_stream->p_es = NULL; + /* 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 && @@ -1359,6 +1392,11 @@ static int Ogg_BeginningOfStream( demux_t *p_demux ) 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; + return VLC_SUCCESS; } @@ -1399,6 +1437,11 @@ static void Ogg_LogicalStreamDelete( demux_t *p_demux, logical_stream_t *p_strea es_format_Clean( &p_stream->fmt_old ); es_format_Clean( &p_stream->fmt ); + if ( p_stream->idx != NULL) + { + oggseek_index_entries_free( p_stream->idx ); + } + free( p_stream ); } /** @@ -1791,7 +1834,7 @@ static void Ogg_ReadAnnodexHeader( vlc_object_t *p_this, p_stream->b_force_backup = 1; } - else if( !strncmp(content_type_string, "audio/x-speex", 14) ) + else if( !strncmp(content_type_string, "audio/x-speex", 13) ) { p_stream->fmt.i_cat = AUDIO_ES; p_stream->fmt.i_codec = VLC_CODEC_SPEEX; @@ -1805,14 +1848,14 @@ static void Ogg_ReadAnnodexHeader( vlc_object_t *p_this, p_stream->b_force_backup = 1; } - else if( !strncmp(content_type_string, "video/x-xvid", 14) ) + else if( !strncmp(content_type_string, "video/x-xvid", 12) ) { p_stream->fmt.i_cat = VIDEO_ES; p_stream->fmt.i_codec = VLC_FOURCC( 'x','v','i','d' ); p_stream->b_force_backup = 1; } - else if( !strncmp(content_type_string, "video/mpeg", 14) ) + else if( !strncmp(content_type_string, "video/mpeg", 10) ) { /* n.b. MPEG streams are unsupported right now */ p_stream->fmt.i_cat = VIDEO_ES;