大华摄像头使用外网接收数据

获取摄像头数据的方法

方法有几种
1 rtsp 获取后转发到外网
2 直接配置大华摄像头发送到外网

第一种方法有缺陷,不直接,需要转发服务,但是一种比较可靠的方法,如果网络中不能直接发出去,只能通过转发服务,那可以使用最为通用的方案,就是rtsp拉取后直接转发送到外网。

第二种方法使用要必须内网直接访问到外网,也就是摄像头可以直接连接到外网。
我们使用第二种方法,大华里面有一个配置是可以直接配置一个IP地址和端口,使用tcp方式直接推到外网的,不过,缺点就是,你得使用大华的sdk去接收,这样工作量少。

程序下载在此

建立数据结构推到外网

#pragma once
#include 
#include 
#include   
#include 
#include 
#include "websocketpp_server.h"
#include "dhnetsdk.h"
#include "dhplay.h"
#include "../RTMPPusher/H264AACRtmp.h"
#include "../RTMPPusher/TPacket.h"
#include "..\RecordAudio\audioRecord.h"
#include "web_send.h"
#pragma comment( lib, "dhnetsdk.lib")
#pragma comment( lib, "dhplay.lib")
using namespace std;


typedef struct tagDH_DEVICE_INFO
{
	string             szDevSerial;
	string             szDevName;
	string				videofile_name;
	string             szIP;
	int                nPort;
	string             szUseName;
	string             szPassWord;
	int                nLoginType;				 // 0:IP登录1:主动注册登录
	int                nLoginStatus;            // 设备状态,0:离线 1:排队登录 2:在线 3:停止预览  4 :当前设备正在播放中 5:注册失败 等待下次注册
	int                nLoginTimes;             // 尝试登录次数
	long long          lLoginID;				  // 登录句柄
	long long          lRealHandle;              //播放句柄
	baseinfo * baseserver = NULL;
	con_list          connections;				//摄像头连接链表
	uint32_t			frist_timestamp=0;
	uint32_t			current_timestamp=0;
	LONG              lRealPort ;               //设备的播放库port号   一个设备一个 不能重复
	//H264AACRtmp			hr;						//推送给RTMP的连接对象
	TQPacket		*packet=NULL;
	telemetry_client   web_client;//视频发送通道
	string   audio_url="";
	string  video_url = "";
	telemetry_client send_aac;//发送音频通道
	audioRecord gater_aac;//录音对象
}DH_DEVICE_INFO;


typedef struct tagNODE_SESSION
{
	baseinfo * baseserver = NULL;
	con_list   connections;
	long long  heartTime = 0;

}NODE_SESSION;

class devClass
{
private:
	devClass();
	//node_list m_node_list;
public:
	//set m_node_connect;
	baseinfo * pWServer = NULL;
	~devClass();
	static devClass* GetInstance();
	mutex mut; 
	map<string, DH_DEVICE_INFO *> mymap;
	//map _node_map;
	list<NODE_SESSION *> node_list;
	map<string, NODE_SESSION *> node_map;
	//map clientHdl_map;
	void setBaseServer(baseinfo * info);
	baseinfo * getBaseServer();
		
	void addDevSession(string dev_serial, string username, string pass)
	{
		std::lock_guard<std::mutex> guard(mut);
		DH_DEVICE_INFO * pinfo = NULL;
		auto map = mymap.find(dev_serial); //通过key确认设备是否注册
		if (map != mymap.end()) {//不等于end说明设备已经注册
			pinfo = map->second;//将设备信息给pinfo
		}
		if (pinfo != NULL) {//更新mymap中key对应的设备信息
			pinfo->baseserver = pWServer;//
			pinfo->szDevSerial = dev_serial;
			pinfo->szUseName = username;
			pinfo->szPassWord = pass;
			OUTINFO_3_PARAM("set  info repate  success   id = %s , username = %s ,pwd = %s   \n", dev_serial.c_str(),username.c_str(),pass.c_str());
		}
		else {
			DH_DEVICE_INFO * pinfo = new DH_DEVICE_INFO();
			pinfo->baseserver = pWServer;
			pinfo->nLoginStatus = 0;
			pinfo->szDevSerial = dev_serial;
			pinfo->szUseName = username;
			pinfo->szPassWord = pass;
			mymap[dev_serial] = pinfo;
			OUTINFO_3_PARAM("set  info   scuuess   id = %s , username = %s ,pwd = %s   \n", dev_serial.c_str(), username.c_str(), pass.c_str());

		}
		
	}

