ffmpeg解码提取帧RGB格式信息

简介: 使用ffmpeg和qt实现播放视频功能

一.ffmpeg主要结构体

1.结构体

1.AVFormatContext

封装格式上下文结构体,也是统领全局的结构体,保存了视频文件封装格式相关信息

通过avformat_alloc_context()函数分配空间,并初始化默认参数


参数:

nb_streams代表封装格式里流有几个

streams[]代表第几个流,其中codec参数代表编解码器对应的上下文对象结构体,codec中codec_type代表类型:AVMEDIA_TYPE_VIDEO为视频类型,AVMEDIA_TYPE_AUDIO为音频类型


2.AVInputFormat/AVOutpufFormat

封装格式,保存了视频文件封装格式相关信息

3.AVStream

视频文件中流

4.AVCodecContext

编码器上下文,保存了编解码相关信息

5.AVCodec

每种编解码器

6.AVPacket

存储一帧压缩编码数据

7.AVFrame

存储一帧解码后像素数据

2.函数

二.ffmpeg解码提取帧RGB格式信息

1.打开视频文件  avformat_open_input()

AVFormatContext*封装格式上下文结构体;//用来保存视频相关信息的结构体,指针别忘记封装格式上下文结构体=avformat_alloc_context();//分配空间intres=avformat_open_input(&forContent,
文件路径+文件名称,nullptr,nullptr);
if(res!=0)//判断是否打开视频文件return;    

2.获取视频信息 如视频码流、音频码流等

//打开视频文件成功,获取文件信息res=avformat_find_stream_info(封装格式上下文结构体,nullptr);
//查看有没有相关视频流信息if(res<0)
return;

3.查找流信息  avformat_find_stream_info()

//一个视频流有多股码流,存在封装格式上下文结构体中streams数组中int第几路流(为视频流的那路流)=-1;
//nb_streams代表封装格式里面的结构体信息有几个,正常两个:音频信息、视频信息for(inti=0;i<封装格式上下文结构体->nb_streams;i++) //i小于流的个数{
if(封装格式上下文结构体->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)//视频流    {
第几路流(为视频流的那路流)=i;//标识类型break;
     }
}
//判断是否有视频流信息if(第几路流(为视频流的那路流)==-1)
return;

4.找到解码器  avcodec_find_decoder()

//编解码器对应的上下文对象结构体:保存解码器信息以及图形的宽高、像素信息AVCodecContext*编解码器对应的上下文对象=封装格式上下文结构体->streams[videoType]->codec;
//查找对应的视频流解码器AVCodec*具体编解码器=avcodec_find_decoder(编解码器对应的上下文对象->codec_id);
if(decoder==nullptr)//判断是否找到解码器return;

5.打开解码器 avcodec_open2()

//找到了解码器,打开解码器res=avcodec_open2(编解码器对应的上下文对象,具体编解码器,nullptr);
if(res!=0)
return;

6.读取码流中的一帧码流数据  av_read_frame()

//AVPacket 用来存储一帧一帧的压缩数据AVPacket*pkt=nullptr;
//设置缓冲区,开空间pkt=(AVPacket*) malloc(sizeof(AVPacket));
intsize=codec->width*codec->height;//计算一张图片数据大小av_new_packet(pkt,size);
/* pictureRGB 保存解码后的RGB像素数据* picture    保存未处理的像素数据*/AVFrame*RGB,*picture=nullptr;
//内存分配RGB=av_frame_alloc();
picture=av_frame_alloc();
//大小以及格式设置RGBRGB->width=codec->width;//宽度RGB->height=codec->height;//高度RGB->format=codec->pix_fmt;//格式设置//一帧码流数据解码后得到RGB像素数据有多大intnumByte_RGB=avpicture_get_size(AV_PIX_FMT_RGB32,编解码器对应的上下文对象->width,编解码器对应的上下文对象->height);
//开的空间用来保存RGB像素数据大小uint8_t*buffer_RGB=(uint8_t*)av_malloc(numByte_RGB*sizeof(uint8_t));
//像素数据的填充avpicture_fill((AVPicture*)RGB,buffer_RGB,AV_PIX_FMT_RGB32,编解码器对应的上下文对象->width,
编解码器对应的上下文对象->height);
//转换规则SwsContext*sws_RGB=nullptr;//保存转换规则的结构体//转换规则的设置AV_PIX_FMT_RGB32sws_RGB=sws_getContext(编解码器对应的上下文对象->width,编解码器对应的上下文对象->height,编解码器对应的上下文对象->pix_fmt,
编解码器对应的上下文对象->width,编解码器对应的上下文对象->height,AV_PIX_FMT_RGB32,  //目标格式SWS_BICUBIC,nullptr,nullptr,nullptr);         //转换规则

