FFmpeg video decoder_ffmpeg decoder-CSDN blog
1. Introduction to FFmpeg library
2.FFmpeg decoding function
2.1 FFmpeg decoding flow chart
av_read_frame(): Loops to read data frame by frame, which is actually h264 code stream
2.2 Introduction to FFmpeg decoding function
3. Data structure of FFmpeg decoding
Display timestamp: The minutes and seconds that this frame should be displayed based on the member variable time_base of AVStream, the time base of the stream
AVPacket: Install h.264 data (data before decoding, encoded data)
AVFrame: Install YUV data (decoded data, decoded data)
4. Supplementary knowledge: Why does the decoded data need to be processed by the sws_scale() function?
5. After-class exercises
/** * The simplest decoder based on FFmpeg * Simplest FFmpeg Decoder * * Lei Xiaohua *[email protected] * Communication University of China/Digital TV Technology * Communication University of China / Digital TV Technology * http://blog.csdn.net/leixiaohua1020 * * This program implements the decoding of video files (supports HEVC, H.264, MPEG2, etc.). * It is the simplest tutorial on FFmpeg video decoding. * By studying this example, you can understand the decoding process of FFmpeg. * This software is a simplest video decoder based on FFmpeg. * Suitable for beginners of FFmpeg. * */ #include <stdio.h> #define __STDC_CONSTANT_MACROS extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" #include "libavutil/imgutils.h" }; int main(int argc, char* argv[]) { AVFormatContext* pFormatCtx; // All information stored about the video int i, videoindex; // videoindex: the serial number value of the video stream AVCodecContext* pCodecCtx; AVCodec* pCodec; AVFrame* pFrame, * pFrameYUV; uint8_t* out_buffer; AVPacket* packet; int y_size; int ret, got_picture; struct SwsContext* img_convert_ctx; //The path of the audio and video file to be decoded char filepath[] = "./test.avi"; //The number of video frames int frame_cnt; // 1. Initialize and register all components //av_register_all(); avformat_network_init(); pFormatCtx = avformat_alloc_context(); // 2. Open the video file if (avformat_open_input( & amp;pFormatCtx, filepath, NULL, NULL) != 0) { printf("Couldn't open input stream.\ "); return -1; } // 3. Get video stream information if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { printf("Couldn't find stream information.\ "); return -1; } // Get stream information and decode it videoindex = -1; //Find the serial number value of the video stream // nb_streams: There are several streams recorded. Generally, stream[0] is video and stream[1] is audio. for (i = 0; i < pFormatCtx->nb_streams; i + + ) if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { //The enumeration value AVMEDIA_TYPE_VIDEO is 0, indicating video videoindex = i; break; } if (videoindex == -1) { printf("Didn't find a video stream.\ "); return -1; } //AVCodecParameters: used to save basic parameter information of audio and video streams AVCodecParameters* codecParameters = pFormatCtx->streams[videoindex]->codecpar; pCodecCtx = avcodec_alloc_context3(nullptr); avcodec_parameters_to_context(pCodecCtx, codecParameters); // 4. Find the decoder, eg: H.264 encoder // pCodecCtx=pFormatCtx->streams[videoindex]->codec; pCodec = (AVCodec*)avcodec_find_decoder(pCodecCtx->codec_id); if (pCodec == NULL) { printf("Codec not found.\ "); return -1; } // 5. Open the decoder if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) { printf("Could not open codec.\ "); return -1; } // open a file FILE * fp, * fp_264, * fp_yuv; fopen_s( & amp;fp, "info.txt", "wb + "); fopen_s( & amp;fp_264, "output264.h264", "wb + "); fopen_s( & amp;fp_yuv, "outputyuv.yuv", "wb + "); /* * Here is the code for the terminal to output video information * Taken from pFormatCtx, using fprintf() */ //Write to file info.txt fprintf(fp, "Duration: %d μs\ ", pFormatCtx->duration); // Microseconds, converted to seconds divided by 1e6 fprintf(fp, "Packaging format:%s\ ", pFormatCtx->iformat->long_name); fprintf(fp, "Resolution: %d*%d\ ", pCodecCtx->width, pCodecCtx->height); packet = av_packet_alloc(); pFrame = av_frame_alloc(); pFrameYUV = av_frame_alloc(); out_buffer = (uint8_t*)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1)); av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1); //Output video file information printf("--------------- File Information ----------------\ "); /* * av_dump_format() function: Print detailed information about the input or output format, such as * duration, bitrate, streams, container, programs, metadata, side data, * codec and time base. */ av_dump_format(pFormatCtx, 0, filepath, 0); printf("-------------------------------------------------- --\ "); img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); //Number of video frames frame_cnt = 0; // Output H264 code stream // 6. av_read_frame(): Read a frame of compressed data from the input file. while (av_read_frame(pFormatCtx, packet) >= 0) { if (packet->stream_index == videoindex) { // videoindex: determine whether it is a video /* * Output the code of H264 code stream here * Taken from packet, use fwrite() to write the data in the memory to the file output264.h264 */ fwrite(packet->data, 1, packet->size, fp_264); if (avcodec_send_packet(pCodecCtx, packet) < 0) { printf("avcodec_send_packet failed!.\ "); continue; } while (1) { ret = avcodec_receive_frame(pCodecCtx, pFrame); if (ret != 0)break; // The sws_scale function processes the generated image, and the generated data is stored in pFrameYUV sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize); // Output the sequence number of the processed frame printf("Decoded frame index: %d\ ", frame_cnt); /* * Add the code to output YUV here * Taken from pFrameYUV, using fwrite() * * * data[0]: Y data, all bright points on the screen, black and white data * data[1]: U data, the data is one quarter of Y * "U" and "V" represent chroma, Its function is to describe the color and saturation of the image, and is used to specify the color of the pixels. * data[2]: V data, the data is one quarter of Y */ fwrite(pFrameYUV->data[0], 1, pCodecCtx->width * pCodecCtx->height, fp_yuv); fwrite(pFrameYUV->data[1], 1, pCodecCtx->width * pCodecCtx->height / 4, fp_yuv); fwrite(pFrameYUV->data[2], 1, pCodecCtx->width * pCodecCtx->height / 4, fp_yuv); frame_cnt + + ; } } av_packet_unref(packet); } sws_freeContext(img_convert_ctx); fclose(fp); fclose(fp_264); fclose(fp_yuv); av_frame_free( & amp;pFrameYUV); av_frame_free( & amp;pFrame); avcodec_close(pCodecCtx); avformat_close_input( & amp;pFormatCtx); return 0; }