	int addDevSession(string dev_serial, connection_hdl hd) {
		std::lock_guard<std::mutex> guard(mut);
		//char * p = (char*)&hd;
		auto  iter = mymap.find(dev_serial);
		if (iter != mymap.end()) {
			DH_DEVICE_INFO * pinfo = iter->second;
			pinfo->connections.insert(hd);
			int size = pinfo->connections.size();
			OUTINFO_1_PARAM("set  connections  scuuess    size = %d  \n", size);
			return 0;
		}
		OUTINFO_0_PARAM("set  connections   error = no this dev   \n");
		return -1;
	}

	void addNodeSession(string key, connection_hdl hd) {
	   OUTINFO_0_PARAM("BEGIN addNodeSession\n");
	   std::lock_guard<std::mutex> guard(mut);
	   NODE_SESSION * pnode = new NODE_SESSION();
	   pnode->connections.clear();
	   pnode->connections.insert(hd);
	   pnode->baseserver = pWServer;
	   //pnode->connections.clear();
	   node_map[key] = pnode;
	   int size = pnode->connections.size();
	   OUTINFO_1_PARAM("set   node_hdl=%s   scuuess\n", key.c_str());
	   OUTINFO_1_PARAM("this nodeconnect  size = %d   \n" , size );
	   OUTINFO_0_PARAM("END addNodeSession\n");
   }
	void addNodeSessionHeartTIme(string key, connection_hdl hd, long long heartTime) {
		OUTINFO_0_PARAM("BEGIN addNodeSession\n");
		std::lock_guard<std::mutex> guard(mut);
		auto iter = node_list.begin();
		int size;
		while (iter != node_list.end())
		{
			NODE_SESSION * pnode = *iter;
			con_list &set = pnode->connections;
			if (set.find(hd) != set.end()) {//找到当前句柄
				size = node_list.size();
				OUTINFO_0_PARAM("have been addNodeSession\n");
				OUTINFO_1_PARAM("this nodeconnect  size = %d   \n", size);
				OUTINFO_0_PARAM("END addNodeSession\n");
				return;
			}
			iter++;
		}
		NODE_SESSION * pnode = new NODE_SESSION();
		pnode->connections.insert(hd);
		pnode->baseserver = pWServer;
		pnode->heartTime = heartTime;
		node_list.push_back(pnode);
		size = node_list.size();
		OUTINFO_1_PARAM("set   node_hdl=%s   scuuess\n", key.c_str());
		OUTINFO_1_PARAM("this nodeconnect  size = %d   \n", size);
		OUTINFO_0_PARAM("END addNodeSession\n");
	}
	int removehd(string key, connection_hdl hd) {
	   std::lock_guard<std::mutex> guard(mut);
	   auto map = mymap.find(key);
	   DH_DEVICE_INFO * pinfo = NULL;
	   if (map != mymap.end())
	   {
		   pinfo = map->second;
		   pinfo->connections.erase(hd);
		   int size = pinfo->connections.size();
		   OUTINFO_1_PARAM("  connect size = %d  \n", size);
	   }
	   if (pinfo != NULL && pinfo->nLoginStatus ==4 &&  pinfo->connections.size() == 0) {
		    OUTINFO_0_PARAM("  stop playing  \n");
			//当前没有浏览器请求流
			devClass * pdevClass = devClass::GetInstance();
			//  根据当前播放的 句柄断开连接  
			//关闭预览
			//关闭预览
			//启动一个线程关闭播放 不影响webscoket 通信
			stopPlay(pinfo);
			//注销用户
			//CLIENT_Logout(pinfo->lLoginID);
			
	   }
	   return 0;
	   
   }
	void stopPlay(DH_DEVICE_INFO * pinfo);
	int set(string key, const char *pIp, WORD wPort, int status,LONG lRealPort);

