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, &param);
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 }