cv::VideoWriter yields unreadable video - c++

I want to produce a video file out of a stream of RGB images flowing at 52fps. I found the opencv api pretty handy to use (cv::VideoWriter). The problem is that I can play the produced avi only with VLC; which plays the video but yells:
[0x28307b0] xcb_xv generic error: no available XVideo adaptor
Any other video player (on the same computer) is not able to read and play the video.
While recording everything looks ok: I get information about the output, about the size of the frame, the video codec, the fps, etc...no error.
Output #0, avi, to '01-23-12_15-24-51.avi':
Stream #0.0: Video: flv, yuv420p, 500x242, q=2-31, 7744 kb/s, 90k tbn, 52tbc
As OpenCv only supports avi as video container, the only thing I could change is the video codec, I tried (FOURCC code) FLV1, DIVX, DIV3 but none of them works correctly.
I would like to play this video with any video player on different computers. How can I make it work? is VideoWriter the right choice?
Any suggestion is very welcome.
Thanks.

If you have a video source for your images, it would be a good idea to use the same codec for output:
int videoType = (int)cap.get(CV_CAP_PROP_FORMAT);
VideoWriter vout;
vout.open(videofile + "_out.avi", videoType, 30, imgSize);
Or, you can try an older, simpler FOURCC. Or a Microsoft-specific, if you want to run it only on Windows.

Related

Encoding uncompressed avi using RAWVIDEO codec and RGB24

I coded an encoder using FFMPEG (c++). The requirements for this encoder are:
The output format should be uncompressed avi,
Preferably using RGB24/YUV444 pixel format since we do not want chroma subsampling.
Most standard players should support the format (windows media player (WMP), VLC)
Using the encoder I wrote, I can write a number of file types right now:
Lossless H.264 encoded video using the YUV420p pixel format and AVI container. (Obviously not uncompressed and chroma subsampled, however both WMP and VLC play without any problem.)
MPEG4 encoded video using the YUV420p pixel format and AVI container.(Obviously not uncompressed and chroma subsampled, however both WMP and VLC play without any problem.)
AYUV encoded video using the YUVA444P pixel format. (uncompressed as far as I understand and not chroma subsampled. However, VLC does not play this.)
FFV1 encoded video using the YUV444P pixel format. (lossless, and not chroma subsampled. However, WMP does not play this.)
The above is derived from this very usefull post.
So I am now looking into the RAWVIDEO encoder from FFMPEG. I can't get this to work and neither can I find an example in the FFMPEG documentation on how to use this encoder for writing video. Can somebody point me in the right direction or supply sample code for this?
Also, if there is another direction I should follow to meet my requirements feel free to point me to it.
Thanks in advance

Error while saving video as MP4 using videoWriter(OpenCV) in Ubuntu

I am trying to save a video file as MP4 format in ubuntu16.04 using videoWriter function as below
int frame_width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
int frame_height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
VideoWriter video("/home/Desktop/1.mp4",CV_FOURCC('M','J','P','G'),10, Size(frame_width,frame_height));
But I am getting the error as below:
OpenCV: FFMPEG: tag 0x47504a4d/'MJPG' is not supported with codec id 8 and format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x0000006c/'l???
When I change my output file extension to .avi, I get no error but VLC player doesn't display any video. I tried different players also but in vain.
I even did the following thinking my VLC might be a problem but didn't work. Really in need of a solution
sudo apt-get ubuntu-restricted-extras
As per this link, Writing x264 from OpenCV 3 with FFmpeg on Linux the terminal message
OpenCV: FFMPEG: tag 0x47504a4d/'MJPG' is not supported with codec id 8 and format 'mp4 / MP4 (MPEG-4 Part 14)' is not an error but a warning that the codec type is incompatible with ffmpeg and mp4 container. However, it does generate the output videofile.
If MJPG codec does not matter to you, then try to replace it with 0x21 and check the output.
VideoWriter video("/home/Desktop/1.mp4",0x21,10, Size(frame_width,frame_height));
If your video still does not play then probably, your VideoWriter is not writing any frames to video. You can check if there are any frames in the written output video by your algorithm.
For more clarifications you can check the VideoWriter class refernce https://docs.opencv.org/3.4.3/dd/d9e/classcv_1_1VideoWriter.html
Thanks

Does LAV Filter do the YUV to RGB conversion

I would like to improve decoding H.264 video stream with MPC-HC using LAV video decoder.
The stream I will play back is always in format yuvj444p (Planar YCbCr 4:4:4 in TV level [0-255]), encoded with x264.
I'm using MPC-HC version 1.7.10, and LAV video decoder 0.68.1
I have a nVidia Quadro K5200, and I know how to write GLSL shader to run YUV to RGB conversion.
I'm wondering if someone here could give me a hint if it's worth doing such job, and possibly on where to start.
Should I customize the EVR (Enhanced Video Renderer - Custom Presenter) ?
Should I just write an internal shader?
...
Yes, LAV Video Decoder filter does support yuvj444p to RGB32 color conversion.
In order to prove it, I have tried the following test:
Create uncompressed AVI file in RGB color format (using MATLAB).
Convert the AVI file to x264 compressed MKV file in yuvj444p color format (using FFMPEG).
Build a filter graph in Graph Studio Next, with LAV Video Decoder (DirectShow) filter.
Inspect the output pin of Decoder filter.
Play the graph, and compare the output frame to original input frame.
Input AVI file name: RGB_INPUT.avi
MKV file name: OUTPUT.mkv
I used ffmpeg with the following parameters (in command line):
ffmpeg -i RGB_INPUT.avi -pix_fmt yuvj444p -vf scale=w=0:h=0:out_color_matrix=bt709 -c:v libx264 -crf 18 -x264opts colorprim=bt709:transfer=bt709:colormatrix=bt709 -an OUTPUT.mkv
I took the example from here: http://forum.doom9.org/showthread.php?p=1671195
Filter Graph:
Inspecting the output pin of LAV Video Decoder, shows that output color format is RGB32 (media sub-type is: MEDIASUBTYPE_RGB32):
Comparing uncompressed input frame, to decoded output frame:
Source frame (uncompressed image):
Video Renderer output (screenshot):
Absolute difference image (scaled by 10):
Conclusion: LAV Video Decoder correctly convert yuvj444 to RGB32.

Capturing H264 with logitech C920 to OpenCV

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

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.