This article introduces a simple Video Encoder Based on FFMPEG. The yuv420p pixel data is encoded as H.264 compressed data. The code of the encoder is very simple, but every line of code is very important. It is suitable for a good study. After the code is clarified, the encoding process of FFmpeg is basically clarified. Although I have already completed the program, I still haven't made it clear in some places. I need to continue to explore and add content.
This program uses the latest version of the Class Library (the Compilation Time is 2014.5.6), and the development platform is vc2010. All the configurations have been completed and only need to be executed.
Flowchart (updated on January 29)
The following is a flowchart of video encoding using FFMPEG. This process can not only encode H.264 videos, but also encode videos supported by MPEG4, MPEG2, Vp8, and other FFMPEG videos. In the figure, the blue background function is the function that actually outputs data. The Light Green function is the video encoding function.
The meaning of each function in the process is described as follows:
Av_register_all (): Note that all codecs of FFMPEG are supported.
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 ).
Code
Paste the Code:
/** The simplest FFMPEG-Based Video Encoder ** simplest FFMPEG Video Encoder ** leixiao Lei Xiaohua * [email protected] * media University of China/Digital TV technology * Communication University china/Digital TV technology * http://blog.csdn.net/leixiaohua1020 ** this program implements the YUV pixel data encoding for video streams (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 H. 264 bitstream. * it's the simplest video encoding software based on FFMPEG. * suitable for beginner of FFMPEG */# include "stdafx. H "extern" C "{# 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 ("encoding successful 1 frame! \ N ");/* MUX encoded frame */ret = av_write_frame (fmt_ctx, & enc_pkt); If (Ret <0) break;} return ret ;} int _ tmain (INT argc, _ tchar * argv []) {avformatcontext * pformatctx; avoutputformat * FMT; avstream * video_st; avcodeccontext * pcodecctx; avcodec * pcodec; uint8_t * handle; avframe * picture; int size; file * in_file = fopen ("src0109480x272.yuv", "rb"); // video YUV source file int in_w = 480, in_h = 272; // int framenum = 50; const C Har * out_file = "src01.h264"; // output file path av_register_all (); // method 1. use several functions in combination: pformatctx = avformat_alloc_context (); // guess the format FMt = av_guess_format (null, out_file, null); pformatctx-> oformat = FMT; // method 2. more active/avformat_alloc_output_context2 (& pformatctx, null, null, out_file); // FMt = pformatctx-> oformat; // note the output path if (avio_open (& pformatctx-> Pb, out_file, avio_flag_read_write) <0) {printf ("failed to open the output file"); Return-1;} vi Deo_st = av_new_stream (pformatctx, 0); If (video_st = NULL) {return-1;} pcodecctx = video_st-> codec; 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-> qmin = 10; pcodecctx-> Qmax = 51; // pcodecctx-> qcompress = 0.6; // output format information av_dump_format (pformatctx, 0, out_file, 1); pcodec = avcodec_find_encoder (pcodecctx-> codec_id); If (! Pcodec) {printf ("no suitable encoder found! \ N "); Return-1;} If (avcodec_open2 (pcodecctx, pcodec, null) <0) {printf (" encoder opening failed! \ 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 the file header avformat_write_header (pformatctx, null); avpacket Pkt; int y_size = pcodecctx-> width * pcodecctx-> height; av_new_packet (& Pkt, y_size * 3); For (INT I = 0; I <framenum; I ++) {// read yuvif (fread (picture_buf, 1, y_size * 3/2, in_file) <0) {printf ("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 ("Encoding Error! \ N "); Return-1;} If (got_picture = 1) {printf (" 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 av_write_trailer (pformatctx) at the end of the file; // clear 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 ;}
Software execution (limited by the file size, the number of original YUV frames is very small ):
The YUV sequence Before encoding:
Encoded H.264 code stream:
:
Http://download.csdn.net/detail/leixiaohua1020/7324115
Correction record:
We found that the encoded H.264 code stream is different from the number of frames input by YUV. After observing and comparing other programs, it is found that flush_encoder () needs to be called to output the remaining video frames in the encoder. The problem has been fixed.
(After modification ):
Http://download.csdn.net/detail/leixiaohua1020/7466649
SourceForge has been updated.
Pudn source code (corrected ):
Http://www.pudn.com/downloads644/sourcecode/multimedia/detail2605258.html
SourceForge Project address:
Https://sourceforge.net/projects/simplestffmpegvideoencoder/
The simplest Video Encoder Based on FFMPEG (YUV encoding: H.264)