mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-18 20:25:25 +00:00
mssdemux: pad exposing initial implementation
Does some basic parsing of the stream caps and adds a pad for each stream detected in the manifest
This commit is contained in:
parent
72b05c0051
commit
5291985efe
4 changed files with 209 additions and 0 deletions
|
@ -122,12 +122,26 @@ gst_mss_demux_init (GstMssDemux * mssdemux, GstMssDemuxClass * klass)
|
||||||
static void
|
static void
|
||||||
gst_mss_demux_reset (GstMssDemux * mssdemux)
|
gst_mss_demux_reset (GstMssDemux * mssdemux)
|
||||||
{
|
{
|
||||||
|
GSList *iter;
|
||||||
if (mssdemux->manifest_buffer) {
|
if (mssdemux->manifest_buffer) {
|
||||||
gst_buffer_unref (mssdemux->manifest_buffer);
|
gst_buffer_unref (mssdemux->manifest_buffer);
|
||||||
|
mssdemux->manifest_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (iter = mssdemux->streams; iter; iter = g_slist_next (iter)) {
|
||||||
|
GstMssDemuxStream *stream = iter->data;
|
||||||
|
gst_element_remove_pad (GST_ELEMENT_CAST (mssdemux), stream->pad);
|
||||||
|
g_free (stream);
|
||||||
|
}
|
||||||
|
g_slist_free (mssdemux->streams);
|
||||||
|
mssdemux->streams = NULL;
|
||||||
|
|
||||||
if (mssdemux->manifest) {
|
if (mssdemux->manifest) {
|
||||||
gst_mss_manifest_free (mssdemux->manifest);
|
gst_mss_manifest_free (mssdemux->manifest);
|
||||||
|
mssdemux->manifest = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mssdemux->n_videos = mssdemux->n_audios = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -222,12 +236,62 @@ gst_mss_demux_create_streams (GstMssDemux * mssdemux)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iter = streams; iter; iter = g_slist_next (iter)) {
|
for (iter = streams; iter; iter = g_slist_next (iter)) {
|
||||||
|
gchar *name;
|
||||||
|
GstPad *srcpad = NULL;
|
||||||
|
GstMssDemuxStream *stream = NULL;
|
||||||
GstMssManifestStream *manifeststream = iter->data;
|
GstMssManifestStream *manifeststream = iter->data;
|
||||||
GstMssManifestStreamType streamtype;
|
GstMssManifestStreamType streamtype;
|
||||||
|
|
||||||
streamtype = gst_mss_manifest_stream_get_type (manifeststream);
|
streamtype = gst_mss_manifest_stream_get_type (manifeststream);
|
||||||
GST_DEBUG_OBJECT (mssdemux, "Found stream of type: %s",
|
GST_DEBUG_OBJECT (mssdemux, "Found stream of type: %s",
|
||||||
gst_mss_manifest_stream_type_name (streamtype));
|
gst_mss_manifest_stream_type_name (streamtype));
|
||||||
|
|
||||||
|
/* TODO use stream's name as the pad name? */
|
||||||
|
if (streamtype == MSS_STREAM_TYPE_VIDEO) {
|
||||||
|
name = g_strdup_printf ("video_%02u", mssdemux->n_videos++);
|
||||||
|
srcpad =
|
||||||
|
gst_pad_new_from_static_template (&gst_mss_demux_videosrc_template,
|
||||||
|
name);
|
||||||
|
g_free (name);
|
||||||
|
} else if (streamtype == MSS_STREAM_TYPE_AUDIO) {
|
||||||
|
name = g_strdup_printf ("audio_%02u", mssdemux->n_audios++);
|
||||||
|
srcpad =
|
||||||
|
gst_pad_new_from_static_template (&gst_mss_demux_audiosrc_template,
|
||||||
|
name);
|
||||||
|
g_free (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!srcpad) {
|
||||||
|
GST_WARNING_OBJECT (mssdemux, "Ignoring unknown type stream");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream = g_new (GstMssDemuxStream, 1);
|
||||||
|
stream->pad = srcpad;
|
||||||
|
stream->manifest_stream = manifeststream;
|
||||||
|
mssdemux->streams = g_slist_append (mssdemux->streams, stream);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_mss_demux_expose_stream (GstMssDemux * mssdemux, GstMssDemuxStream * stream)
|
||||||
|
{
|
||||||
|
GstCaps *caps;
|
||||||
|
GstPad *pad = stream->pad;
|
||||||
|
|
||||||
|
caps = gst_mss_manifest_stream_get_caps (stream->manifest_stream);
|
||||||
|
|
||||||
|
if (caps) {
|
||||||
|
gst_pad_set_caps (pad, caps);
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
|
gst_pad_set_active (pad, TRUE);
|
||||||
|
GST_INFO_OBJECT (mssdemux, "Adding srcpad %s:%s with caps %" GST_PTR_FORMAT,
|
||||||
|
GST_DEBUG_PAD_NAME (pad), caps);
|
||||||
|
gst_element_add_pad (GST_ELEMENT_CAST (mssdemux), pad);
|
||||||
|
} else {
|
||||||
|
GST_WARNING_OBJECT (mssdemux, "Not exposing stream of unrecognized format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,6 +301,7 @@ gst_mss_demux_process_manifest (GstMssDemux * mssdemux)
|
||||||
GstQuery *query;
|
GstQuery *query;
|
||||||
gchar *uri = NULL;
|
gchar *uri = NULL;
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
|
GSList *iter;
|
||||||
|
|
||||||
g_return_if_fail (mssdemux->manifest_buffer != NULL);
|
g_return_if_fail (mssdemux->manifest_buffer != NULL);
|
||||||
g_return_if_fail (mssdemux->manifest == NULL);
|
g_return_if_fail (mssdemux->manifest == NULL);
|
||||||
|
@ -258,4 +323,7 @@ gst_mss_demux_process_manifest (GstMssDemux * mssdemux)
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_mss_demux_create_streams (mssdemux);
|
gst_mss_demux_create_streams (mssdemux);
|
||||||
|
for (iter = mssdemux->streams; iter; iter = g_slist_next (iter)) {
|
||||||
|
gst_mss_demux_expose_stream (mssdemux, iter->data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,9 +45,16 @@ GST_DEBUG_CATEGORY_EXTERN (mssdemux_debug);
|
||||||
|
|
||||||
#define GST_MSS_DEMUX_CAST(obj) ((GstMssDemux *)(obj))
|
#define GST_MSS_DEMUX_CAST(obj) ((GstMssDemux *)(obj))
|
||||||
|
|
||||||
|
typedef struct _GstMssDemuxStream GstMssDemuxStream;
|
||||||
typedef struct _GstMssDemux GstMssDemux;
|
typedef struct _GstMssDemux GstMssDemux;
|
||||||
typedef struct _GstMssDemuxClass GstMssDemuxClass;
|
typedef struct _GstMssDemuxClass GstMssDemuxClass;
|
||||||
|
|
||||||
|
struct _GstMssDemuxStream {
|
||||||
|
GstPad *pad;
|
||||||
|
|
||||||
|
GstMssManifestStream *manifest_stream;
|
||||||
|
};
|
||||||
|
|
||||||
struct _GstMssDemux {
|
struct _GstMssDemux {
|
||||||
GstElement element;
|
GstElement element;
|
||||||
|
|
||||||
|
@ -57,6 +64,10 @@ struct _GstMssDemux {
|
||||||
GstBuffer *manifest_buffer;
|
GstBuffer *manifest_buffer;
|
||||||
|
|
||||||
GstMssManifest *manifest;
|
GstMssManifest *manifest;
|
||||||
|
|
||||||
|
GSList *streams;
|
||||||
|
guint n_videos;
|
||||||
|
guint n_audios;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstMssDemuxClass {
|
struct _GstMssDemuxClass {
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
struct _GstMssManifestStream
|
struct _GstMssManifestStream
|
||||||
{
|
{
|
||||||
xmlNodePtr xmlnode;
|
xmlNodePtr xmlnode;
|
||||||
|
|
||||||
|
gint selectedQualityIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstMssManifest
|
struct _GstMssManifest
|
||||||
|
@ -98,6 +100,133 @@ gst_mss_manifest_stream_get_type (GstMssManifestStream * stream)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstCaps *
|
||||||
|
_gst_mss_manifest_stream_video_caps_from_fourcc (gchar * fourcc)
|
||||||
|
{
|
||||||
|
if (!fourcc)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (strcmp (fourcc, "H264") == 0) {
|
||||||
|
return gst_caps_new_simple ("video/x-h264", NULL);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstCaps *
|
||||||
|
_gst_mss_manifest_stream_audio_caps_from_fourcc (gchar * fourcc)
|
||||||
|
{
|
||||||
|
if (!fourcc)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (strcmp (fourcc, "AACL") == 0) {
|
||||||
|
return gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT, 4,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstCaps *
|
||||||
|
_gst_mss_manifest_stream_video_caps_from_qualitylevel_xml (xmlNodePtr node)
|
||||||
|
{
|
||||||
|
GstCaps *caps;
|
||||||
|
GstStructure *structure;
|
||||||
|
gchar *fourcc = (gchar *) xmlGetProp (node, (xmlChar *) "FourCC");
|
||||||
|
gchar *max_width = (gchar *) xmlGetProp (node, (xmlChar *) "MaxWidth");
|
||||||
|
gchar *max_height = (gchar *) xmlGetProp (node, (xmlChar *) "MaxHeight");
|
||||||
|
gchar *codec_data =
|
||||||
|
(gchar *) xmlGetProp (node, (xmlChar *) "CodecPrivateData");
|
||||||
|
|
||||||
|
caps = _gst_mss_manifest_stream_video_caps_from_fourcc (fourcc);
|
||||||
|
if (!caps)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
|
|
||||||
|
if (max_width)
|
||||||
|
gst_structure_set (structure, "width", G_TYPE_INT, atoi (max_width), NULL);
|
||||||
|
if (max_height)
|
||||||
|
gst_structure_set (structure, "height", G_TYPE_INT, atoi (max_height),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (codec_data) {
|
||||||
|
GValue *value = g_new0 (GValue, 1);
|
||||||
|
g_value_init (value, GST_TYPE_BUFFER);
|
||||||
|
gst_value_deserialize (value, (gchar *) codec_data);
|
||||||
|
gst_structure_take_value (structure, "codec_data", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
g_free (fourcc);
|
||||||
|
g_free (max_width);
|
||||||
|
g_free (max_height);
|
||||||
|
g_free (codec_data);
|
||||||
|
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstCaps *
|
||||||
|
_gst_mss_manifest_stream_audio_caps_from_qualitylevel_xml (xmlNodePtr node)
|
||||||
|
{
|
||||||
|
GstCaps *caps;
|
||||||
|
GstStructure *structure;
|
||||||
|
gchar *fourcc = (gchar *) xmlGetProp (node, (xmlChar *) "FourCC");
|
||||||
|
gchar *channels = (gchar *) xmlGetProp (node, (xmlChar *) "Channels");
|
||||||
|
gchar *rate = (gchar *) xmlGetProp (node, (xmlChar *) "SamplingRate");
|
||||||
|
gchar *codec_data =
|
||||||
|
(gchar *) xmlGetProp (node, (xmlChar *) "CodecPrivateData");
|
||||||
|
|
||||||
|
caps = _gst_mss_manifest_stream_audio_caps_from_fourcc (fourcc);
|
||||||
|
if (!caps)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
|
|
||||||
|
if (channels)
|
||||||
|
gst_structure_set (structure, "channels", G_TYPE_INT, atoi (channels),
|
||||||
|
NULL);
|
||||||
|
if (rate)
|
||||||
|
gst_structure_set (structure, "rate", G_TYPE_INT, atoi (rate), NULL);
|
||||||
|
|
||||||
|
if (codec_data) {
|
||||||
|
GValue *value = g_new0 (GValue, 1);
|
||||||
|
g_value_init (value, GST_TYPE_BUFFER);
|
||||||
|
gst_value_deserialize (value, (gchar *) codec_data);
|
||||||
|
gst_structure_take_value (structure, "codec_data", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
g_free (fourcc);
|
||||||
|
g_free (channels);
|
||||||
|
g_free (rate);
|
||||||
|
g_free (codec_data);
|
||||||
|
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
GstCaps *
|
||||||
|
gst_mss_manifest_stream_get_caps (GstMssManifestStream * stream)
|
||||||
|
{
|
||||||
|
GstMssManifestStreamType streamtype =
|
||||||
|
gst_mss_manifest_stream_get_type (stream);
|
||||||
|
|
||||||
|
/* TODO properly get the stream */
|
||||||
|
xmlNodePtr qualitylevel = stream->xmlnode->children;
|
||||||
|
while (strcmp ((gchar *) qualitylevel->name, "QualityLevel")) {
|
||||||
|
qualitylevel = qualitylevel->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (streamtype == MSS_STREAM_TYPE_VIDEO)
|
||||||
|
return
|
||||||
|
_gst_mss_manifest_stream_video_caps_from_qualitylevel_xml
|
||||||
|
(qualitylevel);
|
||||||
|
else if (streamtype == MSS_STREAM_TYPE_AUDIO)
|
||||||
|
return
|
||||||
|
_gst_mss_manifest_stream_audio_caps_from_qualitylevel_xml
|
||||||
|
(qualitylevel);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
const gchar *
|
const gchar *
|
||||||
gst_mss_manifest_stream_type_name (GstMssManifestStreamType streamtype)
|
gst_mss_manifest_stream_type_name (GstMssManifestStreamType streamtype)
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,6 +43,7 @@ void gst_mss_manifest_free (GstMssManifest * manifest);
|
||||||
GSList * gst_mss_manifest_get_streams (GstMssManifest * manifest);
|
GSList * gst_mss_manifest_get_streams (GstMssManifest * manifest);
|
||||||
|
|
||||||
GstMssManifestStreamType gst_mss_manifest_stream_get_type (GstMssManifestStream *stream);
|
GstMssManifestStreamType gst_mss_manifest_stream_get_type (GstMssManifestStream *stream);
|
||||||
|
GstCaps * gst_mss_manifest_stream_get_caps (GstMssManifestStream * stream);
|
||||||
|
|
||||||
const gchar * gst_mss_manifest_stream_type_name (GstMssManifestStreamType streamtype);
|
const gchar * gst_mss_manifest_stream_type_name (GstMssManifestStreamType streamtype);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue