ffmpeg获取运动矢量及显示
2016-11-08 21:49
1611 查看
最近有个项目需要研究视频压缩域,主要对于运动矢量。获取运动矢量的各种算法比较复杂,发现ffmpeg可以直接获取,非常简便。
初学ffmpeg,雷霄骅大神的博客提供了非常大的帮助,http://blog.csdn.net/leixiaohua1020/article/details/15811977/。
下载ffmpeg源码,在doc/example下有extract_mvs.c文件 ,一个提取运动矢量简单例程。在vs2010编译,遇到一些麻烦,参考http://blog.csdn.net/leixiaohua1020/article/details/12747899,http://blog.csdn.net/leixiaohua1020/article/details/12029697。
关于运动矢量的显示,或者说原始帧数据的显示,雷神用的是SDL,这里使用的是opencv.
在源码基础上改的,图像bgr数据保存在pFrameRGB->data[0],这是关键。转为IplImage然后画出运动矢量,显示播放。
后话:这是几个月前的东西,很多细节和遇到的问题都记不太清了。工作中很多知识没有总结,一段时间过后忘记了,跟没做过一样,没有任何进步,有时候想起来非常惋惜,这也是写博客的意义所在。不要找借口说工作太忙,其实就是懒!!
初学ffmpeg,雷霄骅大神的博客提供了非常大的帮助,http://blog.csdn.net/leixiaohua1020/article/details/15811977/。
下载ffmpeg源码,在doc/example下有extract_mvs.c文件 ,一个提取运动矢量简单例程。在vs2010编译,遇到一些麻烦,参考http://blog.csdn.net/leixiaohua1020/article/details/12747899,http://blog.csdn.net/leixiaohua1020/article/details/12029697。
关于运动矢量的显示,或者说原始帧数据的显示,雷神用的是SDL,这里使用的是opencv.
在源码基础上改的,图像bgr数据保存在pFrameRGB->data[0],这是关键。转为IplImage然后画出运动矢量,显示播放。
//#ifdef __cplusplus // #include "stdio.h" #include "stdlib.h" #include "string.h" using namespace std; extern "C" { #include <libavutil/motion_vector.h> #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" }; //#endif //#pragma comment(lib,"avutil.lib") //#pragma comment(lib,"avcodec.lib") //#pragma comment(lib,"avformat.lib") #include <cv.h> #include <highgui.h> using namespace std; static AVFormatContext *fmt_ctx = NULL; static AVCodecContext *video_dec_ctx = NULL; static AVStream *video_stream = NULL; static const char *src_filename = NULL; static int video_stream_idx = -1; static AVFrame *frame = NULL; static AVFrame *pFrameRGB=NULL; static AVPicture *pFrame=NULL; static AVPacket pkt; static int video_frame_count = 0; static SwsContext *img_convert_ctx=NULL; //FILE *output; FILE *fp; static IplImage *imgShow=NULL; static IplImage *imgShow2=NULL; static unsigned char* frameData=0; typedef struct{ int mv_sx; int mv_sy; int mv_x; int mv_y; }MV_DATA; const int K=3; void uchar2IplImageBGR(unsigned char *inArrayCur, int img_w, int img_h,IplImage* pImg); int img_w,img_h; const int mbNum=131100;//1920*1080/16+1920/4*2+1080/4*2; int num,nozero; CvPoint p1,p2; MV_DATA global_mv; int j,k; unsigned char *out_roi; unsigned char *double_show1; unsigned char *double_show2; IplImage* roi_show=NULL; IplImage* double_show =NULL; unsigned char *gray_roi; IplImage* ipl_gray_roi =NULL; static int decode_packet(int *got_frame, int cached) { MV_DATA* mv_data=(MV_DATA*)malloc(mbNum*sizeof(MV_DATA));//读取运动矢量保存到mv_data中 num=0,nozero=0; ave_x=0,ave_y=0;//平均值 out_roi=(unsigned char *)malloc(img_w*img_h); roi_show=cvCreateImage(cvSize(img_w,img_h),IPL_DEPTH_8U,1); double_show = cvCreateImage(cvSize(img_w*2,img_h),IPL_DEPTH_8U,3); double_show1=(unsigned char *)malloc(img_w*img_h*3); double_show2=(unsigned char *)malloc(img_w*img_h*3); gray_roi=(unsigned char *)malloc(img_w*img_h); ipl_gray_roi = cvCreateImage(cvSize(img_w,img_h),IPL_DEPTH_8U,1); vector<MV_DATA> mv_datas; for(int s=0;s<img_w*img_h;s++) { out_roi[s]=0; } int decoded = pkt.size; *got_frame = 0; if (pkt.stream_index == video_stream_idx) { int ret = avcodec_decode_video2(video_dec_ctx, frame, got_frame, &pkt); if (ret < 0) { //fprintf(stderr, "Error decoding video frame (%s)\n", av_err2str(ret)); return ret; } if (*got_frame) { int i; AVFrameSideData *sd; video_frame_count++; sd = av_frame_get_side_data(frame, AV_FRAME_DATA_MOTION_VECTORS); if (sd) { img_convert_ctx = sws_getContext(video_dec_ctx->width, video_dec_ctx->height, video_dec_ctx->pix_fmt, video_dec_ctx->width, video_dec_ctx->height, AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL); sws_scale(img_convert_ctx, (const uint8_t* const*)frame->data, frame->linesize, 0, video_dec_ctx->height, pFrameRGB->data, pFrameRGB->linesize); //fwrite(pFrameRGB->data[0],(video_dec_ctx->width)*(video_dec_ctx->height)*3,1,output); //memcpy(frameData,pFrameRGB->data[0],video_dec_ctx->width*video_dec_ctx->height*3); uchar2IplImageBGR(pFrameRGB->data[0],video_dec_ctx->width,video_dec_ctx->height,imgShow); cvCopy(imgShow,imgShow2); const AVMotionVector *mvs = (const AVMotionVector *)sd->data; for (i = 0; i < sd->size / sizeof(*mvs); i++) { const AVMotionVector *mv = &mvs[i]; //printf("%d,%2d,%2d,%2d,%4d,%4d,%4d,%4d,0x%"PRIx64"\n", //video_frame_count, mv->source, //mv->w, mv->h, mv->src_x, mv->src_y, c159 //mv->dst_x, mv->dst_y); p1.x=mv->src_x; p1.y=mv->src_y; p2.x=mv->dst_x; p2.y=mv->dst_y; cvLine(imgShow,p2,p2,cvScalar( 0,0,255 ),1,8,0); } cvShowImage("1",imgShow); if(cvWaitKey(50)>=32) cvWaitKey(0); sws_freeContext(img_convert_ctx); } } } free(out_roi); free(double_show1); free(double_show2); free(gray_roi); cvReleaseImage(&roi_show); cvReleaseImage(&double_show); cvReleaseImage(&ipl_gray_roi); free(mv_data); mv_datas.clear(); return decoded; } static int open_codec_context(int *stream_idx, AVFormatContext *fmt_ctx, enum AVMediaType type) { int ret; AVStream *st; AVCodecContext *dec_ctx = NULL; AVCodec *dec = NULL; AVDictionary *opts = NULL; ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0); if (ret < 0) { fprintf(stderr, "Could not find %s stream in input file '%s'\n", av_get_media_type_string(type), src_filename); return ret; } else { *stream_idx = ret; st = fmt_ctx->streams[*stream_idx]; /* find decoder for the stream */ dec_ctx = st->codec; dec = avcodec_find_decoder(dec_ctx->codec_id); if (!dec) { fprintf(stderr, "Failed to find %s codec\n", av_get_media_type_string(type)); return AVERROR(EINVAL); } /* Init the video decoder */ av_dict_set(&opts, "flags2", "+export_mvs", 0); if ((ret = avcodec_open2(dec_ctx, dec, &opts)) < 0) { fprintf(stderr, "Failed to open %s codec\n", av_get_media_type_string(type)); return ret; } } return 0; } int main(int argc, char** argv) { int ret = 0, got_frame; //string name; //getline(cin,name,'\n'); src_filename = "1.mp4"; cvNamedWindow("1",0); cvNamedWindow("2",0); char motionname[] = "MV_Data.txt"; fp = fopen(motionname, "w"); av_register_all(); if (avformat_open_input(&fmt_ctx, src_filename, NULL, NULL) < 0) { fprintf(stderr, "Could not open source file %s\n", src_filename); exit(1); } if (avformat_find_stream_info(fmt_ctx, NULL) < 0) { fprintf(stderr, "Could not find stream information\n"); exit(1); } if (open_codec_context(&video_stream_idx, fmt_ctx, AVMEDIA_TYPE_VIDEO) >= 0) { video_stream = fmt_ctx->streams[video_stream_idx]; video_dec_ctx = video_stream->codec; } av_dump_format(fmt_ctx, 0, src_filename, 0); if (!video_stream) { fprintf(stderr, "Could not find video stream in the input, aborting\n"); ret = 1; goto end; } frame = av_frame_alloc(); pFrameRGB=av_frame_alloc(); uint8_t *out_buffer; out_buffer=new uint8_t[avpicture_get_size(AV_PIX_FMT_BGR24, video_dec_ctx->width, video_dec_ctx->height)]; avpicture_fill((AVPicture *)pFrameRGB, out_buffer, AV_PIX_FMT_BGR24, video_dec_ctx->width, video_dec_ctx->height); imgShow = cvCreateImage(cvSize(video_dec_ctx->width,video_dec_ctx->height),IPL_DEPTH_8U,3); imgShow2 = cvCreateImage(cvSize(video_dec_ctx->width,video_dec_ctx->height),IPL_DEPTH_8U,3); frameData=(unsigned char *)malloc(video_dec_ctx->width*video_dec_ctx->height*3); img_w=video_dec_ctx->width; img_h=video_dec_ctx->height; if (!frame) { fprintf(stderr, "Could not allocate frame\n"); ret = AVERROR(ENOMEM); goto end; } /* initialize packet, set data to NULL, let the demuxer fill it */ av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; //output=fopen("out.rgb","wb+"); /* read frames from the file */ while (av_read_frame(fmt_ctx, &pkt) >= 0) { AVPacket orig_pkt = pkt; do { ret = decode_packet(&got_frame, 0); if (ret < 0) break; pkt.data += ret; pkt.size -= ret; } while (pkt.size > 0); av_packet_unref(&orig_pkt); } /* flush cached frames */ pkt.data = NULL; pkt.size = 0; do { decode_packet(&got_frame, 1); } while (got_frame); end: //fclose(output); fclose(fp); avcodec_close(video_dec_ctx); avformat_close_input(&fmt_ctx); av_frame_free(&frame); av_frame_free(&pFrameRGB); cvReleaseImage(&imgShow); free(frameData); getchar(); return ret < 0; } void uchar2IplImageBGR(unsigned char *inArrayCur, int img_w, int img_h,IplImage* pImg) { int i,j; for (i = 0; i < img_h; i++) { for (j = 0; j < img_w*3; j++) { *(pImg->imageData + i*pImg->widthStep+j)=inArrayCur[(i)*img_w*3+j] ; } } }
后话:这是几个月前的东西,很多细节和遇到的问题都记不太清了。工作中很多知识没有总结,一段时间过后忘记了,跟没做过一样,没有任何进步,有时候想起来非常惋惜,这也是写博客的意义所在。不要找借口说工作太忙,其实就是懒!!
相关文章推荐
- ffmpeg获取运动矢量问题
- ffdshow神奇的功能:视频播放时显示运动矢量和QP
- rtsp获取视频帧 ffmpeg解码h264数据 D3D显示yv12数据
- Mpeg2Peter中运动矢量的获取
- ffdshow神奇的功能:视频播放时显示运动矢量和QP
- ffdshow神奇的功能:视频播放时显示运动矢量和QP
- 获取并显示数据
- 如何获取字符串的屏幕显示长度,以及在button上文字换行。
- 用 Microsoft Ajax Library 异步获取页面并显示
- [导入]用 Microsoft Ajax Library 异步获取页面并显示
- flex中获取并显示数据
- 获取input文本框中高亮显示的值
- JavaScript 获取浏览器的显示区域大小信息
- 用 Microsoft Ajax Library 异步获取页面并显示2跨域读取RSS并处理
- JavaScript获取浏览器的显示区域大小信息
- (DB ,sqlserver2005,tips)如何获取用户自定义的触发器的内容(在sqlserver2005树形菜单没有显示)
- 备忘:解决ajax获取页面直接显示乱码的方法 [摘]
- 解决ajax获取页面直接显示乱码的方法
- 获取一个网页数据返回的编码类型是gzip,解压后,网页中包含的中文字段变成了乱码,只需要把编码更改为BIG5 ,繁体字就正常显示了!
- 获取网页内容并显示出来