#define BUFFERSIZE 1024
//注册所支持的所有的文件(容器)格式及其对应的CODEC av_register_all()
/*
av_register_all该函数注册支持的所有的文件格式(容器)及其对应的CODEC,只需要调用一次,故一般放在main函数中。也可以注册某个特定的容器格式,但通常来说不需要这么做
*/
av_register_all();
AVFormatContext *pFormatCtx;
pFormatCtx = avformat_alloc_context();
char url[BUFFERSIZE];
bzero(&url, sizeof(BUFFERSIZE));
//打开文件 avformat_open_input() 对应的是 avformat_close_input()
/*
avformat_open_input该函数读取文件的头信息,并将其信息保存到AVFormatContext结构体中。其调用如下
AVFormatContext* pFormatCtx = nullptr;
avformat_open_input(&pFormatCtx, filenName, nullptr, nullptr)
第一个参数是AVFormatContext结构体的指针,第二个参数为文件路径;第三个参数用来设定输入文件的格式,如果设为null,将自动检测文件格式;第四个参数用来填充AVFormatContext一些字段以及Demuxer的private选项。
AVFormatContext包含有较多的码流信息参数,通常由avformat_open_input创建并填充关键字段。
*/
avformat_open_input(&pFormatCtx, url, NULL, NULL);
//从文件中提取流信息 avformat_find_stream_info()
avformat_find_stream_info(pFormatCtx, NULL);
//在多个数据流中找到视频流 video stream(类型为MEDIA_TYPE_VIDEO)
int index = -1;
AVCodecContext *pCodecCtx;
for (int i=0; i<pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
index = i;
pCodecCtx = pFormatCtx->streams[i]->codec;
break;
}
}
if (index<0) {
printf("can not find stream");
}
//查找video stream 相对应的解码器 avcodec_find_decoder
AVCodec *pCodec =avcodec_find_decoder(pCodecCtx->codec_id);
//打开解码器 avcodec_open2()
int open_ret =avcodec_open2(pCodecCtx, pCodec, NULL);
if (open_ret<0) {
printf("open coder failed");
return -1;
}
//为解码帧分配内存 av_frame_alloc()
AVFrame *picFrame = av_frame_alloc();
AVPacket package ;
//从流中读取读取数据到Packet中 av_read_frame()
while (av_read_frame(pFormatCtx, &package)>=0) {
if (package.stream_index==index) {
int finished = 0;
// 对video 帧进行解码,调用 avcodec_decode_video2()
avcodec_decode_video2(pCodecCtx, picFrame, &finished, &package);
if (finished) {
//do something
}
}
}
//关闭
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
av_frame_free(&picFrame);
av_packet_unref(&package);
FFmpeg 解码
最新推荐文章于 2024-05-16 09:17:54 发布