先来看两个编解码有关的数据结构:
AVCodec:包含了编解码器的一些方法,比如在解码时将packet发给解码器时的代码如下:
re = avcodec_send_packet(av, pkt);
将指向编解码器的指针与pkt一起给avcodec_send_packet函数
AVCodecContext:作为编解码器的上下文,包含了编解码器的环境,简单来说,AVCodec是说如何编解码,这个就是告诉他相应属性设置,如对应视频来说,长宽,以及编码相应设置是否包含B桢,GOP是多少等。
///02找视频解码器,
const AVCodec *vcodec=avcodec_find_decoder(ic->streams[videoindex]->codecpar->codec_id);
if (!vcodec)
{
cout << "can't find the codec id" << ic->streams[videoindex]->codecpar->codec_id << endl;
getchar();
return -1;
}
cout<< " find the video codec id"<< ic->streams[videoindex]->codecpar->codec_id << endl;
///03创建解码器上下文
AVCodecContext *vc=avcodec_alloc_context3(vcodec);
///04配置解码器上下文参数
avcodec_parameters_to_context(vc, ic->streams[videoindex]->codecpar);
//八线程解码
vc->thread_count = 8;
///05打开解码器上下文
re = avcodec_open2(vc, 0, 0);
if (re != 0)
{
char buf[1024] = { 0 };
av_strerror(re, buf, sizeof(buf) - 1);
cout << "open audio codec failed!" << buf << endl;
getchar();
return -1;
}
cout << "video codec success!" << endl;
01注册解码器
avcodec_register_all()也被弃用了,在新版ffmpeg中不需要注册
02找视频解码器
在读帧前进行该操作,可通过av_find_best_stream()来找:
先定义一个指向AVcodec的常量指针vcodec,
av_find_best_stream()的第五个参数为AVCodec的二级指针,用于改变vcodec的指向
但这样的话解码和解封装在一起,耦合度太大,这里用id号获取
const AVCodec *vcodec=avcodec_find_decoder(ic->streams[videoindex]->codecpar->codec_id);
但有可能找不到流中的解码器号,这里要做个判断看看是否找到解码器
if (!vcodec)
{
cout << "can't find the codec id" << ic->streams[videoindex]->codecpar->codec_id << endl;
getchar();
return -1;
}
03创建解码器上下文
AVCodecContext *vc=avcodec_alloc_context3(vcodec);
将指向解码器的指针传入,开辟一块空间用于放置解码器相关的信息,该空间用vc标记
04配置解码器上下文参数
avcodec_parameters_to_context(vc, ic->streams[videoindex]->codecpar);
将流中的codec参数复制到解码器上下文中
05打开解码器上下文
re = avcodec_open2(vc, 0, 0);
第二个参数是解码器codec,但在03创建上下文的时候已经传进去了,这里就不用再传了,设为0就行了
if (re != 0)
{
char buf[1024] = { 0 };
av_strerror(re, buf, sizeof(buf) - 1);//用buf存放错误信息
cout << "open audio codec failed!" << buf << endl;
getchar();
return -1;
}
打开音频解码同理,改下名字就行了:
///01注册解码器
//avcodec_register_all()也被弃用了
///02找视频解码器,在读帧前进行该操作,可通过av_find_best_stream()来找,但这样的话解码和解封装在一起,耦合度太大,这里用id号获取
const AVCodec* acodec = avcodec_find_decoder(ic->streams[audioindex]->codecpar->codec_id);
//有可能找不到流中的解码器号,这里要做个判断看看是否找到解码器
if (!vcodec)
{
cout << "can't find the codec id" << ic->streams[audioindex]->codecpar->codec_id << endl;
getchar();
return -1;
}
cout << " find the audio codec id" << ic->streams[audioindex]->codecpar->codec_id << endl;
///03创建解码器上下文
AVCodecContext* ac = avcodec_alloc_context3(acodec);//将指向解码器的指针传入,开辟一块空间用于放置解码器相关的信息
///04配置解码器上下文参数
avcodec_parameters_to_context(ac, ic->streams[audioindex]->codecpar);//将流中的codec参数复制到解码器上下文中
//八线程解码
vc->thread_count = 8;
///05打开解码器上下文
re = avcodec_open2(ac, 0, 0);//第二个参数是解码器codec,但在创建上下文的时候已经传进去了,这里就不用再传了
if (re != 0)
{
char buf[1024] = { 0 };
av_strerror(re, buf, sizeof(buf) - 1);//用buf存放错误信息
cout << "open audio codec failed!" << buf << endl;
getchar();
return -1;
}
cout << "video codec success!" << endl;