Advertisement
Guest User

Untitled

a guest
Jul 19th, 2019
923
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 38.45 KB | None | 0 0
  1. /*
  2. * Copyright (c) 2018 NVIDIA Corporation. All rights reserved.
  3. *
  4. * NVIDIA Corporation and its licensors retain all intellectual property
  5. * and proprietary rights in and to this software, related documentation
  6. * and any modifications thereto. Any use, reproduction, disclosure or
  7. * distribution of this software and related documentation without an express
  8. * license agreement from NVIDIA Corporation is strictly prohibited.
  9. *
  10. */
  11.  
  12. #include <gst/gst.h>
  13. #include <string.h>
  14. #include <math.h>
  15. #include <stdlib.h>
  16.  
  17. #include "deepstream_app.h"
  18.  
  19. //new code
  20. #include "cuda_runtime_api.h"
  21. #include "nvbufsurface.h"
  22. #include <opencv2/imgproc/imgproc.hpp>
  23. #include <opencv2/highgui/highgui.hpp>
  24. #include "gstnvdsmeta.h"
  25.  
  26. #define MAX_DISPLAY_LEN 64
  27. static guint batch_num = 0;
  28. gint frame_number = 0;
  29.  
  30. GST_DEBUG_CATEGORY_EXTERN (NVDS_APP);
  31.  
  32. GQuark _dsmeta_quark;
  33.  
  34. #define CEIL(a,b) ((a + b - 1) / b)
  35. #define SOURCE_RESET_INTERVAL_IN_MS 60000
  36.  
  37. /**
  38. * Function called at regular interval when one of NV_DS_SOURCE_RTSP type
  39. * source in the pipeline is down / disconnected. This function try to
  40. * reconnect the source by resetting that source pipeline.
  41. */
  42.  
  43. static void dump_jpg(char* src_data, int src_width, int src_height, int source_id, NvDsObjectMetaList * obj_meta_list) {
  44. if (TRUE){
  45. char file_name[128];
  46. int obj_id = 0;
  47. // NV12 source data
  48. cv::Mat src_mat(src_height , src_width, CV_8UC4, (void*)src_data);
  49. cv::Mat src_mat_BGRA;
  50. cv::cvtColor(src_mat, src_mat_BGRA, CV_BGRA2RGBA);
  51. NvDsObjectMeta *obj_meta = NULL;
  52. NvDsMetaList *l_obj = NULL;
  53. for (l_obj = obj_meta_list; l_obj != NULL; l_obj = l_obj->next, obj_id++ )
  54. {
  55. obj_meta = (NvDsObjectMeta *) (l_obj->data);
  56.  
  57.  
  58. //printf("%i", src_width);
  59. cv::Mat ROI(src_mat_BGRA, cv::Rect(obj_meta->rect_params.left, obj_meta->rect_params.top, obj_meta->rect_params.width, obj_meta->rect_params.height));
  60.  
  61. cv::Mat croppedImage;
  62.  
  63. // Copy the data into new matrix
  64. ROI.copyTo(croppedImage);
  65. //printf("obj->unique_component_id : %d \n", obj_meta->unique_component_id);
  66. printf("source_id : %d \n", source_id);
  67. //sprintf(file_name, "stream%2d_frame%03d_obj%02d.jpg", source_id, frame_number,obj_id);
  68. //cv::imwrite(file_name, croppedImage);
  69. //printf("%u \n", obj_meta->rect_params.left);
  70. }
  71. }
  72.  
  73.  
  74. }
  75.  
  76. static gboolean
  77. watch_source_status (gpointer data)
  78. {
  79. NvDsSrcBin *src_bin = (NvDsSrcBin *) data;
  80.  
  81. g_print ("watch_source_status %s\n", GST_ELEMENT_NAME(src_bin));
  82. if (src_bin && src_bin->reconfiguring) {
  83. // source is still not up, reconfigure it again.
  84. g_timeout_add (20, reset_source_pipeline, src_bin);
  85. return TRUE;
  86. } else {
  87. // source is reconfigured, remove call back.
  88. return FALSE;
  89. }
  90. }
  91.  
  92. /**
  93. * callback function to receive messages from components
  94. * in the pipeline.
  95. */
  96. static gboolean
  97. bus_callback (GstBus * bus, GstMessage * message, gpointer data)
  98. {
  99. AppCtx *appCtx = (AppCtx *) data;
  100. GST_CAT_DEBUG (NVDS_APP,
  101. "Received message on bus: source %s, msg_type %s",
  102. GST_MESSAGE_SRC_NAME (message), GST_MESSAGE_TYPE_NAME (message));
  103. switch (GST_MESSAGE_TYPE (message)) {
  104. case GST_MESSAGE_INFO:{
  105. GError *error = NULL;
  106. gchar *debuginfo = NULL;
  107. gst_message_parse_info (message, &error, &debuginfo);
  108. g_printerr ("INFO from %s: %s\n",
  109. GST_OBJECT_NAME (message->src), error->message);
  110. if (debuginfo) {
  111. g_printerr ("Debug info: %s\n", debuginfo);
  112. }
  113. g_error_free (error);
  114. g_free (debuginfo);
  115. break;
  116. }
  117. case GST_MESSAGE_WARNING:{
  118. GError *error = NULL;
  119. gchar *debuginfo = NULL;
  120. gst_message_parse_warning (message, &error, &debuginfo);
  121. g_printerr ("WARNING from %s: %s\n",
  122. GST_OBJECT_NAME (message->src), error->message);
  123. if (debuginfo) {
  124. g_printerr ("Debug info: %s\n", debuginfo);
  125. }
  126. g_error_free (error);
  127. g_free (debuginfo);
  128. break;
  129. }
  130. case GST_MESSAGE_ERROR:{
  131. GError *error = NULL;
  132. gchar *debuginfo = NULL;
  133. guint i = 0;
  134. gst_message_parse_error (message, &error, &debuginfo);
  135. g_printerr ("ERROR from %s: %s\n",
  136. GST_OBJECT_NAME (message->src), error->message);
  137. if (debuginfo) {
  138. g_printerr ("Debug info: %s\n", debuginfo);
  139. }
  140.  
  141. NvDsSrcParentBin *bin = &appCtx->pipeline.multi_src_bin;
  142. for (i = 0; i < bin->num_bins; i++) {
  143. if (bin->sub_bins[i].src_elem == (GstElement *) GST_MESSAGE_SRC (message))
  144. break;
  145. }
  146.  
  147. if ((i != bin->num_bins) &&
  148. (appCtx->config.multi_source_config[0].type == NV_DS_SOURCE_RTSP)) {
  149. // Error from one of RTSP source.
  150. NvDsSrcBin *subBin = &bin->sub_bins[i];
  151.  
  152. if (!subBin->reconfiguring ||
  153. g_strrstr(debuginfo, "500 (Internal Server Error)")) {
  154. if (!subBin->reconfiguring) {
  155. // Check status of stream at regular interval.
  156. g_timeout_add (SOURCE_RESET_INTERVAL_IN_MS,
  157. watch_source_status, subBin);
  158. }
  159. // Reconfigure the stream.
  160. subBin->reconfiguring = TRUE;
  161. g_timeout_add (20, reset_source_pipeline, subBin);
  162. }
  163. g_error_free (error);
  164. g_free (debuginfo);
  165. return TRUE;
  166. }
  167.  
  168. g_error_free (error);
  169. g_free (debuginfo);
  170. appCtx->return_value = -1;
  171. appCtx->quit = TRUE;
  172. break;
  173. }
  174. case GST_MESSAGE_STATE_CHANGED:{
  175. GstState oldstate, newstate;
  176. gst_message_parse_state_changed (message, &oldstate, &newstate, NULL);
  177. if (GST_ELEMENT (GST_MESSAGE_SRC (message)) == appCtx->pipeline.pipeline) {
  178. switch (newstate) {
  179. case GST_STATE_PLAYING:
  180. NVGSTDS_INFO_MSG_V ("Pipeline running\n");
  181. GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (appCtx->
  182. pipeline.pipeline), GST_DEBUG_GRAPH_SHOW_ALL,
  183. "ds-app-playing");
  184. break;
  185. case GST_STATE_PAUSED:
  186. if (oldstate == GST_STATE_PLAYING) {
  187. NVGSTDS_INFO_MSG_V ("Pipeline paused\n");
  188. }
  189. break;
  190. case GST_STATE_READY:
  191. GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (appCtx->pipeline.
  192. pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "ds-app-ready");
  193. if (oldstate == GST_STATE_NULL) {
  194. NVGSTDS_INFO_MSG_V ("Pipeline ready\n");
  195. } else {
  196. NVGSTDS_INFO_MSG_V ("Pipeline stopped\n");
  197. }
  198. break;
  199. case GST_STATE_NULL:
  200. g_mutex_lock (&appCtx->app_lock);
  201. g_cond_broadcast (&appCtx->app_cond);
  202. g_mutex_unlock (&appCtx->app_lock);
  203. break;
  204. default:
  205. break;
  206. }
  207. }
  208. break;
  209. }
  210. case GST_MESSAGE_EOS:{
  211. /*
  212. * In normal scenario, this would use g_main_loop_quit() to exit the
  213. * loop and release the resources. Since this application might be
  214. * running multiple pipelines through configuration files, it should wait
  215. * till all pipelines are done.
  216. */
  217. NVGSTDS_INFO_MSG_V ("Received EOS. Exiting ...\n");
  218. appCtx->quit = TRUE;
  219. return FALSE;
  220. break;
  221. }
  222. default:
  223. break;
  224. }
  225. return TRUE;
  226. }
  227.  
  228. static GstBusSyncReply
  229. bus_sync_handler (GstBus * bus, GstMessage * msg, gpointer data)
  230. {
  231. AppCtx *appCtx = (AppCtx *) data;
  232.  
  233. switch (GST_MESSAGE_TYPE (msg)) {
  234. case GST_MESSAGE_ELEMENT:
  235. if (GST_MESSAGE_SRC (msg) == GST_OBJECT (appCtx->pipeline.multi_src_bin.bin)) {
  236. const GstStructure *structure;
  237. structure = gst_message_get_structure (msg);
  238.  
  239. if (gst_structure_has_name (structure, "GstBinForwarded")) {
  240. GstMessage *child_msg;
  241.  
  242. if (gst_structure_has_field (structure, "message")) {
  243. const GValue *val = gst_structure_get_value (structure, "message");
  244. if (G_VALUE_TYPE (val) == GST_TYPE_MESSAGE) {
  245. child_msg = (GstMessage *) g_value_get_boxed (val);
  246. if (GST_MESSAGE_TYPE(child_msg) == GST_MESSAGE_ASYNC_DONE) {
  247. guint i = 0;
  248. NvDsSrcParentBin *bin = &appCtx->pipeline.multi_src_bin;
  249. GST_DEBUG ("num bins: %d, message src: %s\n", bin->num_bins,
  250. GST_MESSAGE_SRC_NAME(child_msg));
  251. for (i = 0; i < bin->num_bins; i++) {
  252. if (bin->sub_bins[i].bin == (GstElement *) GST_MESSAGE_SRC (child_msg))
  253. break;
  254. }
  255.  
  256. if (i != bin->num_bins) {
  257. NvDsSrcBin *subBin = &bin->sub_bins[i];
  258. if (subBin->reconfiguring &&
  259. appCtx->config.multi_source_config[0].type == NV_DS_SOURCE_RTSP)
  260. g_timeout_add (20, set_source_to_playing, subBin);
  261. }
  262. }
  263. }
  264. }
  265. }
  266. }
  267. return GST_BUS_PASS;
  268.  
  269. default:
  270. return GST_BUS_PASS;
  271. }
  272. }
  273.  
  274. /**
  275. * Function to dump bounding box data in kitti format. For this to work,
  276. * property "gie-kitti-output-dir" must be set in configuration file.
  277. * Data of different sources and frames is dumped in separate file.
  278. */
  279. static void
  280. write_kitti_output (AppCtx * appCtx, NvDsBatchMeta * batch_meta)
  281. {
  282. gchar bbox_file[1024] = { 0 };
  283. FILE *bbox_params_dump_file = NULL;
  284.  
  285. if (!appCtx->config.bbox_dir_path)
  286. return;
  287.  
  288. for (NvDsMetaList * l_frame = batch_meta->frame_meta_list; l_frame != NULL;
  289. l_frame = l_frame->next) {
  290. NvDsFrameMeta *frame_meta = (NvDsFrameMeta *) l_frame->data;
  291. guint stream_id = frame_meta->pad_index;
  292. g_snprintf (bbox_file, sizeof (bbox_file) - 1,
  293. "%s/%02u_%03u_%06lu.txt", appCtx->config.bbox_dir_path,
  294. appCtx->index, stream_id, (gulong) frame_meta->frame_num);
  295. bbox_params_dump_file = fopen (bbox_file, "w");
  296. if (!bbox_params_dump_file)
  297. continue;
  298.  
  299. for (NvDsMetaList * l_obj = frame_meta->obj_meta_list; l_obj != NULL;
  300. l_obj = l_obj->next) {
  301. NvDsObjectMeta *obj = (NvDsObjectMeta *) l_obj->data;
  302. int left = obj->rect_params.left;
  303. int top = obj->rect_params.top;
  304. int right = left + obj->rect_params.width;
  305. int bottom = top + obj->rect_params.height;
  306. fprintf (bbox_params_dump_file,
  307. "%s 0.0 0 0.0 %d.00 %d.00 %d.00 %d.00 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n",
  308. obj->obj_label, left, top, right, bottom);
  309. }
  310. fclose (bbox_params_dump_file);
  311. }
  312. }
  313.  
  314. /**
  315. * Function to dump bounding box data in kitti format with tracking ID added.
  316. * For this to work, property "kitti-track-output-dir" must be set in configuration file.
  317. * Data of different sources and frames is dumped in separate file.
  318. */
  319. static void
  320. write_kitti_track_output (AppCtx * appCtx, NvDsBatchMeta * batch_meta)
  321. {
  322. gchar bbox_file[1024] = { 0 };
  323. FILE *bbox_params_dump_file = NULL;
  324.  
  325. if (!appCtx->config.kitti_track_dir_path)
  326. return;
  327.  
  328. for (NvDsMetaList * l_frame = batch_meta->frame_meta_list; l_frame != NULL;
  329. l_frame = l_frame->next) {
  330. NvDsFrameMeta *frame_meta = (NvDsFrameMeta *) l_frame->data;
  331. guint stream_id = frame_meta->pad_index;
  332. g_snprintf (bbox_file, sizeof (bbox_file) - 1,
  333. "%s/%02u_%03u_%06lu.txt", appCtx->config.kitti_track_dir_path,
  334. appCtx->index, stream_id, (gulong) frame_meta->frame_num);
  335. bbox_params_dump_file = fopen (bbox_file, "w");
  336. if (!bbox_params_dump_file)
  337. continue;
  338.  
  339. for (NvDsMetaList * l_obj = frame_meta->obj_meta_list; l_obj != NULL;
  340. l_obj = l_obj->next) {
  341. NvDsObjectMeta *obj = (NvDsObjectMeta *) l_obj->data;
  342. int left = obj->rect_params.left;
  343. int top = obj->rect_params.top;
  344. int right = left + obj->rect_params.width;
  345. int bottom = top + obj->rect_params.height;
  346. guint64 id = obj->object_id;
  347. fprintf (bbox_params_dump_file,
  348. "%s %lu 0.0 0 0.0 %d.00 %d.00 %d.00 %d.00 0.0 0.0 0.0 0.0 0.0 0.0 0.0\n",
  349. obj->obj_label, id, left, top, right, bottom);
  350. }
  351. fclose (bbox_params_dump_file);
  352. }
  353. }
  354.  
  355. static gint
  356. component_id_compare_func (gconstpointer a, gconstpointer b)
  357. {
  358. NvDsClassifierMeta *cmetaa = (NvDsClassifierMeta *) a;
  359. NvDsClassifierMeta *cmetab = (NvDsClassifierMeta *) b;
  360.  
  361. if (cmetaa->unique_component_id < cmetab->unique_component_id)
  362. return -1;
  363. if (cmetaa->unique_component_id > cmetab->unique_component_id)
  364. return 1;
  365. return 0;
  366. }
  367.  
  368. /**
  369. * Function to process the attached metadata. This is just for demonstration
  370. * and can be removed if not required.
  371. * Here it demonstrates to use bounding boxes of different color and size for
  372. * different type / class of objects.
  373. * It also demonstrates how to join the different labels(PGIE + SGIEs)
  374. * of an object to form a single string.
  375. */
  376. static void
  377. process_meta (AppCtx * appCtx, NvDsBatchMeta * batch_meta)
  378. {
  379. // For single source always display text either with demuxer or with tiler
  380. if (!appCtx->config.tiled_display_config.enable ||
  381. appCtx->config.num_source_sub_bins == 1) {
  382. appCtx->show_bbox_text = 1;
  383. }
  384.  
  385. for (NvDsMetaList * l_frame = batch_meta->frame_meta_list; l_frame != NULL;
  386. l_frame = l_frame->next) {
  387. NvDsFrameMeta *frame_meta = (NvDsFrameMeta *) l_frame->data;
  388. for (NvDsMetaList * l_obj = frame_meta->obj_meta_list; l_obj != NULL;
  389. l_obj = l_obj->next) {
  390. NvDsObjectMeta *obj = (NvDsObjectMeta *) l_obj->data;
  391. gint class_index = obj->class_id;
  392. NvDsGieConfig *gie_config = NULL;
  393. gchar *str_ins_pos = NULL;
  394.  
  395. if (obj->unique_component_id ==
  396. (gint) appCtx->config.primary_gie_config.unique_id) {
  397. gie_config = &appCtx->config.primary_gie_config;
  398. } else {
  399. for (gint i = 0; i < (gint) appCtx->config.num_secondary_gie_sub_bins;
  400. i++) {
  401. gie_config = &appCtx->config.secondary_gie_sub_bin_config[i];
  402. if (obj->unique_component_id == (gint) gie_config->unique_id) {
  403. break;
  404. }
  405. gie_config = NULL;
  406. }
  407. }
  408. g_free (obj->text_params.display_text);
  409. obj->text_params.display_text = NULL;
  410.  
  411. if (gie_config != NULL) {
  412. if (g_hash_table_contains (gie_config->bbox_border_color_table,
  413. class_index + (gchar *) NULL)) {
  414. obj->rect_params.border_color =
  415. *((NvOSD_ColorParams *)
  416. g_hash_table_lookup (gie_config->bbox_border_color_table,
  417. class_index + (gchar *) NULL));
  418. } else {
  419. obj->rect_params.border_color = gie_config->bbox_border_color;
  420. }
  421. obj->rect_params.border_width = appCtx->config.osd_config.border_width;
  422.  
  423. if (g_hash_table_contains (gie_config->bbox_bg_color_table,
  424. class_index + (gchar *) NULL)) {
  425. obj->rect_params.has_bg_color = 1;
  426. obj->rect_params.bg_color =
  427. *((NvOSD_ColorParams *)
  428. g_hash_table_lookup (gie_config->bbox_bg_color_table,
  429. class_index + (gchar *) NULL));
  430. } else {
  431. obj->rect_params.has_bg_color = 0;
  432. }
  433. }
  434.  
  435. if (!appCtx->show_bbox_text)
  436. continue;
  437.  
  438. obj->text_params.x_offset = obj->rect_params.left;
  439. obj->text_params.y_offset = obj->rect_params.top - 30;
  440. obj->text_params.font_params.font_color =
  441. appCtx->config.osd_config.text_color;
  442. obj->text_params.font_params.font_size =
  443. appCtx->config.osd_config.text_size;
  444. obj->text_params.font_params.font_name = appCtx->config.osd_config.font;
  445. if (appCtx->config.osd_config.text_has_bg) {
  446. obj->text_params.set_bg_clr = 1;
  447. obj->text_params.text_bg_clr = appCtx->config.osd_config.text_bg_color;
  448. }
  449.  
  450. obj->text_params.display_text = (gchar *) g_malloc (128);
  451. obj->text_params.display_text[0] = '\0';
  452. str_ins_pos = obj->text_params.display_text;
  453.  
  454. if (obj->obj_label[0] != '\0')
  455. sprintf (str_ins_pos, "%s", obj->obj_label);
  456. str_ins_pos += strlen (str_ins_pos);
  457.  
  458. if (obj->object_id != UNTRACKED_OBJECT_ID) {
  459. sprintf (str_ins_pos, " %lu", obj->object_id);
  460. str_ins_pos += strlen (str_ins_pos);
  461. }
  462.  
  463. obj->classifier_meta_list =
  464. g_list_sort (obj->classifier_meta_list, component_id_compare_func);
  465. for (NvDsMetaList * l_class = obj->classifier_meta_list; l_class != NULL;
  466. l_class = l_class->next) {
  467. NvDsClassifierMeta *cmeta = (NvDsClassifierMeta *) l_class->data;
  468. for (NvDsMetaList * l_label = cmeta->label_info_list; l_label != NULL;
  469. l_label = l_label->next) {
  470. NvDsLabelInfo *label = (NvDsLabelInfo *) l_label->data;
  471. if (label->pResult_label) {
  472. sprintf (str_ins_pos, " %s", label->pResult_label);
  473. } else if (label->result_label[0] != '\0') {
  474. sprintf (str_ins_pos, " %s", label->result_label);
  475. }
  476. str_ins_pos += strlen (str_ins_pos);
  477. }
  478.  
  479. }
  480. }
  481. }
  482. }
  483.  
  484. /**
  485. * Function which processes the inferred buffer and its metadata.
  486. * It also gives opportunity to attach application specific
  487. * metadata (e.g. clock, analytics output etc.).
  488. */
  489. static void
  490. process_buffer (GstBuffer * buf, AppCtx * appCtx, guint index)
  491. {
  492. NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta (buf);
  493. if (!batch_meta) {
  494. NVGSTDS_WARN_MSG_V ("Batch meta not found for buffer %p", buf);
  495. return;
  496. }
  497. process_meta (appCtx, batch_meta);
  498. //NvDsInstanceData *data = &appCtx->instance_data[index];
  499. //guint i;
  500.  
  501. // data->frame_num++;
  502.  
  503. /* Opportunity to modify the processed metadata or do analytics based on
  504. * type of object e.g. maintaining count of particular type of car.
  505. */
  506. if (appCtx->all_bbox_generated_cb) {
  507. appCtx->all_bbox_generated_cb (appCtx, buf, batch_meta, index);
  508. }
  509. //data->bbox_list_size = 0;
  510.  
  511. /*
  512. * callback to attach application specific additional metadata.
  513. */
  514. if (appCtx->overlay_graphics_cb) {
  515. appCtx->overlay_graphics_cb (appCtx, buf, batch_meta, index);
  516. }
  517. }
  518.  
  519. /**
  520. * Buffer probe function to get the results of primary infer.
  521. * Here it demonstrates the use by dumping bounding box coordinates in
  522. * kitti format.
  523. */
  524. static GstPadProbeReturn
  525. gie_primary_processing_done_buf_prob (GstPad * pad, GstPadProbeInfo * info,
  526. gpointer u_data)
  527. {
  528. GstBuffer *buf = (GstBuffer *) info->data;
  529. AppCtx *appCtx = (AppCtx *) u_data;
  530. NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta (buf);
  531. if (!batch_meta) {
  532. NVGSTDS_WARN_MSG_V ("Batch meta not found for buffer %p", buf);
  533. return GST_PAD_PROBE_OK;
  534. }
  535.  
  536. write_kitti_output (appCtx, batch_meta);
  537.  
  538. return GST_PAD_PROBE_OK;
  539. }
  540.  
  541. /**
  542. * Probe function to get results after all inferences(Primary + Secondary)
  543. * are done. This will be just before OSD or sink (in case OSD is disabled).
  544. */
  545. static GstPadProbeReturn
  546. gie_processing_done_buf_prob (GstPad * pad, GstPadProbeInfo * info,
  547. gpointer u_data)
  548. {
  549. GstBuffer *buf = (GstBuffer *) info->data;
  550. NvDsInstanceBin *bin = (NvDsInstanceBin *) u_data;
  551. guint index = bin->index;
  552. AppCtx *appCtx = bin->appCtx;
  553.  
  554. if (gst_buffer_is_writable (buf))
  555. process_buffer (buf, appCtx, index);
  556.  
  557. //new code
  558.  
  559. guint num_rects = 0;
  560.  
  561. guint vehicle_count = 0;
  562. guint person_count = 0;
  563. //NvDsMetaList *l_frame = NULL;
  564. NvDsMetaList *l_obj = NULL;
  565. NvDsDisplayMeta *display_meta = NULL;
  566. GstMapInfo in_map_info;
  567. char* src_data = NULL;
  568. int stream_id = 0;
  569.  
  570. NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta (buf);
  571. int max_frames_in_batch = batch_meta->max_frames_in_batch;
  572. //printf("%i", max_frames_in_batch);
  573. if (!gst_buffer_map (buf, &in_map_info, GST_MAP_READ)) {
  574. g_print ("Error: Failed to map gst buffer\n");
  575. gst_buffer_unmap (buf, &in_map_info);
  576. return GST_PAD_PROBE_OK;
  577. }
  578. NvBufSurface *surface = (NvBufSurface *)in_map_info.data;
  579.  
  580. for (NvDsMetaList * l_frame = batch_meta->frame_meta_list; l_frame != NULL; l_frame = l_frame->next) {
  581. NvDsFrameMeta *frame_meta = (NvDsFrameMeta *) (l_frame->data);
  582. guint source_id = frame_meta->source_id;
  583. //stream_id = 1;
  584. printf("source_id: %i , stream_id :%i \n: " ,source_id, stream_id);
  585.  
  586. //printf("l_obj : %d \n:" ,l_obj);
  587. src_data = (char*) malloc(surface->surfaceList[stream_id].dataSize);
  588. cudaMemcpy((void*)src_data,
  589. (void*)surface->surfaceList[stream_id].dataPtr,
  590. surface->surfaceList[stream_id].dataSize,
  591. cudaMemcpyDeviceToHost);
  592.  
  593. dump_jpg(src_data, surface->surfaceList[stream_id].width,
  594. surface->surfaceList[stream_id].height, frame_meta->source_id, frame_meta->obj_meta_list);
  595. stream_id++;
  596. }
  597. frame_number++;
  598. gst_buffer_unmap (buf, &in_map_info);
  599. return GST_PAD_PROBE_OK;
  600. }
  601.  
  602. /**
  603. * Buffer probe function after tracker.
  604. */
  605. static GstPadProbeReturn
  606. tracking_done_buf_prob (GstPad * pad, GstPadProbeInfo * info, gpointer u_data)
  607. {
  608. NvDsInstanceBin *bin = (NvDsInstanceBin *) u_data;
  609. guint index = bin->index;
  610. AppCtx *appCtx = bin->appCtx;
  611. GstBuffer *buf = (GstBuffer *) info->data;
  612. NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta (buf);
  613. if (!batch_meta) {
  614. NVGSTDS_WARN_MSG_V ("Batch meta not found for buffer %p", buf);
  615. return GST_PAD_PROBE_OK;
  616. }
  617.  
  618. /*
  619. * Output KITTI labels with tracking ID if configured to do so.
  620. */
  621. write_kitti_track_output(appCtx, batch_meta);
  622.  
  623. if (appCtx->primary_bbox_generated_cb)
  624. appCtx->primary_bbox_generated_cb (appCtx, buf, batch_meta, index);
  625. return GST_PAD_PROBE_OK;
  626. }
  627.  
  628. static GstPadProbeReturn
  629. latency_measurement_buf_prob(GstPad * pad, GstPadProbeInfo * info, gpointer u_data)
  630. {
  631. AppCtx *appCtx = (AppCtx *) u_data;
  632. guint i = 0, num_sources_in_batch = 0;
  633. if(nvds_enable_latency_measurement)
  634. {
  635. GstBuffer *buf = (GstBuffer *) info->data;
  636. NvDsFrameLatencyInfo *latency_info = NULL;
  637. g_mutex_lock (&appCtx->latency_lock);
  638. latency_info = appCtx->latency_info;
  639. g_print("\n************BATCH-NUM = %d**************\n",batch_num);
  640. num_sources_in_batch = nvds_measure_buffer_latency(buf, latency_info);
  641.  
  642. for(i = 0; i < num_sources_in_batch; i++)
  643. {
  644. g_print("Source id = %d Frame_num = %d Frame latency = %lf (ms) \n",
  645. latency_info[i].source_id,
  646. latency_info[i].frame_num,
  647. latency_info[i].latency);
  648. }
  649. g_mutex_unlock (&appCtx->latency_lock);
  650. batch_num++;
  651. }
  652.  
  653. return GST_PAD_PROBE_OK;
  654. }
  655.  
  656. /**
  657. * Function to add components to pipeline which are dependent on number
  658. * of streams. These components work on single buffer. If tiling is being
  659. * used then single instance will be created otherwise < N > such instances
  660. * will be created for < N > streams
  661. */
  662. static gboolean
  663. create_processing_instance (AppCtx * appCtx, guint index)
  664. {
  665. gboolean ret = FALSE;
  666. NvDsConfig *config = &appCtx->config;
  667. NvDsInstanceBin *instance_bin = &appCtx->pipeline.instance_bins[index];
  668. GstElement *last_elem;
  669. gchar elem_name[32];
  670.  
  671. instance_bin->index = index;
  672. instance_bin->appCtx = appCtx;
  673.  
  674. g_snprintf (elem_name, 32, "processing_bin_%d", index);
  675. instance_bin->bin = gst_bin_new (elem_name);
  676.  
  677. if (!create_sink_bin (config->num_sink_sub_bins,
  678. config->sink_bin_sub_bin_config, &instance_bin->sink_bin, index)) {
  679. goto done;
  680. }
  681.  
  682. gst_bin_add (GST_BIN (instance_bin->bin), instance_bin->sink_bin.bin);
  683. last_elem = instance_bin->sink_bin.bin;
  684.  
  685. if (config->osd_config.enable) {
  686. if (!create_osd_bin (&config->osd_config, &instance_bin->osd_bin)) {
  687. goto done;
  688. }
  689.  
  690. gst_bin_add (GST_BIN (instance_bin->bin), instance_bin->osd_bin.bin);
  691.  
  692. NVGSTDS_LINK_ELEMENT (instance_bin->osd_bin.bin, last_elem);
  693.  
  694. last_elem = instance_bin->osd_bin.bin;
  695. }
  696.  
  697. NVGSTDS_BIN_ADD_GHOST_PAD (instance_bin->bin, last_elem, "sink");
  698. if (config->osd_config.enable) {
  699. NVGSTDS_ELEM_ADD_PROBE (instance_bin->all_bbox_buffer_probe_id,
  700. instance_bin->osd_bin.nvosd, "sink",
  701. gie_processing_done_buf_prob, GST_PAD_PROBE_TYPE_BUFFER, instance_bin);
  702. } else {
  703. NVGSTDS_ELEM_ADD_PROBE (instance_bin->all_bbox_buffer_probe_id,
  704. instance_bin->sink_bin.bin, "sink",
  705. gie_processing_done_buf_prob, GST_PAD_PROBE_TYPE_BUFFER, instance_bin);
  706. }
  707.  
  708. ret = TRUE;
  709. done:
  710. if (!ret) {
  711. NVGSTDS_ERR_MSG_V ("%s failed", __func__);
  712. }
  713. return ret;
  714. }
  715.  
  716. /**
  717. * Function to create common elements(Primary infer, tracker, secondary infer)
  718. * of the pipeline. These components operate on muxed data from all the
  719. * streams. So they are independent of number of streams in the pipeline.
  720. */
  721. static gboolean
  722. create_common_elements (NvDsConfig * config, NvDsPipeline * pipeline,
  723. GstElement ** sink_elem, GstElement ** src_elem,
  724. bbox_generated_callback primary_bbox_generated_cb)
  725. {
  726. gboolean ret = FALSE;
  727. *sink_elem = *src_elem = NULL;
  728. if (config->primary_gie_config.enable) {
  729. if (config->num_secondary_gie_sub_bins > 0) {
  730. if (!create_secondary_gie_bin (config->num_secondary_gie_sub_bins,
  731. config->primary_gie_config.unique_id,
  732. config->secondary_gie_sub_bin_config,
  733. &pipeline->common_elements.secondary_gie_bin)) {
  734. goto done;
  735. }
  736. gst_bin_add (GST_BIN (pipeline->pipeline),
  737. pipeline->common_elements.secondary_gie_bin.bin);
  738. if (!*src_elem) {
  739. *src_elem = pipeline->common_elements.secondary_gie_bin.bin;
  740. }
  741. if (*sink_elem) {
  742. NVGSTDS_LINK_ELEMENT (pipeline->common_elements.secondary_gie_bin.bin,
  743. *sink_elem);
  744. }
  745. *sink_elem = pipeline->common_elements.secondary_gie_bin.bin;
  746. }
  747. }
  748.  
  749. if (config->tracker_config.enable) {
  750. if (!create_tracking_bin (&config->tracker_config,
  751. &pipeline->common_elements.tracker_bin)) {
  752. g_print ("creating tracker bin failed\n");
  753. goto done;
  754. }
  755. gst_bin_add (GST_BIN (pipeline->pipeline),
  756. pipeline->common_elements.tracker_bin.bin);
  757. if (!*src_elem) {
  758. *src_elem = pipeline->common_elements.tracker_bin.bin;
  759. }
  760. if (*sink_elem) {
  761. NVGSTDS_LINK_ELEMENT (pipeline->common_elements.tracker_bin.bin,
  762. *sink_elem);
  763. }
  764. *sink_elem = pipeline->common_elements.tracker_bin.bin;
  765. }
  766.  
  767. if (config->primary_gie_config.enable) {
  768. if (!create_primary_gie_bin (&config->primary_gie_config,
  769. &pipeline->common_elements.primary_gie_bin)) {
  770. goto done;
  771. }
  772. gst_bin_add (GST_BIN (pipeline->pipeline),
  773. pipeline->common_elements.primary_gie_bin.bin);
  774. if (*sink_elem) {
  775. NVGSTDS_LINK_ELEMENT (pipeline->common_elements.primary_gie_bin.bin,
  776. *sink_elem);
  777. }
  778. *sink_elem = pipeline->common_elements.primary_gie_bin.bin;
  779. if (!*src_elem) {
  780. *src_elem = pipeline->common_elements.primary_gie_bin.bin;
  781. }
  782. NVGSTDS_ELEM_ADD_PROBE (pipeline->common_elements.
  783. primary_bbox_buffer_probe_id,
  784. pipeline->common_elements.primary_gie_bin.bin, "src",
  785. gie_primary_processing_done_buf_prob, GST_PAD_PROBE_TYPE_BUFFER,
  786. pipeline->common_elements.appCtx);
  787. }
  788.  
  789. if (config->primary_gie_config.enable) {
  790. if (config->tracker_config.enable) {
  791. NVGSTDS_ELEM_ADD_PROBE (pipeline->common_elements.
  792. primary_bbox_buffer_probe_id,
  793. pipeline->common_elements.tracker_bin.bin, "src",
  794. tracking_done_buf_prob, GST_PAD_PROBE_TYPE_BUFFER,
  795. &pipeline->common_elements);
  796. } else {
  797. NVGSTDS_ELEM_ADD_PROBE (pipeline->common_elements.
  798. primary_bbox_buffer_probe_id,
  799. pipeline->common_elements.primary_gie_bin.bin, "src",
  800. tracking_done_buf_prob, GST_PAD_PROBE_TYPE_BUFFER,
  801. &pipeline->common_elements);
  802. }
  803. }
  804. ret = TRUE;
  805. done:
  806. return ret;
  807. }
  808.  
  809. /**
  810. * Main function to create the pipeline.
  811. */
  812. gboolean
  813. create_pipeline (AppCtx * appCtx,
  814. bbox_generated_callback primary_bbox_generated_cb,
  815. bbox_generated_callback all_bbox_generated_cb, perf_callback perf_cb,
  816. overlay_graphics_callback overlay_graphics_cb)
  817. {
  818. gboolean ret = FALSE;
  819. NvDsPipeline *pipeline = &appCtx->pipeline;
  820. NvDsConfig *config = &appCtx->config;
  821. GstBus *bus;
  822. GstElement *last_elem;
  823. GstElement *tmp_elem1;
  824. GstElement *tmp_elem2;
  825. guint i;
  826. GstPad *fps_pad;
  827. gulong latency_probe_id;
  828.  
  829. _dsmeta_quark = g_quark_from_static_string (NVDS_META_STRING);
  830.  
  831. appCtx->all_bbox_generated_cb = all_bbox_generated_cb;
  832. appCtx->primary_bbox_generated_cb = primary_bbox_generated_cb;
  833. appCtx->overlay_graphics_cb = overlay_graphics_cb;
  834.  
  835. if (config->osd_config.num_out_buffers < 8) {
  836. config->osd_config.num_out_buffers = 8;
  837. }
  838.  
  839. pipeline->pipeline = gst_pipeline_new ("pipeline");
  840. if (!pipeline->pipeline) {
  841. NVGSTDS_ERR_MSG_V ("Failed to create pipeline");
  842. goto done;
  843. }
  844.  
  845. bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline->pipeline));
  846. pipeline->bus_id = gst_bus_add_watch (bus, bus_callback, appCtx);
  847. gst_bus_set_sync_handler (bus, bus_sync_handler, appCtx, NULL);
  848. gst_object_unref (bus);
  849.  
  850. if (config->file_loop) {
  851. /* Let each source bin know it needs to loop. */
  852. guint i;
  853. for (i = 0; i < config->num_source_sub_bins; i++)
  854. config->multi_source_config[i].loop = TRUE;
  855. }
  856.  
  857. for (guint i = 0; i < config->num_sink_sub_bins; i++) {
  858. NvDsSinkSubBinConfig *sink_config = &config->sink_bin_sub_bin_config[i];
  859. switch (sink_config->type) {
  860. case NV_DS_SINK_FAKE:
  861. case NV_DS_SINK_RENDER_EGL:
  862. case NV_DS_SINK_RENDER_OVERLAY:
  863. /* Set the "qos" property of sink, if not explicitly specified in the
  864. config. */
  865. if (!sink_config->render_config.qos_value_specified) {
  866. /* QoS events should be generated by sink always in case of live sources
  867. or with synchronous playback for non-live sources. */
  868. if (config->streammux_config.live_source || sink_config->render_config.sync) {
  869. sink_config->render_config.qos = TRUE;
  870. } else {
  871. sink_config->render_config.qos = FALSE;
  872. }
  873. }
  874. default:
  875. break;
  876. }
  877. }
  878.  
  879. /*
  880. * Add muxer and < N > source components to the pipeline based
  881. * on the settings in configuration file.
  882. */
  883. if (!create_multi_source_bin (config->num_source_sub_bins,
  884. config->multi_source_config, &pipeline->multi_src_bin))
  885. goto done;
  886. gst_bin_add (GST_BIN (pipeline->pipeline), pipeline->multi_src_bin.bin);
  887.  
  888.  
  889. if (config->streammux_config.is_parsed)
  890. set_streammux_properties (&config->streammux_config,
  891. pipeline->multi_src_bin.streammux);
  892.  
  893. if(appCtx->latency_info == NULL)
  894. {
  895. appCtx->latency_info = (NvDsFrameLatencyInfo *)
  896. calloc(1, config->streammux_config.batch_size *
  897. sizeof(NvDsFrameLatencyInfo));
  898. }
  899.  
  900. if (config->tiled_display_config.enable) {
  901.  
  902. /* Tiler will generate a single composited buffer for all sources. So need
  903. * to create only one processing instance. */
  904. if (!create_processing_instance (appCtx, 0)) {
  905. goto done;
  906. }
  907. // create and add tiling component to pipeline.
  908. if (config->tiled_display_config.columns *
  909. config->tiled_display_config.rows < config->num_source_sub_bins) {
  910. if (config->tiled_display_config.columns == 0) {
  911. config->tiled_display_config.columns =
  912. (guint) (sqrt (config->num_source_sub_bins) + 0.5);
  913. }
  914. config->tiled_display_config.rows =
  915. (guint) ceil (1.0 * config->num_source_sub_bins /
  916. config->tiled_display_config.columns);
  917. NVGSTDS_WARN_MSG_V
  918. ("Num of Tiles less than number of sources, readjusting to "
  919. "%u rows, %u columns", config->tiled_display_config.rows,
  920. config->tiled_display_config.columns);
  921. }
  922.  
  923. gst_bin_add (GST_BIN (pipeline->pipeline), pipeline->instance_bins[0].bin);
  924. last_elem = pipeline->instance_bins[0].bin;
  925.  
  926. if (!create_tiled_display_bin (&config->tiled_display_config,
  927. &pipeline->tiled_display_bin)) {
  928. goto done;
  929. }
  930. gst_bin_add (GST_BIN (pipeline->pipeline), pipeline->tiled_display_bin.bin);
  931. NVGSTDS_LINK_ELEMENT (pipeline->tiled_display_bin.bin, last_elem);
  932. last_elem = pipeline->tiled_display_bin.bin;
  933. } else {
  934.  
  935. /*
  936. * Create demuxer only if tiled display is disabled.
  937. */
  938. pipeline->demuxer =
  939. gst_element_factory_make (NVDS_ELEM_STREAM_DEMUX, "demuxer");
  940. if (!pipeline->demuxer) {
  941. NVGSTDS_ERR_MSG_V ("Failed to create element 'demuxer'");
  942. goto done;
  943. }
  944. gst_bin_add (GST_BIN (pipeline->pipeline), pipeline->demuxer);
  945.  
  946. for (i = 0; i < config->num_source_sub_bins; i++) {
  947. gchar pad_name[16];
  948. gboolean create_instance = FALSE;
  949. GstPad *demux_src_pad;
  950. guint j;
  951.  
  952. /* Check if any sink has been configured to render/encode output for
  953. * source index `i`. The processing instance for that source will be
  954. * created only if atleast one sink has been configured as such.
  955. */
  956. for (j = 0; j < config->num_sink_sub_bins; j++) {
  957. if (config->sink_bin_sub_bin_config[j].enable &&
  958. config->sink_bin_sub_bin_config[j].source_id == i) {
  959. create_instance = TRUE;
  960. break;
  961. }
  962. }
  963.  
  964. if (!create_instance)
  965. continue;
  966.  
  967. if (!create_processing_instance (appCtx, i)) {
  968. goto done;
  969. }
  970. gst_bin_add (GST_BIN (pipeline->pipeline),
  971. pipeline->instance_bins[i].bin);
  972.  
  973. g_snprintf (pad_name, 16, "src_%02d", i);
  974. demux_src_pad = gst_element_get_request_pad (pipeline->demuxer, pad_name);
  975. NVGSTDS_LINK_ELEMENT_FULL (pipeline->demuxer, pad_name,
  976. pipeline->instance_bins[i].bin, "sink");
  977. gst_object_unref (demux_src_pad);
  978. }
  979.  
  980. last_elem = pipeline->demuxer;
  981. }
  982. fps_pad = gst_element_get_static_pad (last_elem, "sink");
  983.  
  984. pipeline->common_elements.appCtx = appCtx;
  985. // Decide where in the pipeline the element should be added and add only if
  986. // enabled
  987. if (config->dsexample_config.enable) {
  988. // Create dsexample element bin and set properties
  989. if (!create_dsexample_bin (&config->dsexample_config,
  990. &pipeline->dsexample_bin)) {
  991. goto done;
  992. }
  993. // Add dsexample bin to instance bin
  994. gst_bin_add (GST_BIN (pipeline->pipeline), pipeline->dsexample_bin.bin);
  995.  
  996. // Link this bin to the last element in the bin
  997. NVGSTDS_LINK_ELEMENT (pipeline->dsexample_bin.bin, last_elem);
  998.  
  999. // Set this bin as the last element
  1000. last_elem = pipeline->dsexample_bin.bin;
  1001. }
  1002. // create and add common components to pipeline.
  1003. if (!create_common_elements (config, pipeline, &tmp_elem1, &tmp_elem2,
  1004. primary_bbox_generated_cb)) {
  1005. goto done;
  1006. }
  1007.  
  1008. if (tmp_elem2) {
  1009. NVGSTDS_LINK_ELEMENT (tmp_elem2, last_elem);
  1010. last_elem = tmp_elem1;
  1011. }
  1012.  
  1013. NVGSTDS_LINK_ELEMENT (pipeline->multi_src_bin.bin, last_elem);
  1014.  
  1015. // enable performance measurement and add call back function to receive
  1016. // performance data.
  1017. if (config->enable_perf_measurement) {
  1018. appCtx->perf_struct.context = appCtx;
  1019. enable_perf_measurement (&appCtx->perf_struct, fps_pad,
  1020. pipeline->multi_src_bin.num_bins,
  1021. config->perf_measurement_interval_sec, perf_cb);
  1022. }
  1023. //gst_object_unref (fps_pad);
  1024.  
  1025. NVGSTDS_ELEM_ADD_PROBE (latency_probe_id,
  1026. pipeline->instance_bins->sink_bin.sub_bins[0].sink, "sink",
  1027. latency_measurement_buf_prob, GST_PAD_PROBE_TYPE_BUFFER,
  1028. appCtx);
  1029. latency_probe_id = latency_probe_id;
  1030.  
  1031. GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (appCtx->pipeline.pipeline),
  1032. GST_DEBUG_GRAPH_SHOW_ALL, "ds-app-null");
  1033.  
  1034. g_mutex_init (&appCtx->app_lock);
  1035. g_cond_init (&appCtx->app_cond);
  1036. g_mutex_init (&appCtx->latency_lock);
  1037.  
  1038. ret = TRUE;
  1039. done:
  1040. if (!ret) {
  1041. NVGSTDS_ERR_MSG_V ("%s failed", __func__);
  1042. }
  1043. return ret;
  1044. }
  1045.  
  1046. /**
  1047. * Function to destroy pipeline and release the resources, probes etc.
  1048. */
  1049. void
  1050. destroy_pipeline (AppCtx * appCtx)
  1051. {
  1052. gint64 end_time;
  1053. NvDsConfig *config = &appCtx->config;
  1054. guint i;
  1055. GstBus *bus = NULL;
  1056.  
  1057. end_time = g_get_monotonic_time () + G_TIME_SPAN_SECOND;
  1058.  
  1059. if (!appCtx)
  1060. return;
  1061.  
  1062. if (appCtx->pipeline.demuxer) {
  1063. gst_pad_send_event (gst_element_get_static_pad (appCtx->pipeline.demuxer,
  1064. "sink"), gst_event_new_eos ());
  1065. } else if (appCtx->pipeline.instance_bins[0].sink_bin.bin) {
  1066. gst_pad_send_event (gst_element_get_static_pad (appCtx->
  1067. pipeline.instance_bins[0].sink_bin.bin, "sink"),
  1068. gst_event_new_eos ());
  1069. }
  1070.  
  1071. g_usleep (100000);
  1072.  
  1073. g_mutex_lock (&appCtx->app_lock);
  1074. if (appCtx->pipeline.pipeline) {
  1075. bus = gst_pipeline_get_bus (GST_PIPELINE (appCtx->pipeline.pipeline));
  1076.  
  1077. while (TRUE) {
  1078. GstMessage *message = gst_bus_pop (bus);
  1079. if (message == NULL)
  1080. break;
  1081. else if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR)
  1082. bus_callback (bus, message, appCtx);
  1083. else
  1084. gst_message_unref (message);
  1085. }
  1086. gst_element_set_state (appCtx->pipeline.pipeline, GST_STATE_NULL);
  1087. }
  1088. g_cond_wait_until (&appCtx->app_cond, &appCtx->app_lock, end_time);
  1089. g_mutex_unlock (&appCtx->app_lock);
  1090.  
  1091. for (i = 0; i < appCtx->config.num_source_sub_bins; i++) {
  1092. NvDsInstanceBin *bin = &appCtx->pipeline.instance_bins[i];
  1093. if (config->osd_config.enable) {
  1094. NVGSTDS_ELEM_REMOVE_PROBE (bin->all_bbox_buffer_probe_id,
  1095. bin->osd_bin.nvosd, "sink");
  1096. } else {
  1097. NVGSTDS_ELEM_REMOVE_PROBE (bin->all_bbox_buffer_probe_id,
  1098. bin->sink_bin.bin, "sink");
  1099. }
  1100.  
  1101. if (config->primary_gie_config.enable) {
  1102. NVGSTDS_ELEM_REMOVE_PROBE (bin->primary_bbox_buffer_probe_id,
  1103. bin->primary_gie_bin.bin, "src");
  1104. }
  1105.  
  1106. }
  1107. if(appCtx->latency_info == NULL)
  1108. {
  1109. free(appCtx->latency_info);
  1110. appCtx->latency_info = NULL;
  1111. }
  1112.  
  1113. g_mutex_clear(&appCtx->latency_lock);
  1114.  
  1115. if (appCtx->pipeline.pipeline) {
  1116. bus = gst_pipeline_get_bus (GST_PIPELINE (appCtx->pipeline.pipeline));
  1117. gst_bus_remove_watch (bus);
  1118. gst_object_unref (bus);
  1119. gst_object_unref (appCtx->pipeline.pipeline);
  1120. }
  1121. }
  1122.  
  1123. gboolean
  1124. pause_pipeline (AppCtx * appCtx)
  1125. {
  1126. GstState cur;
  1127. GstState pending;
  1128. GstStateChangeReturn ret;
  1129. GstClockTime timeout = 5 * GST_SECOND / 1000;
  1130.  
  1131. ret =
  1132. gst_element_get_state (appCtx->pipeline.pipeline, &cur, &pending,
  1133. timeout);
  1134.  
  1135. if (ret == GST_STATE_CHANGE_ASYNC) {
  1136. return FALSE;
  1137. }
  1138.  
  1139. if (cur == GST_STATE_PAUSED) {
  1140. return TRUE;
  1141. } else if (cur == GST_STATE_PLAYING) {
  1142. gst_element_set_state (appCtx->pipeline.pipeline, GST_STATE_PAUSED);
  1143. gst_element_get_state (appCtx->pipeline.pipeline, &cur, &pending,
  1144. GST_CLOCK_TIME_NONE);
  1145. pause_perf_measurement (&appCtx->perf_struct);
  1146. return TRUE;
  1147. } else {
  1148. return FALSE;
  1149. }
  1150. }
  1151.  
  1152. gboolean
  1153. resume_pipeline (AppCtx * appCtx)
  1154. {
  1155. GstState cur;
  1156. GstState pending;
  1157. GstStateChangeReturn ret;
  1158. GstClockTime timeout = 5 * GST_SECOND / 1000;
  1159.  
  1160. ret =
  1161. gst_element_get_state (appCtx->pipeline.pipeline, &cur, &pending,
  1162. timeout);
  1163.  
  1164. if (ret == GST_STATE_CHANGE_ASYNC) {
  1165. return FALSE;
  1166. }
  1167.  
  1168. if (cur == GST_STATE_PLAYING) {
  1169. return TRUE;
  1170. } else if (cur == GST_STATE_PAUSED) {
  1171. gst_element_set_state (appCtx->pipeline.pipeline, GST_STATE_PLAYING);
  1172. gst_element_get_state (appCtx->pipeline.pipeline, &cur, &pending,
  1173. GST_CLOCK_TIME_NONE);
  1174. resume_perf_measurement (&appCtx->perf_struct);
  1175. return TRUE;
  1176. } else {
  1177. return FALSE;
  1178. }
  1179. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement