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
c1412599
Commit
c1412599
authored
Aug 26, 2008
by
Laurent Aimar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added recording on the fly through sout.
parent
d4e0e64e
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
195 additions
and
57 deletions
+195
-57
src/input/es_out.c
src/input/es_out.c
+132
-16
src/input/input.c
src/input/input.c
+48
-7
src/input/input_internal.h
src/input/input_internal.h
+6
-1
src/input/stream.c
src/input/stream.c
+2
-33
src/libvlc-module.c
src/libvlc-module.c
+7
-0
No files found.
src/input/es_out.c
View file @
c1412599
...
...
@@ -29,9 +29,9 @@
# include "config.h"
#endif
#include <vlc_common.h>
#include <stdio.h>
#include <assert.h>
#include <vlc_common.h>
#include <vlc_input.h>
#include <vlc_es_out.h>
...
...
@@ -40,6 +40,8 @@
#include "input_internal.h"
#include "../stream_output/stream_output.h"
#include <vlc_iso_lang.h>
/* FIXME we should find a better way than including that */
#include "../text/iso-639_def.h"
...
...
@@ -83,6 +85,7 @@ struct es_out_id_t
char
*
psz_language_code
;
decoder_t
*
p_dec
;
decoder_t
*
p_dec_record
;
/* Fields for Video with CC */
bool
pb_cc_present
[
4
];
...
...
@@ -134,6 +137,9 @@ struct es_out_sys_t
/* Rate used to rescale ES ts */
int
i_rate
;
/* Record */
sout_instance_t
*
p_sout_record
;
};
static
es_out_id_t
*
EsOutAdd
(
es_out_t
*
,
es_format_t
*
);
...
...
@@ -266,6 +272,8 @@ es_out_t *input_EsOutNew( input_thread_t *p_input, int i_rate )
p_sys
->
i_rate
=
i_rate
;
p_sys
->
p_sout_record
=
NULL
;
return
out
;
}
...
...
@@ -277,12 +285,14 @@ void input_EsOutDelete( es_out_t *out )
es_out_sys_t
*
p_sys
=
out
->
p_sys
;
int
i
;
if
(
p_sys
->
p_sout_record
)
input_EsOutSetRecord
(
out
,
false
);
for
(
i
=
0
;
i
<
p_sys
->
i_es
;
i
++
)
{
if
(
p_sys
->
es
[
i
]
->
p_dec
)
{
input_DecoderDelete
(
p_sys
->
es
[
i
]
->
p_dec
);
}
free
(
p_sys
->
es
[
i
]
->
psz_language
);
free
(
p_sys
->
es
[
i
]
->
psz_language_code
);
es_format_Clean
(
&
p_sys
->
es
[
i
]
->
fmt
);
...
...
@@ -301,7 +311,6 @@ void input_EsOutDelete( es_out_t *out )
free
(
p_sys
->
ppsz_sub_language
[
i
]
);
free
(
p_sys
->
ppsz_sub_language
);
}
free
(
p_sys
->
es
);
/* FIXME duplicate work EsOutProgramDel (but we cannot use it) add a EsOutProgramClean ? */
...
...
@@ -351,7 +360,11 @@ static void EsOutDiscontinuity( es_out_t *out, bool b_flush, bool b_audio )
/* Send a dummy block to let decoder know that
* there is a discontinuity */
if
(
es
->
p_dec
&&
(
!
b_audio
||
es
->
fmt
.
i_cat
==
AUDIO_ES
)
)
{
input_DecoderDiscontinuity
(
es
->
p_dec
,
b_flush
);
if
(
es
->
p_dec_record
)
input_DecoderDiscontinuity
(
es
->
p_dec_record
,
b_flush
);
}
}
}
void
input_EsOutChangeRate
(
es_out_t
*
out
,
int
i_rate
)
...
...
@@ -366,6 +379,73 @@ void input_EsOutChangeRate( es_out_t *out, int i_rate )
input_ClockSetRate
(
&
p_sys
->
pgrm
[
i
]
->
clock
,
i_rate
);
}
int
input_EsOutSetRecord
(
es_out_t
*
out
,
bool
b_record
)
{
es_out_sys_t
*
p_sys
=
out
->
p_sys
;
input_thread_t
*
p_input
=
p_sys
->
p_input
;
assert
(
(
b_record
&&
!
p_sys
->
p_sout_record
)
||
(
!
b_record
&&
p_sys
->
p_sout_record
)
);
if
(
b_record
)
{
char
*
psz_path
=
var_CreateGetString
(
p_input
,
"input-record-path"
);
if
(
!
psz_path
||
*
psz_path
==
'\0'
)
{
free
(
psz_path
);
psz_path
=
strdup
(
config_GetHomeDir
()
);
}
char
*
psz_sout
=
NULL
;
// TODO conf
if
(
!
psz_sout
&&
psz_path
)
{
char
*
psz_file
=
input_CreateFilename
(
VLC_OBJECT
(
p_input
),
psz_path
,
INPUT_RECORD_PREFIX
,
NULL
);
if
(
psz_file
)
{
if
(
asprintf
(
&
psz_sout
,
"#record{dst-prefix='%s'}"
,
psz_file
)
<
0
)
psz_sout
=
NULL
;
free
(
psz_file
);
}
}
free
(
psz_path
);
if
(
!
psz_sout
)
return
VLC_EGENERIC
;
p_sys
->
p_sout_record
=
sout_NewInstance
(
p_input
,
psz_sout
);
free
(
psz_sout
);
if
(
!
p_sys
->
p_sout_record
)
return
VLC_EGENERIC
;
for
(
int
i
=
0
;
i
<
p_sys
->
i_es
;
i
++
)
{
es_out_id_t
*
p_es
=
p_sys
->
es
[
i
];
if
(
!
p_es
->
p_dec
||
p_es
->
p_master
)
continue
;
p_es
->
p_dec_record
=
input_DecoderNew
(
p_input
,
&
p_es
->
fmt
,
p_sys
->
p_sout_record
);
}
}
else
{
for
(
int
i
=
0
;
i
<
p_sys
->
i_es
;
i
++
)
{
es_out_id_t
*
p_es
=
p_sys
->
es
[
i
];
if
(
!
p_es
->
p_dec_record
)
continue
;
input_DecoderDelete
(
p_es
->
p_dec_record
);
p_es
->
p_dec_record
=
NULL
;
}
sout_DeleteInstance
(
p_sys
->
p_sout_record
);
p_sys
->
p_sout_record
=
NULL
;
}
return
VLC_SUCCESS
;
}
void
input_EsOutSetDelay
(
es_out_t
*
out
,
int
i_cat
,
int64_t
i_delay
)
{
es_out_sys_t
*
p_sys
=
out
->
p_sys
;
...
...
@@ -411,6 +491,8 @@ bool input_EsOutDecodersEmpty( es_out_t *out )
if
(
es
->
p_dec
&&
!
input_DecoderEmpty
(
es
->
p_dec
)
)
return
false
;
if
(
es
->
p_dec_record
&&
!
input_DecoderEmpty
(
es
->
p_dec_record
)
)
return
false
;
}
return
true
;
}
...
...
@@ -994,9 +1076,10 @@ static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
es
->
psz_language
=
LanguageGetName
(
fmt
->
psz_language
);
/* remember so we only need to do it once */
es
->
psz_language_code
=
LanguageGetCode
(
fmt
->
psz_language
);
es
->
p_dec
=
NULL
;
es
->
p_dec_record
=
NULL
;
for
(
i
=
0
;
i
<
4
;
i
++
)
es
->
pb_cc_present
[
i
]
=
false
;
es
->
p_master
=
false
;
es
->
p_master
=
NULL
;
if
(
es
->
p_pgrm
==
p_sys
->
p_pgrm
)
EsOutESVarUpdate
(
out
,
es
,
false
);
...
...
@@ -1043,6 +1126,32 @@ static bool EsIsSelected( es_out_id_t *es )
return
es
->
p_dec
!=
NULL
;
}
}
static
void
EsCreateDecoder
(
es_out_t
*
out
,
es_out_id_t
*
p_es
)
{
es_out_sys_t
*
p_sys
=
out
->
p_sys
;
input_thread_t
*
p_input
=
p_sys
->
p_input
;
p_es
->
p_dec
=
input_DecoderNew
(
p_input
,
&
p_es
->
fmt
,
p_input
->
p
->
p_sout
);
if
(
p_es
->
p_dec
&&
!
p_es
->
p_master
&&
p_sys
->
p_sout_record
)
p_es
->
p_dec_record
=
input_DecoderNew
(
p_input
,
&
p_es
->
fmt
,
p_sys
->
p_sout_record
);
}
static
void
EsDestroyDecoder
(
es_out_t
*
out
,
es_out_id_t
*
p_es
)
{
es_out_sys_t
*
p_sys
=
out
->
p_sys
;
if
(
!
p_es
->
p_dec
)
return
;
input_DecoderDelete
(
p_es
->
p_dec
);
p_es
->
p_dec
=
NULL
;
if
(
p_es
->
p_dec_record
)
{
input_DecoderDelete
(
p_es
->
p_dec_record
);
p_es
->
p_dec_record
=
NULL
;
}
}
static
void
EsSelect
(
es_out_t
*
out
,
es_out_id_t
*
es
)
{
es_out_sys_t
*
p_sys
=
out
->
p_sys
;
...
...
@@ -1099,7 +1208,8 @@ static void EsSelect( es_out_t *out, es_out_id_t *es )
}
es
->
i_preroll_end
=
-
1
;
es
->
p_dec
=
input_DecoderNew
(
p_input
,
&
es
->
fmt
,
false
);
EsCreateDecoder
(
out
,
es
);
if
(
es
->
p_dec
==
NULL
||
es
->
p_pgrm
!=
p_sys
->
p_pgrm
)
return
;
}
...
...
@@ -1163,8 +1273,7 @@ static void EsUnselect( es_out_t *out, es_out_id_t *es, bool b_update )
es
->
pb_cc_present
[
i
]
=
false
;
}
input_DecoderDelete
(
es
->
p_dec
);
es
->
p_dec
=
NULL
;
EsDestroyDecoder
(
out
,
es
);
}
if
(
!
b_update
)
...
...
@@ -1450,6 +1559,12 @@ static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
bool
pb_cc
[
4
];
bool
b_cc_new
=
false
;
int
i
;
if
(
es
->
p_dec_record
)
{
block_t
*
p_dup
=
block_Duplicate
(
p_block
);
if
(
p_dup
)
input_DecoderDecode
(
es
->
p_dec_record
,
p_dup
);
}
input_DecoderDecode
(
es
->
p_dec
,
p_block
);
/* Check CC status */
...
...
@@ -1510,7 +1625,8 @@ static void EsOutDel( es_out_t *out, es_out_id_t *es )
{
while
(
!
out
->
p_sys
->
p_input
->
b_die
&&
es
->
p_dec
)
{
if
(
input_DecoderEmpty
(
es
->
p_dec
)
)
if
(
input_DecoderEmpty
(
es
->
p_dec
)
&&
(
!
es
->
p_dec_record
||
input_DecoderEmpty
(
es
->
p_dec_record
)
))
break
;
msleep
(
20
*
1000
);
}
...
...
@@ -1824,7 +1940,8 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args )
es_format_t
*
p_fmt
;
es
=
(
es_out_id_t
*
)
va_arg
(
args
,
es_out_id_t
*
);
p_fmt
=
(
es_format_t
*
)
va_arg
(
args
,
es_format_t
*
);
if
(
es
==
NULL
)
return
VLC_EGENERIC
;
if
(
es
==
NULL
)
return
VLC_EGENERIC
;
if
(
p_fmt
->
i_extra
)
{
...
...
@@ -1832,13 +1949,12 @@ static int EsOutControl( es_out_t *out, int i_query, va_list args )
es
->
fmt
.
p_extra
=
realloc
(
es
->
fmt
.
p_extra
,
p_fmt
->
i_extra
);
memcpy
(
es
->
fmt
.
p_extra
,
p_fmt
->
p_extra
,
p_fmt
->
i_extra
);
if
(
!
es
->
p_dec
)
return
VLC_SUCCESS
;
if
(
!
es
->
p_dec
)
return
VLC_SUCCESS
;
#if 1
input_DecoderDelete
(
es
->
p_dec
);
es
->
p_dec
=
input_DecoderNew
(
p_sys
->
p_input
,
&
es
->
fmt
,
false
);
EsDestroyDecoder
(
out
,
es
);
EsCreateDecoder
(
out
,
es
);
#else
es
->
p_dec
->
fmt_in
.
i_extra
=
p_fmt
->
i_extra
;
es
->
p_dec
->
fmt_in
.
p_extra
=
...
...
src/input/input.c
View file @
c1412599
...
...
@@ -43,6 +43,7 @@
#include <vlc_interface.h>
#include <vlc_url.h>
#include <vlc_charset.h>
#include <vlc_strings.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
...
...
@@ -1946,16 +1947,20 @@ static bool Control( input_thread_t *p_input, int i_type,
break
;
case
INPUT_CONTROL_SET_RECORD_STATE
:
if
(
p_input
->
p
->
input
.
b_can_record
)
if
(
!!
p_input
->
p
->
b_recording
!=
!!
val
.
b_bool
)
{
if
(
!!
p_input
->
p
->
b_recording
!=
!!
val
.
b_bool
)
if
(
p_input
->
p
->
input
.
b_can_stream_record
)
{
if
(
demux_Control
(
p_input
->
p
->
input
.
p_demux
,
DEMUX_SET_RECORD_STATE
,
val
.
b_bool
)
)
val
.
b_bool
=
false
;
p_input
->
p
->
b_recording
=
val
.
b_bool
;
}
else
{
if
(
input_EsOutSetRecord
(
p_input
->
p
->
p_es_out
,
val
.
b_bool
)
)
val
.
b_bool
=
false
;
}
p_input
->
p
->
b_recording
=
val
.
b_bool
;
var_Change
(
p_input
,
"record"
,
VLC_VAR_SETVALUE
,
&
val
,
NULL
);
...
...
@@ -2365,9 +2370,11 @@ static int InputSourceInit( input_thread_t *p_input,
goto
error
;
}
if
(
demux_Control
(
in
->
p_demux
,
DEMUX_CAN_RECORD
,
&
in
->
b_can_record
)
)
in
->
b_can_record
=
false
;
var_SetBool
(
p_input
,
"can-record"
,
in
->
b_can_record
);
if
(
demux_Control
(
in
->
p_demux
,
DEMUX_CAN_RECORD
,
&
in
->
b_can_stream_record
)
)
in
->
b_can_stream_record
=
false
;
if
(
!
var_CreateGetBool
(
p_input
,
"input-record-native"
)
)
in
->
b_can_stream_record
=
false
;
var_SetBool
(
p_input
,
"can-record"
,
true
);
// Is it still needed ?
/* Get title from demux */
if
(
!
p_input
->
b_preparsing
&&
in
->
i_title
<=
0
)
...
...
@@ -2929,3 +2936,37 @@ vlc_event_manager_t *input_get_event_manager( input_thread_t *p_input )
{
return
&
p_input
->
p
->
event_manager
;
}
/**/
/* TODO FIXME nearly the same logic that snapshot code */
char
*
input_CreateFilename
(
vlc_object_t
*
p_obj
,
const
char
*
psz_path
,
const
char
*
psz_prefix
,
const
char
*
psz_extension
)
{
char
*
psz_file
;
DIR
*
path
;
path
=
utf8_opendir
(
psz_path
);
if
(
path
)
{
closedir
(
path
);
char
*
psz_tmp
=
str_format
(
p_obj
,
psz_prefix
);
if
(
!
psz_tmp
)
return
NULL
;
filename_sanitize
(
psz_tmp
);
if
(
asprintf
(
&
psz_file
,
"%s"
DIR_SEP
"%s%s%s"
,
psz_path
,
psz_tmp
,
psz_extension
?
"."
:
""
,
psz_extension
?
psz_extension
:
""
)
<
0
)
psz_file
=
NULL
;
free
(
psz_tmp
);
return
psz_file
;
}
else
{
psz_file
=
str_format
(
p_obj
,
psz_path
);
path_sanitize
(
psz_file
);
return
psz_file
;
}
}
src/input/input_internal.h
View file @
c1412599
...
...
@@ -63,7 +63,7 @@ typedef struct
bool
b_can_pause
;
bool
b_can_pace_control
;
bool
b_can_rate_control
;
bool
b_can_record
;
bool
b_can_
stream_
record
;
bool
b_rescale_ts
;
bool
b_eof
;
/* eof of demuxer */
...
...
@@ -343,6 +343,7 @@ es_out_t *input_EsOutNew( input_thread_t *, int i_rate );
void
input_EsOutDelete
(
es_out_t
*
);
es_out_id_t
*
input_EsOutGetFromID
(
es_out_t
*
,
int
i_id
);
void
input_EsOutSetDelay
(
es_out_t
*
,
int
i_cat
,
int64_t
);
int
input_EsOutSetRecord
(
es_out_t
*
,
bool
b_record
);
void
input_EsOutChangeRate
(
es_out_t
*
,
int
);
void
input_EsOutChangeState
(
es_out_t
*
);
void
input_EsOutChangePosition
(
es_out_t
*
);
...
...
@@ -419,6 +420,10 @@ static inline void input_ChangeState( input_thread_t *p_input, int state )
input_ChangeStateWithVarCallback
(
p_input
,
state
,
true
);
}
/* Helpers FIXME to export without input_ prefix */
char
*
input_CreateFilename
(
vlc_object_t
*
p_obj
,
const
char
*
psz_path
,
const
char
*
psz_prefix
,
const
char
*
psz_extension
);
#define INPUT_RECORD_PREFIX "vlc-record-%Y-%m-%d-%H:%M:%S-$p"
/* Access */
...
...
src/input/stream.c
View file @
c1412599
...
...
@@ -28,9 +28,9 @@
#include <dirent.h>
#include <vlc_common.h>
#include <vlc_charset.h>
#include <vlc_strings.h>
#include <vlc_osd.h>
#include <vlc_charset.h>
#include <assert.h>
...
...
@@ -731,37 +731,6 @@ static int AStreamControl( stream_t *s, int i_query, va_list args )
/****************************************************************************
* ARecord*: record stream functions
****************************************************************************/
/* TODO FIXME nearly the same logic that snapshot code */
static
char
*
ARecordGetFileName
(
stream_t
*
s
,
const
char
*
psz_path
,
const
char
*
psz_prefix
,
const
char
*
psz_extension
)
{
char
*
psz_file
;
DIR
*
path
;
path
=
utf8_opendir
(
psz_path
);
if
(
path
)
{
closedir
(
path
);
char
*
psz_tmp
=
str_format
(
s
,
psz_prefix
);
if
(
!
psz_tmp
)
return
NULL
;
filename_sanitize
(
psz_tmp
);
if
(
asprintf
(
&
psz_file
,
"%s"
DIR_SEP
"%s.%s"
,
psz_path
,
psz_tmp
,
psz_extension
)
<
0
)
psz_file
=
NULL
;
free
(
psz_tmp
);
return
psz_file
;
}
else
{
psz_file
=
str_format
(
s
,
psz_path
);
path_sanitize
(
psz_file
);
return
psz_file
;
}
}
static
int
ARecordStart
(
stream_t
*
s
,
const
char
*
psz_extension
)
{
stream_sys_t
*
p_sys
=
s
->
p_sys
;
...
...
@@ -786,7 +755,7 @@ static int ARecordStart( stream_t *s, const char *psz_extension )
/* Create file name
* TODO allow prefix configuration */
psz_file
=
ARecordGetFileName
(
s
,
psz_path
,
"vlc-record-%Y-%m-%d-%H:%M:%S-$p"
,
psz_extension
);
psz_file
=
input_CreateFilename
(
VLC_OBJECT
(
s
),
psz_path
,
INPUT_RECORD_PREFIX
,
psz_extension
);
free
(
psz_path
);
...
...
src/libvlc-module.c
View file @
c1412599
...
...
@@ -679,6 +679,11 @@ static const char *const ppsz_clock_descriptions[] =
#define INPUT_RECORD_PATH_LONGTEXT N_( \
"Directory or filename where the records will be stored" )
#define INPUT_RECORD_NATIVE_TEXT N_("Prefer native stream recording")
#define INPUT_RECORD_NATIVE_LONGTEXT N_( \
"When possible, the input stream will be recorded instead of using" \
"the stream output module" )
// DEPRECATED
#define SUB_CAT_LONGTEXT N_( \
"These options allow you to modify the behavior of the subpictures " \
...
...
@@ -1743,6 +1748,8 @@ vlc_module_begin();
add_string
(
"input-record-path"
,
NULL
,
NULL
,
INPUT_RECORD_PATH_TEXT
,
INPUT_RECORD_PATH_LONGTEXT
,
true
);
add_bool
(
"input-record-native"
,
true
,
NULL
,
INPUT_RECORD_NATIVE_TEXT
,
INPUT_RECORD_NATIVE_LONGTEXT
,
true
);
/* Decoder options */
add_category_hint
(
N_
(
"Decoders"
),
CODEC_CAT_LONGTEXT
,
true
);
...
...
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