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后面的是目标大小,但是和前面不同了,所以报错。为了解决,只需要在循环读取帧之前,将第一帧的大小确定,然后都按这个大小解码。
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.net2.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.netY = 0.299R + 0.587G + 0.114B 亮度 灰度图也是这个公式。
ffmpeg 中的 AVFrame 和 AVPictureblog.csdn.nettypedef
但是根据代码AVPicture是RGB格式啊?三通道。
IPL_DEPTH_8U:无符号8位整数。
https://blog.csdn.net/rex1984_/article/details/48655189blog.csdn.netOpenCV的IplImage数据结构的各成员变量的含义 - Shawn_Shuang的学习空间 - CSDN博客
OpenCV的IplImage数据结构的各成员变量的含义 - Shawn_Shuang的学习空间 - CSDN博客blog.csdn.net OpenCV基础知识教程_整理供查询 - 固本培元的专栏 - CSDN博客blog.csdn.net4. 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.netAVCodecContext大多是编码使用、
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.comav_register_all()调用了avcodec_register_all()。avcodec_register_all()注册了和编解码器有关的组件:硬件加速器,解码器,编码器,Parser,Bitstream Filter。av_register_all()除了调用avcodec_register_all()之外,还注册了复用器,解复用器,协议处理器。
ffmpeg 源代码简单分析 : av_register_all()blog.csdn.net打开视频文件:
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对视频流找到解码器。
用av_frame_alloc(void)函数来分配一个AVFrame结构体。给pFrameRGB帧附加上分配的内存 。这段代码和博客类似:
图像视频编码和FFmpeg(3)-----用FFmpeg进行图像格式转换和AVFrame简介 - luotuo44的专栏 - CSDN博客blog.csdn.netwhile(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从第二帧开始计算关键帧距离,去重等操作。对固定尺度的灰度图得到描述子,harrisFeature.SelectKLTFeatures();//得到描述子,vecDesc
然后存储帧特征的id。
genJPG 控制是否提取关键帧阶段还是查询阶段。
保存关键帧。