Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
26cbb3dd
Commit
26cbb3dd
authored
Nov 24, 2020
by
Zebediah Figura
Committed by
Alexandre Julliard
Nov 25, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
qcap: Move the video capture streaming thread to vfwcapture.c.
Signed-off-by:
Zebediah Figura
<
z.figura12@gmail.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
db143ed0
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
103 additions
and
94 deletions
+103
-94
qcap_private.h
dlls/qcap/qcap_private.h
+1
-2
v4l.c
dlls/qcap/v4l.c
+8
-88
vfwcapture.c
dlls/qcap/vfwcapture.c
+94
-4
No files found.
dlls/qcap/qcap_private.h
View file @
26cbb3dd
...
...
@@ -54,9 +54,8 @@ struct video_capture_funcs
LONG
*
min
,
LONG
*
max
,
LONG
*
step
,
LONG
*
default_value
,
LONG
*
flags
);
HRESULT
(
*
get_prop
)(
struct
video_capture_device
*
device
,
VideoProcAmpProperty
property
,
LONG
*
value
,
LONG
*
flags
);
HRESULT
(
*
set_prop
)(
struct
video_capture_device
*
device
,
VideoProcAmpProperty
property
,
LONG
value
,
LONG
flags
);
BOOL
(
*
read_frame
)(
struct
video_capture_device
*
device
,
BYTE
*
data
);
void
(
*
init_stream
)(
struct
video_capture_device
*
device
);
void
(
*
start_stream
)(
struct
video_capture_device
*
device
);
void
(
*
stop_stream
)(
struct
video_capture_device
*
device
);
void
(
*
cleanup_stream
)(
struct
video_capture_device
*
device
);
};
...
...
dlls/qcap/v4l.c
View file @
26cbb3dd
...
...
@@ -99,11 +99,6 @@ struct video_capture_device
struct
strmbase_source
*
pin
;
int
fd
,
mmap
;
HANDLE
thread
;
FILTER_STATE
state
;
CONDITION_VARIABLE
state_cv
;
CRITICAL_SECTION
state_cs
;
};
static
int
xioctl
(
int
fd
,
int
request
,
void
*
arg
)
...
...
@@ -119,8 +114,6 @@ static int xioctl(int fd, int request, void * arg)
static
void
v4l_device_destroy
(
struct
video_capture_device
*
device
)
{
device
->
state_cs
.
DebugInfo
->
Spare
[
0
]
=
0
;
DeleteCriticalSection
(
&
device
->
state_cs
);
if
(
device
->
fd
!=
-
1
)
video_close
(
device
->
fd
);
if
(
device
->
caps_count
)
...
...
@@ -330,62 +323,19 @@ static void reverse_image(struct video_capture_device *device, LPBYTE output, co
}
}
static
DWORD
WINAPI
ReadThread
(
void
*
arg
)
static
BOOL
v4l_device_read_frame
(
struct
video_capture_device
*
device
,
BYTE
*
data
)
{
struct
video_capture_device
*
device
=
arg
;
HRESULT
hr
;
IMediaSample
*
pSample
=
NULL
;
unsigned
char
*
pTarget
;
for
(;;)
while
(
video_read
(
device
->
fd
,
device
->
image_data
,
device
->
image_size
)
<
0
)
{
EnterCriticalSection
(
&
device
->
state_cs
);
while
(
device
->
state
==
State_Paused
)
SleepConditionVariableCS
(
&
device
->
state_cv
,
&
device
->
state_cs
,
INFINITE
);
if
(
device
->
state
==
State_Stopped
)
if
(
errno
!=
EAGAIN
)
{
LeaveCriticalSection
(
&
device
->
state_cs
);
break
;
}
LeaveCriticalSection
(
&
device
->
state_cs
);
hr
=
BaseOutputPinImpl_GetDeliveryBuffer
(
device
->
pin
,
&
pSample
,
NULL
,
NULL
,
0
);
if
(
SUCCEEDED
(
hr
))
{
int
len
;
IMediaSample_SetActualDataLength
(
pSample
,
device
->
image_size
);
len
=
IMediaSample_GetActualDataLength
(
pSample
);
TRACE
(
"Data length: %d KB
\n
"
,
len
/
1024
);
IMediaSample_GetPointer
(
pSample
,
&
pTarget
);
while
(
video_read
(
device
->
fd
,
device
->
image_data
,
device
->
image_size
)
==
-
1
)
{
if
(
errno
!=
EAGAIN
)
{
ERR
(
"Failed to read frame: %s
\n
"
,
strerror
(
errno
));
break
;
}
}
reverse_image
(
device
,
pTarget
,
device
->
image_data
);
hr
=
IMemInputPin_Receive
(
device
->
pin
->
pMemInputPin
,
pSample
);
IMediaSample_Release
(
pSample
);
}
if
(
FAILED
(
hr
)
&&
hr
!=
VFW_E_NOT_CONNECTED
)
{
TRACE
(
"Return %x, stop IFilterGraph
\n
"
,
hr
);
break
;
ERR
(
"Failed to read frame: %s
\n
"
,
strerror
(
errno
));
return
FALSE
;
}
}
return
0
;
reverse_image
(
device
,
data
,
device
->
image_data
);
return
TRUE
;
}
static
void
v4l_device_init_stream
(
struct
video_capture_device
*
device
)
...
...
@@ -407,37 +357,12 @@ static void v4l_device_init_stream(struct video_capture_device *device)
if
(
FAILED
(
hr
=
IMemAllocator_Commit
(
device
->
pin
->
pAllocator
)))
ERR
(
"Failed to commit allocator, hr %#x.
\n
"
,
hr
);
}
device
->
state
=
State_Paused
;
device
->
thread
=
CreateThread
(
NULL
,
0
,
ReadThread
,
device
,
0
,
NULL
);
}
static
void
v4l_device_start_stream
(
struct
video_capture_device
*
device
)
{
EnterCriticalSection
(
&
device
->
state_cs
);
device
->
state
=
State_Running
;
LeaveCriticalSection
(
&
device
->
state_cs
);
}
static
void
v4l_device_stop_stream
(
struct
video_capture_device
*
device
)
{
EnterCriticalSection
(
&
device
->
state_cs
);
device
->
state
=
State_Paused
;
LeaveCriticalSection
(
&
device
->
state_cs
);
}
static
void
v4l_device_cleanup_stream
(
struct
video_capture_device
*
device
)
{
HRESULT
hr
;
EnterCriticalSection
(
&
device
->
state_cs
);
device
->
state
=
State_Stopped
;
LeaveCriticalSection
(
&
device
->
state_cs
);
WakeConditionVariable
(
&
device
->
state_cv
);
WaitForSingleObject
(
device
->
thread
,
INFINITE
);
CloseHandle
(
device
->
thread
);
device
->
thread
=
NULL
;
hr
=
IMemAllocator_Decommit
(
device
->
pin
->
pAllocator
);
if
(
hr
!=
S_OK
&&
hr
!=
VFW_E_NOT_COMMITTED
)
ERR
(
"Failed to decommit allocator, hr %#x.
\n
"
,
hr
);
...
...
@@ -638,10 +563,6 @@ struct video_capture_device *v4l_device_create(struct strmbase_source *pin, USHO
}
device
->
pin
=
pin
;
device
->
state
=
State_Stopped
;
InitializeConditionVariable
(
&
device
->
state_cv
);
InitializeCriticalSection
(
&
device
->
state_cs
);
device
->
state_cs
.
DebugInfo
->
Spare
[
0
]
=
(
DWORD_PTR
)(
__FILE__
": video_capture_device.state_cs"
);
TRACE
(
"Format: %d bpp - %dx%d.
\n
"
,
device
->
current_caps
->
video_info
.
bmiHeader
.
biBitCount
,
device
->
current_caps
->
video_info
.
bmiHeader
.
biWidth
,
...
...
@@ -667,9 +588,8 @@ const struct video_capture_funcs v4l_funcs =
.
get_prop_range
=
v4l_device_get_prop_range
,
.
get_prop
=
v4l_device_get_prop
,
.
set_prop
=
v4l_device_set_prop
,
.
read_frame
=
v4l_device_read_frame
,
.
init_stream
=
v4l_device_init_stream
,
.
start_stream
=
v4l_device_start_stream
,
.
stop_stream
=
v4l_device_stop_stream
,
.
cleanup_stream
=
v4l_device_cleanup_stream
,
};
...
...
dlls/qcap/vfwcapture.c
View file @
26cbb3dd
...
...
@@ -34,10 +34,19 @@ struct vfw_capture
IPersistPropertyBag
IPersistPropertyBag_iface
;
BOOL
init
;
struct
video_capture_device
*
device
;
struct
strmbase_source
source
;
IKsPropertySet
IKsPropertySet_iface
;
struct
video_capture_device
*
device
;
/* FIXME: It would be nice to avoid duplicating this variable with strmbase.
* However, synchronization is tricky; we need access to be protected by a
* separate lock. */
FILTER_STATE
state
;
CONDITION_VARIABLE
state_cv
;
CRITICAL_SECTION
state_cs
;
HANDLE
thread
;
};
static
inline
struct
vfw_capture
*
impl_from_strmbase_filter
(
struct
strmbase_filter
*
iface
)
...
...
@@ -96,6 +105,8 @@ static void vfw_capture_destroy(struct strmbase_filter *iface)
IPin_Disconnect
(
filter
->
source
.
pin
.
peer
);
IPin_Disconnect
(
&
filter
->
source
.
pin
.
IPin_iface
);
}
filter
->
state_cs
.
DebugInfo
->
Spare
[
0
]
=
0
;
DeleteCriticalSection
(
&
filter
->
state_cs
);
strmbase_source_cleanup
(
&
filter
->
source
);
strmbase_filter_cleanup
(
&
filter
->
filter
);
CoTaskMemFree
(
filter
);
...
...
@@ -121,11 +132,71 @@ static HRESULT vfw_capture_query_interface(struct strmbase_filter *iface, REFIID
return
S_OK
;
}
static
DWORD
WINAPI
stream_thread
(
void
*
arg
)
{
struct
vfw_capture
*
filter
=
arg
;
const
VIDEOINFOHEADER
*
format
=
(
const
VIDEOINFOHEADER
*
)
filter
->
source
.
pin
.
mt
.
pbFormat
;
const
unsigned
int
image_size
=
format
->
bmiHeader
.
biWidth
*
format
->
bmiHeader
.
biHeight
*
format
->
bmiHeader
.
biBitCount
/
8
;
for
(;;)
{
IMediaSample
*
sample
;
HRESULT
hr
;
BYTE
*
data
;
EnterCriticalSection
(
&
filter
->
state_cs
);
while
(
filter
->
state
==
State_Paused
)
SleepConditionVariableCS
(
&
filter
->
state_cv
,
&
filter
->
state_cs
,
INFINITE
);
if
(
filter
->
state
==
State_Stopped
)
{
LeaveCriticalSection
(
&
filter
->
state_cs
);
break
;
}
LeaveCriticalSection
(
&
filter
->
state_cs
);
if
(
FAILED
(
hr
=
BaseOutputPinImpl_GetDeliveryBuffer
(
&
filter
->
source
,
&
sample
,
NULL
,
NULL
,
0
)))
{
ERR
(
"Failed to get sample, hr %#x.
\n
"
,
hr
);
break
;
}
IMediaSample_SetActualDataLength
(
sample
,
image_size
);
IMediaSample_GetPointer
(
sample
,
&
data
);
if
(
!
capture_funcs
->
read_frame
(
filter
->
device
,
data
))
{
IMediaSample_Release
(
sample
);
break
;
}
hr
=
IMemInputPin_Receive
(
filter
->
source
.
pMemInputPin
,
sample
);
IMediaSample_Release
(
sample
);
if
(
FAILED
(
hr
))
{
ERR
(
"IMemInputPin::Receive() returned %#x.
\n
"
,
hr
);
break
;
}
}
return
0
;
}
static
HRESULT
vfw_capture_init_stream
(
struct
strmbase_filter
*
iface
)
{
struct
vfw_capture
*
filter
=
impl_from_strmbase_filter
(
iface
);
capture_funcs
->
init_stream
(
filter
->
device
);
EnterCriticalSection
(
&
filter
->
state_cs
);
filter
->
state
=
State_Paused
;
LeaveCriticalSection
(
&
filter
->
state_cs
);
filter
->
thread
=
CreateThread
(
NULL
,
0
,
stream_thread
,
filter
,
0
,
NULL
);
return
S_OK
;
}
...
...
@@ -133,7 +204,10 @@ static HRESULT vfw_capture_start_stream(struct strmbase_filter *iface, REFERENCE
{
struct
vfw_capture
*
filter
=
impl_from_strmbase_filter
(
iface
);
capture_funcs
->
start_stream
(
filter
->
device
);
EnterCriticalSection
(
&
filter
->
state_cs
);
filter
->
state
=
State_Running
;
LeaveCriticalSection
(
&
filter
->
state_cs
);
WakeConditionVariable
(
&
filter
->
state_cv
);
return
S_OK
;
}
...
...
@@ -141,7 +215,9 @@ static HRESULT vfw_capture_stop_stream(struct strmbase_filter *iface)
{
struct
vfw_capture
*
filter
=
impl_from_strmbase_filter
(
iface
);
capture_funcs
->
stop_stream
(
filter
->
device
);
EnterCriticalSection
(
&
filter
->
state_cs
);
filter
->
state
=
State_Paused
;
LeaveCriticalSection
(
&
filter
->
state_cs
);
return
S_OK
;
}
...
...
@@ -149,6 +225,15 @@ static HRESULT vfw_capture_cleanup_stream(struct strmbase_filter *iface)
{
struct
vfw_capture
*
filter
=
impl_from_strmbase_filter
(
iface
);
EnterCriticalSection
(
&
filter
->
state_cs
);
filter
->
state
=
State_Stopped
;
LeaveCriticalSection
(
&
filter
->
state_cs
);
WakeConditionVariable
(
&
filter
->
state_cv
);
WaitForSingleObject
(
filter
->
thread
,
INFINITE
);
CloseHandle
(
filter
->
thread
);
filter
->
thread
=
NULL
;
capture_funcs
->
cleanup_stream
(
filter
->
device
);
return
S_OK
;
}
...
...
@@ -709,6 +794,11 @@ HRESULT vfw_capture_create(IUnknown *outer, IUnknown **out)
object
->
IKsPropertySet_iface
.
lpVtbl
=
&
IKsPropertySet_VTable
;
object
->
state
=
State_Stopped
;
InitializeConditionVariable
(
&
object
->
state_cv
);
InitializeCriticalSection
(
&
object
->
state_cs
);
object
->
state_cs
.
DebugInfo
->
Spare
[
0
]
=
(
DWORD_PTR
)(
__FILE__
": vfw_capture.state_cs"
);
TRACE
(
"Created VFW capture filter %p.
\n
"
,
object
);
ObjectRefCount
(
TRUE
);
*
out
=
&
object
->
filter
.
IUnknown_inner
;
...
...
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