gst/mxf/: Add property to select the top-level source package or material package...
authorSebastian Dröge <slomo@circular-chaos.org>
Sun, 30 Nov 2008 17:26:55 +0000 (17:26 +0000)
committerSebastian Dröge <slomo@circular-chaos.org>
Sun, 30 Nov 2008 17:26:55 +0000 (17:26 +0000)
Original commit message from CVS:
* gst/mxf/mxfdemux.c: (gst_mxf_demux_remove_pads),
(gst_mxf_demux_reset), (gst_mxf_demux_find_package),
(gst_mxf_demux_choose_package),
(gst_mxf_demux_handle_header_metadata_update_streams),
(gst_mxf_demux_handle_klv_packet), (gst_mxf_demux_set_property),
(gst_mxf_demux_get_property), (gst_mxf_demux_finalize),
(gst_mxf_demux_class_init):
* gst/mxf/mxfdemux.h:
* gst/mxf/mxfparse.c: (mxf_umid_from_string):
* gst/mxf/mxfparse.h:
Add property to select the top-level source package or material
package that should be used for playback.

ChangeLog
gst/mxf/mxfdemux.c
gst/mxf/mxfdemux.h
gst/mxf/mxfparse.c
gst/mxf/mxfparse.h

index 77feb1a..cc3e423 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
 2008-11-30  Sebastian Dröge  <sebastian.droege@collabora.co.uk>
 
+       * gst/mxf/mxfdemux.c: (gst_mxf_demux_remove_pads),
+       (gst_mxf_demux_reset), (gst_mxf_demux_find_package),
+       (gst_mxf_demux_choose_package),
+       (gst_mxf_demux_handle_header_metadata_update_streams),
+       (gst_mxf_demux_handle_klv_packet), (gst_mxf_demux_set_property),
+       (gst_mxf_demux_get_property), (gst_mxf_demux_finalize),
+       (gst_mxf_demux_class_init):
+       * gst/mxf/mxfdemux.h:
+       * gst/mxf/mxfparse.c: (mxf_umid_from_string):
+       * gst/mxf/mxfparse.h:
+       Add property to select the top-level source package or material
+       package that should be used for playback.
+
+2008-11-30  Sebastian Dröge  <sebastian.droege@collabora.co.uk>
+
        * gst/mxf/mxfdemux.c: (gst_mxf_demux_pull_random_index_pack):
        Make sure that demux->offset has the correct value before
        calling any gst_mxf_demux_handle_* functions.
index 68d65ca..7572688 100644 (file)
@@ -138,6 +138,12 @@ gst_mxf_pad_init (GstMXFPad * pad)
   pad->last_flow = GST_FLOW_OK;
 }
 
+enum
+{
+  PROP_0,
+  PROP_PACKAGE
+};
+
 static gboolean gst_mxf_demux_sink_event (GstPad * pad, GstEvent * event);
 static gboolean gst_mxf_demux_src_event (GstPad * pad, GstEvent * event);
 static const GstQueryType *gst_mxf_demux_src_query_type (GstPad * pad);
@@ -168,6 +174,17 @@ gst_mxf_demux_remove_pad (GstMXFPad * pad, GstMXFDemux * demux)
 }
 
 static void
