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
fcab6ae6
Commit
fcab6ae6
authored
Mar 22, 2012
by
Rémi Denis-Courmont
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
v4l2: rework format selection into a single pass
parent
1a64a930
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
101 additions
and
172 deletions
+101
-172
modules/access/v4l2/demux.c
modules/access/v4l2/demux.c
+101
-171
modules/access/v4l2/v4l2.h
modules/access/v4l2/v4l2.h
+0
-1
No files found.
modules/access/v4l2/demux.c
View file @
fcab6ae6
...
@@ -85,6 +85,7 @@ int DemuxOpen( vlc_object_t *obj )
...
@@ -85,6 +85,7 @@ int DemuxOpen( vlc_object_t *obj )
}
}
sys
->
i_fd
=
fd
;
sys
->
i_fd
=
fd
;
sys
->
controls
=
ControlsInit
(
VLC_OBJECT
(
demux
),
fd
);
demux
->
pf_demux
=
Demux
;
demux
->
pf_demux
=
Demux
;
demux
->
pf_control
=
DemuxControl
;
demux
->
pf_control
=
DemuxControl
;
demux
->
info
.
i_update
=
0
;
demux
->
info
.
i_update
=
0
;
...
@@ -96,27 +97,16 @@ error:
...
@@ -96,27 +97,16 @@ error:
return
VLC_EGENERIC
;
return
VLC_EGENERIC
;
}
}
/**
typedef
struct
* \return true if the specified V4L2 pixel format is
* in the array of supported formats returned by the driver
*/
static
bool
IsPixelFormatSupported
(
struct
v4l2_fmtdesc
*
codecs
,
size_t
n
,
unsigned
int
i_pixelformat
)
{
{
for
(
size_t
i
=
0
;
i
<
n
;
i
++
)
uint32_t
v4l2
;
if
(
codecs
[
i
].
pixelformat
==
i_pixelformat
)
vlc_fourcc_t
vlc
;
return
true
;
uint32_t
red
;
return
false
;
uint32_t
green
;
}
uint32_t
blue
;
}
vlc_v4l2_fmt_t
;
static
const
struct
{
static
const
vlc_v4l2_fmt_t
v4l2_fmts
[]
=
unsigned
int
i_v4l2
;
vlc_fourcc_t
i_fourcc
;
int
i_rmask
;
int
i_gmask
;
int
i_bmask
;
}
v4l2chroma_to_fourcc
[]
=
{
{
/* Raw data types */
/* Raw data types */
{
V4L2_PIX_FMT_GREY
,
VLC_CODEC_GREY
,
0
,
0
,
0
},
{
V4L2_PIX_FMT_GREY
,
VLC_CODEC_GREY
,
0
,
0
,
0
},
...
@@ -152,9 +142,41 @@ static const struct
...
@@ -152,9 +142,41 @@ static const struct
{ V4L2_PIX_FMT_DV, VLC_FOURCC('?','?','?','?') },
{ V4L2_PIX_FMT_DV, VLC_FOURCC('?','?','?','?') },
{ V4L2_PIX_FMT_MPEG, VLC_FOURCC('?','?','?','?') },
{ V4L2_PIX_FMT_MPEG, VLC_FOURCC('?','?','?','?') },
#endif
#endif
{
0
,
0
,
0
,
0
,
0
}
};
};
static
const
vlc_v4l2_fmt_t
*
vlc_from_v4l2_fourcc
(
uint32_t
fourcc
)
{
for
(
size_t
i
=
0
;
i
<
sizeof
(
v4l2_fmts
)
/
sizeof
(
v4l2_fmts
[
0
]);
i
++
)
if
(
v4l2_fmts
[
i
].
v4l2
==
fourcc
)
return
v4l2_fmts
+
i
;
return
NULL
;
}
static
size_t
vlc_v4l2_fmt_rank
(
const
vlc_v4l2_fmt_t
*
fmt
)
{
if
(
fmt
==
NULL
)
return
SIZE_MAX
;
ptrdiff_t
d
=
fmt
-
v4l2_fmts
;
assert
(
d
>=
0
);
assert
(
d
<
(
ptrdiff_t
)(
sizeof
(
v4l2_fmts
)
/
sizeof
(
v4l2_fmts
[
0
])));
return
d
;
}
static
vlc_fourcc_t
var_InheritFourCC
(
vlc_object_t
*
obj
,
const
char
*
varname
)
{
char
*
str
=
var_InheritString
(
obj
,
varname
);
if
(
str
==
NULL
)
return
0
;
vlc_fourcc_t
fourcc
=
vlc_fourcc_GetCodecFromString
(
VIDEO_ES
,
str
);
if
(
fourcc
==
0
)
msg_Err
(
obj
,
"invalid codec %s"
,
str
);
free
(
str
);
return
fourcc
;
}
#define var_InheritFourCC(o, v) var_InheritFourCC(VLC_OBJECT(o), v)
/**
/**
* List of V4L2 chromas were confident enough to use as fallbacks if the
* List of V4L2 chromas were confident enough to use as fallbacks if the
* user hasn't provided a --v4l2-chroma value.
* user hasn't provided a --v4l2-chroma value.
...
@@ -214,162 +236,81 @@ static int InitVideo (demux_t *demux, int fd)
...
@@ -214,162 +236,81 @@ static int InitVideo (demux_t *demux, int fd)
if
(
SetupInput
(
VLC_OBJECT
(
demux
),
fd
))
if
(
SetupInput
(
VLC_OBJECT
(
demux
),
fd
))
return
-
1
;
return
-
1
;
/* Probe for available chromas */
/* Picture format negotiation */
struct
v4l2_fmtdesc
*
codecs
=
NULL
;
const
vlc_v4l2_fmt_t
*
selected
=
NULL
;
uint_fast32_t
ncodec
=
0
;
vlc_fourcc_t
reqfourcc
=
var_InheritFourCC
(
demux
,
CFG_PREFIX
"chroma"
);
if
(
cap
.
capabilities
&
V4L2_CAP_VIDEO_CAPTURE
)
bool
native
=
false
;
{
struct
v4l2_fmtdesc
codec
=
{
.
index
=
0
,
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
,
};
while
(
v4l2_ioctl
(
fd
,
VIDIOC_ENUM_FMT
,
&
codec
)
>=
0
)
codec
.
index
=
++
ncodec
;
codecs
=
malloc
(
ncodec
*
sizeof
(
*
codecs
));
if
(
unlikely
(
codecs
==
NULL
))
ncodec
=
0
;
for
(
uint_fast32_t
i
=
0
;
i
<
ncodec
;
i
++
)
for
(
struct
v4l2_fmtdesc
codec
=
{
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
};
{
v4l2_ioctl
(
fd
,
VIDIOC_ENUM_FMT
,
&
codec
)
>=
0
;
codecs
[
i
].
index
=
i
;
codec
.
index
++
)
codecs
[
i
].
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
;
{
/* Enumerate available chromas */
const
vlc_v4l2_fmt_t
*
dsc
=
vlc_from_v4l2_fourcc
(
codec
.
pixelformat
);
if
(
v4l2_ioctl
(
fd
,
VIDIOC_ENUM_FMT
,
&
codecs
[
i
])
<
0
)
msg_Dbg
(
demux
,
" %s %s format %4.4s (%4.4s): %s"
,
{
(
codec
.
flags
&
V4L2_FMT_FLAG_EMULATED
)
?
"emulates"
:
"supports"
,
msg_Err
(
demux
,
"cannot get codec description: %m"
);
(
codec
.
flags
&
V4L2_FMT_FLAG_COMPRESSED
)
?
"compressed"
:
"raw"
,
goto
error
;
(
char
*
)
&
codec
.
pixelformat
,
}
(
dsc
!=
NULL
)
?
(
const
char
*
)
&
dsc
->
vlc
:
"N.A."
,
codec
.
description
);
/* only print if vlc supports the format */
if
(
dsc
==
NULL
)
char
fourcc_v4l2
[
5
];
continue
;
/* ignore VLC-unsupported codec */
memset
(
fourcc_v4l2
,
0
,
sizeof
(
fourcc_v4l2
));
vlc_fourcc_to_char
(
codecs
[
i
].
pixelformat
,
fourcc_v4l2
);
bool
b_codec_supported
=
false
;
if
(
codec
.
flags
&
V4L2_FMT_FLAG_EMULATED
)
for
(
unsigned
j
=
0
;
v4l2chroma_to_fourcc
[
j
].
i_v4l2
!=
0
;
j
++
)
{
{
if
(
native
)
if
(
v4l2chroma_to_fourcc
[
j
].
i_v4l2
==
codecs
[
i
].
pixelformat
)
continue
;
/* ignore emulated format if possible */
{
char
fourcc
[
5
];
memset
(
fourcc
,
0
,
sizeof
(
fourcc
));
vlc_fourcc_to_char
(
v4l2chroma_to_fourcc
[
j
].
i_fourcc
,
fourcc
);
msg_Dbg
(
demux
,
"device supports chroma %4.4s [%s, %s]"
,
fourcc
,
codecs
[
i
].
description
,
fourcc_v4l2
);
b_codec_supported
=
true
;
}
}
if
(
!
b_codec_supported
)
msg_Dbg
(
demux
,
"device codec %4.4s (%s) not supported"
,
fourcc_v4l2
,
codecs
[
i
].
description
);
}
}
}
else
native
=
true
;
/* TODO: Move the resolution stuff up here */
sys
->
controls
=
ControlsInit
(
VLC_OBJECT
(
demux
),
fd
);
/* Try and find default resolution if not specified */
struct
v4l2_format
fmt
=
{
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
};
int
width
=
var_InheritInteger
(
demux
,
CFG_PREFIX
"width"
);
int
height
=
var_InheritInteger
(
demux
,
CFG_PREFIX
"height"
);
if
(
width
<=
0
||
height
<=
0
)
if
(
dsc
->
v4l2
==
reqfourcc
)
{
/* Use current width and height settings */
if
(
v4l2_ioctl
(
fd
,
VIDIOC_G_FMT
,
&
fmt
)
<
0
)
{
{
msg_Err
(
demux
,
"cannot get default width and height: %m"
);
msg_Dbg
(
demux
,
" matches the requested format"
);
goto
error
;
selected
=
dsc
;
break
;
/* always select the requested format if found */
}
}
msg_Dbg
(
demux
,
"found default width and height of %ux%u"
,
if
(
vlc_v4l2_fmt_rank
(
dsc
)
>
vlc_v4l2_fmt_rank
(
selected
))
fmt
.
fmt
.
pix
.
width
,
fmt
.
fmt
.
pix
.
height
);
continue
;
/* ignore if rank is worse */
if
(
width
<
0
||
height
<
0
)
selected
=
dsc
;
msg_Dbg
(
demux
,
"will try to find optimal width and height"
);
}
}
else
if
(
selected
==
NULL
)
{
{
/* Use user specified width and height */
msg_Err
(
demux
,
"cannot negotiate supported video format"
);
msg_Dbg
(
demux
,
"trying specified size %dx%d"
,
width
,
height
);
return
-
1
;
fmt
.
fmt
.
pix
.
width
=
width
;
fmt
.
fmt
.
pix
.
height
=
height
;
}
}
msg_Dbg
(
demux
,
"selected format %4.4s (%4.4s)"
,
(
const
char
*
)
&
selected
->
v4l2
,
(
const
char
*
)
&
selected
->
vlc
);
/* Test and set Chroma */
struct
v4l2_format
fmt
=
{
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
};
fmt
.
fmt
.
pix
.
field
=
V4L2_FIELD_NONE
;
if
(
v4l2_ioctl
(
fd
,
VIDIOC_G_FMT
,
&
fmt
)
<
0
)
fmt
.
fmt
.
pix
.
pixelformat
=
0
;
float
fps
;
char
*
reqchroma
=
var_InheritString
(
demux
,
CFG_PREFIX
"chroma"
);
if
(
reqchroma
!=
NULL
)
{
{
/* User specified chroma */
msg_Err
(
demux
,
"cannot get device default format: %m"
);
const
vlc_fourcc_t
i_requested_fourcc
=
return
-
1
;
vlc_fourcc_GetCodecFromString
(
VIDEO_ES
,
reqchroma
);
}
for
(
int
i
=
0
;
v4l2chroma_to_fourcc
[
i
].
i_v4l2
!=
0
;
i
++
)
fmt
.
fmt
.
pix
.
pixelformat
=
selected
->
v4l2
;
if
(
v4l2chroma_to_fourcc
[
i
].
i_fourcc
==
i_requested_fourcc
)
{
fmt
.
fmt
.
pix
.
pixelformat
=
v4l2chroma_to_fourcc
[
i
].
i_v4l2
;
break
;
}
/* Try and set user chroma */
uint32_t
width
=
var_InheritInteger
(
demux
,
CFG_PREFIX
"width"
);
bool
b_error
=
!
IsPixelFormatSupported
(
codecs
,
ncodec
,
if
(
width
!=
(
uint32_t
)
-
1
)
fmt
.
fmt
.
pix
.
pixelformat
);
fmt
.
fmt
.
pix
.
width
=
width
;
/* override width */
if
(
!
b_error
&&
fmt
.
fmt
.
pix
.
pixelformat
)
uint32_t
height
=
var_InheritInteger
(
demux
,
CFG_PREFIX
"height"
);
{
if
(
height
!=
(
uint32_t
)
-
1
)
if
(
v4l2_ioctl
(
fd
,
VIDIOC_S_FMT
,
&
fmt
)
<
0
)
fmt
.
fmt
.
pix
.
height
=
height
;
/* override height */
{
fmt
.
fmt
.
pix
.
field
=
V4L2_FIELD_ANY
;
if
(
v4l2_ioctl
(
fd
,
VIDIOC_S_FMT
,
&
fmt
)
<
0
)
{
fmt
.
fmt
.
pix
.
field
=
V4L2_FIELD_NONE
;
b_error
=
true
;
}
}
}
if
(
b_error
)
{
msg_Warn
(
demux
,
"requested chroma %s not supported. "
" Trying default."
,
reqchroma
);
fmt
.
fmt
.
pix
.
pixelformat
=
0
;
}
free
(
reqchroma
);
}
/* If no user specified chroma, find best */
if
(
v4l2_ioctl
(
fd
,
VIDIOC_S_FMT
,
&
fmt
)
<
0
)
/* This also decides if MPEG encoder card or not */
if
(
!
fmt
.
fmt
.
pix
.
pixelformat
)
{
{
unsigned
int
i
;
msg_Err
(
demux
,
"cannot set format: %m"
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
p_chroma_fallbacks
);
i
++
)
return
-
1
;
{
fmt
.
fmt
.
pix
.
pixelformat
=
p_chroma_fallbacks
[
i
];
if
(
IsPixelFormatSupported
(
codecs
,
ncodec
,
fmt
.
fmt
.
pix
.
pixelformat
))
{
if
(
v4l2_ioctl
(
fd
,
VIDIOC_S_FMT
,
&
fmt
)
>=
0
)
break
;
fmt
.
fmt
.
pix
.
field
=
V4L2_FIELD_ANY
;
if
(
v4l2_ioctl
(
fd
,
VIDIOC_S_FMT
,
&
fmt
)
>=
0
)
break
;
fmt
.
fmt
.
pix
.
field
=
V4L2_FIELD_NONE
;
}
}
if
(
i
==
ARRAY_SIZE
(
p_chroma_fallbacks
))
{
msg_Warn
(
demux
,
"Could not select any of the default chromas; attempting to open as MPEG encoder card (access)"
);
goto
error
;
}
}
}
free
(
codecs
);
if
(
width
<
0
||
height
<
0
)
/* Try and find default resolution if not specified */
float
fps
=
0
.;
if
(
width
==
(
uint32_t
)
-
1
||
height
==
(
uint32_t
)
-
1
)
{
{
fps
=
var_InheritFloat
(
demux
,
CFG_PREFIX
"fps"
);
fps
=
var_InheritFloat
(
demux
,
CFG_PREFIX
"fps"
);
if
(
fps
<=
0
.)
if
(
fps
<=
0
.)
...
@@ -454,17 +395,10 @@ static int InitVideo (demux_t *demux, int fd)
...
@@ -454,17 +395,10 @@ static int InitVideo (demux_t *demux, int fd)
/* Look up final fourcc */
/* Look up final fourcc */
es_format_t
es_fmt
;
es_format_t
es_fmt
;
sys
->
i_fourcc
=
0
;
es_format_Init
(
&
es_fmt
,
VIDEO_ES
,
selected
->
vlc
);
for
(
int
i
=
0
;
v4l2chroma_to_fourcc
[
i
].
i_fourcc
!=
0
;
i
++
)
es_fmt
.
video
.
i_rmask
=
selected
->
red
;
if
(
v4l2chroma_to_fourcc
[
i
].
i_v4l2
==
fmt
.
fmt
.
pix
.
pixelformat
)
es_fmt
.
video
.
i_gmask
=
selected
->
green
;
{
es_fmt
.
video
.
i_bmask
=
selected
->
blue
;
sys
->
i_fourcc
=
v4l2chroma_to_fourcc
[
i
].
i_fourcc
;
es_format_Init
(
&
es_fmt
,
VIDEO_ES
,
sys
->
i_fourcc
);
es_fmt
.
video
.
i_rmask
=
v4l2chroma_to_fourcc
[
i
].
i_rmask
;
es_fmt
.
video
.
i_gmask
=
v4l2chroma_to_fourcc
[
i
].
i_gmask
;
es_fmt
.
video
.
i_bmask
=
v4l2chroma_to_fourcc
[
i
].
i_bmask
;
break
;
}
/* Buggy driver paranoia */
/* Buggy driver paranoia */
i_min
=
fmt
.
fmt
.
pix
.
width
*
2
;
i_min
=
fmt
.
fmt
.
pix
.
width
*
2
;
...
@@ -539,10 +473,6 @@ static int InitVideo (demux_t *demux, int fd)
...
@@ -539,10 +473,6 @@ static int InitVideo (demux_t *demux, int fd)
sys
->
p_es
=
es_out_Add
(
demux
->
out
,
&
es_fmt
);
sys
->
p_es
=
es_out_Add
(
demux
->
out
,
&
es_fmt
);
return
0
;
return
0
;
error:
free
(
codecs
);
return
-
1
;
}
}
void
DemuxClose
(
vlc_object_t
*
obj
)
void
DemuxClose
(
vlc_object_t
*
obj
)
...
...
modules/access/v4l2/v4l2.h
View file @
fcab6ae6
...
@@ -94,7 +94,6 @@ struct demux_sys_t
...
@@ -94,7 +94,6 @@ struct demux_sys_t
unsigned
int
i_nbuffers
;
unsigned
int
i_nbuffers
;
#define blocksize i_nbuffers
/* HACK HACK */
#define blocksize i_nbuffers
/* HACK HACK */
int
i_fourcc
;
uint32_t
i_block_flags
;
uint32_t
i_block_flags
;
es_out_id_t
*
p_es
;
es_out_id_t
*
p_es
;
...
...
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