From d7ba3f3f8499e95a4a7011f54dc59208852e834c Mon Sep 17 00:00:00 2001 From: "ogg.k.ogg.k" Date: Sat, 25 Jul 2009 15:25:53 +0100 Subject: [PATCH] reconstruct Theora granpos Signed-off-by: Laurent Aimar --- modules/codec/theora.c | 5 +++++ modules/demux/ogg.c | 6 ++++++ modules/mux/ogg.c | 34 +++++++++++++++++----------------- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/modules/codec/theora.c b/modules/codec/theora.c index 4faf908b63..83c4a54581 100644 --- a/modules/codec/theora.c +++ b/modules/codec/theora.c @@ -818,6 +818,11 @@ static block_t *Encode( encoder_t *p_enc, picture_t *p_pict ) memcpy( p_block->p_buffer, oggpacket.packet, oggpacket.bytes ); p_block->i_dts = p_block->i_pts = p_pict->date; + if( theora_packet_iskeyframe( &oggpacket ) ) + { + p_block->i_flags |= BLOCK_FLAG_TYPE_I; + } + return p_block; } diff --git a/modules/demux/ogg.c b/modules/demux/ogg.c index 5e50b7a552..6387e12409 100644 --- a/modules/demux/ogg.c +++ b/modules/demux/ogg.c @@ -806,7 +806,13 @@ static void Ogg_DecodePacket( demux_t *p_demux, p_block->i_length = 0; } else if( p_stream->fmt.i_codec == VLC_CODEC_THEORA ) + { p_block->i_dts = p_block->i_pts = i_pts; + if( (p_oggpacket->granulepos & ((1<i_granule_shift)-1)) == 0 ) + { + p_block->i_flags |= BLOCK_FLAG_TYPE_I; + } + } else if( p_stream->fmt.i_codec == VLC_CODEC_DIRAC ) { ogg_int64_t dts = p_oggpacket->granulepos >> 31; diff --git a/modules/mux/ogg.c b/modules/mux/ogg.c index 373637167b..abe139b731 100644 --- a/modules/mux/ogg.c +++ b/modules/mux/ogg.c @@ -179,8 +179,10 @@ typedef struct int i_packet_no; int i_serial_no; int i_keyframe_granule_shift; /* Theora only */ - int i_last_keyframe; /* dirac and eventually theora */ + int i_last_keyframe; /* dirac and theora */ + int i_num_frames; /* Theora only */ uint64_t u_last_granulepos; /* Used for correct EOS page */ + int64_t i_num_keyframes; ogg_stream_state os; oggds_header_t *p_oggds_header; @@ -326,6 +328,9 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input ) p_stream->i_fourcc = p_input->p_fmt->i_codec; p_stream->i_serial_no = p_sys->i_next_serial_no++; p_stream->i_packet_no = 0; + p_stream->i_last_keyframe = 0; + p_stream->i_num_keyframes = 0; + p_stream->i_num_frames = 0; p_stream->p_oggds_header = 0; @@ -654,17 +659,8 @@ static block_t *OggCreateHeader( sout_mux_t *p_mux ) /* Get keyframe_granule_shift for theora granulepos calculation */ if( p_stream->i_fourcc == VLC_CODEC_THEORA ) { - int i_keyframe_frequency_force = - 1 << ((op.packet[40] << 6 >> 3) | (op.packet[41] >> 5)); - - /* granule_shift = i_log( frequency_force -1 ) */ - p_stream->i_keyframe_granule_shift = 0; - i_keyframe_frequency_force--; - while( i_keyframe_frequency_force ) - { - p_stream->i_keyframe_granule_shift++; - i_keyframe_frequency_force >>= 1; - } + p_stream->i_keyframe_granule_shift = + ( (op.packet[40] & 0x03) << 3 ) | ( (op.packet[41] & 0xe0) >> 5 ); } } else if( p_stream->i_fourcc == VLC_CODEC_DIRAC ) @@ -1002,11 +998,15 @@ static int MuxBlock( sout_mux_t *p_mux, sout_input_t *p_input ) { if( p_stream->i_fourcc == VLC_CODEC_THEORA ) { - /* FIXME, we assume only keyframes */ - op.granulepos = ( ( p_data->i_dts - p_sys->i_start_dts ) * - p_input->p_fmt->video.i_frame_rate / - p_input->p_fmt->video.i_frame_rate_base / - INT64_C(1000000) ) << p_stream->i_keyframe_granule_shift; + p_stream->i_num_frames++; + if( p_data->i_flags & BLOCK_FLAG_TYPE_I ) + { + p_stream->i_num_keyframes++; + p_stream->i_last_keyframe = p_stream->i_num_frames; + } + + op.granulepos = (p_stream->i_last_keyframe << p_stream->i_keyframe_granule_shift ) + | (p_stream->i_num_frames-p_stream->i_last_keyframe); } else if( p_stream->i_fourcc == VLC_CODEC_DIRAC ) { -- 2.39.2