【发布时间】:2016-02-18 23:18:41
【问题描述】:
我正在尝试通过 HTTP 将来自 ffmpeg 的视频流传输到智能电视。它工作大约 5-10 分钟,然后电视结束播放。我调查了wireshark的问题,发现电视在停止播放时会发送一个零窗口数据包。我怀疑 tv 达到了其 I/O 或 CPU 过载的程度。
我附上了wireshark 捕获FILE(修剪下来)和屏幕截图。
192.168.0.103 => 电视(三星 UE42F5500)
192.168.0.101 => PC(电视和电脑都使用电缆连接到路由器,没有 wifi)
流是通过使用 HTTPListener 的 C# 应用程序完成的。我已经尝试了很多天和夜,但是更改编解码器、比特率、容器和各种 ffmpeg 选项以进行错误校正对播放时间没有影响。最近,我尝试在将流发送到电视时添加一个小睡眠,效果很好,在这台电视现在在大约 2-4 分钟内停止之前,现在有 20 毫秒的睡眠,它在大约 30 分钟内停止。所以这让我认为 PC 发送的速度比电视可以处理的快。如果我增加睡眠,如果我减少它,播放会变得生涩和失真,电视会更快停止。这是我达到的一点,我对尝试什么没有任何想法,任何提示或想法将不胜感激,谢谢。
下面是向电视发送数据的 sn-p。
void AcceptRequest(IAsyncResult result)
{
HttpListenerContext ctx = null;
try
{
HttpListener listener = (HttpListener)result.AsyncState;
ctx = listener.EndGetContext(result);
listener.BeginGetContext(new AsyncCallback(AcceptRequest), listener);
ctx.Response.StatusCode = 200;
ctx.Response.Headers.Clear();
ctx.Response.AddHeader("Content-Type", "video/x-ms-asf");
ctx.Response.AddHeader("transferMode.dlna.org", "Streaming");
// tv first sends a HEAD to get the headers then a GET to get the actual content then it plays
if (ctx.Request.HttpMethod != "HEAD")
{
using (Stream outputStream = ctx.Response.OutputStream)
{
try
{
//input stream comes from ffmpeg, i get it making a TcpClient connection in this method
using (Stream inputStream = GetVideoStream())
{
int bytesRead = 1;
while (bytesRead != 0)
{
//buffer size is 4096
byte[] buff = new byte[TransmitBufferSize + 1];
bytesRead = inputStream.Read(buff, 0, TransmitBufferSize);
outputStream.Write(buff, 0, bytesRead);
outputStream.Flush();
//this is the silly workaround that "slows" down the stream and allows the tv to play longer
Thread.Sleep(20);
}
}
}
catch (HttpListenerException ex)
{
if (ex.ErrorCode != 62)//The specified network name is no longer available
Globals.Log("Error on VideoServer Buffer copy loop exception={0} callerInfo={1} ", ex.ToString(), PrintDebugCallerInfo(ctx));
}
catch (Exception ex2)
{
Globals.Log("Error on VideoServer Buffer copy loop exception={0} callerInfo={1} ", ex2.ToString(), PrintDebugCallerInfo(ctx));
}
}
}
}
catch (Exception ex)
{
Globals.Log("Error on Accept request, callerInfo={0} exception={1}",PrintDebugCallerInfo(ctx), ex.ToString());
}
finally
{
try
{
ctx.Response.Close();
}
catch (HttpListenerException ex)
{
if (ex.ErrorCode != 1229)//connection invalid, normal it can occur
Globals.Log("Error closing response, error code:{0} ex:{1}",ex.ErrorCode, ex.ToString());
}
catch(Exception ex2)
{
Globals.Log("Error closing response, error ex:{0}",ex2.ToString());
}
}
}
数据流是:Sopcast Stream -> Decoded&Encoded with ffmpeg (以避免任何错误形式sopcast) -> 我的c#代码(使stream upnp兼容) -> TV
【问题讨论】:
标签: c# tcp network-programming streaming samsung-smart-tv