Commit 4654ab23 authored by G Finch's avatar G Finch Committed by Ilkka Ollakka

Ogg-seek-new-logic-generic-changes

Signed-off-by: default avatarIlkka Ollakka <ileoo@videolan.org>
parent f90b7fec
SUBDIRS = asf avformat avi mkv mp4 mpeg playlist
SOURCES_flacsys = flac.c
SOURCES_ogg = ogg.c ogg.h vorbis.h kate_categories.c kate_categories.h xiph.h
SOURCES_ogg = ogg.c ogg.h oggseek.c oggseek.h vorbis.h kate_categories.c \
kate_categories.h xiph.h
SOURCES_demuxdump = demuxdump.c
SOURCES_rawdv = rawdv.c
SOURCES_rawvid = rawvid.c
......
......@@ -43,6 +43,7 @@
#include "vorbis.h"
#include "kate_categories.h"
#include "ogg.h"
#include "oggseek.h"
/*****************************************************************************
* Module descriptor
......@@ -217,6 +218,7 @@ static int Demux( demux_t * p_demux )
ogg_page oggpage;
ogg_packet oggpacket;
int i_stream;
bool b_skipping = false;
if( p_sys->i_eos == p_sys->i_streams )
......@@ -290,9 +292,12 @@ static int Demux( demux_t * p_demux )
}
if( ogg_stream_pagein( &p_stream->os, &oggpage ) != 0 )
{
continue;
}
}
while( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
{
/* Read info from any secondary header packets, if there are any */
......@@ -316,8 +321,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 +390,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;
......@@ -729,6 +743,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 +782,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;
}
......@@ -842,6 +867,10 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
ogg_page oggpage;
int i_stream;
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, &oggpage ) == VLC_SUCCESS )
{
if( ogg_page_bos( &oggpage ) )
......@@ -864,6 +893,9 @@ 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 );
......@@ -1314,6 +1346,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 +1394,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 +1439,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 );
}
/**
......
......@@ -69,6 +69,15 @@ typedef struct logical_stream_s
/* offset of first keyframe for theora; can be 0 or 1 depending on version number */
int64_t i_keyframe_offset;
/* keyframe index for seeking, created as we discover keyframes */
demux_index_entry_t *idx;
/* skip some frames after a seek */
int i_skip_frames;
/* data start offset (absolute) in bytes */
int64_t i_data_start;
/* kate streams have the number of headers in the ID header */
int i_kate_num_headers;
......@@ -105,6 +114,18 @@ struct demux_sys_t
/* after reading all headers, the first data page is stuffed into the relevant stream, ready to use */
bool b_page_waiting;
/* count of total frames in video stream */
int64_t i_total_frames;
/* length of file in bytes */
int64_t i_total_length;
/* offset position in file (for reading) */
int64_t i_input_position;
/* current page being parsed */
ogg_page current_page;
mtime_t i_st_pts;
......
This diff is collapsed.
/*****************************************************************************
* oggseek.h : ogg seeking functions for ogg demuxer vlc
*****************************************************************************
* Copyright (C) 2008 - 2010 Gabriel Finch <salsaman@gmail.com>
*
* Authors: Gabriel Finch <salsaman@gmail.com>
* adapted from: http://lives.svn.sourceforge.net/viewvc/lives/trunk/lives-plugins
* /plugins/decoders/ogg_theora_decoder.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#define PAGE_HEADER_BYTES 27
#define OGGSEEK_BYTES_TO_READ 8500
/* index entries are structured as follows:
* - for theora, highest granulepos -> pagepos (bytes) where keyframe begins
* - for dirac, kframe (sync point) -> pagepos of sequence start (?)
*/
/* this is typedefed to demux_index_entry_t in ogg.h */
struct oggseek_index_entry
{
demux_index_entry_t *p_next;
demux_index_entry_t *p_prev;
/* value is highest granulepos for theora, sync frame for dirac */
int64_t i_value;
int64_t i_pagepos;
/* not used for theora because the granulepos tells us this */
int64_t i_pagepos_end;
};
void oggseek_index_entries_free ( demux_index_entry_t * );
int64_t oggseek_get_last_frame ( demux_t *, logical_stream_t *);
int oggseek_find_frame ( demux_t *, logical_stream_t *, int64_t i_tframe );
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment