Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add Capture implementation for Linux #2061

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Conversation

whg
Copy link
Contributor

@whg whg commented Nov 29, 2018

Given v4l2 is part of the Linux kernel, I thought it would be a good idea to use it to implement video capture on Linux. I didn't need it, but on some distributions you may need to download the libv4l-dev package for this to compile.

With view of issue #2052, CaptureBasic and CaptureCube now build and work on my machine.

Here are a few notes:

  • I setup v4l2 to double buffer the incoming capture frames.
  • When getSurface() is called a copy of the last written buffer is made. As far as I can see, this is necessary.
  • A new shared_ptr is created each time getSurface() is called. I noticed that the Windows implementation has a pool of SurfaceRefs to eliminate this overhead. I chose the simplest solution!

@PetrosKataras
Copy link
Contributor

Great to see this work! Haven't had a detailed look but tried it out quickly on Ubuntu 18.04 VMware inside macOS 10.13.4 and it worked nicely with the built-in camera ( v4l2 recognized it as VMware Virtual USB Device ).

I do get a crash, when closing the window, on the destructor of CaptureImplLinux ( std::thread seems to choke and calls std::terminate ) but this might very well be due to running inside the VM.

Will definitely give it a try again once in front of a proper Linux machine with an external usb camera.

@sortofsleepy
Copy link
Contributor

sortofsleepy commented Dec 6, 2018

👋

Just tried on a Linux box with Ubuntu 18.04 and I believe I'm running into what Petros is seeing(I'm not totally set up to properly debug just yet).

The following shows up in the console when I close the window.

terminate called without an active exception
Aborted (core dumped)

Edit
Ah yep - assuming I'm looking at this output correctly, looks like I'm seeing the same thing as Petros on a non VM machine. WIll try to take a look too

@sortofsleepy
Copy link
Contributor

Looks like if I add

	mRunning.store( false );
	mThread.join();

to the very top of the destructor - this seems to fix things; closing the window doesn't raise the error anymore.

@whg
Copy link
Contributor Author

whg commented Dec 6, 2018

Hi guys,

Thanks @sortofsleepy for pointing me in the right direction, in my tests I was explicitly calling shutdown(), so I've added that to the destructor.

It also turns out that I wasn't properly shutting down the thread, so I've fixed that too.

@andrewfb
Copy link
Collaborator

andrewfb commented Dec 7, 2018

This looks good to me, and I know @sortofsleepy has continued stress-testing it as well. I was going to request a macro like CINDER_DISABLE_CAPTURE before I noticed you'd already done it. Thanks for this - I'd be inclined to merge this unless anyone has any objections (I can bring it in line with Cinder style when I do so).

@gaborpapp
Copy link
Contributor

Thanks for this. Tested it on Fedora and works well.

@3togo
Copy link

3togo commented Aug 13, 2019

I got the following error when compiling cinder-capture with captureBasic in linux.
|error | virtual void CaptureBasicApp::setup()[39] Failed to init capture , exception type: cinder::CaptureExcInitFail, what:

Any pointer on how to fix it?

@3togo
Copy link

3togo commented Aug 13, 2019

I found the bug!. It turns out that the program detected two webcams
/dev/video0 and /dev/video1
but in my notebook, /dev/video0 is NULL

if ( !mDevice ) {
auto &devices = getDevices();
if ( devices.empty() ) {
puts("No device found");
throw CaptureExcInitFail();
} else {
mDevice = getDevices()[1];
}
}

@gaborpapp
Copy link
Contributor

The thing with the two devices shown above is that they are two modes, motion-jpeg and yuv on my webcam. The current implementation only works with the yuv uncompressed stream, which has lower fps. For better frame rate in higher resolutions we would need to implement the mjpg support.

What do you think?
Anyone else experiencing this?

$ v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
	Type: Video Capture

	[0]: 'MJPG' (Motion-JPEG, compressed)
		Size: Discrete 1280x720
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 160x120
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 176x144
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 320x240
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 352x288
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.033s (30.000 fps)
			Interval: Discrete 0.033s (30.000 fps)
	[1]: 'YUYV' (YUYV 4:2:2)
		Size: Discrete 1280x720
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.100s (10.000 fps)
		Size: Discrete 160x120
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 176x144
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 320x240
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 352x288
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 640x480
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.100s (10.000 fps)
			Interval: Discrete 0.100s (10.000 fps)

@Hebali
Copy link

Hebali commented Oct 8, 2021

This seems to have stalled out, any plans to merge? @andrewfb

@richardeakin
Copy link
Collaborator

Just pushed this along with the two merge conflicts fixed to the CaptureLinux branch. It is essentially ready to merge to master, though i wanted to ask a couple questions around how this is built and configured:

  • There is a wget line added to the trusty-install-deps.sh script, is this preferred over sudo apt-get install libpmg123-dev ? The latter is what we have in the linux ubuntu install doc (source)
  • Is there a FindPackage cmake script handy (and liberally licensed) for V4L2? I noticed that the current cmake line adds a command to link to libv4l2.so, but doesn't check if it is available first.
    • I think ideally we could detect if V4L2 is usable and if so, link in the Capture impl. If it isn't, skip CaptureImplLinux.cpp and add a #define for CINDER_DISABLE_CAPTURE
  • Do we need to update the docs at all after this? Okay to do it in a separate PR just want to make a note if things have changed there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants