本文介绍了通过directX问题从网络摄像头捕获!!!的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,
我正在使用C#和direcX库从网络摄像头捕获视频.

我设法以.avi格式捕获了高质量的视频(该格式由库设置,但我没有做到).

但这是问题所在,每分钟捕获的视频大约有1.0 GB的硬盘空间!因此,我使用了DirectX帮助文件中提到的压缩器方法.
但是,现在它使文件更小了,但是现在有2个真正令人讨厌的问题:

1.捕获预览时非常慢!
2.捕获的文件不再平滑并且大量泄漏!

请帮助我.... void openMJEPGFileItem_Click(object sender,System.EventArgs e)
{
URLForm形式=新的URLForm();

form.Description =输入MJPEG视频流的URL:";
form.URLs =新字符串[]
{
"http://129.186.47.239/axis-cgi/mjpg/video.cgi?resolution=352x240",
"http://195.243.185.195/axis-cgi/mjpg/video.cgi?camera=3",
"http://195.243.185.195/axis-cgi/mjpg/video.cgi?camera=4",
"http://chipmunk.uvm.edu/cgi-bin/webcam/nph-up​​date.cgi?dummy=garb"
};

if(form.ShowDialog(this)== DialogResult.OK)
{
//创建视频源
MJPEGStream mjpegSource =新的MJPEGStream();
mjpegSource.VideoSource = form.URL;

//打开
OpenVideoSource(mjpegSource);
}
}

