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
7dc94047
Commit
7dc94047
authored
Apr 11, 2012
by
Rémi Denis-Courmont
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
v4l2: fix and cleanup of mmap buffers allocation
Especially fix memory leaks on error.
parent
7e028434
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
58 additions
and
66 deletions
+58
-66
modules/access/v4l2/access.c
modules/access/v4l2/access.c
+4
-4
modules/access/v4l2/demux.c
modules/access/v4l2/demux.c
+7
-21
modules/access/v4l2/v4l2.h
modules/access/v4l2/v4l2.h
+4
-5
modules/access/v4l2/video.c
modules/access/v4l2/video.c
+43
-36
No files found.
modules/access/v4l2/access.c
View file @
7dc94047
...
@@ -96,7 +96,6 @@ error:
...
@@ -96,7 +96,6 @@ error:
int
InitVideo
(
access_t
*
access
,
int
fd
)
int
InitVideo
(
access_t
*
access
,
int
fd
)
{
{
demux_sys_t
*
sys
=
(
demux_sys_t
*
)
access
->
p_sys
;
demux_sys_t
*
sys
=
(
demux_sys_t
*
)
access
->
p_sys
;
enum
v4l2_buf_type
buf_type
;
/* Get device capabilites */
/* Get device capabilites */
struct
v4l2_capability
cap
;
struct
v4l2_capability
cap
;
...
@@ -168,9 +167,10 @@ int InitVideo (access_t *access, int fd)
...
@@ -168,9 +167,10 @@ int InitVideo (access_t *access, int fd)
/* Init I/O method */
/* Init I/O method */
if
(
cap
.
capabilities
&
V4L2_CAP_STREAMING
)
if
(
cap
.
capabilities
&
V4L2_CAP_STREAMING
)
{
{
if
(
InitMmap
(
VLC_OBJECT
(
access
),
sys
,
fd
))
sys
->
bufv
=
InitMmap
(
VLC_OBJECT
(
access
),
fd
,
&
sys
->
bufc
);
if
(
sys
->
bufv
==
NULL
)
return
-
1
;
return
-
1
;
for
(
u
nsigned
int
i
=
0
;
i
<
sys
->
i_nbuffers
;
i
++
)
for
(
u
int32_t
i
=
0
;
i
<
sys
->
bufc
;
i
++
)
{
{
struct
v4l2_buffer
buf
=
{
struct
v4l2_buffer
buf
=
{
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
,
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
,
...
@@ -185,7 +185,7 @@ int InitVideo (access_t *access, int fd)
...
@@ -185,7 +185,7 @@ int InitVideo (access_t *access, int fd)
}
}
}
}
buf_type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
;
enum
v4l2_buf_type
buf_type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
;
if
(
v4l2_ioctl
(
fd
,
VIDIOC_STREAMON
,
&
buf_type
)
<
0
)
if
(
v4l2_ioctl
(
fd
,
VIDIOC_STREAMON
,
&
buf_type
)
<
0
)
{
{
msg_Err
(
access
,
"cannot start streaming: %m"
);
msg_Err
(
access
,
"cannot start streaming: %m"
);
...
...
modules/access/v4l2/demux.c
View file @
7dc94047
...
@@ -430,9 +430,10 @@ static int InitVideo (demux_t *demux, int fd)
...
@@ -430,9 +430,10 @@ static int InitVideo (demux_t *demux, int fd)
void
*
(
*
entry
)
(
void
*
);
void
*
(
*
entry
)
(
void
*
);
if
(
caps
&
V4L2_CAP_STREAMING
)
if
(
caps
&
V4L2_CAP_STREAMING
)
{
{
if
(
InitMmap
(
VLC_OBJECT
(
demux
),
sys
,
fd
))
sys
->
bufv
=
InitMmap
(
VLC_OBJECT
(
demux
),
fd
,
&
sys
->
bufc
);
if
(
sys
->
bufv
==
NULL
)
return
-
1
;
return
-
1
;
for
(
u
nsigned
int
i
=
0
;
i
<
sys
->
i_nbuffers
;
i
++
)
for
(
u
int32_t
i
=
0
;
i
<
sys
->
bufc
;
i
++
)
{
{
struct
v4l2_buffer
buf
=
{
struct
v4l2_buffer
buf
=
{
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
,
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
,
...
@@ -494,37 +495,22 @@ void DemuxClose( vlc_object_t *obj )
...
@@ -494,37 +495,22 @@ void DemuxClose( vlc_object_t *obj )
{
{
/* NOTE: Some buggy drivers hang if buffers are not unmapped before
/* NOTE: Some buggy drivers hang if buffers are not unmapped before
* streamoff */
* streamoff */
for
(
unsigned
i
=
0
;
i
<
sys
->
i_nbuffers
;
i
++
)
for
(
uint32_t
i
=
0
;
i
<
sys
->
bufc
;
i
++
)
{
{
struct
v4l2_buffer
buf
=
{
struct
v4l2_buffer
buf
=
{
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
,
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
,
.
memory
=
V4L2_MEMORY_MMAP
,
.
memory
=
V4L2_MEMORY_MMAP
,
};
};
v4l2_ioctl
(
fd
,
VIDIOC_DQBUF
,
&
buf
);
v4l2_ioctl
(
fd
,
VIDIOC_DQBUF
,
&
buf
);
v4l2_munmap
(
sys
->
bufv
[
i
].
start
,
sys
->
bufv
[
i
].
length
);
}
}
enum
v4l2_buf_type
buf_type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
;
enum
v4l2_buf_type
buf_type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
;
v4l2_ioctl
(
sys
->
i_fd
,
VIDIOC_STREAMOFF
,
&
buf_type
);
v4l2_ioctl
(
sys
->
i_fd
,
VIDIOC_STREAMOFF
,
&
buf_type
);
free
(
sys
->
bufv
);
break
;
break
;
}
}
}
}
/* Free Video Buffers */
if
(
sys
->
p_buffers
)
{
switch
(
sys
->
io
)
{
case
IO_METHOD_READ
:
free
(
sys
->
p_buffers
[
0
].
start
);
break
;
case
IO_METHOD_MMAP
:
for
(
unsigned
i
=
0
;
i
<
sys
->
i_nbuffers
;
++
i
)
v4l2_munmap
(
sys
->
p_buffers
[
i
].
start
,
sys
->
p_buffers
[
i
].
length
);
break
;
}
free
(
sys
->
p_buffers
);
}
ControlsDeinit
(
obj
,
sys
->
controls
);
ControlsDeinit
(
obj
,
sys
->
controls
);
v4l2_close
(
fd
);
v4l2_close
(
fd
);
free
(
sys
);
free
(
sys
);
...
...
modules/access/v4l2/v4l2.h
View file @
7dc94047
...
@@ -86,9 +86,9 @@ struct demux_sys_t
...
@@ -86,9 +86,9 @@ struct demux_sys_t
/* Video */
/* Video */
io_method
io
;
io_method
io
;
struct
buffer_t
*
p_buffers
;
struct
buffer_t
*
bufv
;
u
nsigned
int
i_nbuffers
;
u
int32_t
bufc
;
#define blocksize
i_nbuffers
/* HACK HACK */
#define blocksize
bufc
/* HACK HACK */
uint32_t
i_block_flags
;
uint32_t
i_block_flags
;
...
@@ -110,8 +110,7 @@ int SetupFormat (vlc_object_t *, int, uint32_t,
...
@@ -110,8 +110,7 @@ int SetupFormat (vlc_object_t *, int, uint32_t,
struct
v4l2_format
*
,
struct
v4l2_streamparm
*
);
struct
v4l2_format
*
,
struct
v4l2_streamparm
*
);
#define SetupFormat(o,fd,fcc,fmt,p) \
#define SetupFormat(o,fd,fcc,fmt,p) \
SetupFormat(VLC_OBJECT(o),fd,fcc,fmt,p)
SetupFormat(VLC_OBJECT(o),fd,fcc,fmt,p)
struct
buffer_t
*
InitMmap
(
vlc_object_t
*
,
int
,
uint32_t
*
);
int
InitMmap
(
vlc_object_t
*
,
demux_sys_t
*
,
int
);
block_t
*
GrabVideo
(
vlc_object_t
*
,
demux_sys_t
*
);
block_t
*
GrabVideo
(
vlc_object_t
*
,
demux_sys_t
*
);
/* demux.c */
/* demux.c */
...
...
modules/access/v4l2/video.c
View file @
7dc94047
...
@@ -1001,7 +1001,7 @@ block_t* GrabVideo (vlc_object_t *demux, demux_sys_t *sys)
...
@@ -1001,7 +1001,7 @@ block_t* GrabVideo (vlc_object_t *demux, demux_sys_t *sys)
}
}
}
}
if
(
buf
.
index
>=
sys
->
i_nbuffers
)
{
if
(
buf
.
index
>=
sys
->
bufc
)
{
msg_Err
(
demux
,
"Failed capturing new frame as i>=nbuffers"
);
msg_Err
(
demux
,
"Failed capturing new frame as i>=nbuffers"
);
return
NULL
;
return
NULL
;
}
}
...
@@ -1010,7 +1010,7 @@ block_t* GrabVideo (vlc_object_t *demux, demux_sys_t *sys)
...
@@ -1010,7 +1010,7 @@ block_t* GrabVideo (vlc_object_t *demux, demux_sys_t *sys)
block_t
*
block
=
block_Alloc
(
buf
.
bytesused
);
block_t
*
block
=
block_Alloc
(
buf
.
bytesused
);
if
(
unlikely
(
block
==
NULL
))
if
(
unlikely
(
block
==
NULL
))
return
NULL
;
return
NULL
;
memcpy
(
block
->
p_buffer
,
sys
->
p_buffers
[
buf
.
index
].
start
,
buf
.
bytesused
);
memcpy
(
block
->
p_buffer
,
sys
->
bufv
[
buf
.
index
].
start
,
buf
.
bytesused
);
/* Unlock */
/* Unlock */
if
(
v4l2_ioctl
(
sys
->
i_fd
,
VIDIOC_QBUF
,
&
buf
)
<
0
)
if
(
v4l2_ioctl
(
sys
->
i_fd
,
VIDIOC_QBUF
,
&
buf
)
<
0
)
...
@@ -1025,56 +1025,63 @@ block_t* GrabVideo (vlc_object_t *demux, demux_sys_t *sys)
...
@@ -1025,56 +1025,63 @@ block_t* GrabVideo (vlc_object_t *demux, demux_sys_t *sys)
/*****************************************************************************
/*****************************************************************************
* Helper function to initalise video IO using the mmap method
* Helper function to initalise video IO using the mmap method
*****************************************************************************/
*****************************************************************************/
int
InitMmap
(
vlc_object_t
*
p_demux
,
demux_sys_t
*
p_sys
,
int
i_fd
)
struct
buffer_t
*
InitMmap
(
vlc_object_t
*
obj
,
int
fd
,
uint32_t
*
restrict
n
)
{
{
struct
v4l2_requestbuffers
req
;
struct
v4l2_requestbuffers
req
=
{
.
count
=
4
,
memset
(
&
req
,
0
,
sizeof
(
req
)
);
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
,
req
.
count
=
4
;
.
memory
=
V4L2_MEMORY_MMAP
,
req
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
;
};
req
.
memory
=
V4L2_MEMORY_MMAP
;
if
(
v4l2_ioctl
(
i_fd
,
VIDIOC_REQBUFS
,
&
req
)
<
0
)
if
(
v4l2_ioctl
(
fd
,
VIDIOC_REQBUFS
,
&
req
)
<
0
)
{
{
msg_Err
(
p_demux
,
"device does not support mmap I/O
"
);
msg_Err
(
obj
,
"cannot allocate buffers: %m
"
);
return
-
1
;
return
NULL
;
}
}
if
(
req
.
count
<
2
)
if
(
req
.
count
<
2
)
{
{
msg_Err
(
p_demux
,
"insufficient buffers"
);
msg_Err
(
obj
,
"cannot allocate enough buffers"
);
return
-
1
;
return
NULL
;
}
}
p_sys
->
p_buffers
=
calloc
(
req
.
count
,
sizeof
(
*
p_sys
->
p_buffers
)
);
struct
buffer_t
*
bufv
=
malloc
(
req
.
count
*
sizeof
(
*
bufv
)
);
if
(
unlikely
(
!
p_sys
->
p_buffers
)
)
if
(
unlikely
(
bufv
==
NULL
)
)
return
-
1
;
return
NULL
;
for
(
p_sys
->
i_nbuffers
=
0
;
p_sys
->
i_nbuffers
<
req
.
count
;
++
p_sys
->
i_nbuffers
)
uint32_t
bufc
;
for
(
bufc
=
0
;
bufc
<
req
.
count
;
bufc
++
)
{
{
struct
v4l2_buffer
buf
;
struct
v4l2_buffer
buf
=
{
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
,
memset
(
&
buf
,
0
,
sizeof
(
buf
)
);
.
memory
=
V4L2_MEMORY_MMAP
,
buf
.
type
=
V4L2_BUF_TYPE_VIDEO_CAPTURE
;
.
index
=
bufc
,
buf
.
memory
=
V4L2_MEMORY_MMAP
;
};
buf
.
index
=
p_sys
->
i_nbuffers
;
if
(
v4l2_ioctl
(
i_fd
,
VIDIOC_QUERYBUF
,
&
buf
)
<
0
)
if
(
v4l2_ioctl
(
fd
,
VIDIOC_QUERYBUF
,
&
buf
)
<
0
)
{
{
msg_Err
(
p_demux
,
"VIDIOC_QUERYBUF: %m"
);
msg_Err
(
obj
,
"cannot query buffer %"
PRIu32
": %m"
,
bufc
);
return
-
1
;
goto
error
;
}
}
p_sys
->
p_buffers
[
p_sys
->
i_nbuffers
].
length
=
buf
.
length
;
bufv
[
bufc
].
start
=
v4l2_mmap
(
NULL
,
buf
.
length
,
PROT_READ
|
PROT_WRITE
,
p_sys
->
p_buffers
[
p_sys
->
i_nbuffers
].
start
=
MAP_SHARED
,
fd
,
buf
.
m
.
offset
);
v4l2_mmap
(
NULL
,
buf
.
length
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
i_fd
,
buf
.
m
.
offset
);
if
(
bufv
[
bufc
].
start
==
MAP_FAILED
)
if
(
p_sys
->
p_buffers
[
p_sys
->
i_nbuffers
].
start
==
MAP_FAILED
)
{
{
msg_Err
(
p_demux
,
"mmap failed: %m"
);
msg_Err
(
obj
,
"cannot map buffer %"
PRIu32
": %m"
,
bufc
);
return
-
1
;
goto
error
;
}
}
bufv
[
bufc
].
length
=
buf
.
length
;
}
}
return
0
;
*
n
=
bufc
;
return
bufv
;
error:
while
(
bufc
>
0
)
{
bufc
--
;
v4l2_munmap
(
bufv
[
bufc
].
start
,
bufv
[
bufc
].
length
);
}
free
(
bufv
);
return
NULL
;
}
}
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