Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-2-2
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-2-2
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
Hide 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
)
;
while
(
1
)
if
(
stream_Seek
(
p_demux
->
s
,
i_pos
)
)
{
if
(
i_start_pos
<
i_pos1
)
i_start_pos
=
i_pos1
;
ogg_sync_clear
(
&
oy
);
ogg_stream_clear
(
&
os
);
return
;
}
i_page_pos
=
find_first_page
(
p_demux
,
i_start_pos
,
i_pos2
,
p_stream
,
&
i_kframe
,
&
i_frame
);
while
(
i_pos
>=
i_lowerbound
)
{
if
(
i_frame
==
-
1
)
while
(
i_pos
<
i_upperbound
)
{
/* no pages found in range */
if
(
i_last_frame
>=
0
)
{
/* No more pages in range -> return last one */
return
i_last_frame
;
}
if
(
i_start_pos
<=
i_pos1
)
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
);
while
(
ogg_sync_pageout
(
&
oy
,
&
page
)
==
1
)
{
return
-
1
;
i_granule
=
ogg_page_granulepos
(
&
page
);
if
(
i_granule
==
-
1
)
continue
;
for
(
int
i
=
0
;
i
<
p_sys
->
i_streams
;
i
++
)
{
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_length
>
0
)
break
;
}
/* Go back a bit */
i_pos2
-=
i_start_pos
;
i_start_pos
-=
OGGSEEK_BYTES_TO_READ
;
if
(
i_start_pos
<
i_pos1
)
i_start_pos
=
i_pos1
;
i_pos2
+=
i_start_pos
;
/* We found at least a page with valid granule */
if
(
i_length
>
0
)
break
;
/* 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