百科不全书之 FFMP之推拉流函数解析

本文详细介绍了FFmpeg的工作流程,包括网络初始化、文件格式处理、解码器查找与开启、数据读取与解码,以及关键步骤如SwsScale进行图像格式转换。通过实例演示了如何使用AVPicture和AVFrame进行视频帧操作和处理,同时探讨了设置网络超时和参数的方法。
摘要由CSDN通过智能技术生成

参考链接: link.
#工作流程

avformat_network_init();// 初始化网络库 网络拉流推流必须用

av_register_all(); //初始化所有的封装和解封装,不包含编码和解码

pFormatCtx = avformat_alloc_context();  // 对AVFormatContext做初始化

if(avformat_open_input(&pFormatCtx,path,NULL,NULL)<0) 	//打开视频流

if(avformat_find_stream_info(pFormatCtx,NULL)<0) // 获取音视频信息

avcodec_find_decoder()	// 查找解码器

avcodec_open2()// 打开解码器

av_read_frame() // 读取原始数据

av_malloc()  // 内存分配

avcodec_decode_video2()  // 解码数据为一帧

int avpicture_fill(AVPicture *picture, uint8_t *ptr,int pix_fmt, int width, int height);// 为已经分配的空间的结构体AVPicture挂上一段用于保存数据的空间.这个结构体中有一个指针数组data[4],挂在这个数组里

avpicture_fill((AVPicture *) pFrameRGB, buffer, PIX_FMT_RGB565, pCodecCtx->width, pCodecCtx->height);//这句调用时,pFrameRGB和buffer都是已经申请到的一段内存, 会将pFrameRGB的数据按RGB565格式自动"关联"到buffer。

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_getContext 函数返回的结果。参数 const uint8_t *const srcSlice[], 输入图像的每个颜色通道的数据指针。其实就是解码后的AVFrame中的data[]数组。因为不同像素的存储格式不同,所以srcSlice[]维数也有可能不同。参数const int srcStride[],输入图像的每个颜色通道的跨度。.也就是每个通道的行字节数,对应的是解码后的AVFrame中的linesize[]数组。根据它可以确立下一行的起始位置,不过stride和width不一定相同,这是因为:a.由于数据帧存储的对齐,有可能会向每行后面增加一些填充字节这样 stride = width + N;b.packet色彩空间下,每个像素几个通道数据混合在一起,例如RGB24,每个像素3字节连续存放,因此下一行的位置需要跳过3*width字节。

4.参数int srcSliceY, int srcSliceH,定义在输入图像上处理区域,srcSliceY是起始位置,srcSliceH是处理多少行。如果srcSliceY=0,srcSliceH=height,表示一次性处理完整个图像。这种设置是为了多线程并行,例如可以创建两个线程,第一个线程处理 [0, h/2-1]行,第二个线程处理 [h/2, h-1]行。并行处理加快速度。
5.参数uint8_t *const dst[], const int dstStride[]定义输出图像信息(输出的每个颜色通道数据指针,每个颜色通道行字节数)
 av_free_packet();// 释放数据
 
void av_init_packet(AVPacket *pkt) //仅仅是把pkt的参数设为默认值,要求pkt的内存已经分配好了,如果为NULL,则此处会崩溃
AVPacket *av_packet_alloc(void)  //分配一个结构体大小的内存
int av_new_packet(AVPacket *pkt, int size)  //为pkt分配一个指定大小的内存

// AVDictionary是FFmpeg的键值对存储工具,FFmpeg经常使用AVDictionary设置/读取内部参数,我们可以在打开码流前指定各种参数,比如:探测时间、超时时间、最大延时、支持的协议的白名单等等
AVDictionary* opts = NULL;  // 设置rtsp超时
av_dict_set(&opts, "rtsp_transport", m_bTcp ? "tcp" : "udp", 0); //设置tcp or udp,默认一般优先tcp再尝试udp
av_dict_set(&opts, "stimeout", "3000000", 0);//设置超时3秒
int ret = avformat_open_input(&ctx, url, NULL, &opts);

AVDictionary* opts = NULL;//设置udp,http超时
av_dict_set(&opts, "timeout", "3000000", 0);//设置超时3秒
int ret = avformat_open_input(&ctx, url, NULL, &opts);

auto ctx = avformat_alloc_context(); // 设置av_read_frame 超时
ctx->interrupt_callback.callback = CheckInterrupt;//超时回调
ctx->interrupt_callback.opaque = this;

avframe类解析

uint8_t *data[AV_NUM_DATA_POINTERS]:解码后原始数据(对视频来说是YUVRGB,对音频来说是PCM)
int linesize[AV_NUM_DATA_POINTERS]:data中“一行”数据的大小。注意:未必等于图像的宽,一般大于图像的宽。
int width, height:视频帧宽和高(1920x1080,1280x720...)
int nb_samples:音频的一个AVFrame中可能包含多个音频帧,在此标记包含了几个
int format:解码后原始数据类型(YUV420YUV422RGB24...)
int key_frame:是否是关键帧
enum AVPictureType pict_type:帧类型(I,B,P...)
AVRational sample_aspect_ratio:宽高比(16:94:3...)
int64_t pts:显示时间戳
int coded_picture_number:编码帧序号
int display_picture_number:显示帧序号
int8_t *qscale_table:QP表
uint8_t *mbskip_table:跳过宏块表
int16_t (*motion_val[2])[2]:运动矢量表
uint32_t *mb_type:宏块类型表
short *dct_coeff:DCT系数,这个没有提取过
int8_t *ref_index[2]:运动估计参考帧列表(貌似H.264这种比较新的标准才会涉及到多参考帧)
int interlaced_frame:是否是隔行扫描
uint8_t motion_subsample_log2:一个宏块中的运动矢量采样个数,取log的


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值