gstreamer/ext/cairo/gsttimeoverlay.c
David Schleef 0163a876c0 configure.ac: add audioresample and cairo plugins. Remove
Original commit message from CVS:
* configure.ac: add audioresample and cairo plugins.  Remove
HAVE_MMX stuff, because it's not used.
* ext/Makefile.am: same
* ext/audioresample/Makefile.am: You are not ready for an
audio resampling element based on audioresample.
* ext/audioresample/gstaudioresample.c:
* ext/audioresample/gstaudioresample.h:
* ext/cairo/Makefile.am: You are not ready for overlay elements
based on cairo.  Don't look too closely, these elements kinda
suck right now.
* ext/cairo/gstcairo.c: new
* ext/cairo/gsttextoverlay.c: new
* ext/cairo/gsttextoverlay.h: new
* ext/cairo/gsttimeoverlay.c: new
* ext/cairo/gsttimeoverlay.h: new
* gst-libs/gst/media-info/media-info-priv.h: fix compile
problem with compilers that don't support variadic macros.
2004-12-16 05:32:07 +00:00

306 lines
8.1 KiB
C

/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* Copyright (C) <2003> David Schleef <ds@schleef.org>
*
* 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.
*/
/*
* This file was (probably) generated from gsttimeoverlay.c,
* gsttimeoverlay.c,v 1.7 2003/11/08 02:48:59 dschleef Exp
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/*#define DEBUG_ENABLED */
#include <gsttimeoverlay.h>
#include <string.h>
#include <math.h>
#include <cairo.h>
/* GstTimeoverlay signals and args */
enum
{
/* FILL ME */
LAST_SIGNAL
};
enum
{
ARG_0
/* FILL ME */
};
static void gst_timeoverlay_base_init (gpointer g_class);
static void gst_timeoverlay_class_init (gpointer g_class, gpointer class_data);
static void gst_timeoverlay_init (GTypeInstance * instance, gpointer g_class);
static void gst_timeoverlay_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_timeoverlay_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static void gst_timeoverlay_planar411 (GstVideofilter * videofilter, void *dest,
void *src);
static void gst_timeoverlay_setup (GstVideofilter * videofilter);
GType
gst_timeoverlay_get_type (void)
{
static GType timeoverlay_type = 0;
if (!timeoverlay_type) {
static const GTypeInfo timeoverlay_info = {
sizeof (GstTimeoverlayClass),
gst_timeoverlay_base_init,
NULL,
gst_timeoverlay_class_init,
NULL,
NULL,
sizeof (GstTimeoverlay),
0,
gst_timeoverlay_init,
};
timeoverlay_type = g_type_register_static (GST_TYPE_VIDEOFILTER,
"GstTimeoverlay", &timeoverlay_info, 0);
}
return timeoverlay_type;
}
static GstVideofilterFormat gst_timeoverlay_formats[] = {
{"I420", 12, gst_timeoverlay_planar411,},
};
static void
gst_timeoverlay_base_init (gpointer g_class)
{
static GstElementDetails timeoverlay_details =
GST_ELEMENT_DETAILS ("Time Overlay",
"Filter/Editor/Video",
"Overlays the time on a video stream",
"David Schleef <ds@schleef.org>");
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
GstVideofilterClass *videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
int i;
gst_element_class_set_details (element_class, &timeoverlay_details);
for (i = 0; i < G_N_ELEMENTS (gst_timeoverlay_formats); i++) {
gst_videofilter_class_add_format (videofilter_class,
gst_timeoverlay_formats + i);
}
gst_videofilter_class_add_pad_templates (GST_VIDEOFILTER_CLASS (g_class));
}
static void
gst_timeoverlay_class_init (gpointer g_class, gpointer class_data)
{
GObjectClass *gobject_class;
GstVideofilterClass *videofilter_class;
gobject_class = G_OBJECT_CLASS (g_class);
videofilter_class = GST_VIDEOFILTER_CLASS (g_class);
#if 0
g_object_class_install_property (gobject_class, ARG_METHOD,
g_param_spec_enum ("method", "method", "method",
GST_TYPE_TIMEOVERLAY_METHOD, GST_TIMEOVERLAY_METHOD_1,
G_PARAM_READWRITE));
#endif
gobject_class->set_property = gst_timeoverlay_set_property;
gobject_class->get_property = gst_timeoverlay_get_property;
videofilter_class->setup = gst_timeoverlay_setup;
}
static void
gst_timeoverlay_init (GTypeInstance * instance, gpointer g_class)
{
GstTimeoverlay *timeoverlay = GST_TIMEOVERLAY (instance);
GstVideofilter *videofilter;
GST_DEBUG ("gst_timeoverlay_init");
videofilter = GST_VIDEOFILTER (timeoverlay);
/* do stuff */
}
static void
gst_timeoverlay_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstTimeoverlay *src;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_TIMEOVERLAY (object));
src = GST_TIMEOVERLAY (object);
GST_DEBUG ("gst_timeoverlay_set_property");
switch (prop_id) {
#if 0
case ARG_METHOD:
src->method = g_value_get_enum (value);
break;
#endif
default:
break;
}
}
static void
gst_timeoverlay_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec)
{
GstTimeoverlay *src;
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_TIMEOVERLAY (object));
src = GST_TIMEOVERLAY (object);
switch (prop_id) {
#if 0
case ARG_METHOD:
g_value_set_enum (value, src->method);
break;
#endif
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_timeoverlay_setup (GstVideofilter * videofilter)
{
GstTimeoverlay *timeoverlay;
cairo_font_extents_t font_extents;
g_return_if_fail (GST_IS_TIMEOVERLAY (videofilter));
timeoverlay = GST_TIMEOVERLAY (videofilter);
/* if any setup needs to be done, do it here */
timeoverlay->cr = cairo_create ();
cairo_set_rgb_color (timeoverlay->cr, 0, 0, 0);
cairo_select_font (timeoverlay->cr, "monospace", 0, 0);
cairo_scale_font (timeoverlay->cr, 20);
cairo_current_font_extents (timeoverlay->cr, &font_extents);
timeoverlay->text_height = font_extents.height;
}
static char *
gst_timeoverlay_print_smpte_time (guint64 time)
{
int hours;
int minutes;
int seconds;
int ms;
double x;
x = rint ((time + 500000) * 1e-6);
hours = floor (x / (60 * 60 * 1000));
x -= hours * 60 * 60 * 1000;
minutes = floor (x / (60 * 1000));
x -= minutes * 60 * 1000;
seconds = floor (x / (1000));
x -= seconds * 1000;
ms = rint (x);
return g_strdup_printf ("%02d:%02d:%02d.%03d", hours, minutes, seconds, ms);
}
static void
gst_timeoverlay_planar411 (GstVideofilter * videofilter, void *dest, void *src)
{
GstTimeoverlay *timeoverlay;
int width;
int height;
int b_width;
char *string;
int i, j;
uint8_t *image;
cairo_text_extents_t extents;
g_return_if_fail (GST_IS_TIMEOVERLAY (videofilter));
timeoverlay = GST_TIMEOVERLAY (videofilter);
width = gst_videofilter_get_input_width (videofilter);
height = gst_videofilter_get_input_height (videofilter);
string =
gst_timeoverlay_print_smpte_time (GST_BUFFER_TIMESTAMP (videofilter->
in_buf));
image = g_malloc (4 * width * timeoverlay->text_height);
cairo_set_target_image (timeoverlay->cr, image, CAIRO_FORMAT_ARGB32,
width, timeoverlay->text_height, width * 4);
cairo_save (timeoverlay->cr);
cairo_rectangle (timeoverlay->cr, 0, 0, width, timeoverlay->text_height);
cairo_set_alpha (timeoverlay->cr, 0);
cairo_set_operator (timeoverlay->cr, CAIRO_OPERATOR_SRC);
cairo_fill (timeoverlay->cr);
cairo_restore (timeoverlay->cr);
cairo_save (timeoverlay->cr);
cairo_text_extents (timeoverlay->cr, string, &extents);
cairo_set_rgb_color (timeoverlay->cr, 1, 1, 1);
cairo_move_to (timeoverlay->cr, 0, timeoverlay->text_height - 2);
cairo_show_text (timeoverlay->cr, string);
g_free (string);
#if 0
cairo_text_path (timeoverlay->cr, string);
cairo_set_rgb_color (timeoverlay->cr, 1, 1, 1);
cairo_set_line_width (timeoverlay->cr, 1.0);
cairo_stroke (timeoverlay->cr);
#endif
cairo_restore (timeoverlay->cr);
b_width = extents.width;
if (b_width > width)
b_width = width;
memcpy (dest, src, videofilter->from_buf_size);
for (i = 0; i < timeoverlay->text_height; i++) {
for (j = 0; j < b_width; j++) {
((uint8_t *) dest)[i * width + j] = image[(i * width + j) * 4 + 0];
}
}
for (i = 0; i < timeoverlay->text_height / 2; i++) {
memset (dest + width * height + i * (width / 2), 128, b_width / 2);
memset (dest + width * height + (width / 2) * (height / 2) +
i * (width / 2), 128, b_width / 2);
}
g_free (image);
}