How to convert YUV frames to a video? - c++

How to convert set of YUV frames to a Video and later convert the video to YUV frames without any loss using C ?(I dont want to convert it to RGB in between)

if you have a raw YUV file, you need to tell ffmpeg which pixel format/subsampling that is used. YUV have no header, so you also need to specify the width and height of the data.
The following ffmpeg commands encodes a 1080p YUV 4:2:0 to H.264 using the x264 encoder and place the result in a mp4-container. This operation is however not losless.
ffmpeg -f rawvideo -pix_fmt yuv420p -s:v 1920x1080 -r 25 -i input.yuv \
-c:v libx264 output.mp4
To get the YUV-frames back again, do
ffmpeg -i output.mp4 frames.yuv
If you are looking for a lossless encoder, try HuffYUV or FFV1

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

Send H.264 encoded stream through RTMP using FFmpeg

I followed this to encode a sequences images to h.264 video.
Here is outputting part of my code:
int srcstride = outwidth*4;
sws_scale(convertCtx, src_data, &srcstride, 0, outheight, pic_in.img.plane, pic_in.img.i_stride);
x264_nal_t* nals;
int i_nals;
int frame_size = x264_encoder_encode(encoder, &nals, &i_nals, &pic_in, &pic_out);
if (frame_size) {
fwrite(nals[0].p_payload, frame_size, 1, fp);
}
This is in a loop to process frames and write them into a file.
Now, I'm trying to stream these encoded frames through RTMP. As I know, the container for the RTMP is FLV. So I used command line as a trial:
ffmpeg -i test.h264 -vcodec copy -f flv rtmp://localhost:1935/hls/test
This one works well as streaming a h.264 encoded video file.
But how can I implement it as C++ code and stream the frames at the same time when they are generated, just like what I did to stream my Facetime camera.
ffmpeg -f avfoundation -pix_fmt uyvy422 -video_size 1280x720 -framerate 30 -i "1:0" -pix_fmt yuv420p -vcodec libx264 -preset veryfast -acodec libvo_aacenc -f flv -framerate 30 rtmp://localhost:1935/hls/test
This may be a common and practical topic. But I'm stuck here for days, really need some relevant exprience. Thank you!

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.

Decode mJPEG to a format usable by libx264

I am compressing frames coming from webcam with libx264. So far I used YUY2 raw frames and swscale to transcode the frames to I420, which is usable by x264.
Anyway I would like to add support for mJPEG webcams (usually webcam provides both, but mJPEG allows higher frame rates and resolutions). What can I use to transcode mJPEG to some format, that can be used by x264?
If you already use swscale why not to use ffmpeg/libav (libavcodec) for decoding mjpeg?

How to write YUV 420 video frames from RGB data using OpenCV or other image processing library?

I have an array of rgb data generated from glReadPixels().
Note that RGB data is pixel packed (r1,g1,b1,r2,g2,b2,...).
How can I quickly write a YUV video frame using OpenCV or another C++ library, so that I can stream them to FFMPEG? Converting RGB pixel to YUV pixel is not a problem, as there are many conversion formula available online. However writing the YUV frame is the main problem for me. I have been trying to write the YUV video frame since the last few days and were not successful in doing that.
This is one of my other question about writing YUV frame and the issues that I encountered: Issue with writing YUV image frame in C/C++
I don't know what is wrong with my current approach in writing the YUV frame to a file.
So right now I may want to use existing library (if any), that accepts an RGB data, and convert them to YUV and write the YUV frame directly to a file or to a pipe. Of course it would be much better if I can fix my existing program to write the YUV frame, but you know, there is also a deadline in every software development project, so time is also a priority for me and my project team members.
FFmpeg will happily receive RGB data in. You can see what pixel formats FFmpeg supports by running:
ffmpeg -pix_fmts
Any entry with an I in the first column can be used as an input.
Since you haven't specified the pixel bit depth, I am going to assume it's 8-bit and use the rgb8 pixel format. So to get FFmpeg to read rgb8 data from stdin you would use the following command (I am cating data in but you would be supplying via your pipe):
cat data.rgb | ffmpeg -f rawvideo -pix_fmt rgb8 -s WIDTHxHEIGHT -i pipe:0 output.mov
Since it is a raw pixel format with no framing, you need to subsitite WIDTH and HEIGHT for the appropriate values of your image dimensions so that FFmpeg knows how to frame the data.
I have specifed the output as a MOV file but you would need to configure your FFmpeg/Red5 output accordingly.
OpenCV does not support the YUV format directly, as you know, so it's really up to you to find a way to do RGB <-> YUV conversions.
This is a very interesting post as it shows how to load and create YUV frames on the disk, while storing the data as IplImage.
ffmpeg will write an AVI file with YUV but as karl says there isn't direct support for it in openCV.
Alternatively (and possibly simpler) you can just write the raw UYVY values to a file and then use ffmpeg to convert it to an AVI/MP4 in any format you want. It's also possible to write directly to a pipe and call ffmpeg directly from your app avoiding the temporary yuv file
eg. to convert an HD yuv422 stream to a h264 MP4 file at 30fps
ffmpeg -pix_fmt yuyv422 -s 1920x1080 -i input.yuv -vcodec libx264 -x264opts -r 30 output.mp4