Last active
February 7, 2016 12:35
-
-
Save cormoran/7108756075785b5c6fc1 to your computer and use it in GitHub Desktop.
c言語のweb socketライブラリで動画をストリーミングする
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>動画ストリーミング サンプル</title> | |
<meta charset="utf-8"> | |
<style type="text/css"> | |
body { | |
background: #f7f7f7; | |
color: #474747; | |
font-family: arial, sans-serif; | |
} | |
</style> | |
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> | |
</head> | |
<body> | |
<input type="button" id="button" value="play" onClick="onButtonClicked()"> | |
<canvas id="img" width="640" height="360"> </canvas> | |
</body> | |
<script> | |
var ws = new WebSocket("ws://localhost:7681", "movie"); | |
var button = $("#button"); | |
ws.onmessage = function(evt) { | |
console.log("received"); | |
var url = window.URL.createObjectURL(evt.data); | |
var img = new Image; | |
img.src = url; | |
img.onload = function () { | |
$("#img")[0].getContext("2d").drawImage(img,0,0); | |
}; | |
}; | |
function onButtonClicked(){ | |
console.log("Button Clicked"); | |
ws.send(button.val()); | |
if(button.val() == "play") button.val("stop"); | |
else button.val("play"); | |
} | |
</script> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef LWS_SUB_H | |
#define LWS_SUB_H | |
#include <libwebsockets.h> | |
const char* lws_getReasonString(int reason){ | |
static const char* reason_strings[] = { | |
"LWS_CALLBACK_ESTABLISHED", | |
"LWS_CALLBACK_CLIENT_CONNECTION_ERROR", | |
"LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH", | |
"LWS_CALLBACK_CLIENT_ESTABLISHED", | |
"LWS_CALLBACK_CLOSED", | |
"LWS_CALLBACK_RECEIVE", | |
"LWS_CALLBACK_CLIENT_RECEIVE", | |
"LWS_CALLBACK_CLIENT_RECEIVE_PONG", | |
"LWS_CALLBACK_CLIENT_WRITEABLE", | |
"LWS_CALLBACK_SERVER_WRITEABLE", | |
"LWS_CALLBACK_HTTP", | |
"LWS_CALLBACK_HTTP_FILE_COMPLETION", | |
"LWS_CALLBACK_FILTER_NETWORK_CONNECTION", | |
"LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION", | |
"LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS", | |
"LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS", | |
"LWS_CALLBACK_OPENSSL_PERFORM_CLIENT_CERT_VERIFICATION", | |
"LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER", | |
"LWS_CALLBACK_CONFIRM_EXTENSION_OKAY", | |
"LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED", | |
"LWS_CALLBACK_PROTOCOL_INIT", | |
"LWS_CALLBACK_PROTOCOL_DESTROY", | |
/* external poll() management support */ | |
"LWS_CALLBACK_ADD_POLL_FD", | |
"LWS_CALLBACK_DEL_POLL_FD", | |
"LWS_CALLBACK_SET_MODE_POLL_FD", | |
"LWS_CALLBACK_CLEAR_MODE_POLL_FD", | |
}; | |
return reason_strings[reason]; | |
} | |
static void dump_handshake_info(struct lws *wsi){ | |
int n; | |
static const char *token_names[WSI_TOKEN_COUNT] = { | |
/*[WSI_TOKEN_GET_URI] =*/ "GET URI", | |
/*[WSI_TOKEN_HOST] =*/ "Host", | |
/*[WSI_TOKEN_CONNECTION] =*/ "Connection", | |
/*[WSI_TOKEN_KEY1] =*/ "key 1", | |
/*[WSI_TOKEN_KEY2] =*/ "key 2", | |
/*[WSI_TOKEN_PROTOCOL] =*/ "Protocol", | |
/*[WSI_TOKEN_UPGRADE] =*/ "Upgrade", | |
/*[WSI_TOKEN_ORIGIN] =*/ "Origin", | |
/*[WSI_TOKEN_DRAFT] =*/ "Draft", | |
/*[WSI_TOKEN_CHALLENGE] =*/ "Challenge", | |
/* new for 04 */ | |
/*[WSI_TOKEN_KEY] =*/ "Key", | |
/*[WSI_TOKEN_VERSION] =*/ "Version", | |
/*[WSI_TOKEN_SWORIGIN] =*/ "Sworigin", | |
/* new for 05 */ | |
/*[WSI_TOKEN_EXTENSIONS] =*/ "Extensions", | |
/* client receives these */ | |
/*[WSI_TOKEN_ACCEPT] =*/ "Accept", | |
/*[WSI_TOKEN_NONCE] =*/ "Nonce", | |
/*[WSI_TOKEN_HTTP] =*/ "Http", | |
/*[WSI_TOKEN_MUXURL] =*/ "MuxURL", | |
}; | |
char buf[256]; | |
for (n = 0; n < WSI_TOKEN_COUNT; n++) { | |
if (!lws_hdr_total_length(wsi, (lws_token_indexes)n)) | |
continue; | |
lws_hdr_copy(wsi, buf, sizeof buf, (lws_token_indexes)n); | |
fprintf(stderr, " %s = %s\n", token_names[n], buf); | |
} | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Websocket Video Streaming Sample | |
2016/2/7 | |
*/ | |
#include <iostream> | |
#include <cstdio> | |
#include <string> | |
#include <vector> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <getopt.h> | |
#include <string.h> | |
#include <sys/time.h> | |
#include <assert.h> | |
#include <syslog.h> | |
#include <signal.h> | |
#include <stdarg.h> | |
#include <opencv2/opencv.hpp> | |
#include <libwebsockets.h> | |
#include "lws-sub.h" | |
using namespace std; | |
using namespace cv; | |
int force_exit = 0; | |
bool start = false; | |
VideoCapture video; | |
class LwsSendBuffer{ | |
vector<uchar> buffer; | |
public: | |
LwsSendBuffer(){ | |
buffer.resize(LWS_SEND_BUFFER_PRE_PADDING); | |
} | |
template<class T> | |
void set(const vector<T> &src){ | |
if(src.size() == 0) return; | |
buffer.resize(LWS_SEND_BUFFER_PRE_PADDING + src.size() * sizeof(T)); | |
copy(src.begin(), | |
src.end(), | |
buffer.begin() + LWS_SEND_BUFFER_PRE_PADDING); | |
} | |
int write(struct lws *wsi, lws_write_protocol protcol){ | |
return lws_write(wsi, | |
&buffer[0] + LWS_SEND_BUFFER_PRE_PADDING, | |
buffer.size() - LWS_SEND_BUFFER_PRE_PADDING, | |
protcol ); | |
} | |
}; | |
vector<unsigned char> toJpeg(Mat &src){ | |
vector<uchar> buff; | |
vector<int> param = { CV_IMWRITE_JPEG_QUALITY, 50 }; | |
imencode(".jpg",src,buff,param); | |
return buff; | |
} | |
static int callback_movie(struct lws *wsi, | |
enum lws_callback_reasons reason, void *user, | |
void *in, size_t len){ | |
switch (reason){ | |
case LWS_CALLBACK_ESTABLISHED: | |
break; | |
case LWS_CALLBACK_PROTOCOL_DESTROY: | |
break; | |
case LWS_CALLBACK_SERVER_WRITEABLE: | |
{ | |
static LwsSendBuffer buffer; | |
Mat frame; | |
video >> frame; | |
if(frame.empty() or video.get(CV_CAP_PROP_POS_AVI_RATIO) == 1) break; | |
buffer.set( toJpeg(frame) ); | |
buffer.write(wsi, LWS_WRITE_BINARY); | |
} | |
break; | |
case LWS_CALLBACK_RECEIVE: // 受信 | |
{ | |
lwsl_notice("ReceiveMessage=[%s]\n",(const char*)in); | |
if( string((const char*)in) == "play" ) start = true; | |
else if( string((const char*)in) == "stop" ) start = false; | |
} | |
break; | |
case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: | |
dump_handshake_info(wsi); | |
break; | |
default: | |
break; | |
} | |
return 0; | |
} | |
static struct lws_protocols protocols[] = { | |
{ | |
"movie", /* name */ | |
callback_movie, /* callback */ | |
0, /* per_session_data_size */ | |
1000000 /* max frame size / rx buffer */ | |
}, | |
{ NULL, NULL, 0, 0 } /* terminator */ | |
}; | |
void sighandler(int sig){ | |
force_exit = 1; | |
} | |
int main(){ | |
video = VideoCapture("video.mp4"); | |
int n = 0; | |
struct lws_context *context; | |
struct lws_context_creation_info info; | |
{ // set info | |
memset(&info, 0, sizeof info); | |
info.port = 7681; | |
info.iface = NULL; | |
info.protocols = protocols; | |
info.ssl_cert_filepath = NULL; | |
info.ssl_private_key_filepath = NULL; | |
info.gid = -1; | |
info.uid = -1; | |
info.options = 0; | |
} | |
signal(SIGINT, sighandler); | |
int syslog_options = LOG_PID | LOG_PERROR; | |
int debug_level = 7; | |
{ // log setting | |
lws_set_log_level(debug_level, lwsl_emit_syslog); | |
lwsl_notice("lws chat server -\n"); | |
setlogmask(LOG_UPTO (LOG_DEBUG)); | |
openlog("lwsts", syslog_options, LOG_DAEMON); | |
} | |
context = lws_create_context(&info); | |
if (context == NULL) { | |
lwsl_err("lws init failed\n"); | |
return -1; | |
} | |
n = 0; | |
while (n >= 0 && !force_exit) { | |
struct timeval tv; | |
gettimeofday(&tv, NULL); | |
n = lws_service(context, 50); | |
if(start) lws_callback_on_writable_all_protocol(context, protocols); | |
usleep(100000); // about 10fps | |
} | |
lws_context_destroy(context); | |
lwsl_notice("lws-test-server exited cleanly\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment