结构
AVCodecContext
相关函数:avcodec_alloc_context3(申请一块AVCodecContext空间)、avcodec_free_context(释放AVCodecContext空间)
AVFrane
1> uint8_t *data[AV_NUM_DATA_POINTERS]:数据内容,视频表示一行数据,音频表示一个通道数据
2> int line_size[AV_NUM_DATA_POINTERS]:数据大小,视频表示一行数据大小,音频表示一个通道数据大小
3> int width, int height:视频参数
4> int nb_samples:音频参数,表示单通道的样本数量,如1024,一个样本2个字节
5> int64_t pts,int64_t dts:显示时间、解码时间
6> int sample_rate, uint64_t channel_layout, int channels:音频参数
7> format:像素格式
相关函数av_frame_alloc(申请内存)、av_frame_free(释放内存)、av_frame_ref(增加引用计数)、av_frame_clone(拷贝frame)、av_frame_unref(减少引用计数)
函数
1> avcodec_register_all:注册所有的解码器
2> avcodec_find_decoder:查找对应的解码器
@param enum AVCodecID id:解码器id
@return AVCodec *:解码器
3> avcodec_find_decoder_by_name:通过名字查找解码器
4> avcodec_open2:打开
@param AVCodecContext *avctx:解码上下文
@param AVCodec *codec:解码器,如果上下文alloc已经指定avcodec可以不传
@param AVDictionary **options:参数
5> avcodec_parameters_to_context:复制解码参数,主要用于从stream->codecpar拷贝参数
6> avcode_send_packet:异步解码发送数据
@param AVCodecContext *avctx:解码上下文
@param AVPacket *avpkt:packet数据
7> avcodec_receive_frame:异步解码接收数据
@param AVCodecContext *avctx:解码上下文
@param AVFrame *frame:解码后的frame
8> avcodec_close:关闭解码器
示例程序
代码(解封装代码已在上篇博客中介绍,不赘述)
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
AVFormatContext *ic = getIc();
if (nullptr == ic) {
return -1;
}
// 注册解码器 @deperated 废弃的函数可以不用调用
// avcodec_register_all();
int AudioStreamIndex = av_find_best_stream(ic, AVMediaType::AVMEDIA_TYPE_AUDIO, -1, -1, 0, 0);
AVStream *auStream = ic->streams[AudioStreamIndex];
// 获取音频解码器
AVCodec *acodec = avcodec_find_decoder(auStream->codecpar->codec_id);
if (nullptr == acodec) {
// 错误处理
return -1;
}
cout << "aucode find codec, id = " << auStream->codecpar->codec_id << endl;
// 创建解码器上下文
AVCodecContext *ac = avcodec_alloc_context3(acodec);
// 复制解码器参数
avcodec_parameters_to_context(ac, auStream->codecpar);
// 设置线程参数
ac->thread_count = 8;
// 打开解码器上下文
int ret = avcodec_open2(ac, acodec, 0);
if (0 != ret) {
// 错误处理
return -1;
}
cout << "aucode open success" << endl;
int VideoStreamIndex = av_find_best_stream(ic, AVMediaType::AVMEDIA_TYPE_VIDEO, -1, -1, 0, 0);
AVStream *vuStream = ic->streams[VideoStreamIndex];
// 获取视频解码器
AVCodec *vcodec = avcodec_find_decoder(vuStream->codecpar->codec_id);
if (nullptr == vcodec) {
// 错误处理
return -1;
}
cout << "avcode find codec, id = " << vuStream->codecpar->codec_id << endl;
// 创建解码器上下文
AVCodecContext *vc = avcodec_alloc_context3(vcodec);
// 复制解码器参数
avcodec_parameters_to_context(vc, vuStream->codecpar);
// 设置线程参数
vc->thread_count = 8;
// 打开解码器上下文
ret = avcodec_open2(vc, vcodec, 0);
if (0 != ret) {
// 错误处理
return -1;
}
cout << "avcode open success" << endl;
// 分配并初始化AVPacket
AVPacket *pkt = av_packet_alloc();
// 分配并初始化AVFrame
AVFrame *frame = av_frame_alloc();
while(1) {
// 读取帧数据
int ret = av_read_frame(ic, pkt);
if (0 != ret) {
break;
}
AVCodecContext *cc = nullptr;
if (pkt->stream_index == AudioStreamIndex) {
cc = ac;
}
if (pkt->stream_index == VideoStreamIndex) {
cc = vc;
}
// 异步解码发送数据
ret = avcodec_send_packet(cc, pkt);
// 发送完成后pkt不再使用,引用计数减1,为0时释放空间
av_packet_unref(pkt);
if (0 != ret) {
// 错误处理
continue;
}
while (0 == avcodec_receive_frame(cc, frame)) {
cout << "recv frame: format = " << frame->format << ", linesize = " << frame->linesize[0] << endl;
}
// 线程延迟,不要打印太快
xsleep(500);
}
av_frame_free(&frame);
av_packet_free(&pkt);
avcodec_close(ac);
avcodec_close(vc);
freeIc(ic);
return a.exec();
}
输出