[gnac] Merged the video part of gnac and gnac-video (libgnac only).



commit 1ac2539150e9fb21d3daa099b3e75fb214122d8a
Author: Benoît Dupasquier <bdupasqu src gnome org>
Date:   Sun Sep 13 20:26:44 2009 +0200

    Merged the video part of gnac and gnac-video (libgnac only).

 libgnac/libgnac-converter.c     |   66 +++++++++++-
 libgnac/libgnac-converter.h     |    2 +
 libgnac/libgnac-gst.c           |  212 +++++++++++++++++++++++++++++++++++----
 libgnac/libgnac-gst.h           |    7 ++
 libgnac/libgnac-metadata-tags.h |   20 ++++
 libgnac/libgnac-metadata.c      |   88 ++++++++++++----
 6 files changed, 347 insertions(+), 48 deletions(-)
---
diff --git a/libgnac/libgnac-converter.c b/libgnac/libgnac-converter.c
index 92eef91..64bc878 100644
--- a/libgnac/libgnac-converter.c
+++ b/libgnac/libgnac-converter.c
@@ -57,7 +57,9 @@ enum
 enum
 {
   PROP_0, 
-  PROP_PIPELINE_DESC,
+  PROP_AUDIO_PIPELINE_DESC,
+  PROP_MUXER_PIPELINE_DESC,
+  PROP_VIDEO_PIPELINE_DESC,
   PROP_STRIP_SPECIAL,
   PROP_RENAME_PATTERN,
   PROP_FOLDER_HIERARCHY,
@@ -82,6 +84,8 @@ struct LibgnacConverterPrivate
 
   gboolean              strip_special;
   gchar                *audio_description;
+  gchar                *muxer_description;
+  gchar                *video_description;
   gchar                *rename_pattern;
   gint                  folder_type;
   gchar                *folder_hierarchy;
@@ -187,10 +191,18 @@ libgnac_converter_get_property(GObject    *object,
 
   switch (property_id) 
   {
-    case PROP_PIPELINE_DESC:
+    case PROP_AUDIO_PIPELINE_DESC:
       g_value_set_string(value, self->priv->audio_description);
     break;
 
+    case PROP_MUXER_PIPELINE_DESC:
+      g_value_set_string(value, self->priv->muxer_description);
+    break;
+
+    case PROP_VIDEO_PIPELINE_DESC:
+      g_value_set_string(value, self->priv->video_description);
+    break;
+
     case PROP_STRIP_SPECIAL:
       g_value_set_boolean(value, self->priv->strip_special);
     break;
@@ -237,12 +249,24 @@ libgnac_converter_set_property(GObject      *object,
 
   switch (property_id) 
   {
-    case PROP_PIPELINE_DESC:
+    case PROP_AUDIO_PIPELINE_DESC:
       g_free(self->priv->audio_description);
       self->priv->audio_description = NULL;
       self->priv->audio_description = g_value_dup_string(value);
     break;
 
+    case PROP_MUXER_PIPELINE_DESC:
+      g_free(self->priv->muxer_description);
+      self->priv->muxer_description = NULL;
+      self->priv->muxer_description = g_value_dup_string(value);
+    break;
+
+    case PROP_VIDEO_PIPELINE_DESC:
+      g_free(self->priv->video_description);
+      self->priv->video_description = NULL;
+      self->priv->video_description = g_value_dup_string(value);
+    break;
+
     case PROP_STRIP_SPECIAL:
       self->priv->strip_special = g_value_get_boolean(value);
     break;
@@ -308,7 +332,7 @@ libgnac_converter_class_init(LibgnacConverterClass *klass)
   gobject_class->set_property = libgnac_converter_set_property;
   gobject_class->get_property = libgnac_converter_get_property;
 
-  /* Pipeline desc */
+  /* Audio pipeline desc */
   pspec = g_param_spec_string("audio-description",
                               "Audio pipeline description",
                               "Audio pipeline description",
@@ -316,7 +340,29 @@ libgnac_converter_class_init(LibgnacConverterClass *klass)
                               G_PARAM_READWRITE);
 
   g_object_class_install_property(gobject_class, 
-                                  PROP_PIPELINE_DESC,
+                                  PROP_AUDIO_PIPELINE_DESC,
+                                  pspec);
+
+  /* Muxer pipeline desc */
+  pspec = g_param_spec_string("muxer-description",
+                              "Muxer pipeline description",
+                              "Muxer pipeline description",
+                              NULL,
+                              G_PARAM_READWRITE);
+
+  g_object_class_install_property(gobject_class,
+                                  PROP_MUXER_PIPELINE_DESC,
+                                  pspec);
+
+  /* Video pipeline desc */
+  pspec = g_param_spec_string("video-description",
+                              "Video pipeline description",
+                              "Video pipeline description",
+                              NULL,
+                              G_PARAM_READWRITE);
+
+  g_object_class_install_property(gobject_class,
+                                  PROP_VIDEO_PIPELINE_DESC,
                                   pspec);
 
   /* Folder hierarchy */
@@ -810,11 +856,19 @@ void
 libgnac_converter_item_build(LibgnacConverterItem  *item, 
                              GError               **error)
 {
+  gboolean has_video = FALSE;
   GError *err = NULL;
+  LibgnacTags *tags;
+
   g_return_if_fail(error == NULL || *error == NULL);
 
+  /* is it a video file? */
+  tags = libgnac_metadata_extract(metadata, item->source, NULL);
+  if (tags && libgnac_metadata_tag_exists(tags, GNAC_TAG_HAS_VIDEO)) {
+    has_video = TRUE;
+  }
 
-  libgnac_gst_build_pipeline(item, &err);
+  libgnac_gst_build_pipeline(item, has_video, &err);
   if (err) {
     libgnac_debug("Unable to build pipeline");
     libgnac_gst_clean_pipeline(item);
diff --git a/libgnac/libgnac-converter.h b/libgnac/libgnac-converter.h
index e8e6e84..d2f488c 100644
--- a/libgnac/libgnac-converter.h
+++ b/libgnac/libgnac-converter.h
@@ -93,6 +93,8 @@ typedef struct
   GFile              *destination;
   GstElement         *pipeline;
   GstElement         *audio_encoder;
+  GstElement         *muxer;
+  GstElement         *video_encoder;
   GstBus             *bus;
   guint               timeout_id;
   gint64              pos;
diff --git a/libgnac/libgnac-gst.c b/libgnac/libgnac-gst.c
index 3d6fe45..a2b6753 100644
--- a/libgnac/libgnac-gst.c
+++ b/libgnac/libgnac-gst.c
@@ -75,10 +75,12 @@ libgnac_gst_stop(LibgnacConverterItem  *item,
 GstElement *
 libgnac_gst_make_pipeline_element(GstElement   *bin,
                                   const gchar  *element,
+                                  const gchar  *name,
                                   GError      **error)
 {
   GstElement *elem;
-  elem = gst_element_factory_make(element, NULL);
+
+  elem = gst_element_factory_make(element, name);
   if (!elem) {
     libgnac_debug("Failed to create %s element", element);
     g_set_error(error,
@@ -89,7 +91,16 @@ libgnac_gst_make_pipeline_element(GstElement   *bin,
     return NULL;
   }
 
-  gst_bin_add(GST_BIN(bin), elem);
+  if (!gst_bin_add(GST_BIN(bin), elem)) {
+    libgnac_debug("Failed to add %s element to the bin", element);
+    g_set_error(error,
+        LIBGNAC_ERROR,
+        LIBGNAC_ERROR_PIPELINE_CREATION,
+        _("Failed to add %s element"),
+        element);
+    return NULL;
+  }
+
   return elem;
 }
 
@@ -113,6 +124,29 @@ libgnac_gst_pipeline_new(GError **error)
 
 
 gboolean
+libgnac_gst_bin_add(GstElement  *bin,
+                    GstElement  *elem,
+                    GError     **error)
+{
+  gchar *name;
+
+  name = gst_element_get_name(elem);
+
+  if (!gst_bin_add(GST_BIN(bin), elem)) {
+    libgnac_debug("Failed to add %s element to the bin", name);
+    g_set_error(error,
+        LIBGNAC_ERROR,
+        LIBGNAC_ERROR_PIPELINE_CREATION,
+        _("Failed to add %s element"),
+        name);
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+
+gboolean
 libgnac_gst_element_link(GstElement  *src,
                          GstElement  *dst,
                          GError     **error)
@@ -206,13 +240,14 @@ libgnac_gst_get_audio_bin(LibgnacConverterItem  *item,
 
   g_object_get(G_OBJECT(item->converter), "audio-description", &descr, NULL);
 
-  conv = libgnac_gst_make_pipeline_element(bin, "audioconvert", error);
+  conv = libgnac_gst_make_pipeline_element(bin, "audioconvert", NULL, error);
   g_return_val_if_fail(conv, NULL);
 
-  resample = libgnac_gst_make_pipeline_element(bin, "audioresample", error);
+  resample = libgnac_gst_make_pipeline_element(bin, "audioresample",
+      NULL, error);
   g_return_val_if_fail(resample, NULL);
 
-  rate = libgnac_gst_make_pipeline_element(bin, "audiorate", error);
+  rate = libgnac_gst_make_pipeline_element(bin, "audiorate", NULL, error);
   g_return_val_if_fail(rate, NULL);
 
   enc = gst_parse_bin_from_description(descr, TRUE, error);
@@ -236,8 +271,52 @@ libgnac_gst_get_audio_bin(LibgnacConverterItem  *item,
 }
 
 
+static GstElement *
+libgnac_gst_get_video_bin(LibgnacConverterItem  *item,
+                          GError               **error)
+{
+  gchar      *descr;
+  GstElement *bin;
+  GstElement *conv;
+  GstElement *enc;
+  GstElement *rate;
+  GstPad     *pad;
+
+  bin = gst_bin_new("video_bin");
+
+  g_object_get(G_OBJECT(item->converter), "video-description", &descr, NULL);
+
+  conv = libgnac_gst_make_pipeline_element(bin, "ffmpegcolorspace",
+      NULL, error);
+  g_return_val_if_fail(conv, NULL);
+
+  rate = libgnac_gst_make_pipeline_element(bin, "videorate", NULL, error);
+  g_return_val_if_fail(rate, NULL);
+
+  enc = gst_parse_bin_from_description(descr, TRUE, error);
+  g_free(descr);
+  g_return_val_if_fail(enc && gst_bin_add(GST_BIN(bin), enc), NULL);
+
+  g_return_val_if_fail(
+      gst_element_link_many(conv, rate, enc, NULL),
+      NULL);
+
+  /* ghost pads */
+  pad = gst_element_get_static_pad(conv, "sink");
+  libgnac_gst_element_add_ghost_pad(bin, pad, "video_sink");
+  gst_object_unref(pad);
+
+  pad = gst_element_get_static_pad(enc, "src");
+  libgnac_gst_element_add_ghost_pad(bin, pad, "src");
+  gst_object_unref(pad);
+
+  return bin;
+}
+
+
 void
-libgnac_gst_build_pipeline(LibgnacConverterItem  *item, 
+libgnac_gst_build_pipeline(LibgnacConverterItem  *item,
+                           gboolean               has_video,
                            GError               **error)
 {
   gboolean    linked;
@@ -249,12 +328,14 @@ libgnac_gst_build_pipeline(LibgnacConverterItem  *item,
 
   g_return_if_fail(!error || !*error);
 
+  /* pipeline */
   item->pipeline = libgnac_gst_pipeline_new(&encoder_error);
   if (encoder_error) {
     g_propagate_error(error, encoder_error);
     return;
   }
 
+  /* output */
   libgnac_output_build_output(item, &encoder_error);
   if (encoder_error) {
     libgnac_debug("Output creation failed");
@@ -262,10 +343,12 @@ libgnac_gst_build_pipeline(LibgnacConverterItem  *item,
     return;
   }
 
+  /* bus */
   item->bus = gst_element_get_bus(GST_ELEMENT(item->pipeline));
   gst_bus_add_signal_watch(item->bus);
 
-  source = libgnac_gst_make_pipeline_element(item->pipeline, "giosrc",
+ /* source */
+  source = libgnac_gst_make_pipeline_element(item->pipeline, "giosrc", NULL,
       &encoder_error);
   if (encoder_error) {
     g_propagate_error(error, encoder_error);
@@ -273,13 +356,22 @@ libgnac_gst_build_pipeline(LibgnacConverterItem  *item,
   }
   g_object_set(G_OBJECT(source), "file", item->source, NULL);
 
+  /* decodebin */
   decodebin = libgnac_gst_make_pipeline_element(item->pipeline, "decodebin",
-      &encoder_error);
+      NULL, &encoder_error);
   if (encoder_error) {
     g_propagate_error(error, encoder_error);
     return;
   }
 
+  linked = libgnac_gst_element_link(source, decodebin, &encoder_error);
+  if (encoder_error) {
+    libgnac_debug("link source->decodebin failed");
+    g_propagate_error(error, encoder_error);
+    return;
+  }
+
+  /* audio_bin */
   audio_bin = libgnac_gst_get_audio_bin(item, &encoder_error);
   if (encoder_error) {
     libgnac_debug("audio_bin creation failed");
@@ -288,28 +380,104 @@ libgnac_gst_build_pipeline(LibgnacConverterItem  *item,
   }
 
   item->audio_encoder = audio_bin;
-  gst_bin_add(GST_BIN(item->pipeline), audio_bin);
 
-  sink = libgnac_gst_make_pipeline_element(item->pipeline, "giosink",
-      &encoder_error);
+  libgnac_gst_bin_add(item->pipeline, audio_bin, &encoder_error);
   if (encoder_error) {
     g_propagate_error(error, encoder_error);
     return;
   }
-  g_object_set(G_OBJECT(sink), "file", item->destination, NULL);
 
-  linked = libgnac_gst_element_link(source, decodebin, &encoder_error);
+  /* sink */
+  sink = libgnac_gst_make_pipeline_element(item->pipeline, "giosink", NULL,
+      &encoder_error);
   if (encoder_error) {
-    libgnac_debug("link source->decodebin failed");
     g_propagate_error(error, encoder_error);
     return;
   }
+  g_object_set(G_OBJECT(sink), "file", item->destination, NULL);
 
-  linked = libgnac_gst_element_link(audio_bin, sink, &encoder_error);
-  if (encoder_error) {
-    libgnac_debug("link encoder->sink failed");
-    g_propagate_error(error, encoder_error);
-    return;
+  if (has_video)
+  {
+    gchar *muxer_descr;
+    GstElement *audio_queue;
+    GstElement *mux;
+    GstElement *video_bin;
+    GstElement *video_queue;
+
+    /* muxer */
+    g_object_get(G_OBJECT(item->converter), "muxer-description",
+        &muxer_descr, NULL);
+    mux = libgnac_gst_make_pipeline_element(item->pipeline, muxer_descr,
+        NULL, &encoder_error);
+    g_free(muxer_descr);
+    if (encoder_error) {
+      g_propagate_error(error, encoder_error);
+      return;
+    }
+    item->muxer = mux;
+
+    linked = libgnac_gst_element_link(mux, sink, &encoder_error);
+    if (encoder_error) {
+      libgnac_debug("link encoder->sink failed");
+      g_propagate_error(error, encoder_error);
+      return;
+    }
+
+    /* audio */
+    audio_queue = libgnac_gst_make_pipeline_element(item->pipeline, "queue",
+        "audio_queue", &encoder_error);
+    if (encoder_error) {
+      g_propagate_error(error, encoder_error);
+      return;
+    }
+    item->audio_encoder = audio_queue;
+
+    if (!gst_element_link_many(audio_queue, audio_bin, mux, NULL)) {
+      g_set_error(error,
+          LIBGNAC_ERROR,
+          LIBGNAC_ERROR_PIPELINE_CREATION,
+          _("Failed to link many audio elements"));
+      return;
+    }
+
+    /* video */
+    video_queue = libgnac_gst_make_pipeline_element(item->pipeline, "queue",
+        "video_queue", &encoder_error);
+    if (encoder_error) {
+      g_propagate_error(error, encoder_error);
+      return;
+    }
+    item->video_encoder = video_queue;
+
+    video_bin = libgnac_gst_get_video_bin(item, &encoder_error);
+    if (encoder_error) {
+      libgnac_debug("video_bin creation failed");
+      g_propagate_error(error, encoder_error);
+      return;
+    }
+
+    libgnac_gst_bin_add(item->pipeline, video_bin, &encoder_error);
+    if (encoder_error) {
+      g_propagate_error(error, encoder_error);
+      return;
+    }
+
+    if (!gst_element_link_many(video_queue, video_bin, mux, NULL)) {
+      g_set_error(error,
+          LIBGNAC_ERROR,
+          LIBGNAC_ERROR_PIPELINE_CREATION,
+          _("Failed to link many video elements"));
+      return;
+    }
+  }
+  else /* audio file */
+  {
+    linked = libgnac_gst_element_link(audio_bin, sink, &encoder_error);
+    if (encoder_error) {
+      libgnac_debug("link encoder->sink failed");
+      g_propagate_error(error, encoder_error);
+      return;
+    }
   }
 
   /* Connect callbacks */
@@ -382,7 +550,11 @@ libgnac_gst_newpad_cb(GstElement *decodebin,
       return;
     }
 	} else if (g_str_has_prefix(mimetype, "video/")) {
-    /* contains video data */
+	  if (!libgnac_gst_get_compatible_pad(item->video_encoder, pad,
+        caps, "video"))
+    {
+      return;
+    }
 	} else {
     /* unhandled mimetype */
 	}
diff --git a/libgnac/libgnac-gst.h b/libgnac/libgnac-gst.h
index df99b03..48ff54e 100644
--- a/libgnac/libgnac-gst.h
+++ b/libgnac/libgnac-gst.h
@@ -53,6 +53,7 @@ libgnac_gst_pause(LibgnacConverterItem  *item,
 
 void
 libgnac_gst_build_pipeline(LibgnacConverterItem  *item,
+                           gboolean               has_video,
                            GError               **error);
 
 void
@@ -61,6 +62,7 @@ libgnac_gst_clean_pipeline(LibgnacConverterItem *item);
 GstElement *
 libgnac_gst_make_pipeline_element(GstElement   *bin,
                                   const gchar  *element,
+                                  const gchar  *name,
                                   GError      **error);
 
 GstPadLinkReturn
@@ -72,6 +74,11 @@ GstElement *
 libgnac_gst_pipeline_new(GError **error);
 
 gboolean
+libgnac_gst_bin_add(GstElement  *bin,
+                    GstElement  *elem,
+                    GError     **error);
+
+gboolean
 libgnac_gst_element_link(GstElement  *src,
                          GstElement  *dst,
                          GError     **error);
diff --git a/libgnac/libgnac-metadata-tags.h b/libgnac/libgnac-metadata-tags.h
index 9cc8bc9..9d70d2d 100644
--- a/libgnac/libgnac-metadata-tags.h
+++ b/libgnac/libgnac-metadata-tags.h
@@ -38,8 +38,12 @@ typedef GHashTable LibgnacTags;
 #define GNAC_TAG_CHANNELS   "channels"
 #define GNAC_TAG_FILENAME   "filename"
 #define GNAC_TAG_FILE_SIZE  "file-size"
+#define GNAC_TAG_FRAMERATE  "framerate"
+#define GNAC_TAG_HAS_VIDEO  "has-video"
+#define GNAC_TAG_HEIGHT     "height"
 #define GNAC_TAG_MODE       "mode"
 #define GNAC_TAG_RATE       "rate"
+#define GNAC_TAG_WIDTH      "width"
 
 #define LIBGNAC_METADATA_TAG_IS_ALBUM(tag) \
     (g_str_equal((tag), GST_TAG_ALBUM))
@@ -65,8 +69,14 @@ typedef GHashTable LibgnacTags;
     (g_str_equal((tag), GNAC_TAG_FILE_SIZE))
 #define LIBGNAC_METADATA_TAG_IS_FILENAME(tag) \
     (g_str_equal((tag), GNAC_TAG_FILENAME))
+#define LIBGNAC_METADATA_TAG_IS_FRAMERATE(tag) \
+    (g_str_equal((tag), GNAC_TAG_FRAMERATE))
 #define LIBGNAC_METADATA_TAG_IS_GENRE(tag) \
     (g_str_equal((tag), GST_TAG_GENRE))
+#define LIBGNAC_METADATA_TAG_IS_HAS_VIDEO(tag) \
+    (g_str_equal((tag), GNAC_TAG_HAS_VIDEO))
+#define LIBGNAC_METADATA_TAG_IS_HEIGHT(tag) \
+    (g_str_equal((tag), GNAC_TAG_HEIGHT))
 #define LIBGNAC_METADATA_TAG_IS_IMAGE(tag) \
     (g_str_equal((tag), GST_TAG_IMAGE))
 #define LIBGNAC_METADATA_TAG_IS_LOCATION(tag) \
@@ -85,6 +95,8 @@ typedef GHashTable LibgnacTags;
     (g_str_equal((tag), GST_TAG_TRACK_GAIN))
 #define LIBGNAC_METADATA_TAG_IS_TRACK_PEAK(tag) \
     (g_str_equal((tag), GST_TAG_TRACK_PEAK))
+#define LIBGNAC_METADATA_TAG_IS_WIDTH(tag) \
+    (g_str_equal((tag), GNAC_TAG_WIDTH))
 
 #define LIBGNAC_METADATA_TAG_ALBUM(tags) \
     (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_ALBUM))
@@ -110,8 +122,14 @@ typedef GHashTable LibgnacTags;
     (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_FILE_SIZE))
 #define LIBGNAC_METADATA_TAG_FILENAME(tags) \
     (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_FILENAME))
+#define LIBGNAC_METADATA_TAG_FRAMERATE(tags) \
+    (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_FRAMERATE))
 #define LIBGNAC_METADATA_TAG_GENRE(tags) \
     (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_GENRE))
+#define LIBGNAC_METADATA_TAG_HAS_VIDEO(tags) \
+    (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_HAS_VIDEO))
+#define LIBGNAC_METADATA_TAG_HEIGHT(tags) \
+    (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_HEIGHT))
 #define LIBGNAC_METADATA_TAG_IMAGE(tags) \
     (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_IMAGE))
 #define LIBGNAC_METADATA_TAG_LOCATION(tags) \
@@ -126,6 +144,8 @@ typedef GHashTable LibgnacTags;
     (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_TRACK_COUNT))
 #define LIBGNAC_METADATA_TAG_TRACK_NUMBER(tags) \
     (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_TRACK_NUMBER))
+#define LIBGNAC_METADATA_TAG_WIDTH(tags) \
+    (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_WIDTH))
 
 G_END_DECLS
 
diff --git a/libgnac/libgnac-metadata.c b/libgnac/libgnac-metadata.c
index cd5af07..48076b5 100644
--- a/libgnac/libgnac-metadata.c
+++ b/libgnac/libgnac-metadata.c
@@ -54,6 +54,7 @@ struct LibgnacMetadataPrivate
   LibgnacTags *metadata;
 
   gboolean eos;
+
   GError *error;
 };
 
@@ -255,6 +256,50 @@ libgnac_metadata_process_tag_image(const GstTagList *taglist,
 
 
 static void
+libgnac_metadata_process_tag_value(GstStructure    *structure,
+                                   gchar           *tag_name,
+                                   LibgnacMetadata *md)
+{
+  const GValue *val;
+  val = gst_structure_get_value(structure, tag_name);
+  if (val)
+  {
+    if (GST_VALUE_HOLDS_FRACTION(val))
+    {
+      GValue *newval;
+      gint numerator;
+      gint denominator;
+
+      numerator = gst_value_get_fraction_numerator(val);
+      denominator = gst_value_get_fraction_denominator(val);
+
+      newval = g_new0(GValue, 1);
+      g_value_init(newval, G_TYPE_FLOAT);
+      g_value_set_float(newval, (gfloat)numerator/denominator);
+      g_hash_table_insert(md->priv->metadata, tag_name, newval);
+    }
+  }
+}
+
+
+static void
+libgnac_metadata_process_tag_int(GstStructure    *structure,
+                                 gchar           *tag_name,
+                                 LibgnacMetadata *md)
+{
+  gint int_val;
+  if (gst_structure_get_int(structure, tag_name, &int_val))
+  {
+    GValue *val;
+    val = g_new0(GValue, 1);
+    g_value_init(val, G_TYPE_INT);
+    g_value_set_int(val, int_val);
+    g_hash_table_insert(md->priv->metadata, tag_name, val);
+  }
+}
+
+
+static void
 libgnac_metadata_process_tag(const GstTagList *taglist, 
                              const gchar      *tag_name, 
                              LibgnacMetadata  *md)
@@ -446,11 +491,17 @@ libgnac_metadata_new_decoded_pad_cb(GstElement      *element,
   structure = gst_caps_get_structure(caps, 0);
   mimetype = gst_structure_get_name(structure);
 
-  if (!g_strrstr(mimetype, "audio")) 
+  if (g_str_has_prefix(mimetype, "video"))
   {
-    gst_caps_unref(caps);
-    gst_object_unref(sink_pad);
-    return;
+    GValue *val;
+    val = g_new0(GValue, 1);
+    g_value_init(val, G_TYPE_BOOLEAN);
+    g_value_set_boolean(val, TRUE);
+    g_hash_table_insert(md->priv->metadata, GNAC_TAG_HAS_VIDEO, val);
+  }
+  else if (!g_str_has_prefix(mimetype, "audio"))
+  {
+    libgnac_debug("Got a non audio or video pad: %s", mimetype);
   }
 
   gst_caps_unref(caps);
@@ -464,8 +515,7 @@ libgnac_metadata_autoplug_continue_cb(GstElement      *decodebin,
                                       GstCaps         *caps,
                                       LibgnacMetadata *md)
 {
-  gint rate, channels;
-  GValue *rate_value, *channels_value;
+  const gchar *mimetype;
   GstStructure *structure;
 
   g_return_val_if_fail(LIBGNAC_IS_METADATA(md), TRUE);
@@ -473,21 +523,15 @@ libgnac_metadata_autoplug_continue_cb(GstElement      *decodebin,
   if (!gst_caps_is_fixed(caps)) return TRUE;
 
   structure = gst_caps_get_structure(caps, 0);
+  mimetype = gst_structure_get_name(structure);
 
-  /* sample rate */
-  if (gst_structure_get_int(structure, GNAC_TAG_RATE, &rate)) {
-    rate_value = g_new0(GValue, 1);
-    g_value_init(rate_value, G_TYPE_INT);
-    g_value_set_int(rate_value, rate);
-    g_hash_table_insert(md->priv->metadata, GNAC_TAG_RATE, rate_value);
-  }
+  libgnac_metadata_process_tag_int(structure, GNAC_TAG_RATE, md);
+  libgnac_metadata_process_tag_int(structure, GNAC_TAG_CHANNELS, md);
 
-  /* channels */
-  if (gst_structure_get_int(structure, GNAC_TAG_CHANNELS, &channels)) {
-    channels_value = g_new0(GValue, 1);
-    g_value_init(channels_value, G_TYPE_INT);
-    g_value_set_int(channels_value, channels);
-    g_hash_table_insert(md->priv->metadata, GNAC_TAG_CHANNELS, channels_value);
+  if (g_str_has_prefix(mimetype, "video")) {
+    libgnac_metadata_process_tag_int(structure, GNAC_TAG_HEIGHT, md);
+    libgnac_metadata_process_tag_int(structure, GNAC_TAG_WIDTH, md);
+    libgnac_metadata_process_tag_value(structure, GNAC_TAG_FRAMERATE, md);
   }
 
   return TRUE;
@@ -578,7 +622,7 @@ libgnac_metadata_extract(LibgnacMetadata  *md,
     }
 
     source = libgnac_gst_make_pipeline_element(pipeline, "giosrc",
-        &metadata_error);
+        NULL, &metadata_error);
     if (metadata_error) {
       libgnac_debug("source creation failed");
       g_propagate_error(error, metadata_error);
@@ -587,14 +631,14 @@ libgnac_metadata_extract(LibgnacMetadata  *md,
     g_object_set(G_OBJECT(source), "file", md->priv->uri, NULL);
 
     decodebin = libgnac_gst_make_pipeline_element(pipeline, "decodebin2",
-        &metadata_error);
+        NULL, &metadata_error);
     if (metadata_error) {
       g_propagate_error(error, metadata_error);
       return NULL;
     }
 
     md->priv->sink = libgnac_gst_make_pipeline_element(pipeline, "fakesink",
-        &metadata_error);
+        NULL, &metadata_error);
     if (metadata_error) {
       g_propagate_error(error, metadata_error);
       return NULL;



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