效果
C#VideoCapture多路视频播放
项目
代码
using OpenCvSharp;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MultiVideoDemo
{
public partial class Form4 : Form
{
public Form4()
{
InitializeComponent();
}
CancellationTokenSource ctsShow;
CancellationTokenSource[] taskCTS = new CancellationTokenSource[6];
ConcurrentQueue<Mat>[] matQueue = new ConcurrentQueue<Mat>[6];
int fps = 25;
string[] rtsp_url = new string[40];
List<RTSPURLInfo> play_rtsp_url = new List<RTSPURLInfo>();
/// <summary>
/// 停止
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
ctsShow.Cancel();
for (int i = 0; i < 6; i++)
{
taskCTS[i].Cancel();
}
}
private void Form1_Load(object sender, EventArgs e)
{
//初始化
for (int i = 0; i < 6; i++)
{
taskCTS[i] = new CancellationTokenSource();
matQueue[i] = new ConcurrentQueue<Mat>();
}
for (int i = 0; i < 40; i++)
{
rtsp_url[i] = "1.dav";
}
//play_rtsp_url
for (int i = 0; i < 6; i++)
{
play_rtsp_url.Add(new RTSPURLInfo((i + 1).ToString(), rtsp_url[i]));
}
}
/// <summary>
/// 播放
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
ctsShow = new CancellationTokenSource();
for (int i = 0; i < 6; i++)
{
taskCTS[i] = new CancellationTokenSource();
matQueue[i] = new ConcurrentQueue<Mat>();
}
play_rtsp_url.Clear();
for (int i = 0; i < 6; i++)
{
play_rtsp_url.Add(new RTSPURLInfo((i + 1).ToString(), rtsp_url[i]));
}
for (int i = 0; i < play_rtsp_url.Count; i++)
{
Task.Run(() => DecodeRTSP(play_rtsp_url[i].index, matQueue[i], play_rtsp_url[i].url, taskCTS[i].Token));
System.Threading.Thread.Sleep(100);
}
//显示线程
Task.Run(() =>
{
Mat mat = new Mat();
string winName = "video";
Cv2.NamedWindow(winName, WindowFlags.Normal);
Cv2.ResizeWindow(winName, fullSize);
int delay = (int)(1000 / fps);
Stopwatch stopwatch = new Stopwatch();
while (true)
{
stopwatch.Restart();
delay = (int)(1000 / fps);
if (ctsShow.IsCancellationRequested) break;
Mat frame = CombiningImages();
Cv2.ImShow(winName, frame);
delay = (int)(delay - stopwatch.ElapsedMilliseconds);
if (delay <= 0)
{
delay = 1;
}
Console.WriteLine("delay:" + delay.ToString());
Cv2.WaitKey(delay);
frame.Dispose();
}
Cv2.DestroyAllWindows();
});
}
OpenCvSharp.Size fullSize = new OpenCvSharp.Size(1008, 570);
OpenCvSharp.Size mainSize = new OpenCvSharp.Size(672, 380);
OpenCvSharp.Size subSize = new OpenCvSharp.Size(336, 190);
Mat CombiningImages()
{
Console.WriteLine(string.Format("matQueue0:{0},matQueue1:{1},matQueue2:{2},matQueue3:{3},matQueue4:{4},matQueue5:{5}"
, matQueue[0].Count
, matQueue[1].Count
, matQueue[2].Count
, matQueue[3].Count
, matQueue[4].Count
, matQueue[5].Count
));
Mat mat = Mat.Zeros(fullSize, MatType.CV_8UC3);
Mat mat0 = new Mat();
matQueue[0].TryDequeue(out mat0);
if (mat0 == null || mat0.Empty())
{
mat0 = Mat.Zeros(mainSize, MatType.CV_8UC3);
}
Cv2.Resize(mat0, mat0, mainSize);
Mat mat1 = new Mat();
matQueue[1].TryDequeue(out mat1);
if (mat1 == null || mat1.Empty())
{
mat1 = Mat.Zeros(subSize, MatType.CV_8UC3);
}
Cv2.Resize(mat1, mat1, subSize);
Mat mat2 = new Mat();
matQueue[2].TryDequeue(out mat2);
if (mat2 == null || mat2.Empty())
{
mat2 = Mat.Zeros(subSize, MatType.CV_8UC3);
}
Cv2.Resize(mat2, mat2, subSize);
Mat mat3 = new Mat();
matQueue[3].TryDequeue(out mat3);
if (mat3 == null || mat3.Empty())
{
mat3 = Mat.Zeros(subSize, MatType.CV_8UC3);
}
Cv2.Resize(mat3, mat3, subSize);
Mat mat4 = new Mat();
matQueue[4].TryDequeue(out mat4);
if (mat4 == null || mat4.Empty())
{
mat4 = Mat.Zeros(subSize, MatType.CV_8UC3);
}
Cv2.Resize(mat4, mat4, subSize);
Mat mat5 = new Mat();
matQueue[5].TryDequeue(out mat5);
if (mat5 == null || mat5.Empty())
{
mat5 = Mat.Zeros(subSize, MatType.CV_8UC3);
}
Cv2.Resize(mat5, mat5, subSize);
//第一张主图
Rect roi0 = new Rect(0, 0, 672, 380);
Mat position0 = new Mat(mat, roi0);
mat0.CopyTo(position0);
//第二张图
Rect roi1 = new Rect(672, 0, 336, 190);
Mat position1 = new Mat(mat, roi1);
mat1.CopyTo(position1);
//第三张图
Rect roi2 = new Rect(672, 190, 336, 190);
Mat position2 = new Mat(mat, roi2);
mat2.CopyTo(position2);
//第4张图
Rect roi3 = new Rect(672, 380, 336, 190);
Mat position3 = new Mat(mat, roi3);
mat3.CopyTo(position3);
//第5张图
Rect roi4 = new Rect(336, 380, 336, 190);
Mat position4 = new Mat(mat, roi4);
mat4.CopyTo(position4);
//第6张图
Rect roi5 = new Rect(0, 380, 336, 190);
Mat position5 = new Mat(mat, roi5);
mat5.CopyTo(position5);
mat0.Dispose();
mat1.Dispose();
mat2.Dispose();
mat3.Dispose();
mat4.Dispose();
mat5.Dispose();
position0.Dispose();
position1.Dispose();
position2.Dispose();
position3.Dispose();
position4.Dispose();
position5.Dispose();
return mat;
}
void DecodeRTSP(string index, ConcurrentQueue<Mat> matQueue, string url, CancellationToken cancellationToken = default)
{
VideoCapture vcapture = new VideoCapture(url);
if (!vcapture.IsOpened())
{
Console.WriteLine("打开视频文件失败");
return;
}
// 计算等待时间(毫秒)
int taskDelay = (int)(1000 / fps);
Stopwatch stopwatch = new Stopwatch();
while (true)
{
if (cancellationToken.IsCancellationRequested) break;
stopwatch.Restart();
Mat frame = new Mat();
if (!vcapture.Read(frame))
{
Console.WriteLine("读取失败");
break;
}
taskDelay = (int)(1000 / fps);
//中间标注数字,模拟路数
Cv2.PutText(frame, index.ToString(), new OpenCvSharp.Point(frame.Width / 2, frame.Height / 2), HersheyFonts.HersheySimplex, 20, Scalar.Red, 20);
matQueue.Enqueue(frame);
taskDelay = (int)(taskDelay - stopwatch.ElapsedMilliseconds);
if (matQueue.Count > 100)
{
Console.WriteLine("index:" + index + ",后续处理能力不足……");
}
if (matQueue.Count < 10)
{
taskDelay = taskDelay - 5;
}
if (taskDelay <= 0)
{
taskDelay = 0;
}
Console.WriteLine("index:" + index + ",taskDelay:" + taskDelay);
Task.Delay(taskDelay).Wait();
}
vcapture.Release();
}
/// <summary>
/// 取消第一路
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button4_Click(object sender, EventArgs e)
{
taskCTS[0].Cancel();
}
/// <summary>
/// 记载第7路
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
for (int i = 0; i < 6; i++)
{
taskCTS[i].Cancel();
}
for (int i = 0; i < 6; i++)
{
taskCTS[i] = new CancellationTokenSource();
}
//删除最后一个元素
play_rtsp_url.RemoveAt(play_rtsp_url.Count - 1);
//把第7路的地址 放到第一的位置
play_rtsp_url.Insert(0, new RTSPURLInfo("7", rtsp_url[6]));
for (int i = 0; i < play_rtsp_url.Count; i++)
{
Task.Run(() => DecodeRTSP(play_rtsp_url[i].index, matQueue[i], play_rtsp_url[i].url, taskCTS[i].Token));
System.Threading.Thread.Sleep(10);
}
}
/// <summary>
/// 加载第8路
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button5_Click(object sender, EventArgs e)
{
for (int i = 0; i < 6; i++)
{
taskCTS[i].Cancel();
}
for (int i = 0; i < 6; i++)
{
taskCTS[i] = new CancellationTokenSource();
}
//删除最后一个元素
play_rtsp_url.RemoveAt(play_rtsp_url.Count - 1);
//把第8路的地址 放到第一的位置
play_rtsp_url.Insert(0, new RTSPURLInfo("8", rtsp_url[7]));
for (int i = 0; i < play_rtsp_url.Count; i++)
{
Task.Run(() => DecodeRTSP(play_rtsp_url[i].index, matQueue[i], play_rtsp_url[i].url, taskCTS[i].Token));
System.Threading.Thread.Sleep(10);
}
}
}
public class RTSPURLInfo
{
public string index;
public string url;
public RTSPURLInfo(string index, string url)
{
this.index = index;
this.url = url;
}
}
}
using OpenCvSharp;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MultiVideoDemo
{
public partial class Form4 : Form
{
public Form4()
{
InitializeComponent();
}
CancellationTokenSource ctsShow;
CancellationTokenSource[] taskCTS = new CancellationTokenSource[6];
ConcurrentQueue<Mat>[] matQueue = new ConcurrentQueue<Mat>[6];
int fps = 25;
string[] rtsp_url = new string[40];
List<RTSPURLInfo> play_rtsp_url = new List<RTSPURLInfo>();
/// <summary>
/// 停止
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
ctsShow.Cancel();
for (int i = 0; i < 6; i++)
{
taskCTS[i].Cancel();
}
}
private void Form1_Load(object sender, EventArgs e)
{
//初始化
for (int i = 0; i < 6; i++)
{
taskCTS[i] = new CancellationTokenSource();
matQueue[i] = new ConcurrentQueue<Mat>();
}
for (int i = 0; i < 40; i++)
{
rtsp_url[i] = "1.dav";
}
//play_rtsp_url
for (int i = 0; i < 6; i++)
{
play_rtsp_url.Add(new RTSPURLInfo((i + 1).ToString(), rtsp_url[i]));
}
}
/// <summary>
/// 播放
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
ctsShow = new CancellationTokenSource();
for (int i = 0; i < 6; i++)
{
taskCTS[i] = new CancellationTokenSource();
matQueue[i] = new ConcurrentQueue<Mat>();
}
play_rtsp_url.Clear();
for (int i = 0; i < 6; i++)
{
play_rtsp_url.Add(new RTSPURLInfo((i + 1).ToString(), rtsp_url[i]));
}
for (int i = 0; i < play_rtsp_url.Count; i++)
{
Task.Run(() => DecodeRTSP(play_rtsp_url[i].index, matQueue[i], play_rtsp_url[i].url, taskCTS[i].Token));
System.Threading.Thread.Sleep(100);
}
//显示线程
Task.Run(() =>
{
Mat mat = new Mat();
string winName = "video";
Cv2.NamedWindow(winName, WindowFlags.Normal);
Cv2.ResizeWindow(winName, fullSize);
int delay = (int)(1000 / fps);
Stopwatch stopwatch = new Stopwatch();
while (true)
{
stopwatch.Restart();
delay = (int)(1000 / fps);
if (ctsShow.IsCancellationRequested) break;
Mat frame = CombiningImages();
Cv2.ImShow(winName, frame);
delay = (int)(delay - stopwatch.ElapsedMilliseconds);
if (delay <= 0)
{
delay = 1;
}
Console.WriteLine("delay:" + delay.ToString());
Cv2.WaitKey(delay);
frame.Dispose();
}
Cv2.DestroyAllWindows();
});
}
OpenCvSharp.Size fullSize = new OpenCvSharp.Size(1008, 570);
OpenCvSharp.Size mainSize = new OpenCvSharp.Size(672, 380);
OpenCvSharp.Size subSize = new OpenCvSharp.Size(336, 190);
Mat CombiningImages()
{
Console.WriteLine(string.Format("matQueue0:{0},matQueue1:{1},matQueue2:{2},matQueue3:{3},matQueue4:{4},matQueue5:{5}"
, matQueue[0].Count
, matQueue[1].Count
, matQueue[2].Count
, matQueue[3].Count
, matQueue[4].Count
, matQueue[5].Count
));
Mat mat = Mat.Zeros(fullSize, MatType.CV_8UC3);
Mat mat0 = new Mat();
matQueue[0].TryDequeue(out mat0);
if (mat0 == null || mat0.Empty())
{
mat0 = Mat.Zeros(mainSize, MatType.CV_8UC3);
}
Cv2.Resize(mat0, mat0, mainSize);
Mat mat1 = new Mat();
matQueue[1].TryDequeue(out mat1);
if (mat1 == null || mat1.Empty())
{
mat1 = Mat.Zeros(subSize, MatType.CV_8UC3);
}
Cv2.Resize(mat1, mat1, subSize);
Mat mat2 = new Mat();
matQueue[2].TryDequeue(out mat2);
if (mat2 == null || mat2.Empty())
{
mat2 = Mat.Zeros(subSize, MatType.CV_8UC3);
}
Cv2.Resize(mat2, mat2, subSize);
Mat mat3 = new Mat();
matQueue[3].TryDequeue(out mat3);
if (mat3 == null || mat3.Empty())
{
mat3 = Mat.Zeros(subSize, MatType.CV_8UC3);
}
Cv2.Resize(mat3, mat3, subSize);
Mat mat4 = new Mat();
matQueue[4].TryDequeue(out mat4);
if (mat4 == null || mat4.Empty())
{
mat4 = Mat.Zeros(subSize, MatType.CV_8UC3);
}
Cv2.Resize(mat4, mat4, subSize);
Mat mat5 = new Mat();
matQueue[5].TryDequeue(out mat5);
if (mat5 == null || mat5.Empty())
{
mat5 = Mat.Zeros(subSize, MatType.CV_8UC3);
}
Cv2.Resize(mat5, mat5, subSize);
//第一张主图
Rect roi0 = new Rect(0, 0, 672, 380);
Mat position0 = new Mat(mat, roi0);
mat0.CopyTo(position0);
//第二张图
Rect roi1 = new Rect(672, 0, 336, 190);
Mat position1 = new Mat(mat, roi1);
mat1.CopyTo(position1);
//第三张图
Rect roi2 = new Rect(672, 190, 336, 190);
Mat position2 = new Mat(mat, roi2);
mat2.CopyTo(position2);
//第4张图
Rect roi3 = new Rect(672, 380, 336, 190);
Mat position3 = new Mat(mat, roi3);
mat3.CopyTo(position3);
//第5张图
Rect roi4 = new Rect(336, 380, 336, 190);
Mat position4 = new Mat(mat, roi4);
mat4.CopyTo(position4);
//第6张图
Rect roi5 = new Rect(0, 380, 336, 190);
Mat position5 = new Mat(mat, roi5);
mat5.CopyTo(position5);
mat0.Dispose();
mat1.Dispose();
mat2.Dispose();
mat3.Dispose();
mat4.Dispose();
mat5.Dispose();
position0.Dispose();
position1.Dispose();
position2.Dispose();
position3.Dispose();
position4.Dispose();
position5.Dispose();
return mat;
}
void DecodeRTSP(string index, ConcurrentQueue<Mat> matQueue, string url, CancellationToken cancellationToken = default)
{
VideoCapture vcapture = new VideoCapture(url);
if (!vcapture.IsOpened())
{
Console.WriteLine("打开视频文件失败");
return;
}
// 计算等待时间(毫秒)
int taskDelay = (int)(1000 / fps);
Stopwatch stopwatch = new Stopwatch();
while (true)
{
if (cancellationToken.IsCancellationRequested) break;
stopwatch.Restart();
Mat frame = new Mat();
if (!vcapture.Read(frame))
{
Console.WriteLine("读取失败");
break;
}
taskDelay = (int)(1000 / fps);
//中间标注数字,模拟路数
Cv2.PutText(frame, index.ToString(), new OpenCvSharp.Point(frame.Width / 2, frame.Height / 2), HersheyFonts.HersheySimplex, 20, Scalar.Red, 20);
matQueue.Enqueue(frame);
taskDelay = (int)(taskDelay - stopwatch.ElapsedMilliseconds);
if (matQueue.Count > 100)
{
Console.WriteLine("index:" + index + ",后续处理能力不足……");
}
if (matQueue.Count < 10)
{
taskDelay = taskDelay - 5;
}
if (taskDelay <= 0)
{
taskDelay = 0;
}
Console.WriteLine("index:" + index + ",taskDelay:" + taskDelay);
Task.Delay(taskDelay).Wait();
}
vcapture.Release();
}
/// <summary>
/// 取消第一路
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button4_Click(object sender, EventArgs e)
{
taskCTS[0].Cancel();
}
/// <summary>
/// 记载第7路
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
for (int i = 0; i < 6; i++)
{
taskCTS[i].Cancel();
}
for (int i = 0; i < 6; i++)
{
taskCTS[i] = new CancellationTokenSource();
}
//删除最后一个元素
play_rtsp_url.RemoveAt(play_rtsp_url.Count - 1);
//把第7路的地址 放到第一的位置
play_rtsp_url.Insert(0, new RTSPURLInfo("7", rtsp_url[6]));
for (int i = 0; i < play_rtsp_url.Count; i++)
{
Task.Run(() => DecodeRTSP(play_rtsp_url[i].index, matQueue[i], play_rtsp_url[i].url, taskCTS[i].Token));
System.Threading.Thread.Sleep(10);
}
}
/// <summary>
/// 加载第8路
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button5_Click(object sender, EventArgs e)
{
for (int i = 0; i < 6; i++)
{
taskCTS[i].Cancel();
}
for (int i = 0; i < 6; i++)
{
taskCTS[i] = new CancellationTokenSource();
}
//删除最后一个元素
play_rtsp_url.RemoveAt(play_rtsp_url.Count - 1);
//把第8路的地址 放到第一的位置
play_rtsp_url.Insert(0, new RTSPURLInfo("8", rtsp_url[7]));
for (int i = 0; i < play_rtsp_url.Count; i++)
{
Task.Run(() => DecodeRTSP(play_rtsp_url[i].index, matQueue[i], play_rtsp_url[i].url, taskCTS[i].Token));
System.Threading.Thread.Sleep(10);
}
}
}
public class RTSPURLInfo
{
public string index;
public string url;
public RTSPURLInfo(string index, string url)
{
this.index = index;
this.url = url;
}
}
}
下载
源码下载
版权归原作者 天天代码码天天 所有, 如有侵权,请联系我们删除。