aboutsummaryrefslogtreecommitdiff
path: root/gst-vocschnipselssink/src/gstvocschnipselsink.c
blob: 6cc62353aa0be44c8de2ebd9dc2800f7833ad8de (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. #define DEFAULT_LOCATION "%Y-%m-%d_%H-%M-%S.ts"
  65. #define DEFAULT_FRAMES (4*60*25)
  66. /* Filter signals and args */
  67. enum
  68. {
  69. /* FILL ME */
  70. LAST_SIGNAL
  71. };
  72. enum
  73. {
  74. PROP_0,
  75. PROP_LOCATION,
  76. PROP_FRAMES
  77. };
  78. /* the capabilities of the inputs and outputs.
  79. *
  80. * describe the real formats here.
  81. */
  82. static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
  83. GST_PAD_SINK,
  84. GST_PAD_ALWAYS,
  85. GST_STATIC_CAPS ("ANY")
  86. );
  87. #define gst_voc_schnipsel_sink_parent_class parent_class
  88. G_DEFINE_TYPE (GstVocSchnipselSink, gst_voc_schnipsel_sink, GST_TYPE_ELEMENT);
  89. static void gst_voc_schnipsel_sink_set_property (GObject * object, guint prop_id,
  90. const GValue * value, GParamSpec * pspec);
  91. static void gst_voc_schnipsel_sink_get_property (GObject * object, guint prop_id,
  92. GValue * value, GParamSpec * pspec);
  93. static gboolean gst_voc_schnipsel_sink_set_caps (GstBaseSink * sink,
  94. GstCaps * caps);
  95. static gboolean gst_voc_schnipsel_sink_open_next_file (GstVocSchnipselSink *
  96. multifilesink);
  97. static void gst_voc_schnipsel_sink_close_file (GstVocSchnipselSink * multifilesink,
  98. GstBuffer * buffer);
  99. static gboolean gst_voc_schnipsel_sink_write_stream_headers (GstVocSchnipselSink * sink);
  100. static gboolean gst_voc_schnipsel_sink_sink_event (GstPad * pad, GstObject * parent, GstEvent * event);
  101. static GstFlowReturn gst_voc_schnipsel_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buf);
  102. /* GObject vmethod implementations */
  103. /* initialize the vocschnipselsink's class */
  104. static void
  105. gst_voc_schnipsel_sink_class_init (GstVocSchnipselSinkClass * klass)
  106. {
  107. GObjectClass *gobject_class;
  108. GstElementClass *gstelement_class;
  109. GstBaseSinkClass *gstbasesink_class;
  110. gobject_class = (GObjectClass *) klass;
  111. gstelement_class = (GstElementClass *) klass;
  112. gstbasesink_class = (GstBaseSinkClass *) (klass);
  113. gstbasesink_class->set_caps = gst_voc_schnipsel_sink_set_caps;
  114. gobject_class->set_property = gst_voc_schnipsel_sink_set_property;
  115. gobject_class->get_property = gst_voc_schnipsel_sink_get_property;
  116. g_object_class_install_property (gobject_class, PROP_LOCATION,
  117. g_param_spec_boolean ("silent", "Silent", "Location of the file to write. Will be processed by strftime, so you can add date/time modifiers. Defaults to " DEFAULT_LOCATION,
  118. FALSE, G_PARAM_READWRITE));
  119. g_object_class_install_property (gobject_class, PROP_FRAMES,
  120. g_param_spec_boolean ("silent", "Silent", "Number of frames sfter which a new File will be started. Defaults to 4*60*25 = 6000 Frames",
  121. FALSE, G_PARAM_READWRITE));
  122. gst_element_class_set_details_simple(gstelement_class,
  123. "VocSchnipselSink",
  124. "FIXME:Generic",
  125. "FIXME:Generic Template Element",
  126. "Peter Körner <<user@hostname.org>>");
  127. gst_element_class_add_pad_template (gstelement_class,
  128. gst_static_pad_template_get (&sink_factory));
  129. }
  130. /* initialize the new element
  131. * instantiate pads and add them to element
  132. * set pad calback functions
  133. * initialize instance structure
  134. */
  135. static void
  136. gst_voc_schnipsel_sink_init (GstVocSchnipselSink * sink)
  137. {
  138. sink->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
  139. gst_pad_set_event_function (sink->sinkpad,
  140. GST_DEBUG_FUNCPTR(gst_voc_schnipsel_sink_sink_event));
  141. gst_pad_set_chain_function (sink->sinkpad,
  142. GST_DEBUG_FUNCPTR(gst_voc_schnipsel_sink_chain));
  143. GST_PAD_SET_PROXY_CAPS (sink->sinkpad);
  144. gst_element_add_pad (GST_ELEMENT (sink), sink->sinkpad);
  145. sink->location = g_strdup (DEFAULT_LOCATION);
  146. sink->maxframes = DEFAULT_FRAMES;
  147. sink->frames = 0;
  148. }
  149. static void
  150. gst_voc_schnipsel_sink_set_property (GObject * object, guint prop_id,
  151. const GValue * value, GParamSpec * pspec)
  152. {
  153. GstVocSchnipselSink *sink = GST_VOCSCHNIPSELSINK (object);
  154. switch (prop_id) {
  155. case PROP_LOCATION:
  156. g_free (sink->location);
  157. sink->location = g_strdup (g_value_get_string (value));
  158. break;
  159. case PROP_FRAMES:
  160. sink->maxframes = g_value_get_uint64 (value);
  161. break;
  162. default:
  163. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  164. break;
  165. }
  166. }
  167. static void
  168. gst_voc_schnipsel_sink_get_property (GObject * object, guint prop_id,
  169. GValue * value, GParamSpec * pspec)
  170. {
  171. GstVocSchnipselSink *sink = GST_VOCSCHNIPSELSINK (object);
  172. switch (prop_id) {
  173. case PROP_LOCATION:
  174. g_value_set_string (value, sink->location);
  175. break;
  176. case PROP_FRAMES:
  177. g_value_set_uint64 (value, sink->maxframes);
  178. break;
  179. default:
  180. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  181. break;
  182. }
  183. }
  184. static gboolean
  185. gst_voc_schnipsel_sink_set_caps (GstBaseSink * sink, GstCaps * caps)
  186. {
  187. GstVocSchnipselSink *vocschnipselsink;
  188. GstStructure *structure;
  189. vocschnipselsink = GST_VOCSCHNIPSELSINK (sink);
  190. structure = gst_caps_get_structure (caps, 0);
  191. if (structure) {
  192. const GValue *value;
  193. value = gst_structure_get_value (structure, "streamheader");
  194. if (GST_VALUE_HOLDS_ARRAY (value)) {
  195. int i;
  196. if (vocschnipselsink->streamheaders) {
  197. for (i = 0; i < vocschnipselsink->n_streamheaders; i++) {
  198. gst_buffer_unref (vocschnipselsink->streamheaders[i]);
  199. }
  200. g_free (vocschnipselsink->streamheaders);
  201. }
  202. vocschnipselsink->n_streamheaders = gst_value_array_get_size (value);
  203. vocschnipselsink->streamheaders =
  204. g_malloc (sizeof (GstBuffer *) * vocschnipselsink->n_streamheaders);
  205. for (i = 0; i < vocschnipselsink->n_streamheaders; i++) {
  206. vocschnipselsink->streamheaders[i] =
  207. gst_buffer_ref (gst_value_get_buffer (gst_value_array_get_value
  208. (value, i)));
  209. }
  210. }
  211. }
  212. return TRUE;
  213. }
  214. /* GstElement vmethod implementations */
  215. /* this function handles sink events */
  216. static gboolean
  217. gst_voc_schnipsel_sink_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
  218. {
  219. gboolean ret;
  220. //GstVocSchnipselSink *filter;
  221. //filter = GST_VOCSCHNIPSELSINK (parent);
  222. switch (GST_EVENT_TYPE (event)) {
  223. case GST_EVENT_CAPS:
  224. {
  225. GstCaps * caps;
  226. gst_event_parse_caps (event, &caps);
  227. /* do something with the caps */
  228. /* and forward */
  229. ret = gst_pad_event_default (pad, parent, event);
  230. break;
  231. }
  232. default:
  233. ret = gst_pad_event_default (pad, parent, event);
  234. break;
  235. }
  236. return ret;
  237. }
  238. /* chain function
  239. * this function does the actual processing
  240. */
  241. static GstFlowReturn
  242. gst_voc_schnipsel_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
  243. {
  244. GstVocSchnipselSink *sink;
  245. sink = GST_VOCSCHNIPSELSINK (parent);
  246. GstMapInfo map;
  247. gst_buffer_map (buf, &map, GST_MAP_READ);
  248. if(++sink->frames > sink->maxframes)
  249. {
  250. sink->frames = 0;
  251. if (sink->file)
  252. {
  253. gst_voc_schnipsel_sink_close_file (sink, buf);
  254. }
  255. if (!gst_voc_schnipsel_sink_open_next_file (sink))
  256. {
  257. GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
  258. ("Error while writing to file."), ("%s", g_strerror (errno)));
  259. gst_buffer_unmap (buf, &map);
  260. return GST_FLOW_ERROR;
  261. }
  262. gst_voc_schnipsel_sink_write_stream_headers (sink);
  263. }
  264. if (sink->file == NULL) {
  265. if (!gst_voc_schnipsel_sink_open_next_file (sink))
  266. {
  267. GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
  268. ("Error while writing to file."), ("%s", g_strerror (errno)));
  269. gst_buffer_unmap (buf, &map);
  270. return GST_FLOW_ERROR;
  271. }
  272. }
  273. int ret = fwrite (map.data, map.size, 1, sink->file);
  274. if (ret != 1)
  275. {
  276. GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
  277. ("Error while writing to file."), ("%s", g_strerror (errno)));
  278. gst_buffer_unmap (buf, &map);
  279. return GST_FLOW_ERROR;
  280. }
  281. gst_buffer_unmap (buf, &map);
  282. return GST_FLOW_OK;
  283. }
  284. static gboolean
  285. gst_voc_schnipsel_sink_write_stream_headers (GstVocSchnipselSink * sink)
  286. {
  287. int i;
  288. if (sink->streamheaders == NULL)
  289. return TRUE;
  290. for (i = 0; i < sink->n_streamheaders; i++) {
  291. GstBuffer *hdr;
  292. GstMapInfo map;
  293. int ret;
  294. hdr = sink->streamheaders[i];
  295. gst_buffer_map (hdr, &map, GST_MAP_READ);
  296. ret = fwrite (map.data, map.size, 1, sink->file);
  297. gst_buffer_unmap (hdr, &map);
  298. if (ret != 1)
  299. return FALSE;
  300. }
  301. return TRUE;
  302. }
  303. static gboolean
  304. gst_voc_schnipsel_sink_open_next_file (GstVocSchnipselSink * sink)
  305. {
  306. char filename[250];
  307. g_return_val_if_fail (sink->file == NULL, FALSE);
  308. time_t rawtime;
  309. struct tm * timeinfo;
  310. time (&rawtime);
  311. timeinfo = localtime (&rawtime);
  312. strftime(filename, sizeof(filename)/sizeof(*filename), sink->location, timeinfo);
  313. printf("new file %s\n", filename);
  314. sink->file = fopen (filename, "wb");
  315. if (sink->file == NULL) {
  316. g_free (filename);
  317. return FALSE;
  318. }
  319. GST_INFO_OBJECT (sink, "opening file %s", filename);
  320. return TRUE;
  321. }
  322. static void
  323. gst_voc_schnipsel_sink_close_file (GstVocSchnipselSink * sink,
  324. GstBuffer * buffer)
  325. {
  326. fclose (sink->file);
  327. sink->file = NULL;
  328. }
  329. /* entry point to initialize the plug-in
  330. * initialize the plug-in itself
  331. * register the element factories and other features
  332. */
  333. static gboolean
  334. vocschnipselsink_init (GstPlugin * vocschnipselsink)
  335. {
  336. /* debug category for fltering log messages
  337. *
  338. * exchange the string 'Template vocschnipselsink' with your description
  339. */
  340. GST_DEBUG_CATEGORY_INIT (gst_voc_schnipsel_sink_debug, "vocschnipselsink",
  341. 0, "Template vocschnipselsink");
  342. return gst_element_register (vocschnipselsink, "vocschnipselsink", GST_RANK_NONE,
  343. GST_TYPE_VOCSCHNIPSELSINK);
  344. }
  345. /* PACKAGE: this is usually set by autotools depending on some _INIT macro
  346. * in configure.ac and then written into and defined in config.h, but we can
  347. * just set it ourselves here in case someone doesn't use autotools to
  348. * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined.
  349. */
  350. #ifndef PACKAGE
  351. #define PACKAGE "myfirstvocschnipselsink"
  352. #endif
  353. /* gstreamer looks for this structure to register vocschnipselsinks
  354. *
  355. * exchange the string 'Template vocschnipselsink' with your vocschnipselsink description
  356. */
  357. GST_PLUGIN_DEFINE (
  358. GST_VERSION_MAJOR,
  359. GST_VERSION_MINOR,
  360. vocschnipselsink,
  361. "Template vocschnipselsink",
  362. vocschnipselsink_init,
  363. VERSION,
  364. "LGPL",
  365. "GStreamer",
  366. "http://gstreamer.net/"
  367. )