bool https_vod_callback(struct tphttp_connection*tc, void* priv)
{ /*
GET /vod/data/mixstream?deviceId=xxx&playerId=xxx&start_time=1591013983 HTTP/1.1
Host: *
User-Agent: *
X-PLAYER-ID: tty.kewzzRltTbQxKfLliIlJczmTiBDbQuBE
Content-Type: multipart/x-mixed-replace;boundary=audio-boundary--
Connection: keep-alive
*/
DBG_ERR("https_mixstream_uri_callback ..\n");
MEDIACENTER_CTX *media_ctx = (MEDIACENTER_CTX *)get_top_ctx();
DEV_INFO *dev_info = NULL;
STORAGE_PLAYBACK_ST *playback = NULL;
struct tpsocket_fd *sock = tc->sock;
int error_code = 0;
char error_msg_buf[LEN_MAX_BUF] = {0};
int remote_type = 0;
int event_type_got = 0;
#ifdef HARDDISK_STORAGE
int face_type_flag = 0;
int face_id_got = 0;
long long vod_session_face_id[FD_FACE_SUPPORT_NUM] = {0};
int vod_session_det_origin[FD_FACE_SUPPORT_NUM] = {0};
int det_origin_exist_flag = 0; /*0表示旧版本不存在det_origin的情况,1代表新版本存在的情况*/
int det_origin_num = 0;
#endif
uint8_t vod_session_event_type[VOD_SESSION_EVENT_TYPE_LEN] = {0};
int playback_type = -1;
sock->handler.write_buf_max = 512*1024;
sock->handler.read_buf_max = 500000;
DBG_INFO("vod session https: %s:%s connected path: '%s' Requested: '%s'", sock->addr, sock->port, sock->path, sock->parser.http.url);
const char *playerId = NULL;
const char* dev_id = NULL;
const char* mac = NULL;
const char *type = NULL;
const char *event_type_str = NULL;
#ifdef HARDDISK_STORAGE
const char *play_type = NULL;
const char *face_id_str = NULL;
const char *det_origin_str = NULL;
#endif
/* check client ip */
if (!strcmp(sock->addr, "127.0.0.1")) {
remote_type = REMOTE_TYPE_P2P;
} else {
remote_type = REMOTE_TYPE_NONE;
}
type = tphttp_env_get(tc, "type");
if ((type && !strncmp(type, VOD_STREAM_TYPE_SDVOD, strlen(VOD_STREAM_TYPE_SDVOD))) || \
(type && !strncmp(type, VOD_STREAM_TYPE_PLAYBACK, strlen(VOD_STREAM_TYPE_PLAYBACK))) || \
strcasewithprefix(sock->parser.http.url, URL_MIXSTREAM)) {
playback_type = PLAYBACK_TYPE_MIXSTREAM;
} else if ((type && !strncmp(type, VOD_STREAM_TYPE_SDDOWNLOAD1, strlen(VOD_STREAM_TYPE_SDDOWNLOAD1))) || \
strcasewithprefix(sock->parser.http.url, URL_PICSTREAMSTREAM)){
#ifdef SDCARD_VIDEO_DOWNLOAD
const char *media_type = tphttp_env_get(tc, "media_type");
if (media_type && atol(media_type) == 0)
{
playback_type = PLAYBACK_TYPE_VIDEO_DOWNLOAD;
}
else
#endif
playback_type = PLAYBACK_TYPE_PICTURESTREAM;
}
/*parse deviceId from url*/
dev_id = tphttp_env_get(tc, "deviceId");
if(!dev_id) {
dev_id = tphttp_env_get(tc, "deviceid");
if(!dev_id) {
dev_id = tphttp_env_get(tc, "dev_id");
if(!dev_id) {
DBG_ERR("lack of deviceId param to get vod media, check mac!\n");
}
}
}
mac = tphttp_env_get(tc, "camera_mac");
if(!mac) {
mac = tphttp_env_get(tc, "deviceMac");
if(!mac) {
mac = tphttp_env_get(tc, "mac");
if(!mac) {
DBG_ERR("lack of deviceMac param to get vod media!\n");
}
}
}
if(!mac && !dev_id && playback_type != PLAYBACK_TYPE_PICTURESTREAM){
DBG_ERR("lack of deviceId and deviceMac param to get vod media!\n");
tpsocket_write_force(sock, tpbuf_http_response(503, "Service Unavailable", 0, false), true);
tpsocket_close(sock);
return true;
}
if(dev_id){
dev_info = get_dev_info(media_ctx, (char *)dev_id, NULL);
}
if(!dev_info && mac){
dev_info = get_del_dev_info_by_mac(media_ctx, (char*) mac);
}
if(!dev_info && mac){
dev_info = get_dev_info_by_mac(media_ctx, mac);
}
if(!dev_info && playback_type == PLAYBACK_TYPE_PICTURESTREAM) {
DBG_WARN("PLAYBACK STREAM TYPE: USE SIMULATE DEV INFO.\n");
dev_info = (DEV_INFO *)media_ctx->hub_dev_for_playback;
}
if(!dev_info) {
DBG_ERR("couldn't find child device\n");
tpsocket_write_force(sock, tpbuf_http_response(503, "Service Unavailable", 0, false), true);
tpsocket_close(sock);
return true;
}
playback = dev_info->playback;
if (!playback) {
DBG_ERR("dev %s playback NULL\n", dev_info->dev_mac);
tpsocket_write_force(sock, tpbuf_http_response(503, "Service Unavailable", 0, false), true);
tpsocket_close(sock);
return true;
}
/*parse playerId from url*/
playerId = tphttp_env_get(tc, "playerId");
if(!playerId) {
playerId = tphttp_env_get(tc, "playerid");
if(!playerId) {
playerId = tphttp_hdr_get(tc, "X-PLAYER-ID");
if(!playerId) {
playerId = tphttp_hdr_get(tc, "X-APP-ID");
if(!playerId || !playerId[0]) {
DBG_ERR("dev:[%s] HAS NOT APP ID\n", dev_info->dev_mac);
tpsocket_write_force(sock, tpbuf_http_response(503, "Service Unavailable", 0, false), true);
tpsocket_close(sock);
return true;
}
}
}
}
/* parse event_type from url */
event_type_str = tphttp_env_get(tc, "event_type");
if (event_type_str) {
DBG_DBG("got event_type: %s\n", event_type_str);
int json_str_len = strlen(event_type_str) + strlen("{\"event_type\":}") + 1;
char *json_str = calloc(1, json_str_len);
struct blob_buf b = {NULL};
blobmsg_buf_init(&b);
snprintf(json_str, json_str_len, "{\"event_type\":%s}", event_type_str);
if (blobmsg_add_json_from_string(&b, json_str)) {
struct blobmsg (
blobmsg_array event_type,
) (response, &b);
if (response.event_type) {
event_type_got = 1;
int rem = 0;
struct blob_attr *cur = NULL;
blobmsg_for_each_attr(cur, response.event_type, rem) {
if (blobmsg_type(cur) == BLOBMSG_TYPE_INT32) {
unsigned int event_type = blobmsg_get_u32(cur);
/* add event type */
#ifdef HARDDISK_STORAGE
if(event_type == STORAGE_CONTROL_FACE_DET_ALARM){
face_type_flag = 1;
}else{
storage_vod_add_event_type(vod_session_event_type, event_type);
}
#else
storage_vod_add_event_type(vod_session_event_type, event_type);
#endif
}
}
}
}
blob_buf_free(&b);
free(json_str);
}
#ifdef HARDDISK_STORAGE
/* parse face_id from url */
face_id_str = tphttp_env_get(tc, "face_id");
if (face_id_str) {
DBG_WARN("\nface_id_strP:%s,face_id_str%s\n",face_id_str,face_id_str);
det_origin_str = tphttp_env_get(tc, "det_origin");
if (!det_origin_str)
{
DBG_DBG("det_origin_str is null, is old version\n");
det_origin_exist_flag = 0;
} else {
DBG_DBG("det_origin_str is exist, is new version\n");
det_origin_exist_flag = 1;
storage_vod_det_origins_init(vod_session_det_origin);
int origin_json_str_len = strlen(det_origin_str) + strlen("{\"det_origin\":}") + 1;
char *origin_json_str = calloc(1, origin_json_str_len);
struct blob_buf bf_origin = {NULL};
blobmsg_buf_init(&bf_origin);
snprintf(origin_json_str, origin_json_str_len, "{\"det_origin\":%s}", det_origin_str);
DBG_DBG("det_origin_str is %s\n", det_origin_str);
if (blobmsg_add_json_from_string(&bf_origin, origin_json_str)) {
struct blobmsg (
blobmsg_array det_origin,
) (response, &bf_origin);
if (response.det_origin) {
int rem_origin = 0;
struct blob_attr *cur_origin = NULL;
int i = 0;
blobmsg_for_each_attr(cur_origin, response.det_origin, rem_origin) {
if (blobmsg_type(cur_origin) == BLOBMSG_TYPE_INT32) {
int det_ori = blobmsg_get_u32(cur_origin);
if (det_ori != 0 && det_ori != 1) {
det_ori = 0;
}
vod_session_det_origin[i] = det_ori;
i++;
}
}
det_origin_num = i;
} else {
DBG_ERR("det_origin is NULL, dev %s playback is NULL\n", dev_info->dev_mac);
tpsocket_write_force(sock, tpbuf_http_response(503, "Service Unavailable", 0, false), true);
tpsocket_close(sock);
return true;
}
}
}
storage_vod_face_ids_init(vod_session_face_id);
int face_json_str_len = strlen(face_id_str) + strlen("{\"face_id\":}") + 1;
char *face_json_str = calloc(1, face_json_str_len);
struct blob_buf bf = {NULL};
blobmsg_buf_init(&bf);
snprintf(face_json_str, face_json_str_len, "{\"face_id\":%s}", face_id_str);
DBG_ERR("\nface_json_str:%s\n",face_json_str);
if (blobmsg_add_json_from_string(&bf, face_json_str)) {
struct blobmsg (
blobmsg_array face_id,
) (response, &bf);
if (response.face_id) {
face_id_got = 1;
int rem_face = 0;
struct blob_attr *cur_face = NULL;
int i = 0;
blobmsg_for_each_attr(cur_face, response.face_id, rem_face) {
if (blobmsg_type(cur_face) == BLOBMSG_TYPE_INT64) {
long long face_id = blobmsg_get_u64(cur_face);
/* add FACE ID */
DBG_INFO("\nadd face_id:%lld\n",face_id);
if (det_origin_exist_flag == 0) {
storage_vod_add_face_id(vod_session_face_id, face_id);
} else if (det_origin_exist_flag == 1) {
if (i < det_origin_num) {
U64 marked_face_id = 0;
/* add FACE ID */
if (vod_session_det_origin[i] == 1) {
marked_face_id = fd_control_mark_nvmp_faceid((U64)face_id);
}
storage_vod_add_face_id(vod_session_face_id, (long long)marked_face_id);
i++;
} else {
DBG_ERR("the det origin and the face id is not match\n");
tpsocket_write_force(sock, tpbuf_http_response(503, "Service Unavailable", 0, false), true);
tpsocket_close(sock);
return true;
}
}
}
}
if (i != det_origin_num) {
DBG_ERR("the det_origin and the face id is not match\n");
tpsocket_write_force(sock, tpbuf_http_response(503, "Service Unavailable", 0, false), true);
tpsocket_close(sock);
return true;
}
}
}
else
{
DBG_ERR("\nface_id not got\n");
}
blob_buf_free(&bf);
free(face_json_str);
}
if (!face_id_got) {
storage_vod_face_ids_init(vod_session_face_id);
}
#endif
if (!event_type_got) {
storage_vod_set_event_types_all(vod_session_event_type);
#ifdef HARDDISK_STORAGE
face_type_flag = 0;
#endif
}
if (playback_type == PLAYBACK_TYPE_MIXSTREAM) {
/* request count of local or P2P vod stream: int */
dev_info->telemetry.vod_stream[!!media_ctx->eth_up].consumer[remote_type].request_count++;
}
/*jude occupied state*/
if(!playback->playerId[0]) {
DBG_NOTICE("dev:[%s] playerId null, local first time to start vod connection\n", dev_info->dev_mac);
strncpy(playback->playerId, playerId, 63);
} else {
if(strcmp(playback->playerId, playerId)) {
DBG_ERR("dev:[%s] local APP ID EXIST AND NOT MATCH\n", dev_info->dev_mac);
snprintf(error_msg_buf, sizeof(error_msg_buf), "{\"error_code\":%d}", MULTI_VOD_SESSION_BUSY);
tphttp_output_simple(tc, 503, "Service Unavailable", error_msg_buf, false);
if (playback_type == PLAYBACK_TYPE_MIXSTREAM) {
/* check busy count due to device occupied during local or P2P vod stream: int */
dev_info->telemetry.vod_stream[!!media_ctx->eth_up].consumer[remote_type].busy_count++;
}
return true;
}
}
// int dev_num = 0;
// DEV_INFO *dev_info_tmp = NULL;
// list_for_each_entry(dev_info_tmp, &media_ctx->dev_info, list){
// dev_num++;
// }
// relay_consumer_cur_left_num += RELAY_CONSUMER_MAX_NUM[dev_num] - relay_consumer_cur_max_num;
// relay_consumer_cur_max_num = RELAY_CONSUMER_MAX_NUM[dev_num];
//DBG_DBG("-------------------------vod-------------cur_num = %d\n", relay_consumer_cur_left_num);
if (playback_type == PLAYBACK_TYPE_MIXSTREAM) {
// if (relay_consumer_cur_left_num < RELAY_CONSUMER_CLIENT_TYPE_VOD_NUM){
// //DBG_DBG("------------------connections has been reached max num------------------------\n");
// return true;
// }
int index = 0;
const char *start_time = tphttp_env_get(tc, "start_time");
struct vod_session_t *vod_session = NULL;
index = storage_vod_session_start(playback, true, tc, PLAYBACK_TYPE_MIXSTREAM, false, remote_type, &error_code);
if(index < 0) {
DBG_ERR("dev:[%s] local VOD SESSION START FAILED\n", dev_info->dev_mac);
if (error_code == MULTI_VOD_SESSION_BUSY_FOR_ONE_CLIENT) {
snprintf(error_msg_buf, sizeof(error_msg_buf), "{\"error_code\":%d}", MULTI_VOD_SESSION_BUSY_FOR_ONE_CLIENT);
tphttp_output_simple(tc, 503, "Service Unavailable", error_msg_buf, false);
} else {
tphttp_output_simple(tc, 503, "Service Unavailable", NULL, false);
}
return true;
}
//sock->handler.priv = playback;
//sock->handler.cb = storage_playback_http_cb;
//relay_consumer_cur_left_num -= RELAY_CONSUMER_CLIENT_TYPE_VOD_NUM;
//DBG_DBG("-------------------------vod-------------cur_num = %d\n", relay_consumer_cur_left_num);
dev_info->vod_status = 1;
vod_session = &playback->vod_session[index];
const char *auto_seek = tphttp_env_get(tc, "auto_seek");
if(start_time) {
vod_session->start_time[VIDEO_START_TIME_INIT] = atoi(start_time);
vod_session->play_state = VOD_PLAY;
if (auto_seek) {
vod_session->auto_seek = atoi(auto_seek);
DBG_ERR("set auto seek %d\n", vod_session->auto_seek);
}
} else {
vod_session->play_state = VOD_PAUSE;
}
/* set event types */
storage_vod_set_event_types(vod_session->event_type, vod_session_event_type);
#ifdef HARDDISK_STORAGE
/* set face ids */
storage_vod_set_face_ids(vod_session->face_id, vod_session_face_id);
vod_session->face_type_flag = face_type_flag;
vod_session->face_traj = FALSE;
play_type = tphttp_env_get(tc, "play_type");
DBG_ERR("\n!!!!!!!!!!!!!!!palay_type = %s;face_id=%llu\n", play_type,vod_session->face_id[0]);
if((play_type && !strncmp(play_type, VOD_STREAM_TYPE_TRAJ_PLAY, strlen(VOD_STREAM_TYPE_TRAJ_PLAY))))
{
vod_session->face_traj = TRUE;
const char *traj_start_time = tphttp_env_get(tc, "traj_start_time");
if (traj_start_time)
{
DBG_ERR("exist traj_start_time: %s.\n", traj_start_time);
vod_session->traj_start_time = atoi(traj_start_time);
}
else
{
DBG_ERR("not exist traj_start_time: %lu.\n", vod_session->traj_start_time);
vod_session->traj_start_time = vod_session->start_time[VIDEO_START_TIME_INIT];
}
vod_session->start_time[VIDEO_START_TIME_PLAY] = vod_session->start_time[VIDEO_START_TIME_INIT];
}
#endif
sock->handler.priv = vod_session;
sock->handler.cb = storage_playback_http_cb;
#ifdef HARDDISK_STORAGE
memset(vod_session->mac, '\0', sizeof(vod_session->mac));
memcpy(vod_session->mac, dev_info->dev_mac, sizeof(dev_info->dev_mac));
vod_session->init_status = 0;
http_vod_handle_hdd(playback, index);
#else
http_vod_handle(playback, index);
#endif
tc->priv = vod_session;
tc->priv_free = (void*)vod_session_stop;
/* telemetry */
if (vod_session->play_state == VOD_PLAY) {
DBG_DBG("vod check success\n");
/* count of checking mp4 file successfully during local or P2P vod stream: int */
if (vod_session->remote_type >= 0 && vod_session->remote_type <= REMOTE_TYPE_P2P) {
dev_info->telemetry.vod_stream[!!media_ctx->eth_up].consumer[vod_session->remote_type].check_success_count++;
}
}
} else if (playback_type == PLAYBACK_TYPE_PICTURESTREAM) {
int index = 0;
struct vod_session_t *vod_session = NULL;
index = storage_vod_session_start(playback, true, tc, PLAYBACK_TYPE_PICTURESTREAM, false, remote_type, &error_code);
if(index < 0) {
DBG_ERR("dev:[%s] lcoal VOD SESSION START FAILED\n", dev_info->dev_mac);
if (error_code == MULTI_VOD_SESSION_BUSY_FOR_ONE_CLIENT) {
snprintf(error_msg_buf, sizeof(error_msg_buf), "{\"error_code\":%d}", MULTI_VOD_SESSION_BUSY_FOR_ONE_CLIENT);
tphttp_output_simple(tc, 503, "Service Unavailable", error_msg_buf, false);
} else {
tphttp_output_simple(tc, 503, "Service Unavailable", NULL, false);
}
return true;
}
//sock->handler.priv = playback;
//sock->handler.cb = storage_playback_http_cb;
vod_session = &playback->vod_session[index];
sock->handler.priv = vod_session;
sock->handler.cb = storage_playback_http_cb;
http_vod_handle(playback, index);
tc->priv = vod_session;
tc->priv_free = (void*)vod_session_stop;
}
#ifdef SDCARD_VIDEO_DOWNLOAD
else if(playback_type == PLAYBACK_TYPE_VIDEO_DOWNLOAD)
{
struct download_session_t *download_session = &media_ctx->download_session;
if (download_session->download_state != VIDEO_DOWNLOAD_NONE)
{
snprintf(error_msg_buf, sizeof(error_msg_buf), "{\"error_code\":%d}", MULTI_VOD_SESSION_BUSY);
tphttp_output_simple(tc, 503, "Service Unavailable", error_msg_buf, false);
return true;
}
if (storage_download_session_init(download_session, sock, dev_id, mac) < 0)
{
tphttp_output_simple(tc, 503, "Service Unavailable", NULL, false);
return true;
}
download_session->playback = playback;
media_ctx->tapo_stream_count += 1;
sock->handler.priv = download_session;
sock->handler.write_buf_max = 4 * 1024 * 1024;
sock->handler.cb = storage_download_request_cb;
http_download_response(download_session);
tc->priv = download_session;
}
#endif
else {
DBG_ERR("dev:[%s] stream type: %s not right or local url Not Matching!%s", type ? type : "NULL", dev_info->dev_mac, sock->parser.http.url);
tpsocket_write_force(sock, tpbuf_http_response(404, "Not Found", 0, false), true);
tpsocket_close(sock);
}
return true;
}
int storage_playback_init(STORAGE_PLAYBACK_ST *playback)
{
int i = 0;
if(!playback){
DBG_ERR("arg NULL\n");
return -1;
}
for(i = 0; i < SESSION_NUM_LIMIT; i++) {
playback->vod_session[i].priv = playback;
playback->vod_session[i].retry_tmo.cb = storage_vod_connect_relay_server;
INIT_LIST_HEAD(&playback->vod_session[i].alt_relay_list);
}
return 0;
}
STORAGE_PLAYBACK_ST *storage_playback_new(void *ctx)
{
if(!ctx){
DBG_ERR("arg NULL\n");
return NULL;
}
STORAGE_PLAYBACK_ST *playback = NULL;
playback = (STORAGE_PLAYBACK_ST *)calloc(1, sizeof(STORAGE_PLAYBACK_ST));
if(!playback){
DBG_ERR("struct STORAGE_PLAYBACK_ST calloc error:%s\n", strerror(errno));
return NULL;
}
playback->topCtx = ctx;
if(storage_playback_init(playback) < 0) {
DBG_ERR("storage_playback_init error\n");
storage_playback_free(playback);
playback = NULL;
}
DBG_DBG("new playback ok\n");
return playback;
}
最新发布