FFmpeg 视频转图片流程:
1、找到视频流信息
2、初始化解码器上下文,并将流中解码器参数拷贝给解码器上下文
3、打开解码器
4、转换像素格式
5、循环读取视频数据包并对数据进行解码avcodec_send_packet()/avcodec_receive_frame();
6、将解码后的数据帧转成 RGB 数据,并保存
相关API
源码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#define INBUF_SIZE 4096
#define WORD uint16_t
#define DWORD uint32_t
#define LONG int32_t
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
//将解码后的数据帧转成 RGB 数据,并保存
void saveBMP(struct SwsContext *img_convert_ctx, AVFrame *frame, char *filename)
{
//1 先进行转换, YUV420=>RGB24:
int w = frame->width;
int h = frame->height;
//转为RGB24
AVFrame *pFrameRGB = av_frame_alloc();
int numBytes = av_image_get_buffer_size(AV_PIX_FMT_BGR24, w, h, 1);
uint8_t *buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
// 存储一帧像素数据缓冲区
av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, buffer, AV_PIX_FMT_BGR24, w, h, 1);
sws_scale(img_convert_ctx, frame->data, frame->linesize,
0, h, pFrameRGB->data, pFrameRGB->linesize);
//2 构造 BITMAPINFOHEADER
BITMAPINFOHEADER header