[PATCH 3/4] qcap: Rework v4l2 state change logic.
Zebediah Figura
z.figura12 at gmail.com
Wed Dec 4 23:03:30 CST 2019
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
dlls/qcap/capture.h | 7 +-
dlls/qcap/v4l.c | 166 +++++++++++++----------------------------
dlls/qcap/vfwcapture.c | 60 ++++++++-------
3 files changed, 89 insertions(+), 144 deletions(-)
diff --git a/dlls/qcap/capture.h b/dlls/qcap/capture.h
index 6433f37d88f..7d2be332488 100644
--- a/dlls/qcap/capture.h
+++ b/dlls/qcap/capture.h
@@ -31,8 +31,9 @@ HRESULT qcap_driver_get_format(const Capture *, AM_MEDIA_TYPE *) DECLSPEC_HIDDEN
HRESULT qcap_driver_get_prop_range(Capture*,VideoProcAmpProperty,LONG*,LONG*,LONG*,LONG*,LONG*) DECLSPEC_HIDDEN;
HRESULT qcap_driver_get_prop(Capture*,VideoProcAmpProperty,LONG*,LONG*) DECLSPEC_HIDDEN;
HRESULT qcap_driver_set_prop(Capture*,VideoProcAmpProperty,LONG,LONG) DECLSPEC_HIDDEN;
-HRESULT qcap_driver_run(Capture*,FILTER_STATE*) DECLSPEC_HIDDEN;
-HRESULT qcap_driver_pause(Capture*,FILTER_STATE*) DECLSPEC_HIDDEN;
-HRESULT qcap_driver_stop(Capture*,FILTER_STATE*) DECLSPEC_HIDDEN;
+void qcap_driver_init_stream(Capture *device) DECLSPEC_HIDDEN;
+void qcap_driver_start_stream(Capture *device) DECLSPEC_HIDDEN;
+void qcap_driver_stop_stream(Capture *device) DECLSPEC_HIDDEN;
+void qcap_driver_cleanup_stream(Capture *device) DECLSPEC_HIDDEN;
#endif /* __QCAP_CAPTURE_H__ */
diff --git a/dlls/qcap/v4l.c b/dlls/qcap/v4l.c
index a203e91e52b..75121fd8518 100644
--- a/dlls/qcap/v4l.c
+++ b/dlls/qcap/v4l.c
@@ -99,13 +99,11 @@ struct _Capture
UINT width, height, bitDepth, fps, outputwidth, outputheight;
BOOL swresize;
- CRITICAL_SECTION CritSect;
-
struct strmbase_source *pin;
int fd, mmap;
- BOOL iscommitted, stopped;
+ FILTER_STATE state;
- HANDLE thread;
+ HANDLE thread, run_event;
};
static int xioctl(int fd, int request, void * arg)
@@ -125,8 +123,6 @@ HRESULT qcap_driver_destroy(Capture *capBox)
if( capBox->fd != -1 )
video_close(capBox->fd);
- capBox->CritSect.DebugInfo->Spare[0] = 0;
- DeleteCriticalSection(&capBox->CritSect);
CoTaskMemFree(capBox);
return S_OK;
}
@@ -389,16 +385,14 @@ static DWORD WINAPI ReadThread(LPVOID lParam)
if (!(image_data = heap_alloc(image_size)))
{
ERR("Failed to allocate memory.\n");
- capBox->thread = 0;
- capBox->stopped = TRUE;
return 0;
}
- while (1)
+ while (capBox->state != State_Stopped)
{
- EnterCriticalSection(&capBox->CritSect);
- if (capBox->stopped)
- break;
+ if (capBox->state == State_Paused)
+ WaitForSingleObject(capBox->run_event, INFINITE);
+
hr = BaseOutputPinImpl_GetDeliveryBuffer(capBox->pin, &pSample, NULL, NULL, 0);
if (SUCCEEDED(hr))
{
@@ -432,124 +426,66 @@ static DWORD WINAPI ReadThread(LPVOID lParam)
if (FAILED(hr) && hr != VFW_E_NOT_CONNECTED)
{
TRACE("Return %x, stop IFilterGraph\n", hr);
- capBox->thread = 0;
- capBox->stopped = TRUE;
break;
}
- LeaveCriticalSection(&capBox->CritSect);
}
- LeaveCriticalSection(&capBox->CritSect);
heap_free(image_data);
return 0;
}
-HRESULT qcap_driver_run(Capture *capBox, FILTER_STATE *state)
+void qcap_driver_init_stream(Capture *device)
{
- HANDLE thread;
+ ALLOCATOR_PROPERTIES req_props, ret_props;
HRESULT hr;
- TRACE("%p -> (%p)\n", capBox, state);
-
- if (*state == State_Running) return S_OK;
-
- EnterCriticalSection(&capBox->CritSect);
+ req_props.cBuffers = 3;
+ if (!device->swresize)
+ req_props.cbBuffer = device->width * device->height;
+ else
+ req_props.cbBuffer = device->outputwidth * device->outputheight;
+ req_props.cbBuffer = (req_props.cbBuffer * device->bitDepth) / 8;
+ req_props.cbAlign = 1;
+ req_props.cbPrefix = 0;
- capBox->stopped = FALSE;
+ hr = IMemAllocator_SetProperties(device->pin->pAllocator, &req_props, &ret_props);
+ if (FAILED(hr))
+ ERR("Failed to set allocator properties (buffer size %u), hr %#x.\n", req_props.cbBuffer, hr);
- if (*state == State_Stopped && capBox->pin->pin.peer)
+ if (SUCCEEDED(hr))
{
- *state = State_Running;
- if (!capBox->iscommitted)
- {
- ALLOCATOR_PROPERTIES ap, actual;
-
- capBox->iscommitted = TRUE;
-
- ap.cBuffers = 3;
- if (!capBox->swresize)
- ap.cbBuffer = capBox->width * capBox->height;
- else
- ap.cbBuffer = capBox->outputwidth * capBox->outputheight;
- ap.cbBuffer = (ap.cbBuffer * capBox->bitDepth) / 8;
- ap.cbAlign = 1;
- ap.cbPrefix = 0;
-
- hr = IMemAllocator_SetProperties(capBox->pin->pAllocator, &ap, &actual);
-
- if (SUCCEEDED(hr))
- hr = IMemAllocator_Commit(capBox->pin->pAllocator);
-
- TRACE("Committing allocator: %x\n", hr);
- }
-
- thread = CreateThread(NULL, 0, ReadThread, capBox, 0, NULL);
- if (thread)
- {
- capBox->thread = thread;
- SetThreadPriority(thread, THREAD_PRIORITY_LOWEST);
- LeaveCriticalSection(&capBox->CritSect);
- return S_OK;
- }
- ERR("Creating thread failed.. %u\n", GetLastError());
- LeaveCriticalSection(&capBox->CritSect);
- return E_FAIL;
+ if (FAILED(hr = IMemAllocator_Commit(device->pin->pAllocator)))
+ ERR("Failed to commit allocator, hr %#x.\n", hr);
}
- ResumeThread(capBox->thread);
- *state = State_Running;
- LeaveCriticalSection(&capBox->CritSect);
- return S_OK;
+ device->state = State_Paused;
+ device->thread = CreateThread(NULL, 0, ReadThread, device, 0, NULL);
}
-HRESULT qcap_driver_pause(Capture *capBox, FILTER_STATE *state)
+void qcap_driver_start_stream(Capture *device)
{
- TRACE("%p -> (%p)\n", capBox, state);
-
- if (*state == State_Paused)
- return S_OK;
- if (*state == State_Stopped)
- qcap_driver_run(capBox, state);
-
- EnterCriticalSection(&capBox->CritSect);
- *state = State_Paused;
- SuspendThread(capBox->thread);
- LeaveCriticalSection(&capBox->CritSect);
-
- return S_OK;
+ device->state = State_Running;
+ SetEvent(device->run_event);
}
-HRESULT qcap_driver_stop(Capture *capBox, FILTER_STATE *state)
+void qcap_driver_stop_stream(Capture *device)
{
- TRACE("%p -> (%p)\n", capBox, state);
-
- if (*state == State_Stopped)
- return S_OK;
-
- EnterCriticalSection(&capBox->CritSect);
-
- if (capBox->thread)
- {
- if (*state == State_Paused)
- ResumeThread(capBox->thread);
- capBox->stopped = TRUE;
- capBox->thread = 0;
- if (capBox->iscommitted)
- {
- HRESULT hr;
-
- capBox->iscommitted = FALSE;
-
- hr = IMemAllocator_Decommit(capBox->pin->pAllocator);
+ device->state = State_Paused;
+ ResetEvent(device->run_event);
+}
- if (hr != S_OK && hr != VFW_E_NOT_COMMITTED)
- WARN("Decommitting allocator: %x\n", hr);
- }
- }
+void qcap_driver_cleanup_stream(Capture *device)
+{
+ HRESULT hr;
- *state = State_Stopped;
- LeaveCriticalSection(&capBox->CritSect);
- return S_OK;
+ device->state = State_Stopped;
+ 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);
}
Capture *qcap_driver_init(struct strmbase_source *pin, USHORT card)
@@ -566,9 +502,6 @@ Capture *qcap_driver_init(struct strmbase_source *pin, USHORT card)
if (!(device = CoTaskMemAlloc(sizeof(*device))))
return NULL;
- InitializeCriticalSection(&device->CritSect);
- device->CritSect.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": Capture.CritSect");
-
sprintf(path, "/dev/video%i", card);
TRACE("Opening device %s.\n", path);
#ifdef O_CLOEXEC
@@ -635,8 +568,8 @@ Capture *qcap_driver_init(struct strmbase_source *pin, USHORT card)
device->bitDepth = 24;
device->pin = pin;
device->fps = 3;
- device->stopped = FALSE;
- device->iscommitted = FALSE;
+ device->state = State_Stopped;
+ device->run_event = CreateEventW(NULL, TRUE, FALSE, NULL);
TRACE("Format: %d bpp - %dx%d.\n", device->bitDepth, device->width, device->height);
@@ -701,17 +634,22 @@ HRESULT qcap_driver_set_prop(Capture *capBox, VideoProcAmpProperty Property,
FAIL_WITH_ERR;
}
-HRESULT qcap_driver_run(Capture *capBox, FILTER_STATE *state)
+void qcap_driver_init_stream(Capture *device)
+{
+ FAIL_WITH_ERR;
+}
+
+void qcap_driver_start_stream(Capture *device)
{
FAIL_WITH_ERR;
}
-HRESULT qcap_driver_pause(Capture *capBox, FILTER_STATE *state)
+void qcap_driver_stop_stream(Capture *device)
{
FAIL_WITH_ERR;
}
-HRESULT qcap_driver_stop(Capture *capBox, FILTER_STATE *state)
+void qcap_driver_cleanup_stream(Capture *device)
{
FAIL_WITH_ERR;
}
diff --git a/dlls/qcap/vfwcapture.c b/dlls/qcap/vfwcapture.c
index 2b60e542eba..0f8beb0f495 100644
--- a/dlls/qcap/vfwcapture.c
+++ b/dlls/qcap/vfwcapture.c
@@ -62,11 +62,6 @@ static inline VfwCapture *impl_from_strmbase_filter(struct strmbase_filter *ifac
return CONTAINING_RECORD(iface, VfwCapture, filter);
}
-static inline VfwCapture *impl_from_IBaseFilter(IBaseFilter *iface)
-{
- return CONTAINING_RECORD(iface, VfwCapture, filter.IBaseFilter_iface);
-}
-
static inline VfwCapture *impl_from_IAMStreamConfig(IAMStreamConfig *iface)
{
return CONTAINING_RECORD(iface, VfwCapture, IAMStreamConfig_iface);
@@ -99,7 +94,7 @@ static void vfw_capture_destroy(struct strmbase_filter *iface)
if (filter->init)
{
if (filter->filter.state != State_Stopped)
- qcap_driver_stop(filter->driver_info, &filter->filter.state);
+ qcap_driver_stop_stream(filter->driver_info);
qcap_driver_destroy(filter->driver_info);
}
@@ -129,47 +124,58 @@ static HRESULT vfw_capture_query_interface(struct strmbase_filter *iface, REFIID
return S_OK;
}
-static const struct strmbase_filter_ops filter_ops =
+static HRESULT vfw_capture_init_stream(struct strmbase_filter *iface)
{
- .filter_get_pin = vfw_capture_get_pin,
- .filter_destroy = vfw_capture_destroy,
- .filter_query_interface = vfw_capture_query_interface,
-};
+ VfwCapture *filter = impl_from_strmbase_filter(iface);
-/** IMediaFilter methods **/
+ qcap_driver_init_stream(filter->driver_info);
+ return VFW_S_CANT_CUE;
+}
-static HRESULT WINAPI VfwCapture_Stop(IBaseFilter * iface)
+static HRESULT vfw_capture_start_stream(struct strmbase_filter *iface, REFERENCE_TIME time)
{
- VfwCapture *This = impl_from_IBaseFilter(iface);
+ VfwCapture *filter = impl_from_strmbase_filter(iface);
- TRACE("()\n");
- return qcap_driver_stop(This->driver_info, &This->filter.state);
+ qcap_driver_start_stream(filter->driver_info);
+ return S_OK;
}
-static HRESULT WINAPI VfwCapture_Pause(IBaseFilter * iface)
+static HRESULT vfw_capture_stop_stream(struct strmbase_filter *iface)
{
- VfwCapture *This = impl_from_IBaseFilter(iface);
+ VfwCapture *filter = impl_from_strmbase_filter(iface);
- TRACE("()\n");
- return qcap_driver_pause(This->driver_info, &This->filter.state);
+ qcap_driver_stop_stream(filter->driver_info);
+ return VFW_S_CANT_CUE;
}
-static HRESULT WINAPI VfwCapture_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
+static HRESULT vfw_capture_cleanup_stream(struct strmbase_filter *iface)
{
- VfwCapture *This = impl_from_IBaseFilter(iface);
- TRACE("(%s)\n", wine_dbgstr_longlong(tStart));
- return qcap_driver_run(This->driver_info, &This->filter.state);
+ VfwCapture *filter = impl_from_strmbase_filter(iface);
+
+ qcap_driver_cleanup_stream(filter->driver_info);
+ return S_OK;
}
+static const struct strmbase_filter_ops filter_ops =
+{
+ .filter_get_pin = vfw_capture_get_pin,
+ .filter_destroy = vfw_capture_destroy,
+ .filter_query_interface = vfw_capture_query_interface,
+ .filter_init_stream = vfw_capture_init_stream,
+ .filter_start_stream = vfw_capture_start_stream,
+ .filter_stop_stream = vfw_capture_stop_stream,
+ .filter_cleanup_stream = vfw_capture_cleanup_stream,
+};
+
static const IBaseFilterVtbl VfwCapture_Vtbl =
{
BaseFilterImpl_QueryInterface,
BaseFilterImpl_AddRef,
BaseFilterImpl_Release,
BaseFilterImpl_GetClassID,
- VfwCapture_Stop,
- VfwCapture_Pause,
- VfwCapture_Run,
+ BaseFilterImpl_Stop,
+ BaseFilterImpl_Pause,
+ BaseFilterImpl_Run,
BaseFilterImpl_GetState,
BaseFilterImpl_SetSyncSource,
BaseFilterImpl_GetSyncSource,
--
2.23.0
More information about the wine-devel
mailing list