The content in this article is original. For more information, see the source.
Decoding h264 data using FFmpeg is actually much easier than video encoding using x264, because FFMPEG provides a decoding_encoding.c file, this file contains simple examples of using FFMPEG for video and audio encoding/decoding. However, some people may not find this example. I will describe the transformed example here, add some explanations.
Note that, when decoding FFMPEG, it will consider whether the data packet to be decoded has a header such as 0x00 00 001. If not, FFmpeg will consider it as a wrong data packet. The following uses opencv to display decoded images. Therefore, you must configure the opencv environment. If not, comment out the showimage function, then, use the pgm_save function to save the decoded image.
I will put my code below. Similarly, the process can be found in code annotations, which is relatively simple and not described here:
Static void pgm_save (unsigned char * Buf, int wrap, int xsize, int ysize, char * filename) {file * F; int I; F = fopen (filename, & quot; WB & quot;); fprintf (F, & quot; P5 \ n % d \ n & quot;, xsize, ysize, 255); for (I = 0; I <ysize; I ++) fwrite (BUF + I * Wrap, 1, xsize, f); fclose (f );} // find the header static int _ find_head (unsigned char * buffer, int Len) {int I; for (I = 512; I <Len; I ++) {If (buffer [I] = 0 & buffer [I + 1] = 0 && Buffer [I + 2] = 0 & buffer [I + 3] = 1) break; if (buffer [I] = 0 & buffer [I + 1] = 0 & buffer [I + 2] = 1) break ;} if (I = Len) return0; if (I = 512) return0; return I ;} // convert a data packet in the file to the avpacket type for FFMPEG decoding # define file_reading_buffer (1*1024*1024) Static void build_avpkt (avpacket * avpkt, file * FP) {static unsigned charbuffer [1*1024*1024]; static int readptr = 0; static int writeptr = 0; intlen, toread; Intnexthead; If (writeptr-readptr <200*1024) {memmove (buffer, & buffer [readptr], writeptr-readptr); writeptr-= readptr; readptr = 0; toread = file_reading_buffer-writeptr; Len = fread (& buffer [writeptr], 1, toread, FP); writeptr + = Len;} nexthead = _ find_head (& buffer [readptr], writeptr-readptr); If (nexthead = 0) {printf ("failedfind next head... \ n "); nexthead = writeptr-readptr;} avpk T-> size = nexthead; avpkt-> DATA = & buffer [readptr]; readptr + = nexthead;} static voidvideo_decode_example (const char * outfilename, constchar * filename) {avcodec * codec; avcodeccontext * c = NULL; int frame, got_picture, Len; file * F, * fout; avframe * picture; uint8_t inbuf [inbuf_size + ff_input_buffer_padding_size] charbuf [1024]; avpacket avpkt; av_init_packet (& avpkt);/* Set end ofbuffer to 0 (this Ensures that no overreading happens for damaged MPEG streams) */memset (inbuf + inbuf_size, 0, ff_input_buffer_padding_size); printf ("videodecoding \ n"); opts = NULL; // av_dict_set (& opts, "B", "2.5 m", 0);/* Find the hsf-video decoder */codec = avcodec_find_decoder (codec_id_h264); If (! Codec) {fprintf (stderr, "codecnot found \ n"); return;} c = avcodec_alloc_context3 (codec); picture = avcodec_alloc_frame (); If (codec-> capabilities & dependencies) c-> flags | = codec_flag_truncated;/* we do not send complete frames * // * For somecodecs, such as msmpeg4 and MPEG4, width and height must be initialized there because thisinformation is not available in the bitstream. * // * Open It */ If (avcodec_open2 (C, codec, null) <0) {fprintf (stderr, "couldnot open codec \ n"); exit (1 );} // fout = fopen (outfilename, "WB");/* the codec givesus the frame size, in samples */F = fopen (filename, "rb"); If (! F) {fprintf (stderr, "couldnot open % s \ n", filename); exit (1) ;}// decode and display the required secondary data structure, it should be noted that avframe can only be used after alloc. Otherwise, the cache space pointer of its memory is null and the program will crash avframe framergb; iplimage * showimage = cvcreateimage (cvsize (352,288 ), 8, 3); avpicture_alloc (avpicture *) & framergb, pix_fmt_rgb24, 352,288); cvnamedwindow ("decode"); frame = 0; For (;) {build_avpkt (& avpkt, f); If (avpkt. size = 0) break; while (avpkt. size> 0) {Len = avco Dec_decode_video2 (C, picture, & got_picture, & avpkt); // decode each frame if (LEN <0) {fprintf (stderr, "Error while Decoding Frame % d \ n", frame); break;} If (got_picture) {printf ("savingframe % 3d \ n", frame); fflush (stdout ); /* thepicture is allocated by the decoder. no need to free it * // convert the yuv420 format image to the conversion context swscontext * scxt = sws_getcontext (picture-> width, picture-> height, pix_fmt_yuv420p, picture-> wid Th, picture-> height, pix_fmt_rgb24, 2, null); If (scxt! = NULL) {sws_scale (scxt, picture-> data, picture-> linesize, 0, C-> height, framergb. data, framergb. linesize); // image format conversion showimage-> imagesize = framergb. linesize [0]; // assign a pointer to the image to be displayed showimage-> imagedata = (char *) framergb. data [0]; cvshowimage ("decode", showimage); // display cvwaitkey (0.5); // set 0.5s to display a frame. If this is not set, the displayed image is invisible} // sprintf (BUF, outfilename, frame); // pgm_save (picture-> data [0], picture-> linesize [0], // C-> width, C-> height, Buf); // pgm_save (picture-> data [1], picture-> linesize [1], // C-> width/2, c-> height/2, fout); // pgm_save (picture-> data [2], picture-> linesize [2], // C-> width/2, c-> height/2, fout); frame ++;} avpkt. size-= Len; avpkt. data + = Len ;}/ * Some codecs, such as MPEG, transmit the I and P frame with a latency of one frame. you must do thefollowing to have a chance to get the last frame of the video */avpkt. data = NULL; avpkt. size = 0; Len = avcodec_decode_video2 (C, picture, & got_picture, & avpkt); If (got_picture) {printf ("savinglast frame % 3d \ n", frame ); fflush (stdout);/* The pictureis allocated by the decoder. no need to free it */sprintf (BUF, outfilename, frame); // pgm_save (picture-> data [0], picture-> linesize [0], // C-> width, C-> height, fout); pgm_save (picture-> data [0], picture-> linesize [0], C-> width, c-> height, fout); pgm_save (picture-> data [1], picture-> linesize [1], C-> width/2, c-> height/2, fout); pgm_save (picture-> data [2], picture-> linesize [2], C-> width/2, c-> height/2, fout ); frame ++;} fclose (f); // fclose (fout); avcodec_close (c); av_free (picture ); printf ("\ n");} int main (INT argc, char * argv []) {avcodec_register_all (); // register all codecs. Be sure to note that, if this line of code does not exist, an error occurs. The system prompts that video_decode_example ("% 3d. PGM "," test.264 "); // The 264 File System (" pause ") that can be encoded using x264; return 0 ;}