Showing posts with label HTTP Live Streaming. Show all posts
Showing posts with label HTTP Live Streaming. Show all posts

Monday, July 21, 2014

Stream Video to HTML5 enabled web browser. (Windows) HLS(HTTP Live Streaming)

Here is the HTML page code for streming


<html>
<body>

<video src="http://192.168.3.155:27015/test.mp4" type="video/ogg" controls="controls" autoplay="autoplay" height="360" width="640"></video>

</body>
</html>


You can specify the src tag with only IP address and no port. But you will have to terminate the use of port 80 on your computer.

Here the c++(win32) code for stream server that will do the streaming . This is a simple code and it will not show how do multiple client connections.

#undef UNICODE

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>

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

#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"

#define BUFFER_S 6000

int FileSize( const std::string& filePath )
{
const char* fpath = filePath.c_str();
FILE *fr = fopen(fpath, "rb");

if(fr != NULL)
{
fseek (fr, 0, SEEK_END);
int size = ftell (fr);
fclose (fr);

return size;
}
else
{
return -1;
}
}

int main()
{
WSADATA wsaData;
int iResult;

SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;

struct addrinfo *result = NULL;
struct addrinfo hints;

char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;

// 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 connecting to server
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;
}

// 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;
}

freeaddrinfo(result);

iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}

// 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;
}

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

  struct sockaddr_in sockserv,sockclient;
  FILE* filefd;
  int count1,cnt;
  int totalcnt;


  char buff[BUFFER_S];
char buff2[BUFFER_S];

  char* ptr, strtemp[20];
  int strcnt;

std::string fileName = "d:\\test_vid\\2.mp4";
int fileSize = FileSize(fileName);

  filefd = fopen(fileName.c_str(), "rb");
  if (filefd == NULL)
  {
return 0;
  }

memset(buff, 0, sizeof(buff));

/** First data request. */
int nRet = recv(ClientSocket, // Connected client
buff, // Receive buffer
BUFSIZ, // Lenght of buffer
0); // Flags

if (nRet == INVALID_SOCKET)
{
closesocket(ListenSocket);
closesocket(ClientSocket);
return 0;
}

  buff[nRet] = '\0';
  printf("Request recieved as \n%s\n", buff);

  cnt = fread(buff2, 1, 1025, filefd);

  sprintf(buff, "HTTP/1.1 206 Partial Content\r\nContent-Type: video/ogg\r\nDate: Mon, 28 Feb 2011 10:38:19 GMT\r\nContent-Range: bytes 0-1024/%d\r\nTransfer-Encoding: chunked\r\nServer: Myserver\r\n\r\n%x\r\n", fileSize, cnt);

  count1 = strlen(buff);
  memcpy(buff + count1, buff2, cnt);
  memcpy(buff + count1 + cnt, "\r\n0\r\n\r\n", strlen("\r\n0\r\n\r\n"));

int byteToSend = count1 + cnt + strlen("\r\n0\r\n\r\n");
cnt = send(ClientSocket, buff, byteToSend, 0);
if (cnt == SOCKET_ERROR)
{
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}

  printf("Data sent to the client %d bytes: %s", cnt, strerror(errno));
printf("Response sent as \n%s\n", buff);
printf("\n");

  // totalcnt = 1025;
  while(1)
  {
memset(buff, 0, BUFFER_S);
int nRet = recv(ClientSocket, // Connected client
buff, // Receive buffer
BUFFER_S, // Lenght of buffer
0); // Flags

if (nRet == INVALID_SOCKET)
{
closesocket(ListenSocket);
closesocket(ClientSocket);
return 0;
}

  if(cnt <= 0)
  break;

  buff[cnt] = '\0';
  printf("Request recieved as \n%s\n", buff);
ptr = strstr(buff, "bytes=") + strlen("bytes=");

  strcnt = 0;
  while(*ptr!='-')
  {
  strtemp[strcnt] = *ptr;
  strcnt++;
  ptr++;
  }

  strtemp[strcnt] = '\0';
  //printf("strcnt = %s\n",strtemp);

  fseek(filefd, atoi(strtemp), SEEK_SET);
cnt = fread(buff2, 1, 5000, filefd);

memset(buff, 0, BUFFER_S);
  sprintf(buff, "HTTP/1.1 206 Partial Content\r\nContent-Type: video/ogg\r\nDate: Mon, 28 Feb 2011 10:38:19 GMT\r\nContent-Range: bytes %d-%d/%d\r\nTransfer-Encoding: chunked\r\nServer: Myserver\r\n\r\n%x\r\n", atoi(strtemp), atoi(strtemp) + cnt - 1, fileSize, cnt);

  count1 = strlen(buff);
  memcpy(buff + count1, buff2, cnt);
  memcpy(buff + count1 + cnt, "\r\n0\r\n\r\n", strlen("\r\n0\r\n\r\n"));

cnt = send(ClientSocket, buff, count1 + cnt + strlen("\r\n0\r\n\r\n"), 0);
if (cnt == SOCKET_ERROR)
{
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}

printf("Total Data sent to the client %d bytes: %s\n", cnt, strerror(errno));
printf("Response sent as \n%s\n", buff);
printf("\n");
  }

fclose(filefd);
closesocket(ListenSocket);
closesocket(ClientSocket);
  return 0;

}