2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <mv_common.h>
20 #include <mv_surveillance.h>
21 #include "controller.h"
22 #include "controller_mv.h"
25 #define VIDEO_STREAM_ID 0
26 #define THRESHOLD_SIZE_REGION 100
29 mv_surveillance_event_trigger_h mv_trigger_handle;
30 movement_detected_cb movement_detected_cb;
31 void *movement_detected_cb_data;
34 static struct __mv_data *mv_data = NULL;
36 static const char *__mv_err_to_str(mv_error_e err)
40 case MEDIA_VISION_ERROR_NONE:
41 err_str = "MEDIA_VISION_ERROR_NONE";
43 case MEDIA_VISION_ERROR_NOT_SUPPORTED:
44 err_str = "MEDIA_VISION_ERROR_NOT_SUPPORTED";
46 case MEDIA_VISION_ERROR_MSG_TOO_LONG:
47 err_str = "MEDIA_VISION_ERROR_MSG_TOO_LONG";
49 case MEDIA_VISION_ERROR_NO_DATA:
50 err_str = "MEDIA_VISION_ERROR_NO_DATA";
52 case MEDIA_VISION_ERROR_KEY_NOT_AVAILABLE:
53 err_str = "MEDIA_VISION_ERROR_KEY_NOT_AVAILABLE";
55 case MEDIA_VISION_ERROR_OUT_OF_MEMORY:
56 err_str = "MEDIA_VISION_ERROR_OUT_OF_MEMORY";
58 case MEDIA_VISION_ERROR_INVALID_PARAMETER:
59 err_str = "MEDIA_VISION_ERROR_INVALID_PARAMETER";
61 case MEDIA_VISION_ERROR_INVALID_OPERATION:
62 err_str = "MEDIA_VISION_ERROR_INVALID_OPERATION";
64 case MEDIA_VISION_ERROR_PERMISSION_DENIED:
65 err_str = "MEDIA_VISION_ERROR_PERMISSION_DENIED";
67 case MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT:
68 err_str = "MEDIA_VISION_ERROR_NOT_SUPPORTED_FORMAT";
70 case MEDIA_VISION_ERROR_INTERNAL:
71 err_str = "MEDIA_VISION_ERROR_INTERNAL";
73 case MEDIA_VISION_ERROR_INVALID_DATA:
74 err_str = "MEDIA_VISION_ERROR_INVALID_DATA";
76 case MEDIA_VISION_ERROR_INVALID_PATH:
77 err_str = "MEDIA_VISION_ERROR_INVALID_PATH";
80 err_str = "Unknown Error";
87 static void __movement_detected_event_cb(mv_surveillance_event_trigger_h trigger, mv_source_h source, int video_stream_id, mv_surveillance_result_h event_result, void *data)
92 int result[MV_RESULT_LENGTH_MAX] = {0, };
95 int valid_area_sum = 0;
97 size_t move_regions_num = 0;
98 mv_rectangle_s *regions = NULL;
101 ret_if(!event_result);
104 ret = mv_surveillance_get_result_value(event_result, MV_SURVEILLANCE_MOVEMENT_NUMBER_OF_REGIONS, &move_regions_num);
105 retm_if(ret, "failed to mv_surveillance_get_result_value for %s - [%s]", MV_SURVEILLANCE_MOVEMENT_NUMBER_OF_REGIONS, __mv_err_to_str(ret));
107 regions = malloc(sizeof(mv_rectangle_s) * move_regions_num);
108 ret = mv_surveillance_get_result_value(event_result, MV_SURVEILLANCE_MOVEMENT_REGIONS, regions);
109 retm_if(ret, "failed to mv_surveillance_get_result_value for %s - [%s]", MV_SURVEILLANCE_MOVEMENT_REGIONS, __mv_err_to_str(ret));
111 for (i = 0; i < move_regions_num; i++) {
112 // _D("region[%u] - position[%d x %d], witdh[%d], height[%d]", i, regions[i].point.x, regions[i].point.y, regions[i].width, regions[i].height);
113 // _D("region[%u] - area[%d]", i, regions[i].width * regions[i].height);
115 if (regions[i].width * regions[i].height < THRESHOLD_SIZE_REGION || result_count >= MV_RESULT_COUNT_MAX)
118 result[result_index] = regions[i].point.x * 99 / IMAGE_WIDTH;
119 result[result_index + 1] = regions[i].point.y * 99 / IMAGE_HEIGHT;
120 result[result_index + 2] = regions[i].width * 99 / IMAGE_WIDTH;
121 result[result_index + 3] = regions[i].height * 99 / IMAGE_HEIGHT;
124 result_index = result_count * 4;
126 valid_area_sum += regions[i].width * regions[i].height;
129 for (i = 0; i < move_regions_num; i++) {
130 if (regions[i].width * regions[i].height < THRESHOLD_SIZE_REGION)
133 //offset 은 움직임의 중심 좌표가 화면의 중심으로 부터 얼마나 벗어났는지의 값으로 -160 ~ 160, -120 ~ 120 의 값을 갖는다.
134 int x_offset = (regions[i].point.x + regions[i].width / 2) - (IMAGE_WIDTH / 2);
135 int y_offset = (regions[i].point.y + regions[i].height / 2) - (IMAGE_HEIGHT / 2);
136 int area = regions[i].width * regions[i].height;
138 // offset 값에 움직임 크기의 상대값(비율)을 곱한 다음, 모두 더해서 최종 offset 값을 구한다.
139 // 최종값의 범위는 offset 값의 범위와 같아야 한다.
140 horizontal += (int) x_offset * area / valid_area_sum;
141 vertical += (int) y_offset * area / valid_area_sum;
145 mv_data->movement_detected_cb(horizontal, vertical, result, result_count, mv_data->movement_detected_cb_data);
148 void controller_mv_push_source(mv_source_h source)
153 ret = mv_surveillance_push_source(source, VIDEO_STREAM_ID);
155 _E("failed to mv_surveillance_push_source() - [%s]", __mv_err_to_str(ret));
157 mv_destroy_source(source);
160 mv_source_h controller_mv_create_source(
161 unsigned char *buffer, unsigned int size,
162 unsigned int width, unsigned int height, mv_colorspace_e colorspace)
164 mv_source_h source = NULL;
167 retv_if(!buffer, NULL);
169 ret = mv_create_source(&source);
170 retvm_if(ret, NULL, "failed to mv_create_source - [%s]", __mv_err_to_str(ret));
172 ret = mv_source_fill_by_buffer(source, buffer, size, width, height, colorspace);
174 _E("failed to fill source - %d", ret);
177 mv_destroy_source(source);
185 int controller_mv_set_movement_detection_event_cb(movement_detected_cb movement_detected_cb, void *user_data)
188 mv_engine_config_h engine_cfg = NULL;
190 if (movement_detected_cb == NULL)
193 if (mv_data != NULL) {
194 mv_data->movement_detected_cb = movement_detected_cb;
195 mv_data->movement_detected_cb_data = user_data;
199 mv_data = malloc(sizeof(struct __mv_data));
200 if (mv_data == NULL) {
201 _E("Failed to allocate media vision data");
204 memset(mv_data, 0, sizeof(struct __mv_data));
206 ret = mv_create_engine_config(&engine_cfg);
208 _E("failed to subsmv_create_engine_configs() - %s", __mv_err_to_str(ret));
212 mv_engine_config_set_int_attribute(engine_cfg, MV_SURVEILLANCE_MOVEMENT_DETECTION_THRESHOLD, 50); /* 10 is default value [0 ~ 255] */
214 ret = mv_surveillance_event_trigger_create(MV_SURVEILLANCE_EVENT_TYPE_MOVEMENT_DETECTED, &mv_data->mv_trigger_handle);
216 _E("failed to mv_surveillance_event_trigger_create - [%s]", __mv_err_to_str(ret));
220 ret = mv_surveillance_subscribe_event_trigger(mv_data->mv_trigger_handle, VIDEO_STREAM_ID, engine_cfg, __movement_detected_event_cb, mv_data);
223 _E("failed to subscribe %s - %s", MV_SURVEILLANCE_EVENT_TYPE_MOVEMENT_DETECTED, __mv_err_to_str(ret));
228 mv_destroy_engine_config(engine_cfg);
230 mv_data->movement_detected_cb = movement_detected_cb;
231 mv_data->movement_detected_cb_data = user_data;
237 mv_destroy_engine_config(engine_cfg);
239 if (mv_data->mv_trigger_handle)
240 mv_surveillance_event_trigger_destroy(mv_data->mv_trigger_handle);
248 void controller_mv_unset_movement_detection_event_cb(void)
253 if (mv_data->mv_trigger_handle)
254 mv_surveillance_event_trigger_destroy(mv_data->mv_trigger_handle);