aboutsummaryrefslogtreecommitdiff
path: root/gst-vocschnipselssink/src/gstvocschnipselsink.c
blob: e4f88ee7098caa0f65074bf7ca2bee586ada1e39 (plain)
  1. /*
  2.  * GStreamer
  3. * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
  4. * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
  5. * Copyright (C) 2014 Peter Körner <<user@hostname.org>>
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the "Software"),
  9. * to deal in the Software without restriction, including without limitation
  10. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. * and/or sell copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. * DEALINGS IN THE SOFTWARE.
  24. *
  25. * Alternatively, the contents of this file may be used under the
  26. * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
  27. * which case the following provisions apply instead of the ones
  28. * mentioned above:
  29. *
  30. * This library is free software; you can redistribute it and/or
  31. * modify it under the terms of the GNU Library General Public
  32. * License as published by the Free Software Foundation; either
  33. * version 2 of the License, or (at your option) any later version.
  34. *
  35. * This library is distributed in the hope that it will be useful,
  36. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  37. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  38. * Library General Public License for more details.
  39. *
  40. * You should have received a copy of the GNU Library General Public
  41. * License along with this library; if not, write to the
  42. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  43. * Boston, MA 02111-1307, USA.
  44. */
  45. /**
  46. * SECTION:element-vocschnipselsink
  47. *
  48. * FIXME:Describe vocschnipselsink here.
  49. *
  50. * <refsect2>
  51. * <title>Example launch line</title>
  52. * |[
  53. * gst-launch -v -m fakesrc ! vocschnipselsink ! fakesink silent=TRUE
  54. * ]|
  55. * </refsect2>
  56. */
  57. #ifdef HAVE_CONFIG_H
  58. # include <config.h>
  59. #endif
  60. #include <gst/gst.h>
  61. #include "gstvocschnipselsink.h"
  62. GST_DEBUG_CATEGORY_STATIC (gst_voc_schnipsel_sink_debug);
  63. #define GST_CAT_DEFAULT gst_voc_schnipsel_sink_debug
  64. /* Filter signals and args */
  65. enum
  66. {
  67. /* FILL ME */
  68. LAST_SIGNAL
  69. };
  70. enum
  71. {
  72. PROP_0,
  73. PROP_SILENT
  74. };
  75. /* the capabilities of the inputs and outputs.
  76. *
  77. * describe the real formats here.
  78. */
  79. static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
  80. GST_PAD_SINK,
  81. GST_PAD_ALWAYS,
  82. GST_STATIC_CAPS ("ANY")
  83. );
  84. #define gst_voc_schnipsel_sink_parent_class parent_class
  85. G_DEFINE_TYPE (GstVocSchnipselSink, gst_voc_schnipsel_sink, GST_TYPE_ELEMENT);
  86. static void gst_voc_schnipsel_sink_set_property (GObject * object, guint prop_id,
  87. const GValue * value, GParamSpec * pspec);
  88. static void gst_voc_schnipsel_sink_get_property (GObject * object, guint prop_id,
  89. GValue * value, GParamSpec * pspec);
  90. static gboolean gst_voc_schnipsel_sink_set_caps (GstBaseSink * sink,
  91. GstCaps * caps);
  92. static gboolean gst_voc_schnipsel_sink_open_next_file (GstVocSchnipselSink *
  93. multifilesink);
  94. static void gst_voc_schnipsel_sink_close_file (GstVocSchnipselSink * multifilesink,
  95. GstBuffer * buffer);
  96. static gboolean gst_voc_schnipsel_sink_write_stream_headers (GstVocSchnipselSink * sink);
  97. static gboolean gst_voc_schnipsel_sink_sink_event (GstPad * pad, GstObject * parent, GstEvent * event);
  98. static GstFlowReturn gst_voc_schnipsel_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buf);
  99. /* GObject vmethod implementations */
  100. /* initialize the vocschnipselsink's class */
  101. static void
  102. gst_voc_schnipsel_sink_class_init (GstVocSchnipselSinkClass * klass)
  103. {
  104. GObjectClass *gobject_class;
  105. GstElementClass *gstelement_class;
  106. GstBaseSinkClass *gstbasesink_class;
  107. gobject_class = (GObjectClass *) klass;
  108. gstelement_class = (GstElementClass *) klass;
  109. gstbasesink_class = (GstBaseSinkClass *) (klass);
  110. gstbasesink_class->set_caps = gst_voc_schnipsel_sink_set_caps;
  111. gobject_class->set_property = gst_voc_schnipsel_sink_set_property;
  112. gobject_class->get_property = gst_voc_schnipsel_sink_get_property;
  113. g_object_class_install_property (gobject_class, PROP_SILENT,
  114. g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
  115. FALSE, G_PARAM_READWRITE));
  116. gst_element_class_set_details_simple(gstelement_class,
  117. "VocSchnipselSink",
  118. "FIXME:Generic",
  119. "FIXME:Generic Template Element",
  120. "Peter Körner <<user@hostname.org>>");
  121. gst_element_class_add_pad_template (gstelement_class,
  122. gst_static_pad_template_get (&sink_factory));
  123. }
  124. /* initialize the new element
  125. * instantiate pads and add them to element
  126. * set pad calback functions
  127. * initialize instance structure
  128. */
  129. static void
  130. gst_voc_schnipsel_sink_init (GstVocSchnipselSink * filter)
  131. {
  132. filter->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
  133. gst_pad_set_event_function (filter->sinkpad,
  134. GST_DEBUG_FUNCPTR(gst_voc_schnipsel_sink_sink_event));
  135. gst_pad_set_chain_function (filter->sinkpad,
  136. GST_DEBUG_FUNCPTR(gst_voc_schnipsel_sink_chain));
  137. GST_PAD_SET_PROXY_CAPS (filter->sinkpad);
  138. gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
  139. filter->silent = FALSE;
  140. filter->frames = 0;
  141. }
  142. static void
  143. gst_voc_schnipsel_sink_set_property (GObject * object, guint prop_id,
  144. const GValue * value, GParamSpec * pspec)
  145. {
  146. GstVocSchnipselSink *filter = GST_VOCSCHNIPSELSINK (object);
  147. switch (prop_id) {
  148. case PROP_SILENT:
  149. filter->silent = g_value_get_boolean (value);
  150. break;
  151. default:
  152. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  153. break;
  154. }
  155. }
  156. static void
  157. gst_voc_schnipsel_sink_get_property (GObject * object, guint prop_id,
  158. GValue * value, GParamSpec * pspec)
  159. {
  160. GstVocSchnipselSink *filter = GST_VOCSCHNIPSELSINK (object);
  161. switch (prop_id) {
  162. case PROP_SILENT:
  163. g_value_set_boolean (value, filter->silent);
  164. break;
  165. default:
  166. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  167. break;
  168. }
  169. }
  170. static gboolean
  171. gst_voc_schnipsel_sink_set_caps (GstBaseSink * sink, GstCaps * caps)
  172. {
  173. GstVocSchnipselSink *vocschnipselsink;
  174. GstStructure *structure;
  175. vocschnipselsink = GST_VOCSCHNIPSELSINK (sink);
  176. structure = gst_caps_get_structure (caps, 0);
  177. if (structure) {
  178. const GValue *value;
  179. value = gst_structure_get_value (structure, "streamheader");
  180. if (GST_VALUE_HOLDS_ARRAY (value)) {
  181. int i;
  182. if (vocschnipselsink->streamheaders) {
  183. for (i = 0; i < vocschnipselsink->n_streamheaders; i++) {
  184. gst_buffer_unref (vocschnipselsink->streamheaders[i]);
  185. }
  186. g_free (vocschnipselsink->streamheaders);
  187. }
  188. vocschnipselsink->n_streamheaders = gst_value_array_get_size (value);
  189. vocschnipselsink->streamheaders =
  190. g_malloc (sizeof (GstBuffer *) * vocschnipselsink->n_streamheaders);
  191. for (i = 0; i < vocschnipselsink->n_streamheaders; i++) {
  192. vocschnipselsink->streamheaders[i] =
  193. gst_buffer_ref (gst_value_get_buffer (gst_value_array_get_value
  194. (value, i)));
  195. }
  196. }
  197. }
  198. return TRUE;
  199. }
  200. /* GstElement vmethod implementations */
  201. /* this function handles sink events */
  202. static gboolean
  203. gst_voc_schnipsel_sink_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
  204. {
  205. gboolean ret;
  206. GstVocSchnipselSink *filter;
  207. filter = GST_VOCSCHNIPSELSINK (parent);
  208. switch (GST_EVENT_TYPE (event)) {
  209. case GST_EVENT_CAPS:
  210. {
  211. GstCaps * caps;
  212. gst_event_parse_caps (event, &caps);
  213. /* do something with the caps */
  214. /* and forward */
  215. ret = gst_pad_event_default (pad, parent, event);
  216. break;
  217. }
  218. default:
  219. ret = gst_pad_event_default (pad, parent, event);
  220. break;
  221. }
  222. return ret;
  223. }
  224. /* chain function
  225. * this function does the actual processing
  226. */
  227. static GstFlowReturn
  228. gst_voc_schnipsel_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
  229. {
  230. GstVocSchnipselSink *sink;
  231. sink = GST_VOCSCHNIPSELSINK (parent);
  232. GstMapInfo map;
  233. gst_buffer_map (buf, &map, GST_MAP_READ);
  234. if (sink->silent == FALSE)
  235. g_print ("buffer of size %zu at pts %zu.\n", gst_buffer_get_size(buf), GST_BUFFER_PTS(buf));
  236. if(++sink->frames > 25 * 5)
  237. {
  238. g_print ("1sec is over, starting new file");
  239. sink->frames = 0;
  240. if (sink->file)
  241. {
  242. gst_voc_schnipsel_sink_close_file (sink, buf);
  243. }
  244. if (!gst_voc_schnipsel_sink_open_next_file (sink))
  245. {
  246. GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
  247. ("Error while writing to file."), ("%s", g_strerror (errno)));
  248. gst_buffer_unmap (buf, &map);
  249. return GST_FLOW_ERROR;
  250. }
  251. gst_voc_schnipsel_sink_write_stream_headers (sink);
  252. }
  253. if (sink->file == NULL) {
  254. if (!gst_voc_schnipsel_sink_open_next_file (sink))
  255. {
  256. GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
  257. ("Error while writing to file."), ("%s", g_strerror (errno)));
  258. gst_buffer_unmap (buf, &map);
  259. return GST_FLOW_ERROR;
  260. }
  261. }
  262. int ret = fwrite (map.data, map.size, 1, sink->file);
  263. if (ret != 1)
  264. {
  265. GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
  266. ("Error while writing to file."), ("%s", g_strerror (errno)));
  267. gst_buffer_unmap (buf, &map);
  268. return GST_FLOW_ERROR;
  269. }
  270. gst_buffer_unmap (buf, &map);
  271. return GST_FLOW_OK;
  272. }
  273. static gboolean
  274. gst_voc_schnipsel_sink_write_stream_headers (GstVocSchnipselSink * sink)
  275. {
  276. int i;
  277. if (sink->streamheaders == NULL)
  278. return TRUE;
  279. for (i = 0; i < sink->n_streamheaders; i++) {
  280. GstBuffer *hdr;
  281. GstMapInfo map;
  282. int ret;
  283. hdr = sink->streamheaders[i];
  284. gst_buffer_map (hdr, &map, GST_MAP_READ);
  285. ret = fwrite (map.data, map.size, 1, sink->file);
  286. gst_buffer_unmap (hdr, &map);
  287. if (ret != 1)
  288. return FALSE;
  289. }
  290. return TRUE;
  291. }
  292. static gboolean
  293. gst_voc_schnipsel_sink_open_next_file (GstVocSchnipselSink * sink)
  294. {
  295. // TODO: prefix
  296. // TODO: number of frames
  297. // TODO: location
  298. char filename[250];
  299. g_return_val_if_fail (sink->file == NULL, FALSE);
  300. //filename = g_strdup_printf (sink->filename, sink->index);
  301. time_t rawtime;
  302. struct tm * timeinfo;
  303. time (&rawtime);
  304. timeinfo = localtime (&rawtime);
  305. strftime(filename, sizeof(filename)/sizeof(*filename), "%Y-%m-%d_%H-%M-%S.ts", timeinfo);
  306. sink->file = fopen (filename, "wb");
  307. if (sink->file == NULL) {
  308. g_free (filename);
  309. return FALSE;
  310. }
  311. GST_INFO_OBJECT (sink, "opening file %s", filename);
  312. return TRUE;
  313. }
  314. static void
  315. gst_voc_schnipsel_sink_close_file (GstVocSchnipselSink * sink,
  316. GstBuffer * buffer)
  317. {
  318. fclose (sink->file);
  319. sink->file = NULL;
  320. }
  321. /* entry point to initialize the plug-in
  322. * initialize the plug-in itself
  323. * register the element factories and other features
  324. */
  325. static gboolean
  326. vocschnipselsink_init (GstPlugin * vocschnipselsink)
  327. {
  328. /* debug category for fltering log messages
  329. *
  330. * exchange the string 'Template vocschnipselsink' with your description
  331. */
  332. GST_DEBUG_CATEGORY_INIT (gst_voc_schnipsel_sink_debug, "vocschnipselsink",
  333. 0, "Template vocschnipselsink");
  334. return gst_element_register (vocschnipselsink, "vocschnipselsink", GST_RANK_NONE,
  335. GST_TYPE_VOCSCHNIPSELSINK);
  336. }
  337. /* PACKAGE: this is usually set by autotools depending on some _INIT macro
  338. * in configure.ac and then written into and defined in config.h, but we can
  339. * just set it ourselves here in case someone doesn't use autotools to
  340. * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined.
  341. */
  342. #ifndef PACKAGE
  343. #define PACKAGE "myfirstvocschnipselsink"
  344. #endif
  345. /* gstreamer looks for this structure to register vocschnipselsinks
  346. *
  347. * exchange the string 'Template vocschnipselsink' with your vocschnipselsink description
  348. */
  349. GST_PLUGIN_DEFINE (
  350. GST_VERSION_MAJOR,
  351. GST_VERSION_MINOR,
  352. vocschnipselsink,
  353. "Template vocschnipselsink",
  354. vocschnipselsink_init,
  355. VERSION,
  356. "LGPL",
  357. "GStreamer",
  358. "http://gstreamer.net/"
  359. )