7.MIL构建一个视频播放器

前面讲解了MIL视频的保存、加载和播放,那么有不少人私信我说按照我的讲解构建的视频播放器有问题,这里综合他们的问题,我这里演示一个简单的播放器,它实现了简单的视频播放功能:打开视频、播放视频和暂停视频。如果你想实现更复杂的功能可以在此基础上扩展。在此过程中,我会指出常犯的错误。

另外,需要补充说明的是,这里的MIL做的播放器,由于支持的视频编码的格式和完善程度有限,并不支持通用视频 的打开,例如如果你在网上下了一段AVI视频那么很可能用这个播放器是打不开的,我们用这里的视频功能主要是构建软件内建的视频录制、保存和播放功能,录制保存的视频用通用播放器是可以打开的。

先讲一下构建一个简单视频播放器的流程:

1.选择要播放的文件

2.查询要打开的视频的相关参数

3.根据查询到的相关参数分配和视频文件对应的MIL Buffer

4.当按开始播放时新建一个播放线程,在此线程中按照查询到的帧率参数间隔一定时间for循环读取视频文件一帧并显示,在for循环中必须有一个事件信号来控制是否继续播放

5.当按暂停播放时设置事件信号使for循环不再继续,即暂停播放

6.当按继续播放时设置事件信号使for循环继续,即继续播放

当然这里查询参数可以在新建线程外也可以在新建线程中来做,这里为了方便把2和3的工作放到了新建线程中做,那么新建线程的工作就是传入一个待播放的文件名,用一个事件信号控制播放线程的开始、继续和暂停。

这里常犯的错误是猜测待播放的视频文件参数来分配Buffer,前面已经讲过MIL Buffer的匹配转换问题,如果视频文件每一帧的大小(800*600等)、类型(8+UNSIGNED等)、格式(AVI_DIB等)和分配的Buffer不匹配的话就会在读入的时候做一个转换。如果只是大小不同做截断操作还好,如果是格式和类型不同那么会大大的消耗时间和性能,如果你的电脑上的显卡够好或安装了Matrox板卡,这时候还看不出大差别,如果你的电脑只是个普通的集显的话,那么基本上在播放的过程中你看不到画面,只有等待整个视频播放完了你看到最后一帧,因为在加载过程中CPU都被耗在Buffer转换上了。很多人反映在实验室的工控机上播放正常,在自己的电脑上播放不正常就是这个原理。总的来说,除非你完全确定,就是不要去猜测视频格式,同样的道理如果对Windows设备编程(包括普通的显示器GDI操作和工业设备程序等)理解比较深入的话也会理解,一般编写 面向设备的程序是不会去猜测其参数的,都会采取查询分配的形式。(有机会,我会考虑出Windows编程系列教程)

下面给出代码

开始并播放

选择要打开的文件,新建线程

 

void CMILPlayDlg::OnPlay() 
{
	//选择文件
	CFileDialog openFileDlg(TRUE);
	openFileDlg.m_ofn.lpstrTitle = TEXT("打开待播放的AVI");
	openFileDlg.m_ofn.lpstrFilter = TEXT("AVI(*.avi)\0*.avi\0\0");
	openFileDlg.m_ofn.lpstrDefExt = TEXT("avi");
	
	if (IDOK == openFileDlg.DoModal())
	{
		params.csFileToPlay = openFileDlg.GetFileName();
		params.hwnd = GetDlgItem(ID_SHOWAREA)->GetSafeHwnd();
		params.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);

		_beginthread(ThreadPlay, 0, ¶ms);
	}
}

在新建线程中查询要打开的视频的相关参数、根据查询到的相关参数分配和视频文件对应的MIL Buffer、照查询到的帧率参数间隔一定时间for循环读取视频文件一帧并显示

 

 

void ThreadPlay(PVOID pvoid)
{
	PPARAMS pparams = (PPARAMS)pvoid;
	CString filename;
	HWND hwnd;

	filename = pparams->csFileToPlay;
	hwnd = pparams->hwnd;

	long bufferNums = MbufDiskInquire(filename.GetBuffer(256), M_NUMBER_OF_IMAGES, M_NULL);
	long frameRate = MbufDiskInquire(filename.GetBuffer(256), M_FRAME_RATE, M_NULL);
	long xWidth = MbufDiskInquire(filename.GetBuffer(256),  M_SIZE_X, M_NULL);
	long yHeight = MbufDiskInquire(filename.GetBuffer(256),  M_SIZE_Y, M_NULL);
	long bufBand = MbufDiskInquire(filename.GetBuffer(256),  M_SIZE_BAND , M_NULL);
	long bufType = MbufDiskInquire(filename.GetBuffer(256), M_TYPE, M_NULL);

	//预分配buffer
	if (M_NULL != MilBufferAvi)
	{
		MbufFree(MilBufferAvi);
	}
	MbufAllocColor(MilSystem, bufBand, xWidth, yHeight, bufType, M_DISP+M_IMAGE, &MilBufferAvi);
	MbufClear(MilBufferAvi, 0x0);
	
	//这里的ID_SHOWAREA一定不要分配成static text类型,若是static text类型对话框管理器默认会
	//重绘它造成冲突这样导致播放出问题,最好是picture框架类型
	MdispSelectWindow(MilDisplay, MilBufferAvi, hwnd);
	
	MbufImportSequence(filename.GetBuffer(256), M_DEFAULT, M_NULL, M_NULL, M_NULL, M_NULL, M_NULL, M_OPEN);
	int i;
	for (i= 0; i < bufferNums; i++)
	{	
		WaitForSingleObject(pparams->hEvent, INFINITE);

		MbufImportSequence(filename.GetBuffer(256), M_DEFAULT, M_LOAD, M_NULL, &MilBufferAvi, i, 1, M_READ);
		Sleep(long(1.0 / frameRate * 1000));
	}
	MbufImportSequence(filename.GetBuffer(256), M_DEFAULT, M_NULL, M_NULL, M_NULL, M_NULL, M_NULL, M_CLOSE);
}

 

 

 

这里要说明是用于显示播放视频的子窗口类型一定不能是static text类型,按照MSDN描述“The control's parent window or dialog box must not process the WM_CTLCOLORSTATIC message.”即对话框管理会默认管理static text控件重绘,如果我们读取一帧图像并显示到该子窗口上的话,该子窗口会在对话框管理器的驱使下用原来的背景色重绘该区域,如果你播放视频的时候出现一闪一闪的情况,请检查是否设置子窗口为static text。

暂停播放

设置事件信号使for循环不再继续

 

void CMILPlayDlg::OnPause() 
{
	// TODO: Add your control notification handler code here
	ResetEvent(params.hEvent);
}

 

继续播放

设置事件信号使for循环继续

 

void CMILPlayDlg::OnContinue() 
{
	// TODO: Add your control notification handler code here
	SetEvent(params.hEvent);
}


那么,这样一个简单的视频播放器就完成了,如果还有什么问题,请留言。

 

 

博客中完整源代码下载链接

至此,关于MIL的图像、采集和视频功能都已详细介绍其原理和使用方法,在这里可以下到笔者为实验室写的针对相机在线观测、录制视频和播放视频的一个小软件Grab,由于实验室版权限制,只有可执行文件,如果你也需要类似的软件那么Grab是个不错的选择。

原创,转载请注明来自http://blog.csdn.net/wenzhou1219

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值