在dsp学习过程中,dsp使用UDP协议把图像帧通过xvid编码发送到PC机,虽然有基于MFC开发的上位机可以使用,但是还是想自己写一个,就开始作死……
既然下位机有enc_main,那么PC端肯定有对应的dec_main,找了找好像都是基于cpp的,而且因为版权问题还只给了源码,要自己编译生成.lib和.h文件,感觉过程有点复杂而且知道怎么把cpp的指针完美的转移到c#里,放弃了~
然后想的既然是视频播放嘛,就想着直接调用window media player直接播放视频流,弄到一般发现……这边压缩传过来的文件好像不是标准的视频流文件,并没有文件名啊什么的……直接填UDP连接只有个连接就绪,也不能用。
然后就想着用ffmpeg调用x264解码看看,就是调用外部程序ffmpeg.exe对保存到本地的数据流进行解码,然后提示非法输入参数……看来xvid传输的应该是裸数据流,并不带视频信息什么的……
想找ffmpeg基于c#的API,好像也找不到……
难过……暂时放弃……
坐等大佬指点迷津。
下面附上放弃前的程序,数据接收是没有问题了,就是不知道怎么解码。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace mp4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Thread thread = new Thread(socketThread)
{
IsBackground = true
};
thread.Start();
}
public void ConvertVideo(string strArg)
{
Process p = new Process();//建立外部调用线程
//p.StartInfo.FileName = "../../ffmpeg/bin/ffmpeg.exe";//要调用外部程序的绝对路径
p.StartInfo.FileName = "ffmpeg.exe";//要调用外部程序的绝对路径
p.StartInfo.Arguments = strArg;
p.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN)
p.StartInfo.RedirectStandardError = true;//把外部程序错误输出写到StandardError流中(这个一定要注意,FFMPEG的所有输出信息,都为错误输出流,用StandardOutput是捕获不到任何消息的...这是我耗费了2个多月得出来的经验...mencoder就是用standardOutput来捕获的)
p.StartInfo.CreateNoWindow = false;//不创建进程窗口
p.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN
p.Start();//启动线程
p.BeginErrorReadLine();//开始异步读取
p.WaitForExit();//阻塞等待进程结束
p.Close();//关闭进程
p.Dispose();//释放资源
}
private void Output(object sendProcess, DataReceivedEventArgs output)
{
if (!String.IsNullOrEmpty(output.Data))
{
//处理方法...
Console.WriteLine(output.Data);
}
}
private void socketThread()
{
//创建一个UDP的SOCKET
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //定义一个Socket
//本机IP
IPAddress ipaddress = IPAddress.Parse("192.168.1.10");
//端口11000(所有网卡的IP都行)
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, 8080);
//接收到信息时,此变量用于保存信息
EndPoint senderRemote = (EndPoint)new IPEndPoint(IPAddress.Any, 0);
// SOCKET绑定端口号,可以进行收发了
s.Bind(endPoint);
while (true)
{
byte[] recData = new Byte[40960]; //接收缓冲区
int recTime = 0; //需要接收的次数
int m4v_Size = 0; //码流大小
int m4v_Type = 0; //IP帧类型,监测数据一直没有变
int length=0; //接收到的文件大小
byte[] msg = new Byte[4096]; //消息头接收
int len = s.ReceiveFrom(msg, SocketFlags.None, ref senderRemote);//接收消息,如果消息不来,一直阻塞
if (len != 16)
continue;
if (msg[0] != 255 ||//FF
msg[1] != 165 ||//A5
msg[2] != 90 || //5A
msg[3] != 255) //FF
continue;
recTime = msg[7] * 256 * 65536 + msg[6] * 65536 + msg[5] * 256 + msg[4];
m4v_Size = msg[11] * 256 * 65536 + msg[10] * 65536 + msg[9] * 256 + msg[8];
//m4v_Type = msg[15] * 256 * 65536 + msg[14] * 65536 + msg[13] * 256 + msg[12];
for (int i = 0; i < recTime; i++)
{
byte[] data_packet = new Byte[4096]; //消息头接收
int len_packet = s.ReceiveFrom(data_packet, SocketFlags.None, ref senderRemote);
if (len_packet > 0)
{
data_packet.CopyTo(recData, length);
length += len_packet;
}
}
Console.WriteLine("m4v_Size" + m4v_Size.ToString());
Console.WriteLine("length:" + length.ToString());
//Console.WriteLine("m4v_Type:" + m4v_Type.ToString());
File.Delete("mydata");
BinaryWriter bw = new BinaryWriter(new FileStream("mydata", FileMode.Create));
bw.Write(recData,0,m4v_Size);
bw.Close();
ConvertVideo("ffmpeg -i mydata -vcodec x264 -s 800*600 -an -f yuv420p xxx3.yuv");
}
//关闭SOCKET
s.Close();
}
}
}