参考链接
官网
https://ffmpeg.org/doxygen/3.4/decode_video_8c-example.html
https://blog.youkuaiyun.com/u014162133/article/details/81131339
核心流程及API
//处理输入
/* register all formats and codecs */
av_register_all();
/* open input file, and allocate format context */
avformat_open_input
/* retrieve stream information */
avformat_find_stream_info
av_init_packet
av_find_best_stream
//处理输出
/* find decoder for the stream */
avcodec_find_decoder
// allocate video codec context ( avcodeccontext)
avcodec_alloc_context3
/* Copy codec parameters from input stream to output codec context */
avcodec_parameters_to_context
/* open it */
avcodec_open2
//Allocate and return an SwsContext to picture scaling or conversion
sws_getContext
av_frame_alloc()
av_read_frame
//自定义函数 解码并输出bmp图片
decode_write_frame
{
//输入一个压缩编码的结构体AVPacket,输出一个解码后的结构体AVFrame
avcodec_decode_video2
//把图片名称存放在buf中
snprintf
//自定义函数,将yuv的帧转化为RGB并输出
saveBMP
{
//计算这个格式的图片,需要多少字节来存储
avpicture_get_size
//申请空间来存放图片数据。包含源数据和目标数据
av_malloc
//为已经分配的空间的结构体AVPicture挂上一段用于保存数据的空间
avpicture_fill
//将yuv转化为RGB
sws_scale
构造BMP文件
// 构造 BITMAPINFOHEADER位图信息头
// 构造文件头
//打开输出文件
//将头和RGB帧写入
}
}
decode_video.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#define INBUF_SIZE 4096
#define WORD uint16_t
#define DWORD uint32_t
#define LONG int32_t
#pragma pack(2)
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;
void saveBMP(struct SwsContext *img_convert_ctx, AVFrame *frame, char *filename)
{
//1 先进行转换, YUV420=>RGB24:
int w = frame->width;
int h = frame->height;
//alloc buf to avframe struct
AVFrame *pFrameRGB = av_frame_alloc();
//计算这个格式的图片,需要多少字节来存储
int numBytes=avpicture_get_size(AV_PIX_FMT_BGR24, w, h);
//申请空间来存放图片数据。包含源数据和目标数据
uint8_t *buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
/* buffer is going to be written to rawvideo file, no alignment */
/*
if (av_image_alloc(pFrameRGB->data, pFrameRGB->linesize,
w, h, AV_PIX_FMT_BGR24, pix_fmt, 1) < 0) {
fprintf(stderr, "Could not allocate destination image\n");
exit(1);
}
*/
//前面的av_frame_alloc函数,只是为这个AVFrame结构体分配了内存,而该类型的指针指向的内存还没分配
//把av_malloc得到的内存和AVFrame关联起来
avpicture_fill((AVPicture *)pFrameRGB, buffer, AV_PIX_FMT_BGR24, w, h);
// FFmpeg定义了一个结构体SwsContext,它记录进行图像格式转换时,源图像和目标图像的格式、大小分别是什么。然后用sws_scale函数直接转换即可。
sws_scale(img_convert_ctx, frame->data, frame->linesize,
0, h, pFrameRGB->data, pFrameRGB->linesize);
//2 构造 BITMAPINFOHEADER
BITMAPINFOHEADER header;
header.biSize = sizeof(BITMAPINFOHEADER);
header.biWidth = w;
header.biHeight = h*(-1)

最低0.47元/天 解锁文章
1369

被折叠的 条评论
为什么被折叠?



