x264 encoder
Basic example that shows how you can use the x264 library and the libswscale library. You can download all files from this gist, just click the download button there;
X264Encoder.h
/* # X264Encoder Simple wrapper for x264 that you can use to encode into x264. Make sure to set all the params before calling `open()`. See belwo for the members that the you need to set. */ #ifndef ROXLU_X264_ENCODER_H #define ROXLU_X264_ENCODER_H #include <inttypes.h> #include <stdio.h> #include <string> extern "C" { # include <x264.h> # include <libswscale/swscale.h> # include <libavcodec/avcodec.h> } class X264Encoder { public: X264Encoder(); ~X264Encoder(); bool open(std::string filename, bool datapath); /* open for encoding */ bool encode(char* pixels); /* encode the given data */ bool close(); /* close the encoder and file, frees all memory */ private: bool validateSettings(); /* validates if all params are set correctly, like width,height, etc.. */ void setParams(); /* sets the x264 params */ public: /* params the user should set */ int in_width; int in_height; int out_width; int out_height; int fps; /* e.g. 25, 60, etc.. */ AVPixelFormat in_pixel_format; AVPixelFormat out_pixel_format; /* x264 */ AVPicture pic_raw; /* used for our "raw" input container */ x264_picture_t pic_in; x264_picture_t pic_out; x264_param_t params; x264_nal_t* nals; x264_t* encoder; int num_nals; /* input / output */ int pts; struct SwsContext* sws; FILE* fp; }; #endif
X264Encoder.cpp
#include <roxlu/core/Log.h> #include <roxlu/core/Utils.h> #include <video/X264Encoder.h> X264Encoder::X264Encoder() :in_width(0) ,in_height(0) ,in_pixel_format(AV_PIX_FMT_NONE) ,out_width(0) ,out_height(0) ,out_pixel_format(AV_PIX_FMT_NONE) ,fps(25) ,fp(NULL) ,encoder(NULL) ,sws(NULL) ,num_nals(0) ,pts(0) { memset((char*)&pic_raw, 0, sizeof(pic_raw)); } X264Encoder::~X264Encoder() { if(sws) { close(); } } bool X264Encoder::open(std::string filename, bool datapath) { if(!validateSettings()) { return false; } int r = 0; int nheader = 0; int header_size = 0; // @todo add validate which checks if all params are set (in/out width/height, fps,etc..); if(encoder) { RX_ERROR("Already opened. first call close()"); return false; } if(out_pixel_format != AV_PIX_FMT_YUV420P) { RX_ERROR("At this moment the output format must be AV_PIX_FMT_YUV420P"); return false; } sws = sws_getContext(in_width, in_height, in_pixel_format, out_width, out_height, out_pixel_format, SWS_FAST_BILINEAR, NULL, NULL, NULL); if(!sws) { RX_ERROR("Cannot create SWS context"); ::exit(EXIT_FAILURE); } if(datapath) { filename = rx_to_data_path(filename); } fp = fopen(filename.c_str(), "w+b"); if(!fp) { RX_ERROR("Cannot open the h264 destination file"); goto error; } x264_picture_alloc(&pic_in, X264_CSP_I420, out_width, out_height); setParams(); // create the encoder using our params encoder = x264_encoder_open(¶ms); if(!encoder) { RX_ERROR("Cannot open the encoder"); goto error; } // write headers r = x264_encoder_headers(encoder, &nals, &nheader); if(r < 0) { RX_ERROR("x264_encoder_headers() failed"); goto error; } header_size = nals[0].i_payload + nals[1].i_payload +nals[2].i_payload; if(!fwrite(nals[0].p_payload, header_size, 1, fp)) { RX_ERROR("Cannot write headers"); goto error; } pts = 0; return true; error: close(); return false; } bool X264Encoder::encode(char* pixels) { if(!sws) { RX_ERROR("Not initialized, so cannot encode"); return false; } // copy the pixels into our "raw input" container. int bytes_filled = avpicture_fill(&pic_raw, (uint8_t*)pixels, in_pixel_format, in_width, in_height); if(!bytes_filled) { RX_ERROR("Cannot fill the raw input buffer"); return false; } // convert to I420 for x264 int h = sws_scale(sws, pic_raw.data, pic_raw.linesize, 0, in_height, pic_in.img.plane, pic_in.img.i_stride); if(h != out_height) { RX_ERROR("scale failed: %d", h); return false; } // and encode and store into pic_out pic_in.i_pts = pts; int frame_size = x264_encoder_encode(encoder, &nals, &num_nals, &pic_in, &pic_out); if(frame_size) { if(!fwrite(nals[0].p_payload, frame_size, 1, fp)) { RX_ERROR("Error while trying to write nal"); return false; } } ++pts; return true; } bool X264Encoder::close() { if(encoder) { x264_picture_clean(&pic_in); memset((char*)&pic_in, 0, sizeof(pic_in)); memset((char*)&pic_out, 0, sizeof(pic_out)); x264_encoder_close(encoder); encoder = NULL; } if(sws) { sws_freeContext(sws); sws = NULL; } memset((char*)&pic_raw, 0, sizeof(pic_raw)); if(fp) { fclose(fp); fp = NULL; } return true; } void X264Encoder::setParams() { x264_param_default_preset(¶ms, "ultrafast", "zerolatency"); params.i_threads = 1; params.i_width = out_width; params.i_height = out_height; params.i_fps_num = fps; params.i_fps_den = 1; } bool X264Encoder::validateSettings() { if(!in_width) { RX_ERROR("No in_width set"); return false; } if(!in_height) { RX_ERROR("No in_height set"); return false; } if(!out_width) { RX_ERROR("No out_width set"); return false; } if(!out_height) { RX_ERROR("No out_height set"); return false; } if(in_pixel_format == AV_PIX_FMT_NONE) { RX_ERROR("No in_pixel_format set"); return false; } if(out_pixel_format == AV_PIX_FMT_NONE) { RX_ERROR("No out_pixel_format set"); return false; } return true; }
NAT Types
Building Cabinets
Compiling GStreamer from source on Windows
Debugging CMake Issues
Dual Boot Arch Linux and Windows 10
Mindset Updated Edition, Carol S. Dweck (Book Notes)
How to setup a self-hosted Unifi NVR with Arch Linux
Blender 2.8 How to use Transparent Textures
Compiling FFmpeg with X264 on Windows 10 using MSVC
Blender 2.8 OpenGL Buffer Exporter
Blender 2.8 Baking lightmaps
Blender 2.8 Tips and Tricks
Setting up a Bluetooth Headset on Arch Linux
Compiling x264 on Windows with MSVC
C/C++ Snippets
Reading Chunks from a Buffer
Handy Bash Commands
Building a zero copy parser
Kalman Filter
Saving pixel data using libpng
Compile Apache, PHP and MySQL on Mac 10.10
Fast Pixel Transfers with Pixel Buffer Objects
High Resolution Timer function in C/C++
Rendering text with Pango, Cairo and Freetype
Fast OpenGL blur shader
Spherical Environment Mapping with OpenGL
Using OpenSSL with memory BIOs
Attributeless Vertex Shader with OpenGL
Circular Image Selector
Decoding H264 and YUV420P playback
Fast Fourier Transform
OpenGL Rim Shader
Rendering The Depth Buffer
Delaunay Triangulation
RapidXML
Git Snippets
Basic Shading With OpenGL
Open Source Libraries For Creative Coding
Bouncing particle effect
OpenGL Instanced Rendering
Mapping a texture on a disc
Download HTML page using CURL
Height Field Simulation on GPU
OpenCV
Some notes on OpenGL
Math
Gists to remember
Reverse SSH
Working Set
Consumer + Producer model with libuv
Parsing binary data
C++ file operation snippets
Importance of blur with image gradients
Real-time oil painting with openGL
x264 encoder
Generative helix with openGL
Mini test with vector field
Protractor gesture recognizer
Hair simulation
Some glitch screenshots
Working on video installation
Generative meshes
Converting video/audio using avconv
Auto start terminal app on mac
Export blender object to simple file format