The simplest Video Encoder Based on FFmpeg-new version (YUV encoding is HEVC (H.265 ))
An example of a video encoder based on FFmpeg was created a while ago:
The simplest Video Encoder Based on FFMPEG (YUV encoding: H.264)
In this example, YUV pixel data (YUV420P) can be encoded as H.264 code streams. Because FFmpeg now supports libx265, the above example of H.264 encoding is upgraded to H.265 (HEVC.
The earlier FFmpeg class library (about a few months ago, my Compilation Time is 5.4.05.06) has a problem with H.265 encoding support. When I started debugging, I thought there was a problem with my code. After several modifications, I did not find a solution. The problem was finally found to be a problem with the class library itself. The problem was solved after the new version of the class library was changed (I compile the time here is 4.04.09.16.
Process
The following is a flowchart of the FFmpeg video. This process not only can encode the H.264/H.265 code streams, but also can encode MPEG4/MPEG2/VP9/VP8 and other code streams. In fact, FFmpeg is used to encode videos in the same way. In the figure, the blue background function is the function that actually outputs data. The Light Green function is the video encoding function.
Briefly introduce the meaning of each function in the process (the previous YUV code was written in H.264. copy and paste it here ):
Av_register_all (): registers all the codecs of FFmpeg.
Avformat_alloc_output_context2 (): Initialize AVFormatContext of the output code stream.
Avio_open (): Open the output file.
Av_new_stream (): creates an AVStream of the output code stream.
Avcodec_find_encoder (): Find the encoder.
Avcodec_open2 (): Enable the encoder.
Avformat_write_header (): Write a file header (this function is not required for some encapsulation formats without a file header. For example, MPEG2TS ).
Avcodec_encode_video2 (): encode a video. Encode AVFrame (storing YUV pixel data) into AVPacket (storing stream data in H.264 and other formats ).
Av_write_frame (): Write the encoded video stream to a file.
Flush_encoder (): This function is called after the input pixel data is read. Used to output the remaining AVPacket In the encoder.
Av_write_trailer (): Write the end of a file (this function is not required for some encapsulation formats without a file header. For example, MPEG2TS ).
Directly paste the code below the code
/*** The Simplest FFmpeg-Based Video Encoder ** Simplest FFmpeg Video Encoder ** leixiao Lei Xiaohua * leixiaohua1020@126.com * China Media University/Digital TV technology * Communication University of China/ digital TV Technology * http://blog.csdn.net/leixiaohua1020 ** this program implements the YUV pixel data encoding for video streams (HEVC (H.265 ), h264, MPEG2, VP8, etc ). * Is the simplest tutorial on FFmpeg video encoding. * By studying this example, you can understand the FFmpeg encoding process. * This software encode YUV420P data to HEVC (H.265) bitstream (or * H. 264, MPEG2, VP8 etc .). * It's the simplest video encoding software based on FFmpeg. * Suitable for beginner of FFmpeg */# include
Extern "C" {# include "libavutil \ opt. h "# include" libavcodec \ avcodec. h "# include" libavformat \ avformat. h "# include" libswscale \ swscale. h "}; int flush_encoder (AVFormatContext * fmt_ctx, unsigned int stream_index) {int ret; int got_frame; AVPacket enc_pkt; if (! (Fmt_ctx-> streams [stream_index]-> codec-> capabilities & CODEC_CAP_DELAY) return 0; while (1) {printf ("Flushing stream # % u encoder \ n", stream_index); // ret = encode_write_frame (NULL, stream_index, & got_frame); enc_pkt.data = NULL; enc_pkt.size = 0; av_init_packet (& enc_pkt); ret = avcodec_encode_video2 (fmt_ctx-> streams [stream_index]-> codec, & enc_pkt, NULL, & got_frame); av_frame_free (NULL ); if (ret <0) B Reak; if (! Got_frame) {ret = 0; break;} printf ("Succeed to encode 1 frame! Encoding successful 1 frame! \ N ");/* mux encoded frame */ret = av_write_frame (fmt_ctx, & enc_pkt); if (ret <0) break;} return ret ;} int main (int argc, char * argv []) {AVFormatContext * pFormatCtx; AVOutputFormat * fmt; AVStream * video_st; AVCodecContext * pCodecCtx; AVCodec * pCodec; uint8_t * picture_buf; AVFrame * picture; int size; // FILE * in_file = fopen ("src0415480x272.yuv", "rb"); // Input YUV data video YUV source FILE * in_file = fopen ("ds_480x272.yu V "," rb "); // Input YUV data video YUV source file int in_w = 480, in_h = 272; // width/height // Frames to encodeint framenum = 100; // const char * out_file = "src01.h264"; // Output Filepath Output file path // const char * out_file = "src01.ts"; // const char * out_file = "src01.hevc "; const char * out_file = "ds. hevc "; av_register_all (); // Method1 method 1. combined use several functions pFormatCtx = avformat_alloc_context (); // Guess Format fmt = av_guess_format (NULL, out_file, NULL); pFormatCtx-> oformat = fmt; // Method 2 Method 2. more automated // avformat_alloc_output_context2 (& pFormatCtx, NULL, NULL, out_file); // fmt = pFormatCtx-> oformat; // Output Format pay attention to the output path if (avio_open (& pFormatCtx-> pb, out_file, AVIO_FLAG_READ_WRITE) <0) {printf ("Failed to open Output file! Failed to open the output file "); return-1;} video_st = avformat_new_stream (pFormatCtx, 0); video_st-> time_base.num = 1; video_st-> time_base.den = 25; if (video_st = NULL) {return-1 ;}// Param that must setpCodecCtx = video_st-> codec; // pCodecCtx-> codec_id = AV_CODEC_ID_HEVC; pCodecCtx-> codec_id = fmt-> video_codec; pCodecCtx-> codec_type = AVMEDIA_TYPE_VIDEO; pCodecCtx-> pix_fmt = bytes; pCodecCtx-> width = in_w; pCodecCtx -> Height = in_h; pCodecCtx-> time_base.num = 1; pCodecCtx-> time_base.den = 25; pCodecCtx-> bit_rate = 400000; pCodecCtx-> gop_size = 250; // H264 // pCodecCtx-> me_range = 16; // pCodecCtx-> max_qdiff = 4; // pCodecCtx-> qcompress = 0.6; pCodecCtx-> qmin = 10; pCodecCtx-> qmax = 51; // Optional ParampCodecCtx-> max_ B _frames = 3; // Set OptionAVDictionary * param = 0; // h.2if (pCodecCtx-> codec_id = Hangzhou) {av_dict _ Set (? M, "preset", "slow", 0); av_dict_set (? M, "tune", "zerolatency", 0);} // H.265if (pCodecCtx-> codec_id = AV_CODEC_ID_H265) {av_dict_set (? M, "x265-params", "qp = 20", 0); av_dict_set (? M, "preset", "ultrafast", 0); av_dict_set (? M, "tune", "zero-latency", 0);} // Dump Information output format Information av_dump_format (pFormatCtx, 0, out_file, 1 ); pCodec = avcodec_find_encoder (pCodecCtx-> codec_id); if (! PCodec) {printf ("Can not find encoder! No suitable encoder found! \ N "); return-1;} if (avcodec_open2 (pCodecCtx, pCodec ,? M) <0) {printf ("Failed to open encoder! An error occurred while enabling the encoder! \ N "); return-1;} picture = avcodec_alloc_frame (); size = avpicture_get_size (pCodecCtx-> pix_fmt, pCodecCtx-> width, pCodecCtx-> height ); picture_buf = (uint8_t *) av_malloc (size); watermark (AVPicture *) picture, picture_buf, pCodecCtx-> pix_fmt, pCodecCtx-> width, pCodecCtx-> height ); // Write File Header avformat_write_header (pFormatCtx, NULL); AVPacket pkt; int y_size = pCodecCtx-> width * pCodecCtx-> hei Ght; av_new_packet (& pkt, y_size * 3); for (int I = 0; I <framenum; I ++) {// Read YUV to Read YUVif (fread (picture_buf, 1, y_size * 3/2, in_file) <0) {printf ("Failed to read YUV data! File Read error \ n "); return-1;} else if (feof (in_file) {break;} picture-> data [0] = picture_buf; // brightness Ypicture-> data [1] = picture_buf + y_size; // U picture-> data [2] = picture_buf + y_size * 5/4; // V // PTSpicture-> pts = I; int got_picture = 0; // Encode: int ret = avcodec_encode_video2 (pCodecCtx, & pkt, picture, & got_picture ); if (ret <0) {printf ("Failed to encode! Encoding Error! \ N "); return-1;} if (got_picture = 1) {printf (" Succeed to encode 1 frame! Encoding successful 1 frame! \ N "); pkt. stream_index = video_st-> index; ret = av_write_frame (pFormatCtx, & pkt); av_free_packet (& pkt) ;}// Flush Encoderint ret = flush_encoder (pFormatCtx, 0 ); if (ret <0) {printf ("Flushing encoder failed \ n"); return-1;} // Write file trailer Write the end Of the file av_write_trailer (pFormatCtx ); // Clean if (video_st) {avcodec_close (video_st-> codec); av_free (picture); av_free (picture_buf);} avio_close (pFormatCtx-> pb ); avformat_free_context (pFormatCtx); fclose (in_file); return 0 ;}
Result
Software running (limited by the file volume, the number of original YUV frames is only 100 ):
This time I changed an interesting YUV sequence. I have been tired of reading the YUV standard test sequence before. The sequence in this new TV series is more vivid. Shows the YUV sequence.
The encoded HEVC (H.265) code stream:
Download
SourceForge Project address:
Https://sourceforge.net/projects/simplestffmpegvideoencoder/
CSDN:
Http://download.csdn.net/detail/leixiaohua1020/8001515