Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-gpu
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-gpu
Commits
cf11da5c
Commit
cf11da5c
authored
Nov 16, 2008
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Untangled es_out_timeshift lock/wait/properties.
parent
46179374
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
247 additions
and
171 deletions
+247
-171
src/input/es_out_timeshift.c
src/input/es_out_timeshift.c
+247
-171
No files found.
src/input/es_out_timeshift.c
View file @
cf11da5c
...
...
@@ -106,6 +106,35 @@ typedef struct
};
}
ts_cmd_t
;
typedef
struct
{
VLC_COMMON_MEMBERS
/* */
input_thread_t
*
p_input
;
es_out_t
*
p_out
;
/* Lock for all following fields */
vlc_mutex_t
lock
;
vlc_cond_t
wait
;
/* */
bool
b_paused
;
mtime_t
i_pause_date
;
/* */
int
i_rate
;
int
i_rate_source
;
mtime_t
i_rate_date
;
mtime_t
i_rate_delay
;
/* */
int
i_cmd
;
ts_cmd_t
**
pp_cmd
;
mtime_t
i_cmd_delay
;
}
ts_thread_t
;
struct
es_out_id_t
{
es_out_id_t
*
p_es
;
...
...
@@ -122,28 +151,20 @@ struct es_out_sys_t
/* Lock for all following fields */
vlc_mutex_t
lock
;
vlc_cond_t
wait
;
/* */
bool
b_delayed
;
vlc_object
_t
*
p_thread
;
ts_thread
_t
*
p_thread
;
bool
b_paused
;
mtime_t
i_pause_date
;
int
i_rate
;
int
i_rate_source
;
mtime_t
i_rate_date
;
mtime_t
i_rate_delay
;
/* */
bool
b_input_paused
;
bool
b_input_paused_source
;
int
i_input_rate
;
int
i_input_rate_source
;
/* */
int
i_es
;
es_out_id_t
**
pp_es
;
/* */
int
i_cmd
;
ts_cmd_t
**
pp_cmd
;
mtime_t
i_cmd_delay
;
};
static
es_out_id_t
*
Add
(
es_out_t
*
,
const
es_format_t
*
);
...
...
@@ -153,11 +174,12 @@ static int Control( es_out_t *, int i_query, va_list );
static
void
Destroy
(
es_out_t
*
);
static
int
TsStart
(
es_out_t
*
);
static
void
TsStop
(
es_out_t
*
);
static
void
TsPushCmd
(
es_out_t
*
,
const
ts_cmd_t
*
);
static
int
TsPopCmd
(
es_out_t
*
,
ts_cmd_t
*
);
static
int
TsChangePause
(
es_out_t
*
,
bool
b_source_paused
,
bool
b_paused
,
mtime_t
i_date
);
static
int
TsChangeRate
(
es_out_t
*
,
int
i_src_rate
,
int
i_rate
);
static
void
TsStop
(
ts_thread_t
*
);
static
void
TsPushCmd
(
ts_thread_t
*
,
const
ts_cmd_t
*
);
static
int
TsPopCmdLocked
(
ts_thread_t
*
,
ts_cmd_t
*
);
static
bool
TsHasCmd
(
ts_thread_t
*
);
static
int
TsChangePause
(
ts_thread_t
*
,
bool
b_source_paused
,
bool
b_paused
,
mtime_t
i_date
);
static
int
TsChangeRate
(
ts_thread_t
*
,
int
i_src_rate
,
int
i_rate
);
static
void
*
TsRun
(
vlc_object_t
*
);
...
...
@@ -169,15 +191,18 @@ static void CmdInitSend ( ts_cmd_t *, es_out_id_t *, block_t * );
static
int
CmdInitDel
(
ts_cmd_t
*
,
es_out_id_t
*
);
static
int
CmdInitControl
(
ts_cmd_t
*
,
int
i_query
,
va_list
,
bool
b_copy
);
/* */
static
void
CmdCleanAdd
(
ts_cmd_t
*
);
static
void
CmdCleanSend
(
ts_cmd_t
*
);
static
void
CmdCleanControl
(
ts_cmd_t
*
p_cmd
);
/* XXX these functions will take the destination es_out_t */
static
void
CmdExecuteAdd
(
es_out_t
*
,
ts_cmd_t
*
);
static
int
CmdExecuteSend
(
es_out_t
*
,
ts_cmd_t
*
);
static
void
CmdExecuteDel
(
es_out_t
*
,
ts_cmd_t
*
);
static
int
CmdExecuteControl
(
es_out_t
*
,
ts_cmd_t
*
);
static
void
CmdCleanAdd
(
ts_cmd_t
*
);
static
void
CmdCleanSend
(
ts_cmd_t
*
);
static
void
CmdCleanControl
(
ts_cmd_t
*
p_cmd
);
/* File helpers */
static
char
*
GetTmpPath
(
char
*
psz_path
);
static
FILE
*
GetTmpFile
(
const
char
*
psz_path
);
...
...
@@ -207,23 +232,19 @@ es_out_t *input_EsOutTimeshiftNew( input_thread_t *p_input, es_out_t *p_next_out
p_out
->
b_sout
=
p_input
->
p
->
p_sout
!=
NULL
;
/* */
p_sys
->
b_input_paused
=
false
;
p_sys
->
b_input_paused_source
=
false
;
p_sys
->
p_input
=
p_input
;
p_sys
->
i_input_rate
=
i_rate
;
p_sys
->
i_input_rate_source
=
i_rate
;
p_sys
->
p_out
=
p_next_out
;
vlc_mutex_init_recursive
(
&
p_sys
->
lock
);
vlc_cond_init
(
&
p_sys
->
wait
);
p_sys
->
b_delayed
=
false
;
p_sys
->
p_thread
=
NULL
;
p_sys
->
b_paused
=
false
;
p_sys
->
i_pause_date
=
-
1
;
p_sys
->
i_rate_source
=
p_sys
->
i_rate
=
i_rate
;
p_sys
->
i_rate_date
=
-
1
;
p_sys
->
i_rate_delay
=
0
;
p_sys
->
i_cmd_delay
=
0
;
TAB_INIT
(
p_sys
->
i_es
,
p_sys
->
pp_es
);
TAB_INIT
(
p_sys
->
i_cmd
,
p_sys
->
pp_cmd
);
/* TODO config
* timeshift-granularity
...
...
@@ -243,16 +264,16 @@ static void Destroy( es_out_t *p_out )
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
if
(
p_sys
->
b_delayed
)
TsStop
(
p_out
);
TAB_CLEAN
(
p_sys
->
i_cmd
,
p_sys
->
pp_cmd
);
{
TsStop
(
p_sys
->
p_thread
);
p_sys
->
b_delayed
=
false
;
}
while
(
p_sys
->
i_es
>
0
)
Del
(
p_out
,
p_sys
->
pp_es
[
0
]
);
TAB_CLEAN
(
p_sys
->
i_es
,
p_sys
->
pp_es
);
free
(
p_sys
->
psz_tmp_path
);
vlc_cond_destroy
(
&
p_sys
->
wait
);
vlc_mutex_destroy
(
&
p_sys
->
lock
);
free
(
p_sys
);
free
(
p_out
);
...
...
@@ -279,9 +300,9 @@ static es_out_id_t *Add( es_out_t *p_out, const es_format_t *p_fmt )
TAB_APPEND
(
p_sys
->
i_es
,
p_sys
->
pp_es
,
p_es
);
if
(
p_sys
->
b_delayed
)
TsPushCmd
(
p_
out
,
&
cmd
);
TsPushCmd
(
p_
sys
->
p_thread
,
&
cmd
);
else
CmdExecuteAdd
(
p_out
,
&
cmd
);
CmdExecuteAdd
(
p_
sys
->
p_
out
,
&
cmd
);
vlc_mutex_unlock
(
&
p_sys
->
lock
);
...
...
@@ -297,9 +318,9 @@ static int Send( es_out_t *p_out, es_out_id_t *p_es, block_t *p_block )
CmdInitSend
(
&
cmd
,
p_es
,
p_block
);
if
(
p_sys
->
b_delayed
)
TsPushCmd
(
p_
out
,
&
cmd
);
TsPushCmd
(
p_
sys
->
p_thread
,
&
cmd
);
else
i_ret
=
CmdExecuteSend
(
p_out
,
&
cmd
)
;
i_ret
=
CmdExecuteSend
(
p_
sys
->
p_
out
,
&
cmd
)
;
vlc_mutex_unlock
(
&
p_sys
->
lock
);
...
...
@@ -314,9 +335,9 @@ static void Del( es_out_t *p_out, es_out_id_t *p_es )
CmdInitDel
(
&
cmd
,
p_es
);
if
(
p_sys
->
b_delayed
)
TsPushCmd
(
p_
out
,
&
cmd
);
TsPushCmd
(
p_
sys
->
p_thread
,
&
cmd
);
else
CmdExecuteDel
(
p_out
,
&
cmd
);
CmdExecuteDel
(
p_
sys
->
p_
out
,
&
cmd
);
TAB_REMOVE
(
p_sys
->
i_es
,
p_sys
->
pp_es
,
p_es
);
...
...
@@ -327,7 +348,7 @@ static int ControlLockedGetEmpty( es_out_t *p_out, bool *pb_empty )
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
if
(
p_sys
->
b_delayed
&&
p_sys
->
i_cmd
>
0
)
if
(
p_sys
->
b_delayed
&&
TsHasCmd
(
p_sys
->
p_thread
)
)
*
pb_empty
=
false
;
else
*
pb_empty
=
es_out_GetEmpty
(
p_sys
->
p_out
);
...
...
@@ -364,24 +385,73 @@ static int ControlLockedGetBuffering( es_out_t *p_out, bool *pb_buffering )
static
int
ControlLockedSetPauseState
(
es_out_t
*
p_out
,
bool
b_source_paused
,
bool
b_paused
,
mtime_t
i_date
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
int
i_ret
;
if
(
!
p_sys
->
b_delayed
&&
!
b_source_paused
==
!
b_paused
)
{
i_ret
=
es_out_SetPauseState
(
p_sys
->
p_out
,
b_source_paused
,
b_paused
,
i_date
);
}
else
{
i_ret
=
VLC_EGENERIC
;
if
(
!
p_sys
->
p_input
->
b_can_pace_control
)
{
if
(
!
p_sys
->
b_delayed
)
TsStart
(
p_out
);
if
(
p_sys
->
b_delayed
)
i_ret
=
TsChangePause
(
p_sys
->
p_thread
,
b_source_paused
,
b_paused
,
i_date
);
}
else
{
/* XXX we may do it BUT it would be better to finish the clock clean up+improvments
* and so be able to advertize correctly pace control property in access
* module */
msg_Err
(
p_sys
->
p_input
,
"EsOutTimeshift does not work with streams that have space control"
);
}
}
if
(
!
p_sys
->
b_delayed
&&
!
b_source_paused
==
!
b_paused
)
if
(
!
i_ret
)
{
return
es_out_SetPauseState
(
p_sys
->
p_out
,
b_source_paused
,
b_paused
,
i_date
);
p_sys
->
b_input_paused_source
=
b_source_paused
;
p_sys
->
b_input_paused
=
b_paused
;
}
return
TsChangePause
(
p_out
,
b_source_paused
,
b_paused
,
i_date
)
;
return
i_ret
;
}
static
int
ControlLockedSetRate
(
es_out_t
*
p_out
,
int
i_src_rate
,
int
i_rate
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
int
i_ret
;
if
(
!
p_sys
->
b_delayed
&&
i_src_rate
==
i_rate
)
if
(
!
p_sys
->
b_delayed
&&
i_src_rate
==
i_rate
)
{
i_ret
=
es_out_SetRate
(
p_sys
->
p_out
,
i_src_rate
,
i_rate
);
}
else
{
return
es_out_SetRate
(
p_sys
->
p_out
,
i_src_rate
,
i_rate
);
i_ret
=
VLC_EGENERIC
;
if
(
!
p_sys
->
p_input
->
b_can_pace_control
)
{
if
(
!
p_sys
->
b_delayed
)
TsStart
(
p_out
);
if
(
p_sys
->
b_delayed
)
i_ret
=
TsChangeRate
(
p_sys
->
p_thread
,
i_src_rate
,
i_rate
);
}
else
{
/* XXX we may do it BUT it would be better to finish the clock clean up+improvments
* and so be able to advertize correctly pace control property in access
* module */
msg_Err
(
p_sys
->
p_input
,
"EsOutTimeshift does not work with streams that have space control"
);
}
}
return
TsChangeRate
(
p_out
,
i_src_rate
,
i_rate
);
if
(
!
i_ret
)
{
p_sys
->
i_input_rate_source
=
i_src_rate
;
p_sys
->
i_input_rate
=
i_rate
;
}
return
i_ret
;
}
static
int
ControlLockedSetTime
(
es_out_t
*
p_out
,
mtime_t
i_date
)
{
...
...
@@ -451,10 +521,10 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args )
return
VLC_EGENERIC
;
if
(
p_sys
->
b_delayed
)
{
TsPushCmd
(
p_
out
,
&
cmd
);
TsPushCmd
(
p_
sys
->
p_thread
,
&
cmd
);
return
VLC_SUCCESS
;
}
return
CmdExecuteControl
(
p_out
,
&
cmd
);
return
CmdExecuteControl
(
p_
sys
->
p_
out
,
&
cmd
);
}
/* Special control */
...
...
@@ -520,23 +590,46 @@ static int Control( es_out_t *p_out, int i_query, va_list args )
/*****************************************************************************
*
*****************************************************************************/
static
void
TsDestructor
(
vlc_object_t
*
p_this
)
{
ts_thread_t
*
p_ts
=
(
ts_thread_t
*
)
p_this
;
vlc_cond_destroy
(
&
p_ts
->
wait
);
vlc_mutex_destroy
(
&
p_ts
->
lock
);
}
static
int
TsStart
(
es_out_t
*
p_out
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
ts_thread_t
*
p_ts
;
assert
(
!
p_sys
->
b_delayed
);
p_sys
->
p_thread
=
vlc_custom_create
(
p_sys
->
p_input
,
sizeof
(
vlc_object
_t
),
VLC_OBJECT_GENERIC
,
"es out timeshift"
);
if
(
!
p_
sys
->
p_thread
)
p_sys
->
p_thread
=
p_ts
=
vlc_custom_create
(
p_sys
->
p_input
,
sizeof
(
ts_thread
_t
),
VLC_OBJECT_GENERIC
,
"es out timeshift"
);
if
(
!
p_
ts
)
return
VLC_EGENERIC
;
p_ts
->
p_input
=
p_sys
->
p_input
;
p_ts
->
p_out
=
p_sys
->
p_out
;
vlc_mutex_init
(
&
p_ts
->
lock
);
vlc_cond_init
(
&
p_ts
->
wait
);
p_ts
->
b_paused
=
p_sys
->
b_input_paused
&&
!
p_sys
->
b_input_paused_source
;
p_ts
->
i_pause_date
=
p_ts
->
b_paused
?
mdate
()
:
-
1
;
p_ts
->
i_rate_source
=
p_sys
->
i_input_rate_source
;
p_ts
->
i_rate
=
p_sys
->
i_input_rate
;
p_ts
->
i_rate_date
=
-
1
;
p_ts
->
i_rate_delay
=
0
;
p_ts
->
i_cmd_delay
=
0
;
TAB_INIT
(
p_ts
->
i_cmd
,
p_ts
->
pp_cmd
);
vlc_object_set_destructor
(
p_ts
,
TsDestructor
);
p_sys
->
b_delayed
=
true
;
p_sys
->
p_thread
->
p_private
=
p_out
;
if
(
vlc_thread_create
(
p_sys
->
p_thread
,
"es out timeshift"
,
TsRun
,
VLC_THREAD_PRIORITY_INPUT
,
false
)
)
{
msg_Err
(
p_sys
->
p_input
,
"cannot create input thread"
);
vlc_object_release
(
p_sys
->
p_thread
);
p_sys
->
b_delayed
=
false
;
...
...
@@ -545,127 +638,118 @@ static int TsStart( es_out_t *p_out )
return
VLC_SUCCESS
;
}
static
void
TsStop
(
es_out_t
*
p_out
)
static
void
TsStop
(
ts_thread_t
*
p_ts
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
assert
(
p_sys
->
b_delayed
);
vlc_object_kill
(
p_sys
->
p_thread
);
vlc_thread_join
(
p_sys
->
p_thread
);
vlc_object_kill
(
p_ts
);
vlc_thread_join
(
p_ts
);
vlc_mutex_lock
(
&
p_ts
->
lock
);
for
(
;;
)
{
ts_cmd_t
cmd
;
if
(
TsPopCmd
(
p_out
,
&
cmd
)
)
if
(
TsPopCmd
Locked
(
p_ts
,
&
cmd
)
)
break
;
CmdClean
(
&
cmd
);
}
vlc_mutex_unlock
(
&
p_ts
->
lock
);
TAB_CLEAN
(
p_ts
->
i_cmd
,
p_ts
->
pp_cmd
);
p_sys
->
b_delayed
=
false
;
vlc_object_release
(
p_ts
)
;
}
static
void
TsPushCmd
(
es_out_t
*
p_out
,
const
ts_cmd_t
*
p_cmd
)
static
void
TsPushCmd
(
ts_thread_t
*
p_ts
,
const
ts_cmd_t
*
p_cmd
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
ts_cmd_t
*
p_dup
=
malloc
(
sizeof
(
*
p_dup
)
);
if
(
p_dup
)
{
*
p_dup
=
*
p_cmd
;
TAB_APPEND
(
p_sys
->
i_cmd
,
p_sys
->
pp_cmd
,
p_dup
);
vlc_cond_signal
(
&
p_sys
->
wait
);
vlc_mutex_lock
(
&
p_ts
->
lock
);
TAB_APPEND
(
p_ts
->
i_cmd
,
p_ts
->
pp_cmd
,
p_dup
);
vlc_cond_signal
(
&
p_ts
->
wait
);
vlc_mutex_unlock
(
&
p_ts
->
lock
);
}
}
static
int
TsPopCmd
(
es_out_t
*
p_out
,
ts_cmd_t
*
p_cmd
)
static
int
TsPopCmd
Locked
(
ts_thread_t
*
p_ts
,
ts_cmd_t
*
p_cmd
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
vlc_assert_locked
(
&
p_ts
->
lock
)
;
if
(
p_
sy
s
->
i_cmd
<=
0
)
if
(
p_
t
s
->
i_cmd
<=
0
)
return
VLC_EGENERIC
;
*
p_cmd
=
*
p_
sy
s
->
pp_cmd
[
0
];
*
p_cmd
=
*
p_
t
s
->
pp_cmd
[
0
];
free
(
p_
sy
s
->
pp_cmd
[
0
]
);
TAB_REMOVE
(
p_
sys
->
i_cmd
,
p_sys
->
pp_cmd
,
p_sy
s
->
pp_cmd
[
0
]
);
free
(
p_
t
s
->
pp_cmd
[
0
]
);
TAB_REMOVE
(
p_
ts
->
i_cmd
,
p_ts
->
pp_cmd
,
p_t
s
->
pp_cmd
[
0
]
);
return
VLC_SUCCESS
;
}
static
int
TsChangePause
(
es_out_t
*
p_out
,
bool
b_source_paused
,
bool
b_paused
,
mtime_t
i_date
)
static
bool
TsHasCmd
(
ts_thread_t
*
p_ts
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
bool
b_cmd
;
if
(
p_sys
->
p_input
->
b_can_pace_control
)
{
/* XXX we may do it BUT it would be better to finish the clock clean up+improvments
* and so be able to advertize correctly pace control property in access
* module */
msg_Err
(
p_sys
->
p_input
,
"EsOutTimeshift does not work with streams that have space control"
);
return
VLC_EGENERIC
;
}
vlc_mutex_lock
(
&
p_ts
->
lock
);
b_cmd
=
p_ts
->
i_cmd
>
0
;
vlc_mutex_unlock
(
&
p_ts
->
lock
);
return
b_cmd
;
}
static
int
TsChangePause
(
ts_thread_t
*
p_ts
,
bool
b_source_paused
,
bool
b_paused
,
mtime_t
i_date
)
{
vlc_mutex_lock
(
&
p_ts
->
lock
);
int
i_ret
;
if
(
b_paused
)
{
assert
(
!
b_source_paused
);
if
(
!
p_sys
->
b_delayed
)
TsStart
(
p_out
);
i_ret
=
es_out_SetPauseState
(
p_sys
->
p_out
,
true
,
true
,
i_date
);
i_ret
=
es_out_SetPauseState
(
p_ts
->
p_out
,
true
,
true
,
i_date
);
}
else
{
i_ret
=
es_out_SetPauseState
(
p_
sy
s
->
p_out
,
false
,
false
,
i_date
);
i_ret
=
es_out_SetPauseState
(
p_
t
s
->
p_out
,
false
,
false
,
i_date
);
}
if
(
!
i_ret
)
{
if
(
!
b_paused
)
{
assert
(
p_
sy
s
->
i_pause_date
>
0
);
assert
(
p_
t
s
->
i_pause_date
>
0
);
p_
sys
->
i_cmd_delay
+=
i_date
-
p_sy
s
->
i_pause_date
;
p_
ts
->
i_cmd_delay
+=
i_date
-
p_t
s
->
i_pause_date
;
}
p_
sy
s
->
b_paused
=
b_paused
;
p_
sy
s
->
i_pause_date
=
i_date
;
p_
t
s
->
b_paused
=
b_paused
;
p_
t
s
->
i_pause_date
=
i_date
;
vlc_cond_signal
(
&
p_
sy
s
->
wait
);
vlc_cond_signal
(
&
p_
t
s
->
wait
);
}
vlc_mutex_unlock
(
&
p_ts
->
lock
);
return
i_ret
;
}
static
int
TsChangeRate
(
es_out_t
*
p_out
,
int
i_src_rate
,
int
i_rate
)
static
int
TsChangeRate
(
ts_thread_t
*
p_ts
,
int
i_src_rate
,
int
i_rate
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
if
(
p_sys
->
p_input
->
b_can_pace_control
)
{
/* XXX we may do it BUT it would be better to finish the clock clean up+improvments
* and so be able to advertize correctly pace control property in access
* module */
msg_Err
(
p_sys
->
p_input
,
"EsOutTimeshift does not work with streams that have space control"
);
return
VLC_EGENERIC
;
}
int
i_ret
;
p_sys
->
i_cmd_delay
+=
p_sys
->
i_rate_delay
;
vlc_mutex_lock
(
&
p_ts
->
lock
);
p_ts
->
i_cmd_delay
+=
p_ts
->
i_rate_delay
;
p_
sy
s
->
i_rate_date
=
-
1
;
p_
sy
s
->
i_rate_delay
=
0
;
p_
sy
s
->
i_rate
=
i_rate
;
p_
sy
s
->
i_rate_source
=
i_src_rate
;
p_
t
s
->
i_rate_date
=
-
1
;
p_
t
s
->
i_rate_delay
=
0
;
p_
t
s
->
i_rate
=
i_rate
;
p_
t
s
->
i_rate_source
=
i_src_rate
;
i
f
(
!
p_sys
->
b_delayed
)
TsStart
(
p_out
);
i
_ret
=
es_out_SetRate
(
p_ts
->
p_out
,
i_rate
,
i_rate
);
vlc_mutex_unlock
(
&
p_ts
->
lock
);
return
es_out_SetRate
(
p_sys
->
p_out
,
i_rate
,
i_rate
)
;
return
i_ret
;
}
static
void
*
TsRun
(
vlc_object_t
*
p_thread
)
{
es_out_t
*
p_out
=
p_thread
->
p_private
;
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
ts_thread_t
*
p_ts
=
(
ts_thread_t
*
)
p_thread
;
for
(
;;
)
{
...
...
@@ -673,81 +757,80 @@ static void *TsRun( vlc_object_t *p_thread )
mtime_t
i_deadline
;
/* Pop a command to execute */
vlc_mutex_lock
(
&
p_
sy
s
->
lock
);
mutex_cleanup_push
(
&
p_
sy
s
->
lock
);
vlc_mutex_lock
(
&
p_
t
s
->
lock
);
mutex_cleanup_push
(
&
p_
t
s
->
lock
);
while
(
p_
sys
->
b_paused
||
TsPopCmd
(
p_out
,
&
cmd
)
)
vlc_cond_wait
(
&
p_
sys
->
wait
,
&
p_sy
s
->
lock
);
while
(
p_
ts
->
b_paused
||
TsPopCmdLocked
(
p_ts
,
&
cmd
)
)
vlc_cond_wait
(
&
p_
ts
->
wait
,
&
p_t
s
->
lock
);
if
(
p_
sy
s
->
i_rate_date
<
0
)
p_
sy
s
->
i_rate_date
=
cmd
.
i_date
;
if
(
p_
t
s
->
i_rate_date
<
0
)
p_
t
s
->
i_rate_date
=
cmd
.
i_date
;
p_
sy
s
->
i_rate_delay
=
0
;
if
(
p_
sys
->
i_rate_source
!=
p_sy
s
->
i_rate
)
p_
t
s
->
i_rate_delay
=
0
;
if
(
p_
ts
->
i_rate_source
!=
p_t
s
->
i_rate
)
{
const
mtime_t
i_duration
=
cmd
.
i_date
-
p_
sy
s
->
i_rate_date
;
p_
sys
->
i_rate_delay
=
i_duration
*
p_sys
->
i_rate
/
p_sy
s
->
i_rate_source
-
i_duration
;
const
mtime_t
i_duration
=
cmd
.
i_date
-
p_
t
s
->
i_rate_date
;
p_
ts
->
i_rate_delay
=
i_duration
*
p_ts
->
i_rate
/
p_t
s
->
i_rate_source
-
i_duration
;
}
if
(
p_
sys
->
i_cmd_delay
+
p_sy
s
->
i_rate_delay
<
0
)
if
(
p_
ts
->
i_cmd_delay
+
p_t
s
->
i_rate_delay
<
0
)
{
const
int
canc
=
vlc_savecancel
();
/* Auto reset to rate 1.0 */
msg_Warn
(
p_
sys
->
p_input
,
"es out timeshift: auto reset rate to %d"
,
p_sy
s
->
i_rate_source
);
msg_Warn
(
p_
ts
->
p_input
,
"es out timeshift: auto reset rate to %d"
,
p_t
s
->
i_rate_source
);
p_
sy
s
->
i_cmd_delay
=
0
;
p_
t
s
->
i_cmd_delay
=
0
;
p_
sy
s
->
i_rate_date
=
-
1
;
p_
sy
s
->
i_rate_delay
=
0
;
p_
sys
->
i_rate
=
p_sy
s
->
i_rate_source
;
p_
t
s
->
i_rate_date
=
-
1
;
p_
t
s
->
i_rate_delay
=
0
;
p_
ts
->
i_rate
=
p_t
s
->
i_rate_source
;
if
(
!
es_out_SetRate
(
p_
sys
->
p_out
,
p_sys
->
i_rate_source
,
p_sy
s
->
i_rate
)
)
if
(
!
es_out_SetRate
(
p_
ts
->
p_out
,
p_ts
->
i_rate_source
,
p_t
s
->
i_rate
)
)
{
vlc_value_t
val
=
{
.
i_int
=
p_
sy
s
->
i_rate
};
vlc_value_t
val
=
{
.
i_int
=
p_
t
s
->
i_rate
};
/* Warn back input
* FIXME it is perfectly safe BUT it is ugly as it may hide a
* rate change requested by user */
input_ControlPush
(
p_
sy
s
->
p_input
,
INPUT_CONTROL_SET_RATE
,
&
val
);
input_ControlPush
(
p_
t
s
->
p_input
,
INPUT_CONTROL_SET_RATE
,
&
val
);
}
vlc_restorecancel
(
canc
);
}
i_deadline
=
cmd
.
i_date
+
p_
sys
->
i_cmd_delay
+
p_sy
s
->
i_rate_delay
;
i_deadline
=
cmd
.
i_date
+
p_
ts
->
i_cmd_delay
+
p_t
s
->
i_rate_delay
;
vlc_cleanup_run
();
/* Regulate the speed of command processing to the same one than
* reading */
//fprintf( stderr, "d=%d - %d\n", (int)(p_sys->i_cmd_delay/1000), (int)( (mdate() - cmd.i_date - p_sys->i_cmd_delay)/1000) );
vlc_cleanup_push
(
cmd_cleanup_routine
,
&
cmd
);
mwait
(
i_deadline
);
vlc_cleanup_pop
();
/* Execute the command */
/* Execute the command
*/
const
int
canc
=
vlc_savecancel
();
vlc_mutex_lock
(
&
p_sys
->
lock
);
switch
(
cmd
.
i_type
)
{
case
C_ADD
:
CmdExecuteAdd
(
p_out
,
&
cmd
);
CmdExecuteAdd
(
p_
ts
->
p_
out
,
&
cmd
);
CmdCleanAdd
(
&
cmd
);
break
;
case
C_SEND
:
CmdExecuteSend
(
p_out
,
&
cmd
);
CmdExecuteSend
(
p_
ts
->
p_
out
,
&
cmd
);
CmdCleanSend
(
&
cmd
);
break
;
case
C_CONTROL
:
CmdExecuteControl
(
p_out
,
&
cmd
);
CmdExecuteControl
(
p_
ts
->
p_
out
,
&
cmd
);
CmdCleanControl
(
&
cmd
);
break
;
case
C_DEL
:
CmdExecuteDel
(
p_out
,
&
cmd
);
CmdExecuteDel
(
p_
ts
->
p_
out
,
&
cmd
);
break
;
default:
assert
(
0
);
break
;
}
vlc_mutex_unlock
(
&
p_sys
->
lock
);
vlc_restorecancel
(
canc
);
}
...
...
@@ -798,9 +881,7 @@ static int CmdInitAdd( ts_cmd_t *p_cmd, es_out_id_t *p_es, const es_format_t *p_
}
static
void
CmdExecuteAdd
(
es_out_t
*
p_out
,
ts_cmd_t
*
p_cmd
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
p_cmd
->
add
.
p_es
->
p_es
=
es_out_Add
(
p_sys
->
p_out
,
p_cmd
->
add
.
p_fmt
);
p_cmd
->
add
.
p_es
->
p_es
=
es_out_Add
(
p_out
,
p_cmd
->
add
.
p_fmt
);
}
static
void
CmdCleanAdd
(
ts_cmd_t
*
p_cmd
)
{
...
...
@@ -817,7 +898,6 @@ static void CmdInitSend( ts_cmd_t *p_cmd, es_out_id_t *p_es, block_t *p_block )
}
static
int
CmdExecuteSend
(
es_out_t
*
p_out
,
ts_cmd_t
*
p_cmd
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
block_t
*
p_block
=
p_cmd
->
send
.
p_block
;
p_cmd
->
send
.
p_block
=
NULL
;
...
...
@@ -825,7 +905,7 @@ static int CmdExecuteSend( es_out_t *p_out, ts_cmd_t *p_cmd )
if
(
p_block
)
{
if
(
p_cmd
->
send
.
p_es
->
p_es
)
return
es_out_Send
(
p_
sys
->
p_
out
,
p_cmd
->
send
.
p_es
->
p_es
,
p_block
);
return
es_out_Send
(
p_out
,
p_cmd
->
send
.
p_es
->
p_es
,
p_block
);
block_Release
(
p_block
);
}
return
VLC_EGENERIC
;
...
...
@@ -845,10 +925,8 @@ static int CmdInitDel( ts_cmd_t *p_cmd, es_out_id_t *p_es )
}
static
void
CmdExecuteDel
(
es_out_t
*
p_out
,
ts_cmd_t
*
p_cmd
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
if
(
p_cmd
->
del
.
p_es
->
p_es
)
es_out_Del
(
p_
sys
->
p_
out
,
p_cmd
->
del
.
p_es
->
p_es
);
es_out_Del
(
p_out
,
p_cmd
->
del
.
p_es
->
p_es
);
free
(
p_cmd
->
del
.
p_es
);
}
...
...
@@ -989,61 +1067,59 @@ static int CmdInitControl( ts_cmd_t *p_cmd, int i_query, va_list args, bool b_co
}
static
int
CmdExecuteControl
(
es_out_t
*
p_out
,
ts_cmd_t
*
p_cmd
)
{
es_out_sys_t
*
p_sys
=
p_out
->
p_sys
;
const
int
i_query
=
p_cmd
->
control
.
i_query
;
switch
(
i_query
)
{
/* Pass-through control */
case
ES_OUT_SET_ACTIVE
:
/* arg1= bool */
return
es_out_Control
(
p_
sys
->
p_
out
,
i_query
,
p_cmd
->
control
.
b_bool
);
return
es_out_Control
(
p_out
,
i_query
,
p_cmd
->
control
.
b_bool
);
case
ES_OUT_GET_ACTIVE
:
/* arg1= bool* */
return
es_out_Control
(
p_
sys
->
p_
out
,
i_query
,
p_cmd
->
control
.
pb_bool
);
return
es_out_Control
(
p_out
,
i_query
,
p_cmd
->
control
.
pb_bool
);
case
ES_OUT_SET_MODE
:
/* arg1= int */
case
ES_OUT_SET_GROUP
:
/* arg1= int */
case
ES_OUT_DEL_GROUP
:
/* arg1=int i_group */
return
es_out_Control
(
p_
sys
->
p_
out
,
i_query
,
p_cmd
->
control
.
i_int
);
return
es_out_Control
(
p_out
,
i_query
,
p_cmd
->
control
.
i_int
);
case
ES_OUT_GET_MODE
:
/* arg2= int* */
case
ES_OUT_GET_GROUP
:
/* arg1= int* */
return
es_out_Control
(
p_
sys
->
p_
out
,
i_query
,
p_cmd
->
control
.
pi_int
);
return
es_out_Control
(
p_out
,
i_query
,
p_cmd
->
control
.
pi_int
);
case
ES_OUT_SET_PCR
:
/* arg1=int64_t i_pcr(microsecond!) (using default group 0)*/
case
ES_OUT_SET_NEXT_DISPLAY_TIME
:
/* arg1=int64_t i_pts(microsecond) */
return
es_out_Control
(
p_
sys
->
p_
out
,
i_query
,
p_cmd
->
control
.
i_i64
);
return
es_out_Control
(
p_out
,
i_query
,
p_cmd
->
control
.
i_i64
);
case
ES_OUT_SET_GROUP_PCR
:
/* arg1= int i_group, arg2=int64_t i_pcr(microsecond!)*/
return
es_out_Control
(
p_
sys
->
p_
out
,
i_query
,
p_cmd
->
control
.
i_int
,
p_cmd
->
control
.
i_i64
);
return
es_out_Control
(
p_out
,
i_query
,
p_cmd
->
control
.
i_int
,
p_cmd
->
control
.
i_i64
);
case
ES_OUT_RESET_PCR
:
/* no arg */
return
es_out_Control
(
p_
sys
->
p_
out
,
i_query
);
return
es_out_Control
(
p_out
,
i_query
);
case
ES_OUT_SET_GROUP_META
:
/* arg1=int i_group arg2=vlc_meta_t* */
return
es_out_Control
(
p_
sys
->
p_
out
,
i_query
,
p_cmd
->
control
.
i_int
,
p_cmd
->
control
.
p_meta
);
return
es_out_Control
(
p_out
,
i_query
,
p_cmd
->
control
.
i_int
,
p_cmd
->
control
.
p_meta
);
case
ES_OUT_SET_GROUP_EPG
:
/* arg1=int i_group arg2=vlc_epg_t* */
return
es_out_Control
(
p_
sys
->
p_
out
,
i_query
,
p_cmd
->
control
.
i_int
,
p_cmd
->
control
.
p_epg
);
return
es_out_Control
(
p_out
,
i_query
,
p_cmd
->
control
.
i_int
,
p_cmd
->
control
.
p_epg
);
/* Modified control */
case
ES_OUT_SET_ES
:
/* arg1= es_out_id_t* */
case
ES_OUT_RESTART_ES
:
/* arg1= es_out_id_t* */
case
ES_OUT_SET_ES_DEFAULT
:
/* arg1= es_out_id_t* */
return
es_out_Control
(
p_
sys
->
p_
out
,
i_query
,
p_cmd
->
control
.
p_es
->
p_es
);
return
es_out_Control
(
p_out
,
i_query
,
p_cmd
->
control
.
p_es
->
p_es
);
case
ES_OUT_SET_ES_STATE
:
/* arg1= es_out_id_t* arg2=bool */
return
es_out_Control
(
p_
sys
->
p_
out
,
i_query
,
p_cmd
->
control
.
p_es
->
p_es
,
p_cmd
->
control
.
b_bool
);
return
es_out_Control
(
p_out
,
i_query
,
p_cmd
->
control
.
p_es
->
p_es
,
p_cmd
->
control
.
b_bool
);
case
ES_OUT_GET_ES_STATE
:
/* arg1= es_out_id_t* arg2=bool* */
return
es_out_Control
(
p_
sys
->
p_
out
,
i_query
,
p_cmd
->
control
.
p_es
->
p_es
,
p_cmd
->
control
.
pb_bool
);
return
es_out_Control
(
p_out
,
i_query
,
p_cmd
->
control
.
p_es
->
p_es
,
p_cmd
->
control
.
pb_bool
);
case
ES_OUT_SET_ES_FMT
:
/* arg1= es_out_id_t* arg2=es_format_t* */
return
es_out_Control
(
p_
sys
->
p_
out
,
i_query
,
p_cmd
->
control
.
p_es
->
p_es
,
p_cmd
->
control
.
p_fmt
);
return
es_out_Control
(
p_out
,
i_query
,
p_cmd
->
control
.
p_es
->
p_es
,
p_cmd
->
control
.
p_fmt
);
default:
assert
(
0
);
msg_Err
(
p_sys
->
p_input
,
"Unknown es_out_Control query in CmdExecuteControl!"
);
return
VLC_EGENERIC
;
}
}
...
...
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