Video Frames in yuv format are encoded using X264 encoding, and h264 video frames are decoded using ffmpeg,
The previous blog introduced how to build and click the open link ffmpeg and x264 Development Environment on centos. The following is an example: 1. Video files in YUV format are encoded as video files in h264 format using the x264 library. 2. Video files in h264 format are decoded into video files in yuv format using the ffmpeh library. for comparison, yuv420p. yuv is the original file with a size of 77 MB encode. h264 is a video file encoded with H264, with a size of 1.4 M decode. yuv is the video file decoded by ffmpeg. The size is 77 MB. The compression ratio of h264 is obvious from the file size. Three files are played on the Windows platform, and the screen is completely different. The following is the code"
/* File: yuvTO264.c * Auth: sjin * Date: 20141115 * Mail: 413977243@qq.com * // use the x264 library to encode the YUV File as an h264 File **/# include <stdint. h> # include <x264.h> # include <stdio. h> # include <unistd. h> # include <fcntl. h> # include <stdlib. h> # include <string. h> # define CLEAR (x) (memset (& x), 0, sizeof (x ))) # define IMAGE_WIDTH 176 # define IMAGE_HEIGHT 144 # define ENCODER_PRESET "veryfast"/* Configuration Parameter * uses the default parameter. Here the zerolatency option is used. After that, * delayed_frames will not exist. If not, the cached * Encoding Frame */# define ENCODER_TUNE "zerolatency" # define ENCODER_PROFILE "baseline" # define ENCODER_COLORSPACE into struct limit {x264_param_t * x1__parameter; char parameter_preset [20]; char parameter_tune [20]; char parameter_profile [20]; x1__t * x1__encoder; x1__picture_t * yuv420p_picture; long colorspace; unsigned char * Yuv; x1__nal_t * nal;} my_x1__encoder; char * read_filename = "yuv420p. yuv "; char * write_filename =" encode. h264 "; int main (int argc, char ** argv) {int ret; int fd_read, fd_write; optional * encoder = (my_x1__encoder *) malloc (sizeof (my_x1__encoder )); if (! Encoder) {printf ("cannot malloc my_x264_encoder! \ N "); exit (EXIT_FAILURE);} CLEAR (* encoder ); /*************************************** * *********************************** Advanced parameter handling functions ************************************** **************************************// * These functions expose the full power of x264's preset-tune-profile system for * easy adjustment of large numbers // free (encoder-> yuv420p_picture ); of interna L parameters. ** In order to replicate x264CLI's option handling, these functions MUST be called * in the following order: * 1) x264_param_default_preset * 2) custom user options (via param_parse or directly assigned variables) * 3) xpai_param_apply_fastfirstpass * 4) xpai_param_apply_profile ** Additionally, xforwarcli does not apply step 3 if the preset chosen is "placebo" * or -- slow-firstpass I S set. */strcpy (encoder-> parameter_preset, ENCODER_PRESET); strcpy (encoder-> parameter_tune, parameters); encoder-> x264_parameter = (parameters *) malloc (sizeof (parameters )); if (! Encoder-> x264_parameter) {printf ("malloc x264_parameter error! \ N "); exit (EXIT_FAILURE);}/* initialize the encoder */CLEAR (* (encoder-> x1__parameter); x1__param_default (encoder-> x1__parameter ); if (ret = xforwar_param_default_preset (encoder-> xforwar_parameter, encoder-> parameter_preset, encoder-> parameter_tune) <0) {printf ("xforwar_param_default_preset error! \ N "); exit (EXIT_FAILURE);}/* cpuFlags go to the empty buffer and continue to use the undead lock to ensure */encoder-> x1__parameter-> I _threads = x1__sync_lookahead_auto; /* video options */encoder-> x1__parameter-> I _width = IMAGE_WIDTH; // encoder-> x1__parameter-> I _height = IMAGE_HEIGHT; // The height of the image to be encoded. encoder-> x1__parameter-> I _frame_total = 0; // The total number of frames to be encoded. I do not know whether to use 0 encoder-> x1__parameter-> I _keyint_max = 25; /* stream parameter */encoder-> x1__parameter-> I _bframe = 5; encoder-> X1__parameter-> B _open_gop = 0; encoder-> x1__parameter-> I _bframe_pyramid = 0; encoder-> x1__parameter-> I _bframe_adaptive = signature;/* log parameter, comment out */encoder-> x1__parameter-> I _log_level = x1__log_debug; encoder-> x1__parameter-> I _fps_den = 1; // bitrate denominator encoder-> x1__parameter-> I _fps_num = 25; // bitrate molecule encoder-> x1__parameter-> priority = 1; encoder-> x1__parameter-> B _1_ B = 1; strcp Y (encoder-> parameter_profile, ENCODER_PROFILE); if (ret = x264_param_apply_profile (encoder-> x264_parameter, encoder-> parameter_profile) <0) {printf ("temperature error! \ N "); exit (EXIT_FAILURE);}/* encoder */encoder-> x1__encoder = x1__encoder_open (encoder-> x1__parameter); encoder-> colorspace = ENCODER_COLORSPACE; /* initialize pic */encoder-> yuv420p_picture = (x264_picture_t *) malloc (sizeof (x264_picture_t); if (! Encoder-> yuv420p_picture) {printf ("malloc encoder-> yuv420p_picture error! \ N "); exit (EXIT_FAILURE);} if (ret = x264_picture_alloc (encoder-> yuv420p_picture, encoder-> colorspace, IMAGE_WIDTH, IMAGE_HEIGHT) <0) {printf ("ret = % d \ n", ret); printf ("x264_picture_alloc error! \ N "); exit (EXIT_FAILURE);} encoder-> yuv420p_picture-> img. I _csp = encoder-> colorspace; encoder-> yuv420p_picture-> img. I _plane = 3; encoder-> yuv420p_picture-> I _type = x1__type_auto;/* apply for YUV buffer */encoder-> yuv = (uint8_t *) malloc (IMAGE_WIDTH * IMAGE_HEIGHT * 3/2 ); if (! Encoder-> yuv) {printf ("malloc yuv error! \ N "); exit (EXIT_FAILURE);} CLEAR (* (encoder-> yuv); encoder-> yuv420p_picture-> img. plane [0] = encoder-> yuv; encoder-> yuv420p_picture-> img. plane [1] = encoder-> yuv + IMAGE_WIDTH * IMAGE_HEIGHT; encoder-> yuv420p_picture-> img. plane [2] = encoder-> yuv + IMAGE_WIDTH * IMAGE_HEIGHT/4; if (fd_read = open (read_filename, O_RDONLY) <0) {printf ("cannot open input file! \ N "); exit (EXIT_FAILURE);} if (fd_write = open (write_filename, O_WRONLY | O_APPEND | O_CREAT, 0777) <0) {printf ("cannot open output file! \ N "); exit (EXIT_FAILURE);} int n_nal = 0; Define pic_out; x1__nal_t * my_nal; encoder-> nal = (x1__nal_t *) malloc )); if (! Encoder-> nal) {printf ("malloc x1__nal_t error! \ N "); exit (EXIT_FAILURE);} CLEAR (* (encoder-> nal);/* encoding */while (read (fd_read, encoder-> yuv, IMAGE_WIDTH * IMAGE_HEIGHT * 3/2)> 0) {encoder-> yuv420p_picture-> I _pts ++; if (ret = x264_encoder_encode (encoder-> x264_encoder, & encoder-> nal, & n_nal, encoder-> yuv420p_picture, & pic_out) <0) {printf ("x1__encoder_encode error! \ N "); exit (EXIT_FAILURE) ;}for (my_nal = encoder-> nal; my_nal <encoder-> nal + n_nal; ++ my_nal) {write (fd_write, my_nal-> p_payload, my_nal-> I _payload) ;}} free (encoder-> yuv); free (encoder-> yuv420p_picture); free (encoder-> x1__parameter ); x1__encoder_close (encoder-> x1__encoder); free (encoder); close (fd_read); close (fd_write); return 0 ;}
/* File: decode_h264.c * Auth: sjin * Date: 20141115 * Mail: 413977243@qq.com * // * decodes h264 into yuv File */# include <stdio. h> # include <string. h> # include <stdlib. h> # include <fcntl. h> # include <unistd. h> # include <libavcodec/avcodec. h> # include <libavformat/avformat. h> # include <libavutil/mathematics. h> # define DECODED_OUTPUT_FORMAT AV_PIX_FMT_YUV420P # define INPUT_FILE_NAME "encode. h264 "# define OUTPUT_FILE_NAME" de Code. yuv "/* h264 file width and height, must be consistent with the actual width and height * otherwise an error will occur **/# define IMAGE_WIDTH 176 # define IMAGE_HEIGHT 144 void error_handle (const char * errorInfo) {printf ("% s error! \ N ", errorInfo); exit (EXIT_FAILURE);} int main (int argc, char ** argv) {int write_fd, ret, videoStream; AVFormatContext * formatContext = NULL; AVCodec * codec; AVCodecContext * codecContext; AVFrame * decodedFrame; AVPacket packet; uint8_t * blocks; unsigned int blocks; int finishedFrame; // initialize environment partition (); write_fd = open (OUTPUT_FILE_NAME, o_RDWR | O_CREAT, 0666); if (write_fd <0) {perror ("open "); Exit (1);} ret = avformat_open_input (& formatContext, INPUT_FILE_NAME, NULL, NULL); if (ret <0) error_handle ("avformat_open_input error "); ret = avformat_find_stream_info (formatContext, NULL); if (ret <0) error_handle ("av_find_stream_info"); // print the detailed information of the input file av_dump_format (formatContext, 0, INPUT_FILE_NAME, 0); videoStream = 0; codecContext = formatContext-> streams [videoStream]-> codec; codec = avcodec_find_decoder (AV_C ODEC_ID_H264); if (codec = NULL) error_handle ("avcodec_find_decoder error! \ N "); ret = avcodec_open2 (codecContext, codec, NULL); if (ret <0) error_handle (" avcodec_open2 "); // allocate the space to save the video frame. decodedFrame = avcodec_alloc_frame (); if (! DecodedFrame) error_handle ("avcodec_alloc_frame! "); // Allocate the decoded video frame space decodedBufferSize = watermark (DECODED_OUTPUT_FORMAT, IMAGE_WIDTH, IMAGE_HEIGHT); decodedBuffer = (uint8_t *) malloc (decodedBufferSize); if (! DecodedBuffer) error_handle ("malloc decodedBuffer error! "); Av_init_packet (& packet); while (av_read_frame (formatContext, & packet) >=0) {ret = avcodec_decode_video2 (codecContext, decodedFrame, & finishedFrame, & packet ); if (ret <0) error_handle ("avcodec_decode_video2 error! "); If (finishedFrame) {transform (AVPicture *) decodedFrame, DECODED_OUTPUT_FORMAT, IMAGE_WIDTH, IMAGE_HEIGHT, decodedBuffer, watermark); ret = write (write_fd, decodedBuffer, watermark ); if (ret <0) error_handle ("write yuv stream error! ");} Av_free_packet (& packet);}/* prevent Frame loss after video decoding */while (1) {packet. data = NULL; packet. size = 0; ret = avcodec_decode_video2 (codecContext, decodedFrame, & finishedFrame, & packet); if (ret <= 0 & (finishedFrame <= 0) break; if (finishedFrame) {destroy (AVPicture *) decodedFrame, DECODED_OUTPUT_FORMAT, IMAGE_WIDTH, IMAGE_HEIGHT, decodedBuffer, decodedBufferSize); ret = write (write_fd, decodedBuffer, decodedBufferSize); If (ret <0) error_handle ("write yuv stream error! ");} Av_free_packet (& packet);} avformat_close_input (& formatContext); free (decodedBuffer); av_free (decodedFrame); avcodec_close (codecContext); return 0 ;}Makefile:
# use pkg-config for getting CFLAGS and LDLIBSFFMPEG_LIBS= libavdevice \ libavformat \ libavfilter \ libavcodec \ libswresample \ libswscale \ libavutil \CFLAGS += -Wall -O2 -gCFLAGS := $(shell pkg-config --cflags $(FFMPEG_LIBS)) $(CFLAGS)LDLIBS := $(shell pkg-config --libs $(FFMPEG_LIBS)) $(LDLIBS)EXAMPLES= decode_h264 yuvTO264 OBJS=$(addsuffix .o,$(EXAMPLES))# the following examples make explicit use of the math libraryLDLIBS += -lx264 -m32 -pthread -lm -ldl.phony:all cleanall: $(OBJS) $(EXAMPLES)clean:rm $(EXAMPLES) $(OBJS)
References: References
1. http://blog.csdn.net/liushu1231/article/details/9203239
2. http://www.cnblogs.com/fojian/archive/2012/09/01/2666627.html
3. http://stackoverflow.com/questions/2940671/how-does-one-encode-a-series-of-images-into-h264-using-the-x264-c-api
4, http://blog.yikuyiku.com /? P = 3486