[byzanz] Add another GStreamer based encoder for FLV videos.



commit b6e469ca61596ae3f0c590305c8353ce6bd4a4dc
Author: Benjamin Otte <otte gnome org>
Date:   Fri Aug 28 19:32:47 2009 +0200

    Add another GStreamer based encoder for FLV videos.
    
    There's now 3 encoders to chose from (with reason of existance)
    1) GIF (default)
    Good for screencasts where changes don't happen constantly and are
    local, easy to export to the web.
    2) Theora
    Good for screencasts with frequent changes where detail is not that
    important, easy to export to the web.
    3) Flash Screen video
    Lossless encoding (if you want to postprocess in Pitivi), same area of
    usage as GIF, but harder to export to the web (needs a Flash environment
    like Youtube).

 src/Makefile.am              |    4 +
 src/byzanzencoder.c          |    4 +-
 src/byzanzencoderflv.c       |   50 ++++++++++
 src/byzanzencoderflv.h       |   46 +++++++++
 src/byzanzencodergstreamer.c |  223 ++++++++++++++++++++++++++++++++++++++++++
 src/byzanzencodergstreamer.h |   58 +++++++++++
 src/byzanzencoderogv.c       |  190 ++----------------------------------
 src/byzanzencoderogv.h       |   34 +++----
 8 files changed, 403 insertions(+), 206 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 97f9939..c2f9d26 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,7 +9,9 @@ BUILT_SOURCES = \
 
 noinst_HEADERS = \
 	byzanzencoder.h \
+	byzanzencoderflv.h \
 	byzanzencodergif.h \
+	byzanzencodergstreamer.h \
 	byzanzencoderogv.h \
 	byzanzlayer.h \
 	byzanzlayercursor.h \
@@ -22,7 +24,9 @@ noinst_HEADERS = \
 
 libbyzanz_la_SOURCES = \
 	byzanzencoder.c \
+	byzanzencoderflv.c \
 	byzanzencodergif.c \
+	byzanzencodergstreamer.c \
 	byzanzencoderogv.c \
 	byzanzlayer.c \
 	byzanzlayercursor.c \
diff --git a/src/byzanzencoder.c b/src/byzanzencoder.c
index ef2749e..ecde2d2 100644
--- a/src/byzanzencoder.c
+++ b/src/byzanzencoder.c
@@ -396,13 +396,15 @@ byzanz_encoder_type_get_filter (GType encoder_type)
 }
 
 /* all the encoders */
+#include "byzanzencoderflv.h"
 #include "byzanzencodergif.h"
 #include "byzanzencoderogv.h"
 
 typedef GType (* TypeFunc) (void);
 static const TypeFunc functions[] = {
   byzanz_encoder_gif_get_type,
-  byzanz_encoder_ogv_get_type
+  byzanz_encoder_ogv_get_type,
+  byzanz_encoder_flv_get_type
 };
 #define BYZANZ_ENCODER_DEFAULT_TYPE (functions[0] ())
 
