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
f9d6ca04
Commit
f9d6ca04
authored
Jan 12, 2008
by
Antoine Cellerier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] v4l2 mpeg2 controls by Dennis Lou. Thanks.
parent
4a48618f
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
193 additions
and
18 deletions
+193
-18
modules/access/v4l2.c
modules/access/v4l2.c
+193
-18
No files found.
modules/access/v4l2.c
View file @
f9d6ca04
...
...
@@ -36,7 +36,6 @@
/*
* TODO: Tuner partial implementation.
* TODO: Add more MPEG stream params
*/
/*****************************************************************************
...
...
@@ -49,6 +48,7 @@
#include <vlc_input.h>
#include <vlc_vout.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
...
...
@@ -183,6 +183,15 @@ static void AccessClose( vlc_object_t * );
"Audio method to use: 0 to disable audio, 1 for OSS, 2 for ALSA, " \
"3 for ALSA or OSS (ALSA is prefered)." )
#endif
#define AUDIO_VOLUME_TEXT N_( "Volume" )
#define AUDIO_VOLUME_LONGTEXT N_( \
"Volume of the audio input (if supported by v4l2 driver)." )
#define AUDIO_BALANCE_TEXT N_( "Balance" )
#define AUDIO_BALANCE_LONGTEXT N_( \
"Balance of the audio input (if supported by v4l2 driver)." )
#define AUDIO_MUTE_TEXT N_( "Mute" )
#define AUDIO_MUTE_LONGTEXT N_( \
"Mute audio input (if supported by v4l2 driver)." )
#define STEREO_TEXT N_( "Stereo" )
#define STEREO_LONGTEXT N_( \
"Capture the audio stream in stereo." )
...
...
@@ -194,6 +203,13 @@ static void AccessClose( vlc_object_t * );
#define CACHING_LONGTEXT N_( \
"Caching value for V4L2 captures. This " \
"value should be set in milliseconds." )
#define S_CTRLS_TEXT N_("v4l2 driver controls")
#define S_CTRLS_LONGTEXT N_( \
"Set the v4l2 driver controls to the values specified using a comma " \
"separated list optionally encapsulated by curly braces " \
"(e.g.: {video_bitrate=6000000,audio_crc=0,stream_type=3} ). " \
"To list available controls, increase verbosity (-vvv) " \
"or use the v4l2-ctl application." )
typedef
enum
{
IO_METHOD_READ
,
...
...
@@ -295,6 +311,14 @@ vlc_module_begin();
HCENTER_LONGTEXT
,
VLC_TRUE
);
add_integer
(
CFG_PREFIX
"vcenter"
,
-
1
,
NULL
,
VCENTER_TEXT
,
VCENTER_LONGTEXT
,
VLC_TRUE
);
add_integer
(
CFG_PREFIX
"audio-volume"
,
-
1
,
NULL
,
AUDIO_VOLUME_TEXT
,
AUDIO_VOLUME_LONGTEXT
,
VLC_TRUE
);
add_integer
(
CFG_PREFIX
"audio-balance"
,
-
1
,
NULL
,
AUDIO_BALANCE_TEXT
,
AUDIO_BALANCE_LONGTEXT
,
VLC_TRUE
);
add_bool
(
CFG_PREFIX
"audio-mute"
,
VLC_FALSE
,
NULL
,
AUDIO_MUTE_TEXT
,
AUDIO_MUTE_LONGTEXT
,
VLC_TRUE
);
add_string
(
CFG_PREFIX
"set-ctrls"
,
NULL
,
NULL
,
S_CTRLS_TEXT
,
S_CTRLS_LONGTEXT
,
VLC_TRUE
);
add_shortcut
(
"v4l2"
);
set_capability
(
"access_demux"
,
10
);
...
...
@@ -315,6 +339,7 @@ vlc_module_end();
static
void
CommonClose
(
vlc_object_t
*
,
demux_sys_t
*
);
static
void
ParseMRL
(
demux_sys_t
*
,
char
*
,
vlc_object_t
*
);
static
void
GetV4L2Params
(
demux_sys_t
*
,
vlc_object_t
*
);
static
void
SetAvailControlsByString
(
vlc_object_t
*
,
demux_sys_t
*
,
int
);
static
int
DemuxControl
(
demux_t
*
,
int
,
va_list
);
static
int
AccessControl
(
access_t
*
,
int
,
va_list
);
...
...
@@ -503,6 +528,8 @@ struct demux_sys_t
size_t
i_alsa_frame_size
;
int
i_alsa_chunk_size
;
#endif
char
*
psz_set_ctrls
;
};
static
int
FindMainDevice
(
vlc_object_t
*
p_this
,
demux_sys_t
*
p_sys
,
...
...
@@ -675,6 +702,8 @@ static void GetV4L2Params( demux_sys_t *p_sys, vlc_object_t *p_obj )
p_sys
->
i_pts
=
var_CreateGetInteger
(
p_obj
,
"v4l2-caching"
);
p_sys
->
psz_set_ctrls
=
var_CreateGetString
(
p_obj
,
"v4l2-set-ctrls"
);
p_sys
->
psz_device
=
p_sys
->
psz_vdev
=
p_sys
->
psz_adev
=
NULL
;
p_sys
->
i_fd_video
=
-
1
;
p_sys
->
i_fd_audio
=
-
1
;
...
...
@@ -891,9 +920,33 @@ static void ParseMRL( demux_sys_t *p_sys, char *psz_path, vlc_object_t *p_obj )
p_sys
->
i_pts
=
strtol
(
psz_parser
+
strlen
(
"caching="
),
&
psz_parser
,
0
);
}
else
if
(
!
strncmp
(
psz_parser
,
"set-ctrls="
,
strlen
(
"set-ctrls="
))
)
{
int
i_len
;
psz_parser
+=
strlen
(
"set-ctrls="
);
if
(
strchr
(
psz_parser
,
':'
)
)
{
i_len
=
strchr
(
psz_parser
,
':'
)
-
psz_parser
;
}
else
{
i_len
=
strlen
(
psz_parser
);
}
p_sys
->
psz_set_ctrls
=
strndup
(
psz_parser
,
i_len
);
psz_parser
+=
i_len
;
}
else
{
msg_Warn
(
p_obj
,
"unknown option"
);
char
*
psz_unk
=
strchr
(
psz_parser
,
':'
);
if
(
psz_unk
)
psz_unk
=
strndup
(
psz_parser
,
psz_unk
-
psz_parser
);
else
psz_unk
=
strdup
(
psz_parser
);
msg_Warn
(
p_obj
,
"unknown option %s"
,
psz_unk
);
free
(
psz_unk
);
}
while
(
*
psz_parser
&&
*
psz_parser
!=
':'
)
...
...
@@ -1019,6 +1072,7 @@ static void CommonClose( vlc_object_t *p_this, demux_sys_t *p_sys )
free
(
p_sys
->
p_tuners
);
free
(
p_sys
->
p_codecs
);
free
(
p_sys
->
psz_requested_chroma
);
free
(
p_sys
->
psz_set_ctrls
);
free
(
p_sys
);
}
...
...
@@ -1722,6 +1776,7 @@ static int OpenVideoDev( vlc_object_t *p_obj, demux_sys_t *p_sys, vlc_bool_t b_d
/* if MPEG encoder card, no need to do anything else after this */
ControlList
(
p_obj
,
i_fd
,
var_GetBool
(
p_obj
,
"v4l2-controls-reset"
),
b_demux
);
SetAvailControlsByString
(
p_obj
,
p_sys
,
i_fd
);
if
(
VLC_FALSE
==
b_demux
)
{
return
i_fd
;
...
...
@@ -2717,6 +2772,12 @@ static vlc_bool_t ProbeAudioDev( vlc_object_t *p_this, demux_sys_t *p_sys,
return
VLC_FALSE
;
}
static
void
name2var
(
unsigned
char
*
name
)
{
for
(
;
*
name
;
name
++
)
*
name
=
(
*
name
==
' '
)
?
'_'
:
tolower
(
*
name
);
}
/*****************************************************************************
* Print a user-class v4l2 control's details, create the relevant variable,
* change the value if needed.
...
...
@@ -2752,12 +2813,8 @@ static void ControlListPrint( vlc_object_t *p_obj, int i_fd,
}
else
{
char
*
psz_buf
;
psz_name
=
strdup
(
(
const
char
*
)
queryctrl
.
name
);
for
(
psz_buf
=
psz_name
;
*
psz_buf
;
psz_buf
++
)
{
if
(
*
psz_buf
==
' '
)
*
psz_buf
=
'-'
;
}
name2var
(
(
unsigned
char
*
)
psz_name
);
i_val
=
-
1
;
}
...
...
@@ -2863,7 +2920,11 @@ static void ControlListPrint( vlc_object_t *p_obj, int i_fd,
var_Change
(
p_obj
,
psz_name
,
VLC_VAR_SETTEXT
,
&
val
,
NULL
);
val
.
i_int
=
queryctrl
.
id
;
val2
.
psz_string
=
(
char
*
)
psz_name
;
var_Change
(
p_obj
,
"controls"
,
VLC_VAR_ADDCHOICE
,
&
val
,
&
val2
);
var_Change
(
p_obj
,
"allcontrols"
,
VLC_VAR_ADDCHOICE
,
&
val
,
&
val2
);
/* bad things happen changing MPEG mid-stream
* so don't add to Ext Settings GUI */
if
(
V4L2_CTRL_ID2CLASS
(
queryctrl
.
id
)
!=
V4L2_CTRL_CLASS_MPEG
)
var_Change
(
p_obj
,
"controls"
,
VLC_VAR_ADDCHOICE
,
&
val
,
&
val2
);
switch
(
var_Type
(
p_obj
,
psz_name
)
&
VLC_VAR_TYPE
)
{
...
...
@@ -2904,9 +2965,12 @@ static int ControlList( vlc_object_t *p_obj, int i_fd,
memset
(
&
queryctrl
,
0
,
sizeof
(
queryctrl
)
);
/* A list of available controls (aka the variable name) will be
* stored as choices in the "controls" variable. We'll thus be able
* to use those to create an appropriate interface */
* stored as choices in the "allcontrols" variable. We'll thus be able
* to use those to create an appropriate interface
* A list of available controls that can be changed mid-stream will
* be stored in the "controls" variable */
var_Create
(
p_obj
,
"controls"
,
VLC_VAR_INTEGER
|
VLC_VAR_HASCHOICE
);
var_Create
(
p_obj
,
"allcontrols"
,
VLC_VAR_INTEGER
|
VLC_VAR_HASCHOICE
);
var_Create
(
p_obj
,
"controls-update"
,
VLC_VAR_VOID
|
VLC_VAR_ISCOMMAND
);
...
...
@@ -2932,6 +2996,12 @@ static int ControlList( vlc_object_t *p_obj, int i_fd,
queryctrl
.
id
=
V4L2_CTRL_FLAG_NEXT_CTRL
;
while
(
ioctl
(
i_fd
,
VIDIOC_QUERYCTRL
,
&
queryctrl
)
>=
0
)
{
if
(
queryctrl
.
type
==
V4L2_CTRL_TYPE_CTRL_CLASS
)
{
msg_Dbg
(
p_obj
,
"%s"
,
queryctrl
.
name
);
queryctrl
.
id
|=
V4L2_CTRL_FLAG_NEXT_CTRL
;
continue
;
}
switch
(
V4L2_CTRL_ID2CLASS
(
queryctrl
.
id
)
)
{
case
V4L2_CTRL_CLASS_USER
:
...
...
@@ -2939,6 +3009,7 @@ static int ControlList( vlc_object_t *p_obj, int i_fd,
queryctrl
.
name
,
queryctrl
.
id
);
break
;
case
V4L2_CTRL_CLASS_MPEG
:
name2var
(
queryctrl
.
name
);
msg_Dbg
(
p_obj
,
"Available MPEG control: %s (%x)"
,
queryctrl
.
name
,
queryctrl
.
id
);
break
;
...
...
@@ -2993,6 +3064,79 @@ static int ControlList( vlc_object_t *p_obj, int i_fd,
return
VLC_SUCCESS
;
}
static
void
SetAvailControlsByString
(
vlc_object_t
*
p_obj
,
demux_sys_t
*
p_sys
,
int
i_fd
)
{
char
*
psz_parser
=
p_sys
->
psz_set_ctrls
;
vlc_value_t
val
,
text
,
name
;
if
(
psz_parser
==
NULL
)
return
;
if
(
*
psz_parser
==
'{'
)
psz_parser
++
;
int
i_ret
=
var_Change
(
p_obj
,
"allcontrols"
,
VLC_VAR_GETCHOICES
,
&
val
,
&
text
);
if
(
i_ret
<
0
)
{
msg_Err
(
p_obj
,
"Oops, can't find 'allcontrols' variable."
);
return
;
}
while
(
*
psz_parser
&&
*
psz_parser
!=
'}'
)
{
char
*
psz_delim
,
*
psz_assign
;
while
(
*
psz_parser
==
','
||
*
psz_parser
==
' '
)
psz_parser
++
;
psz_delim
=
strchr
(
psz_parser
,
','
);
if
(
psz_delim
==
NULL
)
psz_delim
=
strchr
(
psz_parser
,
'}'
);
if
(
psz_delim
==
NULL
)
psz_delim
=
psz_parser
+
strlen
(
psz_parser
);
psz_assign
=
memchr
(
psz_parser
,
'='
,
psz_delim
-
psz_parser
);
if
(
psz_assign
==
NULL
)
{
char
*
psz_name
=
strndup
(
psz_parser
,
psz_delim
-
psz_parser
);
msg_Err
(
p_obj
,
"%s missing '='"
,
psz_name
);
free
(
psz_name
);
psz_parser
=
psz_delim
+
1
;
continue
;
}
for
(
int
i
=
0
;
i
<
val
.
p_list
->
i_count
;
//&& psz_parser < psz_assign;
i
++
)
{
const
char
*
psz_var
=
text
.
p_list
->
p_values
[
i
].
psz_string
;
int
i_cid
=
val
.
p_list
->
p_values
[
i
].
i_int
;
var_Change
(
p_obj
,
psz_var
,
VLC_VAR_GETTEXT
,
&
name
,
NULL
);
const
char
*
psz_name
=
name
.
psz_string
;
int
i_availstrlen
=
strlen
(
psz_name
);
int
i_parsestrlen
=
psz_assign
-
psz_parser
;
int
i_maxstrlen
=
__MAX
(
i_availstrlen
,
i_parsestrlen
);
if
(
!
strncasecmp
(
psz_name
,
psz_parser
,
i_maxstrlen
)
)
{
Control
(
p_obj
,
i_fd
,
psz_name
,
i_cid
,
strtol
(
++
psz_assign
,
&
psz_parser
,
0
)
);
}
}
if
(
psz_parser
<
psz_assign
)
{
char
*
psz_name
=
strndup
(
psz_parser
,
psz_assign
-
psz_parser
);
msg_Err
(
p_obj
,
"Control %s not available"
,
psz_name
);
free
(
psz_name
);
psz_parser
=
(
*
psz_delim
)
?
(
psz_delim
+
1
)
:
psz_delim
;
}
}
}
/*****************************************************************************
* Reset all user-class v4l2 controls to their default value
*****************************************************************************/
...
...
@@ -3064,6 +3208,8 @@ static int Control( vlc_object_t *p_obj, int i_fd,
{
struct
v4l2_queryctrl
queryctrl
;
struct
v4l2_control
control
;
struct
v4l2_ext_control
ext_control
;
struct
v4l2_ext_controls
ext_controls
;
if
(
i_value
==
-
1
)
return
VLC_SUCCESS
;
...
...
@@ -3075,25 +3221,54 @@ static int Control( vlc_object_t *p_obj, int i_fd,
if
(
ioctl
(
i_fd
,
VIDIOC_QUERYCTRL
,
&
queryctrl
)
<
0
||
queryctrl
.
flags
&
V4L2_CTRL_FLAG_DISABLED
)
{
msg_Dbg
(
p_obj
,
"%s (%x) control is not supported."
,
psz_name
,
i_cid
);
msg_Dbg
(
p_obj
,
"%s (%x) control is not supported."
,
psz_name
,
i_cid
);
return
VLC_EGENERIC
;
}
memset
(
&
control
,
0
,
sizeof
(
control
)
);
memset
(
&
ext_control
,
0
,
sizeof
(
ext_control
)
);
memset
(
&
ext_controls
,
0
,
sizeof
(
ext_controls
)
);
control
.
id
=
i_cid
;
ext_control
.
id
=
i_cid
;
ext_controls
.
ctrl_class
=
V4L2_CTRL_CLASS_MPEG
;
ext_controls
.
count
=
1
;
ext_controls
.
controls
=
&
ext_control
;
if
(
i_value
>=
0
)
{
control
.
value
=
i_value
;
if
(
ioctl
(
i_fd
,
VIDIOC_S_CTRL
,
&
control
)
<
0
)
if
(
V4L2_CTRL_ID2CLASS
(
i_cid
)
==
V4L2_CTRL_CLASS_USER
)
{
msg_Err
(
p_obj
,
"unable to set %s to %d (%m)"
,
psz_name
,
i_value
);
return
VLC_EGENERIC
;
control
.
value
=
i_value
;
if
(
ioctl
(
i_fd
,
VIDIOC_S_CTRL
,
&
control
)
<
0
)
{
msg_Err
(
p_obj
,
"unable to set %s (%x) to %d (%m)"
,
psz_name
,
i_cid
,
i_value
);
return
VLC_EGENERIC
;
}
}
else
{
ext_control
.
value
=
i_value
;
if
(
ioctl
(
i_fd
,
VIDIOC_S_EXT_CTRLS
,
&
ext_controls
)
<
0
)
{
msg_Err
(
p_obj
,
"unable to set %s (%x) to %d (%m)"
,
psz_name
,
i_cid
,
i_value
);
return
VLC_EGENERIC
;
}
}
}
int
i_ret
;
if
(
V4L2_CTRL_ID2CLASS
(
i_cid
)
==
V4L2_CTRL_CLASS_USER
)
i_ret
=
ioctl
(
i_fd
,
VIDIOC_G_CTRL
,
&
control
);
else
{
i_ret
=
ioctl
(
i_fd
,
VIDIOC_G_EXT_CTRLS
,
&
ext_controls
);
control
.
value
=
ext_control
.
value
;
}
if
(
ioctl
(
i_fd
,
VIDIOC_G_CTRL
,
&
control
)
>=
0
)
if
(
i_ret
>=
0
)
{
vlc_value_t
val
;
msg_Dbg
(
p_obj
,
"video %s: %d"
,
psz_name
,
control
.
value
);
...
...
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