Advertisement
Guest User

Untitled

a guest
Apr 30th, 2014
379
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.30 KB | None | 0 0
  1. Code:
  2.  
  3. #include <gst/gst.h>
  4. #include <gst/rtsp-server/rtsp-server.h>
  5.  
  6. #include <math.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <mysql.h>
  10. #include <string.h>
  11. #include <time.h>
  12.  
  13. #include <signal.h>
  14.  
  15. int do_exit = FALSE;
  16. void send_eos(int);
  17.  
  18. /* Structure to contain all our information, so we can pass it to callbacks */
  19. typedef struct _CustomData {
  20. GstElement *pipeline;
  21. GstElement *source;
  22. GstElement *tee;
  23. GstElement *decodebin;
  24. GstElement *convert1;
  25. GstElement *deinterlacer;
  26. GstElement *queue;
  27. GstElement *facedetector;
  28. GstElement *faceblur;
  29. GstElement *motiondetect;
  30. GstElement *convert2;
  31. GstElement *scaler;
  32. GstElement *balancer;
  33. GstElement *videorater;
  34. GstElement *convert3;
  35. GstElement *convert4;
  36. GstElement *capsfilter;
  37. GstElement *videoencoder;
  38. GstElement *capsfilter2;
  39. GstElement *rtpencoder;
  40. GstElement *capsfilter3;
  41. GstElement *capsfilter4;
  42. GstElement *sink;
  43. GstElement *timeoverlay;
  44.  
  45. //subpipe 2
  46. GstElement *origrtpdecoder;
  47. GstElement *origrtpencoder;
  48. GstElement *origsink;
  49. } CustomData;
  50.  
  51. /* Handler for the pad-added signal */
  52. static void pad_added_handler (GstElement *src, GstPad *pad, CustomData *data);
  53.  
  54. static void feature_detect_handler(GstElement *e, time_t *t, CustomData *data);
  55. static void motion_start_handler(GstElement *e, time_t *t, CustomData *data);
  56. static void motion_stop_handler(GstElement *e, time_t *t, CustomData *data);
  57.  
  58. /* rtsp server thread */
  59. void *start_rtsp_stream(void *param);
  60.  
  61. CustomData data;
  62. MYSQL *MySQLConRet =NULL, *MySQLConn = NULL;
  63.  
  64. gint orig_video_width=0, orig_video_height=0;
  65.  
  66. const char *hostname = "localhost",
  67. *user = "root",
  68. *pass = "root",
  69. *dbname = "lensbrick";
  70.  
  71. int main(int argc, char *argv[]) {
  72. GstBus *bus = NULL;
  73. GstMessage *msg;
  74. GstStateChangeReturn ret;
  75. gboolean terminate = FALSE;
  76. gboolean add_timestamp = FALSE;
  77.  
  78. time_t time_diff;
  79. time_t pipeline_retries[5] = {0,0,0,0,0};
  80. int next_slot = 0, most_recent_slot = -1;
  81.  
  82. /* Initialize GStreamer */
  83. gst_init (&argc, &argv);
  84.  
  85. if(argc>1 && ( strncmp("-h",argv[1],3) == 0 || strncmp("--help",argv[1],7) == 0 ) ) {
  86. g_print("Usage: rtsp-server <rtsp-feed-url> [add_time] [roi of motion detect]");
  87. exit(0);
  88. }
  89.  
  90. if(argc > 2) {
  91. add_timestamp = strncmp("add_time", argv[2], 9);
  92. }
  93.  
  94. MySQLConn = mysql_init(NULL);
  95. MySQLConRet = mysql_real_connect(MySQLConn,
  96. hostname,
  97. user,
  98. pass,
  99. dbname,
  100. 0,
  101. NULL,
  102. 0);
  103.  
  104. if(MySQLConRet == NULL) {
  105. g_print("Mysql Error: %s\n",mysql_error(MySQLConn));
  106. }
  107.  
  108. //todo: Create multiple threads - one for multiple pipeline maintenance, and
  109. //1 for rtsp streaming server and 1 for reload cmd handling
  110.  
  111. /* Create the elements */
  112. data.source = gst_element_factory_make ("rtspsrc", "source");
  113. data.tee = gst_element_factory_make ("tee", "tee");
  114. data.decodebin = gst_element_factory_make ("decodebin", "decodebin");
  115. data.convert1 = gst_element_factory_make ("videoconvert", "convert1");
  116. data.deinterlacer = gst_element_factory_make ("deinterlace", "deinterlacer");
  117. data.queue = gst_element_factory_make ("queue2", "queue");
  118. data.facedetector = gst_element_factory_make ("facedetect", "facedetector");
  119. data.faceblur = gst_element_factory_make ("faceblur", "faceblur");
  120. data.motiondetect = gst_element_factory_make ("motiondetect", "motiondetect");
  121. data.convert2 = gst_element_factory_make ("videoconvert", "convert2");
  122. data.scaler = gst_element_factory_make ("videoscale", "scaler");
  123. data.balancer = gst_element_factory_make ("videobalance", "balancer");
  124. data.videorater = gst_element_factory_make ("videorate", "videorater");
  125. data.convert3 = gst_element_factory_make ("videoconvert", "convert3");
  126. data.capsfilter = gst_element_factory_make ("capsfilter", "capsfilter");
  127. data.videoencoder = gst_element_factory_make ("x264enc", "videoencoder");
  128. data.rtpencoder = gst_element_factory_make ("rtph264pay", "rtpencoder");
  129. data.capsfilter2 = gst_element_factory_make ("capsfilter", "capsfilter2");
  130. data.capsfilter3 = gst_element_factory_make ("capsfilter", "capsfilter3");
  131. data.capsfilter4 = gst_element_factory_make ("capsfilter", "capsfilter4");
  132. data.convert4 = gst_element_factory_make ("videoconvert", "convert4");
  133. data.sink = gst_element_factory_make ("udpsink", "processed_sink");
  134. data.origsink = gst_element_factory_make ("udpsink", "original_sink");
  135. data.origrtpdecoder = gst_element_factory_make ("rtph264depay", "orig_rtpdecoder");
  136. data.origrtpencoder = gst_element_factory_make ("rtph264pay", "orig_rtpencoder");
  137. data.timeoverlay = gst_element_factory_make ("clockoverlay", "timer");
  138. //data.sink = gst_element_factory_make ("xvimagesink", "sink");
  139.  
  140. /* Create the empty pipeline */
  141. data.pipeline = gst_pipeline_new ("process-pipeline");
  142.  
  143. if (!data.pipeline || !data.source || !data.capsfilter ||
  144. !data.decodebin || !data.convert1 || !data.deinterlacer
  145. || !data.queue || !data.facedetector
  146. || !data.convert2 || !data.capsfilter3
  147. || !data.scaler || !data.balancer || !data.timeoverlay
  148. || !data.videorater || !data.convert3 || !data.tee || !data.origsink
  149. || !data.faceblur || !data.convert4 || !data.capsfilter4 || !data.motiondetect
  150. || !data.videoencoder || !data.rtpencoder || !data.capsfilter2
  151. || !data.sink || !data.origrtpdecoder || !data.origrtpencoder) {
  152. g_printerr ("Not all elements could be created.\n");
  153. return -1;
  154. }
  155.  
  156. /*Set time overlay text props*/
  157. g_object_set (G_OBJECT(data.timeoverlay), "font-desc", "Arial bold 35",
  158. "time-format", "%d-%m-%Y %H:%M:%S", NULL);
  159.  
  160. /*Set queue props*/
  161. g_object_set (G_OBJECT(data.queue), "max-size-buffers", 3, NULL);
  162.  
  163. /*Set face detector profile*/
  164. g_object_set (G_OBJECT(data.facedetector), "profile", "/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml", "updates", 1, NULL);
  165.  
  166. /*Set face detector profile*/
  167. g_object_set (G_OBJECT(data.faceblur), "profile", "/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml", NULL);
  168.  
  169. /*Set motion detector ROI*/
  170. g_object_set (G_OBJECT(data.motiondetect), "roi", (argc>3?argv[3]:""), "silent", TRUE, NULL);
  171.  
  172. /*Set udp port sink for original video*/
  173. g_object_set (G_OBJECT(data.origsink), "port", 5001, NULL);
  174.  
  175. /*Set udp port sink*/
  176. g_object_set (G_OBJECT(data.sink), "port", 5000, NULL);
  177.  
  178. /*Set rtpencoder config-interval*/
  179. g_object_set (G_OBJECT(data.origrtpencoder), "config-interval", 1, NULL);
  180.  
  181. /* Set the capsfilter property */
  182.  
  183. g_object_set (G_OBJECT(data.capsfilter2), "caps", gst_caps_new_simple("video/x-raw",
  184. "framerate",GST_TYPE_FRACTION,8,1,
  185. //"clock-rate",G_TYPE_INT, 90000,
  186. NULL), NULL );
  187. g_object_set (G_OBJECT(data.capsfilter3), "caps", gst_caps_new_simple("video/x-raw",
  188. "format",G_TYPE_STRING,"RGB",
  189. NULL), NULL );
  190. g_object_set (G_OBJECT(data.capsfilter4), "caps", gst_caps_new_simple("video/x-raw",
  191. "format",G_TYPE_STRING,"I420",
  192. NULL), NULL );
  193.  
  194. /* Build the pipeline. Note that we are NOT linking the source at this
  195. * point. We will do it later. */
  196. gst_bin_add_many (GST_BIN (data.pipeline), data.source, data.capsfilter ,
  197. data.decodebin , data.convert1 , data.deinterlacer, data.timeoverlay,
  198. data.queue, data.facedetector, data.convert2, data.capsfilter2,
  199. data.capsfilter3, data.faceblur, data.convert4, data.capsfilter4,
  200. data.motiondetect, data.tee, data.scaler, data.balancer,
  201. data.videorater, data.convert3, data.videoencoder, data.rtpencoder,
  202. data.sink, NULL);
  203. if (!gst_element_link_many (
  204. data.convert1,
  205. data.deinterlacer,
  206. data.queue,
  207. data.convert2,
  208. data.scaler,
  209. data.capsfilter,
  210. data.balancer,
  211. data.videorater,
  212. data.capsfilter2,
  213. data.convert3,
  214. data.capsfilter3,
  215. //data.facedetector,
  216. //data.faceblur,
  217. data.motiondetect,
  218. data.timeoverlay,
  219. data.convert4,
  220. data.capsfilter4,
  221. data.videoencoder,
  222. data.rtpencoder,
  223. data.sink,
  224. NULL )) {
  225. g_printerr ("Elements could not be linked.\n");
  226. gst_object_unref (data.pipeline);
  227. return -1;
  228. }
  229.  
  230. /* Set the URI to play */
  231. g_object_set (data.source, "location", argv[1], NULL);
  232.  
  233. /* Connect to the pad-added signal */
  234. g_signal_connect (data.source, "pad-added", G_CALLBACK (pad_added_handler), &data);
  235. g_signal_connect (data.decodebin, "pad-added", G_CALLBACK (pad_added_handler), &data);
  236. g_signal_connect (data.motiondetect, "motion-start", G_CALLBACK (motion_start_handler), &data);
  237. g_signal_connect (data.motiondetect, "motion-stop", G_CALLBACK (motion_stop_handler), &data);
  238.  
  239. restart_pipeline:
  240.  
  241. pipeline_retries[next_slot] = time(NULL);
  242. g_print("Attempt/Retry %d at %ld\n", (next_slot+1), pipeline_retries[next_slot]);
  243. next_slot = (next_slot+1) % 5;
  244. terminate = FALSE;
  245.  
  246. /* Start playing */
  247. ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING);
  248. if (ret == GST_STATE_CHANGE_FAILURE) {
  249. g_printerr ("Unable to set the pipeline to the playing state.\n");
  250. gst_object_unref (data.pipeline);
  251. return -1;
  252. }
  253.  
  254. g_print("Return value of setting pipeline to playing state = %d\n", ret);
  255.  
  256. signal(SIGINT,send_eos);
  257.  
  258. /* Listen to the bus */
  259. if(!bus) {
  260. bus = gst_element_get_bus (data.pipeline);
  261. }
  262.  
  263. do {
  264. msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
  265. GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
  266. //g_print("Msg received, %p\n", msg);
  267.  
  268. /* Parse message */
  269. if (msg != NULL) {
  270. GError *err;
  271. gchar *debug_info;
  272.  
  273. switch (GST_MESSAGE_TYPE (msg)) {
  274. case GST_MESSAGE_ERROR:
  275. gst_message_parse_error (msg, &err, &debug_info);
  276. g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);
  277. g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
  278. g_clear_error (&err);
  279. g_free (debug_info);
  280. terminate = TRUE;
  281. break;
  282. case GST_MESSAGE_EOS:
  283. g_print ("End-Of-Stream reached.\n");
  284. terminate = TRUE;
  285. break;
  286. case GST_MESSAGE_STATE_CHANGED:
  287. /* We are only interested in state-changed messages from the pipeline */
  288. if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data.pipeline)) {
  289. GstState old_state, new_state, pending_state;
  290. gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
  291. g_print ("Pipeline state changed from %s to %s:\n",
  292. gst_element_state_get_name (old_state), gst_element_state_get_name (new_state));
  293.  
  294. g_print("\nSink Caps is %s\n",
  295. gst_caps_to_string(gst_pad_get_current_caps(gst_element_get_static_pad(data.sink,"sink"))));
  296. g_print("\nOriginal video Sink Caps is %s\n",
  297. gst_caps_to_string(gst_pad_get_current_caps(gst_element_get_static_pad(data.origsink,"sink"))));
  298. }
  299. break;
  300. default:
  301. /* We should not reach here */
  302. g_printerr ("Unexpected message received.\n");
  303. break;
  304. }
  305. gst_message_unref (msg);
  306. }
  307. } while (!terminate);
  308.  
  309. //todo: check if it is a transient error - if not, then should exit
  310.  
  311. //if transient error
  312. gst_element_set_state (data.pipeline, GST_STATE_NULL);
  313. if(do_exit) {
  314. goto terminate_process;
  315. }
  316.  
  317. //check if number of retries exceeded 5 within 90 seconds
  318. //todo: make retry limit of 5, sleep of 10 seconds for next retry
  319. // and time limit of 90 seconds configurable
  320. if(pipeline_retries[next_slot] != 0 ) {
  321. //non-zero next slot means we have done >=5 retries
  322. most_recent_slot = next_slot - 1;
  323. if(most_recent_slot == -1) {
  324. most_recent_slot = 4;
  325. }
  326.  
  327. //oldest slot = next_slot, so do most_recent_slot - next_slot
  328. g_print("most recent_attempt %d = %ld\n",most_recent_slot,pipeline_retries[most_recent_slot]);
  329. g_print("old attempt %d = %ld\n",next_slot,pipeline_retries[next_slot]);
  330. time_diff = time(NULL) - pipeline_retries[next_slot];
  331. if(time_diff < 60) {
  332. //within a span of 60 seconds, 5 retries have happened
  333. g_print("Terminating process\n");
  334. goto terminate_process;
  335. }
  336. }
  337.  
  338. g_print("Pipeline set to NULL state and sleeping for 10 seconds\n");
  339. sleep(10); //todo: to be made configurable
  340. g_print("Pipeline restarting\n");
  341. goto restart_pipeline;
  342.  
  343. terminate_process:
  344.  
  345. /* Free resources */
  346. gst_object_unref (bus);
  347. //gst_element_set_state (data.pipeline, GST_STATE_NULL);
  348. gst_object_unref (data.pipeline);
  349. mysql_close(MySQLConn);
  350. return 0;
  351. }
  352.  
  353. /* This function will be called by the pad-added signal */
  354. static void pad_added_handler (GstElement *src, GstPad *new_pad, CustomData *data) {
  355.  
  356. GstPad *sink_pad = NULL;
  357. GstPadLinkReturn ret;
  358. GstCaps *new_pad_caps = NULL;
  359. GstStructure *new_pad_struct = NULL;
  360. const gchar *new_pad_type = NULL,
  361. *new_pad_media = NULL,
  362. *new_pad_encoding = NULL;
  363. pthread_t thread_id;
  364. int thread_status;
  365.  
  366. if(src == data->source) {
  367.  
  368. sink_pad = gst_element_get_static_pad (data->tee, "sink");
  369. g_print ("Received new pad '%s' from '%s':\n",
  370. GST_PAD_NAME (new_pad), GST_ELEMENT_NAME (src));
  371.  
  372. /* If our converter is already linked, we have nothing to do here */
  373. if (gst_pad_is_linked (sink_pad)) {
  374. g_print (" We are already linked. Ignoring.\n");
  375. goto exit;
  376. }
  377.  
  378. /* Check the new pad's type */
  379. new_pad_caps = gst_pad_query_caps (new_pad,NULL);
  380. new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);
  381. new_pad_type = gst_structure_get_name (new_pad_struct);
  382. new_pad_media = gst_structure_get_string(new_pad_struct,"media");
  383. new_pad_encoding = gst_structure_get_string(new_pad_struct,"encoding-name");
  384.  
  385. g_print(" Caps is = '%s'",gst_caps_to_string(new_pad_caps));
  386.  
  387. if (!g_str_has_prefix (new_pad_type, "application/x-rtp")
  388. || !g_str_has_prefix (new_pad_media, "video")) {
  389. g_print (" It has type '%s' which is not video RTP. Ignoring.\n", new_pad_type);
  390. goto exit;
  391. }
  392.  
  393. /* Attempt the link */
  394. ret = gst_pad_link (new_pad, sink_pad);
  395. if (GST_PAD_LINK_FAILED (ret)) {
  396. g_print (" Type is '%s' but link failed.\n", new_pad_type);
  397. //todo: properly exit instead of calling exit fn abruptly
  398. exit(-1);
  399. } else {
  400. g_print (" Link succeeded (type '%s').\n", new_pad_type);
  401. }
  402.  
  403. if(!gst_element_link(data->tee, data->decodebin)) {
  404. g_print("Linking processing branch pipe to tee failed\n");
  405. //todo: properly exit instead of calling exit fn abruptly
  406. exit(-1);
  407. }
  408.  
  409. gst_element_set_state( data->origrtpdecoder, GST_STATE_PAUSED );
  410. gst_element_set_state( data->origrtpencoder, GST_STATE_PAUSED );
  411. gst_element_set_state( data->origsink, GST_STATE_PAUSED );
  412.  
  413. gst_bin_add_many(GST_BIN(data->pipeline), data->origrtpencoder, data->origrtpdecoder, data->origsink, NULL);
  414. if(!gst_element_link_many(data->tee, data->origrtpdecoder, data->origrtpencoder, data->origsink, NULL)) {
  415. g_print("Setting subpipe to stream original video failed. Couldnt link all elements in pipe\n");
  416. //todo: properly exit instead of calling exit fn abruptly
  417. exit(-1);
  418. }
  419.  
  420. gst_element_set_state( data->origrtpdecoder, GST_STATE_PLAYING );
  421. gst_element_set_state( data->origrtpencoder, GST_STATE_PLAYING );
  422. gst_element_set_state( data->origsink, GST_STATE_PLAYING );
  423.  
  424. } else if( src == data->decodebin) {
  425.  
  426. sink_pad = gst_element_get_static_pad (data->convert1, "sink");
  427.  
  428. g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (new_pad), GST_ELEMENT_NAME (src));
  429.  
  430. /* If our converter is already linked, we have nothing to do here */
  431. if (gst_pad_is_linked (sink_pad)) {
  432. g_print (" We are already linked. Ignoring.\n");
  433. goto exit;
  434. }
  435.  
  436. new_pad_caps = gst_pad_query_caps (new_pad,NULL);
  437. new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);
  438. gst_structure_get_int(new_pad_struct,"width", &orig_video_width);
  439. gst_structure_get_int(new_pad_struct,"height", &orig_video_height);
  440. g_print("%d = width, %d = height\n", orig_video_width, orig_video_height);
  441.  
  442. g_print(" Caps is = '%s'",gst_caps_to_string(new_pad_caps));
  443.  
  444. /* Set the capsfilter property */
  445. if(orig_video_height > 400 && orig_video_width > 400) {
  446.  
  447. g_object_set (G_OBJECT(data->capsfilter), "caps", gst_caps_new_simple("video/x-raw",
  448. "width",G_TYPE_INT,orig_video_width/4,
  449. "height",G_TYPE_INT,orig_video_height/4,
  450. NULL), NULL );
  451. g_print("scaled: %d = width, %d = height\n", orig_video_width/4, orig_video_height/4);
  452. }
  453.  
  454. /* Attempt the link */
  455. ret = gst_pad_link (new_pad, sink_pad);
  456. if (GST_PAD_LINK_FAILED (ret)) {
  457. g_print (" link failed.\n");
  458. //todo: properly exit instead of abrupt exit
  459. exit(-1);
  460. } else {
  461. g_print (" Link succeeded .\n");
  462. thread_status = pthread_create( &thread_id, NULL, start_rtsp_stream, NULL);
  463.  
  464. }
  465. }
  466.  
  467. exit:
  468. /* Unreference the new pad's caps, if we got them */
  469. if (new_pad_caps != NULL)
  470. gst_caps_unref (new_pad_caps);
  471.  
  472. /* Unreference the sink pad */
  473. gst_object_unref (sink_pad);
  474. }
  475.  
  476.  
  477. void *start_rtsp_stream(void *param) {
  478.  
  479. GMainLoop *loop;
  480. GstRTSPServer *server;
  481. GstRTSPMountPoints *mounts;
  482. GstRTSPMediaFactory *factory, *origfactory;
  483.  
  484. loop = g_main_loop_new (NULL, FALSE);
  485.  
  486. /* create a server instance */
  487. server = gst_rtsp_server_new ();
  488. gst_rtsp_server_set_address(server,"0.0.0.0");
  489.  
  490. /* get the mount points for this server, every server has a default object
  491. * that be used to map uri mount points to media factories */
  492. mounts = gst_rtsp_server_get_mount_points (server);
  493.  
  494. /* make a media factory for a test stream. The default media factory can use
  495. * gst-launch syntax to create pipelines.
  496. * any launch line works as long as it contains elements named pay%d. Each
  497. * element with pay%d names will be a stream */
  498. factory = gst_rtsp_media_factory_new ();
  499. gst_rtsp_media_factory_set_launch (factory, " ( "
  500. " udpsrc port=5000 ! "
  501. " capsfilter caps=\"application/x-rtp,clock-rate=90000,payload=96,encoding-name=H264,media=video\" name=pay0 "
  502. " ) " );
  503.  
  504. /* attach the test factory to the /test url */
  505. gst_rtsp_mount_points_add_factory (mounts, "/processed", factory);
  506.  
  507. origfactory = gst_rtsp_media_factory_new ();
  508. gst_rtsp_media_factory_set_launch (origfactory, " ( "
  509. " udpsrc port=5001 ! "
  510. " capsfilter caps=\"application/x-rtp,clock-rate=90000,payload=96,encoding-name=H264,media=video\" name=pay0 "
  511. " ) " );
  512. /* attach the original video factory to the /original url */
  513. gst_rtsp_mount_points_add_factory (mounts, "/original", origfactory);
  514.  
  515. /* don't need the ref to the mapper anymore */
  516. g_object_unref (mounts);
  517.  
  518. /* attach the server to the default maincontext */
  519. gst_rtsp_server_attach (server, NULL);
  520.  
  521. /* start serving */
  522. g_print ("processed/debug stream ready at rtsp://:8554/processed\n");
  523. g_print ("original stream ready at rtsp://:8554/original\n");
  524. g_main_loop_run (loop);
  525.  
  526. return 0;
  527.  
  528. }
  529.  
  530. static void event_handler(GstElement *e, time_t *t, CustomData *data, gchar *event_name) {
  531. struct tm *tmp;
  532. int status = 0;
  533. char sql[200] = "insert into event_notifications values('";
  534. gchar time_str[100];
  535.  
  536. g_print("Hello, captured the event. Timestamp = %ld, ", *t);
  537. tmp = localtime(t);
  538. strftime(time_str, 100, "%Y-%m-%d %H:%M:%S", tmp);
  539. g_print("===%s\n",time_str);
  540.  
  541. //todo: call mysql-real-escape-string()
  542. strncat(sql,event_name,200);
  543. //todo: replace local4 with actual stream name
  544. strncat(sql,"','local4','",200);
  545. strncat(sql,time_str,200);
  546. strncat(sql,"','{}');",200);
  547.  
  548. g_print("SQL: %s\n",sql);
  549. status = mysql_query( MySQLConn, sql);
  550. if(status) {
  551. g_print("SQL Error: %s\n", mysql_error(MySQLConn));
  552. }
  553. }
  554.  
  555. static void motion_start_handler(GstElement *e, time_t *t, CustomData *data) {
  556.  
  557. event_handler(e, t, data, "motion-start");
  558. }
  559.  
  560. static void motion_stop_handler(GstElement *e, time_t *t, CustomData *data) {
  561.  
  562. event_handler(e, t, data, "motion-stop");
  563. }
  564.  
  565. void send_eos(int sig) {
  566.  
  567. do_exit = TRUE;
  568. gst_element_send_event(data.pipeline,gst_event_new_eos());
  569. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement