aboutsummaryrefslogtreecommitdiff
path: root/gst-vocschnipselssink/src/gstvocschnipselsink.c
blob: 2d7ef1c1b325f6ab43153e22d7cfc7322d185842 (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 <peter@mazdermind.de>>
  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 ("video/mpegts")
  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_string ("location", "Location", "Location of the file to write. Will be processed by strftime, so you can add date/time modifiers.",
  118. DEFAULT_LOCATION, G_PARAM_READWRITE));
  119. g_object_class_install_property (gobject_class, PROP_FRAMES,
  120. g_param_spec_uint64 ("frames", "Frames", "Number of frames sfter which a new File will be started. Defaults to 4*60*25 = 6000 Frames",
  121. 0, G_MAXUINT64, DEFAULT_FRAMES, 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_element_add_pad (GST_ELEMENT (sink), sink->sinkpad);
  144. sink->location = g_strdup (DEFAULT_LOCATION);
  145. sink->maxframes = DEFAULT_FRAMES;
  146. sink->frames = 0;
  147. }
  148. static void
  149. gst_voc_schnipsel_sink_set_property (GObject * object, guint prop_id,
  150. const GValue * value, GParamSpec * pspec)
  151. {
  152. GstVocSchnipselSink *sink = GST_VOCSCHNIPSELSINK (object);
  153. switch (prop_id) {
  154. case PROP_LOCATION:
  155. g_free (sink->location);
  156. sink->location = g_strdup (g_value_get_string (value));
  157. break;
  158. case PROP_FRAMES:
  159. sink->maxframes = g_value_get_uint64 (value);
  160. break;
  161. default:
  162. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  163. break;
  164. }
  165. }
  166. static void
  167. gst_voc_schnipsel_sink_get_property (GObject * object, guint prop_id,
  168. GValue * value, GParamSpec * pspec)
  169. {
  170. GstVocSchnipselSink *sink = GST_VOCSCHNIPSELSINK (object);
  171. switch (prop_id) {
  172. case PROP_LOCATION:
  173. g_value_set_string (value, sink->location);
  174. break;
  175. case PROP_FRAMES:
  176. g_value_set_uint64 (value, sink->maxframes);
  177. break;
  178. default:
  179. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  180. break;
  181. }
  182. }
  183. static gboolean
  184. gst_voc_schnipsel_sink_set_caps (GstBaseSink * sink, GstCaps * caps)
  185. {
  186. GstVocSchnipselSink *vocschnipselsink;
  187. GstStructure *structure;
  188. vocschnipselsink = GST_VOCSCHNIPSELSINK (sink);
  189. structure = gst_caps_get_structure (caps, 0);
  190. if (structure) {
  191. const GValue *value;
  192. value = gst_structure_get_value (structure, "streamheader");
  193. if (GST_VALUE_HOLDS_ARRAY (value)) {
  194. int i;
  195. if (vocschnipselsink->streamheaders) {
  196. for (i = 0; i < vocschnipselsink->n_streamheaders; i++) {
  197. gst_buffer_unref (vocschnipselsink->streamheaders[i]);
  198. }
  199. g_free (vocschnipselsink->streamheaders);
  200. }
  201. vocschnipselsink->n_streamheaders = gst_value_array_get_size (value);
  202. vocschnipselsink->streamheaders =
  203. g_malloc (sizeof (GstBuffer *) * vocschnipselsink->n_streamheaders);
  204. for (i = 0; i < vocschnipselsink->n_streamheaders; i++) {
  205. vocschnipselsink->streamheaders[i] =
  206. gst_buffer_ref (gst_value_get_buffer (gst_value_array_get_value
  207. (value, i)));
  208. }
  209. }
  210. }
  211. return TRUE;
  212. }
  213. /* GstElement vmethod implementations */
  214. /* this function handles sink events */
  215. static gboolean
  216. gst_voc_schnipsel_sink_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
  217. {
  218. gboolean ret;
  219. //GstVocSchnipselSink *filter;
  220. //filter = GST_VOCSCHNIPSELSINK (parent);
  221. switch (GST_EVENT_TYPE (event)) {
  222. case GST_EVENT_CAPS:
  223. {
  224. GstCaps * caps;
  225. gst_event_parse_caps (event, &caps);
  226. /* do something with the caps */
  227. /* and forward */
  228. ret = gst_pad_event_default (pad, parent, event);
  229. break;
  230. }
  231. default:
  232. ret = gst_pad_event_default (pad, parent, event);
  233. break;
  234. }
  235. return ret;
  236. }
  237. /* chain function
  238. * this function does the actual processing
  239. */
  240. static GstFlowReturn
  241. gst_voc_schnipsel_sink_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
  242. {
  243. GstVocSchnipselSink *sink;
  244. sink = GST_VOCSCHNIPSELSINK (parent);
  245. GstMapInfo map;
  246. gst_buffer_map (buf, &map, GST_MAP_READ);
  247. if(++sink->frames > sink->maxframes)
  248. {
  249. sink->frames = 0;
  250. if (sink->file)
  251. {
  252. gst_voc_schnipsel_sink_close_file (sink, buf);
  253. }
  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. gst_voc_schnipsel_sink_write_stream_headers (sink);
  262. }
  263. if (sink->file == NULL) {
  264. if (!gst_voc_schnipsel_sink_open_next_file (sink))
  265. {
  266. GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
  267. ("Error while writing to file."), ("%s", g_strerror (errno)));
  268. gst_buffer_unmap (buf, &map);
  269. return GST_FLOW_ERROR;
  270. }
  271. }
  272. int ret = fwrite (map.data, map.size, 1, sink->file);
  273. if (ret != 1)
  274. {
  275. GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
  276. ("Error while writing to file."), ("%s", g_strerror (errno)));
  277. gst_buffer_unmap (buf, &map);
  278. return GST_FLOW_ERROR;
  279. }
  280. gst_buffer_unmap (buf, &map);
  281. return GST_FLOW_OK;
  282. }
  283. static gboolean
  284. gst_voc_schnipsel_sink_write_stream_headers (GstVocSchnipselSink * sink)
  285. {
  286. int i;
  287. if (sink->streamheaders == NULL)
  288. return TRUE;
  289. for (i = 0; i < sink->n_streamheaders; i++) {
  290. GstBuffer *hdr;
  291. GstMapInfo map;
  292. int ret;
  293. hdr = sink->streamheaders[i];
  294. gst_buffer_map (hdr, &map, GST_MAP_READ);
  295. ret = fwrite (map.data, map.size, 1, sink->file);
  296. gst_buffer_unmap (hdr, &map);
  297. if (ret != 1)
  298. return FALSE;
  299. }
  300. return TRUE;
  301. }
  302. static gboolean
  303. gst_voc_schnipsel_sink_open_next_file (GstVocSchnipselSink * sink)
  304. {
  305. char filename[250];
  306. g_return_val_if_fail (sink->file == NULL, FALSE);
  307. time_t rawtime;
  308. struct tm * timeinfo;
  309. time (&rawtime);
  310. timeinfo = localtime (&rawtime);
  311. strftime(filename, sizeof(filename)/sizeof(*filename), sink->location, timeinfo);
  312. printf("new file %s\n", filename);
  313. sink->file = fopen (filename, "wb");
  314. if (sink->file == NULL) {
  315. g_free (filename);
  316. return FALSE;
  317. }
  318. GST_INFO_OBJECT (sink, "opening file %s", filename);
  319. return TRUE;
  320. }
  321. static void
  322. gst_voc_schnipsel_sink_close_file (GstVocSchnipselSink * sink,
  323. GstBuffer * buffer)
  324. {
  325. fclose (sink->file);
  326. sink->file = NULL;
  327. }
  328. /* entry point to initialize the plug-in
  329. * initialize the plug-in itself
  330. * register the element factories and other features
  331. */
  332. static gboolean
  333. vocschnipselsink_init (GstPlugin * vocschnipselsink)
  334. {
  335. /* debug category for fltering log messages
  336. *
  337. * exchange the string 'Template vocschnipselsink' with your description
  338. */
  339. GST_DEBUG_CATEGORY_INIT (gst_voc_schnipsel_sink_debug, "vocschnipselsink",
  340. 0, "Template vocschnipselsink");
  341. return gst_element_register (vocschnipselsink, "vocschnipselsink", GST_RANK_NONE,
  342. GST_TYPE_VOCSCHNIPSELSINK);
  343. }
  344. /* PACKAGE: this is usually set by autotools depending on some _INIT macro
  345. * in configure.ac and then written into and defined in config.h, but we can
  346. * just set it ourselves here in case someone doesn't use autotools to
  347. * compile this code. GST_PLUGIN_DEFINE needs PACKAGE to be defined.
  348. */
  349. #ifndef PACKAGE
  350. #define PACKAGE "myfirstvocschnipselsink"
  351. #endif
  352. /* gstreamer looks for this structure to register vocschnipselsinks
  353. *
  354. * exchange the string 'Template vocschnipselsink' with your vocschnipselsink description
  355. */
  356. GST_PLUGIN_DEFINE (
  357. GST_VERSION_MAJOR,
  358. GST_VERSION_MINOR,
  359. vocschnipselsink,
  360. "Template vocschnipselsink",
  361. vocschnipselsink_init,
  362. VERSION,
  363. "LGPL",
  364. "GStreamer",
  365. "http://gstreamer.net/"
  366. )