decode函数的用法_video_decode

20190221遇到了两个问题,1是代码出现too many open files的问题。二是代码出现了packet不匹配的问题。

1是由于avformat_open_input只打开,未关闭。

2是由于视频的帧高和宽不同,前面都是512*288,最后变成了1920*1280,但是解码的时候

img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);

sws_scale函数的用法-具体应用 - eloudy的专栏 - CSDN博客​blog.csdn.net
3ef9bb2c13c485d236c1a3d8aa8be7b9.png

后面的是目标大小,但是和前面不同了,所以报错。为了解决,只需要在循环读取帧之前,将第一帧的大小确定,然后都按这个大小解码。

int new_width=pCodecCtx->width;
int new_height=pCodecCtx->height;

img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,pCodecCtx->pix_fmt, new_width, new_height,AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);

1.void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)

  AVFrame结构体一般用于存储原始数据(即非压缩数据,例如对视频来说是YUV,RGB,对音频来说是PCM),此外还包含了一些相关的信息。

代码有下面的for循环: for(int i=0;i<width*3;i++)

  AVFrame结构体中uint8_t *data[AV_NUM_DATA_POINTERS]:解码后原始数据(对视频来说是YUV,RGB,对音频来说是PCM)

int linesize[AV_NUM_DATA_POINTERS]:data中“一行”数据的大小。注意:未必等于图像的宽,一般大于图像的宽。

对于packed格式的数据(例如RGB24),会存到data[0]里面。

对于planar格式的数据(例如YUV420P),则会分开成data[0],data[1],data[2]...(YUV420P中data[0]存Y,data[1]存U,data[2]存V)

YUV420P(planar格式)在ffmpeg中存储是在struct AVFrame的data[]数组中

data[0]——-Y分量  data[1]——-U分量  data[2]——-V分量

linesize[]数组中保存的是对应通道的数据宽度

linesize[0]——-Y分量的宽度 linesize[1]——-U分量的宽度 linesize[2]——-V分量的宽度

代码中只保留了Y分量???或者代码是RGB24格式。

FFMPEG结构体分析:AVFrame - 雷霄骅(leixiaohua1020)的专栏 - CSDN博客​blog.csdn.net
92a2fd4c49e0dce9975853dbfd2904d5.png
FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)​blog.csdn.net

2.void SaveFrame_Img(unsigned char *data, int width, int height,int frameId, int lastNum,uint64_t videoId, string strPath)

前三个参数关于图像,后面关于文件路径名 lastNum:持续的帧数

把格式化的数据写入szFilename字符串

3. IplImage* VideoDecode::AVPictureToIplImage(AVPicture * pic,AVCodecContext *pCodeCtx)

AVPicture转化为opencv格式中常用的IplImage。

其中的参数解释为:

基础:关于YUV 和 Cr Cb的区别​blog.csdn.net

Y = 0.299R + 0.587G + 0.114B   亮度 灰度图也是这个公式。

ffmpeg 中的 AVFrame 和 AVPicture​blog.csdn.net
typedef 

但是根据代码AVPicture是RGB格式啊?三通道。

IPL_DEPTH_8U:无符号8位整数。

https://blog.csdn.net/rex1984_/article/details/48655189​blog.csdn.net

OpenCV的IplImage数据结构的各成员变量的含义 - Shawn_Shuang的学习空间 - CSDN博客

OpenCV的IplImage数据结构的各成员变量的含义 - Shawn_Shuang的学习空间 - CSDN博客​blog.csdn.net OpenCV基础知识教程_整理供查询 - 固本培元的专栏 - CSDN博客​blog.csdn.net

4. int VideoDecode::video_decode(const char *szFilename ,vector<KeyFrame> &vKeyFrame ,vector <double> &vIFrameTimeCode,int descDim, uint64_t vid , int genJPG,string strPath)

AVFormatContext是FFMPEG解封装(flv,mp4,rmvb,avi)功能的结构体。

struct AVInputFormat *iformat:输入数据的封装格式

AVIOContext *pb:输入数据的缓存

