Signed-off-by: Zebediah Figura z.figura12@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,