一、了解结构体AVPacket与AVstream
AVPacket:
AVBufferRef *buf :buf指向一个空间,该空间里存放引用计数,packet每次copy的时候引用计数+1,每次删除时引用计数-1
int64_t pts; int64就是long long 长整形 8字节,pts用微秒做单位,有时候取很大
int64_t dts;
uint8_t *data;
int size;
int stream_index;
int flags;
AVPacketSideData *side_data;
int side_data_elems;
int64_t duration;
int64_t pos;
AVRational time_base;
av_packet_unref()将缓存空间的引用计数-1,并将Packet中的其他字段设为初始值。如果引用计数为0,自动的释放缓存空间。
av_packet_free()释放使用av_packet_alloc创建的AVPacket,如果该Packet有引用计数(packet->buf不为空),则先调用av_packet_unref(&packet)。
二、使用
AVPacket* pkt = av_packet_alloc();
for (;;)
{
int re = av_read_frame(ic, pkt);
if (re != 0)
{
//循环播放
cout << "===================end============================" << endl;
int ms = 1000;//三秒位置 根据时间基数(分数)转换
long long pos = (double)ms / (double)1000 * r2d(ic->streams[pkt->stream_index]->time_base);
av_seek_frame(ic, videoindex, pos, AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME);
continue;
}
cout << "pkt->size" << pkt->size << endl;
//显示时间
cout << "pkt->pts" << pkt->pts << endl;
cout<< "pkt->pts ms="<<pkt->pts* r2d(ic->streams[pkt->stream_index]->time_base)*1000<<endl;
//解码时间
cout << "pkt->dts" << pkt->dts << endl;
if (pkt->stream_index == videoindex)
cout << "视频" << endl;
if (pkt->stream_index == audioindex)
cout << "音频" << endl;
av_packet_unref(pkt);//将缓存空间的引用计数-1,并将Packet中的其他字段设为初始值。如果引用计数为0,自动的释放缓存空间。
}
AVPacket pkt = av_packet_alloc();*
先开辟一块空间用于存放AVPacket数据类型,再用指针pkt指向该空间。
int re = av_read_frame(ic, pkt);
读出当前流数据,并存于AVPacket中,
如果当前读到了视频packet,则只读出一packet,
如果当前读到了音频packet,根据音频格式读取固定的数据。
读取成功 流数据自动指向下一个packet,因此不需要一个变量来遍历所有帧
如果AVPacket包内存为空 读取失败,则读取无效,等待 av_read_frame()或者avformat_close_input()处理
av_seek_frame(ic, videoStream, seek_pos, AVSEEK_FLAG_BACKWARD|AVSEEK_FLAG_FRAME)
av_seek_frame
(ic, 打开的封装的上下文
videoindex,
用视频做seek,视频有B帧,为非线性播放, 音频为线性播放,所以如果用音频做seek,seek到的点对应的视频可能非关键帧,就会出现花屏的现象
pos,要seek到的位置
AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_FRAME);**
移动视频的进度条的话,因为时间点为离散的,所以可能没有pos这个时间点,此时设置参数为向后(左)找,并且找的是关键帧