aboutsummaryrefslogtreecommitdiff
path: root/gst-vocschnipselssink/src/gstvocschnipselsink.c
blob: 47d675db64b1aff371864cc4dedd1477d4c7af66 (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->frames > 25 * 5)
  235. {
  236. if (sink->file)
  237. {
  238. gst_voc_schnipsel_sink_close_file (sink, buf);
  239. }
  240. if (!gst_voc_schnipsel_sink_open_next_file (sink))
  241. {
  242. GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
  243. ("Error while writing to file."), ("%s", g_strerror (errno)));
  244. gst_buffer_unmap (buf, &map);
  245. return GST_FLOW_ERROR;
  246. }
  247. gst_voc_schnipsel_sink_write_stream_headers (sink);
  248. }
  249. if (sink->file == NULL) {
  250. if (!gst_voc_schnipsel_sink_open_next_file (sink))
  251. {
  252. GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
  253. ("Error while writing to file."), ("%s", g_strerror (errno)));
  254. gst_buffer_unmap (buf, &map);
  255. return GST_FLOW_ERROR;
  256. }
  257. }
  258. int ret = fwrite (map.data, map.size, 1, sink->file);
  259. if (ret != 1)
  260. {
  261. GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
  262. ("Error while writing to file."), ("%s", g_strerror (errno)));
  263. gst_buffer_unmap (buf, &map);
  264. return GST_FLOW_ERROR;
  265. }
  266. gst_buffer_unmap (buf, &map);
  267. return GST_FLOW_OK;
  268. }
  269. static gboolean
  270. gst_voc_schnipsel_sink_write_stream_headers (GstVocSchnipselSink * sink)
  271. {
  272. int i;
  273. if (sink->streamheaders == NULL)
  274. return TRUE;
  275. for (i = 0; i < sink->n_streamheaders; i++) {
  276. GstBuffer *hdr;
  277. GstMapInfo map;
  278. int ret;
  279. hdr = sink->streamheaders[i];
  280. gst_buffer_map (hdr, &map, GST_MAP_READ);
  281. ret = fwrite (map.data, map.size, 1, sink->file);
  282. gst_buffer_unmap (hdr, &map);
  283. if (ret != 1)
  284. return FALSE;
  285. }
  286. return TRUE;
  287. }
  288. static gboolean
  289. gst_voc_schnipsel_sink_open_next_file (GstVocSchnipselSink * sink)
  290. {
  291. // TODO: prefix
  292. // TODO: number of frames
  293. // TODO: location
  294. char filename[250];
  295. g_return_val_if_fail (sink->file == NULL, FALSE);
  296. //filename = g_strdup_printf (sink->filename, sink->index);
  297. time_t rawtime;
  298. struct tm * timeinfo;
  299. time (&rawtime);
  300. timeinfo = localtime (&rawtime);
  301. strftime(filename, sizeof(filename)/sizeof(*filename), "%Y-%m-%d_%H-%M-%S.ts", timeinfo);
  302. sink->file = fopen (filename, "wb");
  303. if (sink->file == NULL) {
  304. g_free (filename);
  305. return FALSE;
  306. }
  307. GST_INFO_OBJECT (sink, "opening file %s", filename);
  308. return TRUE;
  309. }
  310. static void
  311. gst_voc_schnipsel_sink_close_file (GstVocSchnipselSink * sink,
  312. GstBuffer * buffer)
  313. {
  314. fclose (sink->file);
  315. sink->file = NULL;
  316. }
  317. /* entry point to initialize the plug-in
  318. * initialize the plug-in itself
  319. * register the element factories and other features
  320. */
  321. static gboolean
  322. vocschnipselsink_init (GstPlugin * vocschnipselsink)
  323. {
  324. /* debug category for fltering log messages
  325. *
  326. * exchange the string 'Template vocschnipselsink' with your description
  327. */
  328. GST_DEBUG_CATEGORY_INIT (gst_voc_schnipsel_sink_debug, "vocschnipselsink",
  329. 0, "Template vocschnipselsink");
  330. return gst_element_register (vocschnipselsink, "vocschnipselsink", GST_RANK_NONE,
  331. GST_TYPE_VOCSCHNIPSELSINK);
  332. }
  333. /* PACKAGE: this is usually set by autotools depending on some _INIT macro
  334. * in configure.ac and then written into and defined in config.h, but we can
  335. * just set it ourselves here in case someone doesn't use autotools to
  336. * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined.
  337. */
  338. #ifndef PACKAGE
  339. #define PACKAGE "myfirstvocschnipselsink"
  340. #endif
  341. /* gstreamer looks for this structure to register vocschnipselsinks
  342. *
  343. * exchange the string 'Template vocschnipselsink' with your vocschnipselsink description
  344. */
  345. GST_PLUGIN_DEFINE (
  346. GST_VERSION_MAJOR,
  347. GST_VERSION_MINOR,
  348. vocschnipselsink,
  349. "Template vocschnipselsink",
  350. vocschnipselsink_init,
  351. VERSION,
  352. "LGPL",
  353. "GStreamer",
  354. "http://gstreamer.net/"
  355. )