+gst_mxf_demux_remove_pads (GstMXFDemux * demux)
+{
+  if (demux->src) {
+    g_ptr_array_foreach (demux->src, (GFunc) gst_mxf_demux_remove_pad, demux);
+    g_ptr_array_foreach (demux->src, (GFunc) gst_object_unref, NULL);
+    g_ptr_array_free (demux->src, TRUE);
+    demux->src = NULL;
+  }
+}
+
+static void
 gst_mxf_demux_reset_mxf_state (GstMXFDemux * demux)
 {
   GST_DEBUG_OBJECT (demux, "Resetting MXF state");
@@ -384,12 +401,7 @@ gst_mxf_demux_reset (GstMXFDemux * demux)
 
   gst_adapter_clear (demux->adapter);
 
-  if (demux->src) {
-    g_ptr_array_foreach (demux->src, (GFunc) gst_mxf_demux_remove_pad, demux);
-    g_ptr_array_foreach (demux->src, (GFunc) gst_object_unref, NULL);
-    g_ptr_array_free (demux->src, TRUE);
-    demux->src = NULL;
-  }
+  gst_mxf_demux_remove_pads (demux);
 
   if (demux->partition_index) {
     g_array_free (demux->partition_index, TRUE);
@@ -1293,8 +1305,9 @@ gst_mxf_demux_handle_header_metadata_resolve_references (GstMXFDemux * demux)
           MXFMetadataEssenceContainerData, i);
 
       for (j = 0; j < demux->content_storage.n_essence_container_data; j++) {
-        if (mxf_ul_is_equal (&demux->content_storage.
-                essence_container_data_uids[j], &data->instance_uid)) {
+        if (mxf_ul_is_equal (&demux->
+                content_storage.essence_container_data_uids[j],
+                &data->instance_uid)) {
           demux->content_storage.essence_container_data[j] = data;
           break;
         }
@@ -1608,62 +1621,88 @@ error:
   return ret;
 }
 
-static GstFlowReturn
-gst_mxf_demux_handle_header_metadata_update_streams (GstMXFDemux * demux)
+static MXFMetadataGenericPackage *
+gst_mxf_demux_find_package (GstMXFDemux * demux, const MXFUMID * umid)
 {
-  MXFMetadataGenericPackage *current_package = NULL;
-  guint i, j, k;
-  gboolean first_run;
+  MXFMetadataGenericPackage *ret = NULL;
+  guint i;
 
-  GST_DEBUG_OBJECT (demux, "Updating streams");
+  if (demux->package) {
+    for (i = 0; i < demux->package->len; i++) {
+      MXFMetadataGenericPackage *p = g_ptr_array_index (demux->package, i);
 
-choose_package:
-  /* If no package was selected, select the first material package */
-  if (mxf_umid_is_zero (&demux->current_package_uid)
-      && !demux->material_package) {
-    GST_ERROR_OBJECT (demux, "No material package");
-    return GST_FLOW_ERROR;
-  } else if (mxf_umid_is_zero (&demux->current_package_uid)) {
-    MXFMetadataGenericPackage *p =
-        (MXFMetadataGenericPackage *) demux->material_package->data;
-    memcpy (&demux->current_package_uid, &p->package_uid, 32);
-    current_package = p;
-    if (demux->src) {
-      for (i = 0; i < demux->src->len; i++) {
-        GstMXFPad *pad = g_ptr_array_index (demux->src, i);
-        gst_element_remove_pad (GST_ELEMENT_CAST (demux), GST_PAD_CAST (pad));
-        gst_object_unref (pad);
+      if (mxf_umid_is_equal (&p->package_uid, umid)) {
+        ret = p;
+        break;
       }
-      g_ptr_array_free (demux->src, TRUE);
-      demux->src = NULL;
     }
   }
 
-  if (!current_package && demux->package) {
-    for (i = 0; i < demux->package->len; i++) {
-      MXFMetadataGenericPackage *p = g_ptr_array_index (demux->package, i);
+  return ret;
+}
 
-      if (mxf_umid_is_equal (&p->package_uid, &demux->current_package_uid)) {
-        current_package = p;
-        break;
+static MXFMetadataGenericPackage *
+gst_mxf_demux_choose_package (GstMXFDemux * demux)
+{
+  MXFMetadataGenericPackage *ret = NULL;
+
+  if (demux->requested_package_string) {
+    MXFUMID umid;
+
+    if (!mxf_umid_from_string (demux->requested_package_string, &umid)) {
+      GST_ERROR_OBJECT (demux, "Invalid requested package");
+    } else {
+      if (memcmp (&umid, &demux->current_package_uid, 32) != 0) {
+        if (demux->src)
+          gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
+        gst_mxf_demux_remove_pads (demux);
+        memcpy (&demux->current_package_uid, &umid, 32);
       }
     }
+    g_free (demux->requested_package_string);
+    demux->requested_package_string = NULL;
   }
 
-  if (!current_package) {
+  if (!mxf_umid_is_zero (&demux->current_package_uid))
+    ret = gst_mxf_demux_find_package (demux, &demux->current_package_uid);
+  if (ret && (ret->type == MXF_METADATA_GENERIC_PACKAGE_TOP_LEVEL_SOURCE
+          || ret->type == MXF_METADATA_GENERIC_PACKAGE_MATERIAL))
+    return ret;
+  else if (ret && ret->type == MXF_METADATA_GENERIC_PACKAGE_SOURCE)
     GST_WARNING_OBJECT (demux,
-        "Selected package not found in header metadata, choosing the first best");
-    memset (&demux->current_package_uid, 0, sizeof (MXFUMID));
-    goto choose_package;
-  }
-
-  if (current_package->type == MXF_METADATA_GENERIC_PACKAGE_SOURCE) {
+        "Current package is not a material package or top-level source package, choosing the first best");
+  else if (!mxf_umid_is_zero (&demux->current_package_uid))
     GST_WARNING_OBJECT (demux,
-        "Selected package is not a material package or top-level source package, choosing the first best");
-    memset (&demux->current_package_uid, 0, sizeof (MXFUMID));
-    goto choose_package;
+        "Current package not found, choosing the first best");
+
+  if (!demux->material_package) {
+    GST_ERROR_OBJECT (demux, "No material package");
+    return NULL;
+  } else {
+    MXFMetadataGenericPackage *p =
+        (MXFMetadataGenericPackage *) demux->material_package->data;
+    memcpy (&demux->current_package_uid, &p->package_uid, 32);
+
+    ret = gst_mxf_demux_find_package (demux, &demux->current_package_uid);
   }
 
+  if (!ret)
+    GST_ERROR_OBJECT (demux, "No suitable package found");
+
+  return ret;
+}
+
+static GstFlowReturn
+gst_mxf_demux_handle_header_metadata_update_streams (GstMXFDemux * demux)
+{
+  MXFMetadataGenericPackage *current_package = NULL;
+  guint i, j, k;
+  gboolean first_run;
+
+  GST_DEBUG_OBJECT (demux, "Updating streams");
+
+  current_package = gst_mxf_demux_choose_package (demux);
+
   if (!current_package->tracks) {
     GST_ERROR_OBJECT (demux, "Current package has no (resolved) tracks");
     return GST_FLOW_ERROR;
@@ -2541,6 +2580,11 @@ gst_mxf_demux_handle_klv_packet (GstMXFDemux * demux, const MXFUL * key,
             gst_mxf_demux_handle_header_metadata_update_streams (demux)) !=
         GST_FLOW_OK)
       goto beach;
+  } else if (!demux->update_metadata && demux->requested_package_string) {
+    if ((ret =
+            gst_mxf_demux_handle_header_metadata_update_streams (demux)) !=
+        GST_FLOW_OK)
+      goto beach;
   }
 
   if (!mxf_is_mxf_packet (key)) {
@@ -3091,6 +3135,39 @@ gst_mxf_demux_change_state (GstElement * element, GstStateChange transition)
 }
 
 static void
+gst_mxf_demux_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstMXFDemux *demux = GST_MXF_DEMUX (object);
+
+  switch (prop_id) {
+    case PROP_PACKAGE:
+      g_free (demux->requested_package_string);
+      demux->requested_package_string = g_value_dup_string (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_mxf_demux_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstMXFDemux *demux = GST_MXF_DEMUX (object);
+
+  switch (prop_id) {
+    case PROP_PACKAGE:
+      g_value_set_string (value, demux->current_package_string);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
 gst_mxf_demux_finalize (GObject * object)
 {
   GstMXFDemux *demux = GST_MXF_DEMUX (object);
@@ -3110,12 +3187,12 @@ gst_mxf_demux_finalize (GObject * object)
     demux->close_seg_event = NULL;
   }
 
-  if (demux->src) {
-    g_ptr_array_foreach (demux->src, (GFunc) gst_mxf_demux_remove_pad, demux);
-    g_ptr_array_foreach (demux->src, (GFunc) gst_object_unref, NULL);
-    g_ptr_array_free (demux->src, TRUE);
-    demux->src = NULL;
-  }
+  g_free (demux->current_package_string);
+  demux->current_package_string = NULL;
+  g_free (demux->requested_package_string);
+  demux->requested_package_string = NULL;
+
+  gst_mxf_demux_remove_pads (demux);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -3146,7 +3223,14 @@ gst_mxf_demux_class_init (GstMXFDemuxClass * klass)
 
   GST_DEBUG_CATEGORY_INIT (mxfdemux_debug, "mxfdemux", 0, "MXF demuxer");
 
-  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_mxf_demux_finalize);
+  gobject_class->finalize = gst_mxf_demux_finalize;
+  gobject_class->set_property = gst_mxf_demux_set_property;
+  gobject_class->get_property = gst_mxf_demux_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_PACKAGE,
+      g_param_spec_string ("package", "Package",
+          "Material or Source package to use for playback", NULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gstelement_class->change_state =
       GST_DEBUG_FUNCPTR (gst_mxf_demux_change_state);
index 887200c..7b35d19 100644 (file)
@@ -99,6 +99,8 @@ struct _GstMXFDemux
   
   MXFUMID current_package_uid;
   MXFMetadataGenericPackage *current_package;
+  gchar *current_package_string;
+  gchar *requested_package_string;
 };
 
 struct _GstMXFDemuxClass
index 22efb33..32f5e33 100644 (file)
@@ -271,6 +271,37 @@ mxf_umid_to_string (const MXFUMID * key, gchar str[96])
   return str;
 }
 
+MXFUMID *
+mxf_umid_from_string (const gchar * str, MXFUMID * umid)
+{
+  gint len;
+  guint i, j;
+
+  g_return_val_if_fail (str != NULL, NULL);
+  len = strlen (str);
+
+  memset (umid, 0, 32);
+
+  if (len != 95) {
+    GST_ERROR ("Invalid UMID string length %d", len);
+    return NULL;
+  }
+
+  for (i = 0, j = 0; i < 32; i++) {
+    if (!g_ascii_isxdigit (str[j]) ||
+        !g_ascii_isxdigit (str[j + 1]) ||
+        (str[j + 2] != '.' && str[j + 2] != '\0')) {
+      GST_ERROR ("Invalid UMID string '%s'", str);
+      return NULL;
+    }
+
+    umid->u[i] =
+        (g_ascii_xdigit_value (str[j]) << 4) | (g_ascii_xdigit_value (str[j +
+                1]));
+    j += 3;
+  }
+  return umid;
+}
 
 static guint
 gst_mxf_ul_hash (const MXFUL * key)
index 54b4c0d..bb4e858 100644 (file)
@@ -35,6 +35,7 @@ gboolean mxf_ul_is_equal (const MXFUL *a, const MXFUL *b);
 gboolean mxf_ul_is_zero (const MXFUL *ul);
 
 gchar *mxf_umid_to_string (const MXFUMID * umid, gchar str[96]);
+MXFUMID *mxf_umid_from_string (const gchar *str, MXFUMID * umid);
 gboolean mxf_umid_is_equal (const MXFUMID *a, const MXFUMID *b);
 gboolean mxf_umid_is_zero (const MXFUMID *umid);