Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
4dde2b7a
Commit
4dde2b7a
authored
Oct 12, 2013
by
Francois Cartegnie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
demux: ogg: fix probing duration (fix #9591, #9649)
parent
d1c8352d
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
91 additions
and
141 deletions
+91
-141
modules/demux/ogg.c
modules/demux/ogg.c
+18
-42
modules/demux/oggseek.c
modules/demux/oggseek.c
+72
-97
modules/demux/oggseek.h
modules/demux/oggseek.h
+1
-2
No files found.
modules/demux/ogg.c
View file @
4dde2b7a
...
...
@@ -126,13 +126,12 @@ static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t *
/* */
static
void
Ogg_ExtractMeta
(
demux_t
*
p_demux
,
es_format_t
*
p_fmt
,
const
uint8_t
*
p_headers
,
int
i_headers
);
static
int64_t
Ogg_GetLastPacket
(
demux_t
*
p_demux
,
logical_stream_t
*
p_stream
,
double
f_rate
);
/* Logical bitstream headers */
static
void
Ogg_ReadTheoraHeader
(
demux_t
*
,
logical_stream_t
*
,
ogg_packet
*
);
static
void
Ogg_ReadVorbisHeader
(
demux_t
*
,
logical_stream_t
*
,
ogg_packet
*
);
static
void
Ogg_ReadTheoraHeader
(
logical_stream_t
*
,
ogg_packet
*
);
static
void
Ogg_ReadVorbisHeader
(
logical_stream_t
*
,
ogg_packet
*
);
static
void
Ogg_ReadSpeexHeader
(
logical_stream_t
*
,
ogg_packet
*
);
static
void
Ogg_ReadOpusHeader
(
demux_t
*
,
logical_stream_t
*
,
ogg_packet
*
);
static
void
Ogg_ReadOpusHeader
(
logical_stream_t
*
,
ogg_packet
*
);
static
void
Ogg_ReadKateHeader
(
logical_stream_t
*
,
ogg_packet
*
);
static
void
Ogg_ReadFlacHeader
(
demux_t
*
,
logical_stream_t
*
,
ogg_packet
*
);
static
void
Ogg_ReadAnnodexHeader
(
demux_t
*
,
logical_stream_t
*
,
ogg_packet
*
);
...
...
@@ -234,6 +233,7 @@ static int Demux( demux_t * p_demux )
ogg_packet
oggpacket
;
int
i_stream
;
bool
b_skipping
=
false
;
bool
b_canseek
;
if
(
p_sys
->
i_eos
==
p_sys
->
i_streams
)
...
...
@@ -255,6 +255,11 @@ static int Demux( demux_t * p_demux )
if
(
Ogg_BeginningOfStream
(
p_demux
)
!=
VLC_SUCCESS
)
return
0
;
/* Find the real duration */
stream_Control
(
p_demux
->
s
,
STREAM_CAN_SEEK
,
&
b_canseek
);
if
(
b_canseek
)
Oggseek_ProbeEnd
(
p_demux
);
msg_Dbg
(
p_demux
,
"beginning of a group of logical streams"
);
es_out_Control
(
p_demux
->
out
,
ES_OUT_SET_PCR
,
VLC_TS_0
);
}
...
...
@@ -339,14 +344,14 @@ static int Demux( demux_t * p_demux )
oggpacket
.
bytes
>=
7
&&
!
memcmp
(
oggpacket
.
packet
,
"
\x80
theora"
,
7
)
)
{
Ogg_ReadTheoraHeader
(
p_
demux
,
p_
stream
,
&
oggpacket
);
Ogg_ReadTheoraHeader
(
p_stream
,
&
oggpacket
);
p_stream
->
i_secondary_header_packets
=
0
;
}
else
if
(
p_stream
->
fmt
.
i_codec
==
VLC_CODEC_VORBIS
&&
oggpacket
.
bytes
>=
7
&&
!
memcmp
(
oggpacket
.
packet
,
"
\x01
vorbis"
,
7
)
)
{
Ogg_ReadVorbisHeader
(
p_
demux
,
p_
stream
,
&
oggpacket
);
Ogg_ReadVorbisHeader
(
p_stream
,
&
oggpacket
);
p_stream
->
i_secondary_header_packets
=
0
;
}
else
if
(
p_stream
->
fmt
.
i_codec
==
VLC_CODEC_CMML
)
...
...
@@ -1287,7 +1292,7 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
if
(
oggpacket
.
bytes
>=
7
&&
!
memcmp
(
oggpacket
.
packet
,
"
\x01
vorbis"
,
7
)
)
{
Ogg_ReadVorbisHeader
(
p_
demux
,
p_
stream
,
&
oggpacket
);
Ogg_ReadVorbisHeader
(
p_stream
,
&
oggpacket
);
msg_Dbg
(
p_demux
,
"found vorbis header"
);
}
/* Check for Speex header */
...
...
@@ -1304,7 +1309,7 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
else
if
(
oggpacket
.
bytes
>=
8
&&
!
memcmp
(
oggpacket
.
packet
,
"OpusHead"
,
8
)
)
{
Ogg_ReadOpusHeader
(
p_
demux
,
p_
stream
,
&
oggpacket
);
Ogg_ReadOpusHeader
(
p_stream
,
&
oggpacket
);
msg_Dbg
(
p_demux
,
"found opus header, channels: %i, "
"pre-skip: %i"
,
p_stream
->
fmt
.
audio
.
i_channels
,
...
...
@@ -1348,7 +1353,7 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
else
if
(
oggpacket
.
bytes
>=
7
&&
!
memcmp
(
oggpacket
.
packet
,
"
\x80
theora"
,
7
)
)
{
Ogg_ReadTheoraHeader
(
p_
demux
,
p_
stream
,
&
oggpacket
);
Ogg_ReadTheoraHeader
(
p_stream
,
&
oggpacket
);
msg_Dbg
(
p_demux
,
"found theora header, bitrate: %i, rate: %f"
,
...
...
@@ -2071,14 +2076,7 @@ static void Ogg_ExtractMeta( demux_t *p_demux, es_format_t *p_fmt, const uint8_t
p_demux
->
info
.
i_update
|=
INPUT_UPDATE_META
;
}
static
int64_t
Ogg_GetLastPacket
(
demux_t
*
p_demux
,
logical_stream_t
*
p_stream
,
double
f_rate
)
{
int64_t
last_packet
=
oggseek_get_last_frame
(
p_demux
,
p_stream
);
return
(
last_packet
>=
0
)
?
last_packet
/
f_rate
:
-
1
;
}
static
void
Ogg_ReadTheoraHeader
(
demux_t
*
p_demux
,
logical_stream_t
*
p_stream
,
static
void
Ogg_ReadTheoraHeader
(
logical_stream_t
*
p_stream
,
ogg_packet
*
p_oggpacket
)
{
bs_t
bitstream
;
...
...
@@ -2144,16 +2142,9 @@ static void Ogg_ReadTheoraHeader( demux_t *p_demux, logical_stream_t *p_stream,
{
p_stream
->
i_keyframe_offset
=
1
;
}
if
(
p_demux
->
p_sys
->
i_length
<
0
)
{
int64_t
last_packet
=
Ogg_GetLastPacket
(
p_demux
,
p_stream
,
p_stream
->
f_rate
);
if
(
last_packet
>=
0
)
p_demux
->
p_sys
->
i_length
=
last_packet
;
}
}
static
void
Ogg_ReadVorbisHeader
(
demux_t
*
p_demux
,
logical_stream_t
*
p_stream
,
static
void
Ogg_ReadVorbisHeader
(
logical_stream_t
*
p_stream
,
ogg_packet
*
p_oggpacket
)
{
oggpack_buffer
opb
;
...
...
@@ -2175,13 +2166,6 @@ static void Ogg_ReadVorbisHeader( demux_t *p_demux, logical_stream_t *p_stream,
oggpack_read
(
&
opb
,
32
);
oggpack_adv
(
&
opb
,
32
);
p_stream
->
fmt
.
i_bitrate
=
oggpack_read
(
&
opb
,
32
);
if
(
p_demux
->
p_sys
->
i_length
<
0
)
{
int64_t
last_packet
=
Ogg_GetLastPacket
(
p_demux
,
p_stream
,
p_stream
->
f_rate
);
if
(
last_packet
>=
0
)
p_demux
->
p_sys
->
i_length
=
last_packet
;
}
}
static
void
Ogg_ReadSpeexHeader
(
logical_stream_t
*
p_stream
,
...
...
@@ -2214,8 +2198,7 @@ static void Ogg_ReadSpeexHeader( logical_stream_t *p_stream,
p_stream
->
i_extra_headers_packets
=
oggpack_read
(
&
opb
,
32
);
/* extra_headers */
}
static
void
Ogg_ReadOpusHeader
(
demux_t
*
p_demux
,
logical_stream_t
*
p_stream
,
static
void
Ogg_ReadOpusHeader
(
logical_stream_t
*
p_stream
,
ogg_packet
*
p_oggpacket
)
{
oggpack_buffer
opb
;
...
...
@@ -2240,13 +2223,6 @@ static void Ogg_ReadOpusHeader( demux_t *p_demux,
p_stream
->
fmt
.
audio
.
i_channels
=
oggpack_read
(
&
opb
,
8
);
fill_channels_info
(
&
p_stream
->
fmt
.
audio
);
p_stream
->
i_pre_skip
=
oggpack_read
(
&
opb
,
16
);
if
(
p_demux
->
p_sys
->
i_length
<
0
)
{
int64_t
last_packet
=
Ogg_GetLastPacket
(
p_demux
,
p_stream
,
p_stream
->
f_rate
);
if
(
last_packet
>=
0
)
p_demux
->
p_sys
->
i_length
=
last_packet
;
}
}
static
void
Ogg_ReadFlacHeader
(
demux_t
*
p_demux
,
logical_stream_t
*
p_stream
,
...
...
@@ -2359,7 +2335,7 @@ static void Ogg_ReadAnnodexHeader( demux_t *p_demux,
uint64_t
timebase_numerator
;
uint64_t
timebase_denominator
;
Ogg_ReadTheoraHeader
(
p_
demux
,
p_
stream
,
p_oggpacket
);
Ogg_ReadTheoraHeader
(
p_stream
,
p_oggpacket
);
oggpack_readinit
(
&
opb
,
p_oggpacket
->
packet
,
p_oggpacket
->
bytes
);
oggpack_adv
(
&
opb
,
8
*
8
);
/* "Annodex\0" header */
...
...
modules/demux/oggseek.c
View file @
4dde2b7a
...
...
@@ -36,6 +36,8 @@
#include <ogg/ogg.h>
#include <limits.h>
#include <assert.h>
#include "ogg.h"
#include "oggseek.h"
...
...
@@ -460,68 +462,96 @@ static int64_t find_first_page( demux_t *p_demux, int64_t i_pos1, int64_t i_pos2
}
}
/* Find the last frame for p_stream,
-1 is returned on failure */
static
int64_t
find_last_frame
(
demux_t
*
p_demux
,
logical_stream_t
*
p_stream
)
void
Oggseek_ProbeEnd
(
demux_t
*
p_demux
)
{
/* Temporary state */
ogg_stream_state
os
;
ogg_sync_state
oy
;
ogg_page
page
;
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
int64_t
i_pos
,
i_startpos
,
i_result
,
i_granule
,
i_lowerbound
;
int64_t
i_length
=
0
;
int64_t
i_backup_pos
=
stream_Tell
(
p_demux
->
s
);
int64_t
i_upperbound
=
stream_Size
(
p_demux
->
s
);
unsigned
int
i_backoffset
=
OGGSEEK_BYTES_TO_READ
;
assert
(
OGGSEEK_BYTES_TO_READ
<
UINT_MAX
);
int64_t
i_page_pos
;
int64_t
i_start_pos
;
int64_t
i_frame
=
-
1
;
int64_t
i_last_frame
=
-
1
;
int64_t
i_kframe
=
0
;
int64_t
i_pos1
;
int64_t
i_pos2
;
const
char
*
buffer
;
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
ogg_stream_init
(
&
os
,
-
1
);
ogg_sync_init
(
&
oy
);
i_pos1
=
p_stream
->
i_data_start
;
i_pos2
=
p_sys
->
i_total_length
;
/* Try to lookup last granule from each logical stream */
i_lowerbound
=
stream_Size
(
p_demux
->
s
)
-
p_sys
->
i_streams
*
MAX_PAGE_SIZE
*
2
;
i_lowerbound
=
__MAX
(
0
,
i_lowerbound
);
i_
start_pos
=
i_pos2
-
OGGSEEK_BYTES_TO_READ
;
i_
pos
=
i_startpos
=
__MAX
(
i_lowerbound
,
i_upperbound
-
i_backoffset
)
;
if
(
stream_Seek
(
p_demux
->
s
,
i_pos
)
)
{
ogg_sync_clear
(
&
oy
);
ogg_stream_clear
(
&
os
);
return
;
}
while
(
1
)
while
(
i_pos
>=
i_lowerbound
)
{
if
(
i_start_pos
<
i_pos1
)
i_start_pos
=
i_pos1
;
i_page_pos
=
find_first_page
(
p_demux
,
i_start_pos
,
i_pos2
,
p_stream
,
&
i_kframe
,
&
i_frame
);
while
(
i_pos
<
i_upperbound
)
{
if
(
oy
.
unsynced
)
i_result
=
ogg_sync_pageseek
(
&
oy
,
&
page
);
buffer
=
ogg_sync_buffer
(
&
oy
,
OGGSEEK_BYTES_TO_READ
);
if
(
buffer
==
NULL
)
goto
clean
;
i_result
=
stream_Read
(
p_demux
->
s
,
(
void
*
)
buffer
,
OGGSEEK_BYTES_TO_READ
);
if
(
i_result
<
1
)
goto
clean
;
i_pos
+=
i_result
;
ogg_sync_wrote
(
&
oy
,
i_result
);
if
(
i_frame
==
-
1
)
while
(
ogg_sync_pageout
(
&
oy
,
&
page
)
==
1
)
{
/* no pages found in range */
if
(
i_last_frame
>=
0
)
i_granule
=
ogg_page_granulepos
(
&
page
);
if
(
i_granule
==
-
1
)
continue
;
for
(
int
i
=
0
;
i
<
p_sys
->
i_streams
;
i
++
)
{
/* No more pages in range -> return last one */
return
i_last_frame
;
if
(
p_sys
->
pp_stream
[
i
]
->
i_serial_no
!=
ogg_page_serialno
(
&
page
)
)
continue
;
i_length
=
Oggseek_GranuleToAbsTimestamp
(
p_sys
->
pp_stream
[
i
],
i_granule
,
false
);
p_sys
->
i_length
=
__MAX
(
p_sys
->
i_length
,
i_length
/
1000000
);
break
;
}
if
(
i_start_pos
<=
i_pos1
)
{
return
-
1
;
}
if
(
i_length
>
0
)
break
;
}
/* We found at least a page with valid granule */
if
(
i_length
>
0
)
break
;
/* Go back a bit
*/
i_pos2
-=
i_start_pos
;
i_start_pos
-=
OGGSEEK_BYTES_TO_READ
;
i
f
(
i_start_pos
<
i_pos1
)
i_start_pos
=
i_pos
1
;
i_
pos2
+=
i_start_pos
;
/* Otherwise increase read size, starting earlier
*/
if
(
i_backoffset
<=
(
UINT_MAX
>>
1
)
)
{
i
_backoffset
<<=
1
;
i_
startpos
=
i_upperbound
-
i_backoffset
;
}
else
{
/* found a page, see if we can find another one */
i_last_frame
=
i_frame
;
i_start_pos
=
i_page_pos
+
1
;
}
i_startpos
-=
i_backoffset
;
}
return
-
1
;
}
i_pos
=
i_startpos
;
if
(
stream_Seek
(
p_demux
->
s
,
i_pos
)
)
break
;
}
clean:
stream_Seek
(
p_demux
->
s
,
i_backup_pos
);
ogg_sync_clear
(
&
oy
);
ogg_stream_clear
(
&
os
);
}
/* convert a theora frame to a granulepos */
...
...
@@ -1238,67 +1268,12 @@ static int64_t OggBisectSearchByTime( demux_t *p_demux, logical_stream_t *p_stre
return
bestlower
.
i_pos
;
}
/* get highest frame in theora and opus streams */
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
);
/* We need to reset back to the start here, otherwise packets cannot be decoded.
* I think this is due to the fact that we seek to the end and then we must reset
* all logical streams, which causes remaining headers not to be read correctly.
* Seeking to 0 is the only value which seems to work, and it appears to have no
* adverse effects. */
seek_byte
(
p_demux
,
0
);
/* Reset stream states */
p_sys
->
i_streams
=
0
;
ogg_stream_clear
(
&
p_stream
->
os
);
memcpy
(
&
p_stream
->
os
,
&
os
,
sizeof
(
os
)
);
return
i_frame
;
}
/************************************************************************
* public functions
*************************************************************************/
/* 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
||
p_stream
->
fmt
.
i_codec
==
VLC_CODEC_VORBIS
||
p_stream
->
fmt
.
i_codec
==
VLC_CODEC_OPUS
)
{
i_frame
=
get_last_frame
(
p_demux
,
p_stream
);
if
(
i_frame
<
0
)
return
-
1
;
return
i_frame
;
}
/* unhandled video format */
return
-
1
;
}
int
Oggseek_BlindSeektoPosition
(
demux_t
*
p_demux
,
logical_stream_t
*
p_stream
,
double
f
,
bool
b_canfastseek
)
{
...
...
modules/demux/oggseek.h
View file @
4dde2b7a
...
...
@@ -58,6 +58,7 @@ bool Oggseek_PacketPCRFixup ( logical_stream_t *p_stream, ogg_page *, ogg_pac
int
Oggseek_BlindSeektoPosition
(
demux_t
*
,
logical_stream_t
*
,
double
f
,
bool
);
int
Oggseek_SeektoAbsolutetime
(
demux_t
*
,
logical_stream_t
*
,
int64_t
i_granulepos
);
const
demux_index_entry_t
*
OggSeek_IndexAdd
(
logical_stream_t
*
,
int64_t
,
int64_t
);
void
Oggseek_ProbeEnd
(
demux_t
*
);
const
demux_index_entry_t
*
oggseek_theora_index_entry_add
(
logical_stream_t
*
,
int64_t
i_granule
,
...
...
@@ -65,8 +66,6 @@ const demux_index_entry_t *oggseek_theora_index_entry_add ( logical_stream_t *,
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
);
int64_t
oggseek_read_page
(
demux_t
*
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment