33#ifdef HAVE_SYS_IOCTL_H
43#ifdef HAVE_ASM_TYPES_H
49#ifdef HAVE_LINUX_VIDEODEV_H
50#include <linux/videodev.h>
78static typeof(mmap) *video_mmap = mmap;
79static typeof(munmap) *video_munmap = munmap;
81static void video_init(
void)
84 static void *video_lib;
111 BOOL iscommitted, stopped;
112 struct video_picture pict;
113 int dbrightness, dhue, dcolour, dcontrast;
116 struct video_mmap *grab_buf;
117 struct video_mbuf gb_buffers;
141static const struct renderlist renderlist_V4l[] = {
142 { 0,
"NULL renderer",
NULL },
143 { 8,
"Gray scales",
NULL },
144 { 0,
"High 240 cube (BT848)",
NULL },
145 { 16,
"16 bit RGB (565)",
NULL },
146 { 24,
"24 bit RGB values", renderer_RGB },
147 { 32,
"32 bit RGB values", renderer_RGB },
148 { 16,
"15 bit RGB (555)",
NULL },
149 { 16,
"YUV 422 (Not P)", renderer_YUV },
150 { 16,
"YUYV (Not P)", renderer_YUV },
151 { 16,
"UYVY (Not P)", renderer_YUV },
152 { 16,
"YUV 420 (Not P)",
NULL },
153 { 12,
"YUV 411 (Not P)", renderer_YUV },
154 { 0,
"Raw capturing (BT848)",
NULL },
155 { 16,
"YUV 422 (Planar)", renderer_YUV },
156 { 12,
"YUV 411 (Planar)", renderer_YUV },
157 { 12,
"YUV 420 (Planar)", renderer_YUV },
158 { 10,
"YUV 410 (Planar)", renderer_YUV },
163static const int fallback_V4l[] = { 4, 5, 7, 8, 9, 13, 15, 14, 16, 11, -1 };
182 TRACE(
"%p: Preparing for %dx%d resolution\n", capBox, capBox->width, capBox->height);
186 if (xioctl(capBox->fd, VIDIOCGMBUF, &capBox->gb_buffers) != -1 &&
187 capBox->gb_buffers.frames)
189 capBox->buffers = capBox->gb_buffers.frames;
190 if (capBox->gb_buffers.frames > 1)
192 TRACE(
"%p: Using %d/%d buffers\n", capBox,
193 capBox->buffers, capBox->gb_buffers.frames);
195 capBox->pmap = video_mmap( 0, capBox->gb_buffers.size, PROT_READ|PROT_WRITE,
196 MAP_SHARED, capBox->fd, 0 );
201 capBox->grab_buf =
CoTaskMemAlloc(
sizeof(
struct video_mmap) * capBox->buffers);
202 if (!capBox->grab_buf)
204 video_munmap(capBox->pmap, capBox->gb_buffers.size);
209 for (
i = 0;
i < capBox->buffers;
i++)
211 capBox->grab_buf[
i].format = capBox->pict.palette;
212 capBox->grab_buf[
i].frame =
i;
213 capBox->grab_buf[
i].width = capBox->width;
214 capBox->grab_buf[
i].height = capBox->height;
222 capBox->imagesize = renderlist_V4l[capBox->pict.palette].depth *
223 capBox->height * capBox->width / 8;
225 if (!capBox->grab_data)
228 TRACE(
"Using mmap: %d\n", capBox->mmap);
232static void V4l_Unprepare(
Capture *capBox)
236 for (capBox->curframe = 0; capBox->curframe < capBox->buffers; capBox->curframe++)
237 xioctl(capBox->fd, VIDIOCSYNC, &capBox->grab_buf[capBox->curframe]);
238 video_munmap(capBox->pmap, capBox->gb_buffers.size);
247 TRACE(
"%p\n", capBox);
249 if( capBox->fd != -1 )
250 video_close(capBox->fd);
251 capBox->CritSect.DebugInfo->Spare[0] = 0;
259 int newheight, newwidth;
260 struct video_window
window;
263 TRACE(
"%p\n", capBox);
266 if (
format->bmiHeader.biBitCount != 24 ||
269 FIXME(
"unsupported media type %d %d\n",
format->bmiHeader.biBitCount,
270 format->bmiHeader.biCompression );
274 newwidth =
format->bmiHeader.biWidth;
275 newheight =
format->bmiHeader.biHeight;
277 TRACE(
"%p -> (%p) - %d %d\n", capBox, mT, newwidth, newheight);
279 if (capBox->height == newheight && capBox->width == newwidth)
282 if(-1 == xioctl(capBox->fd, VIDIOCGWIN, &
window))
284 ERR(
"ioctl(VIDIOCGWIN) failed (%d)\n",
errno);
288 window.height = newheight;
289 if (xioctl(capBox->fd, VIDIOCSWIN, &
window) == -1)
291 TRACE(
"using software resize: %dx%d -> %dx%d\n",
292 window.width,
window.height, capBox->width, capBox->height);
293 capBox->swresize =
TRUE;
297 capBox->height =
window.height;
298 capBox->width =
window.width;
299 capBox->swresize =
FALSE;
301 capBox->outputwidth =
window.width;
302 capBox->outputheight =
window.height;
321 mT[0]->majortype = MEDIATYPE_Video;
322 mT[0]->subtype = MEDIASUBTYPE_RGB24;
323 mT[0]->formattype = FORMAT_VideoInfo;
324 mT[0]->bFixedSizeSamples =
TRUE;
325 mT[0]->bTemporalCompression =
FALSE;
327 mT[0]->lSampleSize = capBox->outputwidth * capBox->outputheight * capBox->bitDepth / 8;
328 TRACE(
"Output format: %dx%d - %d bits = %u KB\n", capBox->outputwidth,
329 capBox->outputheight, capBox->bitDepth, mT[0]->lSampleSize/1024);
330 vi->rcSource.left = 0;
vi->rcSource.top = 0;
331 vi->rcTarget.left = 0;
vi->rcTarget.top = 0;
332 vi->rcSource.right = capBox->width;
vi->rcSource.bottom = capBox->height;
333 vi->rcTarget.right = capBox->outputwidth;
vi->rcTarget.bottom = capBox->outputheight;
334 vi->dwBitRate = capBox->fps * mT[0]->lSampleSize;
335 vi->dwBitErrorRate = 0;
337 vi->bmiHeader.biSize = 40;
338 vi->bmiHeader.biWidth = capBox->outputwidth;
339 vi->bmiHeader.biHeight = capBox->outputheight;
340 vi->bmiHeader.biPlanes = 1;
341 vi->bmiHeader.biBitCount = 24;
342 vi->bmiHeader.biCompression =
BI_RGB;
343 vi->bmiHeader.biSizeImage = mT[0]->lSampleSize;
344 vi->bmiHeader.biClrUsed =
vi->bmiHeader.biClrImportant = 0;
345 vi->bmiHeader.biXPelsPerMeter = 100;
346 vi->bmiHeader.biYPelsPerMeter = 100;
347 mT[0]->pbFormat = (
void *)
vi;
354 LONG *pSteppingDelta,
LONG *pDefault,
LONG *pCapsFlags )
357 pMin, pMax, pSteppingDelta, pDefault, pCapsFlags);
361 case VideoProcAmp_Brightness:
362 *pDefault = capBox->dbrightness;
365 *pDefault = capBox->dcontrast;
368 *pDefault = capBox->dhue;
371 *pDefault = capBox->dcolour;
379 *pSteppingDelta = 65536/256;
391 case VideoProcAmp_Brightness:
392 *lValue = capBox->pict.brightness;
395 *lValue = capBox->pict.contrast;
398 *lValue = capBox->pict.hue;
401 *lValue = capBox->pict.colour;
418 case VideoProcAmp_Brightness:
419 capBox->pict.brightness = lValue;
422 capBox->pict.contrast = lValue;
425 capBox->pict.hue = lValue;
428 capBox->pict.colour = lValue;
435 if (xioctl(capBox->fd, VIDIOCSPICT, &capBox->pict) == -1)
437 ERR(
"ioctl(VIDIOCSPICT) failed (%d)\n",
errno);
445 int depth = renderlist_V4l[capBox->pict.palette].depth;
446 int size = capBox->height * capBox->width *
depth / 8;
469 ERR(
"Unknown bit depth %d\n",
depth);
478 switch (capBox->pict.palette)
503 ERR(
"Unknown palette %d\n", capBox->pict.palette);
513 if (!capBox->swresize)
515 int depth = capBox->bitDepth / 8;
516 int inoffset = 0, outoffset = capBox->height * capBox->width *
depth;
517 int ow = capBox->width *
depth;
518 while (outoffset > 0)
522 for (
x = 0;
x < ow;
x++)
523 output[outoffset +
x] =
input[inoffset +
x];
531 int depth = capBox->bitDepth / 8;
532 int inoffset = 0, outoffset = (capBox->outputheight) * capBox->outputwidth *
depth;
533 int ow = capBox->outputwidth *
depth;
542 bmp_d =
CreateBitmap(capBox->outputwidth, capBox->outputheight, 1, capBox->bitDepth,
NULL);
545 StretchBlt(dc_d, 0, 0, capBox->outputwidth, capBox->outputheight,
546 dc_s, 0, 0, capBox->width, capBox->height,
SRCCOPY);
548 while (outoffset > 0)
553 for (
i = 0;
i < ow;
i++)
554 output[outoffset +
i] = myarray[inoffset +
i];
565static void V4l_GetFrame(
Capture * capBox,
unsigned char ** pInput)
569 if (xioctl(capBox->fd, VIDIOCSYNC, &capBox->grab_buf[capBox->curframe]) == -1)
570 WARN(
"Syncing ioctl failed: %d\n",
errno);
572 *pInput = capBox->pmap + capBox->gb_buffers.offsets[capBox->curframe];
577 while ((retval = video_read(capBox->fd, capBox->grab_data, capBox->imagesize)) == -1)
581 *pInput = (
unsigned char*) capBox->grab_data;
585static void V4l_FreeFrame(
Capture * capBox)
590 if (xioctl(capBox->fd, VIDIOCMCAPTURE, &capBox->grab_buf[capBox->curframe]) == -1)
593 if (++capBox->curframe == capBox->buffers)
594 capBox->curframe = 0;
602 ULONG framecount = 0;
603 unsigned char *
pTarget, *pInput, *pOutput;
605 hr = V4l_Prepare(capBox);
608 ERR(
"Stop IFilterGraph: %x\n",
hr);
610 capBox->stopped =
TRUE;
614 pOutput =
CoTaskMemAlloc(capBox->width * capBox->height * capBox->bitDepth / 8);
615 capBox->curframe = 0;
617 V4l_FreeFrame(capBox);
618 }
while (capBox->curframe != 0);
630 if (!capBox->swresize)
631 len = capBox->height * capBox->width * capBox->bitDepth / 8;
633 len = capBox->outputheight * capBox->outputwidth * capBox->bitDepth / 8;
634 IMediaSample_SetActualDataLength(pSample,
len);
636 len = IMediaSample_GetActualDataLength(pSample);
637 TRACE(
"Data length: %d KB\n",
len / 1024);
639 IMediaSample_GetPointer(pSample, &
pTarget);
641 V4l_GetFrame(capBox, &pInput);
642 capBox->renderer(capBox, pOutput, pInput);
643 Resize(capBox,
pTarget, pOutput);
645 TRACE(
"%p -> Frame %u: %x\n", capBox, ++framecount,
hr);
646 IMediaSample_Release(pSample);
647 V4l_FreeFrame(capBox);
651 TRACE(
"Return %x, stop IFilterGraph\n",
hr);
652 V4l_Unprepare(capBox);
654 capBox->stopped =
TRUE;
672 if (*
state == State_Running)
return S_OK;
676 capBox->stopped =
FALSE;
678 if (*
state == State_Stopped)
680 *
state = State_Running;
681 if (!capBox->iscommitted)
686 capBox->iscommitted =
TRUE;
689 if (!capBox->swresize)
690 ap.cbBuffer = capBox->width * capBox->height;
692 ap.cbBuffer = capBox->outputwidth * capBox->outputheight;
693 ap.cbBuffer = (
ap.cbBuffer * capBox->bitDepth) / 8;
699 hr = IMemAllocator_SetProperties(
out->pAllocator, &
ap, &actual);
702 hr = IMemAllocator_Commit(
out->pAllocator);
704 TRACE(
"Committing allocator: %x\n",
hr);
721 *
state = State_Running;
730 if (*
state == State_Paused)
732 if (*
state == State_Stopped)
736 *
state = State_Paused;
747 if (*
state == State_Stopped)
754 if (*
state == State_Paused)
756 capBox->stopped =
TRUE;
758 if (capBox->iscommitted)
763 capBox->iscommitted =
FALSE;
767 hr = IMemAllocator_Decommit(
out->pAllocator);
770 WARN(
"Decommitting allocator: %x\n",
hr);
772 V4l_Unprepare(capBox);
775 *
state = State_Stopped;
784 struct video_capability capa;
785 struct video_picture pict;
786 struct video_window
window;
798 capBox->CritSect.DebugInfo->Spare[0] = (
DWORD_PTR)(__FILE__
": Capture.CritSect");
806 if (capBox->fd == -1)
813 memset(&capa, 0,
sizeof(capa));
815 if (xioctl(capBox->fd, VIDIOCGCAP, &capa) == -1)
817 WARN(
"ioctl(VIDIOCGCAP) failed (%d)\n",
errno);
821 if (!(capa.type & VID_TYPE_CAPTURE))
823 WARN(
"not a video capture device\n");
827 TRACE(
"%d inputs on %s\n", capa.channels, capa.name );
829 if (xioctl(capBox->fd, VIDIOCGPICT, &pict) == -1)
831 ERR(
"ioctl(VIDIOCGPICT) failed (%d)\n",
errno );
835 TRACE(
"depth %d palette %d (%s) hue %d color %d contrast %d\n",
836 pict.depth, pict.palette, renderlist_V4l[pict.palette].name,
837 pict.hue, pict.colour, pict.contrast );
839 capBox->dbrightness = pict.brightness;
840 capBox->dcolour = pict.colour;
841 capBox->dhue = pict.hue;
842 capBox->dcontrast = pict.contrast;
844 if (!renderlist_V4l[pict.palette].renderer)
846 int palet = pict.palette,
i;
848 TRACE(
"No renderer available for %s, falling back to defaults\n",
849 renderlist_V4l[pict.palette].name);
850 capBox->renderer =
NULL;
851 for (
i = 0; fallback_V4l[
i] >=0 ;
i++)
853 int n = fallback_V4l[
i];
855 if (renderlist_V4l[
n].renderer ==
NULL)
858 pict.depth = renderlist_V4l[
n].depth;
860 if (xioctl(capBox->fd, VIDIOCSPICT, &pict) == -1)
862 TRACE(
"Could not render with %s (%d)\n",
863 renderlist_V4l[
n].
name,
n);
866 TRACE(
"using renderer %s (%d)\n",
867 renderlist_V4l[
n].
name,
n);
868 capBox->renderer = renderlist_V4l[
n].renderer;
872 if (!capBox->renderer)
874 ERR(
"video format %s isn't available\n",
875 renderlist_V4l[palet].
name);
881 TRACE(
"Using the suggested format\n");
882 capBox->renderer = renderlist_V4l[pict.palette].renderer;
884 memcpy(&capBox->pict, &pict,
sizeof(
struct video_picture));
887 if (xioctl(capBox->fd, VIDIOCGWIN, &
window) == -1)
893 capBox->height = capBox->outputheight =
window.height;
894 capBox->width = capBox->outputwidth =
window.width;
895 capBox->swresize =
FALSE;
896 capBox->bitDepth = 24;
899 capBox->stopped =
FALSE;
900 capBox->curframe = 0;
901 capBox->iscommitted =
FALSE;
903 TRACE(
"format: %d bits - %d x %d\n", capBox->bitDepth, capBox->width, capBox->height);
919 "The v4l headers were not available at compile time,\n"
920 "so video capture support is not available.\n";
925#define FAIL_WITH_ERR \
926 ERR("v4l absent: shouldn't be called\n"); \
946 LONG *pSteppingDelta,
LONG *pDefault,
LONG *pCapsFlags )
RTL_CRITICAL_SECTION CritSect
struct tagVIDEOINFOHEADER VIDEOINFOHEADER
enum VideoProcAmp_Contrast
enum VideoProcAmp_Saturation
@ VideoProcAmp_Flags_Manual
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
DWORD WINAPI ResumeThread(IN HANDLE hThread)
BOOL WINAPI SetThreadPriority(IN HANDLE hThread, IN int nPriority)
DWORD WINAPI SuspendThread(IN HANDLE hThread)
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
GLint GLint GLsizei GLsizei GLsizei depth
GLint GLint GLint GLint GLint x
GLint GLint GLsizei GLsizei height
GLdouble GLdouble GLdouble r
GLint GLint GLsizei width
GLsizei const GLvoid * pointer
GLenum GLenum GLenum input
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
VOID WINAPI CoTaskMemFree(LPVOID ptr)
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
void * wine_dlopen(const char *filename, int flag, char *error, size_t errorsize)
void * wine_dlsym(void *handle, const char *symbol, char *error, size_t errorsize)
struct msdos_volume_info vi
#define memcpy(s1, s2, n)
#define sprintf(buf, format,...)
static IHTMLWindow2 * window
const char * strerror(int err)
void YUV_Init(void) DECLSPEC_HIDDEN
void YUV_To_RGB24(enum YUV_Format format, unsigned char *target, const unsigned char *source, int width, int height) DECLSPEC_HIDDEN
HRESULT WINAPI BaseOutputPinImpl_Deliver(BaseOutputPin *This, IMediaSample *pSample)
HRESULT WINAPI BaseOutputPinImpl_GetDeliveryBuffer(BaseOutputPin *This, IMediaSample **ppSample, REFERENCE_TIME *tStart, REFERENCE_TIME *tStop, DWORD dwFlags)
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
HRESULT qcap_driver_get_format(const Capture *capBox, AM_MEDIA_TYPE **mT)
HRESULT qcap_driver_set_prop(Capture *capBox, VideoProcAmpProperty Property, LONG lValue, LONG Flags)
HRESULT qcap_driver_destroy(Capture *capBox)
HRESULT qcap_driver_get_prop(Capture *capBox, VideoProcAmpProperty Property, LONG *lValue, LONG *Flags)
HRESULT qcap_driver_set_format(Capture *capBox, AM_MEDIA_TYPE *mT)
HRESULT qcap_driver_pause(Capture *capBox, FILTER_STATE *state)
Capture * qcap_driver_init(IPin *pOut, USHORT card)
HRESULT qcap_driver_get_prop_range(Capture *capBox, VideoProcAmpProperty Property, LONG *pMin, LONG *pMax, LONG *pSteppingDelta, LONG *pDefault, LONG *pCapsFlags)
HRESULT qcap_driver_run(Capture *capBox, FILTER_STATE *state)
HRESULT qcap_driver_stop(Capture *capBox, FILTER_STATE *state)
#define VFW_E_INVALIDMEDIATYPE
#define VFW_E_NOT_COMMITTED
#define VFW_E_NOT_CONNECTED
DWORD WINAPI GetLastError(void)
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define THREAD_PRIORITY_LOWEST
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
void WINAPI DeleteCriticalSection(PCRITICAL_SECTION)
void int int ULONGLONG int va_list * ap
HBITMAP WINAPI CreateBitmap(_In_ INT cx, _In_ INT cy, _In_ UINT cPlanes, _In_ UINT cBitsPerPel, _In_opt_ const VOID *pvBits)
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
BOOL WINAPI StretchBlt(_In_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_opt_ HDC, _In_ int, _In_ int, _In_ int, _In_ int, _In_ DWORD)
LONG WINAPI GetBitmapBits(_In_ HBITMAP hbit, _In_ LONG cb, _Out_writes_bytes_(cb) LPVOID lpvBits)
_Must_inspect_result_ _In_ ULONG Flags