2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) <2003> David Schleef <ds@schleef.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
21 /* portions derived from:
23 * pangoft2topgm.c: Example program to view a UTF-8 encoding file
24 * using Pango to render result.
26 * Copyright (C) 1999 Red Hat Software
27 * Copyright (C) 2001 Sun Microsystems
31 * This file was (probably) generated from gsttimeoverlay.c,
32 * gsttimeoverlay.c,v 1.7 2003/11/08 02:48:59 dschleef Exp
39 /*#define DEBUG_ENABLED */
40 #include <gsttimeoverlay.h>
43 #include <pango/pango.h>
44 #include <pango/pangoft2.h>
47 /* GstTimeoverlay signals and args */
58 static void gst_timeoverlay_base_init (gpointer g_class);
59 static void gst_timeoverlay_class_init (gpointer g_class, gpointer class_data);
60 static void gst_timeoverlay_init (GTypeInstance *instance, gpointer g_class);
62 static void gst_timeoverlay_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
63 static void gst_timeoverlay_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
65 static void gst_timeoverlay_planar411(GstVideofilter *videofilter, void *dest, void *src);
66 static void gst_timeoverlay_setup(GstVideofilter *videofilter);
69 gst_timeoverlay_get_type (void)
71 static GType timeoverlay_type = 0;
73 if (!timeoverlay_type) {
74 static const GTypeInfo timeoverlay_info = {
75 sizeof(GstTimeoverlayClass),
76 gst_timeoverlay_base_init,
78 gst_timeoverlay_class_init,
81 sizeof(GstTimeoverlay),
85 timeoverlay_type = g_type_register_static(GST_TYPE_VIDEOFILTER,
86 "GstTimeoverlay", &timeoverlay_info, 0);
88 return timeoverlay_type;
91 static GstVideofilterFormat gst_timeoverlay_formats[] = {
92 { "I420", 12, gst_timeoverlay_planar411, },
97 gst_timeoverlay_base_init (gpointer g_class)
99 static GstElementDetails timeoverlay_details = GST_ELEMENT_DETAILS (
101 "Filter/Editor/Video",
102 "Overlays the time on a video stream",
103 "David Schleef <ds@schleef.org>"
105 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
106 GstVideofilterClass *videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
109 gst_element_class_set_details (element_class, &timeoverlay_details);
111 for(i=0;i<G_N_ELEMENTS(gst_timeoverlay_formats);i++){
112 gst_videofilter_class_add_format(videofilter_class,
113 gst_timeoverlay_formats + i);
116 gst_videofilter_class_add_pad_templates (GST_VIDEOFILTER_CLASS (g_class));
120 gst_timeoverlay_class_init (gpointer g_class, gpointer class_data)
122 GObjectClass *gobject_class;
123 GstVideofilterClass *videofilter_class;
125 gobject_class = G_OBJECT_CLASS (g_class);
126 videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
129 g_object_class_install_property(gobject_class, ARG_METHOD,
130 g_param_spec_enum("method","method","method",
131 GST_TYPE_TIMEOVERLAY_METHOD, GST_TIMEOVERLAY_METHOD_1,
135 gobject_class->set_property = gst_timeoverlay_set_property;
136 gobject_class->get_property = gst_timeoverlay_get_property;
138 videofilter_class->setup = gst_timeoverlay_setup;
142 gst_timeoverlay_init (GTypeInstance *instance, gpointer g_class)
144 GstTimeoverlay *timeoverlay = GST_TIMEOVERLAY (instance);
145 GstVideofilter *videofilter;
147 GST_DEBUG("gst_timeoverlay_init");
149 videofilter = GST_VIDEOFILTER(timeoverlay);
155 gst_timeoverlay_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
159 /* it's not null if we got it, but it might not be ours */
160 g_return_if_fail(GST_IS_TIMEOVERLAY(object));
161 src = GST_TIMEOVERLAY(object);
163 GST_DEBUG("gst_timeoverlay_set_property");
167 src->method = g_value_get_enum (value);
176 gst_timeoverlay_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
180 /* it's not null if we got it, but it might not be ours */
181 g_return_if_fail(GST_IS_TIMEOVERLAY(object));
182 src = GST_TIMEOVERLAY(object);
187 g_value_set_enum (value, src->method);
191 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
196 static gboolean plugin_init (GstPlugin *plugin)
198 if(!gst_library_load("gstvideofilter"))
201 return gst_element_register (plugin, "timeoverlay", GST_RANK_NONE,
202 GST_TYPE_TIMEOVERLAY);
217 static void gst_timeoverlay_setup(GstVideofilter *videofilter)
219 GstTimeoverlay *timeoverlay;
220 PangoFontDescription *font_description;
221 PangoContext *context;
223 g_return_if_fail(GST_IS_TIMEOVERLAY(videofilter));
224 timeoverlay = GST_TIMEOVERLAY(videofilter);
226 /* if any setup needs to be done, do it here */
228 /* what does this affect? */
229 context = pango_ft2_get_context (100, 100);
231 pango_context_set_language (context, pango_language_from_string ("en_US"));
232 pango_context_set_base_dir (context, PANGO_DIRECTION_LTR);
234 font_description = pango_font_description_new ();
235 pango_font_description_set_family (font_description, g_strdup ("Monospace"));
236 pango_font_description_set_style (font_description, PANGO_STYLE_NORMAL);
237 pango_font_description_set_variant (font_description, PANGO_VARIANT_NORMAL);
238 pango_font_description_set_weight (font_description, PANGO_WEIGHT_NORMAL);
239 pango_font_description_set_stretch (font_description, PANGO_STRETCH_NORMAL);
240 pango_font_description_set_size (font_description, 12 * PANGO_SCALE);
242 pango_context_set_font_description (context, font_description);
244 timeoverlay->context = context;
245 timeoverlay->font_description = font_description;
249 static char *gst_timeoverlay_print_smpte_time(guint64 time)
257 x = rint((time + 500000)*1e-6);
259 hours = floor(x/(60*60*1000));
260 x -= hours*60*60*1000;
261 minutes = floor(x/(60*1000));
262 x -= minutes*60*1000;
263 seconds = floor(x/(1000));
267 return g_strdup_printf("%02d:%02d:%02d.%03d",hours,minutes,seconds,ms);
270 static void gst_timeoverlay_planar411(GstVideofilter *videofilter,
271 void *dest, void *src)
273 GstTimeoverlay *timeoverlay;
276 PangoRectangle logical_rect;
278 int b_height, b_width;
283 g_return_if_fail(GST_IS_TIMEOVERLAY(videofilter));
284 timeoverlay = GST_TIMEOVERLAY(videofilter);
286 width = gst_videofilter_get_input_width(videofilter);
287 height = gst_videofilter_get_input_height(videofilter);
289 width = gst_videofilter_get_input_width(videofilter);
290 height = gst_videofilter_get_input_height(videofilter);
292 layout = pango_layout_new (timeoverlay->context);
293 string = gst_timeoverlay_print_smpte_time(GST_BUFFER_TIMESTAMP(videofilter->in_buf));
294 pango_layout_set_text (layout, string, strlen(string));
297 pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT);
298 pango_layout_set_width (layout, -1);
300 pango_layout_get_extents (layout, NULL, &logical_rect);
301 b_height = PANGO_PIXELS (logical_rect.height);
302 b_width = PANGO_PIXELS (logical_rect.width);
306 memcpy(dest, src, videofilter->from_buf_size);
308 for(i=0;i<b_height;i++){
309 memset(dest + i*width, 0, b_width);
311 for(i=0;i<b_height/2;i++){
312 memset(dest + width*height + i*(width/2), 128, b_width/2);
313 memset(dest + width*height + (width/2)*(height/2) + i*(width/2), 128,
316 bitmap.rows = b_height;
317 bitmap.width = b_width;
318 bitmap.pitch = width;
319 bitmap.buffer = dest;
320 bitmap.num_grays = 256;
321 bitmap.pixel_mode = ft_pixel_mode_grays;
323 pango_ft2_render_layout (&bitmap, layout, 0, 0);