	void setheartTime(connection_hdl hdl,long long heartTime) {
		auto iter = node_list.begin();
		while (iter != node_list.end())
		{
			NODE_SESSION * pnode = *iter;
			con_list &set = pnode->connections;
			if (set.find(hdl) != set.end()) {//找到当前句柄
				pnode->heartTime = heartTime;
				OUTINFO_1_PARAM("set heart  time = %lld \n", heartTime);
				break;
			}
			iter++;
		}
	}


	int setlLoginID(string key, long long lLoginID)
	{
		std::lock_guard<std::mutex> guard(mut);
		DH_DEVICE_INFO * pinfo = NULL;
		auto map = mymap.find(key);
		if (map != mymap.end() ) {
			pinfo = map->second;
		}
		if (pinfo != NULL)
		{
			pinfo->lLoginID = lLoginID;
		}
		else {
			return -1;
		}
		return 0;
	};
	int  setlRealHandle(string key, long long lRealHandle) 
	{
		OUTINFO_0_PARAM(" BEGIN  setlRealHandle  \n");
		
		std::lock_guard<std::mutex> guard(mut);
		auto map = mymap.find(key);
		DH_DEVICE_INFO * pinfo = NULL;
		if (map != mymap.end()) {
			pinfo = map->second;
		}
		if (pinfo != NULL)
		{
			pinfo->lRealHandle = lRealHandle;
			OUTINFO_1_PARAM(" END  setlRealHandle    handeleid = %lld \n"  , lRealHandle);
			return 0;
		}
		else {
			OUTINFO_0_PARAM(" END   setlRealHandle   error = -1  \n");
			return -1;
		}
	
	}
	int setLoginStatus(string key, int status);
	int getLoginStatus(string key);
	int  getDevSession(string key, DH_DEVICE_INFO  * dhInfo);
	void delDevSession(string key);


	void Send(char * p, int len, string key) {
		std::lock_guard<std::mutex> guard(mut);
		try {
			DH_DEVICE_INFO * pinfo = NULL;
			auto map = mymap.find(key);
			if (map != mymap.end())
			{
				pinfo = map->second;
				con_list  &set = pinfo->connections;
				con_list::iterator it;
				for (it = set.begin(); it != set.end(); ++it) {
					pinfo->baseserver->SendFrame(*it, p, len);
				}
			}
		}
		catch (string const & e) {
			OUTINFO_1_PARAM("Send   error = %s \n", e.c_str());
		}
	}


	void Send(void * devSerial, int status) {
		OUTINFO_0_PARAM("BEGIN SEND_DEV_STA\n");
		std::lock_guard<std::mutex> guard(mut);
		try {
			auto iter = node_list.begin();
			while (iter != node_list.end())
			{
				NODE_SESSION * pnode = *iter;
				if (pnode != NULL) {
					con_list  &set = pnode->connections;
					con_list::iterator it;
					for (it = set.begin(); it != set.end(); ++it) {
						pnode->baseserver->SendFrame(*it, devSerial, status);
					}
				}
				iter++;
			}
		}
		catch (string const & e) {
			//std::cout << e.c_str() << std::endl;
			OUTINFO_1_PARAM("SEND_DEV_STA   error = %s  \n", e.c_str());
		}
		OUTINFO_0_PARAM("END SEND_DEV_STA\n");
	}

	void Send(string devSerial,string pic_name) {
		std::lock_guard<std::mutex> guard(mut);
		try {
			auto iter = node_list.begin();
			while (iter != node_list.end())
			{
				NODE_SESSION * pnode = *iter;
				if (pnode != NULL) {
					con_list  &set = pnode->connections;
					con_list::iterator it;
					for (it = set.begin(); it != set.end(); ++it) {
						pnode->baseserver->SendFrame(*it, devSerial, pic_name);
					}
				}
				iter++;
			}
			
		}
		catch (string const & e) {
			OUTINFO_1_PARAM("SEND_DEV_STA   error = %s  \n", e.c_str());
		}
	}