-------------------------------------------------- -------------------------------------------------- ----------------
命名空间VideoSource
{
使用系统;
使用System.Drawing;
使用System.IO;
使用System.Text;
使用System.Threading;
使用System.Net;

///< summary>
///MJPEGSource-MJPEG流支持
///</summary>
公共类MJPEGStream:IVideoSource
{
私有字符串源;
私有字符串login = null;
私人字符串密码= null;
私有对象userData = null;
私人int框架;已收到;
private int bytesReceived;
私人布尔useSeparateConnectionGroup = true;

私有const int bufSize = 512 * 1024; //缓冲区大小
私有const int readSize = 1024; //要读取的部分大小

私有线程thread = null;
私人ManualResetEvent stopEvent = null;
私人ManualResetEvent reloadEvent = null;

//新框架事件
公共事件CameraEventHandler NewFrame;

//SeparateConnectioGroup属性
//表示要在单独的连接组中打开WebRequest
公共布尔SeparateConnectionGroup
{
得到{return useSeparateConnectionGroup; }
设置{useSeparateConnectionGroup = value; }
}
//VideoSource属性
公共字符串VideoSource
{
得到{返回源; }
设置
{
来源=值;
//信号提示重新加载
如果(thread!= null)
reloadEvent.Set();
}
}
//登录属性
公共字符串登录
{
得到{返回登录名; }
设置{登录=值; }
}
//密码属性
公共字符串密码
{
得到{返回密码; }
设置{密码=值; }
}
//FramesReceived属性
public int FramesReceived
{
获取
{
int帧= framesReceived;
frameReceived = 0;
返回帧;
}
}
//BytesReceived属性
public int BytesReceived
{
获取
{
int字节=接收到的字节数;
bytesReceived = 0;
返回字节;
}
}
//UserData属性
公共对象UserData
{
得到{return userData; }
设置{userData =值; }
}
//获取视频源线程的状态
Public bool Running
{
获取
{
如果(thread!= null)
{
如果(thread.Join(0)==假)
返回true;

//线程未在运行,因此释放了资源
Free();
}
返回false;
}
}



//构造函数
公共MJPEGStream()
{
}

//开始工作
public void Start()
{
如果(thread == null)
{
frameReceived = 0;
bytesReceived = 0;

//创建事件
stopEvent =新的ManualResetEvent(false);
reloadEvent =新的ManualResetEvent(false);

//创建并启动新线程
线程=新线程(新ThreadStart(WorkerThread));
thread.Name =源;
thread.Start();
}
}

//发出信号以停止工作
公共无效SignalToStop()
{
//停止线程
如果(thread!= null)
{
//发出停止信号
stopEvent.Set();
}
}

//等待线程停止
公共无效的WaitForStop()
{
如果(thread!= null)
{
//等待线程停止
thread.Join();

Free();
}
}

//中止线程
公共无效Stop()
{
如果(this.Running)
{
thread.Abort();
WaitForStop();
}
}

//免费资源
私人void Free()
{
线程= null;

//发布事件
stopEvent.Close();
stopEvent = null;
reloadEvent.Close();
reloadEvent = null;
}

//线程入口点
公共无效的WorkerThread()
{
byte []缓冲区=新的byte [bufSize]; //缓冲区以读取流

而(true)
{
//重置重新加载事件
reloadEvent.Reset();

HttpWebRequest req = null;
Web响应响应= null;
流stream = null;
byte []分隔符= null;
byte [] delimiter2 = null;
byte [] boundary = null;
int boundaryLen,delimiterLen = 0,delimiter2Len = 0;
int读取,todo = 0,总计= 0,pos = 0,align = 1;
int开始= 0,停止= 0;

//对齐
//1 =搜索图片开始
//2 =搜索图像结尾
试试
{
//创建请求
req =(HttpWebRequest)WebRequest.Create(源);
//设置登录名和密码
if((登录!=空)&&(密码!=空)&&(登录!=")))
req.Credentials =新的NetworkCredential(登录名,密码);
//设置连接组名称
如果(useSeparateConnectionGroup)
req.ConnectionGroupName = GetHashCode().ToString();
//获得响应
resp = req.GetResponse();

//检查内容类型
字符串ct = resp.ContentType;
如果(ct.IndexOf("multipart/x-mixed-replace")== -1)
抛出新的ApplicationException("Invalid URL");

//获取边界
ASCIIEncoding编码=新的ASCIIEncoding();
边界= encoding.GetBytes(ct.Substring(ct.IndexOf("boundary =",0)+ 9));
boundaryLen = boundary.Length;

//获取响应流
流= resp.GetResponseStream();

//循环
while((!stopEvent.WaitOne(0,true))&&(!reloadEvent.WaitOne(0,true)))
{
//检查总读取
如果(总计> bufSize-readSize)
{
System.Diagnostics.Debug.WriteLine("flushing");
total = pos = todo = 0;
}

//从流中读取下一部分
如果((read = stream.Read(buffer,total,readSize))== 0)
抛出新的ApplicationException();

总计+ =已读;
待办事项+ =阅读;

//增加接收的字节数计数器
bytesReceived + =已读取;

//我们知道定界符吗?
if(定界符== null)
{
//找到边界
pos = ByteArrayUtils.Find(缓冲区,边界,pos,待办事项);

如果(pos == -1)
{
//找不到
todo = boundaryLen-1;
pos =总计-待办事项;
继续;
}

待办事项=总计-pos;

如果(todo< 2)
继续;

//检查新行分隔符类型
如果(buffer [pos + boundaryLen] == 10)
{
delimiterLen = 2;
定界符=新字节[2] {10,10};
delimiter2Len = 1;
delimiter2 =新字节[1] {10};
}
其他
{
delimiterLen = 4;
定界符=新字节[4] {13,10,13,10};
delimiter2Len = 2;
delimiter2 =新字节[2] {13,10};
}

pos + = boundaryLen + delimiter2Len;
待办事项=总计-pos;
}

//边界对齐
/* if((align == 0)&&(todo> = boundaryLen))
{
如果(ByteArrayUtils.Compare(buffer,boundary,pos))
{
//边界位于
align = 1;
待办事项-= boundaryLen;
pos + = boundaryLen;
}
其他
align = 2;
} */

//搜索图片
如果(align == 1)
{
start = ByteArrayUtils.Find(buffer,delimiter,pos,todo);
如果(开始!= -1)
{
//找到定界符
开始+ = delimiterLen;
pos =开始;
待办事项=总计-pos;
align = 2;
}
其他
{
//找不到分隔符
todo = delimiterLen-1;
pos =总计-待办事项;
}
}

//搜索图像结尾
while((align == 2)&&(todo> = boundaryLen))
{
停止= ByteArrayUtils.Find(缓冲区,边界,位置,待办事项);
如果(停止!= -1)
{
pos =停止;
待办事项=总计-pos;

//递增帧计数器
framesReceived ++;

//停止时的图像
如果(NewFrame!= null)
{
位图bmp =(位图)Bitmap.FromStream(new MemoryStream(buffer,start,stop-start));
//通知客户
NewFrame(this,new CameraEventArgs(bmp));
//释放图像
bmp.Dispose();
bmp = null;
}
//System.Diagnostics.Debug.WriteLine(找到映像结束,大小=" +(停止-开始));

//移位数组
pos =停止+ boundaryLen;
待办事项=总计-pos;
Array.Copy(buffer,pos,buffer,0,todo);

总计=待办事项;
pos = 0;
align = 1;
}
其他
{
//找不到分隔符
todo = boundaryLen-1;
pos =总计-待办事项;
}
}
}
}
捕获(WebException ex)
{
System.Diagnostics.Debug.WriteLine("=============:" + ex.Message);
//等待一段时间,然后再尝试
Thread.Sleep(250);
}
抓(ApplicationException ex)
{
System.Diagnostics.Debug.WriteLine("=============:" + ex.Message);
//等待一段时间,然后再尝试
Thread.Sleep(250);
}
catch(ex ex例外)
{
System.Diagnostics.Debug.WriteLine("=============:" + ex.Message);
}
终于
{
//中止请求
如果(req!= null)
{
req.Abort();
req = null;
}
//关闭响应流
如果(流!=空)
{
stream.Close();
流=空;
}
//关闭响应
如果(resp!= null)
{
resp.Close();
resp = null;
}
}

//需要停止吗?
如果(stopEvent.WaitOne(0,true))
休息;
}
}
}
}


-------------------------------------------------- -------------------------------------------------- ------------------

可以使用dshow来平滑视频
^ ]


hi everyone,
I''m using C# and direcX library to capture video from a webcam.

i managed to capture video with a great quality in .avi format(which the format is set by the library, i didn''t make it).

but here is the problem each minute of captured video is approximately 1.0 GB of harddisk space!!!
So i used its compressor method which was mentioned in directX help file.
BUT, now it makes the file MUCH smaller but 2 real annoying problems are there NOW:

1. when it''s capturing the preview is SO MUCH slow!
2. the captured file is not smooth any more and leaks alot!

please help me.... I''m confused SO MUCH

解决方案



这篇关于通过directX问题从网络摄像头捕获!!!的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-04 22:52