TCP传输视频流的失真

时间:2014-06-05 19:42:04

标签: c++ tcp udp streaming video-streaming

我目前正在开发一个客户端 - 服务器应用程序。服务器渲染图像,使用Nvidias H264编码器压缩它们并将它们发送到客户端。在客户端,图像被解压缩并显示。我使用TCP和UDP Berkeley Windows套接字的包装器。 UDP工作正常,所有图片都正常显示。切换到TCP传输时,会出现一些随机失真。不是一直以来,只是在某些场合。失败通常如下所示:

http://de.tinypic.com/r/14sedf6/8

它可以保持约5到10帧(60fps)。网站 http://www.onsip.com/about-voip/sip/udp-versus-tcp-for-voip表示,使用TCP进行音频传输会导致某种抖动,这对于最终用户来说是“不可接受的”。。您是否认为抖动是导致观察到的图像失真或其他任何线索的原因?

这是TCP包装器的代码。像Bind()这样的函数在超类中实现并且应该可以工作,因为udp包装器也使用它们。 :)

TcpSocket::TcpSocket()
{
    WSADATA wsaData;

    int i = WSAStartup(MAKEWORD(2,2), &wsaData);

    m_Sock = -1;
}

bool TcpSocket::Create()
{
    if ((m_Sock = socket(AF_INET, SOCK_STREAM, 0)) > 0)
        return true;
    return false;
}

bool TcpSocket::Listen(int que)
{
    if (listen(m_Sock, que) == 0)
        return true;
    return false;
}

bool TcpSocket::Accept(TcpSocket &clientSock)
{
    int size = sizeof(struct sockaddr);
    clientSock.m_Sock = accept(m_Sock,
        (struct sockaddr *) &clientSock.m_SockAddr, (socklen_t *) &size);
    if (clientSock.m_Sock == -1)
        cout << "accept failed: " << WSAGetLastError() << endl;

    WSACleanup();
    return false;
    return true;
}

bool TcpSocket::Connect(string address, int port)
{
    struct in_addr *addr_ptr;
    struct hostent *hostPtr;
    string add;
    try
    {
        hostPtr = gethostbyname(address.c_str());
        if (hostPtr == NULL)
            return false;

        // the first address in the list of host addresses
        addr_ptr = (struct in_addr *) *hostPtr->h_addr_list;

        // changed the address format to the Internet address in standard dot notation
        add = inet_ntoa(*addr_ptr);
        if (add.c_str() == "")
            return false;
    } catch (int e)
    {
        return false;
    }

    struct sockaddr_in sockAddr;
    sockAddr.sin_family = AF_INET;
    sockAddr.sin_port = htons(port);
    sockAddr.sin_addr.s_addr = inet_addr(add.c_str());
    if (connect(m_Sock, (struct sockaddr *) &sockAddr, sizeof(struct sockaddr))== 0)
        return true;
    return false;

}

int TcpSocket::Receive(char *buff, int buffLen)
{
    return recv(m_Sock, buff, buffLen, 0);
}

int TcpSocket::Send(const char *buff, int len)
{
    return send(m_Sock, buff, len, 0);
}

非常感谢您提供任何帮助,线索或建议!

Edit1:我在客户端获取数据包如下:

//This is the TCP read() call which should block until something is received            
int i = server->Receive(serverMessage, 100000);
//Passing the received buffer to decoder. sizeof(UINT8) is because of an identifyer which kind of package is received, 
//sizeof(int) is the length of the actual buffer
m_decoder->parseData((const unsigned char*)(serverMessage + sizeof(UINT8) + sizeof(int)), size);

1 个答案:

答案 0 :(得分:0)

正如您链接的VOIP页面所说,UDB和TCP之间唯一的差异,假设其他一切都正确实现,TCP会偶尔延迟您的数据。所以真正的问题是:输入数据的延迟会导致你的H264解码器像你的图像一样以紫色画出一半的屏幕吗?我不太了解这个解码器来回答这个问题。

更多地解释这种偶然延迟的来源:网络不时丢弃数据包。可能是因为链路过载,或是因为电噪声或宇宙射线;类似的东西。

因此,当使用UDP并丢弃数据包时,数据流丢失了一些数据;你的H264解码器将它拒绝为腐败,1/60秒后出现一个新帧,你没有注意到它。

另一方面,TCP被迫以正确的顺序正确地传递每个数据包。因此,当数据包被丢弃时,TCP会稍稍等待,然后重新发送丢失的数据。如果连续两个数据包被丢弃,TCP会使等待时间加倍并再次尝试,依此类推。

在问题TCP vs UDP on video stream的答案中查看类似信息