ffmpeg解码+opencv显示+时间测试
2015-07-09 13:34
411 查看
/** * 抽取ffmpeg中的函数接口实现视频解码,再通过Opencv中的函数接口播放 */ #define _CRTDBG_MAP_ALLOC #include <crtdbg.h> #define __STDC_CONSTANT_MACROS #include <stdio.h> #include <Windows.h> #include <process.h> // Opencv #include <opencv/cv.h> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include "QueryPerformance.h" extern "C" { #include "libavutil/avutil.h" #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" //新版里的图像转换结构需要引入的头文件 #include "libswscale/swscale.h" }; using namespace cv; char filename[] = "cuc_ieschool.avi"; int main() { ***Codec *pCodec; //解码器指针 ***CodecContext* pCodecCtx; //ffmpeg解码类的类成员 ***Frame* pAvFrame; //多媒体帧,保存解码后的数据帧 ***FormatContext* pFormatCtx; //保存视频流的信息 av_register_all(); //注册库中所有可用的文件格式和编码器 pFormatCtx = avformat_alloc_context(); if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0) { //检查文件头部 printf("Can't find the stream!\n"); } if (av_find_stream_info(pFormatCtx) < 0) { //查找流信息 printf("Can't find the stream information !\n"); } int videoindex = -1; for (int i=0; i < pFormatCtx->nb_streams; ++i) //遍历各个流,找到第一个视频流,并记录该流的编码信息 { if (pFormatCtx->streams[i]->codec->codec_type == ***MEDIA_TYPE_VIDEO) { videoindex = i; break; } } if (videoindex == -1) { printf("Don't find a video stream !\n"); return -1; } pCodecCtx = pFormatCtx->streams[videoindex]->codec; //得到一个指向视频流的上下文指针 pCodec = avcodec_find_decoder(pCodecCtx->codec_id); //到该格式的解码器 if (pCodec == NULL) { printf("Cant't find the decoder !\n"); //寻找解码器 return -1; } if (avcodec_open2(pCodecCtx,pCodec,NULL) < 0) { //打开解码器 printf("Can't open the decoder !\n"); return -1; } pAvFrame = avcodec_alloc_frame(); //分配帧存储空间 ***Frame* pFrameBGR = avcodec_alloc_frame(); //存储解码后转换的RGB数据 // 保存BGR,opencv中是按BGR来保存的 int size = avpicture_get_size(***_PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height); uint8_t *out_buffer = (uint8_t *)av_malloc(size); avpicture_fill((***Picture *)pFrameBGR, out_buffer, ***_PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height); ***Packet* packet = (***Packet*)malloc(sizeof(***Packet)); printf("-----------输出文件信息---------\n"); av_dump_format(pFormatCtx, 0, filename, 0); printf("------------------------------"); struct SwsContext *img_convert_ctx; img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, ***_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL); //opencv cv::Mat pCvMat; pCvMat.create(cv::Size(pCodecCtx->width, pCodecCtx->height), CV_8UC3); int ret; int got_picture; cvNamedWindow("RGB", 1); CStopwatch stopwatchqq; int frame_counter = 0; //解码的帧数 for (;;) { if(av_read_frame(pFormatCtx, packet)>=0) { if(packet->stream_index==videoindex) { //计时 CStopwatch stopwatch; ret = avcodec_decode_video2(pCodecCtx, pAvFrame, &got_picture, packet); __int64 qwElapsedTime = stopwatch.Now(); // 单位为:毫秒(ms) printf("解码单帧的时间为:%d (ms)\n", qwElapsedTime); if(ret < 0) { printf("Decode Error.(解码错误)\n"); return -1; } if (got_picture) { frame_counter++; //YUV to RGB sws_scale(img_convert_ctx, (const uint8_t* const*)pAvFrame->data, pAvFrame->linesize, 0, pCodecCtx->height, pFrameBGR->data, pFrameBGR->linesize); memcpy(pCvMat.data, out_buffer, size); imshow("RGB", pCvMat); waitKey(1); } } av_free_packet(packet); } else { break; } } __int64 qwElapsedTimeqq = stopwatchqq.Now(); // 单位为:毫秒(ms) printf("\n总解码时间为:%d(ms)\n", qwElapsedTimeqq); printf("总视频帧数为:%d\n", frame_counter); av_free(out_buffer); av_free(pFrameBGR); av_free(pAvFrame); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); sws_freeContext(img_convert_ctx); cvDestroyWindow("RGB"); system("pause"); _CrtDumpMemoryLeaks(); return 0; }
// 添加png图片保存
/** * 抽取ffmpeg中的函数接口实现视频解码,再通过Opencv中的函数接口播放 */ #define _CRTDBG_MAP_ALLOC #include <crtdbg.h> #define __STDC_CONSTANT_MACROS #include <stdio.h> #include <Windows.h> #include <process.h> // Opencv #include <opencv/cv.h> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include "QueryPerformance.h" extern "C" { #include "libavutil/avutil.h" #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" //新版里的图像转换结构需要引入的头文件 #include "libswscale/swscale.h" }; using namespace cv; char filename[] = "cuc_ieschool.avi"; int main() { ***Codec *pCodec; //解码器指针 ***CodecContext* pCodecCtx; //ffmpeg解码类的类成员 ***Frame* pAvFrame; //多媒体帧,保存解码后的数据帧 ***FormatContext* pFormatCtx; //保存视频流的信息 av_register_all(); //注册库中所有可用的文件格式和编码器 pFormatCtx = avformat_alloc_context(); if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0) { //检查文件头部 printf("Can't find the stream!\n"); } if (av_find_stream_info(pFormatCtx) < 0) { //查找流信息 printf("Can't find the stream information !\n"); } int videoindex = -1; for (int i=0; i < pFormatCtx->nb_streams; ++i) //遍历各个流,找到第一个视频流,并记录该流的编码信息 { if (pFormatCtx->streams[i]->codec->codec_type == ***MEDIA_TYPE_VIDEO) { videoindex = i; break; } } if (videoindex == -1) { printf("Don't find a video stream !\n"); return -1; } pCodecCtx = pFormatCtx->streams[videoindex]->codec; //得到一个指向视频流的上下文指针 pCodec = avcodec_find_decoder(pCodecCtx->codec_id); //到该格式的解码器 if (pCodec == NULL) { printf("Cant't find the decoder !\n"); //寻找解码器 return -1; } if (avcodec_open2(pCodecCtx,pCodec,NULL) < 0) { //打开解码器 printf("Can't open the decoder !\n"); return -1; } pAvFrame = avcodec_alloc_frame(); //分配帧存储空间 ***Frame* pFrameBGR = avcodec_alloc_frame(); //存储解码后转换的RGB数据 // 保存BGR,opencv中是按BGR来保存的 int size = avpicture_get_size(***_PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height); uint8_t *out_buffer = (uint8_t *)av_malloc(size); avpicture_fill((***Picture *)pFrameBGR, out_buffer, ***_PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height); ***Packet* packet = (***Packet*)malloc(sizeof(***Packet)); printf("-----------输出文件信息---------\n"); av_dump_format(pFormatCtx, 0, filename, 0); printf("------------------------------"); struct SwsContext *img_convert_ctx; img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, ***_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL); //opencv cv::Mat pCvMat; pCvMat.create(cv::Size(pCodecCtx->width, pCodecCtx->height), CV_8UC3); int ret; int got_picture; cvNamedWindow("RGB", 1); CStopwatch stopwatchqq; int frame_counter = 0; //解码的帧序号 char buffer[50]; for (;;) { if(av_read_frame(pFormatCtx, packet)>=0) { if(packet->stream_index==videoindex) { //计时 CStopwatch stopwatch; ret = avcodec_decode_video2(pCodecCtx, pAvFrame, &got_picture, packet); __int64 qwElapsedTime = stopwatch.Now(); // 单位为:毫秒(ms) // printf("解码单帧的时间为:%d (ms)\n", qwElapsedTime); if(ret < 0) { printf("Decode Error.(解码错误)\n"); return -1; } if (got_picture) { frame_counter++; sprintf(buffer, "./pic/%d.png", frame_counter); //YUV to RGB sws_scale(img_convert_ctx, (const uint8_t* const*)pAvFrame->data, pAvFrame->linesize, 0, pCodecCtx->height, pFrameBGR->data, pFrameBGR->linesize); memcpy(pCvMat.data, out_buffer, size); imshow("RGB", pCvMat); // printf("pCvMat= %p\n", &pCvMat); imwrite(buffer, pCvMat);//将视频帧保存为png图片 waitKey(1); } } av_free_packet(packet); } else { break; } } __int64 qwElapsedTimeqq = stopwatchqq.Now(); // 单位为:毫秒(ms) printf("\n总解码时间为:%d(ms)\n", qwElapsedTimeqq); printf("总视频帧数为:%d\n", frame_counter); av_free(out_buffer); av_free(pFrameBGR); av_free(pAvFrame); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); sws_freeContext(img_convert_ctx); cvDestroyWindow("RGB"); system("pause"); _CrtDumpMemoryLeaks(); return 0; }
相关文章推荐
- 微信、陌陌等著名IM软件设计架构
- linux 系统负载高 如何检查
- linux 系统负载高 如何检查
- shell工具
- linux下调整进程、线程优先级
- 基本SHELL语句总结【20150709】
- Ubuntu 安装openGL
- HDU 5072 Coprime (单色三角形+容斥原理)
- PopupWindon实例
- codeforces 339D Xenia and Bit Operations 线段树
- linux(Centos)下编译安装gcc4.8.2
- linux下编译安装boost库
- ffmpeg解码+opencv显示
- Linux的s、t、i、a权限
- SharePoint自动化系列——Set MMS field value using PowerShell.
- 细说Linux系统优化
- Emgucv传递Image类参数给Opencv的Mat类
- windows下使用xShell向远程linux上传文件
- setsockopt()用法(参数详细说明)
- 如何加入该网站for Linux(绑定域名)