mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 00:06:36 +00:00
51a921b34b
Fix missing and/or dupplicated separators, bogus breaks, typos, etc.
532 lines
15 KiB
C
532 lines
15 KiB
C
/* Gstreamer
|
|
*
|
|
* Copyright (c) 2012, Collabora Ltd.
|
|
* Author: Thibault Saunier <thibault.saunier@collabora.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "media-descriptor-parser.h"
|
|
#include <string.h>
|
|
|
|
G_DEFINE_TYPE (GstValidateMediaDescriptorParser,
|
|
gst_validate_media_descriptor_parser, GST_TYPE_VALIDATE_MEDIA_DESCRIPTOR);
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_PATH,
|
|
N_PROPERTIES
|
|
};
|
|
|
|
struct _GstValidateMediaDescriptorParserPrivate
|
|
{
|
|
gchar *xmlpath;
|
|
|
|
gboolean in_stream;
|
|
gchar *xmlcontent;
|
|
GMarkupParseContext *parsecontext;
|
|
};
|
|
|
|
/* Private methods and callbacks */
|
|
static gint
|
|
compare_frames (GstValidateMediaFrameNode * frm,
|
|
GstValidateMediaFrameNode * frm1)
|
|
{
|
|
if (frm->id < frm1->id)
|
|
return -1;
|
|
|
|
else if (frm->id == frm1->id)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void
|
|
deserialize_filenode
|
|
(GstValidateMediaFileNode *
|
|
filenode, const gchar ** names, const gchar ** values)
|
|
{
|
|
gint i;
|
|
for (i = 0; names[i] != NULL; i++) {
|
|
if (g_strcmp0 (names[i], "uri") == 0)
|
|
filenode->uri = g_strdup (values[i]);
|
|
else if (g_strcmp0 (names[i], "id") == 0)
|
|
filenode->id = g_ascii_strtoull (values[i], NULL, 0);
|
|
else if (g_strcmp0 (names[i], "frame-detection") == 0)
|
|
filenode->frame_detection = g_ascii_strtoull (values[i], NULL, 0);
|
|
else if (g_strcmp0 (names[i], "duration") == 0)
|
|
filenode->duration = g_ascii_strtoull (values[i], NULL, 0);
|
|
else if (g_strcmp0 (names[i], "seekable") == 0)
|
|
filenode->seekable = (g_strcmp0 (values[i], "true") == 0);
|
|
}
|
|
}
|
|
|
|
static GstValidateMediaStreamNode *
|
|
deserialize_streamnode (const gchar ** names, const gchar ** values)
|
|
{
|
|
gint i;
|
|
GstValidateMediaStreamNode
|
|
* streamnode = g_slice_new0 (GstValidateMediaStreamNode);
|
|
|
|
for (i = 0; names[i] != NULL; i++) {
|
|
if (g_strcmp0 (names[i], "id") == 0)
|
|
streamnode->id = g_strdup (values[i]);
|
|
else if (g_strcmp0 (names[i], "caps") == 0)
|
|
streamnode->caps = gst_caps_from_string (values[i]);
|
|
else if (g_strcmp0 (names[i], "padname") == 0)
|
|
streamnode->padname = g_strdup (values[i]);
|
|
}
|
|
|
|
|
|
return streamnode;
|
|
}
|
|
|
|
static GstValidateMediaTagsNode *
|
|
deserialize_tagsnode (const gchar ** names, const gchar ** values)
|
|
{
|
|
GstValidateMediaTagsNode *tagsnode = g_slice_new0 (GstValidateMediaTagsNode);
|
|
|
|
return tagsnode;
|
|
}
|
|
|
|
static GstValidateMediaTagNode *
|
|
deserialize_tagnode (const gchar ** names, const gchar ** values)
|
|
{
|
|
gint i;
|
|
GstValidateMediaTagNode *tagnode = g_slice_new0 (GstValidateMediaTagNode);
|
|
|
|
for (i = 0; names[i] != NULL; i++) {
|
|
if (g_strcmp0 (names[i], "content") == 0)
|
|
tagnode->taglist = gst_tag_list_new_from_string (values[i]);
|
|
}
|
|
|
|
return tagnode;
|
|
}
|
|
|
|
static GstValidateMediaFrameNode *
|
|
deserialize_framenode (const gchar ** names, const gchar ** values)
|
|
{
|
|
gint i;
|
|
|
|
GstValidateMediaFrameNode *framenode =
|
|
g_slice_new0 (GstValidateMediaFrameNode);
|
|
|
|
for (i = 0; names[i] != NULL; i++) {
|
|
if (g_strcmp0 (names[i], "id") == 0)
|
|
framenode->id = g_ascii_strtoull (values[i], NULL, 0);
|
|
else if (g_strcmp0 (names[i], "offset") == 0)
|
|
framenode->offset = g_ascii_strtoull (values[i], NULL, 0);
|
|
else if (g_strcmp0 (names[i], "offset-end") == 0)
|
|
framenode->offset_end = g_ascii_strtoull (values[i], NULL, 0);
|
|
else if (g_strcmp0 (names[i], "duration") == 0)
|
|
framenode->duration = g_ascii_strtoull (values[i], NULL, 0);
|
|
else if (g_strcmp0 (names[i], "pts") == 0)
|
|
framenode->pts = g_ascii_strtoull (values[i], NULL, 0);
|
|
else if (g_strcmp0 (names[i], "dts") == 0)
|
|
framenode->dts = g_ascii_strtoull (values[i], NULL, 0);
|
|
else if (g_strcmp0 (names[i], "running-time") == 0)
|
|
framenode->running_time = g_ascii_strtoull (values[i], NULL, 0);
|
|
else if (g_strcmp0 (names[i], "checksum") == 0)
|
|
framenode->checksum = g_strdup (values[i]);
|
|
else if (g_strcmp0 (names[i], "is-keyframe") == 0) {
|
|
if (!g_ascii_strcasecmp (values[i], "true"))
|
|
framenode->is_keyframe = TRUE;
|
|
else
|
|
framenode->is_keyframe = FALSE;
|
|
}
|
|
}
|
|
|
|
framenode->buf = gst_buffer_new_wrapped (framenode->checksum,
|
|
strlen (framenode->checksum) + 1);
|
|
|
|
GST_BUFFER_OFFSET (framenode->buf) = framenode->offset;
|
|
GST_BUFFER_OFFSET_END (framenode->buf) = framenode->offset_end;
|
|
GST_BUFFER_DURATION (framenode->buf) = framenode->duration;
|
|
GST_BUFFER_PTS (framenode->buf) = framenode->pts;
|
|
GST_BUFFER_DTS (framenode->buf) = framenode->dts;
|
|
|
|
if (framenode->is_keyframe) {
|
|
GST_BUFFER_FLAG_UNSET (framenode->buf, GST_BUFFER_FLAG_DELTA_UNIT);
|
|
} else {
|
|
GST_BUFFER_FLAG_SET (framenode->buf, GST_BUFFER_FLAG_DELTA_UNIT);
|
|
}
|
|
|
|
return framenode;
|
|
}
|
|
|
|
|
|
static void
|
|
on_end_element_cb (GMarkupParseContext * context,
|
|
const gchar * element_name, gpointer user_data, GError ** error)
|
|
{
|
|
GstValidateMediaDescriptorParserPrivate *priv =
|
|
GST_VALIDATE_MEDIA_DESCRIPTOR_PARSER (user_data)->priv;
|
|
|
|
if (g_strcmp0 (element_name, "stream") == 0) {
|
|
priv->in_stream = FALSE;
|
|
}
|
|
}
|
|
|
|
static void
|
|
on_start_element_cb (GMarkupParseContext * context,
|
|
const gchar * element_name, const gchar ** attribute_names,
|
|
const gchar ** attribute_values, gpointer user_data, GError ** error)
|
|
{
|
|
GstValidateMediaFileNode
|
|
* filenode = GST_VALIDATE_MEDIA_DESCRIPTOR (user_data)->filenode;
|
|
|
|
GstValidateMediaDescriptorParserPrivate *priv =
|
|
GST_VALIDATE_MEDIA_DESCRIPTOR_PARSER (user_data)->priv;
|
|
|
|
if (g_strcmp0 (element_name, "file") == 0) {
|
|
deserialize_filenode (filenode, attribute_names, attribute_values);
|
|
} else if (g_strcmp0 (element_name, "stream") == 0) {
|
|
GstValidateMediaStreamNode
|
|
* node = deserialize_streamnode (attribute_names, attribute_values);
|
|
priv->in_stream = TRUE;
|
|
filenode->streams = g_list_prepend (filenode->streams, node);
|
|
} else if (g_strcmp0 (element_name, "frame") == 0) {
|
|
GstValidateMediaStreamNode *streamnode = filenode->streams->data;
|
|
|
|
streamnode->cframe = streamnode->frames =
|
|
g_list_insert_sorted (streamnode->frames,
|
|
deserialize_framenode (attribute_names, attribute_values),
|
|
(GCompareFunc) compare_frames);
|
|
} else if (g_strcmp0 (element_name, "tags") == 0) {
|
|
if (priv->in_stream) {
|
|
GstValidateMediaStreamNode *snode = (GstValidateMediaStreamNode *)
|
|
filenode->streams->data;
|
|
|
|
snode->tags = deserialize_tagsnode (attribute_names, attribute_values);
|
|
} else {
|
|
filenode->tags = deserialize_tagsnode (attribute_names, attribute_values);
|
|
}
|
|
} else if (g_strcmp0 (element_name, "tag") == 0) {
|
|
GstValidateMediaTagsNode *tagsnode;
|
|
|
|
if (priv->in_stream) {
|
|
GstValidateMediaStreamNode *snode = (GstValidateMediaStreamNode *)
|
|
filenode->streams->data;
|
|
tagsnode = snode->tags;
|
|
} else {
|
|
tagsnode = filenode->tags;
|
|
}
|
|
|
|
tagsnode->tags = g_list_prepend (tagsnode->tags,
|
|
deserialize_tagnode (attribute_names, attribute_values));
|
|
}
|
|
}
|
|
|
|
static void
|
|
on_error_cb (GMarkupParseContext * context, GError * error, gpointer user_data)
|
|
{
|
|
GST_ERROR ("Error parsing file: %s", error->message);
|
|
}
|
|
|
|
static const GMarkupParser content_parser = {
|
|
on_start_element_cb,
|
|
on_end_element_cb,
|
|
NULL,
|
|
NULL,
|
|
&on_error_cb
|
|
};
|
|
|
|
static gboolean
|
|
_set_content (GstValidateMediaDescriptorParser * parser,
|
|
const gchar * content, gsize size, GError ** error)
|
|
{
|
|
GError *err = NULL;
|
|
GstValidateMediaDescriptorParserPrivate *priv = parser->priv;
|
|
|
|
priv->parsecontext = g_markup_parse_context_new (&content_parser,
|
|
G_MARKUP_TREAT_CDATA_AS_TEXT, parser, NULL);
|
|
|
|
if (g_markup_parse_context_parse (priv->parsecontext, content,
|
|
size, &err) == FALSE)
|
|
goto failed;
|
|
|
|
return TRUE;
|
|
|
|
failed:
|
|
g_propagate_error (error, err);
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
set_xml_path (GstValidateMediaDescriptorParser * parser, const gchar * path,
|
|
GError ** error)
|
|
{
|
|
gsize xmlsize;
|
|
gchar *content;
|
|
GError *err = NULL;
|
|
GstValidateMediaDescriptorParserPrivate *priv = parser->priv;
|
|
gboolean result;
|
|
|
|
if (!g_file_get_contents (path, &content, &xmlsize, &err))
|
|
goto failed;
|
|
|
|
priv->xmlpath = g_strdup (path);
|
|
|
|
result = _set_content (parser, content, xmlsize, error);
|
|
g_free (content);
|
|
return result;
|
|
|
|
failed:
|
|
g_propagate_error (error, err);
|
|
return FALSE;
|
|
}
|
|
|
|
/* GObject standard vmethods */
|
|
static void
|
|
dispose (GstValidateMediaDescriptorParser * parser)
|
|
{
|
|
G_OBJECT_CLASS (gst_validate_media_descriptor_parser_parent_class)->dispose
|
|
(G_OBJECT (parser));
|
|
}
|
|
|
|
static void
|
|
finalize (GstValidateMediaDescriptorParser * parser)
|
|
{
|
|
GstValidateMediaDescriptorParserPrivate *priv;
|
|
|
|
priv = parser->priv;
|
|
|
|
g_free (priv->xmlpath);
|
|
g_free (priv->xmlcontent);
|
|
|
|
if (priv->parsecontext != NULL)
|
|
g_markup_parse_context_free (priv->parsecontext);
|
|
|
|
G_OBJECT_CLASS (gst_validate_media_descriptor_parser_parent_class)->finalize
|
|
(G_OBJECT (parser));
|
|
}
|
|
|
|
|
|
static void
|
|
get_property (GObject * gobject, guint prop_id, GValue * value,
|
|
GParamSpec * pspec)
|
|
{
|
|
switch (prop_id) {
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
set_property (GObject * gobject, guint prop_id, const GValue * value,
|
|
GParamSpec * pspec)
|
|
{
|
|
switch (prop_id) {
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
}
|
|
|
|
static void
|
|
gst_validate_media_descriptor_parser_init (GstValidateMediaDescriptorParser *
|
|
parser)
|
|
{
|
|
GstValidateMediaDescriptorParserPrivate *priv;
|
|
|
|
parser->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (parser,
|
|
GST_TYPE_VALIDATE_MEDIA_DESCRIPTOR_PARSER,
|
|
GstValidateMediaDescriptorParserPrivate);
|
|
|
|
priv->xmlpath = NULL;
|
|
}
|
|
|
|
static void
|
|
gst_validate_media_descriptor_parser_class_init
|
|
(GstValidateMediaDescriptorParserClass * self_class)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (self_class);
|
|
|
|
g_type_class_add_private (self_class,
|
|
sizeof (GstValidateMediaDescriptorParserPrivate));
|
|
object_class->dispose = (void (*)(GObject * object)) dispose;
|
|
object_class->finalize = (void (*)(GObject * object)) finalize;
|
|
object_class->get_property = get_property;
|
|
object_class->set_property = set_property;
|
|
}
|
|
|
|
/* Public methods */
|
|
GstValidateMediaDescriptorParser *
|
|
gst_validate_media_descriptor_parser_new (GstValidateRunner * runner,
|
|
const gchar * xmlpath, GError ** error)
|
|
{
|
|
GstValidateMediaDescriptorParser *parser;
|
|
|
|
parser =
|
|
g_object_new (GST_TYPE_VALIDATE_MEDIA_DESCRIPTOR_PARSER,
|
|
"validate-runner", runner, NULL);
|
|
|
|
if (set_xml_path (parser, xmlpath, error) == FALSE) {
|
|
g_object_unref (parser);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
return parser;
|
|
}
|
|
|
|
GstValidateMediaDescriptorParser *
|
|
gst_validate_media_descriptor_parser_new_from_xml (GstValidateRunner * runner,
|
|
const gchar * xml, GError ** error)
|
|
{
|
|
GstValidateMediaDescriptorParser *parser;
|
|
|
|
parser =
|
|
g_object_new (GST_TYPE_VALIDATE_MEDIA_DESCRIPTOR_PARSER,
|
|
"validate-runner", runner, NULL);
|
|
if (_set_content (parser, xml, strlen (xml) * sizeof (gchar), error) == FALSE) {
|
|
g_object_unref (parser);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
return parser;
|
|
}
|
|
|
|
gchar *gst_validate_media_descriptor_parser_get_xml_path
|
|
(GstValidateMediaDescriptorParser * parser)
|
|
{
|
|
g_return_val_if_fail (GST_IS_VALIDATE_MEDIA_DESCRIPTOR_PARSER (parser), NULL);
|
|
|
|
return g_strdup (parser->priv->xmlpath);
|
|
}
|
|
|
|
gboolean
|
|
gst_validate_media_descriptor_parser_add_stream
|
|
(GstValidateMediaDescriptorParser * parser, GstPad * pad) {
|
|
GList *tmp;
|
|
gboolean ret = FALSE;
|
|
GstCaps *caps;
|
|
|
|
g_return_val_if_fail (GST_IS_VALIDATE_MEDIA_DESCRIPTOR_PARSER (parser),
|
|
FALSE);
|
|
g_return_val_if_fail (((GstValidateMediaDescriptor *) parser)->filenode,
|
|
FALSE);
|
|
|
|
caps = gst_pad_query_caps (pad, NULL);
|
|
for (tmp = ((GstValidateMediaDescriptor *) parser)->filenode->streams; tmp;
|
|
tmp = tmp->next) {
|
|
GstValidateMediaStreamNode *streamnode = (GstValidateMediaStreamNode *)
|
|
tmp->data;
|
|
|
|
if (streamnode->pad == NULL && gst_caps_is_equal (streamnode->caps, caps)) {
|
|
ret = TRUE;
|
|
streamnode->pad = gst_object_ref (pad);
|
|
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
done:
|
|
if (caps != NULL)
|
|
gst_caps_unref (caps);
|
|
|
|
return ret;
|
|
}
|
|
|
|
gboolean
|
|
gst_validate_media_descriptor_parser_all_stream_found
|
|
(GstValidateMediaDescriptorParser * parser) {
|
|
GList *tmp;
|
|
|
|
g_return_val_if_fail (GST_IS_VALIDATE_MEDIA_DESCRIPTOR_PARSER (parser),
|
|
FALSE);
|
|
g_return_val_if_fail (((GstValidateMediaDescriptor *) parser)->filenode,
|
|
FALSE);
|
|
|
|
for (tmp = ((GstValidateMediaDescriptor *) parser)->filenode->streams; tmp;
|
|
tmp = tmp->next) {
|
|
GstValidateMediaStreamNode *streamnode = (GstValidateMediaStreamNode *)
|
|
tmp->data;
|
|
|
|
if (streamnode->pad == NULL)
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
gst_validate_media_descriptor_parser_add_taglist
|
|
(GstValidateMediaDescriptorParser * parser, GstTagList * taglist) {
|
|
GList *tmptag;
|
|
GstValidateMediaTagsNode *tagsnode;
|
|
|
|
g_return_val_if_fail (GST_IS_VALIDATE_MEDIA_DESCRIPTOR_PARSER (parser),
|
|
FALSE);
|
|
g_return_val_if_fail (((GstValidateMediaDescriptor *) parser)->filenode,
|
|
FALSE);
|
|
g_return_val_if_fail (GST_IS_STRUCTURE (taglist), FALSE);
|
|
|
|
tagsnode = ((GstValidateMediaDescriptor *) parser)->filenode->tags;
|
|
|
|
for (tmptag = tagsnode->tags; tmptag; tmptag = tmptag->next) {
|
|
if (gst_validate_tag_node_compare ((GstValidateMediaTagNode *)
|
|
tmptag->data, taglist)) {
|
|
GST_DEBUG ("Adding tag %" GST_PTR_FORMAT, taglist);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
gboolean
|
|
gst_validate_media_descriptor_parser_all_tags_found
|
|
(GstValidateMediaDescriptorParser * parser) {
|
|
GList *tmptag;
|
|
GstValidateMediaTagsNode *tagsnode;
|
|
gboolean ret = TRUE;
|
|
|
|
g_return_val_if_fail (GST_IS_VALIDATE_MEDIA_DESCRIPTOR_PARSER (parser),
|
|
FALSE);
|
|
g_return_val_if_fail (((GstValidateMediaDescriptor *) parser)->filenode,
|
|
FALSE);
|
|
|
|
tagsnode = ((GstValidateMediaDescriptor *) parser)->filenode->tags;
|
|
for (tmptag = tagsnode->tags; tmptag; tmptag = tmptag->next) {
|
|
gchar *tag = NULL;
|
|
|
|
tag = gst_tag_list_to_string (((GstValidateMediaTagNode *)
|
|
tmptag->data)->taglist);
|
|
if (((GstValidateMediaTagNode *)
|
|
tmptag->data)->found == FALSE) {
|
|
|
|
if (((GstValidateMediaTagNode *)
|
|
tmptag->data)->taglist != NULL) {
|
|
GST_DEBUG ("Tag not found %s", tag);
|
|
} else {
|
|
GST_DEBUG ("Tag not properly deserialized");
|
|
}
|
|
|
|
ret = FALSE;
|
|
}
|
|
|
|
GST_DEBUG ("Tag properly found %s", tag);
|
|
g_free (tag);
|
|
}
|
|
|
|
return ret;
|
|
}
|