	void delete_mem()
	{
		//lock
		//map mymap;
		//map _node_map;
		//list node_map;
		{

			auto iter = mymap.begin();
			while (iter != mymap.end())
			{
				DH_DEVICE_INFO *item = iter->second;
				delete item;
				iter++;
			}
		}
		{
			auto iter1 = node_list.begin();
			while (iter1 != node_list.end())
			{
				NODE_SESSION * s = *iter1;
				delete s;
				iter1++;
			}
		}
	}
		 
};

建立websocket 服务

为了使得数据能够被浏览器访问,建立一个websocket服务,直接转发h264,也可以转发到rtmp server,两种方式都可以,程序里面有。主要程序如下所示


#define _CRT_SECURE_NO_WARNINGS
#include "websocketpp_server.h"
#include "devClass.h"
#include "dhServer.h"
broadcast_server::broadcast_server() {

	m_server.init_asio();
	m_server.set_open_handler(bind(&broadcast_server::on_open, this, std::placeholders::_1));
	m_server.set_close_handler(bind(&broadcast_server::on_close, this, std::placeholders::_1));
	m_server.set_message_handler(bind(&broadcast_server::on_message, this, std::placeholders::_1, std::placeholders::_2));
}

void broadcast_server::run(uint16_t port) {
	m_server.listen(port);
	m_server.start_accept();
	try {
		OUTINFO_1_PARAM("***WS server Listen Success! port:%d ***\n", port);
		m_server.run();
	}
	catch (const std::exception & e) {
		OUTINFO_1_PARAM(" WS server Listen fail ! error:%s\n", e.what());
	}
}

void broadcast_server::on_open(connection_hdl hdl) {
		//lock_guard guard(m_action_lock);
		OUTINFO_0_PARAM(" WS server on_open \n" );
		//m_actions.push(action(SUBSCRIBE, hdl));
		//m_action_cond.notify_one();
}

