FFMpeg提取视频关键帧

1. FFMpegSDK下载

下载FFMpegSDK,我在官网上找了好久,现在应该在官网上下载不了,于是就在CSDN上使用积分下载了一下,下载链接:FFMpegSDK
下载解压后:
在这里插入图片描述
把shared里面的bin文件复制到dev文件中
在这里插入图片描述
bin文件中的.dll文件
在这里插入图片描述
复制后的dev文件
在这里插入图片描述

2. 建立vs工程

建立头文件
在这里插入图片描述
配置属性页>>VC++目录>>包含目录
配置属性页>>VC++目录>>库目录
把刚才的dev中include路径和lib路径分别放入包含目录和库目录中。
在这里插入图片描述
在这里插入图片描述
配置属性页>>链接器>>输入>>附加依赖项
把lib文件夹里面的lib文件添加进附加依赖项中
avcodec.lib
avdevice.lib
avfilter.lib
avformat.lib
avutil.lib
postproc.lib
swresample.lib
swscale.lib
把bin中的文件复制到项目文件中,把测试视频也放入
在这里插入图片描述

环境配置完成
注意
属性页中的两点:
字符集一定改成多字节的
SOL检查改成否
在这里插入图片描述
在这里插入图片描述

3. 程序

获取视频流程序:

int getStream(AVFormatContext **fmt_ctx, AVCodecContext **dec_ctx, const char* file_name) {int video_stream_index = -1;int ret;bool decoder_init = false;//打开视频文件if ((ret = avformat_open_input(fmt_ctx, file_name, NULL, NULL)) < 0) {av_log(NULL, AV_LOG_ERROR, "fail to open input file.\n");return ret;}//获取流信息if ((ret = avformat_find_stream_info(*fmt_ctx, NULL)) < 0) {av_log(NULL, AV_LOG_ERROR, "fail to find stream information.\n");avformat_close_input(fmt_ctx);return ret;}//从多个流中寻找视频流for (int i = 0; i < (*fmt_ctx)->nb_streams; i++) {if ((*fmt_ctx)->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {video_stream_index = i;//进行解码器的初始化if (!decoder_init) {*dec_ctx = (*fmt_ctx)->streams[i]->codec;AVCodec *cod = avcodec_find_decoder((*dec_ctx)->codec_id);if (!cod) {av_log(NULL, AV_LOG_ERROR, "fail to find decoder.\n");avformat_close_input(fmt_ctx);return 1;}if (avcodec_open2(*dec_ctx, cod, NULL) != 0) {av_log(NULL, AV_LOG_ERROR, "fail to open codecer.\n");avformat_close_input(fmt_ctx);return 2;}decoder_init = true;}}return 0;}return video_stream_index;
}

保存图片的程序:

void saveImage(const char *filename, unsigned char *data, int width, int height) {CImage image;image.Create(width, height, 32, 0);//依次写入每个像素点的RGB值for (int i = 0; i < width; i++)for (int j = 0; j < height; j++) {image.SetPixelRGB(i, j,data[j * width * 3 + i * 3 + 0],data[j * width * 3 + i * 3 + 1],data[j * width * 3 + i * 3 + 2]);}image.Save(filename);
}

视频编码解码的程序:

int decoder(AVFormatContext** fmt_ctx, AVCodecContext** dec_ctx, int video_stream_index, AVFrame *pFrame, AVFrame *pFrameColor, int* width, int* height)
{AVPacket packet;int i = 0;int frameFinished;uint8_t *buffer;int numBytes;char filename[32];//计算图像所需空间大小并分配空间numBytes = avpicture_get_size(AV_PIX_FMT_RGB24, (*dec_ctx)->width, (*dec_ctx)->height);buffer = (uint8_t*)av_malloc(numBytes);avpicture_fill((AVPicture *)pFrameColor, buffer, AV_PIX_FMT_RGB24, (*dec_ctx)->width, (*dec_ctx)->height);//读取视频帧并解码得到图像while (av_read_frame(*fmt_ctx, &packet) >= 0) {if (packet.stream_index == video_stream_index) {avcodec_decode_video2(*dec_ctx, pFrame, &frameFinished, &packet);//得到已解码的图像if (frameFinished){if (pFrame->key_frame == 1)			//判断是否为关键帧{struct SwsContext *img_convert_ctx = NULL;img_convert_ctx = sws_getCachedContext(img_convert_ctx, (*dec_ctx)->width,(*dec_ctx)->height, (*dec_ctx)->pix_fmt,(*dec_ctx)->width, (*dec_ctx)->height,AV_PIX_FMT_RGB24, SWS_BICUBIC,NULL, NULL, NULL);if (!img_convert_ctx) {fprintf(stderr, "Cannot initialize sws conversion context\n");exit(1);}//将解码后的图像格式转化为RGB24sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data,pFrame->linesize, 0, (*dec_ctx)->height, pFrameColor->data,pFrameColor->linesize);//将图像写入jpg文件sprintf(filename, "result%d.jpg", ++i);saveImage(filename, pFrameColor->data[0], (*dec_ctx)->width, (*dec_ctx)->height);printf("keyframe %d get\n", i);}}}av_free_packet(&packet);}printf("finished");//释放信息av_free(buffer);av_free(pFrameColor);av_free(pFrame);avcodec_close(*dec_ctx);avformat_close_input(fmt_ctx);
}

主程序:

int main()
{//初始化并分配帧AVFormatContext *fmt_ctx = NULL;AVCodecContext *dec_ctx = NULL;AVFrame *pf = av_frame_alloc();AVFrame *pfc = av_frame_alloc();int video_stream_index;int width, height;av_register_all();//读取视频video_stream_index = getStream(&fmt_ctx, &dec_ctx, "video1.mp4");//解码并保存关键帧数据为jpg图片输出decoder(&fmt_ctx, &dec_ctx, video_stream_index, pf, pfc, &width, &height);}

完整项目链接:FFMpeg关键帧提取


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部