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
cb5f74d6
Commit
cb5f74d6
authored
Oct 07, 2011
by
Naohiro KORIYAMA
Committed by
Laurent Aimar
Oct 08, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
TS demux: Enhance TS demuxer to support duration and current time
It closes #2985.
parent
bd55fe88
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
425 additions
and
91 deletions
+425
-91
modules/demux/ts.c
modules/demux/ts.c
+425
-91
No files found.
modules/demux/ts.c
View file @
cb5f74d6
...
@@ -138,6 +138,12 @@ static void Close ( vlc_object_t * );
...
@@ -138,6 +138,12 @@ static void Close ( vlc_object_t * );
"Separate teletex/dvbs pages into independent ES. " \
"Separate teletex/dvbs pages into independent ES. " \
"It can be useful to turn off this option when using stream output." )
"It can be useful to turn off this option when using stream output." )
#define SEEK_PERCENT_TEXT N_("Seek based on percent not time")
#define SEEK_PERCENT_LONGTEXT N_( \
"Seek and position based on a percent byte position, not a PCR generated " \
"time position. If seeking doesn't work propery, turn on this option." )
vlc_module_begin
()
vlc_module_begin
()
set_description
(
N_
(
"MPEG Transport Stream demuxer"
)
)
set_description
(
N_
(
"MPEG Transport Stream demuxer"
)
)
set_shortname
(
"MPEG-TS"
)
set_shortname
(
"MPEG-TS"
)
...
@@ -165,6 +171,7 @@ vlc_module_begin ()
...
@@ -165,6 +171,7 @@ vlc_module_begin ()
add_integer
(
"ts-dump-size"
,
16384
,
DUMPSIZE_TEXT
,
add_integer
(
"ts-dump-size"
,
16384
,
DUMPSIZE_TEXT
,
DUMPSIZE_LONGTEXT
,
true
)
DUMPSIZE_LONGTEXT
,
true
)
add_bool
(
"ts-split-es"
,
true
,
SPLIT_ES_TEXT
,
SPLIT_ES_LONGTEXT
,
false
)
add_bool
(
"ts-split-es"
,
true
,
SPLIT_ES_TEXT
,
SPLIT_ES_LONGTEXT
,
false
)
add_bool
(
"ts-seek-percent"
,
false
,
SEEK_PERCENT_TEXT
,
SEEK_PERCENT_LONGTEXT
,
true
)
set_capability
(
"demux"
,
10
)
set_capability
(
"demux"
,
10
)
set_callbacks
(
Open
,
Close
)
set_callbacks
(
Open
,
Close
)
...
@@ -336,6 +343,16 @@ struct demux_sys_t
...
@@ -336,6 +343,16 @@ struct demux_sys_t
/* how many TS packet we read at once */
/* how many TS packet we read at once */
int
i_ts_read
;
int
i_ts_read
;
/* to determine length and time */
int
i_pid_ref_pcr
;
mtime_t
i_first_pcr
;
mtime_t
i_current_pcr
;
mtime_t
i_last_pcr
;
bool
b_force_seek_per_percent
;
int
i_pcrs_num
;
mtime_t
*
p_pcrs
;
int64_t
*
p_pos
;
/* All pid */
/* All pid */
ts_pid_t
pid
[
8192
];
ts_pid_t
pid
[
8192
];
...
@@ -401,6 +418,13 @@ static inline int PIDGet( block_t *p )
...
@@ -401,6 +418,13 @@ static inline int PIDGet( block_t *p )
static
bool
GatherPES
(
demux_t
*
p_demux
,
ts_pid_t
*
pid
,
block_t
*
p_bk
);
static
bool
GatherPES
(
demux_t
*
p_demux
,
ts_pid_t
*
pid
,
block_t
*
p_bk
);
static
block_t
*
ReadTSPacket
(
demux_t
*
p_demux
);
static
mtime_t
GetPCR
(
block_t
*
p_pkt
);
static
int
SeekToPCR
(
demux_t
*
p_demux
,
int64_t
i_pos
);
static
int
Seek
(
demux_t
*
p_demux
,
double
f_percent
);
static
void
GetFirstPCR
(
demux_t
*
p_demux
);
static
void
GetLastPCR
(
demux_t
*
p_demux
);
static
void
CheckPCR
(
demux_t
*
p_demux
);
static
void
PCRHandle
(
demux_t
*
p_demux
,
ts_pid_t
*
,
block_t
*
);
static
void
PCRHandle
(
demux_t
*
p_demux
,
ts_pid_t
*
,
block_t
*
);
static
iod_descriptor_t
*
IODNew
(
int
,
uint8_t
*
);
static
iod_descriptor_t
*
IODNew
(
int
,
uint8_t
*
);
...
@@ -788,6 +812,28 @@ static int Open( vlc_object_t *p_this )
...
@@ -788,6 +812,28 @@ static int Open( vlc_object_t *p_this )
p_sys
->
b_silent
=
var_CreateGetBool
(
p_demux
,
"ts-silent"
);
p_sys
->
b_silent
=
var_CreateGetBool
(
p_demux
,
"ts-silent"
);
p_sys
->
b_split_es
=
var_InheritBool
(
p_demux
,
"ts-split-es"
);
p_sys
->
b_split_es
=
var_InheritBool
(
p_demux
,
"ts-split-es"
);
p_sys
->
i_pid_ref_pcr
=
-
1
;
p_sys
->
i_first_pcr
=
-
1
;
p_sys
->
i_current_pcr
=
-
1
;
p_sys
->
i_last_pcr
=
-
1
;
p_sys
->
b_force_seek_per_percent
=
var_InheritBool
(
p_demux
,
"ts-seek-percent"
);
p_sys
->
i_pcrs_num
=
10
;
p_sys
->
p_pcrs
=
(
mtime_t
*
)
calloc
(
p_sys
->
i_pcrs_num
,
sizeof
(
mtime_t
)
);
p_sys
->
p_pos
=
(
int64_t
*
)
calloc
(
p_sys
->
i_pcrs_num
,
sizeof
(
int64_t
)
);
bool
can_seek
=
false
;
stream_Control
(
p_demux
->
s
,
STREAM_CAN_SEEK
,
&
can_seek
);
if
(
can_seek
)
{
GetFirstPCR
(
p_demux
);
CheckPCR
(
p_demux
);
GetLastPCR
(
p_demux
);
}
if
(
p_sys
->
i_first_pcr
<
0
||
p_sys
->
i_last_pcr
<
0
)
{
p_sys
->
b_force_seek_per_percent
=
true
;
}
while
(
!
p_sys
->
b_file_out
&&
p_sys
->
i_pmt_es
<=
0
&&
while
(
!
p_sys
->
b_file_out
&&
p_sys
->
i_pmt_es
<=
0
&&
vlc_object_alive
(
p_demux
)
)
vlc_object_alive
(
p_demux
)
)
{
{
...
@@ -885,6 +931,9 @@ static void Close( vlc_object_t *p_this )
...
@@ -885,6 +931,9 @@ static void Close( vlc_object_t *p_this )
free
(
p_sys
->
buffer
);
free
(
p_sys
->
buffer
);
free
(
p_sys
->
psz_file
);
free
(
p_sys
->
psz_file
);
free
(
p_sys
->
p_pcrs
);
free
(
p_sys
->
p_pos
);
vlc_mutex_destroy
(
&
p_sys
->
csa_lock
);
vlc_mutex_destroy
(
&
p_sys
->
csa_lock
);
free
(
p_sys
);
free
(
p_sys
);
}
}
...
@@ -1026,59 +1075,11 @@ static int Demux( demux_t *p_demux )
...
@@ -1026,59 +1075,11 @@ static int Demux( demux_t *p_demux )
{
{
bool
b_frame
=
false
;
bool
b_frame
=
false
;
block_t
*
p_pkt
;
block_t
*
p_pkt
;
if
(
!
(
p_pkt
=
ReadTSPacket
(
p_demux
))
)
/* Get a new TS packet */
if
(
!
(
p_pkt
=
stream_Block
(
p_demux
->
s
,
p_sys
->
i_packet_size
)
)
)
{
{
msg_Dbg
(
p_demux
,
"eof ?"
);
return
0
;
return
0
;
}
}
/* Check sync byte and re-sync if needed */
if
(
p_pkt
->
p_buffer
[
0
]
!=
0x47
)
{
msg_Warn
(
p_demux
,
"lost synchro"
);
block_Release
(
p_pkt
);
while
(
vlc_object_alive
(
p_demux
)
)
{
const
uint8_t
*
p_peek
;
int
i_peek
,
i_skip
=
0
;
i_peek
=
stream_Peek
(
p_demux
->
s
,
&
p_peek
,
p_sys
->
i_packet_size
*
10
);
if
(
i_peek
<
p_sys
->
i_packet_size
+
1
)
{
msg_Dbg
(
p_demux
,
"eof ?"
);
return
0
;
}
while
(
i_skip
<
i_peek
-
p_sys
->
i_packet_size
)
{
if
(
p_peek
[
i_skip
]
==
0x47
&&
p_peek
[
i_skip
+
p_sys
->
i_packet_size
]
==
0x47
)
{
break
;
}
i_skip
++
;
}
msg_Dbg
(
p_demux
,
"skipping %d bytes of garbage"
,
i_skip
);
stream_Read
(
p_demux
->
s
,
NULL
,
i_skip
);
if
(
i_skip
<
i_peek
-
p_sys
->
i_packet_size
)
{
break
;
}
}
if
(
!
(
p_pkt
=
stream_Block
(
p_demux
->
s
,
p_sys
->
i_packet_size
)
)
)
{
msg_Dbg
(
p_demux
,
"eof ?"
);
return
0
;
}
}
if
(
p_sys
->
b_start_record
)
if
(
p_sys
->
b_start_record
)
{
{
/* Enable recording once synchronized */
/* Enable recording once synchronized */
...
@@ -1196,64 +1197,83 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
...
@@ -1196,64 +1197,83 @@ static int Control( demux_t *p_demux, int i_query, va_list args )
{
{
case
DEMUX_GET_POSITION
:
case
DEMUX_GET_POSITION
:
pf
=
(
double
*
)
va_arg
(
args
,
double
*
);
pf
=
(
double
*
)
va_arg
(
args
,
double
*
);
i64
=
stream_Size
(
p_demux
->
s
);
if
(
i64
>
0
)
if
(
p_sys
->
b_force_seek_per_percent
||
{
(
p_sys
->
b_dvb_meta
&&
p_sys
->
b_access_control
)
||
double
f_current
=
stream_Tell
(
p_demux
->
s
);
p_sys
->
i_first_pcr
<
0
||
*
pf
=
f_current
/
(
double
)
i64
;
p_sys
->
i_current_pcr
-
p_sys
->
i_first_pcr
<
0
||
}
p_sys
->
i_last_pcr
-
p_sys
->
i_first_pcr
<=
0
)
else
{
{
int64_t
i_time
,
i_length
;
int64_t
i_time
,
i_length
;
if
(
!
DVBEventInformation
(
p_demux
,
&
i_time
,
&
i_length
)
&&
i_length
>
0
)
if
(
!
DVBEventInformation
(
p_demux
,
&
i_time
,
&
i_length
)
&&
i_length
>
0
)
*
pf
=
(
double
)
i_time
/
(
double
)
i_length
;
*
pf
=
(
double
)
i_time
/
(
double
)
i_length
;
else
if
(
(
i64
=
stream_Size
(
p_demux
->
s
)
)
>
0
)
*
pf
=
(
double
)
stream_Tell
(
p_demux
->
s
)
/
(
double
)
i64
;
else
else
*
pf
=
0
.
0
;
*
pf
=
0
.
0
;
}
}
else
{
*
pf
=
(
double
)(
p_sys
->
i_current_pcr
-
p_sys
->
i_first_pcr
)
/
(
double
)(
p_sys
->
i_last_pcr
-
p_sys
->
i_first_pcr
);
}
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
case
DEMUX_SET_POSITION
:
case
DEMUX_SET_POSITION
:
f
=
(
double
)
va_arg
(
args
,
double
);
f
=
(
double
)
va_arg
(
args
,
double
);
i64
=
stream_Size
(
p_demux
->
s
);
if
(
stream_Seek
(
p_demux
->
s
,
(
int64_t
)(
i64
*
f
)
)
)
return
VLC_EGENERIC
;
if
(
p_sys
->
b_force_seek_per_percent
||
(
p_sys
->
b_dvb_meta
&&
p_sys
->
b_access_control
)
||
p_sys
->
i_first_pcr
<
0
||
p_sys
->
i_last_pcr
-
p_sys
->
i_first_pcr
<=
0
)
{
i64
=
stream_Size
(
p_demux
->
s
);
if
(
stream_Seek
(
p_demux
->
s
,
(
int64_t
)(
i64
*
f
)
)
)
return
VLC_EGENERIC
;
}
else
{
if
(
Seek
(
p_demux
,
f
)
)
{
p_sys
->
b_force_seek_per_percent
=
true
;
return
VLC_EGENERIC
;
}
}
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
#if 0
case
DEMUX_GET_TIME
:
case
DEMUX_GET_TIME
:
pi64
=
(
int64_t
*
)
va_arg
(
args
,
int64_t
*
);
pi64
=
(
int64_t
*
)
va_arg
(
args
,
int64_t
*
);
if( p_sys->i_time < 0 )
if
(
(
p_sys
->
b_dvb_meta
&&
p_sys
->
b_access_control
)
||
p_sys
->
i_first_pcr
<
0
||
p_sys
->
i_current_pcr
-
p_sys
->
i_first_pcr
<
0
)
{
{
*pi64 = 0;
if
(
DVBEventInformation
(
p_demux
,
pi64
,
NULL
)
)
return VLC_EGENERIC;
{
*
pi64
=
0
;
}
}
else
{
*
pi64
=
(
p_sys
->
i_current_pcr
-
p_sys
->
i_first_pcr
)
*
100
/
9
;
}
}
*pi64 = p_sys->i_time;
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
case
DEMUX_GET_LENGTH
:
case
DEMUX_GET_LENGTH
:
pi64
=
(
int64_t
*
)
va_arg
(
args
,
int64_t
*
);
pi64
=
(
int64_t
*
)
va_arg
(
args
,
int64_t
*
);
if( p_sys->i_mux_rate > 0 )
if
(
(
p_sys
->
b_dvb_meta
&&
p_sys
->
b_access_control
)
||
p_sys
->
i_first_pcr
<
0
||
p_sys
->
i_last_pcr
-
p_sys
->
i_first_pcr
<=
0
)
{
{
*pi64 = INT64_C(1000000) * ( stream_Size( p_demux->s ) / 50 ) /
if
(
DVBEventInformation
(
p_demux
,
NULL
,
pi64
)
)
p_sys->i_mux_rate;
{
return VLC_SUCCESS;
*
pi64
=
0
;
}
}
else
{
*
pi64
=
(
p_sys
->
i_last_pcr
-
p_sys
->
i_first_pcr
)
*
100
/
9
;
}
}
*pi64 = 0;
return VLC_EGENERIC;
#else
case
DEMUX_GET_TIME
:
pi64
=
(
int64_t
*
)
va_arg
(
args
,
int64_t
*
);
if
(
DVBEventInformation
(
p_demux
,
pi64
,
NULL
)
)
*
pi64
=
0
;
return
VLC_SUCCESS
;
return
VLC_SUCCESS
;
case
DEMUX_GET_LENGTH
:
pi64
=
(
int64_t
*
)
va_arg
(
args
,
int64_t
*
);
if
(
DVBEventInformation
(
p_demux
,
NULL
,
pi64
)
)
*
pi64
=
0
;
return
VLC_SUCCESS
;
#endif
case
DEMUX_SET_GROUP
:
case
DEMUX_SET_GROUP
:
{
{
vlc_list_t
*
p_list
;
vlc_list_t
*
p_list
;
...
@@ -1847,24 +1867,338 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid )
...
@@ -1847,24 +1867,338 @@ static void ParsePES( demux_t *p_demux, ts_pid_t *pid )
}
}
}
}
static
void
PCRHandle
(
demux_t
*
p_demux
,
ts_pid_t
*
pid
,
block_t
*
p_bk
)
static
block_t
*
ReadTSPacket
(
demux_t
*
p_demux
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
block_t
*
p_pkt
;
/* Get a new TS packet */
if
(
!
(
p_pkt
=
stream_Block
(
p_demux
->
s
,
p_sys
->
i_packet_size
)
)
)
{
msg_Dbg
(
p_demux
,
"eof ?"
);
return
NULL
;
}
/* Check sync byte and re-sync if needed */
if
(
p_pkt
->
p_buffer
[
0
]
!=
0x47
)
{
msg_Warn
(
p_demux
,
"lost synchro"
);
block_Release
(
p_pkt
);
while
(
vlc_object_alive
(
p_demux
)
)
{
const
uint8_t
*
p_peek
;
int
i_peek
,
i_skip
=
0
;
i_peek
=
stream_Peek
(
p_demux
->
s
,
&
p_peek
,
p_sys
->
i_packet_size
*
10
);
if
(
i_peek
<
p_sys
->
i_packet_size
+
1
)
{
msg_Dbg
(
p_demux
,
"eof ?"
);
return
NULL
;
}
while
(
i_skip
<
i_peek
-
p_sys
->
i_packet_size
)
{
if
(
p_peek
[
i_skip
]
==
0x47
&&
p_peek
[
i_skip
+
p_sys
->
i_packet_size
]
==
0x47
)
{
break
;
}
i_skip
++
;
}
msg_Dbg
(
p_demux
,
"skipping %d bytes of garbage"
,
i_skip
);
stream_Read
(
p_demux
->
s
,
NULL
,
i_skip
);
if
(
i_skip
<
i_peek
-
p_sys
->
i_packet_size
)
{
break
;
}
}
if
(
!
(
p_pkt
=
stream_Block
(
p_demux
->
s
,
p_sys
->
i_packet_size
)
)
)
{
msg_Dbg
(
p_demux
,
"eof ?"
);
return
NULL
;
}
}
return
p_pkt
;
}
static
mtime_t
AdjustPCRWrapAround
(
demux_t
*
p_demux
,
mtime_t
i_pcr
)
{
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
const
uint8_t
*
p
=
p_bk
->
p_buffer
;
/*
* PCR is 33bit. If PCR reaches to 0x1FFFFFFFF (26:30:43.717), ressets from 0.
* So, need to add 0x1FFFFFFFF, for calculating duration or current position.
*/
mtime_t
i_adjust
=
0
;
int64_t
i_pos
=
stream_Tell
(
p_demux
->
s
);
int
i
;
for
(
i
=
1
;
i
<
p_sys
->
i_pcrs_num
&&
p_sys
->
p_pos
[
i
]
<=
i_pos
;
++
i
)
{
if
(
p_sys
->
p_pcrs
[
i
-
1
]
>
p_sys
->
p_pcrs
[
i
]
)
i_adjust
+=
0x1FFFFFFFF
;
}
if
(
p_sys
->
p_pcrs
[
i
-
1
]
>
i_pcr
)
i_adjust
+=
0x1FFFFFFFF
;
if
(
p_sys
->
i_pmt_es
<=
0
)
return
i_pcr
+
i_adjust
;
return
;
}
static
mtime_t
GetPCR
(
block_t
*
p_pkt
)
{
const
uint8_t
*
p
=
p_pkt
->
p_buffer
;
mtime_t
i_pcr
=
-
1
;
if
(
(
p
[
3
]
&
0x20
)
&&
/* adaptation */
if
(
(
p
[
3
]
&
0x20
)
&&
/* adaptation */
(
p
[
5
]
&
0x10
)
&&
(
p
[
5
]
&
0x10
)
&&
(
p
[
4
]
>=
7
)
)
(
p
[
4
]
>=
7
)
)
{
{
/* PCR is 33 bits */
/* PCR is 33 bits */
const
mtime_t
i_pcr
=
(
(
mtime_t
)
p
[
6
]
<<
25
)
|
i_pcr
=
(
(
mtime_t
)
p
[
6
]
<<
25
)
|
(
(
mtime_t
)
p
[
7
]
<<
17
)
|
(
(
mtime_t
)
p
[
7
]
<<
17
)
|
(
(
mtime_t
)
p
[
8
]
<<
9
)
|
(
(
mtime_t
)
p
[
8
]
<<
9
)
|
(
(
mtime_t
)
p
[
9
]
<<
1
)
|
(
(
mtime_t
)
p
[
9
]
<<
1
)
|
(
(
mtime_t
)
p
[
10
]
>>
7
);
(
(
mtime_t
)
p
[
10
]
>>
7
);
}
return
i_pcr
;
}
static
int
SeekToPCR
(
demux_t
*
p_demux
,
int64_t
i_pos
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
mtime_t
i_pcr
=
-
1
;
int64_t
i_initial_pos
=
stream_Tell
(
p_demux
->
s
);
if
(
i_pos
<
0
)
return
VLC_EGENERIC
;
int64_t
i_last_pos
=
i_pos
+
p_sys
->
i_packet_size
*
4500
;
//XXX
if
(
i_last_pos
>
stream_Size
(
p_demux
->
s
)
-
p_sys
->
i_packet_size
)
{
i_last_pos
=
stream_Size
(
p_demux
->
s
)
-
p_sys
->
i_packet_size
;
}
if
(
stream_Seek
(
p_demux
->
s
,
i_pos
)
)
return
VLC_EGENERIC
;
while
(
vlc_object_alive
(
p_demux
)
)
{
block_t
*
p_pkt
;
if
(
!
(
p_pkt
=
ReadTSPacket
(
p_demux
)
)
)
{
break
;
}
if
(
PIDGet
(
p_pkt
)
==
p_sys
->
i_pid_ref_pcr
)
{
i_pcr
=
GetPCR
(
p_pkt
);
}
block_Release
(
p_pkt
);
if
(
i_pcr
>=
0
)
break
;
if
(
stream_Tell
(
p_demux
->
s
)
>=
i_last_pos
)
break
;
}
if
(
i_pcr
<
0
)
{
stream_Seek
(
p_demux
->
s
,
i_initial_pos
);
return
VLC_EGENERIC
;
}
else
{
p_sys
->
i_current_pcr
=
i_pcr
;
return
VLC_SUCCESS
;
}
}
static
int
Seek
(
demux_t
*
p_demux
,
double
f_percent
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
int64_t
i_initial_pos
=
stream_Tell
(
p_demux
->
s
);
mtime_t
i_initial_pcr
=
p_sys
->
i_current_pcr
;
/*
* Find the time position by using binary search algorithm.
*/
mtime_t
i_target_pcr
=
(
p_sys
->
i_last_pcr
-
p_sys
->
i_first_pcr
)
*
f_percent
+
p_sys
->
i_first_pcr
;
int64_t
i_head_pos
=
0
;
int64_t
i_tail_pos
=
stream_Size
(
p_demux
->
s
);
{
mtime_t
i_adjust
=
0
;
int
i
;
for
(
i
=
1
;
i
<
p_sys
->
i_pcrs_num
;
++
i
)
{
if
(
p_sys
->
p_pcrs
[
i
-
1
]
>
p_sys
->
p_pcrs
[
i
]
)
i_adjust
+=
0x1FFFFFFFF
;
if
(
p_sys
->
p_pcrs
[
i
]
+
i_adjust
>
i_target_pcr
)
break
;
}
i_head_pos
=
p_sys
->
p_pos
[
i
-
1
];
i_tail_pos
=
(
i
<
p_sys
->
i_pcrs_num
)
?
p_sys
->
p_pos
[
i
]
:
stream_Size
(
p_demux
->
s
);
}
msg_Dbg
(
p_demux
,
"Seek():i_head_pos:%lld, i_tail_pos:%lld"
,
i_head_pos
,
i_tail_pos
);
bool
b_found
=
false
;
int
i_cnt
=
0
;
while
(
i_head_pos
<=
i_tail_pos
)
{
int64_t
i_pos
=
i_head_pos
+
(
i_tail_pos
-
i_head_pos
)
/
2
;
if
(
SeekToPCR
(
p_demux
,
i_pos
)
)
break
;
p_sys
->
i_current_pcr
=
AdjustPCRWrapAround
(
p_demux
,
p_sys
->
i_current_pcr
);
int64_t
i_diff_msec
=
(
p_sys
->
i_current_pcr
-
i_target_pcr
)
*
100
/
9
/
1000
;
if
(
i_diff_msec
>
500
)
{
i_tail_pos
=
i_pos
-
p_sys
->
i_packet_size
;
}
else
if
(
i_diff_msec
<
-
500
)
{
i_head_pos
=
i_pos
+
p_sys
->
i_packet_size
;
}
else
{
// diff time <= 500msec
b_found
=
true
;
break
;
}
++
i_cnt
;
}
if
(
!
b_found
)
{
msg_Dbg
(
p_demux
,
"Seek():cannot find a time position. i_cnt:%d"
,
i_cnt
);
stream_Seek
(
p_demux
->
s
,
i_initial_pos
);
p_sys
->
i_current_pcr
=
i_initial_pcr
;
return
VLC_EGENERIC
;
}
else
{
msg_Dbg
(
p_demux
,
"Seek():can find a time position. i_cnt:%d"
,
i_cnt
);
return
VLC_SUCCESS
;
}
}
static
void
GetFirstPCR
(
demux_t
*
p_demux
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
int64_t
i_initial_pos
=
stream_Tell
(
p_demux
->
s
);
if
(
stream_Seek
(
p_demux
->
s
,
0
)
)
return
;
while
(
vlc_object_alive
(
p_demux
)
)
{
block_t
*
p_pkt
;
if
(
!
(
p_pkt
=
ReadTSPacket
(
p_demux
)
)
)
{
break
;
}
mtime_t
i_pcr
=
GetPCR
(
p_pkt
);
if
(
i_pcr
>=
0
)
{
p_sys
->
i_pid_ref_pcr
=
PIDGet
(
p_pkt
);
p_sys
->
i_first_pcr
=
i_pcr
;
p_sys
->
i_current_pcr
=
i_pcr
;
}
block_Release
(
p_pkt
);
if
(
p_sys
->
i_first_pcr
>=
0
)
break
;
}
stream_Seek
(
p_demux
->
s
,
i_initial_pos
);
}
static
void
GetLastPCR
(
demux_t
*
p_demux
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
int64_t
i_initial_pos
=
stream_Tell
(
p_demux
->
s
);
mtime_t
i_initial_pcr
=
p_sys
->
i_current_pcr
;
int64_t
i_last_pos
=
stream_Size
(
p_demux
->
s
)
-
p_sys
->
i_packet_size
;
int64_t
i_pos
=
i_last_pos
-
p_sys
->
i_packet_size
*
4500
;
/* FIXME if the value is not reasonable, please change it. */
if
(
i_pos
<
0
)
return
;
while
(
vlc_object_alive
(
p_demux
)
)
{
if
(
SeekToPCR
(
p_demux
,
i_pos
)
)
break
;
p_sys
->
i_last_pcr
=
AdjustPCRWrapAround
(
p_demux
,
p_sys
->
i_current_pcr
);
if
(
(
i_pos
=
stream_Tell
(
p_demux
->
s
)
)
>=
i_last_pos
)
break
;
}
if
(
p_sys
->
i_last_pcr
>=
0
)
{
int64_t
i_size
=
stream_Size
(
p_demux
->
s
);
mtime_t
i_duration_msec
=
(
p_sys
->
i_last_pcr
-
p_sys
->
i_first_pcr
)
*
100
/
9
/
1000
;
int64_t
i_rate
=
(
i_size
<
0
||
i_duration_msec
<=
0
)
?
0
:
i_size
*
1000
*
8
/
i_duration_msec
;
const
int64_t
TS_SUPPOSED_MAXRATE
=
55
*
1000
*
1000
;
//FIXME I think it's enough.
const
int64_t
TS_SUPPOSED_MINRATE
=
0
.
5
*
1000
*
1000
;
//FIXME
if
(
i_rate
<
TS_SUPPOSED_MINRATE
||
i_rate
>
TS_SUPPOSED_MAXRATE
)
{
msg_Dbg
(
p_demux
,
"calculated bitrate (%lldbit/s) is too low or too high. min bitrate (%lldbit/s) max bitrate (%lldbit/s)"
,
i_rate
,
TS_SUPPOSED_MINRATE
,
TS_SUPPOSED_MAXRATE
);
p_sys
->
i_last_pcr
=
-
1
;
}
}
stream_Seek
(
p_demux
->
s
,
i_initial_pos
);
p_sys
->
i_current_pcr
=
i_initial_pcr
;
}
static
void
CheckPCR
(
demux_t
*
p_demux
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
int64_t
i_initial_pos
=
stream_Tell
(
p_demux
->
s
);
mtime_t
i_initial_pcr
=
p_sys
->
i_current_pcr
;
int64_t
i_size
=
stream_Size
(
p_demux
->
s
);
int
i
=
0
;
p_sys
->
p_pcrs
[
0
]
=
p_sys
->
i_first_pcr
;
p_sys
->
p_pos
[
0
]
=
i_initial_pos
;
for
(
i
=
1
;
i
<
p_sys
->
i_pcrs_num
&&
vlc_object_alive
(
p_demux
);
++
i
)
{
int64_t
i_pos
=
i_size
/
p_sys
->
i_pcrs_num
*
i
;
if
(
SeekToPCR
(
p_demux
,
i_pos
)
)
break
;
p_sys
->
p_pcrs
[
i
]
=
p_sys
->
i_current_pcr
;
p_sys
->
p_pos
[
i
]
=
stream_Tell
(
p_demux
->
s
);
if
(
p_sys
->
p_pcrs
[
i
-
1
]
>
p_sys
->
p_pcrs
[
i
]
)
{
msg_Dbg
(
p_demux
,
"PCR Wrap Around found between %d%% and %d%% (pcr:%lld(0x%09llx) pcr:%lld(0x%09llx))"
,
(
int
)((
i
-
1
)
*
100
/
p_sys
->
i_pcrs_num
),
(
int
)(
i
*
100
/
p_sys
->
i_pcrs_num
),
p_sys
->
p_pcrs
[
i
-
1
],
p_sys
->
p_pcrs
[
i
-
1
],
p_sys
->
p_pcrs
[
i
],
p_sys
->
p_pcrs
[
i
]
);
}
}
if
(
i
<
p_sys
->
i_pcrs_num
)
{
msg_Dbg
(
p_demux
,
"Force Seek Per Percent: Seeking failed at %d%%."
,
(
int
)(
i
*
100
/
p_sys
->
i_pcrs_num
)
);
p_sys
->
b_force_seek_per_percent
=
true
;
}
stream_Seek
(
p_demux
->
s
,
i_initial_pos
);
p_sys
->
i_current_pcr
=
i_initial_pcr
;
}
static
void
PCRHandle
(
demux_t
*
p_demux
,
ts_pid_t
*
pid
,
block_t
*
p_bk
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
if
(
p_sys
->
i_pmt_es
<=
0
)
return
;
mtime_t
i_pcr
=
GetPCR
(
p_bk
);
if
(
i_pcr
>=
0
)
{
if
(
p_sys
->
i_pid_ref_pcr
==
pid
->
i_pid
)
{
p_sys
->
i_current_pcr
=
AdjustPCRWrapAround
(
p_demux
,
i_pcr
);
}
/* Search program and set the PCR */
/* Search program and set the PCR */
for
(
int
i
=
0
;
i
<
p_sys
->
i_pmt
;
i
++
)
for
(
int
i
=
0
;
i
<
p_sys
->
i_pmt
;
i
++
)
...
...
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