ffmpeg实现简单视频解码(将视频文件分解为单张RGB图片)

参考链接
官网
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)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值