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);
218 static void gst_timeoverlay_setup(GstVideofilter *videofilter)
220 GstTimeoverlay *timeoverlay;
221 PangoFontDescription *font_description;
222 PangoContext *context;
224 g_return_if_fail(GST_IS_TIMEOVERLAY(videofilter));
225 timeoverlay = GST_TIMEOVERLAY(videofilter);
227 /* if any setup needs to be done, do it here */
229 /* what does this affect? */
230 context = pango_ft2_get_context (100, 100);
232 pango_context_set_language (context, pango_language_from_string ("en_US"));
233 pango_context_set_base_dir (context, PANGO_DIRECTION_LTR);
235 font_description = pango_font_description_new ();
236 pango_font_description_set_family (font_description, g_strdup ("Monospace"));
237 pango_font_description_set_style (font_description, PANGO_STYLE_NORMAL);
238 pango_font_description_set_variant (font_description, PANGO_VARIANT_NORMAL);
239 pango_font_description_set_weight (font_description, PANGO_WEIGHT_NORMAL);
240 pango_font_description_set_stretch (font_description, PANGO_STRETCH_NORMAL);
241 pango_font_description_set_size (font_description, 12 * PANGO_SCALE);
243 pango_context_set_font_description (context, font_description);
245 timeoverlay->context = context;
246 timeoverlay->font_description = font_description;
250 static char *gst_timeoverlay_print_smpte_time(guint64 time)
258 x = rint((time + 500000)*1e-6);
260 hours = floor(x/(60*60*1000));
261 x -= hours*60*60*1000;
262 minutes = floor(x/(60*1000));
263 x -= minutes*60*1000;
264 seconds = floor(x/(1000));
268 return g_strdup_printf("%02d:%02d:%02d.%03d",hours,minutes,seconds,ms);
271 static void gst_timeoverlay_planar411(GstVideofilter *videofilter,
272 void *dest, void *src)
274 GstTimeoverlay *timeoverlay;
277 PangoRectangle logical_rect;
279 int b_height, b_width;
284 g_return_if_fail(GST_IS_TIMEOVERLAY(videofilter));
285 timeoverlay = GST_TIMEOVERLAY(videofilter);
287 width = gst_videofilter_get_input_width(videofilter);
288 height = gst_videofilter_get_input_height(videofilter);
290 width = gst_videofilter_get_input_width(videofilter);
291 height = gst_videofilter_get_input_height(videofilter);
293 layout = pango_layout_new (timeoverlay->context);
294 string = gst_timeoverlay_print_smpte_time(GST_BUFFER_TIMESTAMP(videofilter->in_buf));
295 pango_layout_set_text (layout, string, strlen(string));
298 pango_layout_set_alignment (layout, PANGO_ALIGN_LEFT);
299 pango_layout_set_width (layout, -1);
301 pango_layout_get_extents (layout, NULL, &logical_rect);
302 b_height = PANGO_PIXELS (logical_rect.height);
303 b_width = PANGO_PIXELS (logical_rect.width);
307 memcpy(dest, src, videofilter->from_buf_size);
309 for(i=0;i<b_height;i++){
310 memset(dest + i*width, 0, b_width);
312 for(i=0;i<b_height/2;i++){
313 memset(dest + width*height + i*(width/2), 128, b_width/2);
314 memset(dest + width*height + (width/2)*(height/2) + i*(width/2), 128,
317 bitmap.rows = b_height;
318 bitmap.width = b_width;
319 bitmap.pitch = width;
320 bitmap.buffer = dest;
321 bitmap.num_grays = 256;
322 bitmap.pixel_mode = ft_pixel_mode_grays;
324 pango_ft2_render_layout (&bitmap, layout, 0, 0);