void broadcast_server::on_close(connection_hdl hdl) {
	
		//lock_guard guard(m_action_lock);
		OUTINFO_0_PARAM(" WS server on_close \n");
		devClass * pdevclass = devClass::GetInstance();
		/*map clientHdl_map = pdevclass->clientHdl_map;
		string id = clientHdl_map[(char*)&hdl] ;*/

		//string id = pdevclass->clientHdl_map[hdl] ;
		map<string, DH_DEVICE_INFO *>::iterator iter;
		iter = pdevclass->mymap.begin();
		for (; iter != pdevclass->mymap.end(); iter++) {
			DH_DEVICE_INFO * pinfo = iter->second;
			string id = iter->first;
			if (pinfo !=NULL)
			{
				con_list &set = pinfo->connections;
				if (set.find(hdl) != set.end()) {
					OUTINFO_1_PARAM("this disconnect  id = %s \n",id.c_str());
					pdevclass->removehd(id, hdl);
				
				}
			}
		}
		//m_actions.push(action(UNSUBSCRIBE, hdl));
		//m_action_cond.notify_one();
}
//通过该方法从web端获得摄像头的配置信息(链接句柄,配置信息)
void broadcast_server::on_message(connection_hdl hdl, server::message_ptr msg) {

	devClass * pdevclass = devClass::GetInstance();
	
	OUTINFO_0_PARAM("BEGIN WS server on_message resove \n");
	
	string  tempstring = msg->get_payload();

	//安全判断
	if (tempstring == "undifined" || tempstring == "null"  || tempstring == "[object Object]") {
		OUTINFO_0_PARAM("WS server  recieve error = undifined OR null  \n");
		std::string msg_str = "{\"type\":\"999\",\"info\":\"Bad Request,parameter error;\",\"code\":\"0\"}";
		sendText(hdl, msg_str);
		return;
	}
   string type = m_type_number(tempstring);
   if (type == "0") {
	   OUTINFO_1_PARAM("recieve node msg : %s \n", tempstring.c_str());
	   pdevclass->addNodeSessionHeartTIme("node", hdl, getMilliTime());
	   //给当前变量全局 ms 数进行赋值
	   std::string msg_str = "{\"type\":\"0\",\"info\":\"u are node_client\"}";
	   sendText(hdl, msg_str);
   }
   else if (type == "1"  || type == "2") //添加设备信息
   {
	   device one_device = m_init_device_list(tempstring);
	   list<device_init_add>::iterator it;
	   list<device_init_add>  list = one_device.dev_list;
	   it = list.begin();
	   while (it != list.end())
	   {
	   pdevclass->addDevSession(it->dev_serial, it->user_name, it->passwd);
	   it++;
	   }
   }
//++++++++++++++++++++直播代码段++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   else if(type == "4")  
   {
	   OUTINFO_1_PARAM("recieve node msg : %s \n", tempstring.c_str());
	   //printf("recieve node msg : %s \n", tempstring.c_str());
	   string dev_serial = m_live_broadcast(tempstring);//浏览器将想要获得的摄像头的唯一序列号通过websocketpp(js_sion)传给服务器
														//类似于申请获取那个摄像头的流
	   string type = m_video_type(tempstring);//要获取的视频流类型
	   if (dev_serial.empty())//没有连接到摄像头
	   {
		   OUTINFO_0_PARAM(" dev_serial = nullstr  \n");
		   printf("dev_serial=nullstr");
		   std::string msg_str = "{\"type\":\"4\",\"info\":\"Bad Request,parameter error; \",\"code\":\"0\"}";
		   sendText(hdl, msg_str);
		   return;
	   }
	   //将当前请求直播的 hd ———— id 存入到map 中
	   //将当前请求直播的连接保存到connections属性中
       int ret = pdevclass->addDevSession(dev_serial,hdl);

	   if (ret == -1) {//返回-1说明连接没有成功,没有找到设备
		   std::string msg_str = "{\"type\":\"4\",\"info\":\"Not Found This Dev;\",\"code\":\"1\"}";
		   sendText(hdl, msg_str);
	   }
	   else
	   {
		   //获得摄像头的状态
		   // 设备状态,0:离线 1:排队登录 2:在线 3:停止预览  4 :当前设备正在播放中 5:注册失败 等待下次注册
		   int loginStatus = pdevclass->getLoginStatus(dev_serial);
		   if(loginStatus == -1){
				std::string msg_str = "{\"type\":\"4\",\"info\":\"This Dev Offline\",\"code\":\"2\"}";
				sendText(hdl,msg_str);

		   }
		   else
		   {
			   //开启获取设备的线程
			   std::string msg_str = "{\"type\":\"4\",\"info\":\"Play It Right Now\",\"code\":\"3\"}";
			   sendText(hdl, msg_str);
			   dhServer dhserver;
			   dhserver.thread_getH264ById(dev_serial,type);
		   }
	   }
   }
   else if (type == "8")  //截图
   { 
	   OUTINFO_1_PARAM("recieve node msg : %s \n", tempstring.c_str());
	   device_take_pic  pics = m_device_take_pic(tempstring);
	   string dev_serial = pics.dev_serial;
	   string pic_name = pics.pic_name;
	   dhServer dhserver;
	   dhserver.thread_getpicture(dev_serial, pic_name);
	  
   }
   else if (type == "10")  //get cam isonline 
   {
	   OUTINFO_1_PARAM("recieve node msg : %s \n", tempstring.c_str());
	   char body [128] = "";
	   std::string head = "{\"type\":\"10\",\"info\":{";
	   device one_device = m_init_device_list(tempstring);
	   list<device_init_add>::iterator it;
	   list<device_init_add>  list = one_device.dev_list;
	   it = list.begin();
	   while (it != list.end())
	   {
		  int status =  pdevclass->getLoginStatus(it->dev_serial);
		  _snprintf(body, sizeof(body) - 1, " \"%s\":{\"deviceid\":\"%s\" ,\"status\":\"%d\"} ,", it->dev_serial.c_str(), it->dev_serial.c_str(), status);
		  string body1 = body;
		  head +=  body1;
		  *it++;
	   }
	   head.pop_back();
	   head = head + "}}";
	   sendText(hdl, head);
   }
   else if (type == "11")  //接受node 心跳
   {
	   OUTINFO_1_PARAM("recieve node msg : %s \n", tempstring.c_str());
	   //给当前变量全局 ms 数进行赋值
	   std::string msg_str = "{\"type\":\"11\",\"info\":\"heart beatting\"}";
	   sendText(hdl, msg_str);
	   //设置当前连接的心跳
	   pdevclass->setheartTime(hdl, getMilliTime());
	 
	 /*function sfunc = std::bind(&broadcast_server::timer_callback, this, std::placeholders::_1);
	   m_server.set_timer(time, sfunc);*/
   }
  OUTINFO_0_PARAM("END WS server on_message resove\n");
}

