Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-1.1
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-1.1
Commits
ac2a4ae1
Commit
ac2a4ae1
authored
Jun 22, 2003
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* mkv: better seeking support.
parent
a4b28e62
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
295 additions
and
203 deletions
+295
-203
modules/demux/mkv.cpp
modules/demux/mkv.cpp
+295
-203
No files found.
modules/demux/mkv.cpp
View file @
ac2a4ae1
...
...
@@ -2,7 +2,7 @@
* mkv.cpp : matroska demuxer
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: mkv.cpp,v 1.
2 2003/06/22 12:27:16
fenrir Exp $
* $Id: mkv.cpp,v 1.
3 2003/06/22 14:36:34
fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
...
...
@@ -399,6 +399,8 @@ typedef struct
int
i_data_init
;
uint8_t
*
p_data_init
;
/* hack : it's for seek */
vlc_bool_t
b_search_keyframe
;
}
mkv_track_t
;
typedef
struct
...
...
@@ -1443,211 +1445,30 @@ static void Deactivate( vlc_object_t *p_this )
free
(
p_sys
);
}
static
void
Seek
(
input_thread_t
*
p_input
,
mtime_t
i_date
,
int
i_percent
)
static
int
BlockGet
(
input_thread_t
*
p_input
,
KaxBlock
**
pp_block
,
int64_t
*
pi_ref1
,
int64_t
*
pi_ref2
,
int64_t
*
pi_duration
)
{
demux_sys_t
*
p_sys
=
p_input
->
p_demux_data
;
int
i_index
;
msg_Dbg
(
p_input
,
"seek request to %lld (%d%%)"
,
i_date
,
i_percent
);
for
(
i_index
=
0
;
i_index
<
p_sys
->
i_index
;
i_index
++
)
{
if
(
p_sys
->
index
[
i_index
].
i_time
>=
i_date
)
{
break
;
}
}
if
(
i_index
>
0
)
{
i_index
--
;
}
msg_Dbg
(
p_input
,
"seek got %lld (%d%%)"
,
p_sys
->
index
[
i_index
].
i_time
,
(
int
)(
100
*
p_sys
->
index
[
i_index
].
i_position
/
p_input
->
stream
.
p_selected_area
->
i_size
)
);
delete
p_sys
->
ep
;
p_sys
->
in
->
setFilePointer
(
p_sys
->
index
[
i_index
].
i_position
,
seek_beginning
);
p_sys
->
ep
=
new
EbmlParser
(
p_sys
->
es
,
p_sys
->
segment
);
// p_sys->cluster = p_sys->es->FindNextElement( p_sys->segment->Generic().Context,
// i_ulev, 0xFFFFFFFFL, true, 1);
}
/*****************************************************************************
* Demux: reads and demuxes data packets
*****************************************************************************
* Returns -1 in case of error, 0 in case of EOF, 1 otherwise
*****************************************************************************/
static
int
Demux
(
input_thread_t
*
p_input
)
{
demux_sys_t
*
p_sys
=
p_input
->
p_demux_data
;
mtime_t
i_start_pts
=
p_sys
->
i_pts
;
KaxBlock
*
block
=
NULL
;
int64_t
i_block_duration
=
-
1
;
int64_t
i_block_ref1
=
0
;
int64_t
i_block_ref2
=
0
;
if
(
p_input
->
stream
.
p_selected_program
->
i_synchro_state
==
SYNCHRO_REINIT
)
{
mtime_t
i_duration
=
(
mtime_t
)(
p_sys
->
f_duration
/
1000
);
mtime_t
i_date
;
int
i_percent
;
i_date
=
(
mtime_t
)
1000000
*
(
mtime_t
)
i_duration
*
(
mtime_t
)
p_sys
->
in
->
getFilePointer
()
/
(
mtime_t
)
p_input
->
stream
.
p_selected_area
->
i_size
;
i_percent
=
100
*
p_sys
->
in
->
getFilePointer
()
/
p_input
->
stream
.
p_selected_area
->
i_size
;
Seek
(
p_input
,
i_date
,
i_percent
);
i_start_pts
=
-
1
;
}
*
pp_block
=
NULL
;
*
pi_ref1
=
-
1
;
*
pi_ref2
=
-
1
;
for
(
;;
)
{
EbmlElement
*
el
;
int
i_level
;
if
(
p_input
->
b_die
)
{
return
VLC_EGENERIC
;
}
el
=
p_sys
->
ep
->
Get
();
i_level
=
p_sys
->
ep
->
GetLevel
();
/* First send last collected blocks (before ep->Up, because of cluster) */
if
(
el
==
NULL
&&
block
!=
NULL
)
if
(
el
==
NULL
&&
*
pp_block
!=
NULL
)
{
/* we have data */
int
i_track
;
#define tk p_sys->track[i_track]
for
(
i_track
=
0
;
i_track
<
p_sys
->
i_track
;
i_track
++
)
{
if
(
tk
.
i_number
==
block
->
TrackNum
()
)
{
break
;
}
}
p_sys
->
i_pts
=
block
->
GlobalTimecode
()
*
(
mtime_t
)
1000
/
p_sys
->
i_timescale
;
if
(
p_sys
->
i_pts
>
0
)
{
input_ClockManageRef
(
p_input
,
p_input
->
stream
.
p_selected_program
,
p_sys
->
i_pts
*
9
/
100
);
}
if
(
i_track
>=
p_sys
->
i_track
)
{
msg_Err
(
p_input
,
"invalid track number=%d"
,
block
->
TrackNum
()
);
}
else
if
(
tk
.
p_es
->
p_decoder_fifo
!=
NULL
)
{
pes_packet_t
*
p_pes
;
unsigned
int
i
;
if
(
(
p_pes
=
input_NewPES
(
p_input
->
p_method_data
)
)
!=
NULL
)
{
mtime_t
i_pts
;
i_pts
=
input_ClockGetTS
(
p_input
,
p_input
->
stream
.
p_selected_program
,
p_sys
->
i_pts
*
9
/
100
);
p_pes
->
i_pts
=
i_pts
;
p_pes
->
i_dts
=
i_pts
;
if
(
tk
.
i_cat
==
SPU_ES
)
{
/* special case : dts mean end of display */
if
(
i_block_duration
>
0
)
{
/* FIXME not sure about that */
p_pes
->
i_dts
+=
i_block_duration
*
1000
;
// * (mtime_t) 1000 / p_sys->i_timescale;
}
else
{
/* unknown */
p_pes
->
i_dts
=
0
;
}
}
p_pes
->
p_first
=
p_pes
->
p_last
=
NULL
;
p_pes
->
i_nb_data
=
0
;
p_pes
->
i_pes_size
=
0
;
for
(
i
=
0
;
i
<
block
->
NumberFrames
();
i
++
)
{
data_packet_t
*
p_data
=
NULL
;
DataBuffer
&
data
=
block
->
GetBuffer
(
i
);
if
(
(
p_data
=
input_NewPacket
(
p_input
->
p_method_data
,
data
.
Size
()
)
)
!=
NULL
)
{
memcpy
(
p_data
->
p_payload_start
,
data
.
Buffer
(),
data
.
Size
()
);
p_data
->
p_payload_end
=
p_data
->
p_payload_start
+
data
.
Size
();
if
(
p_pes
->
p_first
==
NULL
)
{
p_pes
->
p_first
=
p_data
;
}
else
{
p_pes
->
p_last
->
p_next
=
p_data
;
}
p_pes
->
i_nb_data
++
;
p_pes
->
i_pes_size
+=
data
.
Size
();
p_pes
->
p_last
=
p_data
;
}
}
if
(
tk
.
i_cat
==
SPU_ES
&&
p_pes
->
p_first
&&
p_pes
->
i_pes_size
>
0
)
{
p_pes
->
p_first
->
p_payload_end
[
-
1
]
=
'\0'
;
}
if
(
!
tk
.
b_inited
&&
tk
.
i_data_init
>
0
)
{
pes_packet_t
*
p_init
;
data_packet_t
*
p_data
;
msg_Dbg
(
p_input
,
"sending header (%d bytes)"
,
tk
.
i_data_init
);
p_init
=
input_NewPES
(
p_input
->
p_method_data
);
p_data
=
input_NewPacket
(
p_input
->
p_method_data
,
tk
.
i_data_init
);
memcpy
(
p_data
->
p_payload_start
,
tk
.
p_data_init
,
tk
.
i_data_init
);
p_data
->
p_payload_end
=
p_data
->
p_payload_start
+
tk
.
i_data_init
;
p_init
->
p_first
=
p_init
->
p_last
=
p_data
;
p_init
->
i_nb_data
=
1
;
p_init
->
i_pes_size
=
tk
.
i_data_init
;
input_DecodePES
(
tk
.
p_es
->
p_decoder_fifo
,
p_init
);
}
tk
.
b_inited
=
VLC_TRUE
;
input_DecodePES
(
tk
.
p_es
->
p_decoder_fifo
,
p_pes
);
}
else
{
tk
.
b_inited
=
VLC_FALSE
;
}
}
#undef tk
delete
block
;
block
=
NULL
;
if
(
i_start_pts
==
-
1
)
{
i_start_pts
=
p_sys
->
i_pts
;
}
else
if
(
p_sys
->
i_pts
>
i_start_pts
+
(
mtime_t
)
100000
)
{
return
1
;
}
return
VLC_SUCCESS
;
}
if
(
el
==
NULL
)
...
...
@@ -1658,7 +1479,7 @@ static int Demux( input_thread_t * p_input )
continue
;
}
msg_Warn
(
p_input
,
"EOF"
);
return
0
;
return
VLC_EGENERIC
;
}
/* do parsing */
...
...
@@ -1672,7 +1493,7 @@ static int Demux( input_thread_t * p_input )
else
if
(
EbmlId
(
*
el
)
==
KaxCues
::
ClassInfos
.
GlobalId
)
{
msg_Warn
(
p_input
,
"find KaxCues FIXME"
);
return
0
;
return
VLC_EGENERIC
;
}
else
{
...
...
@@ -1697,10 +1518,10 @@ static int Demux( input_thread_t * p_input )
{
if
(
EbmlId
(
*
el
)
==
KaxBlock
::
ClassInfos
.
GlobalId
)
{
block
=
(
KaxBlock
*
)
el
;
*
pp_
block
=
(
KaxBlock
*
)
el
;
block
->
ReadData
(
p_sys
->
es
->
I_O
()
);
block
->
SetParent
(
*
p_sys
->
cluster
);
(
*
pp_block
)
->
ReadData
(
p_sys
->
es
->
I_O
()
);
(
*
pp_block
)
->
SetParent
(
*
p_sys
->
cluster
);
p_sys
->
ep
->
Keep
();
}
...
...
@@ -1709,30 +1530,301 @@ static int Demux( input_thread_t * p_input )
KaxBlockDuration
&
dur
=
*
(
KaxBlockDuration
*
)
el
;
dur
.
ReadData
(
p_sys
->
es
->
I_O
()
);
i_block
_duration
=
uint64
(
dur
);
*
pi
_duration
=
uint64
(
dur
);
}
else
if
(
EbmlId
(
*
el
)
==
KaxReferenceBlock
::
ClassInfos
.
GlobalId
)
{
KaxReferenceBlock
&
ref
=
*
(
KaxReferenceBlock
*
)
el
;
ref
.
ReadData
(
p_sys
->
es
->
I_O
()
);
if
(
i_block_ref1
==
0
)
if
(
*
pi_ref1
==
-
1
)
{
i_block
_ref1
=
int64
(
ref
);
*
pi
_ref1
=
int64
(
ref
);
}
else
{
i_block
_ref2
=
int64
(
ref
);
*
pi
_ref2
=
int64
(
ref
);
}
}
}
else
{
msg_Err
(
p_input
,
"invalid level = %d"
,
i_level
);
return
0
;
return
VLC_EGENERIC
;
}
}
}
static
void
BlockDecode
(
input_thread_t
*
p_input
,
KaxBlock
*
block
,
mtime_t
i_pts
,
mtime_t
i_duration
)
{
demux_sys_t
*
p_sys
=
p_input
->
p_demux_data
;
int
i_track
;
pes_packet_t
*
p_pes
;
unsigned
int
i
;
#define tk p_sys->track[i_track]
for
(
i_track
=
0
;
i_track
<
p_sys
->
i_track
;
i_track
++
)
{
if
(
tk
.
i_number
==
block
->
TrackNum
()
)
{
break
;
}
}
if
(
i_track
>=
p_sys
->
i_track
)
{
msg_Err
(
p_input
,
"invalid track number=%d"
,
block
->
TrackNum
()
);
delete
block
;
return
;
}
if
(
tk
.
p_es
->
p_decoder_fifo
==
NULL
)
{
delete
block
;
return
;
}
if
(
(
p_pes
=
input_NewPES
(
p_input
->
p_method_data
)
)
==
NULL
)
{
msg_Err
(
p_input
,
"cannot allocate PES"
);
}
p_pes
->
i_pts
=
i_pts
;
p_pes
->
i_dts
=
i_pts
;
if
(
tk
.
i_cat
==
SPU_ES
)
{
/* special case : dts mean end of display */
if
(
i_duration
>
0
)
{
/* FIXME not sure about that */
p_pes
->
i_dts
+=
i_duration
*
1000
;
// * (mtime_t) 1000 / p_sys->i_timescale;
}
else
{
/* unknown */
p_pes
->
i_dts
=
0
;
}
}
p_pes
->
p_first
=
p_pes
->
p_last
=
NULL
;
p_pes
->
i_nb_data
=
0
;
p_pes
->
i_pes_size
=
0
;
for
(
i
=
0
;
i
<
block
->
NumberFrames
();
i
++
)
{
data_packet_t
*
p_data
=
NULL
;
DataBuffer
&
data
=
block
->
GetBuffer
(
i
);
if
(
(
p_data
=
input_NewPacket
(
p_input
->
p_method_data
,
data
.
Size
()
)
)
!=
NULL
)
{
memcpy
(
p_data
->
p_payload_start
,
data
.
Buffer
(),
data
.
Size
()
);
p_data
->
p_payload_end
=
p_data
->
p_payload_start
+
data
.
Size
();
if
(
p_pes
->
p_first
==
NULL
)
{
p_pes
->
p_first
=
p_data
;
}
else
{
p_pes
->
p_last
->
p_next
=
p_data
;
}
p_pes
->
i_nb_data
++
;
p_pes
->
i_pes_size
+=
data
.
Size
();
p_pes
->
p_last
=
p_data
;
}
}
if
(
tk
.
i_cat
==
SPU_ES
&&
p_pes
->
p_first
&&
p_pes
->
i_pes_size
>
0
)
{
p_pes
->
p_first
->
p_payload_end
[
-
1
]
=
'\0'
;
}
if
(
!
tk
.
b_inited
&&
tk
.
i_data_init
>
0
)
{
pes_packet_t
*
p_init
;
data_packet_t
*
p_data
;
msg_Dbg
(
p_input
,
"sending header (%d bytes)"
,
tk
.
i_data_init
);
p_init
=
input_NewPES
(
p_input
->
p_method_data
);
p_data
=
input_NewPacket
(
p_input
->
p_method_data
,
tk
.
i_data_init
);
memcpy
(
p_data
->
p_payload_start
,
tk
.
p_data_init
,
tk
.
i_data_init
);
p_data
->
p_payload_end
=
p_data
->
p_payload_start
+
tk
.
i_data_init
;
p_init
->
p_first
=
p_init
->
p_last
=
p_data
;
p_init
->
i_nb_data
=
1
;
p_init
->
i_pes_size
=
tk
.
i_data_init
;
input_DecodePES
(
tk
.
p_es
->
p_decoder_fifo
,
p_init
);
}
tk
.
b_inited
=
VLC_TRUE
;
input_DecodePES
(
tk
.
p_es
->
p_decoder_fifo
,
p_pes
);
#undef tk
}
static
void
Seek
(
input_thread_t
*
p_input
,
mtime_t
i_date
,
int
i_percent
)
{
demux_sys_t
*
p_sys
=
p_input
->
p_demux_data
;
KaxBlock
*
block
;
int64_t
i_block_duration
;
int64_t
i_block_ref1
;
int64_t
i_block_ref2
;
int
i_index
;
int
i_track_skipping
;
int
i_track
;
msg_Dbg
(
p_input
,
"seek request to %lld (%d%%)"
,
i_date
,
i_percent
);
for
(
i_index
=
0
;
i_index
<
p_sys
->
i_index
;
i_index
++
)
{
if
(
p_sys
->
index
[
i_index
].
i_time
>=
i_date
)
{
break
;
}
}
if
(
i_index
>
0
)
{
i_index
--
;
}
msg_Dbg
(
p_input
,
"seek got %lld (%d%%)"
,
p_sys
->
index
[
i_index
].
i_time
,
(
int
)(
100
*
p_sys
->
index
[
i_index
].
i_position
/
p_input
->
stream
.
p_selected_area
->
i_size
)
);
delete
p_sys
->
ep
;
p_sys
->
in
->
setFilePointer
(
p_sys
->
index
[
i_index
].
i_position
,
seek_beginning
);
p_sys
->
ep
=
new
EbmlParser
(
p_sys
->
es
,
p_sys
->
segment
);
/* now parse until key frame */
#define tk p_sys->track[i_track]
i_track_skipping
=
0
;
for
(
i_track
=
0
;
i_track
<
p_sys
->
i_track
;
i_track
++
)
{
if
(
tk
.
i_cat
==
VIDEO_ES
)
{
tk
.
b_search_keyframe
=
VLC_TRUE
;
i_track_skipping
++
;
}
}
while
(
i_track_skipping
>
0
)
{
if
(
BlockGet
(
p_input
,
&
block
,
&
i_block_ref1
,
&
i_block_ref2
,
&
i_block_duration
)
)
{
msg_Warn
(
p_input
,
"cannot get block EOF?"
);
return
;
}
p_sys
->
i_pts
=
block
->
GlobalTimecode
()
*
(
mtime_t
)
1000
/
p_sys
->
i_timescale
;
for
(
i_track
=
0
;
i_track
<
p_sys
->
i_track
;
i_track
++
)
{
if
(
tk
.
i_number
==
block
->
TrackNum
()
)
{
break
;
}
}
if
(
i_track
<
p_sys
->
i_track
)
{
if
(
tk
.
i_cat
==
VIDEO_ES
&&
i_block_ref1
==
-
1
&&
tk
.
b_search_keyframe
)
{
tk
.
b_search_keyframe
=
VLC_FALSE
;
i_track_skipping
--
;
}
if
(
tk
.
i_cat
==
VIDEO_ES
&&
!
tk
.
b_search_keyframe
)
{
BlockDecode
(
p_input
,
block
,
0
,
0
);
}
}
delete
block
;
}
#undef tk
}
/*****************************************************************************
* Demux: reads and demuxes data packets
*****************************************************************************
* Returns -1 in case of error, 0 in case of EOF, 1 otherwise
*****************************************************************************/
static
int
Demux
(
input_thread_t
*
p_input
)
{
demux_sys_t
*
p_sys
=
p_input
->
p_demux_data
;
mtime_t
i_start_pts
;
KaxBlock
*
block
;
int64_t
i_block_duration
;
int64_t
i_block_ref1
;
int64_t
i_block_ref2
;
if
(
p_input
->
stream
.
p_selected_program
->
i_synchro_state
==
SYNCHRO_REINIT
)
{
mtime_t
i_duration
=
(
mtime_t
)(
p_sys
->
f_duration
/
1000
);
mtime_t
i_date
;
int
i_percent
;
i_date
=
(
mtime_t
)
1000000
*
(
mtime_t
)
i_duration
*
(
mtime_t
)
p_sys
->
in
->
getFilePointer
()
/
(
mtime_t
)
p_input
->
stream
.
p_selected_area
->
i_size
;
i_percent
=
100
*
p_sys
->
in
->
getFilePointer
()
/
p_input
->
stream
.
p_selected_area
->
i_size
;
Seek
(
p_input
,
i_date
,
i_percent
);
}
i_start_pts
=
p_sys
->
i_pts
;
for
(
;;
)
{
mtime_t
i_pts
;
if
(
BlockGet
(
p_input
,
&
block
,
&
i_block_ref1
,
&
i_block_ref2
,
&
i_block_duration
)
)
{
msg_Warn
(
p_input
,
"cannot get block EOF?"
);
return
0
;
}
p_sys
->
i_pts
=
block
->
GlobalTimecode
()
*
(
mtime_t
)
1000
/
p_sys
->
i_timescale
;
if
(
p_sys
->
i_pts
>
0
)
{
input_ClockManageRef
(
p_input
,
p_input
->
stream
.
p_selected_program
,
p_sys
->
i_pts
*
9
/
100
);
}
i_pts
=
input_ClockGetTS
(
p_input
,
p_input
->
stream
.
p_selected_program
,
p_sys
->
i_pts
*
9
/
100
);
BlockDecode
(
p_input
,
block
,
i_pts
,
i_block_duration
);
delete
block
;
if
(
i_start_pts
==
-
1
)
{
i_start_pts
=
p_sys
->
i_pts
;
}
else
if
(
p_sys
->
i_pts
>
i_start_pts
+
(
mtime_t
)
100000
)
{
return
1
;
}
}
}
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