1 #include "ak_rtsp.h"
2
3 #include <fcntl.h>
4 #include <kernel.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <sys/ioctl.h>
8 #include <sys/stat.h>
9 #include <sys/time.h>
10 #include <sys/types.h>
11
12 #include "HaasLog.h"
13 #include "ak_common.h"
14 #include "ak_common_video.h"
15 #include "ak_log.h"
16 #include "ak_mem.h"
17 #include "ak_thread.h"
18 #include "ak_venc.h"
19 #include "ak_vi.h"
20 #include "ak_video.h"
21 #include "ak_vpss.h"
22 #include "camera_ioctl.h"
23 #include "dev_info.h"
24 #include "videocommon.h"
25
26 #define RTSP_STREAM_TASK_STACK_SIZE (32 * 1024)
27
28 #define RTSP_CHAN_NUM_MAX (RTSP_CHUNNEL_1 + 1)
29 #define RTSP_THREAD_PRIORITY (60)
30 #define RTSP_DEFAULT_FPS (25)
31
32 enum PY_RTSP_STATE_T {
33 RTSP_STATE_CLOSE,
34 RTSP_STATE_READY,
35 RTSP_STATE_WORK,
36 };
37
38 struct rtsp_video_thread_attr {
39 ak_pthread_t thread_id;
40 char *thread_name;
41 int vi_channel_id;
42 enum rtsp_chunnel_type rtsp_channel;
43 };
44
45 struct rtsp_ctrl {
46 int fps;
47 int camera_idx;
48 int media_type;
49
50 char *url;
51 char *save_path;
52
53 enum PY_RTSP_STATE_T chan_state[RTSP_CHAN_NUM_MAX];
54 struct rtsp_video_thread_attr *attr;
55 };
56
57 /******************************************************
58 * Global Variables
59 ******************************************************/
60 static struct rtsp_ctrl g_rtsp_ctrl = {
61 .fps = RTSP_DEFAULT_FPS,
62 .camera_idx = -1,
63 .media_type = VIDEO_MEDIA_TYPE_H264,
64 .url = NULL,
65 .save_path = NULL,
66 .attr = NULL,
67 };
68
69 /*
70 * @note: there are two channel concept.
71 * vi-channel refers to video data stream, one vi device has two related
72 * vi-channels. rtsp-channel refers to rtsp send data stream, rtsp module has
73 * two rtsp-channel, they are defined in <enum rtsp_chunnel_type> in "ak_rtsp.h"
74 * since there are two vi devices(sensor), we have 4 vi-channels, 2
75 * rtsp-channel total.
76 *
77 * @rtsp_video_thread: get vi stream and send to rtsp
78 * @param args[in]: rtsp channel which thread will relate to
79 * @return void *
80 */
81
rtsp_video_thread(void * arg)82 static void *rtsp_video_thread(void *arg)
83 {
84 struct rtsp_video_thread_attr *self = (struct rtsp_video_thread_attr *)arg;
85
86 int ret = -1;
87 int venc_handle = -1;
88 enum rtsp_frame_type frame_type;
89 char ifram_force = 1;
90
91 struct video_stream stream = { 0 };
92 unsigned long long gop_size = 0;
93 unsigned max_size = 0;
94 struct ak_timeval pre_tv;
95 struct ak_timeval cur_tv;
96
97 int width = CAMERA_SUB_CHN_DEFAULT_WIDTH;
98 int height = CAMERA_SUB_CHN_DEFAULT_HEIGHT;
99
100 FILE *save_fp = NULL;
101 char save_file[96] = { 0 };
102
103 ak_thread_set_name(self->thread_name);
104
105 if (self->rtsp_channel == RTSP_CHUNNEL_0) {
106 py_video_camera_config_get(&width, &height, NULL);
107 }
108
109 venc_handle =
110 py_venc_init(width, height, g_rtsp_ctrl.fps, g_rtsp_ctrl.media_type);
111 if (venc_handle < 0) {
112 LOG_E("video encode open failed!\n");
113 goto exit_thread;
114 }
115
116 APP_CHN_S Schn, Dchn;
117 Schn.mid = MODULE_ID_VI;
118 Schn.oid = self->vi_channel_id;
119 Dchn.mid = MODULE_ID_VENC;
120 Dchn.oid = self->rtsp_channel;
121 APP_BIND_PARAM param;
122 param.frame_rate = 0;
123 param.frame_depth = 100;
124
125 unsigned long kbps_r = 0;
126 unsigned int count = 0;
127
128 int bind_flag = 0;
129 while (1) {
130 /* iterate main and sub channel, get stream and set to rtsp */
131 while (RTSP_STATE_WORK == g_rtsp_ctrl.chan_state[self->rtsp_channel]) {
132 /* get stream until success */
133 if (ak_rtsp_get_chunnel_state(self->rtsp_channel) == 0) {
134 if (bind_flag == 0) {
135 bind_flag = 1;
136
137 ret = ak_app_video_bind_chn(&Schn, &Dchn, ¶m);
138 if (ret != AK_SUCCESS) {
139 LOG_E("ak_app_video_bind_chn failed [%d]\n", ret);
140 goto exit_venc;
141 }
142
143 ak_get_ostime(&pre_tv);
144 ak_get_ostime(&cur_tv);
145 ak_app_video_set_dst_chn_active(&Dchn, AK_TRUE);
146 }
147
148 if (ifram_force) {
149 ak_venc_request_idr(venc_handle);
150 ifram_force = 0;
151 }
152 } else {
153 ifram_force = 1;
154 if (bind_flag == 1) {
155 if (ak_app_video_venc_get_stream(&Dchn, &stream) == 0) {
156 ak_venc_release_stream(venc_handle, &stream);
157 } else {
158 ak_sleep_ms(10);
159 }
160
161 if (g_rtsp_ctrl.save_path) {
162 if (NULL != save_fp) {
163 fclose(save_fp);
164 save_fp = NULL;
165 count++;
166 }
167 }
168 } else {
169 ak_sleep_ms(200);
170 }
171 continue;
172 }
173
174 if (g_rtsp_ctrl.save_path) {
175 if (NULL == save_fp) {
176 snprintf(save_file, sizeof(save_file), "%s/chn%d_%d.%s",
177 g_rtsp_ctrl.save_path, self->rtsp_channel, count,
178 g_rtsp_ctrl.media_type == VIDEO_MEDIA_TYPE_H264
179 ? "h264"
180 : "hevc");
181 save_fp = fopen(save_file, "w+");
182 if (save_fp == NULL) {
183 LOG_E("fopen %s failed\n", save_file);
184 return NULL;
185 }
186 }
187 }
188
189 memset(&stream, 0, sizeof(struct video_stream));
190 ret = ak_app_video_venc_get_stream(&Dchn, &stream);
191 if (ret == AK_SUCCESS) {
192 /* send stream */
193 if (FRAME_TYPE_I == stream.frame_type) {
194 frame_type = RTSP_IFRAME;
195 } else if (FRAME_TYPE_P == stream.frame_type) {
196 frame_type = RTSP_PFRAME;
197 }
198
199 ret = ak_rtsp_send_stream(self->rtsp_channel, frame_type,
200 stream.data, stream.len, stream.ts);
201 if (ret < 0) {
202 LOG_E("ak_rtsp_send_stream fail %d\n", ret);
203 }
204
205 if (g_rtsp_ctrl.save_path) {
206 if (stream.len > 0) {
207 if (fwrite(stream.data, stream.len, 1, save_fp) <= 0) {
208 LOG_E("fwrite %s failed!\n", save_file);
209 }
210 }
211 }
212 ak_venc_release_stream(venc_handle, &stream);
213 } else {
214 ak_sleep_ms(10);
215 }
216 }
217
218 if (RTSP_STATE_CLOSE == g_rtsp_ctrl.chan_state[self->rtsp_channel]) {
219 ak_app_video_unbind_chn(&Schn, &Dchn);
220 goto exit_venc;
221 }
222
223 ak_sleep_ms(30);
224 }
225
226 exit_venc:
227 ak_venc_close(venc_handle);
228
229 exit_thread:
230 ak_thread_exit();
231 return NULL;
232 }
233
rtsp_create_monitor_thread()234 static int rtsp_create_monitor_thread()
235 {
236 /* start rtsp_control, create two video threads for two RTSP channels */
237 struct rtsp_video_thread_attr *attr;
238
239 if (g_rtsp_ctrl.attr != NULL)
240 return 0;
241
242 attr = (struct rtsp_video_thread_attr *)malloc(
243 sizeof(struct rtsp_video_thread_attr) * RTSP_CHAN_NUM_MAX);
244 if (NULL == attr) {
245 LOG_E("malloc video thread attr failed.\n");
246 return -1;
247 }
248
249 // build main channel thread attribute
250 attr[RTSP_CHUNNEL_0].thread_name = "rtsp_main_video";
251 attr[RTSP_CHUNNEL_0].vi_channel_id = VIDEO_CHN_MAIN;
252 attr[RTSP_CHUNNEL_0].rtsp_channel = RTSP_CHUNNEL_0;
253 g_rtsp_ctrl.chan_state[RTSP_CHUNNEL_0] =
254 RTSP_STATE_WORK; // open audio rtsp main chan(defaut main chan)
255
256 // build sub channel thread attribute
257 attr[RTSP_CHUNNEL_1].thread_name = "rtsp_sub_video";
258 attr[RTSP_CHUNNEL_1].vi_channel_id = VIDEO_CHN_SUB;
259 attr[RTSP_CHUNNEL_1].rtsp_channel = RTSP_CHUNNEL_1;
260 g_rtsp_ctrl.chan_state[RTSP_CHUNNEL_1] =
261 RTSP_STATE_WORK; // open video rtsp sub chan for double chan use
262
263 if (ak_thread_create(&attr[RTSP_CHUNNEL_0].thread_id, rtsp_video_thread,
264 &attr[RTSP_CHUNNEL_0], RTSP_STREAM_TASK_STACK_SIZE,
265 RTSP_THREAD_PRIORITY) != 0) {
266 g_rtsp_ctrl.chan_state[RTSP_CHUNNEL_0] = RTSP_STATE_CLOSE;
267 g_rtsp_ctrl.chan_state[RTSP_CHUNNEL_1] = RTSP_STATE_CLOSE;
268 free(attr);
269 LOG_E("create client_listen main_chan thread error.\r\n");
270 return -1;
271 }
272
273 /* start sub video */
274 if (ak_thread_create(&attr[RTSP_CHUNNEL_1].thread_id, rtsp_video_thread,
275 &attr[RTSP_CHUNNEL_1], RTSP_STREAM_TASK_STACK_SIZE,
276 RTSP_THREAD_PRIORITY) != 0) {
277 g_rtsp_ctrl.chan_state[RTSP_CHUNNEL_0] = RTSP_STATE_CLOSE;
278 g_rtsp_ctrl.chan_state[RTSP_CHUNNEL_1] = RTSP_STATE_CLOSE;
279 ak_thread_join(attr[RTSP_CHUNNEL_0].thread_id);
280 free(attr);
281 LOG_E("create client_listen sub_chan thread error.\r\n");
282 return -1;
283 }
284
285 g_rtsp_ctrl.attr = attr;
286
287 return 0;
288 }
289
py_rtsp_start(void)290 int py_rtsp_start(void)
291 {
292 char path[32];
293
294 if (RTSP_STATE_CLOSE == g_rtsp_ctrl.chan_state[0]) {
295 /* init rtsp */
296 if (ak_rtsp_init() != 0) {
297 LOG_E("init rtsp failed\n");
298 return -1;
299 }
300
301 /* init rtsp channel name,default name is camera-x,x: 1,2*/
302 if (g_rtsp_ctrl.url == NULL) {
303 strncpy(path, "main", sizeof(path));
304 } else {
305 snprintf(path, sizeof(path), "main/%s", g_rtsp_ctrl.url);
306 }
307 if (ak_rtsp_set_chunnel_name(RTSP_CHUNNEL_0, path) != 0) {
308 LOG_E("rtsp set chan_main name error\n");
309 ak_rtsp_deinit();
310 return -1;
311 }
312
313 if (g_rtsp_ctrl.url == NULL) {
314 strncpy(path, "sub", sizeof(path));
315 } else {
316 snprintf(path, sizeof(path), "sub/%s", g_rtsp_ctrl.url);
317 }
318 if (ak_rtsp_set_chunnel_name(RTSP_CHUNNEL_1, path) != 0) {
319 LOG_E("rtsp set chan_sub name error\n");
320 ak_rtsp_deinit();
321 return -1;
322 }
323
324 /* set rtsp video type */
325 enum rtsp_video_type rtsp_enc_type;
326 if (g_rtsp_ctrl.media_type == VIDEO_MEDIA_TYPE_HEVC) {
327 rtsp_enc_type = RTSP_VIDEO_H265;
328 } else {
329 rtsp_enc_type = RTSP_VIDEO_H264;
330 }
331
332 // for single steam, set both of channel rtsp type
333 ak_rtsp_set_video_type(RTSP_CHUNNEL_0, rtsp_enc_type);
334 ak_rtsp_set_video_type(RTSP_CHUNNEL_1, rtsp_enc_type);
335
336 /* start rtsp service */
337 ak_rtsp_start();
338
339 if (rtsp_create_monitor_thread() < 0) {
340 LOG_E("create rtsp main thread error\r\n");
341 ak_rtsp_stop();
342 ak_rtsp_deinit();
343 return -1;
344 }
345 } else {
346 LOG_W("rtsp state is not closed, can't be started!\n");
347 }
348 return 0;
349 }
350
py_rtsp_open(int camera_idx,int media_type,int fps,const char * url)351 int py_rtsp_open(int camera_idx, int media_type, int fps, const char *url)
352 {
353 if (g_rtsp_ctrl.camera_idx >= 0) {
354 py_rtsp_close();
355 }
356
357 if (g_rtsp_ctrl.camera_idx < 0) {
358 if (url && strlen(url) > 0) {
359 g_rtsp_ctrl.url = strdup(url);
360 if (g_rtsp_ctrl.url == NULL) {
361 LOG_E("rtsp alloc url fail\n");
362 return -1;
363 }
364 }
365
366 py_video_camera_config_set(0, 0, VIDEO_MEDIA_TYPE_H264);
367 if (py_video_camera_open(camera_idx, fps) != 0) {
368 LOG_E("vi dev[%d] init fail\n", camera_idx);
369 if (g_rtsp_ctrl.url) {
370 free(g_rtsp_ctrl.url);
371 g_rtsp_ctrl.url = NULL;
372 }
373 return -1;
374 }
375 g_rtsp_ctrl.camera_idx = camera_idx;
376 g_rtsp_ctrl.fps = fps;
377 g_rtsp_ctrl.media_type = media_type;
378 }
379 return 0;
380 }
381
py_rtsp_stop(void)382 int py_rtsp_stop(void)
383 {
384 if (RTSP_STATE_CLOSE != g_rtsp_ctrl.chan_state[0]) {
385 g_rtsp_ctrl.chan_state[0] = RTSP_STATE_CLOSE;
386 g_rtsp_ctrl.chan_state[1] = RTSP_STATE_CLOSE;
387 }
388
389 if (g_rtsp_ctrl.attr != NULL) {
390 ak_thread_join(g_rtsp_ctrl.attr[RTSP_CHUNNEL_0].thread_id);
391 ak_thread_join(g_rtsp_ctrl.attr[RTSP_CHUNNEL_1].thread_id);
392 ak_rtsp_stop();
393 free(g_rtsp_ctrl.attr);
394 g_rtsp_ctrl.attr = NULL;
395 }
396
397 return 0;
398 }
399
py_rtsp_close(void)400 int py_rtsp_close(void)
401 {
402 py_rtsp_stop();
403
404 py_video_camera_close(g_rtsp_ctrl.camera_idx);
405
406 if (g_rtsp_ctrl.url) {
407 free(g_rtsp_ctrl.url);
408 g_rtsp_ctrl.url = NULL;
409 }
410 if (g_rtsp_ctrl.save_path) {
411 free(g_rtsp_ctrl.save_path);
412 g_rtsp_ctrl.save_path = NULL;
413 }
414 }
415
py_rtsp_resume(void)416 int py_rtsp_resume(void)
417 {
418 if (RTSP_STATE_READY == g_rtsp_ctrl.chan_state[0]) {
419 g_rtsp_ctrl.chan_state[0] = RTSP_STATE_WORK;
420 g_rtsp_ctrl.chan_state[1] = RTSP_STATE_WORK;
421 } else {
422 LOG_W("rtsp state is not ready, can't be resumed!\n");
423 }
424 return 0;
425 }
426
py_rtsp_pause(void)427 int py_rtsp_pause(void)
428 {
429 if (RTSP_STATE_WORK == g_rtsp_ctrl.chan_state[0]) {
430 g_rtsp_ctrl.chan_state[0] = RTSP_STATE_READY;
431 g_rtsp_ctrl.chan_state[1] = RTSP_STATE_READY;
432 } else {
433 LOG_W("rtsp state is not work, can't be paused!\n");
434 }
435 return 0;
436 }