X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdemux%2Foggseek.c;h=3c65e5f177e4689f1ce0815871bcb032fa1adf9a;hb=56d4e908e1b71fc6161622701d1cf0db64e57aa6;hp=567d920df32cba2cf16447ae9804f3ae96cefc05;hpb=78a8771f4c69bdb2080a06f8b0c8db4d5675f6b9;p=vlc diff --git a/modules/demux/oggseek.c b/modules/demux/oggseek.c index 567d920df3..3c65e5f177 100644 --- a/modules/demux/oggseek.c +++ b/modules/demux/oggseek.c @@ -7,19 +7,19 @@ * 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 + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 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. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser 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. + * You should have received a copy of the GNU Lesser 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. *****************************************************************************/ /***************************************************************************** @@ -58,22 +58,6 @@ void oggseek_index_entries_free ( demux_index_entry_t *idx ) } -/* unlink and free idx. If idx is head of list, return new head */ - -static demux_index_entry_t *index_entry_delete( demux_index_entry_t *idx ) -{ - demux_index_entry_t *xidx = idx; - - if ( idx->p_prev != NULL ) idx->p_prev->p_next = idx->p_next; - else xidx = idx->p_next; - - if ( idx->p_next != NULL ) idx->p_next->p_prev = idx->p_prev; - free( idx ); - - return xidx; -} - - /* internal function to create a new list member */ static demux_index_entry_t *index_entry_new( void ) @@ -391,13 +375,11 @@ static int64_t find_last_frame (demux_t *p_demux, logical_stream_t *p_stream) int64_t i_kframe = 0; int64_t i_pos1; int64_t i_pos2; - int64_t i_serialno; demux_sys_t *p_sys = p_demux->p_sys; i_pos1 = p_stream->i_data_start; i_pos2 = p_sys->i_total_length; - i_serialno = p_stream->os.serialno; i_start_pos = i_pos2 - OGGSEEK_BYTES_TO_READ; @@ -690,11 +672,20 @@ static demux_index_entry_t *get_bounds_for ( logical_stream_t *p_stream, int64_t } -/* get highest frame in theora stream */ +/* get highest frame in theora and opus streams */ -static int64_t find_last_theora_frame ( demux_t *p_demux, logical_stream_t *p_stream ) +static int64_t get_last_frame ( demux_t *p_demux, logical_stream_t *p_stream ) { + demux_sys_t *p_sys = p_demux->p_sys; int64_t i_frame; + ogg_stream_state os; + + /* Backup the stream state. We get called during header processing, and our + * caller expects its header packet to remain valid after the call. If we + * let find_last_frame() reuse the same stream state, then it will + * invalidate the pointers in that packet. */ + memcpy(&os, &p_stream->os, sizeof(os)); + ogg_stream_init( &p_stream->os, p_stream->i_serial_no ); i_frame = find_last_frame ( p_demux, p_stream ); @@ -706,9 +697,9 @@ static int64_t find_last_theora_frame ( demux_t *p_demux, logical_stream_t *p_st seek_byte( p_demux, 0 ); /* Reset stream states */ - p_stream->i_serial_no = ogg_page_serialno( &p_demux->p_sys->current_page ); - ogg_stream_init( &p_stream->os, p_stream->i_serial_no ); - ogg_stream_pagein( &p_stream->os, &p_demux->p_sys->current_page ); + p_sys->i_streams = 0; + ogg_stream_clear( &p_stream->os ); + memcpy( &p_stream->os, &os, sizeof(os) ); return i_frame; } @@ -722,15 +713,17 @@ static int64_t find_last_theora_frame ( demux_t *p_demux, logical_stream_t *p_st -/* return highest frame number for p_stream (which must be a theora or dirac video stream) */ +/* return highest frame number for p_stream (which must be a theora, dirac or opus stream) */ int64_t oggseek_get_last_frame ( demux_t *p_demux, logical_stream_t *p_stream ) { int64_t i_frame = -1; - if ( p_stream->fmt.i_codec == VLC_CODEC_THEORA ) + if ( p_stream->fmt.i_codec == VLC_CODEC_THEORA || + p_stream->fmt.i_codec == VLC_CODEC_VORBIS || + p_stream->fmt.i_codec == VLC_CODEC_OPUS ) { - i_frame = find_last_theora_frame ( p_demux, p_stream ); + i_frame = get_last_frame ( p_demux, p_stream ); if ( i_frame < 0 ) return -1; return i_frame; @@ -776,14 +769,26 @@ int oggseek_find_frame ( demux_t *p_demux, logical_stream_t *p_stream, int64_t i i_tframe += p_stream->i_keyframe_offset; + i_cframe = i_tframe; + /* For Opus, seek back 80 ms before the target playback position. */ + if ( p_stream->fmt.i_codec == VLC_CODEC_OPUS ) + { + if ( i_tframe <= p_stream->i_pre_skip ) + i_cframe = 0; + else if ( i_tframe < 80*48 ) + i_cframe = 0; + else + i_cframe = i_tframe - 80*48; + } + /* reduce the search domain */ - fidx = get_bounds_for( p_stream, i_tframe, &i_pos_lower, &i_pos_upper ); + fidx = get_bounds_for( p_stream, i_cframe, &i_pos_lower, &i_pos_upper ); if ( fidx == NULL ) { - /* no exact match found; search the domain for highest keyframe <= i_tframe */ + /* no exact match found; search the domain for highest keyframe <= i_cframe */ - i_granulepos = ogg_seek ( p_demux, p_stream, i_tframe, i_pos_lower, i_pos_upper, + i_granulepos = ogg_seek ( p_demux, p_stream, i_cframe, i_pos_lower, i_pos_upper, &i_pagepos, true ); if ( i_granulepos == -1 ) {