summaryrefslogtreecommitdiffstats
path: root/gst/mxf
diff options
context:
space:
mode:
Diffstat (limited to 'gst/mxf')
-rw-r--r--gst/mxf/mxfdemux.c194
-rw-r--r--gst/mxf/mxfdemux.h2
-rw-r--r--gst/mxf/mxfparse.c31
-rw-r--r--gst/mxf/mxfparse.h1
4 files changed, 173 insertions, 55 deletions
diff --git a/gst/mxf/mxfdemux.c b/gst/mxf/mxfdemux.c
index 68d65cab..75726888 100644
--- a/gst/mxf/mxfdemux.c
+++ b/gst/mxf/mxfdemux.c
@@ -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);
diff --git a/gst/mxf/mxfdemux.h b/gst/mxf/mxfdemux.h
index 887200cd..7b35d19a 100644
--- a/gst/mxf/mxfdemux.h
+++ b/gst/mxf/mxfdemux.h
@@ -99,6 +99,8 @@ struct _GstMXFDemux
MXFUMID current_package_uid;
MXFMetadataGenericPackage *current_package;
+ gchar *current_package_string;
+ gchar *requested_package_string;
};
struct _GstMXFDemuxClass
diff --git a/gst/mxf/mxfparse.c b/gst/mxf/mxfparse.c
index 22efb333..32f5e336 100644
--- a/gst/mxf/mxfparse.c
+++ b/gst/mxf/mxfparse.c
@@ -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)
diff --git a/gst/mxf/mxfparse.h b/gst/mxf/mxfparse.h
index 54b4c0dd..bb4e8580 100644
--- a/gst/mxf/mxfparse.h
+++ b/gst/mxf/mxfparse.h
@@ -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);