首页 > 代码库 > OpenCV 播放mkv视频

OpenCV 播放mkv视频

作者:卿笃军

原文地址:http://blog.csdn.net/qingdujun/article/details/33371013


一、一个简单的OpenCV程序,用于播放硬盘中的视频文件

#include "opencv\highgui.h"  
  
int main()  
{
	cvNamedWindow("生活大爆炸.mkv",CV_WINDOW_AUTOSIZE);
	CvCapture* capture = cvCreateFileCapture("生活大爆炸.mkv");
	IplImage* frame = NULL;
	while (1)
	{
		frame = cvQueryFrame(capture);
		if (!frame)
			break;
		cvShowImage("生活大爆炸.mkv",frame);
		char c = cvWaitKey(33);
		if (c == 27)
			break;
	}
	cvReleaseCapture(&capture);
	cvDestroyWindow("生活大爆炸.mkv");
    return 0;  
}  

二、播放效果



使用OpenCV播放视频,几乎与使用它来显示图像一样容易。播放视频时只需要处理的新问题就是如何循环地顺序读取视频中的每一帧,以及如何从枯燥的电影视频的读取中退出该循环操作。


三、源代码分析

cvNamedWindow("生活大爆炸.mkv",CV_WINDOW_AUTOSIZE);

::新建一个标题为 “生活大爆炸.mkv” ,CV_WINDOW_AUTOSIZE 表示窗体自适应大小。

CvCapture* capture = cvCreateFileCapture("生活大爆炸.mkv");

::函数cvCreateFileCapture()通过参数设置确定要读入的mkv文件,返回一个指向CvCapture结构体的指针。这个结构体包括了所有关于读入mkv文件的信息,其中包含状态信息。在调用这个函数后,返回指针所指向的CvCapture结构体被初始化到所对应的mkv文件的开头。

frame = cvQueryFrame(capture);

::一旦进入while(1)循环,我们便开始读入mkv文件,cvQueryFrame的参数为CvCapture结构的指针。用来将下一帧视频文件载入内存(实际是填充或更新CvCapture结构中)。返回一个对应当前帧的指针。与cvLoadImage不同的是,cvLoadImage为图像分配内存空间,而cvQueryFrame使用已经在cvCapture结构中分配好的内存。这样的话,就没必要通过cvReleaseImage()对这个返回的图像指针进行释放,当CvCapture结构被释放后,每一帧图像所对应的内存空间即被释放。

char c = cvWaitKey(33);
if (c == 27)
break;

::表示当用户按ESC键时,退出视频播放。

四、实现滚动条&并使滚动条随着播放移动

#include "opencv\highgui.h"  
#include "opencv\cv.h"

int g_pos = 0;
CvCapture *g_capture = NULL; 

//回调函数
void onTrackbarSlide(int pos)
{
	cvSetCaptureProperty(g_capture,CV_CAP_PROP_POS_FRAMES,pos);
}
int main()  
{
	cvNamedWindow("生活大爆炸.mkv",CV_WINDOW_AUTOSIZE); //创建窗体
	g_capture = cvCreateFileCapture("生活大爆炸.mkv");  //获得要载入的mkv文件
	
	int frames = (int)cvGetCaptureProperty(g_capture,CV_CAP_PROP_FRAME_COUNT); //获得mkv文件总帧数
	if (frames != 0) //mpeg编码格式的文件不可后退拖动
	{
		cvCreateTrackbar("当前位置","生活大爆炸.mkv",&g_pos,frames,onTrackbarSlide);
	}
	IplImage* frame = NULL;
	
	while (1)
	{
		//获得下一帧
		frame = cvQueryFrame(g_capture);
		if (!frame)
			break;
		cvShowImage("生活大爆炸.mkv",frame);

		//获取视频播放位置
		int nowpos=(int)cvGetCaptureProperty(g_capture,CV_CAP_PROP_POS_FRAMES);
		//设置进度条位置,使其和视频播放同步
		cvSetTrackbarPos("当前位置","生活大爆炸.mkv", nowpos);
		//ESC退出
		char c = cvWaitKey(33);
		if (c == 27)
			break;
	}
	cvReleaseCapture(&g_capture);
	cvDestroyWindow("生活大爆炸.mkv");
    return 0;  
}  

五、滚动条效果


不过,貌似有点卡的样子。可能主要是帧数的问题吧,暂停33ms的问题。


参考文献:(美)布拉德斯基(Bradski,G.),(美)克勒(Kaehler,A.) 著,于仕琪,刘瑞祯 译.学习OpenCV(中文版)[M].北京:清华大学出版社,2009.21-26.

lisa的新浪博客.OpenCV笔记3 视频读取与进度条[CP/OL].http://blog.sina.com.cn/s/blog_67e477780100mpg9.html,2010-11-26/2014-06-23.

Augusdi的专栏.OpenCV播放视频并控制位置[CP/OL].http://blog.csdn.net/augusdi/article/details/9000592,2013-05-31/2014-06-23.