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);
前面只是减少引用计数,这里需要清空间