数据的读取
一个多媒体文件包含有多个流(视频流video stream,音频流 audio stream,字幕等),流是一种抽象的概念,表示一连串的数据元素.流中的数据元素称为帧frame,也就是说多媒体文件中,主要有两种数据:流stream及其数据元素帧frame,在FFmpeg自然有与这两种数据相对应的抽象AVStream和AVPacket.
使用FFmpeg的解码,数据的传递过程可归纳如下:
1.调用avformat_open_input,打开流,将信息填充到AVFormatContext *ic中
bool XFFmpeg::Open(const char *url)
{printf("XFFmpeg::Open %s\n",url);//打开视频解封装,打开流,将信息填充到AVFormatContext *ic中int re=avformat_open_input(&ic,url,0,0);
2.调用av_read_frame,从流中读取数据帧到AVPacket *pkt,pkt保存的仍然是未解码的数据
re=av_read_frame(ic,pkt);
3.调用..待补充
结构体的存储空间的分配与释放
FFmpeg并没有垃圾回收机制,所分配的空间都需要自己维护.而由于视频处理过程中数据量是非常大,对于动态内存的使用更要谨慎.本小节主要介绍解码过程使用到的结构体存储空间的分配与释放.
AVFormatContext 在FFmpeg中有很重要的作用,描述一个多媒体文件的构成及其基本信息,存放了视频解码过程中的大部分唏嘘你.通常该结构体由avformat_open_input分配存储空间,在最后调用avformat_input_close关闭.
AVPacket 用来存放解码之前的数据,它只是一个容器,其data成员指向实际的数据缓冲区,在解码的过程中可由av_read_frame创建和填充AVPacket中的数据缓冲区,当数据缓冲区不再使用的时候可以调用
av_packet_free释放这块缓冲区.
bool XFFmpeg::Read()
{...if(!pkt)//第一次读取,分配对象空间{pkt=av_packet_alloc();}//从流ic中读取一帧数据到 AVPacket *pkt,pkt保存的仍然是未解码的数据re=av_read_frame(ic,pkt);...
}void XFFmpeg::Close()//清理函数
{...if(pkt){av_packet_free(&pkt);}...
}
AVFrame 存放从AVPacket解码出来的原始数据,其必须通过av_frame_alloc来创建,通过av_frame_free来释放,和AVPacket类似,AVFrame中也有一块数据缓存空间,在调用av_frame_alloc的时候并不会为这块缓存区域分配空间,需要使用其他的方法,再解码的过程中使用了两个AVFrame,
bool XFFmpeg::Decode(int outwidth, int outheight)
{...if(!frame)frame=av_frame_alloc();//调用函数动态分配内存...
}void XFFmpeg::Close()//清理函数
{if (frame){av_frame_free(&frame);}
}
sws_scale()函数分析
FFmpeg中的sws_scale()函数主要是用来做视频像素格式和分辨率的转换,其优势在于:可以在同一个函数里实现:1.图像色彩空间转换,2:分辨率缩放,3:前后图像滤波处理,不足之处在于:效率相对较低,不如libyuv或shader,函数定义为
int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],const int srcStride[], int srcSliceY, int srcSliceH,uint8_t *const dst[], const int dstStride[]);
参数说明
1. SwsContext *c,转换格式的上下文,也就是sws_getCachedContext()函数的返回结果.
2.参数