Capturing H264 with logitech C920 to OpenCV - c++

I’ve been trying to capture a H264 stream from my two C920 Logitech camera with OpenCV (On a Raspberry Pi 2). I have come to the conclusion that this is not possible because it is not yet implemented. I’ve looked a little in OpenCV/modules/highgui/cap_libv4l.cpp and found that the “Videocapture-function” always convert the pixelformat to BGR24. I tried to change this to h264, but only got a black screen. I guess this is because it is not being decoded the right way.
So I made a workaround using:
V4l2loopback
h264_v4l2_rtspserver
Gstreamer-0.10
(You can find the loopback and rtspserver on github)
First I setup a virtual device using v4l2loopback. Then the rtspserver captures in h264 then streams rtsp to my localhost(127.0.0.1). Then I catch it again with gstreamer and pipe it to my virtual v4l2 video device made by loopback using the “v4l2sink” option in gst-launch-0.10.
This solution works and I can actually connect to the virtual device with the opencv videocapture and get a full HD picture without overloading the cpu, but this is nowhere near a good enough solution. I get a roughly 3 second delay which is too high for my stereo vision application and it uses a ton of bandwidth.
So I was wondering if anybody knew a way that I could use the v4l2 capture program from Derek Molloys boneCV/capture program (which i know works) to capture in h264 then maybe pipe it to gst-launche-0.10 and then again pipe it to the v4l2sink for my virtual device?
(You can find the capture program here: https://github.com/derekmolloy/boneCV)
The gstreamer command I use is:
“gst-launch-0.10 rtspsrc location=rtsp://admin:pi#127.0.0.1:8554/unicast ! decodebin ! v4l2sink device=/dev/video4”
OR maybe in fact you know what I would change in the opencv highgui code to be able to capture h264 directly from my device without having to use the virtual device? That would be amazingly awesome!
Here is the links to loopback and the rtspserver that I use:
github.com/mpromonet/h264_v4l2_rtspserver
github.com/umlaeute/v4l2loopback
Sorry about the wierd links I don't have enough reputation yet to poste more links..

I don't know exactly where you need to change in the OpenCV, but very recently I started to code using video on Raspberry PI.
I'll share my findings with you.
I got this so far:
can read the C920 h264 stream directly from the camera using V4L2 API at 30 FPS (if you try to read YUYV buffers the driver has a limit of 10 fps, 5 fps or 2 fps from USB...)
can decode the stream to YUV 4:2:0 buffers using the broadcom chip from raspberry using OpenMax IL API
My Work In Progress code is at: GitHub.
Sorry about the code organization. But I think the abstraction I made is more readable than the plain V4L2 or OpenMAX code.
Some code examples:
Reading camera h264 using V4L2 Wrapper:
device.streamON();
v4l2_buffer bufferQueue;
while (!exit_requested){
//capture code
device.dequeueBuffer(&bufferQueue);
// use the h264 buffer inside bufferPtr[bufferQueue.index]
...
device.queueBuffer(bufferQueue.index, &bufferQueue);
}
device.streamOFF();
Decoding h264 using OpenMax IL:
BroadcomVideoDecode decoder;
while (!exit_requested) {
//capture code start
...
//decoding code
decoder.writeH264Buffer(bufferPtr[bufferQueue.index],bufferQueue.bytesused);
//capture code end
...
}

check out Derek Molloy on youtube. He's using a Beaglebone, but presumably ticks this box
https://www.youtube.com/watch?v=8QouvYMfmQo

Related

Sound capture hang/freeze during v4l2 VIDIOC_QBUF calls

I'm trying to capture sound with ALSA asound + video via v4l2 on raspberry pi, and separately it works fine. But on same time some audio frames loosing during VIDIOC_QBUF ioctl call:
ioctl(fd, VIDIOC_QBUF, &bufferinfo[i])
and capturing audio with
snd_pcm_readi (capture_handle, input_buffer_audio, audio_frames)
On every VIDIOC_QBUF snd_pcm_readi loose/hang for around ~300 audio frames. I'm also tried calling audio capture and video on separated test apps running on RPi, the problem also reproduced in this case.
I don't see and CPU overload or something indicating the problem (the load bellow < 12% on my RPi 3b). And the problem not reproduced on PC with linux with ALSA+v4l2 stack with the same camera (logitech c270).
On camera with 30 fps it's a big problem, because such big frames loose make sound laggy.

Is decoder automaticly added between two filter?

I have created a c++ dll where it shows camera live streaming at panel handle with DirectShow API. My Camera is Logitech c920 Webcam. My camera offers H264 codec on the 3rd output pin.
When I use graphEdit, if I connect the Logitech Webcam 3rd output Pin to Video Mixing Render 9 1st input pin, it automaticly adds the DTV-DVD microsoft decoder between the connection like this :
Logitech HD Pro Webcam C920 [Capturer] => [VMR Input0] Video Mixing Renderer 9
(When connected become)
Logitech HD Pro Webcam C920 [Capturer] => [video Input1] Microsoft DTV-DVD Video Decoder [video Output 1] => [VMR Input0] Video Mixing Renderer 9
The quality is very nice and I have a fast video streaming rates on the active movie window.
This is where it's getting incorrect. In my code, I have directly connected the 3rd pin of capture source to vmr7 input pin (without adding dt-dvd decoder). I have also set the video settings as 1600x896 and H264 Mediatype with IAMStreamConfig.
I readed on msdn (if i have understand correctly) that directshow will automaticly put the necessary filter between two connected pins. It's working but the video quality is terrible.It looks like theres lot pixels mixed or corrupted. I also don't have any evidence that the filter as been added. Is it because i haven't programmaticaly put the decoder between them? And if it could be, how do I add this filter?
Thanks in advance and sorry for the english.
The problem is here:
if I connect the Logitech Webcam 3rd output Pin to Video Mixing Render 9
versus
I have directly connected the 3rd pin of capture source to vmr7 input pin
VMR-9 vs. VMR-7. The former is backed by Direct3D surfaces, with frames scaled smoothly by hardware. The latter, on the opposite, uses DirectDraw surfaces with scaling unavailable since Windows Vista, and the picture quality is terrible.
Use EVR as video renderer (or VMR-9) to get best picture quality.

How to write an opencv image (IplImage) to a V4L2 loopback device?

As the title says I am not sure how to write an IplImage to a V4l2 loopback device. I know how to write to a device as I have posted here How to write/pipe to a virtual webcam created by V4L2loopback module?
But now I am not sure how I can exactly write IplImage objects in to the device. If I just write the image->imageData where image is an IplImage*, when I view the device using "luvcview" the malformed frames show up for about a second then it throws the following error.
luvcview 0.2.6
SDL information:
Video driver: x11
A window manager is available
Device information:
Device path: /dev/video3
Stream settings:
Frame format: YUYV (MJPG is not supported by device)
Frame size: 520x474 (requested size 640x480 is not supported by device)
Frame rate: 30 fps
libv4l2: error dequeuing buf: Invalid argument
Unable to dequeue buffer: Invalid argument
Error grabbing
Cleanup done. Exiting ...
Could it be because I have not converted the opencv images to v4l2 format? or the v4l2 arguments does not match with the IplImage properties? If so how to do it?
If anyone knows what this error means please let me know.
I decided to post this question separately as this question is not about writing to the device its particularly about write an IplImage to the device.
Could anyone please give me a code snippet that shows how to write an IplImage to a V4l2 loopback device?
I worked out that the above issue was not an issue anymore as it seems that luvcview or skype does not fully support v4l2. But if I view the loopback device using VLC player, it works fine.

stream video from panda board to IPhone

I am using panda board and i have installed opencv and wrote a code for sticking 3 different images from 3 different cams.now this stitched image is stored in a matrix location(pointer).i for that 3 cams images will be continuously captured and stitched.so it becomes a video.so i need to stream that stitched image to iPhone .can any one help me with this.i am really stuck here and need help.its very important for me.
I would suggest you look at constructing either mjpeg stream or better a RTSP (encapsulating mpeg4 - saving bandwidth) stream based on RTP protocol. Say you decide to go with mjpeg stream, then each of your opencv IplImage* can be converted to JPEG Frames using libjpeg compression. See my answer here Compressing IplImage to JPEG using libjpeg in OpenCV. You would compress each frame and then create mjpeg stream. See creating my own MJPEG stream. You would need a webserver to run mjpeg cgi that streams your image stream. You could look at lighttpd web server running on Panda Board. Gstreamer is the package that may be helpful in your situation. On the decoding side (iphone) you can construct gstreamer decoding pipeline as follows - say you are streaming mjpeg gst-launch -v souphttpsrc location="http://<ip>:<port>/cgi_bin/<mjpegcginame>.cgi" do-timestamp=true is_live=true ! multipartdemux ! jpegdec ! ffmpegcolorspace ! autovideosink

FFMpeg encoding RGB images to H264

I'm developing a DirectShow filter which has 2 input pins (1 for audio, 1 for video). I'm using libavcodec/libavformat/libavutil of FFMpeg for encoding the video to H264, audio to AAC and mux it/stream using RTP. So far I was able to encode video and audio correctly using libavcodec but now I see that FFMpeg seems to support RTP muxing too. Unfortunatelly, I can't find any example code which shows how to perform H264 encoding and RTP muxing. Does anybody know good samples?
Try checking out the code in HandBrake. Specifically, this file muxmp4.c, which was a jem I found working with FFMpeg / RTP. Be sure and use av_interleaved_write_frame() and the extradata fields correctly. Those were some key differences I remember for RTP.
Still, I had some stability issues with RTP/RTSP with FFMpeg, (I'm sure it's getting better). I had much better luck with live555, and you can look at the code in VLC and MPlayer for good examples on how to use it.