void broadcast_server::timer_callback(error_code const &error) {
	// printf("this is a test\n\n");
}





string broadcast_server::m_type_number(string json_string) {

	std::stringstream str_stream(json_string);
	boost::property_tree::ptree root;
	boost::property_tree::read_json(str_stream, root);
	//boost::property_tree::ptree::iterator root_it = root.BEGIN();
	string type = root.get<string>("type");
	return type;

}


device broadcast_server::m_init_device_list(string json_string) {
	device one_device;
	try{

		std::stringstream str_stream(json_string);
		boost::property_tree::ptree root;
		boost::property_tree::read_json(str_stream, root);
		boost::property_tree::ptree::iterator root_it = root.begin();
		for (; root_it != root.end(); ++root_it)
		{
			string key = root_it->first;
			if ("type" == key)
			{
				one_device.type = root.get<string>(key);

			}
			if ("info" == key)
			{

				boost::property_tree::ptree info_node = root.get_child(key);
				boost::property_tree::ptree list_node = info_node.get_child("list");
				boost::property_tree::ptree::iterator list_node_it = list_node.begin();
				for (; list_node_it != list_node.end(); ++list_node_it)
				{
					device_init_add one_init_add;
					boost::property_tree::ptree tkt = list_node_it->second;
					boost::property_tree::ptree::iterator tkt_it = tkt.begin();
					for (; tkt_it != tkt.end(); ++tkt_it)
					{
						string tkt_key = tkt_it->first;

						string tkt_val = tkt.get<string>(tkt_key);
						if (tkt_key == "deviceid")
							one_init_add.dev_serial = tkt_val;
						else if (tkt_key == "username")
							one_init_add.user_name = tkt_val;
						else if (tkt_key == "password")
							one_init_add.passwd = tkt_val;

						//	cout << tkt_key << ":" << tkt_val << endl;

					}
					/*struct device
					{
						string type;
						std::list dev_list;
					};*/
					one_device.dev_list.push_back(one_init_add);//push设备的deviceid、usename、password 到list中
				}

			}

			else
			{
				/*string val = root.get(key);
				cout << key << ":" << val << endl;
				*/
			}

		}
	}
	catch (const std::exception& e)
	{
		OUTINFO_1_PARAM("m_init_device_list   error = %s  \n", e.what());
	}
	return one_device;

}

//获取操作的deviceid
string  broadcast_server::m_live_broadcast(string json_string )
 {
	string  device_s;
	try
	{
		std::stringstream str_stream(json_string);
		boost::property_tree::ptree root;
		boost::property_tree::read_json(str_stream, root);
		boost::property_tree::ptree info_node = root.get_child("info");
		device_s = info_node.get<string>("deviceid");
	}
	catch (const std::exception& e)
	{
		OUTINFO_1_PARAM("m_live_broadcast   error = %s  \n", e.what());
	}
	return device_s;
 }