diff --git a/src/byzanzencoderflv.c b/src/byzanzencoderflv.c
new file mode 100644
index 0000000..5e539da
--- /dev/null
+++ b/src/byzanzencoderflv.c
@@ -0,0 +1,50 @@
+/* desktop session recorder
+ * Copyright (C) 2009 Benjamin Otte <otte gnome 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 3 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 "byzanzencoderflv.h"
+
+#include <glib/gi18n.h>
+
+G_DEFINE_TYPE (ByzanzEncoderFlv, byzanz_encoder_flv, BYZANZ_TYPE_ENCODER_GSTREAMER)
+
+static void
+byzanz_encoder_flv_class_init (ByzanzEncoderFlvClass *klass)
+{
+  ByzanzEncoderClass *encoder_class = BYZANZ_ENCODER_CLASS (klass);
+  ByzanzEncoderGStreamerClass *gstreamer_class = BYZANZ_ENCODER_GSTREAMER_CLASS (klass);
+
+  encoder_class->filter = gtk_file_filter_new ();
+  g_object_ref_sink (encoder_class->filter);
+  gtk_file_filter_set_name (encoder_class->filter, _("Flash video"));
+  gtk_file_filter_add_mime_type (encoder_class->filter, "video/x-flv");
+  gtk_file_filter_add_pattern (encoder_class->filter, "*.flv");
+
+  gstreamer_class->pipeline_string = 
+    "appsrc name=src ! ffmpegcolorspace ! ffenc_flashsv buffer-size=8388608 ! flvmux ! giostreamsink name=sink";
+}
+
+static void
+byzanz_encoder_flv_init (ByzanzEncoderFlv *encoder_flv)
+{
+}
+
diff --git a/src/byzanzencoderflv.h b/src/byzanzencoderflv.h
new file mode 100644
index 0000000..f1d7a19
--- /dev/null
+++ b/src/byzanzencoderflv.h
@@ -0,0 +1,46 @@
+/* desktop session recorder
+ * Copyright (C) 2009 Benjamin Otte <otte gnome 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 3 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.
+ */
+
+#include "byzanzencodergstreamer.h"
+
+#ifndef __HAVE_BYZANZ_ENCODER_FLV_H__
+#define __HAVE_BYZANZ_ENCODER_FLV_H__
+
+typedef struct _ByzanzEncoderFlv ByzanzEncoderFlv;
+typedef struct _ByzanzEncoderFlvClass ByzanzEncoderFlvClass;
+
+#define BYZANZ_TYPE_ENCODER_FLV                    (byzanz_encoder_flv_get_type())
+#define BYZANZ_IS_ENCODER_FLV(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BYZANZ_TYPE_ENCODER_FLV))
+#define BYZANZ_IS_ENCODER_FLV_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), BYZANZ_TYPE_ENCODER_FLV))
+#define BYZANZ_ENCODER_FLV(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), BYZANZ_TYPE_ENCODER_FLV, ByzanzEncoderFlv))
+#define BYZANZ_ENCODER_FLV_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), BYZANZ_TYPE_ENCODER_FLV, ByzanzEncoderFlvClass))
+#define BYZANZ_ENCODER_FLV_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), BYZANZ_TYPE_ENCODER_FLV, ByzanzEncoderFlvClass))
+
+struct _ByzanzEncoderFlv {
+  ByzanzEncoderGStreamer        encoder;
+};
+
+struct _ByzanzEncoderFlvClass {
+  ByzanzEncoderGStreamerClass   encoder_class;
+};
+
+GType		byzanz_encoder_flv_get_type		(void) G_GNUC_CONST;
+
+
+#endif /* __HAVE_BYZANZ_ENCODER_FLV_H__ */
diff --git a/src/byzanzencodergstreamer.c b/src/byzanzencodergstreamer.c
new file mode 100644
index 0000000..6fc86e9
--- /dev/null
+++ b/src/byzanzencodergstreamer.c
@@ -0,0 +1,223 @@
+/* desktop session recorder
+ * Copyright (C) 2009 Benjamin Otte <otte gnome 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 3 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 "byzanzencodergstreamer.h"
+
+#include <glib/gi18n.h>
+#include <gst/app/gstappbuffer.h>
+#include <gst/video/video.h>
+
+G_DEFINE_TYPE (ByzanzEncoderGStreamer, byzanz_encoder_gstreamer, BYZANZ_TYPE_ENCODER)
+
+#define PIPELINE_STRING "appsrc name=src ! ffmpegcolorspace ! videorate ! video/x-raw-yuv,framerate=25/1 ! theoraenc ! oggmux ! giostreamsink name=sink"
+
+static gboolean
+byzanz_encoder_gstreamer_setup (ByzanzEncoder * encoder,
+                          GOutputStream * stream,
+                          guint           width,
+                          guint           height,
+                          GCancellable *  cancellable,
+                          GError **	  error)
+{
+  ByzanzEncoderGStreamer *gstreamer = BYZANZ_ENCODER_GSTREAMER (encoder);
+  ByzanzEncoderGStreamerClass *klass = BYZANZ_ENCODER_GSTREAMER_GET_CLASS (encoder);
+  GstElement *sink;
+
+  g_assert (klass->pipeline_string);
+  gstreamer->pipeline = gst_parse_launch (klass->pipeline_string, error);
+  if (gstreamer->pipeline == NULL)
+    return FALSE;
+
+  g_assert (GST_IS_PIPELINE (gstreamer->pipeline));
+  gstreamer->src = GST_APP_SRC (gst_bin_get_by_name (GST_BIN (gstreamer->pipeline), "src"));
+  g_assert (GST_IS_APP_SRC (gstreamer->src));
+  sink = gst_bin_get_by_name (GST_BIN (gstreamer->pipeline), "sink");
+  g_assert (sink);
+  g_object_set (sink, "stream", stream, NULL);
+  g_object_unref (sink);
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+  gstreamer->caps = gst_caps_from_string (GST_VIDEO_CAPS_BGRx);
+#elif G_BYTE_ORDER == G_BIG_ENDIAN
+  gstreamer->caps = gst_caps_new_from_string (GST_VIDEO_CAPS_xRGB);
+#else
+#error "Please add the Cairo caps format here"
+#endif
+  gst_caps_set_simple (gstreamer->caps,
+      "width", G_TYPE_INT, width, 
+      "height", G_TYPE_INT, height,
+      "framerate", GST_TYPE_FRACTION, 0, 1, NULL);
+  g_assert (gst_caps_is_fixed (gstreamer->caps));
+
+  gst_app_src_set_caps (gstreamer->src, gstreamer->caps);
+  gst_app_src_set_stream_type (gstreamer->src, GST_APP_STREAM_TYPE_STREAM);
+
+  if (!gst_element_set_state (gstreamer->pipeline, GST_STATE_PLAYING)) {
+    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Failed to start GStreamer pipeline"));
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+byzanz_encoder_gstreamer_got_error (ByzanzEncoderGStreamer *gstreamer, GError **error)
+{
+  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (gstreamer->pipeline));
+  GstMessage *message = gst_bus_pop_filtered (bus, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
+
+  g_object_unref (bus);
+  if (message != NULL) {
+    if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR) {
+      gst_message_parse_error (message, error, NULL);
+    } else {
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Premature end of GStreamer pipeline"));
+    }
+    gst_message_unref (message);
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+byzanz_encoder_gstreamer_process (ByzanzEncoder *   encoder,
+                            GOutputStream *   stream,
+                            cairo_surface_t * surface,
+                            const GdkRegion * region,
+                            const GTimeVal *  total_elapsed,
+                            GCancellable *    cancellable,
+                            GError **	      error)
+{
+  ByzanzEncoderGStreamer *gstreamer = BYZANZ_ENCODER_GSTREAMER (encoder);
+  GstBuffer *buffer;
+
+  if (!byzanz_encoder_gstreamer_got_error (gstreamer, error))
+    return FALSE;
+
+  /* update the surface */
+  if (gstreamer->surface == NULL) {
+    /* just assume that the size is right and pray */
+    gstreamer->surface = cairo_surface_reference (surface);
+    gstreamer->start_time = *total_elapsed;
+  } else {
+    cairo_t *cr;
+
+    if (cairo_surface_get_reference_count (gstreamer->surface) > 1) {
+      cairo_surface_t *copy = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+          cairo_image_surface_get_width (gstreamer->surface), cairo_image_surface_get_height (gstreamer->surface));
+      
+      cr = cairo_create (copy);
+      cairo_set_source_surface (cr, gstreamer->surface, 0, 0);
+      cairo_paint (cr);
+      cairo_destroy (cr);
+
+      cairo_surface_destroy (gstreamer->surface);
+      gstreamer->surface = copy;
+    }
+    cr = cairo_create (gstreamer->surface);
+    cairo_set_source_surface (cr, surface, 0, 0);
+    gdk_cairo_region (cr, region);
+    cairo_fill (cr);
+    cairo_destroy (cr);
+  }
+
+  /* create a buffer and send it */
+  /* FIXME: stride just works? */
+  cairo_surface_reference (gstreamer->surface);
+  buffer = gst_app_buffer_new (cairo_image_surface_get_data (gstreamer->surface),
+      cairo_image_surface_get_stride (gstreamer->surface) * cairo_image_surface_get_height (gstreamer->surface),
+      (GstAppBufferFinalizeFunc) cairo_surface_destroy, gstreamer->surface);
+  GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_READONLY);
+  GST_BUFFER_TIMESTAMP (buffer) = GST_TIMEVAL_TO_TIME (*total_elapsed) - GST_TIMEVAL_TO_TIME (gstreamer->start_time);
+  gst_buffer_set_caps (buffer, gstreamer->caps);
+  gst_app_src_push_buffer (gstreamer->src, buffer);
+
+  return TRUE;
+}
+
+static gboolean
+byzanz_encoder_gstreamer_close (ByzanzEncoder *  encoder,
+                          GOutputStream *  stream,
+                          const GTimeVal * total_elapsed,
+                          GCancellable *   cancellable,
+                          GError **	   error)
+{
+  ByzanzEncoderGStreamer *gstreamer = BYZANZ_ENCODER_GSTREAMER (encoder);
+  GstBus *bus;
+  GstMessage *message;
+
+  gst_app_src_end_of_stream (gstreamer->src);
+
+  bus = gst_pipeline_get_bus (GST_PIPELINE (gstreamer->pipeline));
+  message = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
+
+  if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR) {
+    gst_message_parse_error (message, error, NULL);
+    gst_message_unref (message);
+    return FALSE;
+  }
+  gst_message_unref (message);
+  g_object_unref (bus);
+  gst_element_set_state (gstreamer->pipeline, GST_STATE_NULL);
+
+  return TRUE;
+}
+
+static void
+byzanz_encoder_gstreamer_finalize (GObject *object)
+{
+  ByzanzEncoderGStreamer *gstreamer = BYZANZ_ENCODER_GSTREAMER (object);
+
+  if (gstreamer->pipeline) {
+    gst_element_set_state (gstreamer->pipeline, GST_STATE_NULL);
+    g_object_unref (gstreamer->pipeline);
+  }
+  if (gstreamer->src)
+    g_object_unref (gstreamer->src);
+  if (gstreamer->caps)
+    gst_caps_unref (gstreamer->caps);
+
+  G_OBJECT_CLASS (byzanz_encoder_gstreamer_parent_class)->finalize (object);
+}
+
+static void
+byzanz_encoder_gstreamer_class_init (ByzanzEncoderGStreamerClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  ByzanzEncoderClass *encoder_class = BYZANZ_ENCODER_CLASS (klass);
+
+  gst_init (NULL, NULL);
+
+  object_class->finalize = byzanz_encoder_gstreamer_finalize;
+
+  encoder_class->setup = byzanz_encoder_gstreamer_setup;
+  encoder_class->process = byzanz_encoder_gstreamer_process;
+  encoder_class->close = byzanz_encoder_gstreamer_close;
+}
+
+static void
+byzanz_encoder_gstreamer_init (ByzanzEncoderGStreamer *encoder_gstreamer)
+{
+}
+
diff --git a/src/byzanzencodergstreamer.h b/src/byzanzencodergstreamer.h
new file mode 100644
index 0000000..507a95e
--- /dev/null
+++ b/src/byzanzencodergstreamer.h
@@ -0,0 +1,58 @@
+/* desktop session recorder
+ * Copyright (C) 2009 Benjamin Otte <otte gnome 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 3 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.
+ */
+
+#include "byzanzencoder.h"
+
+#include <gst/gst.h>
+#include <gst/app/gstappsrc.h>
+
+#ifndef __HAVE_BYZANZ_ENCODER_GSTREAMER_H__
+#define __HAVE_BYZANZ_ENCODER_GSTREAMER_H__
+
+typedef struct _ByzanzEncoderGStreamer ByzanzEncoderGStreamer;
+typedef struct _ByzanzEncoderGStreamerClass ByzanzEncoderGStreamerClass;
+
+#define BYZANZ_TYPE_ENCODER_GSTREAMER                    (byzanz_encoder_gstreamer_get_type())
+#define BYZANZ_IS_ENCODER_GSTREAMER(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BYZANZ_TYPE_ENCODER_GSTREAMER))
+#define BYZANZ_IS_ENCODER_GSTREAMER_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), BYZANZ_TYPE_ENCODER_GSTREAMER))
+#define BYZANZ_ENCODER_GSTREAMER(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), BYZANZ_TYPE_ENCODER_GSTREAMER, ByzanzEncoderGStreamer))
+#define BYZANZ_ENCODER_GSTREAMER_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), BYZANZ_TYPE_ENCODER_GSTREAMER, ByzanzEncoderGStreamerClass))
+#define BYZANZ_ENCODER_GSTREAMER_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), BYZANZ_TYPE_ENCODER_GSTREAMER, ByzanzEncoderGStreamerClass))
+
+struct _ByzanzEncoderGStreamer {
+  ByzanzEncoder         encoder;
+
+  cairo_surface_t *     surface;        /* last surface pushed down the pipeline */
+  GTimeVal              start_time;     /* timestamp of first image */
+
+  GstElement *          pipeline;       /* The pipeline */
+  GstAppSrc *           src;            /* the source we feed with images */
+  GstCaps *             caps;           /* caps of video stream */
+};
+
+struct _ByzanzEncoderGStreamerClass {
+  ByzanzEncoderClass    encoder_class;
+
+  const char *          pipeline_string;
+};
+
+GType		byzanz_encoder_gstreamer_get_type		(void) G_GNUC_CONST;
+
+
+#endif /* __HAVE_BYZANZ_ENCODER_GSTREAMER_H__ */
diff --git a/src/byzanzencoderogv.c b/src/byzanzencoderogv.c
index bc8cfc4..c61a67c 100644
--- a/src/byzanzencoderogv.c
+++ b/src/byzanzencoderogv.c
@@ -24,201 +24,25 @@
 #include "byzanzencoderogv.h"
 
 #include <glib/gi18n.h>