7.解码读到一帧码流数据 得到一帧的像素数据  

8.重复6,7两个步骤直到视频所有的帧都处理完

//一帧一帧的读取压缩数据while(av_read_frame(封装格式上下文结构体,pkt)==0)//读到数据{
if(pkt->stream_index==第几路流(为视频流的那路流))//判断一帧码流数据是不是需要得到的视频流    {
intptr=-1;
//解码res=avcodec_decode_video2(封装格式上下文结构体,picture,&ptr,pkt);
if(res<0)
return;
//压缩码流数据,解码后的像素数据,判断有没有数据可以解码,对谁进行解码if(ptr!=0)//解码操作         {
//把解码得到的坏数据剔除sws_scale(sws_RGB,picture->data,picture->linesize,0/*像素内存的偏移位*/,picture->height,
RGB->data,RGB->linesize);//RGBQImageimage((uchar*)RGB->data[0],RGB->width,RGB->height,QImage::Format_RGB32);//像素数据         }
        }
//释放包以及AVFrame资源av_packet_unref(pkt);
 }

9.关闭解码器

10.关闭视频文件


//释放AVFrameav_frame_free(&picture);
//关闭解码器avcodec_close(编解码器对应的上下文对象);
//释放视频信息结构体avformat_free_context(forContent)
sws_freeContext(sws_RGB); // 释放一个SwsContextav_frame_free(&RGB);
相关文章
|
1月前
|
算法 数据处理 开发者
FFmpeg库的使用与深度解析:解码音频流流程
FFmpeg库的使用与深度解析:解码音频流流程
36 0
|
1月前
|
存储 编解码 数据处理
【FFmpeg 视频基本格式】深入理解FFmpeg:从YUV到PCM,解码到编码(三)
【FFmpeg 视频基本格式】深入理解FFmpeg:从YUV到PCM,解码到编码
36 0
|
1月前
|
存储 编解码 数据处理
【FFmpeg 视频基本格式】深入理解FFmpeg:从YUV到PCM,解码到编码(二)
【FFmpeg 视频基本格式】深入理解FFmpeg:从YUV到PCM,解码到编码
40 0
|
1月前
|
编解码 算法 vr&ar
深度剖析FFmpeg视频解码后的帧处理到Qt显示 从AVFrame到QImage的转换(二)
深度剖析FFmpeg视频解码后的帧处理到Qt显示 从AVFrame到QImage的转换
30 1
|
1月前
|
存储 缓存 编解码
【FFmpeg 视频基本格式】深入理解FFmpeg:从YUV到PCM,解码到编码(一)
【FFmpeg 视频基本格式】深入理解FFmpeg:从YUV到PCM,解码到编码
44 0
|
1月前
|
存储 算法 前端开发
深入理解FFmpeg音视频编程:处理封装、解码、播放 队列与回放策略
深入理解FFmpeg音视频编程:处理封装、解码、播放 队列与回放策略
25 0
|
3月前
|
Linux 编译器 数据安全/隐私保护
Windows10 使用MSYS2和VS2019编译FFmpeg源代码-测试通过
FFmpeg作为一个流媒体的整体解决方案,在很多项目中都使用了它,如果我们也需要使用FFmpeg进行开发,很多时候我们需要将源码编译成动态库或者静态库,然后将库放入到我们的项目中,这样我们就能在我们的项目中使用FFmpeg提供的接口进行开发。关于FFmpeg的介绍这里就不过多说明。
76 0
|
7月前
|
C++ Windows
FFmpeg入门及编译 3
FFmpeg入门及编译
54 0
|
7月前
|
编解码 API 开发工具
FFmpeg入门及编译 1
FFmpeg入门及编译
97 0
|
24天前
|
开发工具
使用FFmpeg4.3.1的SDK官方开发包编译ffmpeg.c(二)
使用FFmpeg4.3.1的SDK官方开发包编译ffmpeg.c(二)
12 0