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
77787198
Commit
77787198
authored
Dec 24, 2007
by
Richard Hosking
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
v4l2.c: Patch by Dennis Lou to add MPEG2 support. Many thanks.
parent
4b295c7c
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
463 additions
and
175 deletions
+463
-175
modules/access/v4l2.c
modules/access/v4l2.c
+463
-175
No files found.
modules/access/v4l2.c
View file @
77787198
...
...
@@ -35,6 +35,7 @@
/*
* TODO: Tuner partial implementation.
* TODO: Add more MPEG stream params
*/
/*****************************************************************************
...
...
@@ -66,8 +67,10 @@
* Module descriptior
*****************************************************************************/
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
static
int
DemuxOpen
(
vlc_object_t
*
);
static
void
DemuxClose
(
vlc_object_t
*
);
static
int
AccessOpen
(
vlc_object_t
*
);
static
void
AccessClose
(
vlc_object_t
*
);
#define DEV_TEXT N_("Device name")
#define DEV_LONGTEXT N_( \
...
...
@@ -210,18 +213,30 @@ vlc_module_begin();
add_shortcut
(
"v4l2"
);
set_capability
(
"access_demux"
,
10
);
set_callbacks
(
Open
,
Close
);
set_callbacks
(
DemuxOpen
,
DemuxClose
);
add_submodule
();
set_description
(
_
(
"Video4Linux2 Compressed A/V"
)
);
set_capability
(
"access2"
,
0
);
/* use these when open as access_demux fails; VLC will use another demux */
set_callbacks
(
AccessOpen
,
AccessClose
);
vlc_module_end
();
/*****************************************************************************
* Access: local prototypes
*****************************************************************************/
static
void
ParseMRL
(
demux_t
*
);
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
int
DemuxControl
(
demux_t
*
,
int
,
va_list
);
static
int
AccessControl
(
access_t
*
,
int
,
va_list
);
static
int
Demux
(
demux_t
*
);
static
ssize_t
AccessRead
(
access_t
*
,
uint8_t
*
,
size_t
);
static
block_t
*
GrabVideo
(
demux_t
*
p_demux
);
static
block_t
*
ProcessVideoFrame
(
demux_t
*
p_demux
,
uint8_t
*
p_frame
,
size_t
);
static
block_t
*
GrabAudio
(
demux_t
*
p_demux
);
...
...
@@ -229,18 +244,24 @@ static block_t* GrabAudio( demux_t *p_demux );
vlc_bool_t
IsPixelFormatSupported
(
demux_t
*
p_demux
,
unsigned
int
i_pixelformat
);
char
*
ResolveALSADeviceName
(
char
*
psz_device
);
static
int
OpenVideoDev
(
demux_t
*
,
char
*
psz_device
);
static
int
OpenVideoDev
(
vlc_object_t
*
,
demux_sys_t
*
,
vlc_bool_t
);
static
int
OpenAudioDev
(
demux_t
*
,
char
*
psz_device
);
static
vlc_bool_t
ProbeVideoDev
(
demux
_t
*
,
char
*
psz_device
);
static
vlc_bool_t
ProbeVideoDev
(
vlc_object_t
*
,
demux_sys
_t
*
,
char
*
psz_device
);
static
vlc_bool_t
ProbeAudioDev
(
demux_t
*
,
char
*
psz_device
);
static
int
ControlList
(
demux_t
*
p_demux
,
int
i_fd
,
vlc_bool_t
b_rese
t
);
static
int
Control
(
demux
_t
*
,
int
i_fd
,
static
int
ControlList
(
vlc_object_t
*
,
int
,
vlc_bool_t
,
vlc_bool_
t
);
static
int
Control
(
vlc_object
_t
*
,
int
i_fd
,
const
char
*
psz_name
,
int
i_cid
,
int
i_value
);
static
int
ControlCallback
(
vlc_object_t
*
p_this
,
static
int
DemuxControlCallback
(
vlc_object_t
*
p_this
,
const
char
*
psz_var
,
vlc_value_t
oldval
,
vlc_value_t
newval
,
void
*
p_data
);
static
int
DemuxControlResetCallback
(
vlc_object_t
*
p_this
,
const
char
*
psz_var
,
vlc_value_t
oldval
,
vlc_value_t
newval
,
void
*
p_data
);
static
int
AccessControlCallback
(
vlc_object_t
*
p_this
,
const
char
*
psz_var
,
vlc_value_t
oldval
,
vlc_value_t
newval
,
void
*
p_data
);
static
int
ControlResetCallback
(
vlc_object_t
*
p_this
,
static
int
Access
ControlResetCallback
(
vlc_object_t
*
p_this
,
const
char
*
psz_var
,
vlc_value_t
oldval
,
vlc_value_t
newval
,
void
*
p_data
);
...
...
@@ -379,17 +400,16 @@ struct demux_sys_t
};
/*****************************************************************************
*
Open: opens v4l2 device
*
DemuxOpen: opens v4l2 device, access_demux callback
*****************************************************************************
*
* url: <video device>::::
*
*****************************************************************************/
static
int
Open
(
vlc_object_t
*
p_this
)
static
int
Demux
Open
(
vlc_object_t
*
p_this
)
{
demux_t
*
p_demux
=
(
demux_t
*
)
p_this
;
demux_sys_t
*
p_sys
;
vlc_value_t
val
;
/* Only when selected */
if
(
*
p_demux
->
psz_access
==
'\0'
)
return
VLC_EGENERIC
;
...
...
@@ -404,51 +424,9 @@ static int Open( vlc_object_t *p_this )
p_demux
->
p_sys
=
p_sys
=
calloc
(
1
,
sizeof
(
demux_sys_t
)
);
if
(
p_sys
==
NULL
)
return
VLC_ENOMEM
;
p_sys
->
i_video_pts
=
-
1
;
var_Create
(
p_demux
,
"v4l2-standard"
,
VLC_VAR_INTEGER
|
VLC_VAR_DOINHERIT
);
var_Get
(
p_demux
,
"v4l2-standard"
,
&
val
);
p_sys
->
i_selected_standard_id
=
i_standards_list
[
val
.
i_int
];
p_sys
->
i_selected_input
=
var_CreateGetInteger
(
p_demux
,
"v4l2-input"
);
GetV4L2Params
(
p_sys
,
(
vlc_object_t
*
)
p_demux
);
p_sys
->
io
=
var_CreateGetInteger
(
p_demux
,
"v4l2-io"
);
p_sys
->
i_width
=
var_CreateGetInteger
(
p_demux
,
"v4l2-width"
);
p_sys
->
i_height
=
var_CreateGetInteger
(
p_demux
,
"v4l2-height"
);
var_CreateGetBool
(
p_demux
,
"v4l2-controls-reset"
);
var_Create
(
p_demux
,
"v4l2-fps"
,
VLC_VAR_FLOAT
|
VLC_VAR_DOINHERIT
);
var_Get
(
p_demux
,
"v4l2-fps"
,
&
val
);
p_sys
->
f_fps
=
val
.
f_float
;
var_Create
(
p_demux
,
"v4l2-samplerate"
,
VLC_VAR_INTEGER
|
VLC_VAR_DOINHERIT
);
var_Get
(
p_demux
,
"v4l2-samplerate"
,
&
val
);
p_sys
->
i_sample_rate
=
val
.
i_int
;
p_sys
->
psz_requested_chroma
=
var_CreateGetString
(
p_demux
,
"v4l2-chroma"
);
#ifdef HAVE_ALSA
var_Create
(
p_demux
,
"v4l2-alsa"
,
VLC_VAR_BOOL
|
VLC_VAR_DOINHERIT
);
var_Get
(
p_demux
,
"v4l2-alsa"
,
&
val
);
p_sys
->
b_use_alsa
=
val
.
b_bool
;
#endif
var_Create
(
p_demux
,
"v4l2-stereo"
,
VLC_VAR_BOOL
|
VLC_VAR_DOINHERIT
);
var_Get
(
p_demux
,
"v4l2-stereo"
,
&
val
);
p_sys
->
b_stereo
=
val
.
b_bool
;
p_sys
->
i_pts
=
var_CreateGetInteger
(
p_demux
,
"v4l2-caching"
);
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
;
p_sys
->
p_es_video
=
p_sys
->
p_es_audio
=
0
;
p_sys
->
p_block_audio
=
0
;
ParseMRL
(
p_demux
);
ParseMRL
(
p_sys
,
p_demux
->
psz_path
,
(
vlc_object_t
*
)
p_demux
);
#ifdef HAVE_ALSA
/* Alsa support available? */
...
...
@@ -462,17 +440,17 @@ static int Open( vlc_object_t *p_this )
/* Try to open as video device */
msg_Dbg
(
p_demux
,
"trying device '%s' as video"
,
p_sys
->
psz_device
);
if
(
ProbeVideoDev
(
p_demux
,
p_sys
->
psz_device
)
)
if
(
ProbeVideoDev
(
(
vlc_object_t
*
)
p_demux
,
p_sys
,
p_sys
->
psz_device
)
)
{
msg_Dbg
(
p_demux
,
"'%s' is a video device"
,
p_sys
->
psz_device
);
/* Device was a video device */
if
(
p_sys
->
psz_vdev
)
free
(
p_sys
->
psz_vdev
);
p_sys
->
psz_vdev
=
p_sys
->
psz_device
;
p_sys
->
psz_device
=
NULL
;
p_sys
->
i_fd_video
=
OpenVideoDev
(
p_demux
,
p_sys
->
psz_vdev
);
p_sys
->
i_fd_video
=
OpenVideoDev
(
(
vlc_object_t
*
)
p_demux
,
p_sys
,
VLC_TRUE
);
if
(
p_sys
->
i_fd_video
<
0
)
{
Close
(
p_this
);
Demux
Close
(
p_this
);
return
VLC_EGENERIC
;
}
}
...
...
@@ -490,7 +468,7 @@ static int Open( vlc_object_t *p_this )
p_sys
->
i_fd_audio
=
OpenAudioDev
(
p_demux
,
p_sys
->
psz_adev
);
if
(
p_sys
->
i_fd_audio
<
0
)
{
Close
(
p_this
);
Demux
Close
(
p_this
);
return
VLC_EGENERIC
;
}
}
...
...
@@ -502,7 +480,7 @@ static int Open( vlc_object_t *p_this )
{
if
(
strcmp
(
p_demux
->
psz_access
,
"v4l2"
)
)
{
Close
(
p_this
);
Demux
Close
(
p_this
);
return
VLC_EGENERIC
;
}
}
...
...
@@ -517,9 +495,9 @@ static int Open( vlc_object_t *p_this )
}
msg_Dbg
(
p_demux
,
"opening '%s' as video"
,
p_sys
->
psz_vdev
);
if
(
p_sys
->
psz_vdev
&&
*
p_sys
->
psz_vdev
&&
ProbeVideoDev
(
p_demux
,
p_sys
->
psz_vdev
)
)
if
(
p_sys
->
psz_vdev
&&
*
p_sys
->
psz_vdev
&&
ProbeVideoDev
(
(
vlc_object_t
*
)
p_demux
,
p_sys
,
p_sys
->
psz_vdev
)
)
{
p_sys
->
i_fd_video
=
OpenVideoDev
(
p_demux
,
p_sys
->
psz_vdev
);
p_sys
->
i_fd_video
=
OpenVideoDev
(
(
vlc_object_t
*
)
p_demux
,
p_sys
,
VLC_TRUE
);
}
}
...
...
@@ -541,7 +519,7 @@ static int Open( vlc_object_t *p_this )
if
(
p_sys
->
i_fd_video
<
0
&&
p_sys
->
i_fd_audio
<
0
)
{
Close
(
p_this
);
Demux
Close
(
p_this
);
return
VLC_EGENERIC
;
}
...
...
@@ -549,13 +527,63 @@ static int Open( vlc_object_t *p_this )
}
/*****************************************************************************
*
ParseMRL: parse the options contained in the MRL
*
GetV4L2Params: fill in p_sys parameters (shared by DemuxOpen and AccessOpen)
*****************************************************************************/
static
void
ParseMRL
(
demux_t
*
p_demux
)
void
GetV4L2Params
(
demux_sys_t
*
p_sys
,
vlc_object_t
*
p_obj
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
vlc_value_t
val
;
p_sys
->
i_video_pts
=
-
1
;
var_Create
(
p_obj
,
"v4l2-standard"
,
VLC_VAR_INTEGER
|
VLC_VAR_DOINHERIT
);
var_Get
(
p_obj
,
"v4l2-standard"
,
&
val
);
p_sys
->
i_selected_standard_id
=
i_standards_list
[
val
.
i_int
];
p_sys
->
i_selected_input
=
var_CreateGetInteger
(
p_obj
,
"v4l2-input"
);
p_sys
->
io
=
var_CreateGetInteger
(
p_obj
,
"v4l2-io"
);
p_sys
->
i_width
=
var_CreateGetInteger
(
p_obj
,
"v4l2-width"
);
p_sys
->
i_height
=
var_CreateGetInteger
(
p_obj
,
"v4l2-height"
);
var_CreateGetBool
(
p_obj
,
"v4l2-controls-reset"
);
var_Create
(
p_obj
,
"v4l2-fps"
,
VLC_VAR_FLOAT
|
VLC_VAR_DOINHERIT
);
var_Get
(
p_obj
,
"v4l2-fps"
,
&
val
);
p_sys
->
f_fps
=
val
.
f_float
;
var_Create
(
p_obj
,
"v4l2-samplerate"
,
VLC_VAR_INTEGER
|
VLC_VAR_DOINHERIT
);
var_Get
(
p_obj
,
"v4l2-samplerate"
,
&
val
);
p_sys
->
i_sample_rate
=
val
.
i_int
;
p_sys
->
psz_requested_chroma
=
var_CreateGetString
(
p_obj
,
"v4l2-chroma"
);
#ifdef HAVE_ALSA
var_Create
(
p_obj
,
"v4l2-alsa"
,
VLC_VAR_BOOL
|
VLC_VAR_DOINHERIT
);
var_Get
(
p_obj
,
"v4l2-alsa"
,
&
val
);
p_sys
->
b_use_alsa
=
val
.
b_bool
;
#endif
var_Create
(
p_obj
,
"v4l2-stereo"
,
VLC_VAR_BOOL
|
VLC_VAR_DOINHERIT
);
var_Get
(
p_obj
,
"v4l2-stereo"
,
&
val
);
p_sys
->
b_stereo
=
val
.
b_bool
;
p_sys
->
i_pts
=
var_CreateGetInteger
(
p_obj
,
"v4l2-caching"
);
char
*
psz_dup
=
strdup
(
p_demux
->
psz_path
);
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
;
p_sys
->
p_es_video
=
p_sys
->
p_es_audio
=
0
;
p_sys
->
p_block_audio
=
0
;
}
/*****************************************************************************
* ParseMRL: parse the options contained in the MRL
*****************************************************************************/
static
void
ParseMRL
(
demux_sys_t
*
p_sys
,
char
*
psz_path
,
vlc_object_t
*
p_obj
)
{
char
*
psz_dup
=
strdup
(
psz_path
);
char
*
psz_parser
=
psz_dup
;
while
(
*
psz_parser
&&
*
psz_parser
!=
':'
)
...
...
@@ -685,42 +713,42 @@ static void ParseMRL( demux_t *p_demux )
else
if
(
!
strncmp
(
psz_parser
,
"controls-reset"
,
strlen
(
"controls-reset"
)
)
)
{
var_SetBool
(
p_
demux
,
"v4l2-controls-reset"
,
VLC_TRUE
);
var_SetBool
(
p_
obj
,
"v4l2-controls-reset"
,
VLC_TRUE
);
psz_parser
+=
strlen
(
"controls-reset"
);
}
#if 0
else if( !strncmp( psz_parser, "brightness=",
strlen( "brightness=" ) ) )
{
var_SetInteger( p_
demux
, "brightness",
var_SetInteger( p_
obj
, "brightness",
strtol( psz_parser + strlen( "brightness=" ),
&psz_parser, 0 ) );
}
else if( !strncmp( psz_parser, "contrast=",
strlen( "contrast=" ) ) )
{
var_SetInteger( p_
demux
, "contrast",
var_SetInteger( p_
obj
, "contrast",
strtol( psz_parser + strlen( "contrast=" ),
&psz_parser, 0 ) );
}
else if( !strncmp( psz_parser, "saturation=",
strlen( "saturation=" ) ) )
{
var_SetInteger( p_
demux
, "saturation",
var_SetInteger( p_
obj
, "saturation",
strtol( psz_parser + strlen( "saturation=" ),
&psz_parser, 0 ) );
}
else if( !strncmp( psz_parser, "hue=",
strlen( "hue=" ) ) )
{
var_SetInteger( p_
demux
, "hue",
var_SetInteger( p_
obj
, "hue",
strtol( psz_parser + strlen( "hue=" ),
&psz_parser, 0 ) );
}
else if( !strncmp( psz_parser, "gamma=",
strlen( "gamma=" ) ) )
{
var_SetInteger( p_
demux
, "gamma",
var_SetInteger( p_
obj
, "gamma",
strtol( psz_parser + strlen( "gamma=" ),
&psz_parser, 0 ) );
}
...
...
@@ -756,7 +784,7 @@ static void ParseMRL( demux_t *p_demux )
}
else
{
msg_Warn
(
p_
demux
,
"unknown option"
);
msg_Warn
(
p_
obj
,
"unknown option"
);
}
while
(
*
psz_parser
&&
*
psz_parser
!=
':'
)
...
...
@@ -782,14 +810,23 @@ static void ParseMRL( demux_t *p_demux )
/*****************************************************************************
* Close: close device, free resources
*****************************************************************************/
static
void
Close
(
vlc_object_t
*
p_this
)
static
void
AccessClose
(
vlc_object_t
*
p_this
)
{
access_t
*
p_access
=
(
access_t
*
)
p_this
;
demux_sys_t
*
p_sys
=
(
demux_sys_t
*
)
p_access
->
p_sys
;
CommonClose
(
p_this
,
p_sys
);
}
static
void
DemuxClose
(
vlc_object_t
*
p_this
)
{
demux_t
*
p_demux
=
(
demux_t
*
)
p_this
;
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
struct
v4l2_buffer
buf
;
enum
v4l2_buf_type
buf_type
;
unsigned
int
i
;
demux_t
*
p_demux
=
(
demux_t
*
)
p_this
;
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
/* Stop video capture */
if
(
p_sys
->
i_fd_video
>=
0
)
{
...
...
@@ -813,7 +850,7 @@ static void Close( vlc_object_t *p_this )
buf_type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
;
if
(
ioctl
(
p_sys
->
i_fd_video
,
VIDIOC_STREAMOFF
,
&
buf_type
)
<
0
)
{
msg_Err
(
p_
demux
,
"VIDIOC_STREAMOFF failed"
);
msg_Err
(
p_
this
,
"VIDIOC_STREAMOFF failed"
);
}
break
;
...
...
@@ -833,7 +870,7 @@ static void Close( vlc_object_t *p_this )
{
if
(
munmap
(
p_sys
->
p_buffers
[
i
].
start
,
p_sys
->
p_buffers
[
i
].
length
)
)
{
msg_Err
(
p_
demux
,
"munmap failed"
);
msg_Err
(
p_
this
,
"munmap failed"
);
}
}
break
;
...
...
@@ -848,6 +885,11 @@ static void Close( vlc_object_t *p_this )
free
(
p_sys
->
p_buffers
);
}
CommonClose
(
p_this
,
p_sys
);
}
static
void
CommonClose
(
vlc_object_t
*
p_this
,
demux_sys_t
*
p_sys
)
{
/* Close */
if
(
p_sys
->
i_fd_video
>=
0
)
close
(
p_sys
->
i_fd_video
);
#ifdef HAVE_ALSA
...
...
@@ -874,6 +916,99 @@ static void Close( vlc_object_t *p_this )
free
(
p_sys
);
}
/*****************************************************************************
* AccessOpen: opens v4l2 device, access2 callback
*****************************************************************************
*
* url: <video device>::::
*
*****************************************************************************/
static
int
AccessOpen
(
vlc_object_t
*
p_this
)
{
access_t
*
p_access
=
(
access_t
*
)
p_this
;
demux_sys_t
*
p_sys
;
/* Only when selected */
if
(
*
p_access
->
psz_access
==
'\0'
)
return
VLC_EGENERIC
;
p_access
->
pf_read
=
AccessRead
;
p_access
->
pf_block
=
NULL
;
p_access
->
pf_seek
=
NULL
;
p_access
->
pf_control
=
AccessControl
;
p_access
->
info
.
i_update
=
0
;
p_access
->
info
.
i_size
=
0
;
p_access
->
info
.
i_pos
=
0
;
p_access
->
info
.
b_eof
=
VLC_FALSE
;
p_access
->
info
.
i_title
=
0
;
p_access
->
info
.
i_seekpoint
=
0
;
p_sys
=
calloc
(
1
,
sizeof
(
demux_sys_t
)
);
p_access
->
p_sys
=
(
access_sys_t
*
)
p_sys
;
if
(
p_sys
==
NULL
)
return
VLC_ENOMEM
;
GetV4L2Params
(
p_sys
,
(
vlc_object_t
*
)
p_access
);
ParseMRL
(
p_sys
,
p_access
->
psz_path
,
(
vlc_object_t
*
)
p_access
);
/* Find main device (video) */
if
(
p_sys
->
psz_device
&&
*
p_sys
->
psz_device
)
{
msg_Dbg
(
p_access
,
"main device='%s'"
,
p_sys
->
psz_device
);
/* Try to open as video device */
msg_Dbg
(
p_access
,
"trying device '%s' as video"
,
p_sys
->
psz_device
);
if
(
ProbeVideoDev
(
(
vlc_object_t
*
)
p_access
,
p_sys
,
p_sys
->
psz_device
)
)
{
msg_Dbg
(
p_access
,
"'%s' is a video device"
,
p_sys
->
psz_device
);
/* Device was a video device */
if
(
p_sys
->
psz_vdev
)
free
(
p_sys
->
psz_vdev
);
p_sys
->
psz_vdev
=
p_sys
->
psz_device
;
p_sys
->
psz_device
=
NULL
;
p_sys
->
i_fd_video
=
OpenVideoDev
(
(
vlc_object_t
*
)
p_access
,
p_sys
,
VLC_FALSE
);
if
(
p_sys
->
i_fd_video
<
0
)
{
AccessClose
(
p_this
);
return
VLC_EGENERIC
;
}
}
}
/* If no device opened, only continue if the access was forced */
if
(
p_sys
->
i_fd_video
<
0
)
{
if
(
strcmp
(
p_access
->
psz_access
,
"v4l2"
)
)
{
AccessClose
(
p_this
);
return
VLC_EGENERIC
;
}
}
/* Find video device */
if
(
p_sys
->
i_fd_video
<
0
)
{
if
(
!
p_sys
->
psz_vdev
||
!*
p_sys
->
psz_vdev
)
{
if
(
p_sys
->
psz_vdev
)
free
(
p_sys
->
psz_vdev
);
p_sys
->
psz_vdev
=
var_CreateGetString
(
p_access
,
"v4l2-dev"
);
}
msg_Dbg
(
p_access
,
"opening '%s' as video"
,
p_sys
->
psz_vdev
);
if
(
p_sys
->
psz_vdev
&&
*
p_sys
->
psz_vdev
&&
ProbeVideoDev
(
(
vlc_object_t
*
)
p_access
,
p_sys
,
p_sys
->
psz_vdev
)
)
{
p_sys
->
i_fd_video
=
OpenVideoDev
(
(
vlc_object_t
*
)
p_access
,
p_sys
,
VLC_FALSE
);
}
}
if
(
p_sys
->
i_fd_video
<
0
)
{
AccessClose
(
p_this
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
/*****************************************************************************
* DemuxControl:
*****************************************************************************/
...
...
@@ -911,6 +1046,108 @@ static int DemuxControl( demux_t *p_demux, int i_query, va_list args )
return
VLC_EGENERIC
;
}
/*****************************************************************************
* AccessControl: access2 callback
*****************************************************************************/
static
int
AccessControl
(
access_t
*
p_access
,
int
i_query
,
va_list
args
)
{
vlc_bool_t
*
pb_bool
;
int
*
pi_int
;
int64_t
*
pi_64
;
demux_sys_t
*
p_sys
=
(
demux_sys_t
*
)
p_access
->
p_sys
;
switch
(
i_query
)
{
/* */
case
ACCESS_CAN_SEEK
:
case
ACCESS_CAN_FASTSEEK
:
pb_bool
=
(
vlc_bool_t
*
)
va_arg
(
args
,
vlc_bool_t
*
);
*
pb_bool
=
VLC_FALSE
;
break
;
case
ACCESS_CAN_PAUSE
:
pb_bool
=
(
vlc_bool_t
*
)
va_arg
(
args
,
vlc_bool_t
*
);
*
pb_bool
=
VLC_FALSE
;
break
;
case
ACCESS_CAN_CONTROL_PACE
:
pb_bool
=
(
vlc_bool_t
*
)
va_arg
(
args
,
vlc_bool_t
*
);
*
pb_bool
=
VLC_FALSE
;
break
;
/* */
case
ACCESS_GET_MTU
:
pi_int
=
(
int
*
)
va_arg
(
args
,
int
*
);
*
pi_int
=
0
;
break
;
case
ACCESS_GET_PTS_DELAY
:
pi_64
=
(
int64_t
*
)
va_arg
(
args
,
int64_t
*
);
*
pi_64
=
(
int64_t
)
p_sys
->
i_pts
*
1000
;
break
;
/* */
case
ACCESS_SET_PAUSE_STATE
:
/* Nothing to do */
break
;
case
ACCESS_GET_TITLE_INFO
:
case
ACCESS_SET_TITLE
:
case
ACCESS_SET_SEEKPOINT
:
case
ACCESS_SET_PRIVATE_ID_STATE
:
case
ACCESS_GET_CONTENT_TYPE
:
case
ACCESS_GET_META
:
return
VLC_EGENERIC
;
default:
msg_Warn
(
p_access
,
"Unimplemented query in control(%d)."
,
i_query
);
return
VLC_EGENERIC
;
}
return
VLC_SUCCESS
;
}
/*****************************************************************************
* AccessRead: access2 callback
******************************************************************************/
static
ssize_t
AccessRead
(
access_t
*
p_access
,
uint8_t
*
p_buffer
,
size_t
i_len
)
{
demux_sys_t
*
p_sys
=
(
demux_sys_t
*
)
p_access
->
p_sys
;
struct
pollfd
ufd
;
int
i_ret
;
ufd
.
fd
=
p_sys
->
i_fd_video
;
ufd
.
events
=
POLLIN
;
if
(
p_access
->
info
.
b_eof
)
return
0
;
do
{
if
(
p_access
->
b_die
)
return
0
;
ufd
.
revents
=
0
;
}
while
(
(
i_ret
=
poll
(
&
ufd
,
1
,
500
)
)
==
0
);
if
(
i_ret
<
0
)
{
msg_Err
(
p_access
,
"Polling error (%m)."
);
return
-
1
;
}
i_ret
=
read
(
p_sys
->
i_fd_video
,
p_buffer
,
i_len
);
if
(
i_ret
==
0
)
{
p_access
->
info
.
b_eof
=
VLC_TRUE
;
}
else
if
(
i_ret
>
0
)
{
p_access
->
info
.
i_pos
+=
i_ret
;
}
return
i_ret
;
}
/*****************************************************************************
* Demux: Processes the audio or video frame
*****************************************************************************/
...
...
@@ -1379,19 +1616,19 @@ vlc_bool_t IsPixelFormatSupported( demux_t *p_demux, unsigned int i_pixelformat
/*****************************************************************************
* OpenVideoDev: open and set up the video device and probe for capabilities
*****************************************************************************/
int
OpenVideoDev
(
demux_t
*
p_demux
,
char
*
psz_device
)
int
OpenVideoDev
(
vlc_object_t
*
p_obj
,
demux_sys_t
*
p_sys
,
vlc_bool_t
b_demux
)
{
int
i_fd
;
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
struct
v4l2_cropcap
cropcap
;
struct
v4l2_crop
crop
;
struct
v4l2_format
fmt
;
unsigned
int
i_min
;
enum
v4l2_buf_type
buf_type
;
char
*
psz_device
=
p_sys
->
psz_vdev
;
if
(
(
i_fd
=
open
(
psz_device
,
O_RDWR
)
)
<
0
)
{
msg_Err
(
p_
demux
,
"cannot open device (%m)"
);
msg_Err
(
p_
obj
,
"cannot open device (%m)"
);
goto
open_failed
;
}
...
...
@@ -1401,26 +1638,38 @@ int OpenVideoDev( demux_t *p_demux, char *psz_device )
{
if
(
ioctl
(
i_fd
,
VIDIOC_S_STD
,
&
p_sys
->
i_selected_standard_id
)
<
0
)
{
msg_Err
(
p_
demux
,
"cannot set standard (%m)"
);
msg_Err
(
p_
obj
,
"cannot set standard (%m)"
);
goto
open_failed
;
}
msg_Dbg
(
p_
demux
,
"Set standard"
);
msg_Dbg
(
p_
obj
,
"Set standard"
);
}
/* Select input */
if
(
p_sys
->
i_selected_input
>
p_sys
->
i_input
)
{
msg_Warn
(
p_
demux
,
"invalid input. Using the default one"
);
msg_Warn
(
p_
obj
,
"invalid input. Using the default one"
);
p_sys
->
i_selected_input
=
0
;
}
if
(
ioctl
(
i_fd
,
VIDIOC_S_INPUT
,
&
p_sys
->
i_selected_input
)
<
0
)
{
msg_Err
(
p_
demux
,
"cannot set input (%m)"
);
msg_Err
(
p_
obj
,
"cannot set input (%m)"
);
goto
open_failed
;
}
/* TODO: Move the resolution stuff up here */
/* if MPEG encoder card, no need to do anything else after this */
if
(
VLC_FALSE
==
b_demux
)
{
ControlList
(
p_obj
,
i_fd
,
var_GetBool
(
p_obj
,
"v4l2-controls-reset"
),
b_demux
);
return
i_fd
;
}
demux_t
*
p_demux
=
(
demux_t
*
)
p_obj
;
/* Verify device support for the various IO methods */
switch
(
p_sys
->
io
)
{
...
...
@@ -1524,6 +1773,7 @@ int OpenVideoDev( demux_t *p_demux, char *psz_device )
}
/* If no user specified chroma, find best */
/* This also decides if MPEG encoder card or not */
if
(
!
fmt
.
fmt
.
pix
.
pixelformat
)
{
fmt
.
fmt
.
pix
.
pixelformat
=
V4L2_PIX_FMT_YVU420
;
...
...
@@ -1535,7 +1785,7 @@ int OpenVideoDev( demux_t *p_demux, char *psz_device )
fmt
.
fmt
.
pix
.
pixelformat
=
V4L2_PIX_FMT_YUYV
;
if
(
!
IsPixelFormatSupported
(
p_demux
,
fmt
.
fmt
.
pix
.
pixelformat
)
||
ioctl
(
i_fd
,
VIDIOC_S_FMT
,
&
fmt
)
<
0
)
{
msg_
Err
(
p_demux
,
"Could not select any of the default chromas!
"
);
msg_
Warn
(
p_demux
,
"Could not select any of the default chromas; attempting to open as MPEG encoder card (access2)
"
);
goto
open_failed
;
}
}
...
...
@@ -1612,9 +1862,6 @@ int OpenVideoDev( demux_t *p_demux, char *psz_device )
}
#endif
ControlList
(
p_demux
,
i_fd
,
var_GetBool
(
p_demux
,
"v4l2-controls-reset"
)
);
/* Init IO method */
switch
(
p_sys
->
io
)
{
...
...
@@ -2000,17 +2247,16 @@ int OpenAudioDev( demux_t *p_demux, char *psz_device )
/*****************************************************************************
* ProbeVideoDev: probe video for capabilities
*****************************************************************************/
vlc_bool_t
ProbeVideoDev
(
demux_t
*
p_demux
,
char
*
psz_device
)
vlc_bool_t
ProbeVideoDev
(
vlc_object_t
*
p_obj
,
demux_sys_t
*
p_sys
,
char
*
psz_device
)
{
int
i_index
;
int
i_standard
;
int
i_fd
;
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
if
(
(
i_fd
=
open
(
psz_device
,
O_RDWR
)
)
<
0
)
{
msg_Err
(
p_
demux
,
"cannot open video device (%m)"
);
msg_Err
(
p_
obj
,
"cannot open video device (%m)"
);
goto
open_failed
;
}
...
...
@@ -2018,11 +2264,11 @@ vlc_bool_t ProbeVideoDev( demux_t *p_demux, char *psz_device )
if
(
ioctl
(
i_fd
,
VIDIOC_QUERYCAP
,
&
p_sys
->
dev_cap
)
<
0
)
{
msg_Err
(
p_
demux
,
"cannot get video capabilities (%m)"
);
msg_Err
(
p_
obj
,
"cannot get video capabilities (%m)"
);
goto
open_failed
;
}
msg_Dbg
(
p_
demux
,
"V4L2 device: %s using driver: %s (version: %u.%u.%u) on %s"
,
msg_Dbg
(
p_
obj
,
"V4L2 device: %s using driver: %s (version: %u.%u.%u) on %s"
,
p_sys
->
dev_cap
.
card
,
p_sys
->
dev_cap
.
driver
,
(
p_sys
->
dev_cap
.
version
>>
16
)
&
0xFF
,
...
...
@@ -2030,14 +2276,14 @@ vlc_bool_t ProbeVideoDev( demux_t *p_demux, char *psz_device )
p_sys
->
dev_cap
.
version
&
0xFF
,
p_sys
->
dev_cap
.
bus_info
);
msg_Dbg
(
p_
demux
,
"the device has the capabilities: (%c) Video Capure, "
msg_Dbg
(
p_
obj
,
"the device has the capabilities: (%c) Video Capure, "
"(%c) Audio, "
"(%c) Tuner"
,
(
p_sys
->
dev_cap
.
capabilities
&
V4L2_CAP_VIDEO_CAPTURE
?
'X'
:
' '
),
(
p_sys
->
dev_cap
.
capabilities
&
V4L2_CAP_AUDIO
?
'X'
:
' '
),
(
p_sys
->
dev_cap
.
capabilities
&
V4L2_CAP_TUNER
?
'X'
:
' '
)
);
msg_Dbg
(
p_
demux
,
"supported I/O methods are: (%c) Read/Write, "
msg_Dbg
(
p_
obj
,
"supported I/O methods are: (%c) Read/Write, "
"(%c) Streaming, "
"(%c) Asynchronous"
,
(
p_sys
->
dev_cap
.
capabilities
&
V4L2_CAP_READWRITE
?
'X'
:
' '
),
...
...
@@ -2067,10 +2313,10 @@ vlc_bool_t ProbeVideoDev( demux_t *p_demux, char *psz_device )
if
(
ioctl
(
i_fd
,
VIDIOC_ENUMINPUT
,
&
p_sys
->
p_inputs
[
i_index
]
)
)
{
msg_Err
(
p_
demux
,
"cannot get video input characteristics (%m)"
);
msg_Err
(
p_
obj
,
"cannot get video input characteristics (%m)"
);
goto
open_failed
;
}
msg_Dbg
(
p_
demux
,
"video input %i (%s) has type: %s"
,
msg_Dbg
(
p_
obj
,
"video input %i (%s) has type: %s"
,
i_index
,
p_sys
->
p_inputs
[
i_index
].
name
,
p_sys
->
p_inputs
[
i_index
].
type
...
...
@@ -2100,10 +2346,10 @@ vlc_bool_t ProbeVideoDev( demux_t *p_demux, char *psz_device )
if
(
ioctl
(
i_fd
,
VIDIOC_ENUMSTD
,
&
p_sys
->
p_standards
[
i_standard
]
)
)
{
msg_Err
(
p_
demux
,
"cannot get video input standards (%m)"
);
msg_Err
(
p_
obj
,
"cannot get video input standards (%m)"
);
goto
open_failed
;
}
msg_Dbg
(
p_
demux
,
"video standard %i is: %s"
,
msg_Dbg
(
p_
obj
,
"video standard %i is: %s"
,
i_standard
,
p_sys
->
p_standards
[
i_standard
].
name
);
}
...
...
@@ -2123,11 +2369,11 @@ vlc_bool_t ProbeVideoDev( demux_t *p_demux, char *psz_device )
{
if
(
ioctl
(
i_fd
,
VIDIOC_G_AUDIO
,
&
p_sys
->
p_audios
[
p_sys
->
i_audio
]
)
<
0
)
{
msg_Err
(
p_
demux
,
"cannot get audio input characteristics (%m)"
);
msg_Err
(
p_
obj
,
"cannot get audio input characteristics (%m)"
);
goto
open_failed
;
}
msg_Dbg
(
p_
demux
,
"audio device %i (%s) is %s"
,
msg_Dbg
(
p_
obj
,
"audio device %i (%s) is %s"
,
p_sys
->
i_audio
,
p_sys
->
p_audios
[
p_sys
->
i_audio
].
name
,
p_sys
->
p_audios
[
p_sys
->
i_audio
].
capability
&
...
...
@@ -2159,10 +2405,10 @@ vlc_bool_t ProbeVideoDev( demux_t *p_demux, char *psz_device )
if
(
ioctl
(
i_fd
,
VIDIOC_G_TUNER
,
&
p_sys
->
p_tuners
[
i_index
]
)
)
{
msg_Err
(
p_
demux
,
"cannot get tuner characteristics (%m)"
);
msg_Err
(
p_
obj
,
"cannot get tuner characteristics (%m)"
);
goto
open_failed
;
}
msg_Dbg
(
p_
demux
,
"tuner %i (%s) has type: %s, "
msg_Dbg
(
p_
obj
,
"tuner %i (%s) has type: %s, "
"frequency range: %.1f %s -> %.1f %s"
,
i_index
,
p_sys
->
p_tuners
[
i_index
].
name
,
...
...
@@ -2207,7 +2453,7 @@ vlc_bool_t ProbeVideoDev( demux_t *p_demux, char *psz_device )
if
(
ioctl
(
i_fd
,
VIDIOC_ENUM_FMT
,
&
p_sys
->
p_codecs
[
i_index
]
)
<
0
)
{
msg_Err
(
p_
demux
,
"cannot get codec description (%m)"
);
msg_Err
(
p_
obj
,
"cannot get codec description (%m)"
);
goto
open_failed
;
}
...
...
@@ -2222,7 +2468,7 @@ vlc_bool_t ProbeVideoDev( demux_t *p_demux, char *psz_device )
char
sz_fourcc
[
5
];
memset
(
&
sz_fourcc
,
0
,
sizeof
(
sz_fourcc
)
);
vlc_fourcc_to_char
(
v4l2chroma_to_fourcc
[
i
].
i_fourcc
,
&
sz_fourcc
);
msg_Dbg
(
p_
demux
,
"device supports chroma %4s [%s]"
,
msg_Dbg
(
p_
obj
,
"device supports chroma %4s [%s]"
,
sz_fourcc
,
p_sys
->
p_codecs
[
i_index
].
description
);
...
...
@@ -2235,7 +2481,7 @@ vlc_bool_t ProbeVideoDev( demux_t *p_demux, char *psz_device )
if
(
ioctl
(
i_fd
,
VIDIOC_ENUM_FRAMESIZES
,
&
frmsize
)
<
0
)
{
/* Not all devices support this ioctl */
msg_Warn
(
p_
demux
,
"Unable to query for frame sizes"
);
msg_Warn
(
p_
obj
,
"Unable to query for frame sizes"
);
}
else
{
...
...
@@ -2244,21 +2490,21 @@ vlc_bool_t ProbeVideoDev( demux_t *p_demux, char *psz_device )
case
V4L2_FRMSIZE_TYPE_DISCRETE
:
do
{
msg_Dbg
(
p_
demux
,
msg_Dbg
(
p_
obj
,
" device supports size %dx%d"
,
frmsize
.
discrete
.
width
,
frmsize
.
discrete
.
height
);
frmsize
.
index
++
;
}
while
(
ioctl
(
i_fd
,
VIDIOC_ENUM_FRAMESIZES
,
&
frmsize
)
>=
0
);
break
;
case
V4L2_FRMSIZE_TYPE_STEPWISE
:
msg_Dbg
(
p_
demux
,
msg_Dbg
(
p_
obj
,
" device supports sizes %dx%d to %dx%d using %dx%d increments"
,
frmsize
.
stepwise
.
min_width
,
frmsize
.
stepwise
.
min_height
,
frmsize
.
stepwise
.
max_width
,
frmsize
.
stepwise
.
max_height
,
frmsize
.
stepwise
.
step_width
,
frmsize
.
stepwise
.
step_height
);
break
;
case
V4L2_FRMSIZE_TYPE_CONTINUOUS
:
msg_Dbg
(
p_
demux
,
msg_Dbg
(
p_
obj
,
" device supports all sizes %dx%d to %dx%d"
,
frmsize
.
stepwise
.
min_width
,
frmsize
.
stepwise
.
min_height
,
frmsize
.
stepwise
.
max_width
,
frmsize
.
stepwise
.
max_height
);
...
...
@@ -2270,7 +2516,7 @@ vlc_bool_t ProbeVideoDev( demux_t *p_demux, char *psz_device )
}
if
(
!
b_codec_supported
)
{
msg_Dbg
(
p_
demux
,
"device codec %s not supported
"
,
msg_Dbg
(
p_
obj
,
"device codec %s not supported as access_demux
"
,
p_sys
->
p_codecs
[
i_index
].
description
);
}
...
...
@@ -2350,9 +2596,9 @@ open_failed:
* Print a user-class v4l2 control's details, create the relevant variable,
* change the value if needed.
*****************************************************************************/
static
void
ControlListPrint
(
demux_t
*
p_demux
,
int
i_fd
,
static
void
ControlListPrint
(
vlc_object_t
*
p_obj
,
int
i_fd
,
struct
v4l2_queryctrl
queryctrl
,
vlc_bool_t
b_reset
)
vlc_bool_t
b_reset
,
vlc_bool_t
b_demux
)
{
struct
v4l2_querymenu
querymenu
;
unsigned
int
i_mid
;
...
...
@@ -2364,9 +2610,9 @@ static void ControlListPrint( demux_t *p_demux, int i_fd,
vlc_value_t
val
,
val2
;
if
(
queryctrl
.
flags
&
V4L2_CTRL_FLAG_GRABBED
)
msg_Dbg
(
p_
demux
,
" control is busy"
);
msg_Dbg
(
p_
obj
,
" control is busy"
);
if
(
queryctrl
.
flags
&
V4L2_CTRL_FLAG_READ_ONLY
)
msg_Dbg
(
p_
demux
,
" control is read-only"
);
msg_Dbg
(
p_
obj
,
" control is read-only"
);
for
(
i
=
0
;
controls
[
i
].
psz_name
!=
NULL
;
i
++
)
if
(
controls
[
i
].
i_cid
==
queryctrl
.
id
)
break
;
...
...
@@ -2376,8 +2622,8 @@ static void ControlListPrint( demux_t *p_demux, int i_fd,
psz_name
=
strdup
(
controls
[
i
].
psz_name
);
char
psz_cfg_name
[
40
];
sprintf
(
psz_cfg_name
,
CFG_PREFIX
"%s"
,
psz_name
);
i_val
=
var_CreateGetInteger
(
p_
demux
,
psz_cfg_name
);
var_Destroy
(
p_
demux
,
psz_cfg_name
);
i_val
=
var_CreateGetInteger
(
p_
obj
,
psz_cfg_name
);
var_Destroy
(
p_
obj
,
psz_cfg_name
);
}
else
{
...
...
@@ -2393,30 +2639,30 @@ static void ControlListPrint( demux_t *p_demux, int i_fd,
switch
(
queryctrl
.
type
)
{
case
V4L2_CTRL_TYPE_INTEGER
:
msg_Dbg
(
p_
demux
,
" integer control"
);
msg_Dbg
(
p_
demux
,
msg_Dbg
(
p_
obj
,
" integer control"
);
msg_Dbg
(
p_
obj
,
" valid values: %d to %d by steps of %d"
,
queryctrl
.
minimum
,
queryctrl
.
maximum
,
queryctrl
.
step
);
var_Create
(
p_
demux
,
psz_name
,
var_Create
(
p_
obj
,
psz_name
,
VLC_VAR_INTEGER
|
VLC_VAR_HASMIN
|
VLC_VAR_HASMAX
|
VLC_VAR_HASSTEP
|
VLC_VAR_ISCOMMAND
);
val
.
i_int
=
queryctrl
.
minimum
;
var_Change
(
p_
demux
,
psz_name
,
VLC_VAR_SETMIN
,
&
val
,
NULL
);
var_Change
(
p_
obj
,
psz_name
,
VLC_VAR_SETMIN
,
&
val
,
NULL
);
val
.
i_int
=
queryctrl
.
maximum
;
var_Change
(
p_
demux
,
psz_name
,
VLC_VAR_SETMAX
,
&
val
,
NULL
);
var_Change
(
p_
obj
,
psz_name
,
VLC_VAR_SETMAX
,
&
val
,
NULL
);
val
.
i_int
=
queryctrl
.
step
;
var_Change
(
p_
demux
,
psz_name
,
VLC_VAR_SETSTEP
,
&
val
,
NULL
);
var_Change
(
p_
obj
,
psz_name
,
VLC_VAR_SETSTEP
,
&
val
,
NULL
);
break
;
case
V4L2_CTRL_TYPE_BOOLEAN
:
msg_Dbg
(
p_
demux
,
" boolean control"
);
var_Create
(
p_
demux
,
psz_name
,
msg_Dbg
(
p_
obj
,
" boolean control"
);
var_Create
(
p_
obj
,
psz_name
,
VLC_VAR_BOOL
|
VLC_VAR_ISCOMMAND
);
break
;
case
V4L2_CTRL_TYPE_MENU
:
msg_Dbg
(
p_
demux
,
" menu control"
);
var_Create
(
p_
demux
,
psz_name
,
msg_Dbg
(
p_
obj
,
" menu control"
);
var_Create
(
p_
obj
,
psz_name
,
VLC_VAR_INTEGER
|
VLC_VAR_HASCHOICE
|
VLC_VAR_ISCOMMAND
);
memset
(
&
querymenu
,
0
,
sizeof
(
querymenu
)
);
...
...
@@ -2428,22 +2674,22 @@ static void ControlListPrint( demux_t *p_demux, int i_fd,
querymenu
.
id
=
queryctrl
.
id
;
if
(
ioctl
(
i_fd
,
VIDIOC_QUERYMENU
,
&
querymenu
)
>=
0
)
{
msg_Dbg
(
p_
demux
,
" %d: %s"
,
msg_Dbg
(
p_
obj
,
" %d: %s"
,
querymenu
.
index
,
querymenu
.
name
);
val
.
i_int
=
querymenu
.
index
;
val2
.
psz_string
=
(
char
*
)
querymenu
.
name
;
var_Change
(
p_
demux
,
psz_name
,
var_Change
(
p_
obj
,
psz_name
,
VLC_VAR_ADDCHOICE
,
&
val
,
&
val2
);
}
}
break
;
case
V4L2_CTRL_TYPE_BUTTON
:
msg_Dbg
(
p_
demux
,
" button control"
);
var_Create
(
p_
demux
,
psz_name
,
msg_Dbg
(
p_
obj
,
" button control"
);
var_Create
(
p_
obj
,
psz_name
,
VLC_VAR_VOID
|
VLC_VAR_ISCOMMAND
);
break
;
default:
msg_Dbg
(
p_
demux
,
" unknown control type (FIXME)"
);
msg_Dbg
(
p_
obj
,
" unknown control type (FIXME)"
);
/* FIXME */
break
;
}
...
...
@@ -2455,27 +2701,27 @@ static void ControlListPrint( demux_t *p_demux, int i_fd,
case
V4L2_CTRL_TYPE_MENU
:
{
struct
v4l2_control
control
;
msg_Dbg
(
p_
demux
,
" default value: %d"
,
msg_Dbg
(
p_
obj
,
" default value: %d"
,
queryctrl
.
default_value
);
memset
(
&
control
,
0
,
sizeof
(
control
)
);
control
.
id
=
queryctrl
.
id
;
if
(
ioctl
(
i_fd
,
VIDIOC_G_CTRL
,
&
control
)
>=
0
)
{
msg_Dbg
(
p_
demux
,
" current value: %d"
,
control
.
value
);
msg_Dbg
(
p_
obj
,
" current value: %d"
,
control
.
value
);
}
if
(
i_val
==
-
1
)
{
i_val
=
control
.
value
;
if
(
b_reset
&&
queryctrl
.
default_value
!=
control
.
value
)
{
msg_Dbg
(
p_
demux
,
" reset value to default"
);
Control
(
p_
demux
,
i_fd
,
psz_name
,
msg_Dbg
(
p_
obj
,
" reset value to default"
);
Control
(
p_
obj
,
i_fd
,
psz_name
,
queryctrl
.
id
,
queryctrl
.
default_value
);
}
}
else
{
Control
(
p_
demux
,
i_fd
,
psz_name
,
Control
(
p_
obj
,
i_fd
,
psz_name
,
queryctrl
.
id
,
i_val
);
}
}
...
...
@@ -2485,29 +2731,33 @@ static void ControlListPrint( demux_t *p_demux, int i_fd,
}
val
.
psz_string
=
(
char
*
)
queryctrl
.
name
;
var_Change
(
p_
demux
,
psz_name
,
VLC_VAR_SETTEXT
,
&
val
,
NULL
);
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_
demux
,
"controls"
,
VLC_VAR_ADDCHOICE
,
&
val
,
&
val2
);
var_Change
(
p_
obj
,
"controls"
,
VLC_VAR_ADDCHOICE
,
&
val
,
&
val2
);
switch
(
var_Type
(
p_
demux
,
psz_name
)
&
VLC_VAR_TYPE
)
switch
(
var_Type
(
p_
obj
,
psz_name
)
&
VLC_VAR_TYPE
)
{
case
VLC_VAR_BOOL
:
var_SetBool
(
p_
demux
,
psz_name
,
i_val
);
var_SetBool
(
p_
obj
,
psz_name
,
i_val
);
break
;
case
VLC_VAR_INTEGER
:
var_SetInteger
(
p_
demux
,
psz_name
,
i_val
);
var_SetInteger
(
p_
obj
,
psz_name
,
i_val
);
break
;
case
VLC_VAR_VOID
:
break
;
default:
msg_Warn
(
p_
demux
,
"FIXME: %s %s %d"
,
__FILE__
,
__func__
,
msg_Warn
(
p_
obj
,
"FIXME: %s %s %d"
,
__FILE__
,
__func__
,
__LINE__
);
break
;
}
var_AddCallback
(
p_demux
,
psz_name
,
ControlCallback
,
(
void
*
)
queryctrl
.
id
);
if
(
b_demux
)
var_AddCallback
(
p_obj
,
psz_name
,
DemuxControlCallback
,
(
void
*
)
queryctrl
.
id
);
else
var_AddCallback
(
p_obj
,
psz_name
,
AccessControlCallback
,
(
void
*
)
queryctrl
.
id
);
free
(
psz_name
);
}
...
...
@@ -2516,7 +2766,7 @@ static void ControlListPrint( demux_t *p_demux, int i_fd,
* List all user-class v4l2 controls, set them to the user specified
* value and create the relevant variables to enable runtime changes
*****************************************************************************/
static
int
ControlList
(
demux_t
*
p_demux
,
int
i_fd
,
vlc_bool_t
b_reset
)
static
int
ControlList
(
vlc_object_t
*
p_obj
,
int
i_fd
,
vlc_bool_t
b_reset
,
vlc_bool_t
b_demux
)
{
struct
v4l2_queryctrl
queryctrl
;
int
i_cid
;
...
...
@@ -2526,19 +2776,22 @@ static int ControlList( demux_t *p_demux, int i_fd, vlc_bool_t b_reset )
/* 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 */
var_Create
(
p_
demux
,
"controls"
,
VLC_VAR_INTEGER
|
VLC_VAR_HASCHOICE
);
var_Create
(
p_
obj
,
"controls"
,
VLC_VAR_INTEGER
|
VLC_VAR_HASCHOICE
);
var_Create
(
p_
demux
,
"controls-update"
,
VLC_VAR_VOID
|
VLC_VAR_ISCOMMAND
);
var_Create
(
p_
obj
,
"controls-update"
,
VLC_VAR_VOID
|
VLC_VAR_ISCOMMAND
);
/* Add a control to reset all controls to their default values */
vlc_value_t
val
,
val2
;
var_Create
(
p_
demux
,
"controls-reset"
,
VLC_VAR_VOID
|
VLC_VAR_ISCOMMAND
);
var_Create
(
p_
obj
,
"controls-reset"
,
VLC_VAR_VOID
|
VLC_VAR_ISCOMMAND
);
val
.
psz_string
=
_
(
"Reset controls to default"
);
var_Change
(
p_
demux
,
"controls-reset"
,
VLC_VAR_SETTEXT
,
&
val
,
NULL
);
var_Change
(
p_
obj
,
"controls-reset"
,
VLC_VAR_SETTEXT
,
&
val
,
NULL
);
val
.
i_int
=
-
1
;
val2
.
psz_string
=
(
char
*
)
"controls-reset"
;
var_Change
(
p_demux
,
"controls"
,
VLC_VAR_ADDCHOICE
,
&
val
,
&
val2
);
var_AddCallback
(
p_demux
,
"controls-reset"
,
ControlResetCallback
,
NULL
);
var_Change
(
p_obj
,
"controls"
,
VLC_VAR_ADDCHOICE
,
&
val
,
&
val2
);
if
(
b_demux
)
var_AddCallback
(
p_obj
,
"controls-reset"
,
DemuxControlResetCallback
,
NULL
);
else
var_AddCallback
(
p_obj
,
"controls-reset"
,
AccessControlResetCallback
,
NULL
);
/* List public controls */
for
(
i_cid
=
V4L2_CID_BASE
;
...
...
@@ -2550,9 +2803,9 @@ static int ControlList( demux_t *p_demux, int i_fd, vlc_bool_t b_reset )
{
if
(
queryctrl
.
flags
&
V4L2_CTRL_FLAG_DISABLED
)
continue
;
msg_Dbg
(
p_
demux
,
"Available control: %s (%x)"
,
msg_Dbg
(
p_
obj
,
"Available control: %s (%x)"
,
queryctrl
.
name
,
queryctrl
.
id
);
ControlListPrint
(
p_
demux
,
i_fd
,
queryctrl
,
b_reset
);
ControlListPrint
(
p_
obj
,
i_fd
,
queryctrl
,
b_reset
,
b_demux
);
}
}
...
...
@@ -2566,9 +2819,9 @@ static int ControlList( demux_t *p_demux, int i_fd, vlc_bool_t b_reset )
{
if
(
queryctrl
.
flags
&
V4L2_CTRL_FLAG_DISABLED
)
continue
;
msg_Dbg
(
p_
demux
,
"Available private control: %s (%x)"
,
msg_Dbg
(
p_
obj
,
"Available private control: %s (%x)"
,
queryctrl
.
name
,
queryctrl
.
id
);
ControlListPrint
(
p_
demux
,
i_fd
,
queryctrl
,
b_reset
);
ControlListPrint
(
p_
obj
,
i_fd
,
queryctrl
,
b_reset
,
b_demux
);
}
else
break
;
...
...
@@ -2579,7 +2832,7 @@ static int ControlList( demux_t *p_demux, int i_fd, vlc_bool_t b_reset )
/*****************************************************************************
* Reset all user-class v4l2 controls to their default value
*****************************************************************************/
static
int
ControlReset
(
demux_t
*
p_demux
,
int
i_fd
)
static
int
ControlReset
(
vlc_object_t
*
p_obj
,
int
i_fd
)
{
struct
v4l2_queryctrl
queryctrl
;
int
i_cid
;
...
...
@@ -2605,7 +2858,7 @@ static int ControlReset( demux_t *p_demux, int i_fd )
int
i
;
for
(
i
=
0
;
controls
[
i
].
psz_name
!=
NULL
;
i
++
)
if
(
controls
[
i
].
i_cid
==
queryctrl
.
id
)
break
;
Control
(
p_
demux
,
i_fd
,
Control
(
p_
obj
,
i_fd
,
controls
[
i
].
psz_name
?
controls
[
i
].
psz_name
:
(
const
char
*
)
queryctrl
.
name
,
queryctrl
.
id
,
queryctrl
.
default_value
);
...
...
@@ -2629,7 +2882,7 @@ static int ControlReset( demux_t *p_demux, int i_fd )
if
(
ioctl
(
i_fd
,
VIDIOC_G_CTRL
,
&
control
)
>=
0
&&
queryctrl
.
default_value
!=
control
.
value
)
{
Control
(
p_
demux
,
i_fd
,
(
const
char
*
)
queryctrl
.
name
,
Control
(
p_
obj
,
i_fd
,
(
const
char
*
)
queryctrl
.
name
,
queryctrl
.
id
,
queryctrl
.
default_value
);
}
}
...
...
@@ -2642,7 +2895,7 @@ static int ControlReset( demux_t *p_demux, int i_fd )
/*****************************************************************************
* Issue user-class v4l2 controls
*****************************************************************************/
static
int
Control
(
demux_t
*
p_demux
,
int
i_fd
,
static
int
Control
(
vlc_object_t
*
p_obj
,
int
i_fd
,
const
char
*
psz_name
,
int
i_cid
,
int
i_value
)
{
struct
v4l2_queryctrl
queryctrl
;
...
...
@@ -2658,7 +2911,7 @@ static int Control( demux_t *p_demux, int i_fd,
if
(
ioctl
(
i_fd
,
VIDIOC_QUERYCTRL
,
&
queryctrl
)
<
0
||
queryctrl
.
flags
&
V4L2_CTRL_FLAG_DISABLED
)
{
msg_Dbg
(
p_
demux
,
"%s (%x) control is not supported."
,
psz_name
,
msg_Dbg
(
p_
obj
,
"%s (%x) control is not supported."
,
psz_name
,
i_cid
);
return
VLC_EGENERIC
;
}
...
...
@@ -2671,7 +2924,7 @@ static int Control( demux_t *p_demux, int i_fd,
control
.
value
=
i_value
;
if
(
ioctl
(
i_fd
,
VIDIOC_S_CTRL
,
&
control
)
<
0
)
{
msg_Err
(
p_
demux
,
"unable to set %s to %d (%m)"
,
psz_name
,
msg_Err
(
p_
obj
,
"unable to set %s to %d (%m)"
,
psz_name
,
i_value
);
return
VLC_EGENERIC
;
}
...
...
@@ -2679,18 +2932,18 @@ static int Control( demux_t *p_demux, int i_fd,
if
(
ioctl
(
i_fd
,
VIDIOC_G_CTRL
,
&
control
)
>=
0
)
{
vlc_value_t
val
;
msg_Dbg
(
p_
demux
,
"video %s: %d"
,
psz_name
,
control
.
value
);
switch
(
var_Type
(
p_
demux
,
psz_name
)
&
VLC_VAR_TYPE
)
msg_Dbg
(
p_
obj
,
"video %s: %d"
,
psz_name
,
control
.
value
);
switch
(
var_Type
(
p_
obj
,
psz_name
)
&
VLC_VAR_TYPE
)
{
case
VLC_VAR_BOOL
:
val
.
b_bool
=
control
.
value
;
var_Change
(
p_
demux
,
psz_name
,
VLC_VAR_SETVALUE
,
&
val
,
NULL
);
var_SetVoid
(
p_
demux
,
"controls-update"
);
var_Change
(
p_
obj
,
psz_name
,
VLC_VAR_SETVALUE
,
&
val
,
NULL
);
var_SetVoid
(
p_
obj
,
"controls-update"
);
break
;
case
VLC_VAR_INTEGER
:
val
.
i_int
=
control
.
value
;
var_Change
(
p_
demux
,
psz_name
,
VLC_VAR_SETVALUE
,
&
val
,
NULL
);
var_SetVoid
(
p_
demux
,
"controls-update"
);
var_Change
(
p_
obj
,
psz_name
,
VLC_VAR_SETVALUE
,
&
val
,
NULL
);
var_SetVoid
(
p_
obj
,
"controls-update"
);
break
;
}
}
...
...
@@ -2700,7 +2953,7 @@ static int Control( demux_t *p_demux, int i_fd,
/*****************************************************************************
* On the fly change settings callback
*****************************************************************************/
static
int
ControlCallback
(
vlc_object_t
*
p_this
,
static
int
Demux
ControlCallback
(
vlc_object_t
*
p_this
,
const
char
*
psz_var
,
vlc_value_t
oldval
,
vlc_value_t
newval
,
void
*
p_data
)
{
...
...
@@ -2713,12 +2966,12 @@ static int ControlCallback( vlc_object_t *p_this,
if
(
i_fd
<
0
)
return
VLC_EGENERIC
;
Control
(
p_
demux
,
i_fd
,
psz_var
,
i_cid
,
newval
.
i_int
);
Control
(
p_
this
,
i_fd
,
psz_var
,
i_cid
,
newval
.
i_int
);
return
VLC_EGENERIC
;
}
static
int
ControlResetCallback
(
vlc_object_t
*
p_this
,
static
int
Demux
ControlResetCallback
(
vlc_object_t
*
p_this
,
const
char
*
psz_var
,
vlc_value_t
oldval
,
vlc_value_t
newval
,
void
*
p_data
)
{
...
...
@@ -2730,7 +2983,42 @@ static int ControlResetCallback( vlc_object_t *p_this,
if
(
i_fd
<
0
)
return
VLC_EGENERIC
;
ControlReset
(
p_demux
,
i_fd
);
ControlReset
(
p_this
,
i_fd
);
return
VLC_EGENERIC
;
}
static
int
AccessControlCallback
(
vlc_object_t
*
p_this
,
const
char
*
psz_var
,
vlc_value_t
oldval
,
vlc_value_t
newval
,
void
*
p_data
)
{
access_t
*
p_access
=
(
access_t
*
)
p_this
;
demux_sys_t
*
p_sys
=
(
demux_sys_t
*
)
p_access
->
p_sys
;
int
i_cid
=
(
int
)
p_data
;
int
i_fd
=
p_sys
->
i_fd_video
;
if
(
i_fd
<
0
)
return
VLC_EGENERIC
;
Control
(
p_this
,
i_fd
,
psz_var
,
i_cid
,
newval
.
i_int
);
return
VLC_EGENERIC
;
}
static
int
AccessControlResetCallback
(
vlc_object_t
*
p_this
,
const
char
*
psz_var
,
vlc_value_t
oldval
,
vlc_value_t
newval
,
void
*
p_data
)
{
access_t
*
p_access
=
(
access_t
*
)
p_this
;
demux_sys_t
*
p_sys
=
(
demux_sys_t
*
)
p_access
->
p_sys
;
int
i_fd
=
p_sys
->
i_fd_video
;
if
(
i_fd
<
0
)
return
VLC_EGENERIC
;
ControlReset
(
p_this
,
i_fd
);
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