mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-06 07:28:53 +00:00
qtdemux: Add support for ONVIF XML Timed MetaData
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2453>
This commit is contained in:
parent
365a9af9c5
commit
7273024ae5
2 changed files with 98 additions and 0 deletions
|
@ -289,6 +289,12 @@ GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
|
||||||
GST_PAD_SOMETIMES,
|
GST_PAD_SOMETIMES,
|
||||||
GST_STATIC_CAPS_ANY);
|
GST_STATIC_CAPS_ANY);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate gst_qtdemux_metasrc_template =
|
||||||
|
GST_STATIC_PAD_TEMPLATE ("meta_%u",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_SOMETIMES,
|
||||||
|
GST_STATIC_CAPS_ANY);
|
||||||
|
|
||||||
#define gst_qtdemux_parent_class parent_class
|
#define gst_qtdemux_parent_class parent_class
|
||||||
G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
|
G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
|
||||||
GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
|
GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (qtdemux, "qtdemux",
|
||||||
|
@ -351,6 +357,9 @@ static GstCaps *qtdemux_audio_caps (GstQTDemux * qtdemux,
|
||||||
static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
|
static GstCaps *qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
|
||||||
QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
|
QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
|
||||||
gchar ** codec_name);
|
gchar ** codec_name);
|
||||||
|
static GstCaps *qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
|
||||||
|
QtDemuxStreamStsdEntry * entry, guint32 fourcc, const guint8 * data,
|
||||||
|
gchar ** codec_name);
|
||||||
static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
|
static GstCaps *qtdemux_generic_caps (GstQTDemux * qtdemux,
|
||||||
QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
|
QtDemuxStream * stream, QtDemuxStreamStsdEntry * entry, guint32 fourcc,
|
||||||
const guint8 * stsd_entry_data, gchar ** codec_name);
|
const guint8 * stsd_entry_data, gchar ** codec_name);
|
||||||
|
@ -2051,6 +2060,7 @@ gst_qtdemux_reset (GstQTDemux * qtdemux, gboolean hard)
|
||||||
qtdemux->n_video_streams = 0;
|
qtdemux->n_video_streams = 0;
|
||||||
qtdemux->n_audio_streams = 0;
|
qtdemux->n_audio_streams = 0;
|
||||||
qtdemux->n_sub_streams = 0;
|
qtdemux->n_sub_streams = 0;
|
||||||
|
qtdemux->n_meta_streams = 0;
|
||||||
qtdemux->exposed = FALSE;
|
qtdemux->exposed = FALSE;
|
||||||
qtdemux->fragmented = FALSE;
|
qtdemux->fragmented = FALSE;
|
||||||
qtdemux->mss_mode = FALSE;
|
qtdemux->mss_mode = FALSE;
|
||||||
|
@ -9028,6 +9038,19 @@ gst_qtdemux_add_stream (GstQTDemux * qtdemux,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
qtdemux->n_sub_streams++;
|
qtdemux->n_sub_streams++;
|
||||||
|
} else if (stream->subtype == FOURCC_meta) {
|
||||||
|
gchar *name = g_strdup_printf ("meta_%u", qtdemux->n_meta_streams);
|
||||||
|
|
||||||
|
stream->pad =
|
||||||
|
gst_pad_new_from_static_template (&gst_qtdemux_metasrc_template, name);
|
||||||
|
g_free (name);
|
||||||
|
if (!gst_qtdemux_configure_stream (qtdemux, stream)) {
|
||||||
|
gst_object_unref (stream->pad);
|
||||||
|
stream->pad = NULL;
|
||||||
|
ret = FALSE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
qtdemux->n_meta_streams++;
|
||||||
} else if (CUR_STREAM (stream)->caps) {
|
} else if (CUR_STREAM (stream)->caps) {
|
||||||
gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
|
gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
|
||||||
|
|
||||||
|
@ -13107,6 +13130,23 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
|
||||||
"unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
|
"unhandled type %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
GST_INFO_OBJECT (qtdemux,
|
||||||
|
"type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
|
||||||
|
GST_FOURCC_ARGS (fourcc), entry->caps);
|
||||||
|
} else if (stream->subtype == FOURCC_meta) {
|
||||||
|
entry->sampled = TRUE;
|
||||||
|
entry->sparse = TRUE;
|
||||||
|
|
||||||
|
entry->caps =
|
||||||
|
qtdemux_meta_caps (qtdemux, stream, entry, fourcc, stsd_entry_data,
|
||||||
|
&codec);
|
||||||
|
if (codec) {
|
||||||
|
gst_tag_list_add (stream->stream_tags, GST_TAG_MERGE_REPLACE,
|
||||||
|
GST_TAG_CODEC, codec, NULL);
|
||||||
|
g_free (codec);
|
||||||
|
codec = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
GST_INFO_OBJECT (qtdemux,
|
GST_INFO_OBJECT (qtdemux,
|
||||||
"type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
|
"type %" GST_FOURCC_FORMAT " caps %" GST_PTR_FORMAT,
|
||||||
GST_FOURCC_ARGS (fourcc), entry->caps);
|
GST_FOURCC_ARGS (fourcc), entry->caps);
|
||||||
|
@ -15270,6 +15310,63 @@ qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
|
||||||
return caps;
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstCaps *
|
||||||
|
qtdemux_meta_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
|
||||||
|
QtDemuxStreamStsdEntry * entry, guint32 fourcc,
|
||||||
|
const guint8 * stsd_entry_data, gchar ** codec_name)
|
||||||
|
{
|
||||||
|
GstCaps *caps = NULL;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (qtdemux, "resolve fourcc 0x%08x", GUINT32_TO_BE (fourcc));
|
||||||
|
|
||||||
|
switch (fourcc) {
|
||||||
|
case FOURCC_metx:{
|
||||||
|
gsize size = QT_UINT32 (stsd_entry_data);
|
||||||
|
GstByteReader reader = GST_BYTE_READER_INIT (stsd_entry_data, size);
|
||||||
|
const gchar *content_encoding;
|
||||||
|
const gchar *namespaces;
|
||||||
|
const gchar *schema_locations;
|
||||||
|
|
||||||
|
if (!gst_byte_reader_skip (&reader, 8 + 6 + 2)) {
|
||||||
|
GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gst_byte_reader_get_string (&reader, &content_encoding) ||
|
||||||
|
!gst_byte_reader_get_string (&reader, &namespaces) ||
|
||||||
|
!gst_byte_reader_get_string (&reader, &schema_locations)) {
|
||||||
|
GST_WARNING_OBJECT (qtdemux, "Too short metx sample entry");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr (namespaces, "http://www.onvif.org/ver10/schema") != 0) {
|
||||||
|
if (content_encoding == NULL || *content_encoding == '\0'
|
||||||
|
|| g_ascii_strcasecmp (content_encoding, "xml") == 0) {
|
||||||
|
_codec ("ONVIF Timed XML MetaData");
|
||||||
|
caps =
|
||||||
|
gst_caps_new_simple ("application/x-onvif-metadata", "encoding",
|
||||||
|
G_TYPE_STRING, "utf8", NULL);
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (qtdemux, "Unknown content encoding: %s",
|
||||||
|
content_encoding);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (qtdemux, "Unknown metadata namespaces: %s",
|
||||||
|
namespaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!caps)
|
||||||
|
caps = _get_unknown_codec_name ("meta", fourcc);
|
||||||
|
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
|
qtdemux_generic_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
|
||||||
QtDemuxStreamStsdEntry * entry, guint32 fourcc,
|
QtDemuxStreamStsdEntry * entry, guint32 fourcc,
|
||||||
|
|
|
@ -89,6 +89,7 @@ struct _GstQTDemux {
|
||||||
gint n_video_streams;
|
gint n_video_streams;
|
||||||
gint n_audio_streams;
|
gint n_audio_streams;
|
||||||
gint n_sub_streams;
|
gint n_sub_streams;
|
||||||
|
gint n_meta_streams;
|
||||||
|
|
||||||
GstFlowCombiner *flowcombiner;
|
GstFlowCombiner *flowcombiner;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue