Commit bf835128 authored by Timothy B. Terriberry's avatar Timothy B. Terriberry Committed by Jean-Baptiste Kempf

Opus demuxing fixes.

This properly handles pre-skip, seeking pre-roll, and end-trim. It
uses the i_nb_samples field of block_t to signal to the decoder how
many samples should be returned after (possibly) skipping some at
the start of the block (for both pre-skip and pre-roll). In
addition, it abuses the i_length field of block_t to signal to the
decoder how many samples to trim from the end of the packet (for
end-trimming).

This patch does not compute correct timestamps for streams which
start at a non-zero offset (e.g., live streams joined in the
middle), nor does it correctly compute the length of a stream. But
neither of those things work for Vorbis, either. I'm leaving them
for a follow-up patch.
Signed-off-by: default avatarRafaël Carré <funman@videolan.org>
(cherry picked from commit 675072a8)
Signed-off-by: default avatarJean-Baptiste Kempf <jb@videolan.org>
parent 410a1013
This diff is collapsed.
...@@ -55,6 +55,7 @@ typedef struct logical_stream_s ...@@ -55,6 +55,7 @@ typedef struct logical_stream_s
int i_packets_backup; int i_packets_backup;
void *p_headers; void *p_headers;
int i_headers; int i_headers;
ogg_int64_t i_previous_granulepos;
/* program clock reference (in units of 90kHz) derived from the previous /* program clock reference (in units of 90kHz) derived from the previous
* granulepos */ * granulepos */
...@@ -67,6 +68,8 @@ typedef struct logical_stream_s ...@@ -67,6 +68,8 @@ typedef struct logical_stream_s
int i_granule_shift; int i_granule_shift;
/* Opus has a starting offset in the headers. */ /* Opus has a starting offset in the headers. */
int i_pre_skip; int i_pre_skip;
/* Vorbis and Opus can trim the end of a stream using granule positions. */
int i_end_trim;
/* offset of first keyframe for theora; can be 0 or 1 depending on version number */ /* offset of first keyframe for theora; can be 0 or 1 depending on version number */
int64_t i_keyframe_offset; int64_t i_keyframe_offset;
......
...@@ -772,14 +772,26 @@ int oggseek_find_frame ( demux_t *p_demux, logical_stream_t *p_stream, int64_t i ...@@ -772,14 +772,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_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 */ /* 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 ) 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 ); &i_pagepos, true );
if ( i_granulepos == -1 ) if ( i_granulepos == -1 )
{ {
......
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