510 lines
11 KiB
C++
510 lines
11 KiB
C++
/***************************************************************************************
|
|
*
|
|
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
|
*
|
|
* By downloading, copying, installing or using the software you agree to this license.
|
|
* If you do not agree to this license, do not download, install,
|
|
* copy or use the software.
|
|
*
|
|
* Copyright (C) 2014-2022, Happytimesoft Corporation, all rights reserved.
|
|
*
|
|
* Redistribution and use in binary forms, with or without modification, are permitted.
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software distributed
|
|
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
|
|
* language governing permissions and limitations under the License.
|
|
*
|
|
****************************************************************************************/
|
|
|
|
#include "sys_inc.h"
|
|
#include "gb28181_cfg.h"
|
|
#include "xml_node.h"
|
|
#include "media_format.h"
|
|
|
|
|
|
/***************************************************************************************/
|
|
|
|
// the default configuration file name
|
|
#define GB28181_DEF_CFG "config.xml"
|
|
|
|
// global gb28181 configuration variable
|
|
GB28181_CFG g_gb28181_cfg;
|
|
|
|
|
|
/***************************************************************************************/
|
|
void gb28181_init_config()
|
|
{
|
|
memset(&g_gb28181_cfg, 0, sizeof(GB28181_CFG));
|
|
|
|
g_gb28181_cfg.server_port = 5060;
|
|
g_gb28181_cfg.media_protocol = 1;
|
|
g_gb28181_cfg.heartbeat_interval = 60;
|
|
g_gb28181_cfg.heartbeat_count = 3;
|
|
g_gb28181_cfg.reg_expires = 3600;
|
|
g_gb28181_cfg.media_base_port = 19000;
|
|
strcpy(g_gb28181_cfg.server_ip, get_local_ip());
|
|
strcpy(g_gb28181_cfg.server_domain, g_gb28181_cfg.server_ip);
|
|
strcpy(g_gb28181_cfg.device_id, "34020000001110000001");
|
|
strcpy(g_gb28181_cfg.password, "12345678");
|
|
}
|
|
|
|
int gb28181_parse_video_codec(const char * buff)
|
|
{
|
|
if (strcasecmp(buff, "H264") == 0)
|
|
{
|
|
return VIDEO_CODEC_H264;
|
|
}
|
|
else if (strcasecmp(buff, "H265") == 0)
|
|
{
|
|
return VIDEO_CODEC_H265;
|
|
}
|
|
else if (strcasecmp(buff, "MP4") == 0)
|
|
{
|
|
return VIDEO_CODEC_MP4;
|
|
}
|
|
|
|
return VIDEO_CODEC_NONE;
|
|
}
|
|
|
|
int gb28181_parse_audio_codec(const char * buff)
|
|
{
|
|
if (strcasecmp(buff, "G711") == 0)
|
|
{
|
|
return AUDIO_CODEC_G711A;
|
|
}
|
|
else if (strcasecmp(buff, "G711A") == 0)
|
|
{
|
|
return AUDIO_CODEC_G711A;
|
|
}
|
|
else if (strcasecmp(buff, "G711U") == 0)
|
|
{
|
|
return AUDIO_CODEC_G711U;
|
|
}
|
|
else if (strcasecmp(buff, "G722") == 0)
|
|
{
|
|
return AUDIO_CODEC_G722;
|
|
}
|
|
else if (strcasecmp(buff, "AAC") == 0)
|
|
{
|
|
return AUDIO_CODEC_AAC;
|
|
}
|
|
|
|
return AUDIO_CODEC_NONE;
|
|
}
|
|
|
|
BOOL gb28181_parse_video(XMLN * p_node, VIDEO_INFO * p_info)
|
|
{
|
|
XMLN * p_codec;
|
|
XMLN * p_width;
|
|
XMLN * p_height;
|
|
XMLN * p_framerate;
|
|
XMLN * p_bitrate;
|
|
|
|
p_codec = xml_node_get(p_node, "codec");
|
|
if (p_codec && p_codec->data)
|
|
{
|
|
p_info->codec = gb28181_parse_video_codec(p_codec->data);
|
|
}
|
|
|
|
p_width = xml_node_get(p_node, "width");
|
|
if (p_width && p_width->data)
|
|
{
|
|
p_info->width = atoi(p_width->data);
|
|
|
|
if (p_info->width < 0)
|
|
{
|
|
p_info->width = 0;
|
|
}
|
|
}
|
|
|
|
p_height = xml_node_get(p_node, "height");
|
|
if (p_height && p_height->data)
|
|
{
|
|
p_info->height = atoi(p_height->data);
|
|
|
|
if (p_info->height < 0)
|
|
{
|
|
p_info->height = 0;
|
|
}
|
|
}
|
|
|
|
p_framerate = xml_node_get(p_node, "framerate");
|
|
if (p_framerate && p_framerate->data)
|
|
{
|
|
p_info->framerate = atoi(p_framerate->data);
|
|
|
|
if (p_info->framerate < 0)
|
|
{
|
|
p_info->framerate = 0;
|
|
}
|
|
}
|
|
|
|
p_bitrate = xml_node_get(p_node, "bitrate");
|
|
if (p_bitrate && p_bitrate->data)
|
|
{
|
|
p_info->bitrate = atoi(p_bitrate->data);
|
|
|
|
if (p_info->bitrate < 0)
|
|
{
|
|
p_info->bitrate = 0;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL gb28181_parse_audio(XMLN * p_node, AUDIO_INFO * p_info)
|
|
{
|
|
XMLN * p_codec;
|
|
XMLN * p_samplerate;
|
|
XMLN * p_channels;
|
|
XMLN * p_bitrate;
|
|
|
|
p_codec = xml_node_get(p_node, "codec");
|
|
if (p_codec && p_codec->data)
|
|
{
|
|
p_info->codec = gb28181_parse_audio_codec(p_codec->data);
|
|
}
|
|
|
|
p_samplerate = xml_node_get(p_node, "samplerate");
|
|
if (p_samplerate && p_samplerate->data)
|
|
{
|
|
p_info->samplerate = atoi(p_samplerate->data);
|
|
|
|
if (p_info->samplerate < 0)
|
|
{
|
|
p_info->samplerate = 0;
|
|
}
|
|
}
|
|
|
|
p_channels = xml_node_get(p_node, "channels");
|
|
if (p_channels && p_channels->data)
|
|
{
|
|
p_info->channels = atoi(p_channels->data);
|
|
|
|
if (p_info->channels < 0)
|
|
{
|
|
p_info->channels = 0;
|
|
}
|
|
else if (p_info->channels > 2)
|
|
{
|
|
p_info->channels = 2;
|
|
}
|
|
}
|
|
|
|
p_bitrate = xml_node_get(p_node, "bitrate");
|
|
if (p_bitrate && p_bitrate->data)
|
|
{
|
|
p_info->bitrate = atoi(p_bitrate->data);
|
|
|
|
if (p_info->bitrate < 0)
|
|
{
|
|
p_info->bitrate = 0;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL gb28181_parse_output(XMLN * p_node, MEDIA_INFO * p_output)
|
|
{
|
|
XMLN * p_video;
|
|
XMLN * p_audio;
|
|
|
|
p_video = xml_node_get(p_node, "video");
|
|
if (p_video)
|
|
{
|
|
p_output->has_video = gb28181_parse_video(p_video, &p_output->video);
|
|
}
|
|
|
|
p_audio = xml_node_get(p_node, "audio");
|
|
if (p_audio)
|
|
{
|
|
p_output->has_audio = gb28181_parse_audio(p_audio, &p_output->audio);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL gb28181_parse_channel(XMLN * p_node, GBCHANNEL * p_channel)
|
|
{
|
|
XMLN * p_cid;
|
|
XMLN * p_cname;
|
|
XMLN * p_media_url;
|
|
XMLN * p_output;
|
|
|
|
p_cid = xml_node_get(p_node, "cid");
|
|
if (p_cid && p_cid->data)
|
|
{
|
|
strncpy(p_channel->cid, p_cid->data, sizeof(p_channel->cid)-1);
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
p_cname = xml_node_get(p_node, "cname");
|
|
if (p_cname && p_cname->data)
|
|
{
|
|
strncpy(p_channel->cname, p_cname->data, sizeof(p_channel->cname)-1);
|
|
}
|
|
|
|
p_media_url = xml_node_get(p_node, "media_url");
|
|
if (p_media_url && p_media_url->data)
|
|
{
|
|
strncpy(p_channel->media_url, p_media_url->data, sizeof(p_channel->media_url)-1);
|
|
}
|
|
|
|
p_output = xml_node_get(p_node, "output");
|
|
if (p_output)
|
|
{
|
|
gb28181_parse_output(p_output, &p_channel->output);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL gb28181_parse_config(char * xml_buff, int rlen)
|
|
{
|
|
XMLN * p_node;
|
|
XMLN * p_server_ip;
|
|
XMLN * p_server_port;
|
|
XMLN * p_server_id;
|
|
XMLN * p_server_domain;
|
|
XMLN * p_local_port;
|
|
XMLN * p_device_id;
|
|
XMLN * p_device_name;
|
|
XMLN * p_password;
|
|
XMLN * p_protocol;
|
|
XMLN * p_media_protocol;
|
|
XMLN * p_reg_expires;
|
|
XMLN * p_heartbeat_interval;
|
|
XMLN * p_heartbeat_count;
|
|
XMLN * p_media_base_port;
|
|
XMLN * p_log_enable;
|
|
XMLN * p_log_level;
|
|
XMLN * p_channel;
|
|
|
|
p_node = xxx_hxml_parse(xml_buff, rlen);
|
|
if (NULL == p_node)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
p_server_ip = xml_node_get(p_node, "server_ip");
|
|
if (p_server_ip && p_server_ip->data)
|
|
{
|
|
strncpy(g_gb28181_cfg.server_ip, p_server_ip->data, sizeof(g_gb28181_cfg.server_ip)-1);
|
|
}
|
|
|
|
p_server_port = xml_node_get(p_node, "server_port");
|
|
if (p_server_port && p_server_port->data)
|
|
{
|
|
g_gb28181_cfg.server_port = atoi(p_server_port->data);
|
|
}
|
|
|
|
p_server_id = xml_node_get(p_node, "server_id");
|
|
if (p_server_id && p_server_id->data)
|
|
{
|
|
strncpy(g_gb28181_cfg.server_id, p_server_id->data, sizeof(g_gb28181_cfg.server_id)-1);
|
|
}
|
|
|
|
p_server_domain = xml_node_get(p_node, "server_domain");
|
|
if (p_server_domain && p_server_domain->data)
|
|
{
|
|
strncpy(g_gb28181_cfg.server_domain, p_server_domain->data, sizeof(g_gb28181_cfg.server_domain)-1);
|
|
}
|
|
|
|
p_local_port = xml_node_get(p_node, "local_port");
|
|
if (p_local_port && p_local_port->data)
|
|
{
|
|
g_gb28181_cfg.local_port = atoi(p_local_port->data);
|
|
}
|
|
|
|
p_device_id = xml_node_get(p_node, "device_id");
|
|
if (p_device_id && p_device_id->data)
|
|
{
|
|
strncpy(g_gb28181_cfg.device_id, p_device_id->data, sizeof(g_gb28181_cfg.device_id)-1);
|
|
}
|
|
|
|
p_device_name = xml_node_get(p_node, "device_name");
|
|
if (p_device_name && p_device_name->data)
|
|
{
|
|
strncpy(g_gb28181_cfg.device_name, p_device_name->data, sizeof(g_gb28181_cfg.device_name)-1);
|
|
}
|
|
|
|
p_password = xml_node_get(p_node, "password");
|
|
if (p_password && p_password->data)
|
|
{
|
|
strncpy(g_gb28181_cfg.password, p_password->data, sizeof(g_gb28181_cfg.password)-1);
|
|
}
|
|
|
|
p_protocol = xml_node_get(p_node, "protocol");
|
|
if (p_protocol && p_protocol->data)
|
|
{
|
|
if (strcasecmp(p_protocol->data, "tcp") == 0)
|
|
{
|
|
g_gb28181_cfg.protocol = 1;
|
|
}
|
|
}
|
|
|
|
p_media_protocol = xml_node_get(p_node, "media_protocol");
|
|
if (p_media_protocol && p_media_protocol->data)
|
|
{
|
|
if (strcasecmp(p_media_protocol->data, "tcp") == 0)
|
|
{
|
|
g_gb28181_cfg.media_protocol = 1;
|
|
}
|
|
}
|
|
|
|
p_reg_expires = xml_node_get(p_node, "reg_expires");
|
|
if (p_reg_expires && p_reg_expires->data)
|
|
{
|
|
g_gb28181_cfg.reg_expires = atoi(p_reg_expires->data);
|
|
}
|
|
|
|
p_heartbeat_interval = xml_node_get(p_node, "heartbeat_interval");
|
|
if (p_heartbeat_interval && p_heartbeat_interval->data)
|
|
{
|
|
g_gb28181_cfg.heartbeat_interval = atoi(p_heartbeat_interval->data);
|
|
}
|
|
|
|
p_heartbeat_count = xml_node_get(p_node, "heartbeat_count");
|
|
if (p_heartbeat_count && p_heartbeat_count->data)
|
|
{
|
|
g_gb28181_cfg.heartbeat_count = atoi(p_heartbeat_count->data);
|
|
}
|
|
|
|
p_media_base_port = xml_node_get(p_node, "media_base_port");
|
|
if (p_media_base_port && p_media_base_port->data)
|
|
{
|
|
g_gb28181_cfg.media_base_port = atoi(p_media_base_port->data);
|
|
}
|
|
|
|
p_log_enable = xml_node_get(p_node, "log_enable");
|
|
if (p_log_enable && p_log_enable->data)
|
|
{
|
|
g_gb28181_cfg.log_enable = atoi(p_log_enable->data);
|
|
}
|
|
|
|
p_log_level = xml_node_get(p_node, "log_level");
|
|
if (p_log_level && p_log_level->data)
|
|
{
|
|
g_gb28181_cfg.log_level = atoi(p_log_level->data);
|
|
}
|
|
|
|
p_channel = xml_node_get(p_node, "channel");
|
|
while (p_channel && soap_strcmp(p_channel->name, "channel") == 0)
|
|
{
|
|
int idx = g_gb28181_cfg.channel_nums;
|
|
|
|
if (gb28181_parse_channel(p_channel, &g_gb28181_cfg.channels[idx]))
|
|
{
|
|
g_gb28181_cfg.channel_nums++;
|
|
|
|
if (g_gb28181_cfg.channel_nums >= MAX_CH_NUMS)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
p_channel = p_channel->next;
|
|
}
|
|
|
|
xml_node_del(p_node);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL gb28181_read_config(const char * config)
|
|
{
|
|
gb28181_init_config();
|
|
|
|
BOOL ret = FALSE;
|
|
int len, rlen;
|
|
FILE * fp = NULL;
|
|
char * xml_buff = NULL;
|
|
const char * filename = NULL;
|
|
|
|
if (NULL == config || config[0] == '\0')
|
|
{
|
|
filename = GB28181_DEF_CFG;
|
|
}
|
|
else
|
|
{
|
|
filename = config;
|
|
}
|
|
|
|
// read config file
|
|
|
|
fp = fopen(filename, "r");
|
|
if (NULL == fp)
|
|
{
|
|
goto FAILED;
|
|
}
|
|
|
|
fseek(fp, 0, SEEK_END);
|
|
|
|
len = ftell(fp);
|
|
if (len <= 0)
|
|
{
|
|
goto FAILED;
|
|
}
|
|
fseek(fp, 0, SEEK_SET);
|
|
|
|
xml_buff = (char *) malloc(len + 1);
|
|
if (NULL == xml_buff)
|
|
{
|
|
goto FAILED;
|
|
}
|
|
|
|
rlen = fread(xml_buff, 1, len, fp);
|
|
if (rlen > 0)
|
|
{
|
|
xml_buff[rlen] = '\0';
|
|
ret = gb28181_parse_config(xml_buff, rlen);
|
|
}
|
|
else
|
|
{
|
|
log_print(HT_LOG_ERR, "%s, rlen = %d, len=%d\r\n", __FUNCTION__, rlen, len);
|
|
}
|
|
|
|
FAILED:
|
|
|
|
if (fp)
|
|
{
|
|
fclose(fp);
|
|
}
|
|
|
|
if (xml_buff)
|
|
{
|
|
free(xml_buff);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
GBCHANNEL * gb28181_get_channel(const char * cid)
|
|
{
|
|
int i;
|
|
|
|
if (strcmp(cid, g_gb28181_cfg.device_id) == 0)
|
|
{
|
|
return &g_gb28181_cfg.channels[0];
|
|
}
|
|
|
|
for (i = 0; i < g_gb28181_cfg.channel_nums; i++)
|
|
{
|
|
if (strcmp(cid, g_gb28181_cfg.channels[i].cid) == 0)
|
|
{
|
|
return &g_gb28181_cfg.channels[i];
|
|
}
|
|
}
|
|
|
|
return &g_gb28181_cfg.channels[0];
|
|
}
|
|
|
|
|
|
|