-#include <gst/app/gstappbuffer.h>
-#include <gst/video/video.h>
 
-G_DEFINE_TYPE (ByzanzEncoderOgv, byzanz_encoder_ogv, BYZANZ_TYPE_ENCODER)
-
-#define PIPELINE_STRING "appsrc name=src ! ffmpegcolorspace ! videorate ! video/x-raw-yuv,framerate=25/1 ! theoraenc ! oggmux ! giostreamsink name=sink"
-
-static gboolean
-byzanz_encoder_ogv_setup (ByzanzEncoder * encoder,
-                          GOutputStream * stream,
-                          guint           width,
-                          guint           height,
-                          GCancellable *  cancellable,
-                          GError **	  error)
-{
-  ByzanzEncoderOgv *ogv = BYZANZ_ENCODER_OGG (encoder);
-  GstElement *sink;
-
-  ogv->pipeline = gst_parse_launch (PIPELINE_STRING, error);
-  if (ogv->pipeline == NULL)
-    return FALSE;
-
-  g_assert (GST_IS_PIPELINE (ogv->pipeline));
-  ogv->src = GST_APP_SRC (gst_bin_get_by_name (GST_BIN (ogv->pipeline), "src"));
-  g_assert (GST_IS_APP_SRC (ogv->src));
-  sink = gst_bin_get_by_name (GST_BIN (ogv->pipeline), "sink");
-  g_assert (sink);
-  g_object_set (sink, "stream", stream, NULL);
-  g_object_unref (sink);
-
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-  ogv->caps = gst_caps_from_string (GST_VIDEO_CAPS_BGRx);
-#elif G_BYTE_ORDER == G_BIG_ENDIAN
-  ogv->caps = gst_caps_new_from_string (GST_VIDEO_CAPS_xRGB);
-#else
-#error "Please add the Cairo caps format here"
-#endif
-  gst_caps_set_simple (ogv->caps,
-      "width", G_TYPE_INT, width, 
-      "height", G_TYPE_INT, height,
-      "framerate", GST_TYPE_FRACTION, 0, 1, NULL);
-  g_assert (gst_caps_is_fixed (ogv->caps));
-
-  gst_app_src_set_caps (ogv->src, ogv->caps);
-  gst_app_src_set_stream_type (ogv->src, GST_APP_STREAM_TYPE_STREAM);
-
-  if (!gst_element_set_state (ogv->pipeline, GST_STATE_PLAYING)) {
-    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Failed to start GStreamer pipeline"));
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-static gboolean
-byzanz_encoder_ogv_got_error (ByzanzEncoderOgv *ogv, GError **error)
-{
-  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (ogv->pipeline));
-  GstMessage *message = gst_bus_pop_filtered (bus, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
-
-  g_object_unref (bus);
-  if (message != NULL) {
-    if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR) {
-      gst_message_parse_error (message, error, NULL);
-    } else {
-      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Premature end of GStreamer pipeline"));
-    }
-    gst_message_unref (message);
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
-static gboolean
-byzanz_encoder_ogv_process (ByzanzEncoder *   encoder,
-                            GOutputStream *   stream,
-                            cairo_surface_t * surface,
-                            const GdkRegion * region,
-                            const GTimeVal *  total_elapsed,
-                            GCancellable *    cancellable,
-                            GError **	      error)
-{
-  ByzanzEncoderOgv *ogv = BYZANZ_ENCODER_OGG (encoder);
-  GstBuffer *buffer;
-
-  if (!byzanz_encoder_ogv_got_error (ogv, error))
-    return FALSE;
-
-  /* update the surface */
-  if (ogv->surface == NULL) {
-    /* just assume that the size is right and pray */
-    ogv->surface = cairo_surface_reference (surface);
-    ogv->start_time = *total_elapsed;
-  } else {
-    cairo_t *cr;
-
-    if (cairo_surface_get_reference_count (ogv->surface) > 1) {
-      cairo_surface_t *copy = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
-          cairo_image_surface_get_width (ogv->surface), cairo_image_surface_get_height (ogv->surface));
-      
-      cr = cairo_create (copy);
-      cairo_set_source_surface (cr, ogv->surface, 0, 0);
-      cairo_paint (cr);
-      cairo_destroy (cr);
-
-      cairo_surface_destroy (ogv->surface);
-      ogv->surface = copy;
-    }
-    cr = cairo_create (ogv->surface);
-    cairo_set_source_surface (cr, surface, 0, 0);
-    gdk_cairo_region (cr, region);
-    cairo_fill (cr);
-    cairo_destroy (cr);
-  }
-
-  /* create a buffer and send it */
-  /* FIXME: stride just works? */
-  cairo_surface_reference (ogv->surface);
-  buffer = gst_app_buffer_new (cairo_image_surface_get_data (ogv->surface),
-      cairo_image_surface_get_stride (ogv->surface) * cairo_image_surface_get_height (ogv->surface),
-      (GstAppBufferFinalizeFunc) cairo_surface_destroy, ogv->surface);
-  GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_READONLY);
-  GST_BUFFER_TIMESTAMP (buffer) = GST_TIMEVAL_TO_TIME (*total_elapsed) - GST_TIMEVAL_TO_TIME (ogv->start_time);
-  gst_buffer_set_caps (buffer, ogv->caps);
-  gst_app_src_push_buffer (ogv->src, buffer);
-
-  return TRUE;
-}
-
-static gboolean
-byzanz_encoder_ogv_close (ByzanzEncoder *  encoder,
-                          GOutputStream *  stream,
-                          const GTimeVal * total_elapsed,
-                          GCancellable *   cancellable,
-                          GError **	   error)
-{
-  ByzanzEncoderOgv *ogv = BYZANZ_ENCODER_OGG (encoder);
-  GstBus *bus;
-  GstMessage *message;
-
-  gst_app_src_end_of_stream (ogv->src);
-
-  bus = gst_pipeline_get_bus (GST_PIPELINE (ogv->pipeline));
-  message = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
-
-  if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR) {
-    gst_message_parse_error (message, error, NULL);
-    gst_message_unref (message);
-    return FALSE;
-  }
-  gst_message_unref (message);
-  g_object_unref (bus);
-  gst_element_set_state (ogv->pipeline, GST_STATE_NULL);
-
-  return TRUE;
-}
-
-static void
-byzanz_encoder_ogv_finalize (GObject *object)
-{
-  ByzanzEncoderOgv *ogv = BYZANZ_ENCODER_OGG (object);
-
-  if (ogv->pipeline) {
-    gst_element_set_state (ogv->pipeline, GST_STATE_NULL);
-    g_object_unref (ogv->pipeline);
-  }
-  if (ogv->src)
-    g_object_unref (ogv->src);
-  if (ogv->caps)
-    gst_caps_unref (ogv->caps);
-
-  G_OBJECT_CLASS (byzanz_encoder_ogv_parent_class)->finalize (object);
-}
+G_DEFINE_TYPE (ByzanzEncoderOgv, byzanz_encoder_ogv, BYZANZ_TYPE_ENCODER_GSTREAMER)
 
 static void
 byzanz_encoder_ogv_class_init (ByzanzEncoderOgvClass *klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
   ByzanzEncoderClass *encoder_class = BYZANZ_ENCODER_CLASS (klass);
-
-  gst_init (NULL, NULL);
-
-  object_class->finalize = byzanz_encoder_ogv_finalize;
-
-  encoder_class->setup = byzanz_encoder_ogv_setup;
-  encoder_class->process = byzanz_encoder_ogv_process;
-  encoder_class->close = byzanz_encoder_ogv_close;
+  ByzanzEncoderGStreamerClass *gstreamer_class = BYZANZ_ENCODER_GSTREAMER_CLASS (klass);
 
   encoder_class->filter = gtk_file_filter_new ();
   g_object_ref_sink (encoder_class->filter);
-  gtk_file_filter_set_name (encoder_class->filter, _("Theora videos"));
+  gtk_file_filter_set_name (encoder_class->filter, _("Theora video"));
   gtk_file_filter_add_mime_type (encoder_class->filter, "video/ogg");
   gtk_file_filter_add_pattern (encoder_class->filter, "*.ogv");
   gtk_file_filter_add_pattern (encoder_class->filter, "*.ogg");
+
+  gstreamer_class->pipeline_string = 
+    "appsrc name=src ! ffmpegcolorspace ! videorate ! "
+    "video/x-raw-yuv,framerate=25/1 ! theoraenc ! oggmux ! giostreamsink name=sink";
 }
 
 static void
