播放器实战09 send packet与receive frame

AVCodecContext* av = 0;
		if (pkt->stream_index == videoindex)
		{
			cout << "视频" << endl;
			av = vc;
		}
		if (pkt->stream_index == audioindex)
		{
			cout << "音频" << endl;
			av = ac;
		}

在前面打开解码器操作时通过
AVCodecContext* ac = avcodec_alloc_context3(acodec);创建了音频解码器上下文ac与视频解码器上下文vc,这里想创建一个解码器上文类型的值,但在后面才知道指向的是音频还是视频,这里先用ac表示并先初始化为0.

re = avcodec_send_packet(av, pkt);

获取解码数据,一次send可能需要多次Recv,
获取缓冲中的数据Send NULL在Recv多次

av_packet_unref(pkt);

pkt丢到解码队列中了,pkt没有利用价值了,这里释放,引用计数-1

		if (re != 0)
		{
			char buf[1024] = { 0 };
			av_strerror(re, buf, sizeof(buf) - 1);//用buf存放错误信息
			cout << "send packet failed!" << buf << endl;
			getchar();
			continue;
		}

若发送失败则打印错误信息

for (;;)
		{
			re= avcodec_receive_frame(av, frame);//
			if (re != 0)break;
			cout << "recv frame" << frame->format << " " << frame->linesize[0] << endl;//视频的为一行的值,why?
		}

一次send可能对应多次receive,因为一次send的packet里可能包含多帧的信息,因此要多次接收,直到收不到为止
frame申请方法与packet一致:
AVPacket* pkt = av_packet_alloc();
AVFrame* frame = av_frame_alloc();
,但比packet的空间大的多,因为frame放的是完整一张图片信息,而packet放的是压缩后的信息

AVPacket是FFmpeg中很重要的一个数据结构,它保存了解复用之后,解码之前的数据(仍然是压缩后的数据)和关于这些数据的一些附加信息,如显示时间戳(pts)、解码时间戳(dts)、数据时长,所在媒体流的索引等。

对于视频(Video)来说,AVPacket通常包含一个压缩的Frame,而音频(Audio)则有可能包含多个压缩的Frame。并且,一个Packet有可能是空的,不包含任何压缩数据,只含有side data(side data,容器提供的关于Packet的一些附加信息。例如,在编码结束的时候更新一些流的参数)。

AVPacket中的字段可用分为两部分:数据的缓存及管理,关于数据的属性说明。

关于数据的属性有以下字段:
pts 显示时间戳
dts 解码时间戳
stream_index Packet所在stream的index
flats 标志,其中最低为1表示该数据是一个关键帧
duration 数据的时长,以所属媒体流的时间基准为单位
pos 数据在媒体流中的位置,未知则值为-1
convergence_duration 该字段已被deprecated,不再使用
数据缓存,AVPacket本身只是个容器,不直接的包含数据,而是通过数据缓存的指针引用数据。AVPacket中包含有两种数据
data 指向保存压缩数据的指针,这就是AVPacket实际的数据。
side_data 容器提供的一些附加数据
buf 是AVBufferRef类型的指针,用来管理data指针引用的数据缓存的。
详细:https://blog.csdn.net/with_dream/article/details/84928280?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0.pc_relevant_default&spm=1001.2101.3001.4242.1&utm_relevant_index=2
在这里插入图片描述

关于linesize

/**
 * int linesize[AV_NUM_DATA_POINTERS];
 * pointers to the data planes/channels.
 *
 * For video, this should simply point to data[].
 *
 * For planar audio, each channel has a separate data pointer, and
 * linesize[0] contains the size of each channel buffer.
 * For packed audio, there is just one data pointer, and linesize[0]
 * contains the total size of the buffer for all channels.
 *
 * Note: Both data and extended_data should always be set in a valid frame,
 * but for planar audio with more channels that can fit in data,
 * extended_data must be used in order to access all channels.
 */

对于音频来说linesize[0] contains the total size of the buffer for all channels.
由运行结果可以看到所有通道中缓存的总大小为8192
在这里插入图片描述
int nb_samples:音频的一个AVFrame中可能包含多个音频帧,在此标记包含了几个、(1024)

int format:解码后原始数据类型(YUV420,YUV422,RGB24…) (8)
format 8对应float类型,一个float占32位,也就是4个字节
双通道
102442=8192
视频的为一行的值,所以比较小(1280)

av_frame_free(&frame);
av_packet_free(&pkt);

前面只是减少引用计数,这里需要清空间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值