I'm trying to send multiple frames (previsously taken from an actual video file) via socket (C++) to then play with VLC.
I've searched a lot and didn't find a solution. Hope you can help me.
So, this is my code:
#include <stdio.h>
#include <stdlib.h>
#include <direct.h>
#include <iostream>
#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string.h>
#include <time.h>
#include <errno.h>
//#include <fstream>
#include <opencv2/core/core.hpp> // Basic OpenCV structures (cv::Mat, Scalar)
#include <opencv2/highgui/highgui.hpp> // OpenCV window I/O
using namespace std;
#define PORT 6666
#define GROUP "127.0.0.1"
//#define INADDR_ANY
int serversock, clientsock;
int is_data_ready = 0;
struct sockaddr_in server, client;
int bytes = 0;
int count = 0;
int addrlen = sizeof(server);
int clielen = sizeof(client);
int opt = 1;
//methods
void quit(char* msg, int retval);
void quit(char* msg, int retval)
{
if (retval == 0) {
fprintf(stdout, (msg == NULL ? "" : msg));
fprintf(stdout, "\n");
} else {
fprintf(stderr, (msg == NULL ? "" : msg));
fprintf(stderr, "\n");
}
if (clientsock) closesocket(clientsock);
if (serversock) closesocket(serversock);
exit(retval);
}
int main()
{
// Initialize Winsock
WSADATA wsaData;
int iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup failed with error: %ld\n", iResult);
return 1;
}
//char *imgname; //path e nome das imagens
int i=0;
char filename[50];
IplImage *img = cvLoadImage(<path\\imgname.jpg); //1ª imagem como referência
//IplImage *img2;
CvSize size;
size.width = img->width;
size.height = img->height;
/* setup server's IP and port */
memset(&server,0,sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(6666/*PORT*/);
server.sin_addr.s_addr = inet_addr("127.0.0.1"/*GROUP*/);
//server.sin_addr.s_addr = INADDR_ANY;
SOCKET serversock = socket(AF_INET, SOCK_STREAM, 0);
//SOCKET t;
//t = socket(AF_INET, SOCK_STREAM,NULL);
if (serversock < 0) { // or == -1
wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
//quit("socket() failed", 1);
}
/* bind the socket */
int b = bind(serversock, (const sockaddr*)&server, sizeof(server));
if (b < 0) {
wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
quit("bind() failed", 1);
}
/* wait for connection */
int l = listen(serversock, 5);
if(l < 0) {
quit("listen() failed.", 1);
}
setsockopt(serversock, SOL_SOCKET, SO_KEEPALIVE, (const char*) &opt, sizeof(int));
while(img != NULL)
{
sprintf(filename, "filter\\frame_%d.jpg", i);
img = cvLoadImage(filename);
if (img) {
int imgSize = (int) &size;
sendto(serversock, img->imageData, imgSize, 0, (const struct sockaddr*)&server, addrlen);
if(bytes < 0) { //error
wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
quit("sendto FAILED", 1);
}
//end socket stuff
cout << "Image sent!" << endl;
}
i++;
}
cvReleaseImage(&img);
}
Ant then I open VLC and set it to receive network stream on the next address: rtp://127.0.0.1:6666
.
The application ends and VLC doesn't show anything.
Thanks a lot!
First,
int sendto(
_In_ SOCKET s,
_In_ const char *buf,
_In_ int len,
_In_ int flags,
_In_ const struct sockaddr *to,
_In_ int tolen
);
sendto
third argument is « The length, in bytes, of the data pointed to by the buf parameter »
, not the address of some OpenCV size object. So that's not surprising if your program crashes. imgSize
should be img.imageSize
.
Secondly, I really doubt that VLC is able to decode a stream composed of several raw Image data, I'm pretty sure it needs some streaming protocol around it.
First you need to use a transport protocol as streaming protocol (HTTP, RTP, etc.). Then you need to build an actual video to stream (MJPEG, MPEG4, etc.)
Your server could relatively easily stream MJPEG over HTTP, for any other protocol, you should use an external library.
You should search about how implementing a video streaming server in C++, see this thread : How to get started implementing a video streaming server in c/c++?