gnunet_gst.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2016 GNUnet e.V.
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  15. Boston, MA 02110-1301, USA.
  16. */
  17. /**
  18. * @file conversation/gnunet_gst.c
  19. * @brief FIXME
  20. * @author Hark
  21. */
  22. #include "gnunet_gst_def.h"
  23. /**
  24. * Our configuration.
  25. */
  26. static struct GNUNET_CONFIGURATION_Handle *cfg;
  27. void
  28. dump_buffer(unsigned n, const unsigned char* buf)
  29. {
  30. const unsigned char *p, *end;
  31. unsigned i, j;
  32. end = buf + n;
  33. for (i = 0; ; i += 16) {
  34. p = buf + i;
  35. for (j = 0; j < 16; j++) {
  36. fprintf(stderr, "%02X ", p[j]);
  37. if (p + j >= end)
  38. goto BREAKOUT;
  39. }
  40. fprintf(stderr, " ");
  41. p = buf + i;
  42. for (j = 0; j < 16; j++) {
  43. fprintf(stderr, "%c", isprint(p[j]) ? p[j] :
  44. '.');
  45. if (p + j >= end)
  46. goto BREAKOUT;
  47. }
  48. fprintf(stderr, "\n");
  49. }
  50. BREAKOUT:
  51. return;
  52. }
  53. /***
  54. * load gnunet configuration
  55. */
  56. void
  57. gg_load_configuration(GNUNET_gstData * d)
  58. {
  59. char *audiobackend_string;
  60. cfg = GNUNET_CONFIGURATION_create();
  61. GNUNET_CONFIGURATION_load(cfg, "mediahelper.conf");
  62. GNUNET_CONFIGURATION_get_value_string(cfg, "MEDIAHELPER", "JACK_PP_IN", &d->jack_pp_in);
  63. GNUNET_CONFIGURATION_get_value_string(cfg, "MEDIAHELPER", "JACK_PP_OUT", &d->jack_pp_out);
  64. GNUNET_CONFIGURATION_get_value_string(cfg, "MEDIAHELPER", "AUDIOBACKEND", &audiobackend_string);
  65. // printf("abstring: %s \n", audiobackend_string);
  66. if (0 == strcasecmp (audiobackend_string, "AUTO"))
  67. {
  68. d->audiobackend = AUTO;
  69. } else if (0 == strcasecmp (audiobackend_string, "JACK"))
  70. {
  71. d->audiobackend = JACK;
  72. } else if (0 == strcasecmp (audiobackend_string, "ALSA"))
  73. {
  74. d->audiobackend = ALSA;
  75. } else if (0 == strcasecmp (audiobackend_string, "FAKE"))
  76. {
  77. d->audiobackend = FAKE;
  78. } else if (0 == strcasecmp (audiobackend_string, "TEST"))
  79. {
  80. d->audiobackend = TEST;
  81. } else
  82. {
  83. d->audiobackend = AUTO;
  84. }
  85. if (GNUNET_CONFIGURATION_get_value_yesno(cfg, "MEDIAHELPER", "REMOVESILENCE") == GNUNET_YES)
  86. {
  87. d->dropsilence = TRUE;
  88. } else {
  89. d->dropsilence = FALSE;
  90. }
  91. if (GNUNET_CONFIGURATION_get_value_yesno(cfg, "MEDIAHELPER", "NO_GN_HEADERS") == GNUNET_YES)
  92. {
  93. d->pure_ogg = TRUE;
  94. } else {
  95. d->pure_ogg = FALSE;
  96. }
  97. if (GNUNET_CONFIGURATION_get_value_yesno(cfg, "MEDIAHELPER", "USERTP") == GNUNET_YES)
  98. {
  99. d->usertp = TRUE;
  100. } else {
  101. d->usertp = FALSE;
  102. }
  103. // GNUNET_CONFIGURATION_write(cfg, "mediahelper.conf");
  104. }
  105. static void
  106. write_data (const char *ptr, size_t msg_size)
  107. {
  108. ssize_t ret;
  109. size_t off;
  110. off = 0;
  111. while (off < msg_size)
  112. {
  113. ret = write (1, &ptr[off], msg_size - off);
  114. if (0 >= ret)
  115. {
  116. if (-1 == ret)
  117. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "write");
  118. // quit (2);
  119. }
  120. off += ret;
  121. }
  122. }
  123. extern GstFlowReturn
  124. on_appsink_new_sample (GstElement * element, GNUNET_gstData * d)
  125. {
  126. //size of message including gnunet header
  127. size_t msg_size;
  128. GstSample *s;
  129. GstBuffer *b;
  130. GstMapInfo map;
  131. /*
  132. const GstStructure *si;
  133. char *si_str;
  134. GstCaps *s_caps;
  135. char *caps_str;
  136. */
  137. if (gst_app_sink_is_eos(GST_APP_SINK(element)))
  138. return GST_FLOW_OK;
  139. //pull sample from appsink
  140. s = gst_app_sink_pull_sample (GST_APP_SINK(element));
  141. if (s == NULL)
  142. return GST_FLOW_OK;
  143. if (!GST_IS_SAMPLE (s))
  144. return GST_FLOW_OK;
  145. b = gst_sample_get_buffer(s);
  146. GST_WARNING ("caps are %" GST_PTR_FORMAT, gst_sample_get_caps(s));
  147. gst_buffer_map (b, &map, GST_MAP_READ);
  148. size_t len;
  149. len = map.size;
  150. if (len > UINT16_MAX - sizeof (struct AudioMessage))
  151. {
  152. // this should never happen?
  153. printf("GSTREAMER sample too big! \n");
  154. exit(20);
  155. len = UINT16_MAX - sizeof (struct AudioMessage);
  156. }
  157. msg_size = sizeof (struct AudioMessage) + len;
  158. // copy the data into audio_message
  159. GNUNET_memcpy (((char *) &(d->audio_message)[1]), map.data, len);
  160. (d->audio_message)->header.size = htons ((uint16_t) msg_size);
  161. if (d->pure_ogg)
  162. // write the audio_message without the gnunet headers
  163. write_data ((const char *) &(d->audio_message)[1], len);
  164. else
  165. write_data ((const char *) d->audio_message, msg_size);
  166. gst_sample_unref(s);
  167. return GST_FLOW_OK;
  168. }
  169. /***
  170. * Dump a pipeline graph
  171. */
  172. extern void
  173. pl_graph(GstElement * pipeline)
  174. {
  175. #ifdef IS_SPEAKER
  176. gst_debug_bin_to_dot_file_with_ts(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "playback_helper.dot");
  177. #endif
  178. #ifdef IS_MIC
  179. gst_debug_bin_to_dot_file_with_ts(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "record_helper.dot");
  180. #endif
  181. // load_configuration();
  182. }
  183. extern gboolean
  184. gnunet_gst_bus_call (GstBus *bus, GstMessage *msg, gpointer data)
  185. {
  186. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  187. "Bus message\n");
  188. switch (GST_MESSAGE_TYPE (msg))
  189. {
  190. case GST_MESSAGE_EOS:
  191. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  192. "End of stream\n");
  193. exit (10);
  194. break;
  195. case GST_MESSAGE_ERROR:
  196. {
  197. gchar *debug;
  198. GError *error;
  199. gst_message_parse_error (msg, &error, &debug);
  200. g_free (debug);
  201. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  202. "Error: %s\n",
  203. error->message);
  204. g_error_free (error);
  205. exit (10);
  206. break;
  207. }
  208. default:
  209. break;
  210. }
  211. return TRUE;
  212. }
  213. /* called when pipeline changes state */
  214. extern void
  215. state_changed_cb (GstBus * bus, GstMessage * msg, GNUNET_gstData * d)
  216. {
  217. GstState old_state, new_state, pending_state;
  218. gst_message_parse_state_changed (msg, &old_state, &new_state,
  219. &pending_state);
  220. switch (new_state)
  221. {
  222. case GST_STATE_READY:
  223. // printf("ready.... \n");
  224. //pl_graph(GST_ELEMENT(d->pipeline));
  225. break;
  226. case GST_STATE_PLAYING:
  227. //GST_LOG ("caps are %" GST_PTR_FORMAT, caps);
  228. // printf("Playing.... \n");
  229. pl_graph(GST_ELEMENT(d->pipeline));
  230. break;
  231. case GST_STATE_VOID_PENDING:
  232. // printf("void_pending.... \n");
  233. //pl_graph(GST_ELEMENT(d->pipeline));
  234. break;
  235. case GST_STATE_NULL:
  236. // printf("null.... \n");
  237. //pl_graph(GST_ELEMENT(d->pipeline));
  238. break;
  239. case GST_STATE_PAUSED:
  240. // printf("paused.... \n");
  241. //pl_graph(GST_ELEMENT(d->pipeline));
  242. break;
  243. }
  244. }
  245. static void
  246. application_cb (GstBus * bus, GstMessage * msg, GNUNET_gstData * data)
  247. {
  248. // printf("application cb");
  249. return;
  250. }
  251. static void
  252. error_cb (GstBus * bus, GstMessage * msg, GNUNET_gstData * data)
  253. {
  254. // printf("error cb");
  255. return;
  256. }
  257. static void
  258. eos_cb (GstBus * bus, GstMessage * msg, GNUNET_gstData * data)
  259. {
  260. // printf("eos cb");
  261. return;
  262. }
  263. extern void
  264. gg_setup_gst_bus (GNUNET_gstData * d)
  265. {
  266. GstBus *bus;
  267. bus = gst_element_get_bus (GST_ELEMENT(d->pipeline));
  268. gst_bus_add_signal_watch (bus);
  269. g_signal_connect (G_OBJECT (bus), "message::error", (GCallback) error_cb,
  270. d);
  271. g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback) eos_cb,
  272. d);
  273. g_signal_connect (G_OBJECT (bus), "message::state-changed",
  274. (GCallback) state_changed_cb, d);
  275. g_signal_connect (G_OBJECT (bus), "message::application",
  276. (GCallback) application_cb, d);
  277. g_signal_connect (G_OBJECT (bus), "message::about-to-finish",
  278. (GCallback) application_cb, d);
  279. gst_object_unref (bus);
  280. }
  281. /*
  282. * take buffer from gstreamer and feed it to gnunet
  283. */
  284. /*
  285. extern int
  286. feed_buffer_to_gnunet (GNUNET_gstData * d)
  287. {
  288. GstSample *s;
  289. GstBuffer *b;
  290. GstMapInfo m;
  291. size_t len, msg_size;
  292. const char *ptr;
  293. int phase;
  294. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pulling...\n");
  295. s = gst_app_sink_pull_sample (GST_APP_SINK(d->appsink));
  296. if (NULL == s)
  297. {
  298. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pulled NULL\n");
  299. return OK;
  300. }
  301. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "...pulled!\n");
  302. const GstStructure *si;
  303. char *si_str;
  304. GstCaps *s_caps;
  305. char *caps_str;
  306. si = gst_sample_get_info (s);
  307. if (si)
  308. {
  309. si_str = gst_structure_to_string (si);
  310. if (si_str)
  311. {
  312. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample %s\n", si_str);
  313. g_free (si_str);
  314. }
  315. }
  316. else
  317. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with no info\n");
  318. s_caps = gst_sample_get_caps (s);
  319. if (s_caps)
  320. {
  321. caps_str = gst_caps_to_string (s_caps);
  322. if (caps_str)
  323. {
  324. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with caps %s\n", caps_str);
  325. g_free (caps_str);
  326. }
  327. }
  328. else
  329. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got sample with no caps\n");
  330. b = gst_sample_get_buffer (s);
  331. if (NULL == b || !gst_buffer_map (b, &m, GST_MAP_READ))
  332. {
  333. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got NULL buffer %p or failed to map the buffer\n", b);
  334. gst_sample_unref (s);
  335. return FAIL;
  336. }
  337. len = m.size;
  338. if (len > UINT16_MAX - sizeof (struct AudioMessage))
  339. {
  340. GNUNET_break (0);
  341. len = UINT16_MAX - sizeof (struct AudioMessage);
  342. }
  343. msg_size = sizeof (struct AudioMessage) + len;
  344. audio_message.header.size = htons ((uint16_t) msg_size);
  345. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  346. "Sending %u bytes of audio data\n", (unsigned int) msg_size);
  347. for (phase = 0; phase < 2; phase++)
  348. {
  349. size_t offset;
  350. size_t to_send;
  351. ssize_t ret;
  352. if (0 == phase && !d->pure_ogg)
  353. {
  354. //#ifdef DEBUG_RECORD_PURE_OGG
  355. // if (d->pure_ogg)
  356. // break;
  357. //#endif
  358. ptr = (const char *) &audio_message;
  359. to_send = sizeof (audio_message);
  360. }
  361. else
  362. {
  363. ptr = (const char *) m.data;
  364. to_send = len;
  365. }
  366. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  367. "Sending %u bytes on phase %d\n", (unsigned int) to_send, phase);
  368. for (offset = 0; offset < to_send; offset += ret)
  369. {
  370. ret = write (1, &ptr[offset], to_send - offset);
  371. if (0 >= ret)
  372. {
  373. if (-1 == ret)
  374. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  375. "Failed to write %u bytes at offset %u (total %u) in phase %d: %s\n",
  376. (unsigned int) to_send - offset, (unsigned int) offset,
  377. (unsigned int) (to_send + offset), phase, strerror (errno));
  378. // abort_send = 1;
  379. return FAIL;
  380. }
  381. }
  382. // if (abort_send)
  383. // break;
  384. }
  385. gst_buffer_unmap (b, &m);
  386. gst_sample_unref (s);
  387. }
  388. */
  389. extern int
  390. feed_buffer_to_gst (const char *audio, size_t b_len, GNUNET_gstData * d)
  391. {
  392. GstBuffer *b;
  393. gchar *bufspace;
  394. GstFlowReturn flow;
  395. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  396. "Feeding %u bytes to GStreamer\n",
  397. (unsigned int) b_len);
  398. bufspace = g_memdup (audio, b_len);
  399. b = gst_buffer_new_wrapped (bufspace, b_len);
  400. if (NULL == b)
  401. {
  402. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  403. "Failed to wrap a buffer\n");
  404. g_free (bufspace);
  405. return GNUNET_SYSERR;
  406. }
  407. if (GST_APP_SRC(d->appsrc) == NULL)
  408. exit(10);
  409. flow = gst_app_src_push_buffer (GST_APP_SRC(d->appsrc), b);
  410. /* They all return GNUNET_OK, because currently player stops when
  411. * data stops coming. This might need to be changed for the player
  412. * to also stop when pipeline breaks.
  413. */
  414. switch (flow)
  415. {
  416. case GST_FLOW_OK:
  417. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  418. "Fed %u bytes to the pipeline\n",
  419. (unsigned int) b_len);
  420. break;
  421. case GST_FLOW_FLUSHING:
  422. /* buffer was dropped, because pipeline state is not PAUSED or PLAYING */
  423. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  424. "Dropped a buffer\n");
  425. break;
  426. case GST_FLOW_EOS:
  427. /* end of stream */
  428. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  429. "EOS\n");
  430. break;
  431. default:
  432. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  433. "Unexpected push result\n");
  434. break;
  435. }
  436. return GNUNET_OK;
  437. }
  438. /**
  439. * debug making elements
  440. */
  441. extern GstElement *
  442. gst_element_factory_make_debug( gchar *factoryname, gchar *name)
  443. {
  444. GstElement *element;
  445. element = gst_element_factory_make(factoryname,name);
  446. if (element == NULL) {
  447. printf ("\n Failed to create element - type: %s name: %s \n", factoryname, name);
  448. exit(10);
  449. return element;
  450. } else {
  451. return element;
  452. }
  453. }
  454. /*
  455. static gboolean
  456. gst_element_link_many_debug(...)
  457. {
  458. va_list arguments;
  459. gst_element_link_many(argptr);
  460. }
  461. #define gst_element_link_many(...) \
  462. gst_element_link_many_debug(__VA_ARGS__)
  463. */
  464. extern void
  465. lf(char * msg)
  466. {
  467. printf("linking elements failed: %s", msg);
  468. exit(10);
  469. }
  470. /***
  471. * used to set properties on autoaudiosink's chosen sink
  472. */
  473. static void
  474. autoaudiosink_child_added (GstChildProxy *child_proxy,
  475. GObject *object,
  476. gchar *name,
  477. gpointer user_data)
  478. {
  479. if (GST_IS_AUDIO_BASE_SRC (object))
  480. g_object_set (object,
  481. "buffer-time", (gint64) BUFFER_TIME,
  482. "latency-time", (gint64) LATENCY_TIME,
  483. NULL);
  484. }
  485. /***
  486. * used to set properties on autoaudiosource's chosen sink
  487. */
  488. static void
  489. autoaudiosource_child_added (GstChildProxy *child_proxy, GObject *object, gchar *name, gpointer user_data)
  490. {
  491. if (GST_IS_AUDIO_BASE_SRC (object))
  492. g_object_set (object, "buffer-time", (gint64) BUFFER_TIME, "latency-time", (gint64) LATENCY_TIME, NULL);
  493. }
  494. GstElement *
  495. get_pipeline(GstElement *element)
  496. {
  497. GstPipeline *p;
  498. p = GST_PIPELINE (gst_object_get_parent(GST_OBJECT (element)));
  499. return GST_ELEMENT (p);
  500. }
  501. static void
  502. decoder_ogg_pad_added (GstElement *element,
  503. GstPad *pad,
  504. gpointer data)
  505. {
  506. GstPad *sinkpad;
  507. GstElement *decoder = (GstElement *) data;
  508. printf("==== ogg pad added callback \n");
  509. /* We can now link this pad with the opus-decoder sink pad */
  510. // pl_graph(get_pipeline(element));
  511. sinkpad = gst_element_get_static_pad (decoder, "sink");
  512. gst_pad_link (pad, sinkpad);
  513. gst_element_link_many(element, decoder, NULL);
  514. gst_object_unref (sinkpad);
  515. }
  516. int
  517. gnunet_read (GNUNET_gstData * d)
  518. {
  519. char readbuf[MAXLINE];
  520. int ret;
  521. printf("read \n");
  522. ret = read (0, readbuf, sizeof (readbuf));
  523. if (0 > ret)
  524. {
  525. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  526. _("Read error from STDIN: %d %s\n"),
  527. ret, strerror (errno));
  528. return FAIL;
  529. }
  530. //toff += ret;
  531. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  532. "Received %d bytes of audio data\n",
  533. (int) ret);
  534. if (0 == ret)
  535. return FAIL;
  536. //#ifdef DEBUG_READ_PURE_OGG
  537. if (d->pure_ogg)
  538. {
  539. feed_buffer_to_gst (readbuf, ret, d);
  540. }
  541. else
  542. {
  543. //#endif
  544. GNUNET_MST_from_buffer (d->stdin_mst,
  545. readbuf,
  546. ret,
  547. GNUNET_NO,
  548. GNUNET_NO);
  549. }
  550. return 0;
  551. }
  552. /**
  553. * Message callback
  554. */
  555. static int
  556. stdin_receiver (void *cls,
  557. const struct GNUNET_MessageHeader *msg)
  558. {
  559. struct AudioMessage *audio;
  560. size_t b_len;
  561. printf("stdin receiver \n ");
  562. dump_buffer (sizeof(msg),
  563. (const unsigned char *) msg);
  564. switch (ntohs (msg->type))
  565. {
  566. case GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO:
  567. audio = (struct AudioMessage *) msg;
  568. b_len = ntohs (audio->header.size) - sizeof (struct AudioMessage);
  569. printf("feeding buffer to gst \n ");
  570. feed_buffer_to_gst ((const char *) &audio[1], b_len, cls);
  571. break;
  572. default:
  573. printf("No audio message: %u \n ", ntohs(msg->type));
  574. break;
  575. }
  576. return GNUNET_OK;
  577. }
  578. GstBin *
  579. get_app(GNUNET_gstData *d, int type)
  580. {
  581. GstBin *bin;
  582. GstPad *pad, *ghostpad;
  583. if ( type == SOURCE )
  584. {
  585. bin = GST_BIN(gst_bin_new("Gnunet appsrc"));
  586. GNUNET_assert (GNUNET_OK ==
  587. GNUNET_log_setup ("gnunet-helper-audio-playback",
  588. "WARNING",
  589. NULL));
  590. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  591. "Audio playback starts\n");
  592. printf(" creating appsrc \n ");
  593. //d->audio_message.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO);
  594. // d->audio_message = GNUNET_malloc (UINT16_MAX);
  595. // d->audio_message = (AudioMessage*)malloc(sizeof(struct AudioMessage));
  596. // d->audio_message = GNUNET_malloc(sizeof(struct AudioMessage));
  597. //d->audio_message.header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO);
  598. d->stdin_mst = GNUNET_MST_create (&stdin_receiver, d);
  599. if ( d->stdin_mst == NULL)
  600. printf("stdin_mst = NULL");
  601. d->appsrc = gst_element_factory_make ("appsrc", "appsrc");
  602. gst_bin_add_many( bin, d->appsrc, NULL);
  603. // gst_element_link_many ( encoder, muxer, NULL);
  604. pad = gst_element_get_static_pad (d->appsrc, "src");
  605. ghostpad = gst_ghost_pad_new ("src", pad);
  606. }
  607. if ( type == SINK )
  608. {
  609. bin = GST_BIN(gst_bin_new("Gnunet appsink"));
  610. GNUNET_assert (GNUNET_OK ==
  611. GNUNET_log_setup ("gnunet-helper-audio-record",
  612. "WARNING",
  613. NULL));
  614. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  615. "Audio source starts\n");
  616. d->appsink = gst_element_factory_make ("appsink", "appsink");
  617. // Move this out of here!
  618. d->audio_message = GNUNET_malloc (UINT16_MAX);
  619. (d->audio_message)->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO);
  620. g_object_set (G_OBJECT (d->appsink), "emit-signals", TRUE, "sync", TRUE, NULL);
  621. g_signal_connect (d->appsink, "new-sample",
  622. G_CALLBACK (on_appsink_new_sample), &d);
  623. gst_bin_add_many( bin, d->appsink, NULL);
  624. // gst_element_link_many ( encoder, muxer, NULL);
  625. pad = gst_element_get_static_pad (d->appsink, "sink");
  626. ghostpad = gst_ghost_pad_new ("sink", pad);
  627. }
  628. /* set the bin pads */
  629. gst_pad_set_active (ghostpad, TRUE);
  630. gst_element_add_pad (GST_ELEMENT(bin), ghostpad);
  631. gst_object_unref (pad);
  632. return bin;
  633. }
  634. extern GstBin *
  635. get_coder(GNUNET_gstData *d , int type)
  636. {
  637. GstBin *bin;
  638. GstPad *srcpad, *sinkpad, *srcghostpad, *sinkghostpad;
  639. GstCaps *rtpcaps;
  640. GstElement *encoder, *muxer, *decoder, *demuxer, *jitterbuffer, *rtpcapsfilter;
  641. if ( d->usertp == TRUE )
  642. {
  643. /*
  644. * application/x-rtp, media=(string)audio, clock-rate=(int)48000, encoding-name=(string)OPUS, sprop-maxcapturerate=(string)48000, sprop-stereo=(string)0, payload=(int)96, encoding-params=(string)2, ssrc=(uint)630297634, timestamp-offset=(uint)678334141, seqnum-offset=(uint)16938 */
  645. /*
  646. rtpcaps = gst_caps_new_simple ("application/x-rtp",
  647. "media", G_TYPE_STRING, "audio",
  648. "clock-rate", G_TYPE_INT, SAMPLING_RATE,
  649. "encoding-name", G_TYPE_STRING, "OPUS",
  650. "payload", G_TYPE_INT, 96,
  651. "sprop-stereo", G_TYPE_STRING, "0",
  652. "encoding-params", G_TYPE_STRING, "2",
  653. NULL);
  654. */
  655. rtpcaps = gst_caps_new_simple ("application/x-rtp",
  656. "media", G_TYPE_STRING, "audio",
  657. "clock-rate", G_TYPE_INT, SAMPLING_RATE,
  658. "encoding-name", G_TYPE_STRING, "OPUS",
  659. "payload", G_TYPE_INT, 96,
  660. "sprop-stereo", G_TYPE_STRING, "0",
  661. "encoding-params", G_TYPE_STRING, "2",
  662. NULL);
  663. rtpcapsfilter = gst_element_factory_make ("capsfilter", "rtpcapsfilter");
  664. g_object_set (G_OBJECT (rtpcapsfilter),
  665. "caps", rtpcaps,
  666. NULL);
  667. gst_caps_unref (rtpcaps);
  668. }
  669. if ( type == ENCODER )
  670. {
  671. bin = GST_BIN(gst_bin_new("Gnunet audioencoder"));
  672. encoder = gst_element_factory_make ("opusenc", "opus-encoder");
  673. if ( d->usertp == TRUE )
  674. {
  675. muxer = gst_element_factory_make ("rtpopuspay", "rtp-payloader");
  676. } else {
  677. muxer = gst_element_factory_make ("oggmux", "ogg-muxer");
  678. }
  679. g_object_set (G_OBJECT (encoder),
  680. /* "bitrate", 64000, */
  681. /* "bandwidth", OPUS_BANDWIDTH_FULLBAND, */
  682. "inband-fec", INBAND_FEC_MODE,
  683. "packet-loss-percentage", PACKET_LOSS_PERCENTAGE,
  684. "max-payload-size", MAX_PAYLOAD_SIZE,
  685. "audio", TRUE, /* VoIP, not audio */
  686. "frame-size", OPUS_FRAME_SIZE,
  687. NULL);
  688. if ( d->usertp != TRUE)
  689. {
  690. g_object_set (G_OBJECT (muxer),
  691. "max-delay", OGG_MAX_DELAY,
  692. "max-page-delay", OGG_MAX_PAGE_DELAY,
  693. NULL);
  694. }
  695. gst_bin_add_many( bin, encoder, muxer, NULL);
  696. gst_element_link_many ( encoder, muxer, NULL);
  697. sinkpad = gst_element_get_static_pad(encoder, "sink");
  698. sinkghostpad = gst_ghost_pad_new ("sink", sinkpad);
  699. srcpad = gst_element_get_static_pad(muxer, "src");
  700. srcghostpad = gst_ghost_pad_new ("src", srcpad);
  701. }
  702. if ( type == DECODER )
  703. {
  704. bin = GST_BIN(gst_bin_new("Gnunet audiodecoder"));
  705. // decoder
  706. if ( d->usertp == TRUE )
  707. {
  708. demuxer = gst_element_factory_make ("rtpopusdepay", "ogg-demuxer");
  709. jitterbuffer = gst_element_factory_make ("rtpjitterbuffer", "rtpjitterbuffer");
  710. } else {
  711. demuxer = gst_element_factory_make ("oggdemux", "ogg-demuxer");
  712. }
  713. decoder = gst_element_factory_make ("opusdec", "opus-decoder");
  714. if ( d->usertp == TRUE )
  715. {
  716. gst_bin_add_many( bin, rtpcapsfilter, jitterbuffer, demuxer, decoder, NULL);
  717. gst_element_link_many ( rtpcapsfilter, jitterbuffer, demuxer, decoder, NULL);
  718. sinkpad = gst_element_get_static_pad(rtpcapsfilter, "sink");
  719. } else {
  720. gst_bin_add_many( bin, demuxer, decoder, NULL);
  721. g_signal_connect (demuxer,
  722. "pad-added",
  723. G_CALLBACK (decoder_ogg_pad_added),
  724. decoder);
  725. sinkpad = gst_element_get_static_pad(demuxer, "sink");
  726. }
  727. sinkghostpad = gst_ghost_pad_new ("sink", sinkpad);
  728. srcpad = gst_element_get_static_pad(decoder, "src");
  729. srcghostpad = gst_ghost_pad_new ("src", srcpad);
  730. }
  731. // add pads to the bin
  732. gst_pad_set_active (sinkghostpad, TRUE);
  733. gst_element_add_pad (GST_ELEMENT(bin), sinkghostpad);
  734. gst_pad_set_active (srcghostpad, TRUE);
  735. gst_element_add_pad (GST_ELEMENT(bin), srcghostpad);
  736. return bin;
  737. }
  738. extern GstBin *
  739. get_audiobin(GNUNET_gstData *d , int type)
  740. {
  741. GstBin *bin;
  742. GstElement *sink, *source, *queue, *conv, *resampler, *removesilence, *filter;
  743. GstPad *pad, *ghostpad;
  744. GstCaps *caps;
  745. if ( type == SINK ) {
  746. bin = GST_BIN(gst_bin_new("Gnunet audiosink"));
  747. /* Create all the elements */
  748. if ( d->dropsilence == TRUE )
  749. {
  750. queue = gst_element_factory_make ("queue", "queue");
  751. removesilence = gst_element_factory_make ("removesilence", "removesilence");
  752. }
  753. conv = gst_element_factory_make ("audioconvert", "converter");
  754. resampler= gst_element_factory_make ("audioresample", "resampler");
  755. if ( d->audiobackend == AUTO )
  756. {
  757. sink = gst_element_factory_make ("autoaudiosink", "audiosink");
  758. g_signal_connect (sink, "child-added", G_CALLBACK (autoaudiosink_child_added), NULL);
  759. }
  760. if ( d->audiobackend == ALSA )
  761. {
  762. sink = gst_element_factory_make ("alsaaudiosink", "audiosink");
  763. }
  764. if ( d->audiobackend == JACK )
  765. {
  766. sink = gst_element_factory_make ("jackaudiosink", "audiosink");
  767. g_object_set (G_OBJECT (sink), "client-name", "gnunet", NULL);
  768. if (g_object_class_find_property
  769. (G_OBJECT_GET_CLASS (sink), "port-pattern"))
  770. {
  771. // char *portpattern = "system";
  772. g_object_set (G_OBJECT (sink), "port-pattern", d->jack_pp_out,
  773. NULL);
  774. }
  775. }
  776. if ( d->audiobackend == FAKE )
  777. {
  778. sink = gst_element_factory_make ("fakesink", "audiosink");
  779. }
  780. g_object_set (sink,
  781. "buffer-time", (gint64) BUFFER_TIME,
  782. "latency-time", (gint64) LATENCY_TIME,
  783. NULL);
  784. if ( d->dropsilence == TRUE )
  785. {
  786. // Do not remove silence by default
  787. g_object_set( removesilence, "remove", FALSE, NULL);
  788. g_object_set( queue, "max-size-buffers", 12, NULL);
  789. /*
  790. g_signal_connect (source,
  791. "need-data",
  792. G_CALLBACK(appsrc_need_data),
  793. NULL);
  794. g_signal_connect (source,
  795. "enough-data",
  796. G_CALLBACK(appsrc_enough_data),
  797. NULL);
  798. */
  799. /*
  800. g_signal_connect (queue,
  801. "notify::current-level-bytes",
  802. G_CALLBACK(queue_current_level),
  803. NULL);
  804. g_signal_connect (queue,
  805. "underrun",
  806. G_CALLBACK(queue_underrun),
  807. NULL);
  808. g_signal_connect (queue,
  809. "running",
  810. G_CALLBACK(queue_running),
  811. NULL);
  812. g_signal_connect (queue,
  813. "overrun",
  814. G_CALLBACK(queue_overrun),
  815. NULL);
  816. g_signal_connect (queue,
  817. "pushing",
  818. G_CALLBACK(queue_pushing),
  819. NULL);
  820. */
  821. }
  822. gst_bin_add_many (bin , conv, resampler, sink, NULL);
  823. gst_element_link_many ( conv, resampler, sink, NULL);
  824. if ( d->dropsilence == TRUE )
  825. {
  826. gst_bin_add_many (bin , queue ,removesilence , NULL);
  827. if ( !gst_element_link_many ( queue, removesilence, conv, NULL) )
  828. lf ("queue, removesilence, conv ");
  829. pad = gst_element_get_static_pad (queue, "sink");
  830. } else {
  831. pad = gst_element_get_static_pad(conv, "sink");
  832. }
  833. ghostpad = gst_ghost_pad_new ("sink", pad);
  834. } else {
  835. // SOURCE
  836. bin = GST_BIN(gst_bin_new("Gnunet audiosource"));
  837. // source = gst_element_factory_make("audiotestsrc", "audiotestsrcbla");
  838. if (d->audiobackend == AUTO )
  839. {
  840. source = gst_element_factory_make ("autoaudiosrc", "audiosource");
  841. }
  842. if (d->audiobackend == ALSA )
  843. {
  844. source = gst_element_factory_make ("alsasrc", "audiosource");
  845. }
  846. if (d->audiobackend == JACK )
  847. {
  848. source = gst_element_factory_make ("jackaudiosrc", "audiosource");
  849. }
  850. if (d->audiobackend == TEST )
  851. {
  852. source = gst_element_factory_make ("audiotestsrc", "audiosource");
  853. }
  854. filter = gst_element_factory_make ("capsfilter", "filter");
  855. conv = gst_element_factory_make ("audioconvert", "converter");
  856. resampler= gst_element_factory_make ("audioresample", "resampler");
  857. if (d->audiobackend == AUTO ) {
  858. g_signal_connect (source, "child-added", G_CALLBACK (autoaudiosource_child_added), NULL);
  859. } else {
  860. if (GST_IS_AUDIO_BASE_SRC (source))
  861. g_object_set (source, "buffer-time", (gint64) BUFFER_TIME, "latency-time", (gint64) LATENCY_TIME, NULL);
  862. if ( d->audiobackend == JACK ) {
  863. g_object_set (G_OBJECT (source), "client-name", "gnunet", NULL);
  864. if (g_object_class_find_property
  865. (G_OBJECT_GET_CLASS (source), "port-pattern"))
  866. {
  867. char *portpattern = "moc";
  868. g_object_set (G_OBJECT (source), "port-pattern", portpattern,
  869. NULL);
  870. }
  871. }
  872. }
  873. caps = gst_caps_new_simple ("audio/x-raw",
  874. /* "format", G_TYPE_STRING, "S16LE", */
  875. /* "rate", G_TYPE_INT, SAMPLING_RATE,*/
  876. "channels", G_TYPE_INT, OPUS_CHANNELS,
  877. /* "layout", G_TYPE_STRING, "interleaved",*/
  878. NULL);
  879. g_object_set (G_OBJECT (filter),
  880. "caps", caps,
  881. NULL);
  882. gst_caps_unref (caps);
  883. gst_bin_add_many (bin , source, filter, conv, resampler, NULL);
  884. gst_element_link_many ( source, filter, conv, resampler, NULL);
  885. pad = gst_element_get_static_pad (resampler, "src");
  886. /* pads */
  887. ghostpad = gst_ghost_pad_new ("src", pad);
  888. }
  889. /* set the bin pads */
  890. gst_pad_set_active (ghostpad, TRUE);
  891. gst_element_add_pad (GST_ELEMENT(bin), ghostpad);
  892. gst_object_unref (pad);
  893. return bin;
  894. }