基于 OpenCV 的流媒体视频客户端无法显示视频?[关闭]

OpenCV-based streaming video client won't display video? [closed]

提问人:Riley Bain 提问时间:11/14/2023 最后编辑:genpfaultRiley Bain 更新时间:11/14/2023 访问量:23

问:


想改进这个问题吗?更新问题,使其仅通过编辑这篇文章来关注一个问题。

7天前关闭。

我正在开发一个程序,使用 OpenCV 和 C++ 通过 TCP 直播视频片段。但是,代码似乎不是 100% 正确的。我遇到的问题出在客户端(我相信),视频将显示在服务器端,所以我知道相机正在正确捕获。但是在客户端,我认为它没有正确接收数据,救命!

服务器:

#undef UNICODE

#define WIN32_LEAN_AND_MEAN

#include <ws2tcpip.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/videoio/videoio.hpp>
#include <fstream>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <vector>

using namespace cv;

int capDev = 0;

    VideoCapture cap(capDev);       //open the default camera

// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")

#define DEFAULT_BUFLEN 256
#define DEFAULT_PORT "12345"

int __cdecl main(void) 
{
    //Initialize variables
    Mat img;
    WSADATA wsaData;

    int iResult, key;

    std::vector<uchar> buffer;                  //create vector buffer

    SOCKET ListenSocket = INVALID_SOCKET;   
    SOCKET ClientSocket = INVALID_SOCKET;

    struct addrinfo *result = NULL;
    struct addrinfo hints;
    
    //initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    //resolve the server address and port
    iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
    if ( iResult != 0 ) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 1;
    }

    //create a SOCKET for the server to listen for client connections.
    ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    if (ListenSocket == INVALID_SOCKET) {
        printf("socket failed with error: %ld\n", WSAGetLastError());
        freeaddrinfo(result);
        WSACleanup();
        return 1;
    }
    else
    {
        printf("Socket init: Successful\n");
    }
 
    //setup the TCP listening socket
    iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        printf("bind failed with error: %d\n", WSAGetLastError());
        freeaddrinfo(result);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    else
    {
        printf("Bind: Successful\n");
    }

    freeaddrinfo(result);

    //listen for client socket
    iResult = listen(ListenSocket, SOMAXCONN);
    if (iResult == SOCKET_ERROR) {
        printf("listen failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    else
    {
        printf("Server: Listening...\n");
    }
    
    //accept a client socket
    ClientSocket = accept(ListenSocket, NULL, NULL);
    if (ClientSocket == INVALID_SOCKET) {
        printf("accept failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }
    else
    {
        printf("Accept: Successful\n");
    }

    //no longer need server socket
    closesocket(ListenSocket);

    //----------------------------------------------------------
    //OpenCV Code
    //----------------------------------------------------------

    //commented out code old code for b&w image  

    //img = Mat::zeros(480, 640, CV_8U);   

    /*//make img continuos
    if ( ! img.isContinuous() ) 
    { 
        img = img.clone();
    }

    size_t imgSize = img.total() * img.elemSize();
    int bytes = 0;
        
    std::cout << "Image Size:" << imgSize << std::endl; */

    //runs while VideoCapture obj is operational
    while(cap.isOpened()) 
    {    
        cap >> img;                                                               //get a frame from camera
        if (img.empty())
        {
            printf("Err: 1");
            break;
        }

        imencode(".jpg", img, buffer);                                            //encode the data
        uint64_t imgSize = buffer.size();                                         //create var for buffer size
                
        send(ClientSocket, (char *) &imgSize, sizeof(imgSize), 0);                //send buffer size
        send(ClientSocket, (char *) buffer.data(), (int) imgSize, 0);             //send buffer data (image)

        buffer.clear();                                                           //clear the buffer for next frame

        //checks for empty frames
        if (!(img.empty()))
        {
            imshow("Sending...", img);                                            //displays image being sent
        }

        if (key = waitKey(10) == 27)                                              //exits window with "esc"         
        {
            goto S;
        }
    }

    S : //shutdown the connection since we're done
    iResult = shutdown(ClientSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) 
    {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ClientSocket);
        WSACleanup();
        return 1;
    }

    //cleanup
    cap.release();
    closesocket(ClientSocket);
    WSACleanup();

    return 0; 
}

客户:

#define WIN32_LEAN_AND_MEAN

#include <iostream>
#include <opencv2/opencv.hpp>
#include <ws2tcpip.h>
#include <vector>
#include <cstring>

using namespace cv;

//need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")


#define DEFAULT_BUFLEN 256
#define DEFAULT_PORT "12345"

int __cdecl main(int argc, char **argv)
{
    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo *result = NULL, *ptr = NULL, hints;

    Mat img;
    int bytes = 0;
    char key = 's';

    int payloadSize = 1024;
    int bufferSize = 4 * 1024;
    std::vector<uchar> buffer;

    int iResult;
    int recvbuflen = DEFAULT_BUFLEN;
   
    //validate the parameters
    if (argc != 2)
    {
        printf("usage: %s server-name\n", argv[0]);
        return 1;
    }

    //initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0)
    {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    ZeroMemory( &hints, sizeof(hints) );
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    //resolve the server address and port
    iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
    if ( iResult != 0 )
    {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 1;
    }

    //attempt to connect to an address until one succeeds
    for(ptr=result; ptr != NULL ;ptr=ptr->ai_next)
    {

        //create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET)
        {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }
        else
        {
            printf("Socket init: Successful\n");
        }


        //connect to server.
        iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR)
        {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET)
    {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return 1;
    }
    else 
    {
        printf("Connection: Successful\n");
    }

    //----------------------------------------------------------
    //OpenCV Code
    //----------------------------------------------------------
    /*size_t imgSize = img.total() * img.elemSize();
       
    std::cout << "Image Size:" << imgSize << std::endl;*/

    namedWindow("Receiving...", WINDOW_AUTOSIZE);

    while (1)
    {
        uint64_t imgSize;
        if(recv(ConnectSocket, (char *) &imgSize, sizeof(imgSize), MSG_WAITALL <= 0))
        {
            printf("Err: 1");
            break;
        }

        buffer.resize(imgSize);
        if (recv(ConnectSocket, (char *) buffer.data(), (int) imgSize, MSG_WAITALL <= 0))
        {
            printf("Err: 2");
            break;
        }

        img = imdecode(buffer, IMREAD_COLOR);

        imshow("Receiving...", img);

        if(waitKey(10) == 27)
        {
            goto S;
        }
    }  

    // cleanup
    S : closesocket(ConnectSocket);
    WSACleanup();

    return 0;
}
C++ OpenCV Winsock 流式处理-视频

评论

0赞 pptaszni 11/14/2023
如果您遇到客户端套接字无法接收数据的问题,请删除您的 QT 样板代码并检查您的客户端服务器是否使用简单的“Hello World!”。我看到您从 MS 文档中复制粘贴了示例,所以我想它应该可以在没有您修改的情况下工作。如果没有,那么将您的问题简化为该特定问题。
0赞 Dan Mašek 11/15/2023
为什么要将参数设置为结果?这没有任何意义——也许是放错了地方?flagsrecvMSG_WAITALL <= 0)
0赞 Dan Mašek 11/15/2023
还有 stackoverflow.com/questions/67509709/... (这可能是你问题的根源,因为你认为一个就足以得到这一切)recv

答: 暂无答案