diff options
author | Thijs Vermeir <thijsvermeir@gmail.com> | 2008-04-01 13:42:55 +0000 |
---|---|---|
committer | Thijs Vermeir <thijsvermeir@gmail.com> | 2008-04-01 13:42:55 +0000 |
commit | eaa8e58f0c93a60b02debbb82bb7b1ec9215ee07 (patch) | |
tree | 64030256faad4cd6d75b66be3687ee015cded681 /gst/subenc | |
parent | b891ea8e813463c9e54113c3c02e8c8ffb3d2f9a (diff) |
Add srt subtitle encoder
Original commit message from CVS:
* configure.ac:
* gst/srtenc/Makefile.am:
* gst/srtenc/gstsrtenc.c:
* gst/srtenc/gstsrtenc.h:
Add srt subtitle encoder
Diffstat (limited to 'gst/subenc')
-rw-r--r-- | gst/subenc/Makefile.am | 10 | ||||
-rw-r--r-- | gst/subenc/gstsrtenc.c | 254 | ||||
-rw-r--r-- | gst/subenc/gstsrtenc.h | 63 |
3 files changed, 327 insertions, 0 deletions
diff --git a/gst/subenc/Makefile.am b/gst/subenc/Makefile.am new file mode 100644 index 000000000..c83b6bb46 --- /dev/null +++ b/gst/subenc/Makefile.am @@ -0,0 +1,10 @@ +plugin_LTLIBRARIES = libgstsrtenc.la + +libgstsrtenc_la_SOURCES = \ + gstsrtenc.c +libgstsrtenc_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(GST_CONTROLLER_CFLAGS) +libgstsrtenc_la_LIBADD = $(GST_BASE_LIBS) $(GST_CONTROLLER_LIBS) +libgstsrtenc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +noinst_HEADERS = \ + gstsrtenc.h diff --git a/gst/subenc/gstsrtenc.c b/gst/subenc/gstsrtenc.c new file mode 100644 index 000000000..715334bea --- /dev/null +++ b/gst/subenc/gstsrtenc.c @@ -0,0 +1,254 @@ +/* GStreamer + * Copyright (C) <2008> Thijs Vermeir <thijsvermeir@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "string.h" + +#include "gstsrtenc.h" +#include <gst/controller/gstcontroller.h> + +GST_DEBUG_CATEGORY_STATIC (srtenc_debug); +#define GST_CAT_DEFAULT srtenc_debug + +enum +{ + ARG_0, + ARG_TIMESTAMP, + ARG_DURATION +}; + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-subtitle")); + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("text/plain; text/x-pango-markup")); + +static GstFlowReturn gst_srtenc_chain (GstPad * pad, GstBuffer * buf); +static gboolean plugin_init (GstPlugin * plugin); +static gchar *gst_srtenc_timeconvertion (GstSrtenc * srtenc, GstBuffer * buf); +static gchar *gst_srtenc_timestamp_to_string (GstClockTime timestamp); +static void gst_srtenc_base_init (gpointer klass); +static void gst_srtenc_class_init (GstSrtencClass * klass); +static void gst_srtenc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_srtenc_init (GstSrtenc * src, GstSrtencClass * klass); +static void gst_srtenc_reset (GstSrtenc * srtenc); +static void gst_srtenc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); + +GST_BOILERPLATE (GstSrtenc, gst_srtenc, GstElement, GST_TYPE_ELEMENT); + +static gchar * +gst_srtenc_timestamp_to_string (GstClockTime timestamp) +{ + guint h = timestamp / (3600 * GST_SECOND); + + timestamp -= h * 3600 * GST_SECOND; + guint m = timestamp / (60 * GST_SECOND); + + timestamp -= m * 60 * GST_SECOND; + guint s = timestamp / GST_SECOND; + + timestamp -= s * GST_SECOND; + guint ms = timestamp / GST_MSECOND; + + return g_strdup_printf ("%.2d:%.2d:%.2d,%.3d", h, m, s, ms); +} + +static gchar * +gst_srtenc_timeconvertion (GstSrtenc * srtenc, GstBuffer * buf) +{ + gchar *start_time = + gst_srtenc_timestamp_to_string (GST_BUFFER_TIMESTAMP (buf) + + srtenc->timestamp); + gchar *stop_time = + gst_srtenc_timestamp_to_string (GST_BUFFER_TIMESTAMP (buf) + + srtenc->timestamp + GST_BUFFER_DURATION (buf) + srtenc->duration); + gchar *string = g_strdup_printf ("%s --> %s\n", start_time, stop_time); + + g_free (start_time); + g_free (stop_time); + return string; +} + +static GstFlowReturn +gst_srtenc_chain (GstPad * pad, GstBuffer * buf) +{ + GstSrtenc *srtenc; + GstBuffer *new_buffer; + gchar *timing; + gchar *string; + + srtenc = GST_SRTENC (gst_pad_get_parent_element (pad)); + gst_object_sync_values (G_OBJECT (srtenc), GST_BUFFER_TIMESTAMP (buf)); + timing = gst_srtenc_timeconvertion (srtenc, buf); + string = g_strdup_printf ("%d\n%s", srtenc->counter++, timing); + g_free (timing); + new_buffer = + gst_buffer_new_and_alloc (strlen (string) + GST_BUFFER_SIZE (buf) + 2); + memcpy (GST_BUFFER_DATA (new_buffer), string, strlen (string)); + memcpy (GST_BUFFER_DATA (new_buffer) + strlen (string), GST_BUFFER_DATA (buf), + GST_BUFFER_SIZE (buf)); + memcpy (GST_BUFFER_DATA (new_buffer) + GST_BUFFER_SIZE (new_buffer) - 2, + "\n\n", 2); + g_free (string); + + gst_buffer_unref (buf); + + return gst_pad_push (srtenc->srcpad, new_buffer); +} + +static void +gst_srtenc_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template)); + + gst_element_class_set_details_simple (element_class, + "Srt encoder", "Codec/Encoder/Subtitle", + "Srt subtitle encoder", "Thijs Vermeir <thijsvermeir@gmail.com>"); +} + +static void +gst_srtenc_reset (GstSrtenc * srtenc) +{ + srtenc->counter = 1; +} + +static GstStateChangeReturn +gst_srtenc_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstSrtenc *srtenc = GST_SRTENC (element); + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_srtenc_reset (srtenc); + break; + default: + break; + } + + return ret; +} + +static void +gst_srtenc_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstSrtenc *srtenc; + + srtenc = GST_SRTENC (object); + + switch (prop_id) { + case ARG_TIMESTAMP: + g_value_set_int64 (value, srtenc->timestamp); + break; + case ARG_DURATION: + g_value_set_int64 (value, srtenc->duration); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_srtenc_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + + GstSrtenc *srtenc; + + srtenc = GST_SRTENC (object); + + switch (prop_id) { + case ARG_TIMESTAMP: + srtenc->timestamp = g_value_get_int64 (value); + break; + case ARG_DURATION: + srtenc->duration = g_value_get_int64 (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_srtenc_class_init (GstSrtencClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_srtenc_set_property); + gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_srtenc_get_property); + + element_class->change_state = GST_DEBUG_FUNCPTR (gst_srtenc_change_state); + + g_object_class_install_property (gobject_class, ARG_TIMESTAMP, + g_param_spec_int64 ("timestamp", "Offset for the starttime", + "Offset for the starttime for the subtitles", G_MININT64, G_MAXINT64, + 0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + g_object_class_install_property (gobject_class, ARG_DURATION, + g_param_spec_int64 ("duration", "Offset for the duration", + "Offset for the duration of the subtitles", G_MININT64, G_MAXINT64, + 0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + GST_DEBUG_CATEGORY_INIT (srtenc_debug, "srtenc", 0, "srt subtitle encoder"); +} + +static void +gst_srtenc_init (GstSrtenc * srtenc, GstSrtencClass * klass) +{ + gst_srtenc_reset (srtenc); + + srtenc->srcpad = gst_pad_new_from_static_template (&src_template, "src"); + gst_element_add_pad (GST_ELEMENT (srtenc), srtenc->srcpad); + srtenc->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink"); + gst_element_add_pad (GST_ELEMENT (srtenc), srtenc->sinkpad); + gst_pad_set_chain_function (srtenc->sinkpad, gst_srtenc_chain); +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "srtenc", GST_RANK_NONE, + GST_TYPE_SRTENC); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "srtenc", + "Srt subtitle encoder", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/subenc/gstsrtenc.h b/gst/subenc/gstsrtenc.h new file mode 100644 index 000000000..0fd865316 --- /dev/null +++ b/gst/subenc/gstsrtenc.h @@ -0,0 +1,63 @@ +/* GStreamer + * Copyright (C) <2008> Thijs Vermeir <thijsvermeir@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_SRTENC_H__ +#define __GST_SRTENC_H__ + +#include <gst/gst.h> + +G_BEGIN_DECLS +#define GST_TYPE_SRTENC \ + (gst_srtenc_get_type()) +#define GST_SRTENC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SRTENC,GstSrtenc)) +#define GST_SRTENC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SRTENC,GstSrtenc)) +#define GST_IS_SRTENC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SRTENC)) +#define GST_IS_SRTENC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SRTENC)) + +typedef struct _GstSrtenc GstSrtenc; +typedef struct _GstSrtencClass GstSrtencClass; + +struct _GstSrtencClass +{ + GstElementClass parent_class; +}; + +struct _GstSrtenc +{ + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + /* properties */ + gint64 timestamp; + gint64 duration; + + /* counter for subtitle entry */ + guint counter; +}; + +GType gst_srtenc_get_type (void); + +G_END_DECLS +#endif |