再来介绍下如何读取视频帧,打开视频参考前面的文章,首先需要创建一个帧的存放对象
AVPacket pkt;
memset(&pkt, 0, sizeof(AVPacket));
再通过 int err = av_read_frame(ic, &pkt); 读取帧数据,其中ic是之前打开的视频流句柄。读取视频帧后要注意一点av_read_frame会自动给视频帧分配空间,返回值0表示成功。
可以通过 av_packet_unref(&pkt);删除packet的控制,注意这里删除的不是packet对象的空间,而是packet对象指向的数据空间。
通过判断pkt的stream_index 成员可以判断此帧数据是不是视频
if (pkt.stream_index == videoStream),
videoStream是打开视频时存放的视频流索引,大部分文件都是0,参考前一篇文章。
- extern "C"
- {
- #include<libavformat/avformat.h>
- }
- //引用lib库,也可以在项目中设置,打开视频只需要用到这三个库
- #pragma comment(lib,"avformat.lib")
- #pragma comment(lib,"avutil.lib")
- #pragma comment(lib,"avcodec.lib")
- #include <iostream>
- using namespace std;
- int main(int argc, char *argv[])
- {
- //初始化所以ffmpeg的解码器
- av_register_all();
- char path[1024] = "video.mp4";
- //用来存放打开的视频流信息
- AVFormatContext *ic = NULL;
- //用来存储视频流索引
- int videoStream = 0;
- //打开视频播放流
- //path参数表示打开的视频路径,这个路径可以包括各种视频文件
- //也包括rtsp和http网络视频流
- //第三个参数表示传入的视频格式,我这边不传递有FFmpeg内部获取
- //最后一个参数是设置,我们这里也不传递
- int re = avformat_open_input(&ic, path, 0, 0);
- if (re != 0)
- {
- //获取到FFmpeg的错误信息
- char errorbuf[1024] = { 0 };
- av_strerror(re, errorbuf, sizeof(errorbuf));
- printf("open %s failed: %s\n", path, errorbuf);
- return -1;
- }
- //遍历视频流,里面包含音频流,视频流,或者字母流,我们这里只处理视频
- for (int i = 0; i < ic->nb_streams; i++)
- {
- AVCodecContext *enc = ic->streams[i]->codec;
- //确认是视频流
- if (enc->codec_type == AVMEDIA_TYPE_VIDEO)
- {
- //存放视频流索引,后面的代码要用到
- videoStream = i;
- //找到解码器,比如H264,解码器的信息也是ffmpeg内部获取的
- AVCodec *codec = avcodec_find_decoder(enc->codec_id);
- if (!codec)
- {
- printf("video code not find!\n");
- return -2;
- }
- //打开视频解码器,打开音频解码器用的也是同一个函数
- int err = avcodec_open2(enc, codec, NULL);
- if (err != 0)
- {
- char buf[1024] = { 0 };
- av_strerror(err, buf, sizeof(buf));
- printf(buf);
- return -3;
- }
- }
- }
- //创建视频帧对象
- AVPacket pkt;
- memset(&pkt, 0, sizeof(AVPacket));
- for (;;)
- {
- //读取视频帧
- int err = av_read_frame(ic, &pkt);
- if (err != 0)
- {
- //读到结尾或者出错
- char buf[1024] = { 0 };
- av_strerror(err, buf, sizeof(buf));
- printf(buf);
- break;
- }
- //判断是否是音频
- if (pkt.stream_index == videoStream)
- {
- printf("video pkt size is %d\n", pkt.size);
- //视频处理,解码或者存储
- }
- //视频帧数据空间
- av_packet_unref(&pkt);
- }
- }
更多的资料也可以关注我51CTO上的视频课程
夏老师的课堂 http://edu.51cto.com/lecturer/index/user_id-12016059.html
http://edu.51cto.com/course/course_id-8059.html
时间: 2024-10-13 21:10:30