//获取device传输码流的类型
string  broadcast_server::m_video_type(string json_string)
{
	string  type;
	try
	{
		std::stringstream str_stream(json_string);
		boost::property_tree::ptree root;
		boost::property_tree::read_json(str_stream, root);
		boost::property_tree::ptree info_node = root.get_child("info");
		type = info_node.get<string>("video_type");
		//printf(">>>>>video_type:%s<<<<<",type.c_str());
	}
	catch (const std::exception& e)
	{
		OUTINFO_1_PARAM("m_video_type   error = %s  \n", e.what());
	}
	return type;
}


//获取截图的 摄像头 序列号 和 截取图片的name
device_take_pic  broadcast_server::m_device_take_pic(string json_string)
{
	device_take_pic  takes;
	try
	{
		std::stringstream str_stream(json_string);
		boost::property_tree::ptree root;
		boost::property_tree::read_json(str_stream, root);
		boost::property_tree::ptree info_node = root.get_child("info");
		takes.dev_serial = info_node.get<string>("deviceid");
		takes.pic_name = info_node.get<string>("time");
	}
	catch (const std::exception& e)
	{

		OUTINFO_1_PARAM("m_device_take_pic   error = %s  \n", e.what());
	}
	return takes;
}
//{"type":8, "info" : {"bim_id":"123456", "deviceid" : "3CEF8CFC7990", "time" : ""}}
//{"type":4, "info" : {"bim_id":"123456", "deviceid": "3CEF8CFC7990"}}
//void  broadcast_server::process_messages() {
//
//	while (1) {
//
//
//		unique_lock lock(m_action_lock);
//
//
//		while (m_actions.empty()) {
//			m_action_cond.wait(lock);
//		}
//
//
//		action a = m_actions.front();
//
//
//		m_actions.pop();
//
//		lock.unlock();
//
//
//
//
//			if (a.type == SUBSCRIBE) {
//				lock_guard guard(m_connection_lock);
//				m_connections.insert(a.hdl);
//				devClass * pdevClass = devClass::GetInstance();
//				string key = "3CEF8CFC7990";
//				string username = "admin";
//				string pass = "ma11111111";
//				pdevClass->addDevSession(key, username, pass);
//				
//			}
//			else if (a.type == UNSUBSCRIBE) {
//				lock_guard guard(m_connection_lock);
//				printf("当前设备断开连接。。。。。。。。。。。。。。。。。。。。。。。。。");
//				m_connections.erase(a.hdl);
//			}
//			else if (a.type == MESSAGE) {
//				lock_guard guard(m_connection_lock);
//				
//				devClass * pdevClass = devClass::GetInstance();
//				pdevClass->addDevSession("3CEF8CFC7990", a.hdl);
//				dhServer dhserver;
//				dhserver.thread_getH264ById("3CEF8CFC7990");
//				//摄像头的信息在a.msg里面,组建结构,写到map里面去
//				/*string payload = a.msg->get_payload();
//				string DevSerial = analysePayload(payload);*/
//				
//
//				//con_list::iterator it;
//				/*for (it = m_connections.begin(); it != m_connections.end(); ++it) {
//					m_server.send(*it, a.msg);
//				}*/
//			}
//		}
//		else {
//			// undefined.
//		}
//
//	}
//}



void broadcast_server::SendFrame(connection_hdl hd, char * p, int len)
{


	try {//将数据以二进制的形式发出去
		m_server.send(hd, p, len, websocketpp::frame::opcode::binary);
	}
	catch (websocketpp::exception const & e) {

		OUTINFO_1_PARAM("SendFrame_video   error = %s  \n", e.what());

	}
}

void broadcast_server::SendFrame(connection_hdl hd, void * devSerial, int status)
{
	try {
		string strSerial = (char*)devSerial;
		char body[128]  = "";
		_snprintf(body, sizeof(body) - 1, "{ \"type\":\"0\",\"info\":{ \"deviceid\":\"%s\" ,\"status\":\"%d\"}}", strSerial.c_str(), status);
		sendText(hd, (string)body);
	}
	catch (websocketpp::exception const & e) {
		OUTINFO_1_PARAM("SendFrame_sendText   error = %s  \n", e.what());
	}
}