diff --git a/src/byzanzencoderogv.h b/src/byzanzencoderogv.h
index 6337d7f..e741f78 100644
--- a/src/byzanzencoderogv.h
+++ b/src/byzanzencoderogv.h
@@ -17,40 +17,30 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#include "byzanzencoder.h"
+#include "byzanzencodergstreamer.h"
 
-#include <gst/gst.h>
-#include <gst/app/gstappsrc.h>
-
-#ifndef __HAVE_BYZANZ_ENCODER_OGG_H__
-#define __HAVE_BYZANZ_ENCODER_OGG_H__
+#ifndef __HAVE_BYZANZ_ENCODER_OGV_H__
+#define __HAVE_BYZANZ_ENCODER_OGV_H__
 
 typedef struct _ByzanzEncoderOgv ByzanzEncoderOgv;
 typedef struct _ByzanzEncoderOgvClass ByzanzEncoderOgvClass;
 
-#define BYZANZ_TYPE_ENCODER_OGG                    (byzanz_encoder_ogv_get_type())
-#define BYZANZ_IS_ENCODER_OGG(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BYZANZ_TYPE_ENCODER_OGG))
-#define BYZANZ_IS_ENCODER_OGG_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), BYZANZ_TYPE_ENCODER_OGG))
-#define BYZANZ_ENCODER_OGG(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), BYZANZ_TYPE_ENCODER_OGG, ByzanzEncoderOgv))
-#define BYZANZ_ENCODER_OGG_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), BYZANZ_TYPE_ENCODER_OGG, ByzanzEncoderOgvClass))
-#define BYZANZ_ENCODER_OGG_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), BYZANZ_TYPE_ENCODER_OGG, ByzanzEncoderOgvClass))
+#define BYZANZ_TYPE_ENCODER_OGV                    (byzanz_encoder_ogv_get_type())
+#define BYZANZ_IS_ENCODER_OGV(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BYZANZ_TYPE_ENCODER_OGV))
+#define BYZANZ_IS_ENCODER_OGV_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), BYZANZ_TYPE_ENCODER_OGV))
+#define BYZANZ_ENCODER_OGV(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), BYZANZ_TYPE_ENCODER_OGV, ByzanzEncoderOgv))
+#define BYZANZ_ENCODER_OGV_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), BYZANZ_TYPE_ENCODER_OGV, ByzanzEncoderOgvClass))
+#define BYZANZ_ENCODER_OGV_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), BYZANZ_TYPE_ENCODER_OGV, ByzanzEncoderOgvClass))
 
 struct _ByzanzEncoderOgv {
-  ByzanzEncoder         encoder;
-
-  cairo_surface_t *     surface;        /* last surface pushed down the pipeline */
-  GTimeVal              start_time;     /* timestamp of first image */
-
-  GstElement *          pipeline;       /* The pipeline */
-  GstAppSrc *           src;            /* the source we feed with images */
-  GstCaps *             caps;           /* caps of video stream */
+  ByzanzEncoderGStreamer        encoder;
 };
 
 struct _ByzanzEncoderOgvClass {
-  ByzanzEncoderClass    encoder_class;
+  ByzanzEncoderGStreamerClass   encoder_class;
 };
 
 GType		byzanz_encoder_ogv_get_type		(void) G_GNUC_CONST;
 
 
-#endif /* __HAVE_BYZANZ_ENCODER_OGG_H__ */
+#endif /* __HAVE_BYZANZ_ENCODER_OGV_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]