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;

}

Thursday, June 26, 2014

Interpolate Between Two angles(SLerp) C++ example.

This example Will show you how to interpolate between two angles that is given in degrees in 2D world. This code can be modified to use to interpolate between two 2DVectors.

In here vector3D is not included. you should write a simple vector3d class.


#include <math.h>

float PI = 3.141592653589793;

float RadianToDegree = 180.0f/PI;
float DegreeToRadian = PI/180.0f;

const float Dot(const vector3D& from, const vector3D& to)
{
return ((from.getX() * to.getX()) + (from.getZ() * to.getZ()));
}

const float Length(const vector3D& vector)
{
return sqrt((vector.getX() * vector.getX()) + (vector.getZ() * vector.getZ()));
}

vector3D Slerp(const vector3D& from, const vector3D& to, const float step)
{
if (step == 0) return from;
if (from == to || step == 1.0f) return to;

float theta = acos(Dot(from, to)/(Length(from) * Length(to)));
//float thetaDegree = theta * RadianToDegree;

if (theta == 0) return to;

float sinTheta = sin(theta);
return (from * (sin((1 - step) * theta) / sinTheta)) + (to * (sin(step * theta) / sinTheta));
}

float CurveAngle2(float from, float to, const float step)
{
if (step == 0) return from;
if (from == to || step == 1.0f)
{
return to;
}

if (from == 0.0f)
{
from = 1.0f * DegreeToRadian;
}

if (to == 0.0f)
{
to = 1.0f * DegreeToRadian;
}

VBS2Fusion::vector3D fromVector(cos(from), sin(from), 0.0f);
VBS2Fusion::vector3D toVector(cos(to), sin(to), 0.0f);

VBS2Fusion::vector3D currentVector = Slerp(fromVector, toVector, step);
float angleRadian = atan2(currentVector.getZ(), currentVector.getX());
if (angleRadian < 0.0f)
{
angleRadian = 2 * PI + angleRadian;
}

return angleRadian;
}

Saturday, June 21, 2014

RPC 1723 error can be occur when the RPC server you registered is stuck in a RPC function that the client is calling. If the 1723 error occurs check all the function that the RPC client calling is ended in the last time you have used the same server. We can check this by monitoring the RPC server listen thread(the thread that  you call RpcServerListen function) returned successfully after calling RpcMgmtStopServerListening call

Note : Even if you set DontWait = FALSE in RpcServerListen function RPC server might be stuck in the last call that it had.