void broadcast_server::SendFrame(connection_hdl hd,string devSerial,string pic_name)
{


	try {

	/*	string id_name = (char*)devSerial;
		int flag = id_name.find("#");
		string id = id_name.substr(0, flag);
		string pic_name = id_name.substr(++flag, -1);*/
		char body[128] = "";
		_snprintf(body, sizeof(body) - 1, "{ \"type\":\"8\",\"info\":{ \"deviceid\":\"%s\",\"pic_name\":\"%s\"}}", devSerial.c_str(), pic_name.c_str());
		sendText(hd, (string)body);
	   /* char * p = (char *)devSerial;
		delete[]p;*/
	}
	catch (websocketpp::exception const & e) {
		OUTINFO_1_PARAM("SendFrame_pic   error = %s  \n", e.what());
	}
}

void broadcast_server::CloseConnect(connection_hdl hd)
{
	try {
		m_server.close(hd,0,"heartbeat close");
		OUTINFO_0_PARAM("close connect ,becauser no recieve data...\n");
	}
	catch (websocketpp::exception const & e) {
		OUTINFO_1_PARAM("CloseConnect   error = %s  \n", e.what());
	}

}

int broadcast_server::GetUserNumberByDevName(const char * devname)
{
	return 0;
}

long long broadcast_server::getMilliTime()
{ 
	struct timeb t1;
	ftime(&t1);
	return t1.time * 1000 + t1.millitm;
}

void broadcast_server::sendText(connection_hdl hdl,string & msg) {
	OUTINFO_1_PARAM(" BEGIN sendText  msg = %s\n" , msg.c_str());
	try {
		int len = msg.size();
		server::message_ptr m;
		char *p = (char *)msg.c_str();
		m_server.send(hdl, p, len, websocketpp::frame::opcode::text);
		}
	catch (websocketpp::exception const & e)
		{
		OUTINFO_1_PARAM(" sendText   error = %s  \n", e.what());
		}
	
}

接收程序

html端使用h264 js解码,直接播放,这样的好处是可以让手机端使用html5也直接播放,当然,可以使用原生的程序直接播放,就可以避免一些限制。下面使用html5 解码,使用的decoder.js 等为开源程序,缺陷,只能解码baseline 的h264,各位要解码h264 和h265 请使用wasm的程序,网上有很多。

DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=320, initial-scale=1" />
    <title>h264 streamingtitle>
    <style type="text/css">
        body {
            background: #333;
            text-align: center;
            margin-top: 10%;
        }

        #videoCanvas {
            /* Always stretch the canvas to 640x480, regardless of its
            internal size. */
            width: 640px;
            height: 480px;
        }
    style>
head>
<body>
    
    
    <script type="text/javascript" src="Decoder.js">script>
    <script type="text/javascript" src="YUVCanvas.js">script>
    <script type="text/javascript" src="Player.js">script>

    <script type="text/javascript">

		var player = new Player({size: {
        width: 640,
        height: 320
         }});

		document.body.appendChild(player.canvas);

		//var strhost = "ws://" + window.location.host ;
		var strhost = "ws://192.168.3.245:9002" ;
		// Setup the WebSocket connection and start the player
		var client = new WebSocket( strhost );


   	client.binaryType = 'arraybuffer';

        client.onopen = function(evt) {
            onOpen(evt)
        };
        client.onclose = function(evt) {
            onClose(evt)
        };
        client.onmessage = function(evt) {
            onMessage(evt)
        };
        client.onerror = function(evt) {
            onError(evt)
        };

    function onOpen(evt) {
        //  document.getElementById('messages').innerHTML = 'Connection established';
        console.log("connection ");
      //  alert("open");
    }

    function onClose(evt) {
        alert("close");
    }

    function onMessage(evt) {
        //console.log(evt.data);
        //return;
        var messageData = new Uint8Array(evt.data);
        player.decode(messageData);
    }

    function onError(evt) {
        alert("error");
    }

    script>
body>
html>

你可能感兴趣的:(c++,音视频和c++,java,物联网,大华摄像头,h264,推流)