H264行車記錄儀 視頻解析 用於監控
class Program
{
static void Main(string[] args)
{
try
{
Socket socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Any;
IPEndPoint point = new IPEndPoint(ip, 3687);
socketServer.Bind(point);
socketServer.Listen(10);
while (true)
{
try
{
Socket socketClient = socketServer.Accept();
ThreadPool.QueueUserWorkItem(Receive, socketClient);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
catch (Exception e)
{
}
}
/// <summary>
/// 截取包
/// </summary>
/// <param name="state"></param>
public static void SubPack(EndPoint NowPoint)
{
try
{
//認爲存在完整包體
int nowSub1078Index = dicSub[NowPoint].ToString().IndexOf("30316364");
while (nowSub1078Index > -1)
{
MsgModel m = new MsgModel();
m.imei = dicSub[NowPoint].ToString().Substring(nowSub1078Index + 16, 12);//卡號
m.channel = Convert.ToInt32(dicSub[NowPoint].ToString().Substring(nowSub1078Index + 28, 2), 16);//通道
m.dataType = Convert.ToInt32(dicSub[NowPoint].ToString().Substring(nowSub1078Index + 30, 1), 16);//數據類型
m.packMark = Convert.ToInt32(dicSub[NowPoint].ToString().Substring(nowSub1078Index + 31, 1), 16);//分包標識
string time = dicSub[NowPoint].ToString().Substring(nowSub1078Index + 32, 16);//時間戳
m.OfLastGJTime = Convert.ToInt32(dicSub[NowPoint].ToString().Substring(nowSub1078Index + 48, 4), 16);
m.OfLastTime = Convert.ToInt32(dicSub[NowPoint].ToString().Substring(nowSub1078Index + 52, 4), 16);
m.dataLength = Convert.ToInt32(dicSub[NowPoint].ToString().Substring(nowSub1078Index + 56, 4), 16);//包長度
m.data = dicSub[NowPoint].ToString().Substring(nowSub1078Index + 60, m.dataLength * 2);//H264數據
byte[] buffer = Comm.strToToHexByte(m.data);
if (!dicSubFFmpegPort.Keys.Contains(NowPoint))
{
int tempPort = new Random().Next(13688, 23688);
while (GetNextNoUsePort(tempPort))
{
tempPort = new Random().Next(13688, 23688);
}
Socket socketFFmpegServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Any;
IPEndPoint point = new IPEndPoint(ip, tempPort);
socketFFmpegServer.Bind(point);
socketFFmpegServer.Listen(10);
ThreadPool.QueueUserWorkItem(Start, " -re -i tcp://192.168.0.19:" + tempPort + " -r 15 -an -f flv rtmp://192.168.0.19:1935/hls/" + m.imei + m.channel);
Socket socketClient = socketFFmpegServer.Accept();
dicSubFFmpegPort[NowPoint] = socketClient;
}
dicSubFFmpegPort[NowPoint].Send(buffer);
dicSub[NowPoint].Remove(0, nowSub1078Index + 60 + (m.dataLength * 2));
dicSubLastTime[NowPoint] = DateTime.Now;
nowSub1078Index = dicSub[NowPoint].ToString().IndexOf("30316364");
}
//檢查超時鏈接
foreach (KeyValuePair<EndPoint, DateTime> temp in dicSubLastTime)
{
if (temp.Value < DateTime.Now.AddMinutes(-10))
{
dicSub.Remove(temp.Key);
dicSubFFmpegPort.Remove(temp.Key);
}
}
}
catch (Exception e)
{
//Console.WriteLine("SubPackError:" + e.Message);
}
}
/// <summary>
/// 端口是否佔用
/// </summary>
/// <param name="port"></param>
/// <returns></returns>
private static bool GetNextNoUsePort(int port)
{
bool inUse = false;
IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();
foreach (IPEndPoint endPoint in ipEndPoints)
{
if (endPoint.Port == port)
{
inUse = true;
break;
}
}
return inUse;
}
static Dictionary<EndPoint, StringBuilder> dicSub = new Dictionary<EndPoint, StringBuilder>();
static Dictionary<EndPoint, DateTime> dicSubLastTime = new Dictionary<EndPoint, DateTime>();
static Dictionary<EndPoint, Socket> dicSubFFmpegPort = new Dictionary<EndPoint, Socket>();
/// <summary>
/// 接收單設備
/// </summary>
/// <param name="state"></param>
public static void Receive(object state)
{
using (Socket socketClient = state as Socket)
{
try
{
while (true)
{
byte[] buffer = new byte[1024];
int len = socketClient.Receive(buffer);
try
{
string msg = BitConverter.ToString(buffer).Replace("-", string.Empty).ToUpper();
if (dicSub.Keys.Contains(socketClient.RemoteEndPoint))
{
dicSub[socketClient.RemoteEndPoint].Append(msg);
}
else
{
int msg1078Index = msg.IndexOf("30316364");
if (msg1078Index > -1)
{
dicSub[socketClient.RemoteEndPoint] = new StringBuilder(msg.Substring(msg1078Index));
}
}
if (dicSub[socketClient.RemoteEndPoint].ToString().IndexOf("30316364") > -1)
{
dicSubLastTime[socketClient.RemoteEndPoint] = DateTime.Now;
SubPack(socketClient.RemoteEndPoint);
}
}
catch (Exception e)
{
//Console.WriteLine(e.Message);
}
}
}
catch (Exception e)
{
}
finally
{
socketClient.Close();
socketClient.Dispose();
}
}
}
#region 直推所需
// ffmpeg進程
static Process process = new Process();
// ffmpeg路徑
const string FFmpegPath = @"D:\StreamData\ffmpeg-3.4.2-win64-static\bin\ffmpeg.exe";
/// <summary>
/// 開始
/// </summary>
public static void Start(object auguments)
{
Console.WriteLine(FFmpegPath + auguments);
ProcessStartInfo startInfo = new ProcessStartInfo(FFmpegPath, auguments + "");
startInfo.UseShellExecute = false;//必須不使用操作系統shell
startInfo.RedirectStandardInput = true;//可能接受來自調用程序的輸入信息
startInfo.RedirectStandardOutput = true;//由調用程序獲取輸出信息
startInfo.CreateNoWindow = false;//不顯示程序窗口
process.StartInfo = startInfo;
process.Start();
}
/// <summary>
/// 停止
/// </summary>
public static void Stop()
{
AttachConsole(process.Id);
SetConsoleCtrlHandler(IntPtr.Zero, true);
GenerateConsoleCtrlEvent(0, 0);
FreeConsole();
try
{
Process.GetProcessById(process.Id).Kill();
}
catch (Exception) { }
}
#region 模擬控制檯信號
/// <summary>
/// 附加到目標進程的console
/// </summary>
/// <param name="dwProcessId"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
static extern bool AttachConsole(int dwProcessId);
/// <summary>
/// 設置自己的ctrl+c處理,防止自己被終止
/// </summary>
/// <param name="handlerRoutine"></param>
/// <param name="add"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
static extern bool SetConsoleCtrlHandler(IntPtr handlerRoutine, bool add);
/// <summary>
/// 發送ctrl+c(注意:這是向所有共享該console的進程發送)
/// </summary>
/// <param name="dwCtrlEvent"></param>
/// <param name="dwProcessGroupId"></param>
/// <returns></returns>
[DllImport("kernel32.dll")]
static extern bool GenerateConsoleCtrlEvent(int dwCtrlEvent, int dwProcessGroupId);
/// <summary>
/// 脫離目標console
/// </summary>
/// <returns></returns>
[DllImport("kernel32.dll")]
static extern bool FreeConsole();
// 使用時
//AttachConsole(processId);
//SetConsoleCtrlHandler(IntPtr.Zero, true);
//GenerateConsoleCtrlEvent(0, 0);
//FreeConsole();
#endregion
#endregion
/// <summary>
/// 記錄日誌
/// </summary>
/// <param name="msg"></param>
public static void log(string name, string msg)
{
try
{
name = name.Replace("/", "").Replace("\\", "").Replace(":", "").Replace("*", "").Replace("\"", "").Replace("<", "").Replace(">", "").Replace("|", "").Replace("?", "").Replace("?", "");
using (StreamWriter sw = new StreamWriter(name + DateTime.Now.ToString("yyyyMMdd HH") + ".log", true))
{
sw.WriteLine(msg);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}