/******************************************************************************
* 函数名称: tr2_set_video_encoder_config_xml_to_json()
* 函数描述: 解析tr2:SetVideoEncoderConfiguration请求的具体内容
* 输 入: soap -- soap结构体
* 输 出: json_req -- 根据请求构造的json object
* 返 回 值: ERROR/OK
******************************************************************************/
LOCAL S32 tr2_set_video_encoder_config_xml_to_json(SOAP_CONTEXT *soap, JSON_OBJPTR *json_req)
{
S32 i = 0;
JSON_OBJPTR json_obj = NULL;
JSON_OBJPTR json_sec = NULL;
JSON_OBJPTR json_opt = NULL;
S32 request_len = 0;
S32 ch = 0;
char *xml_start = NULL;
char *xml_str = NULL;
char **p = NULL;
char charbuf[LEN_INFO] = {0};
char attr_name[2][LEN_TAG] = {{"token"}, {"anyAttribute"}};
S32 name_str_len = sizeof(attr_name[0]);
char attr_value_buf[2][LEN_ANY/2] = {{0}};
S32 value_str_len = sizeof(attr_value_buf[0]);
void *ptrs_to_free[ONVIF_MAX_FREE_NUM] = {0};
TRT_SET_VIDEO_ENCODER_CONF set_config_cmd = {0};
char resolution[LEN_VALUE] = {0};
S32 frame_rate_limit = 0;
S32 bitrate_limit = 0;
S32 rate_control_flag = 1;
VIDEO_CAP_MAIN video_cap_main = {{0}};
char *encode_type = NULL;
S32 bitrate_type = -1;
if (soap == NULL || json_req == NULL)
{
ONVIF_TRACE("soap == NULL.");
return ERROR;
}
if (OK != soap_usernametoken_auth(soap, UM_OPERATOR))
{
ONVIF_TRACE("Auth failed\n");
soap_fault(soap, "SOAP-ENV:Sender", "ter:NotAuthorized", NULL, "Authority failure");
soap->error = 400;
return ERROR;
}
if (soap->request_begin != NULL && soap->request_end != NULL)
{
request_len = soap->request_end - soap->request_begin;
if (request_len < 0)
{
ONVIF_TRACE("request_len < 0.");
goto error_parse;
}
xml_str = xml_start = soap->request_begin;
p = (char **)&xml_str;
}
else
{
ONVIF_ERROR("soap request content is NULL.");
return ERROR;
}
while (((*p) - xml_start) < request_len)
{
if ((ch = soap_get_tag(xml_start, request_len, p, charbuf, sizeof(charbuf))) == EOF)
{
goto error_parse;
}
if (charbuf[0] == '/')
{
continue;
}
if (TRUE == soap_match_tag(charbuf, "Configuration"))
{
if (IS_WHITE_SPACE(ch))
{
ch = soap_parse_element_attr_out_len(xml_start, request_len, p,
2, (char *)attr_name, name_str_len, (char *)attr_value_buf, value_str_len);
if (strlen(attr_value_buf[1]) != 0)
{
json_obj = jso_from_string((const char *)attr_value_buf[1]);
if (json_obj != NULL)
{
goto out;
}
}
ONVIF_TRACE("token: %s", attr_value_buf[0]);
if(0 != strcmp(attr_value_buf[0], "main") && 0 != strcmp(attr_value_buf[0], "minor"))
{
goto error_parse;
}
set_config_cmd.config = MALLOC_AND_REGISTER(TT_VIDEO_ENCODER_CONFIG, 1,
ptrs_to_free, ONVIF_MAX_FREE_NUM);
if (NULL == set_config_cmd.config)
{
goto error_parse;
}
set_config_cmd.config->token = MALLOC_AND_REGISTER(char, strlen(attr_value_buf[0]) + 1,
ptrs_to_free, ONVIF_MAX_FREE_NUM);
if (NULL == set_config_cmd.config->token)
{
goto error_parse;
}
strncpy(set_config_cmd.config->token, attr_value_buf[0], strlen(attr_value_buf[0]) + 1);
}
continue;
}
if (TRUE == soap_match_tag(charbuf, "Name"))
{
if (NULL == set_config_cmd.config)
{
goto error_parse;
}
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("Name: %s", charbuf);
set_config_cmd.config->name = MALLOC_AND_REGISTER(char, strlen(charbuf) + 1,
ptrs_to_free, ONVIF_MAX_FREE_NUM);
if (NULL == set_config_cmd.config->name)
{
goto error_parse;
}
strncpy(set_config_cmd.config->name, charbuf,strlen(charbuf) + 1);
continue;
}
if (TRUE == soap_match_tag(charbuf, "UseCount"))
{
if (NULL == set_config_cmd.config)
{
goto error_parse;
}
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("UseCount: %s", charbuf);
set_config_cmd.config->use_count = atoi(charbuf);
continue;
}
if (TRUE == soap_match_tag(charbuf, "Encoding"))
{
if (NULL == set_config_cmd.config)
{
goto error_parse;
}
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("Encoding: %s", charbuf);
if (0 == strcmp(charbuf, TR2_VIDEO_ENCODING_MIME_NAME_H264))
{
encode_type = "H264";
}
else if (0 == strcmp(charbuf, TR2_VIDEO_ENCODING_MIME_NAME_H265))
{
encode_type = "H265";
}
else
{
ONVIF_ERROR("Invalid encode type: %s", charbuf);
goto error_parse;
}
continue;
}
if (TRUE == soap_match_tag(charbuf, "Resolution"))
{
if (NULL == set_config_cmd.config)
{
goto error_parse;
}
set_config_cmd.config->resolution = MALLOC_AND_REGISTER(TT_VIDEO_RESOLUTION, 1,
ptrs_to_free, ONVIF_MAX_FREE_NUM);
if (NULL == set_config_cmd.config->resolution)
{
goto error_parse;
}
continue;
}
if (TRUE == soap_match_tag(charbuf, "Width"))
{
if (NULL == set_config_cmd.config || NULL == set_config_cmd.config->resolution)
{
goto error_parse;
}
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("Width: %s", charbuf);
set_config_cmd.config->resolution->width = atoi(charbuf);
continue;
}
if (TRUE == soap_match_tag(charbuf, "Height"))
{
if (NULL == set_config_cmd.config || NULL == set_config_cmd.config->resolution)
{
goto error_parse;
}
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("Height: %s", charbuf);
set_config_cmd.config->resolution->height = atoi(charbuf);
continue;
}
if (TRUE == soap_match_tag(charbuf, "Quality"))
{
if (NULL == set_config_cmd.config)
{
goto error_parse;
}
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("Quality: %s", charbuf);
set_config_cmd.config->quality = atoi(charbuf);
continue;
}
if (TRUE == soap_match_tag(charbuf, "RateControl"))
{
if (NULL == set_config_cmd.config)
{
goto error_parse;
}
if (IS_WHITE_SPACE(ch))
{
char attr_in_name[20] = {"ConstantBitRate"};
char attr_out_buf[30] = {0};
int name_string_len = sizeof(attr_in_name);
int value_string_len = sizeof(attr_out_buf);
ch = soap_parse_element_attr_out_len(xml_start, request_len, p,
1, attr_in_name, name_string_len, attr_out_buf, value_string_len);
if (EOF == ch)
{
ONVIF_ERROR("EOF == ch");
goto error_parse;
}
if (0 == strcmp(attr_out_buf, "true"))
{
bitrate_type = BITRATE_TYPE_CBR;
}
else if (0 == strcmp(attr_out_buf, "false"))
{
bitrate_type = BITRATE_TYPE_VBR;
}
}
set_config_cmd.config->rate_control = MALLOC_AND_REGISTER(TT_VIDEO_RATE_CONTROL, 1,
ptrs_to_free, ONVIF_MAX_FREE_NUM);
if (NULL == set_config_cmd.config->rate_control)
{
goto error_parse;
}
continue;
}
if (TRUE == soap_match_tag(charbuf, "FrameRateLimit"))
{
if (NULL == set_config_cmd.config || NULL == set_config_cmd.config->rate_control)
{
goto error_parse;
}
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("FrameRateLimit: %s", charbuf);
set_config_cmd.config->rate_control->frame_rate_limit = atoi(charbuf);
continue;
}
if (TRUE == soap_match_tag(charbuf, "BitrateLimit"))
{
if (NULL == set_config_cmd.config || NULL == set_config_cmd.config->rate_control)
{
goto error_parse;
}
if (OK != soap_parse_element_value(xml_start, request_len, p, ch,
charbuf, sizeof(charbuf)))
{
goto error_parse;
}
ONVIF_TRACE("BitrateLimit: %s", charbuf);
set_config_cmd.config->rate_control->bitrate_limit = atoi(charbuf);
continue;
}
}
/* bug #434969, 在大华NVR上有抓到SetVideoEncoderConfiguration中没有Configuratio内容的报文,
* 为防止处理这样的异常报文时set_config_cmd.config为NULL空指针,增加以下判断防止系统崩溃*/
if(!set_config_cmd.config)
{
goto error_parse;
}
if(set_config_cmd.config->rate_control)
{
/* TODO: 比较是否超出最大值 */
/*
if((minFr > req->Configuration->RateControl->frame_rate_limit)
|| (maxFr < req->Configuration->RateControl->frame_rate_limit)
|| (minBr > req->Configuration->RateControl->bitrate_limit)
|| (maxBr < req->Configuration->RateControl->bitrate_limit))
{
return onvif_fault(soap, "SOAP-ENV:Sender", "ter:InvalidArgVal", "ter:ConfigModify", NULL);
}*/
frame_rate_limit = (1 << 16) + set_config_cmd.config->rate_control->frame_rate_limit;
bitrate_limit = select_appropriate_bitrate_limit(set_config_cmd.config->token,
set_config_cmd.config->rate_control->bitrate_limit);
if (ERROR == bitrate_limit)
{
goto error_parse;
}
}
else
{
rate_control_flag = FALSE;
}
snprintf(resolution, LEN_VALUE, "%d*%d", set_config_cmd.config->resolution->width, set_config_cmd.config->resolution->height);
ONVIF_TRACE("VideoPrama:%s,%d,%s,%d,%d\n",
set_config_cmd.config->token,
set_config_cmd.config->quality,
resolution,
frame_rate_limit,
bitrate_limit);
json_obj = jso_new_obj();
json_sec = jso_new_obj();
json_opt = jso_new_obj();
if (!json_obj || !json_sec || !json_opt)
{
ONVIF_ERROR("jso_new_obj fail.");
jso_free_obj(json_obj);
jso_free_obj(json_sec);
jso_free_obj(json_opt);
goto error_parse;
}
jso_obj_add(json_obj, "video", json_sec);
jso_obj_add(json_sec, set_config_cmd.config->token, json_opt);
if (encode_type)
{
jso_add_string(json_opt, "encode_type", encode_type);
}
jso_add_string(json_opt, "resolution", resolution);
/* 设置quality时,DUT只支持1、3、5(低中高三挡),但外司NVR可支持更多选项,
* 当DUT不支持设置的quality时,和SLP平台一致,就近保存为1、3、5三档。 */
if (0 == ds_read(VIDEO_CAP_MAIN_PATH, &video_cap_main, sizeof(VIDEO_CAP_MAIN)))
{
if ((VIDEO_QUALITY_S <= set_config_cmd.config->quality) &&
(VIDEO_QUALITY_L >= set_config_cmd.config->quality))
{
jso_add_int(json_opt, "quality", set_config_cmd.config->quality);
}
}
else
{
i = 0;
while (QUALITYS_NUM > i)
{
if (set_config_cmd.config->quality >= video_cap_main.qualitys[i])
{
++i;
}
else
{
break;
}
}
if (QUALITYS_NUM == i)
{
set_config_cmd.config->quality = video_cap_main.qualitys[QUALITYS_NUM - 1];
}
else if (0 == i)
{
set_config_cmd.config->quality = video_cap_main.qualitys[0];
}
else
{
set_config_cmd.config->quality = video_cap_main.qualitys[i - 1];
}
jso_add_int(json_opt, "quality", set_config_cmd.config->quality);
}
if(rate_control_flag)
{
jso_add_int(json_opt, "frame_rate", frame_rate_limit);
jso_add_int(json_opt, "bitrate", bitrate_limit);
if (BITRATE_TYPE_CBR == bitrate_type)
{
jso_add_string(json_opt, "bitrate_type", "cbr");
}
else if (BITRATE_TYPE_VBR == bitrate_type)
{
jso_add_string(json_opt, "bitrate_type", "vbr");
}
}
jso_add_string(json_obj, "method", "set");
out:
*json_req = json_obj;
free_ptrs(ptrs_to_free, ONVIF_MAX_FREE_NUM);
return OK;
error_parse:
free_ptrs(ptrs_to_free, ONVIF_MAX_FREE_NUM);
return ERROR;
}
解释代码