unsigned int nb_streams:视音频流的个数

AVStream **streams:视音频流

char filename[1024]:文件名

int64_t duration:时长(单位:微秒us,转换为秒需要除以1000000)

int bit_rate:比特率(单位bps,转换为kbps需要除以1000)

AVDictionary *metadata:元数据

视频的原数据(metadata)信息可以通过AVDictionary获取。元数据存储在AVDictionaryEntry结构体中。

FFMPEG结构体分析:AVFormatContext - 雷霄骅(leixiaohua1020)的专栏 - CSDN博客​blog.csdn.net

AVCodecContext大多是编码使用、

enum AVMediaType codec_type:编解码器的类型(视频,音频...)

struct AVCodec *codec:采用的解码器AVCodec(H.264,MPEG2...)

int bit_rate:平均比特率

uint8_t *extradata; int extradata_size:针对特定编码器包含的附加信息(例如对于H.264解码器来说,存储SPS,PPS等)

AVRational time_base:根据该参数,可以把PTS转化为实际的时间(单位为秒s)

int width, height:如果是视频的话,代表宽和高

int refs:运动估计参考帧的个数(H.264的话会有多帧,MPEG2这类的一般就没有了)

int sample_rate:采样率(音频)

int channels:声道数(音频)

enum AVSampleFormat sample_fmt:采样格式

int profile:型(H.264里面就有,其他编码标准应该也有)

int level:级(和profile差不太多)

FFMPEG结构体分析:AVCodecContext - 雷霄骅(leixiaohua1020)的专栏 - CSDN博客​blog.csdn.net FFmpeg AVPacket - WCCW - 博客园​www.cnblogs.com

av_register_all()调用了avcodec_register_all()。avcodec_register_all()注册了和编解码器有关的组件:硬件加速器,解码器,编码器,Parser,Bitstream Filter。av_register_all()除了调用avcodec_register_all()之外,还注册了复用器,解复用器,协议处理器。

ffmpeg 源代码简单分析 : av_register_all()​blog.csdn.net
0525c3c892cabb39dc3637a54f1b2855.png

打开视频文件:

if(avformat_open_input(&pFormatCtx, szFilename, NULL, NULL) != 0)

其中的参数:

ps:函数调用成功之后处理过的AVFormatContext结构体。

file:打开的视音频流的URL。

fmt:强制指定AVFormatContext中AVInputFormat的。这个参数一般情况下可以设置为NULL,这样FFmpeg可以自动检测AVInputFormat。

dictionay:附加的一些选项,一般情况下可以设置为NULL。

返回AVFormatContext的实例。

avformat_find_stream_info函数正常执行后返回值大于等于0。

这段代码和博客里一样:

FFMPEG学习----打印视频信息 - 晚晴小筑 - CSDN博客​blog.csdn.net
1e270d70ff5a1dd9700d104a5bdb676f.png

对视频流找到解码器。

用av_frame_alloc(void)函数来分配一个AVFrame结构体。给pFrameRGB帧附加上分配的内存 。这段代码和博客类似:

图像视频编码和FFmpeg(3)-----用FFmpeg进行图像格式转换和AVFrame简介 - luotuo44的专栏 - CSDN博客​blog.csdn.net

while(av_read_frame(pFormatCtx, &packet)>=0) //读取码流中的视频帧

找到与第一个视频流对应的帧,然后avcodec_decode_video2进行解码为帧。

ffmpeg源码简析(八)解码 av_read_frame(),avcodec_decode_video2(),avformat_close_input()​www.voidcn.com

然后转化为RGB24格式,

sws_getContext函数详细使用 - 相见不如怀念 - CSDN博客​blog.csdn.net
b18457fe96211555dabb21314f027543.png

从第二帧开始计算关键帧距离,去重等操作。对固定尺度的灰度图得到描述子,harrisFeature.SelectKLTFeatures();//得到描述子,vecDesc

然后存储帧特征的id。

genJPG 控制是否提取关键帧阶段还是查询阶段。

保存关键帧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值