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
51cff6ef
Commit
51cff6ef
authored
Sep 09, 2013
by
Francois Cartegnie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
demux: ogg: add skeleton index seeking
parent
d6a7b808
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
476 additions
and
74 deletions
+476
-74
modules/demux/ogg.c
modules/demux/ogg.c
+380
-69
modules/demux/ogg.h
modules/demux/ogg.h
+32
-0
modules/demux/oggseek.c
modules/demux/oggseek.c
+62
-5
modules/demux/oggseek.h
modules/demux/oggseek.h
+1
-0
modules/mux/ogg.c
modules/mux/ogg.c
+1
-0
No files found.
modules/demux/ogg.c
View file @
51cff6ef
...
...
@@ -136,6 +136,13 @@ 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
*
);
static
bool
Ogg_ReadDiracHeader
(
logical_stream_t
*
,
ogg_packet
*
);
static
void
Ogg_ReadSkeletonHeader
(
demux_t
*
,
logical_stream_t
*
,
ogg_packet
*
);
/* Skeleton */
static
void
Ogg_ReadSkeletonBones
(
demux_t
*
,
ogg_packet
*
);
static
void
Ogg_ReadSkeletonIndex
(
demux_t
*
,
ogg_packet
*
);
static
void
Ogg_FreeSkeleton
(
ogg_skeleton_t
*
);
static
void
Ogg_ApplySkeleton
(
logical_stream_t
*
);
static
void
fill_channels_info
(
audio_format_t
*
audio
)
{
...
...
@@ -286,11 +293,32 @@ static int Demux( demux_t * p_demux )
if
(
Ogg_ReadPage
(
p_demux
,
&
p_sys
->
current_page
)
!=
VLC_SUCCESS
)
return
0
;
/* EOF */
/* Test for End of Stream */
if
(
ogg_page_eos
(
&
p_sys
->
current_page
)
)
{
/* If we delayed restarting encoders/SET_ES_FMT for more
* skeleton provided configuration */
if
(
p_sys
->
p_skelstream
&&
p_sys
->
p_skelstream
->
i_serial_no
==
ogg_page_serialno
(
&
p_sys
->
current_page
)
)
{
msg_Dbg
(
p_demux
,
"End of Skeleton"
);
for
(
i_stream
=
0
;
i_stream
<
p_sys
->
i_streams
;
i_stream
++
)
{
logical_stream_t
*
p_stream
=
p_sys
->
pp_stream
[
i_stream
];
if
(
p_stream
->
b_have_updated_format
)
{
p_stream
->
b_have_updated_format
=
false
;
if
(
p_stream
->
p_skel
)
Ogg_ApplySkeleton
(
p_stream
);
msg_Dbg
(
p_demux
,
"Resetting format for stream %d"
,
i_stream
);
es_out_Control
(
p_demux
->
out
,
ES_OUT_SET_ES_FMT
,
p_stream
->
p_es
,
&
p_stream
->
fmt
);
}
}
}
/* FIXME that eos handling is innapropriate with seeking and concatenated streams */
if
(
ogg_page_eos
(
&
p_sys
->
current_page
)
&&
ogg_page_granulepos
(
&
p_sys
->
current_page
)
!=
0
)
/* skel workaround */
if
(
ogg_page_granulepos
(
&
p_sys
->
current_page
)
!=
0
)
/* skel workaround */
p_sys
->
i_eos
++
;
}
}
b_skipping
=
false
;
for
(
i_stream
=
0
;
i_stream
<
p_sys
->
i_streams
;
i_stream
++
)
...
...
@@ -564,6 +592,22 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
return
VLC_SUCCESS
;
case
DEMUX_SET_TIME
:
i64
=
(
int64_t
)
va_arg
(
args
,
int64_t
);
logical_stream_t
*
p_stream
=
Ogg_GetSelectedStream
(
p_demux
);
if
(
!
p_stream
)
{
msg_Err
(
p_demux
,
"No selected seekable stream found"
);
return
VLC_EGENERIC
;
}
stream_Control
(
p_demux
->
s
,
STREAM_CAN_FASTSEEK
,
&
b
);
if
(
Oggseek_BlindSeektoAbsoluteTime
(
p_demux
,
p_stream
,
i64
,
b
)
)
{
Ogg_ResetStreamHelper
(
p_sys
);
es_out_Control
(
p_demux
->
out
,
ES_OUT_SET_NEXT_DISPLAY_TIME
,
VLC_TS_0
+
i64
);
return
VLC_SUCCESS
;
}
else
return
VLC_EGENERIC
;
case
DEMUX_GET_ATTACHMENTS
:
...
...
@@ -606,7 +650,7 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
return
VLC_EGENERIC
;
}
logical_stream_t
*
p_stream
=
Ogg_GetSelectedStream
(
p_demux
);
p_stream
=
Ogg_GetSelectedStream
(
p_demux
);
if
(
!
p_stream
)
{
msg_Err
(
p_demux
,
"No selected seekable stream found"
);
...
...
@@ -674,42 +718,31 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
case
DEMUX_SET_SEEKPOINT
:
{
const
int
i_seekpoint
=
(
int
)
va_arg
(
args
,
int
);
if
(
i_seekpoint
>
p_sys
->
i_seekpoints
)
return
VLC_EGENERIC
;
if
(
p_sys
->
i_bos
>
0
)
{
if
(
i_seekpoint
>
p_sys
->
i_seekpoints
||
p_sys
->
i_bos
>
0
)
return
VLC_EGENERIC
;
}
Ogg_ResetStreamHelper
(
p_sys
)
;
i64
=
p_sys
->
pp_seekpoints
[
i_seekpoint
]
->
i_time_offset
;
if
(
p_sys
->
i_bitrate
==
0
||
p_sys
->
b_partial_bitrate
)
{
/* we won't be able to find block by time
* we'll need to bisect search from here
* or use skeleton index if any (FIXME)
*/
logical_stream_t
*
p_stream
=
Ogg_GetSelectedStream
(
p_demux
);
p_stream
=
Ogg_GetSelectedStream
(
p_demux
);
if
(
!
p_stream
)
{
msg_Err
(
p_demux
,
"No selected seekable stream found"
);
return
VLC_EGENERIC
;
}
Oggseek_SeektoAbsolutetime
(
p_demux
,
p_stream
,
p_sys
->
pp_seekpoints
[
i_seekpoint
]
->
i_time_offset
);
return
VLC_SUCCESS
;
}
else
stream_Control
(
p_demux
->
s
,
STREAM_CAN_FASTSEEK
,
&
b
);
if
(
Oggseek_BlindSeektoAbsoluteTime
(
p_demux
,
p_stream
,
i64
,
b
)
)
{
int64_t
i_block
=
p_sys
->
pp_seekpoints
[
i_seekpoint
]
->
i_time_offset
*
p_sys
->
i_bitrate
/
INT64_C
(
8000000
);
if
(
stream_Seek
(
p_demux
->
s
,
i_block
)
)
return
VLC_EGENERIC
;
}
Ogg_ResetStreamHelper
(
p_sys
);
es_out_Control
(
p_demux
->
out
,
ES_OUT_SET_NEXT_DISPLAY_TIME
,
VLC_TS_0
+
i64
);
p_demux
->
info
.
i_update
|=
INPUT_UPDATE_SEEKPOINT
;
p_demux
->
info
.
i_seekpoint
=
i_seekpoint
;
return
VLC_SUCCESS
;
}
else
return
VLC_EGENERIC
;
}
default:
return
demux_vaControlHelper
(
p_demux
->
s
,
0
,
-
1
,
p_sys
->
i_bitrate
,
...
...
@@ -851,6 +884,18 @@ static void Ogg_DecodePacket( demux_t *p_demux,
/* it's an AnxData packet -- skip it (do nothing) */
return
;
}
else
if
(
p_oggpacket
->
bytes
>=
8
&&
!
memcmp
(
p_oggpacket
->
packet
,
"fisbone"
,
8
)
)
{
Ogg_ReadSkeletonBones
(
p_demux
,
p_oggpacket
);
return
;
}
else
if
(
p_oggpacket
->
bytes
>=
6
&&
!
memcmp
(
p_oggpacket
->
packet
,
"index"
,
6
)
)
{
Ogg_ReadSkeletonIndex
(
p_demux
,
p_oggpacket
);
return
;
}
if
(
p_stream
->
fmt
.
i_codec
==
VLC_CODEC_SUBT
&&
p_oggpacket
->
bytes
>
0
&&
p_oggpacket
->
packet
[
0
]
&
PACKET_TYPE_BITS
)
return
;
...
...
@@ -955,8 +1000,23 @@ static void Ogg_DecodePacket( demux_t *p_demux,
p_stream
->
fmt
.
i_extra
=
0
;
if
(
Ogg_LogicalStreamResetEsFormat
(
p_demux
,
p_stream
)
)
{
if
(
p_ogg
->
p_skelstream
)
{
/* We delay until eos is reached on skeleton.
* There should only be headers, as no data page is
* allowed before skeleton's eos.
* Skeleton data is appended to fmt on skeleton eos.
*/
p_stream
->
b_have_updated_format
=
true
;
}
else
{
/* Otherwise we set config from first headers */
es_out_Control
(
p_demux
->
out
,
ES_OUT_SET_ES_FMT
,
p_stream
->
p_es
,
&
p_stream
->
fmt
);
}
}
if
(
p_stream
->
i_headers
>
0
)
Ogg_ExtractMeta
(
p_demux
,
&
p_stream
->
fmt
,
...
...
@@ -1657,14 +1717,14 @@ static int Ogg_FindLogicalStreams( demux_t *p_demux )
p_ogg
->
i_streams
--
;
}
}
else
if
(
oggpacket
.
bytes
>=
7
&&
!
memcmp
(
oggpacket
.
packet
,
"fishead
"
,
7
)
)
else
if
(
oggpacket
.
bytes
>=
8
&&
!
memcmp
(
oggpacket
.
packet
,
"fishead
\0
"
,
8
)
)
{
/* Skeleton */
msg_Dbg
(
p_demux
,
"stream %d is a skeleton"
,
p_ogg
->
i_streams
-
1
);
/* FIXME: https://trac.videolan.org/vlc/ticket/1412 */
Ogg_ReadSkeletonHeader
(
p_demux
,
p_stream
,
&
oggpacket
);
}
else
{
...
...
@@ -1811,6 +1871,8 @@ static void Ogg_EndOfStream( demux_t *p_demux )
p_ogg
->
i_bitrate
=
0
;
p_ogg
->
i_streams
=
0
;
p_ogg
->
pp_stream
=
NULL
;
p_ogg
->
skeleton
.
major
=
0
;
p_ogg
->
skeleton
.
minor
=
0
;
/* */
if
(
p_ogg
->
p_meta
)
...
...
@@ -1837,6 +1899,11 @@ static void Ogg_LogicalStreamDelete( demux_t *p_demux, logical_stream_t *p_strea
oggseek_index_entries_free
(
p_stream
->
idx
);
}
Ogg_FreeSkeleton
(
p_stream
->
p_skel
);
p_stream
->
p_skel
=
NULL
;
if
(
p_demux
->
p_sys
->
p_skelstream
==
p_stream
)
p_demux
->
p_sys
->
p_skelstream
=
NULL
;
free
(
p_stream
);
}
/**
...
...
@@ -2321,6 +2388,76 @@ static void Ogg_ReadKateHeader( logical_stream_t *p_stream,
}
}
static
void
Ogg_ApplyContentType
(
logical_stream_t
*
p_stream
,
const
char
*
psz_value
,
bool
*
b_force_backup
,
bool
*
b_packet_out
)
{
if
(
!
strncmp
(
psz_value
,
"audio/x-wav"
,
11
)
)
{
/* n.b. WAVs are unsupported right now */
p_stream
->
fmt
.
i_cat
=
UNKNOWN_ES
;
free
(
p_stream
->
fmt
.
psz_description
);
p_stream
->
fmt
.
psz_description
=
strdup
(
"WAV Audio (Unsupported)"
);
}
else
if
(
!
strncmp
(
psz_value
,
"audio/x-vorbis"
,
14
)
||
!
strncmp
(
psz_value
,
"audio/vorbis"
,
12
)
)
{
p_stream
->
fmt
.
i_cat
=
AUDIO_ES
;
p_stream
->
fmt
.
i_codec
=
VLC_CODEC_VORBIS
;
*
b_force_backup
=
true
;
}
else
if
(
!
strncmp
(
psz_value
,
"audio/x-speex"
,
13
)
||
!
strncmp
(
psz_value
,
"audio/speex"
,
11
)
)
{
p_stream
->
fmt
.
i_cat
=
AUDIO_ES
;
p_stream
->
fmt
.
i_codec
=
VLC_CODEC_SPEEX
;
*
b_force_backup
=
true
;
}
else
if
(
!
strncmp
(
psz_value
,
"audio/flac"
,
10
)
)
{
p_stream
->
fmt
.
i_cat
=
AUDIO_ES
;
p_stream
->
fmt
.
i_codec
=
VLC_CODEC_FLAC
;
*
b_force_backup
=
true
;
}
else
if
(
!
strncmp
(
psz_value
,
"video/x-theora"
,
14
)
||
!
strncmp
(
psz_value
,
"video/theora"
,
12
)
)
{
p_stream
->
fmt
.
i_cat
=
VIDEO_ES
;
p_stream
->
fmt
.
i_codec
=
VLC_CODEC_THEORA
;
*
b_force_backup
=
true
;
}
else
if
(
!
strncmp
(
psz_value
,
"video/x-xvid"
,
12
)
)
{
p_stream
->
fmt
.
i_cat
=
VIDEO_ES
;
p_stream
->
fmt
.
i_codec
=
VLC_FOURCC
(
'x'
,
'v'
,
'i'
,
'd'
);
*
b_force_backup
=
true
;
}
else
if
(
!
strncmp
(
psz_value
,
"video/mpeg"
,
10
)
)
{
/* n.b. MPEG streams are unsupported right now */
p_stream
->
fmt
.
i_cat
=
VIDEO_ES
;
p_stream
->
fmt
.
i_codec
=
VLC_CODEC_MPGV
;
}
else
if
(
!
strncmp
(
psz_value
,
"text/x-cmml"
,
11
)
||
!
strncmp
(
psz_value
,
"text/cmml"
,
9
)
)
{
p_stream
->
fmt
.
i_cat
=
SPU_ES
;
p_stream
->
fmt
.
i_codec
=
VLC_CODEC_CMML
;
*
b_packet_out
=
true
;
}
else
if
(
!
strncmp
(
psz_value
,
"application/kate"
,
16
)
)
{
/* ??? */
p_stream
->
fmt
.
i_cat
=
UNKNOWN_ES
;
free
(
p_stream
->
fmt
.
psz_description
);
p_stream
->
fmt
.
psz_description
=
strdup
(
"OGG Kate Overlay (Unsupported)"
);
}
}
static
void
Ogg_ReadAnnodexHeader
(
demux_t
*
p_demux
,
logical_stream_t
*
p_stream
,
ogg_packet
*
p_oggpacket
)
...
...
@@ -2385,52 +2522,226 @@ static void Ogg_ReadAnnodexHeader( demux_t *p_demux,
/* What type of file do we have?
* strcmp is safe to use here because we've extracted
* content_type_string from the stream manually */
if
(
!
strncmp
(
content_type_string
,
"audio/x-wav"
,
11
)
)
{
/* n.b. WAVs are unsupported right now */
p_stream
->
fmt
.
i_cat
=
UNKNOWN_ES
;
bool
b_dopacketout
=
false
;
Ogg_ApplyContentType
(
p_stream
,
content_type_string
,
&
p_stream
->
b_force_backup
,
&
b_dopacketout
);
if
(
b_dopacketout
)
ogg_stream_packetout
(
&
p_stream
->
os
,
p_oggpacket
)
;
}
else
if
(
!
strncmp
(
content_type_string
,
"audio/x-vorbis"
,
14
)
)
}
static
void
Ogg_ReadSkeletonHeader
(
demux_t
*
p_demux
,
logical_stream_t
*
p_stream
,
ogg_packet
*
p_oggpacket
)
{
p_demux
->
p_sys
->
p_skelstream
=
p_stream
;
/* There can be only 1 skeleton for streams */
p_demux
->
p_sys
->
skeleton
.
major
=
GetWLE
(
&
p_oggpacket
->
packet
[
8
]
);
p_demux
->
p_sys
->
skeleton
.
minor
=
GetWLE
(
&
p_oggpacket
->
packet
[
10
]
);
if
(
asprintf
(
&
p_stream
->
fmt
.
psz_description
,
"OGG Skeleton version %"
PRIu16
".%"
PRIu16
,
p_demux
->
p_sys
->
skeleton
.
major
,
p_demux
->
p_sys
->
skeleton
.
minor
)
<
0
)
p_stream
->
fmt
.
psz_description
=
NULL
;
}
static
void
Ogg_ReadSkeletonBones
(
demux_t
*
p_demux
,
ogg_packet
*
p_oggpacket
)
{
if
(
p_demux
->
p_sys
->
skeleton
.
major
<
3
||
p_oggpacket
->
bytes
<
52
)
return
;
/* Find the matching stream for this skeleton data */
ogg_int32_t
i_serialno
=
GetDWLE
(
&
p_oggpacket
->
packet
[
12
]
);
logical_stream_t
*
p_target_stream
=
NULL
;
for
(
int
i
=
0
;
i
<
p_demux
->
p_sys
->
i_streams
;
i
++
)
{
p_stream
->
fmt
.
i_cat
=
AUDIO_ES
;
p_stream
->
fmt
.
i_codec
=
VLC_CODEC_VORBIS
;
if
(
p_demux
->
p_sys
->
pp_stream
[
i
]
->
i_serial_no
==
i_serialno
)
{
p_target_stream
=
p_demux
->
p_sys
->
pp_stream
[
i
];
break
;
}
}
if
(
!
p_target_stream
)
return
;
p_stream
->
b_force_backup
=
true
;
ogg_skeleton_t
*
p_skel
=
p_target_stream
->
p_skel
;
if
(
!
p_skel
)
{
p_skel
=
malloc
(
sizeof
(
ogg_skeleton_t
)
);
if
(
!
p_skel
)
return
;
TAB_INIT
(
p_skel
->
i_messages
,
p_skel
->
ppsz_messages
);
p_skel
->
p_index
=
NULL
;
p_target_stream
->
p_skel
=
p_skel
;
}
else
if
(
!
strncmp
(
content_type_string
,
"audio/x-speex"
,
13
)
)
const
unsigned
char
*
p_messages
=
p_oggpacket
->
packet
+
8
+
GetDWLE
(
&
p_oggpacket
->
packet
[
8
]
);
const
unsigned
char
*
p_boundary
=
p_oggpacket
->
packet
+
p_oggpacket
->
bytes
;
const
unsigned
char
*
p
=
p_messages
;
while
(
p
<=
p_boundary
-
1
&&
p
>
p_oggpacket
->
packet
)
{
p_stream
->
fmt
.
i_cat
=
AUDIO_ES
;
p_stream
->
fmt
.
i_codec
=
VLC_CODEC_SPEEX
;
if
(
*
p
==
0x0D
&&
*
(
p
+
1
)
==
0x0A
)
{
char
*
psz_message
=
strndup
(
(
const
char
*
)
p_messages
,
p
-
p_messages
);
if
(
psz_message
)
{
msg_Dbg
(
p_demux
,
"stream %"
PRId32
" [%s]"
,
i_serialno
,
psz_message
);
TAB_APPEND
(
p_skel
->
i_messages
,
p_skel
->
ppsz_messages
,
psz_message
);
}
if
(
p
<
p_boundary
-
1
)
p_messages
=
p
+
2
;
}
p
++
;
}
p_stream
->
b_force_backup
=
true
;
}
/* Unpacks the 7bit variable encoding used in skeleton indexes */
unsigned
const
char
*
Read7BitsVariableLE
(
unsigned
const
char
*
p_begin
,
unsigned
const
char
const
*
p_end
,
uint64_t
*
pi_value
)
{
int
i_shift
=
0
;
int64_t
i_read
=
0
;
*
pi_value
=
0
;
while
(
p_begin
<
p_end
)
{
i_read
=
*
p_begin
&
0x7F
;
/* High bit is start of integer */
*
pi_value
=
*
pi_value
|
(
i_read
<<
i_shift
);
i_shift
+=
7
;
if
(
(
*
p_begin
++
&
0x80
)
==
0x80
)
break
;
/* see prev */
}
else
if
(
!
strncmp
(
content_type_string
,
"video/x-theora"
,
14
)
)
*
pi_value
=
GetQWLE
(
pi_value
);
return
p_begin
;
}
static
void
Ogg_ReadSkeletonIndex
(
demux_t
*
p_demux
,
ogg_packet
*
p_oggpacket
)
{
if
(
p_demux
->
p_sys
->
skeleton
.
major
<
4
||
p_oggpacket
->
bytes
<
44
/* Need at least 1 index value (42+1+1) */
)
return
;
/* Find the matching stream for this skeleton data */
int32_t
i_serialno
=
GetDWLE
(
&
p_oggpacket
->
packet
[
6
]
);
logical_stream_t
*
p_stream
=
NULL
;
for
(
int
i
=
0
;
i
<
p_demux
->
p_sys
->
i_streams
;
i
++
)
{
p_stream
->
fmt
.
i_cat
=
VIDEO_ES
;
p_stream
->
fmt
.
i_codec
=
VLC_CODEC_THEORA
;
if
(
p_demux
->
p_sys
->
pp_stream
[
i
]
->
i_serial_no
==
i_serialno
)
{
p_stream
=
p_demux
->
p_sys
->
pp_stream
[
i
];
break
;
}
}
if
(
!
p_stream
)
return
;
uint64_t
i_keypoints
=
GetQWLE
(
&
p_oggpacket
->
packet
[
10
]
);
msg_Dbg
(
p_demux
,
"%"
PRIi64
" index data for %"
PRIi32
,
i_keypoints
,
i_serialno
);
if
(
!
i_keypoints
)
return
;
p_stream
->
b_force_backup
=
true
;
p_stream
->
p_skel
->
i_indexstampden
=
GetQWLE
(
&
p_oggpacket
->
packet
[
18
]
);
p_stream
->
p_skel
->
i_indexfirstnum
=
GetQWLE
(
&
p_oggpacket
->
packet
[
24
]
);
p_stream
->
p_skel
->
i_indexlastnum
=
GetQWLE
(
&
p_oggpacket
->
packet
[
32
]
);
unsigned
const
char
*
p_fwdbyte
=
&
p_oggpacket
->
packet
[
42
];
unsigned
const
char
const
*
p_boundary
=
p_oggpacket
->
packet
+
p_oggpacket
->
bytes
;
uint64_t
i_offset
=
0
;
uint64_t
i_time
=
0
;
uint64_t
i_keypoints_found
=
0
;
while
(
p_fwdbyte
<
p_boundary
&&
i_keypoints_found
<
i_keypoints
)
{
uint64_t
i_val
;
p_fwdbyte
=
Read7BitsVariableLE
(
p_fwdbyte
,
p_boundary
,
&
i_val
);
i_offset
+=
i_val
;
p_fwdbyte
=
Read7BitsVariableLE
(
p_fwdbyte
,
p_boundary
,
&
i_val
);
i_time
+=
i_val
*
p_stream
->
p_skel
->
i_indexstampden
;
i_keypoints_found
++
;
}
else
if
(
!
strncmp
(
content_type_string
,
"video/x-xvid"
,
12
)
)
if
(
i_keypoints_found
!=
i_keypoints
)
{
p_stream
->
fmt
.
i_cat
=
VIDEO_ES
;
p_stream
->
fmt
.
i_codec
=
VLC_FOURCC
(
'x'
,
'v'
,
'i'
,
'd'
);
msg_Warn
(
p_demux
,
"Invalid Index: missing entries"
);
return
;
}
p_stream
->
b_force_backup
=
true
;
p_stream
->
p_skel
->
p_index
=
malloc
(
p_oggpacket
->
bytes
-
42
);
if
(
!
p_stream
->
p_skel
->
p_index
)
return
;
memcpy
(
p_stream
->
p_skel
->
p_index
,
&
p_oggpacket
->
packet
[
42
],
p_oggpacket
->
bytes
-
42
);
p_stream
->
p_skel
->
i_index
=
i_keypoints_found
;
p_stream
->
p_skel
->
i_index_size
=
p_oggpacket
->
bytes
-
42
;
}
static
void
Ogg_FreeSkeleton
(
ogg_skeleton_t
*
p_skel
)
{
if
(
!
p_skel
)
return
;
for
(
int
i
=
0
;
i
<
p_skel
->
i_messages
;
i
++
)
free
(
p_skel
->
ppsz_messages
[
i
]
);
TAB_CLEAN
(
p_skel
->
i_messages
,
p_skel
->
ppsz_messages
);
free
(
p_skel
->
p_index
);
free
(
p_skel
);
}
static
void
Ogg_ApplySkeleton
(
logical_stream_t
*
p_stream
)
{
if
(
!
p_stream
->
p_skel
)
return
;
for
(
int
i
=
0
;
i
<
p_stream
->
p_skel
->
i_messages
;
i
++
)
{
const
char
*
psz_message
=
p_stream
->
p_skel
->
ppsz_messages
[
i
];
if
(
!
strncmp
(
"Name: "
,
psz_message
,
6
)
)
{
free
(
p_stream
->
fmt
.
psz_description
);
p_stream
->
fmt
.
psz_description
=
strdup
(
psz_message
+
6
);
}
else
if
(
!
strncmp
(
content_type_string
,
"video/mpeg"
,
10
)
)
else
if
(
!
strncmp
(
"Content-Type: "
,
psz_message
,
14
)
)
{
/* n.b. MPEG streams are unsupported right now */
p_stream
->
fmt
.
i_cat
=
VIDEO_ES
;
p_stream
->
fmt
.
i_codec
=
VLC_CODEC_MPGV
;
bool
b_foo
;
Ogg_ApplyContentType
(
p_stream
,
psz_message
+
14
,
&
b_foo
,
&
b_foo
)
;
}
}
else
if
(
!
strncmp
(
content_type_string
,
"text/x-cmml"
,
11
)
)
}
/* Return true if there's a skeleton exact match */
bool
Ogg_GetBoundsUsingSkeletonIndex
(
logical_stream_t
*
p_stream
,
int64_t
i_time
,
int64_t
*
pi_lower
,
int64_t
*
pi_upper
)
{
if
(
!
p_stream
||
!
p_stream
->
p_skel
||
!
p_stream
->
p_skel
->
p_index
)
return
false
;
/* Validate range */
if
(
i_time
<
p_stream
->
p_skel
->
i_indexfirstnum
*
p_stream
->
p_skel
->
i_indexstampden
||
i_time
>
p_stream
->
p_skel
->
i_indexlastnum
*
p_stream
->
p_skel
->
i_indexstampden
)
return
false
;
/* Then Lookup its index */
unsigned
const
char
*
p_fwdbyte
=
p_stream
->
p_skel
->
p_index
;
struct
{
ogg_stream_packetout
(
&
p_stream
->
os
,
p_oggpacket
);
p_stream
->
fmt
.
i_cat
=
SPU_ES
;
p_stream
->
fmt
.
i_codec
=
VLC_CODEC_CMML
;
int64_t
i_pos
;
int64_t
i_time
;
}
current
=
{
0
,
0
},
prev
=
{
-
1
,
-
1
};
uint64_t
i_keypoints_found
=
0
;
while
(
p_fwdbyte
<
p_fwdbyte
+
p_stream
->
p_skel
->
i_index_size
&&
i_keypoints_found
<
p_stream
->
p_skel
->
i_index
)
{
uint64_t
i_val
;
p_fwdbyte
=
Read7BitsVariableLE
(
p_fwdbyte
,
p_fwdbyte
+
p_stream
->
p_skel
->
i_index_size
,
&
i_val
);
current
.
i_pos
+=
i_val
;
p_fwdbyte
=
Read7BitsVariableLE
(
p_fwdbyte
,
p_fwdbyte
+
p_stream
->
p_skel
->
i_index_size
,
&
i_val
);
current
.
i_time
+=
i_val
*
p_stream
->
p_skel
->
i_indexstampden
;
if
(
current
.
i_pos
<
0
||
current
.
i_time
<
0
)
break
;
i_keypoints_found
++
;
if
(
i_time
<=
current
.
i_time
)
{
*
pi_lower
=
prev
.
i_pos
;
*
pi_upper
=
current
.
i_pos
;
return
(
i_time
==
current
.
i_time
);
}
prev
=
current
;
}
return
false
;
}
static
uint32_t
dirac_uint
(
bs_t
*
p_bs
)
...
...
modules/demux/ogg.h
View file @
51cff6ef
...
...
@@ -41,6 +41,7 @@
#define PACKET_IS_SYNCPOINT 0x08
typedef
struct
oggseek_index_entry
demux_index_entry_t
;
typedef
struct
ogg_skeleton_t
ogg_skeleton_t
;
typedef
struct
logical_stream_s
{
...
...
@@ -57,6 +58,7 @@ typedef struct logical_stream_s
* data for the decoder. We back them up here in case we need to re-feed
* them to the decoder. */
bool
b_force_backup
;
bool
b_have_updated_format
;
int
i_packets_backup
;
int32_t
i_extra_headers_packets
;
void
*
p_headers
;
...
...
@@ -85,6 +87,9 @@ typedef struct logical_stream_s
/* keyframe index for seeking, created as we discover keyframes */
demux_index_entry_t
*
idx
;
/* Skeleton data */
ogg_skeleton_t
*
p_skel
;
/* skip some frames after a seek */
int
i_skip_frames
;
...
...
@@ -99,12 +104,25 @@ typedef struct logical_stream_s
}
logical_stream_t
;
struct
ogg_skeleton_t
{
int
i_messages
;
char
**
ppsz_messages
;
unsigned
char
*
p_index
;
uint64_t
i_index
;
uint64_t
i_index_size
;
int64_t
i_indexstampden
;
/* time denominator */
int64_t
i_indexfirstnum
;
/* first sample time numerator */
int64_t
i_indexlastnum
;
};
struct
demux_sys_t
{
ogg_sync_state
oy
;
/* sync and verify incoming physical bitstream */
int
i_streams
;
/* number of logical bitstreams */
logical_stream_t
**
pp_stream
;
/* pointer to an array of logical streams */
logical_stream_t
*
p_skelstream
;
/* pointer to skeleton stream if any */
logical_stream_t
*
p_old_stream
;
/* pointer to a old logical stream to avoid recreating it */
...
...
@@ -140,6 +158,13 @@ struct demux_sys_t
int
i_seekpoints
;
seekpoint_t
**
pp_seekpoints
;
/* skeleton */
struct
{
uint16_t
major
;
uint16_t
minor
;
}
skeleton
;
/* */
int
i_attachments
;
input_attachment_t
**
attachments
;
...
...
@@ -149,3 +174,10 @@ struct demux_sys_t
DemuxDebug
(
bool
b_seeked
;
)
};
unsigned
const
char
*
Read7BitsVariableLE
(
unsigned
const
char
*
,
unsigned
const
char
const
*
,
uint64_t
*
);
bool
Ogg_GetBoundsUsingSkeletonIndex
(
logical_stream_t
*
p_stream
,
int64_t
i_time
,
int64_t
*
pi_lower
,
int64_t
*
pi_upper
);
modules/demux/oggseek.c
View file @
51cff6ef
...
...
@@ -246,7 +246,6 @@ static bool OggSeekIndexFind ( logical_stream_t *p_stream, int64_t i_timestamp,
int64_t
*
pi_pos_lower
,
int64_t
*
pi_pos_upper
)
{
demux_index_entry_t
*
idx
=
p_stream
->
idx
;
*
pi_pos_lower
=
*
pi_pos_upper
=
-
1
;
while
(
idx
!=
NULL
)
{
...
...
@@ -553,7 +552,6 @@ clean:
ogg_stream_clear
(
&
os
);
}
/* convert a theora frame to a granulepos */
static
inline
int64_t
frame_to_gpos
(
logical_stream_t
*
p_stream
,
int64_t
i_kframe
,
...
...
@@ -1273,6 +1271,54 @@ static int64_t OggBisectSearchByTime( demux_t *p_demux, logical_stream_t *p_stre
* public functions
*************************************************************************/
int
Oggseek_BlindSeektoAbsoluteTime
(
demux_t
*
p_demux
,
logical_stream_t
*
p_stream
,
int64_t
i_time
,
bool
b_fastseek
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
int64_t
i_pos
=
-
1
;
int64_t
i_unusedpos
=
-
1
;
bool
b_found
=
false
;
/* Search in skeleton */
Ogg_GetBoundsUsingSkeletonIndex
(
p_stream
,
i_time
,
&
i_pos
,
&
i_unusedpos
);
if
(
i_pos
!=
-
1
)
b_found
=
true
;
/* And also search in our own index */
if
(
!
b_found
&&
OggSeekIndexFind
(
p_stream
,
i_time
,
&
i_pos
,
&
i_unusedpos
)
)
{
b_found
=
true
;
}
/* Or try to be smart with audio fixed bitrate streams */
if
(
!
b_found
&&
p_stream
->
fmt
.
i_cat
==
AUDIO_ES
&&
p_sys
->
i_streams
==
1
&&
p_sys
->
i_bitrate
&&
Ogg_GetKeyframeGranule
(
p_stream
,
0xFF00FF00
)
==
0xFF00FF00
)
{
/* But only if there's no keyframe/preload requirements */
/* FIXME: add function to get preload time by codec, ex: opus */
i_pos
=
i_time
*
p_sys
->
i_bitrate
/
INT64_C
(
8000000
);
b_found
=
true
;
}
/* or search */
if
(
!
b_found
&&
b_fastseek
)
{
i_pos
=
OggBisectSearchByTime
(
p_demux
,
p_stream
,
i_time
,
p_stream
->
i_data_start
,
p_sys
->
i_total_length
);
b_found
=
(
i_pos
!=
-
1
);
}
if
(
!
b_found
)
return
-
1
;
if
(
i_pos
<
p_stream
->
i_data_start
||
i_unusedpos
>
p_sys
->
i_total_length
)
return
-
1
;
/* And really do seek */
p_sys
->
i_input_position
=
i_pos
;
seek_byte
(
p_demux
,
p_sys
->
i_input_position
);
ogg_stream_reset
(
&
p_stream
->
os
);
return
i_pos
;
}
int
Oggseek_BlindSeektoPosition
(
demux_t
*
p_demux
,
logical_stream_t
*
p_stream
,
double
f
,
bool
b_canfastseek
)
...
...
@@ -1319,8 +1365,20 @@ int Oggseek_SeektoAbsolutetime( demux_t *p_demux, logical_stream_t *p_stream,
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
OggDebug
(
msg_Dbg
(
p_demux
,
"=================== Seeking To Absolute Time %"
PRId64
,
i_time
)
);
int64_t
i_offset_lower
=
p_stream
->
i_data_start
;
int64_t
i_offset_upper
=
p_sys
->
i_total_length
;
int64_t
i_offset_lower
=
-
1
;
int64_t
i_offset_upper
=
-
1
;
if
(
Ogg_GetBoundsUsingSkeletonIndex
(
p_stream
,
i_time
,
&
i_offset_lower
,
&
i_offset_upper
)
)
{
/* Exact match */
OggDebug
(
msg_Dbg
(
p_demux
,
"Found keyframe at %"
PRId64
" using skeleton index"
,
i_offset_lower
)
);
if
(
i_offset_lower
==
-
1
)
i_offset_lower
=
p_stream
->
i_data_start
;
p_sys
->
i_input_position
=
i_offset_lower
;
seek_byte
(
p_demux
,
p_sys
->
i_input_position
);
ogg_stream_reset
(
&
p_stream
->
os
);
return
i_offset_lower
;
}
OggDebug
(
msg_Dbg
(
p_demux
,
"Search bounds set to %"
PRId64
" %"
PRId64
" using skeleton index"
,
i_offset_lower
,
i_offset_upper
)
);
OggNoDebug
(
OggSeekIndexFind
(
p_stream
,
i_time
,
&
i_offset_lower
,
&
i_offset_upper
)
...
...
@@ -1420,4 +1478,3 @@ int64_t oggseek_read_page( demux_t *p_demux )
return
i_result
+
PAGE_HEADER_BYTES
+
i_nsegs
;
}
modules/demux/oggseek.h
View file @
51cff6ef
...
...
@@ -55,6 +55,7 @@ bool Ogg_IsKeyFrame ( logical_stream_t *, ogg_packet * );
int64_t
Oggseek_GranuleToAbsTimestamp
(
logical_stream_t
*
p_stream
,
int64_t
i_granule
,
bool
b_presentation
);
bool
Oggseek_PacketPCRFixup
(
logical_stream_t
*
p_stream
,
ogg_page
*
,
ogg_packet
*
);
int
Oggseek_BlindSeektoAbsoluteTime
(
demux_t
*
,
logical_stream_t
*
,
int64_t
,
bool
);
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
);
...
...
modules/mux/ogg.c
View file @
51cff6ef
...
...
@@ -289,6 +289,7 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
p_stream
->
p_oggds_header
=
0
;
/* FIXME: https://trac.videolan.org/vlc/ticket/1412 */
switch
(
p_input
->
p_fmt
->
i_cat
)
{
case
VIDEO_ES
:
...
...
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