diff --git a/validate/gst/validate/gst-validate-report.c b/validate/gst/validate/gst-validate-report.c
index e67d5c522f..72f7749c05 100644
--- a/validate/gst/validate/gst-validate-report.c
+++ b/validate/gst/validate/gst-validate-report.c
@@ -361,6 +361,8 @@ gst_validate_report_load_issues (void)
_("detected tags are different than expected ones"), NULL);
REGISTER_VALIDATE_ISSUE (CRITICAL, FILE_FRAMES_INCORRECT,
_("resulting file frames are not as expected"), NULL);
+ REGISTER_VALIDATE_ISSUE (CRITICAL, FILE_SEGMENT_INCORRECT,
+ _("resulting segment is not as expected"), NULL);
REGISTER_VALIDATE_ISSUE (WARNING, FILE_NO_STREAM_INFO,
_("the discoverer could not determine the stream info"), NULL);
REGISTER_VALIDATE_ISSUE (WARNING, FILE_NO_STREAM_ID,
diff --git a/validate/gst/validate/gst-validate-report.h b/validate/gst/validate/gst-validate-report.h
index 09db59893e..4c43aae664 100644
--- a/validate/gst/validate/gst-validate-report.h
+++ b/validate/gst/validate/gst-validate-report.h
@@ -104,6 +104,7 @@ typedef enum {
#define FILE_SEEKABLE_INCORRECT _QUARK("file-checking::seekable-incorrect")
#define FILE_PROFILE_INCORRECT _QUARK("file-checking::profile-incorrect")
#define FILE_FRAMES_INCORRECT _QUARK("file-checking::frames-incorrect")
+#define FILE_SEGMENT_INCORRECT _QUARK("file-checking::segment-incorrect")
#define ALLOCATION_FAILURE _QUARK("runtime::allocation-failure")
#define MISSING_PLUGIN _QUARK("runtime::missing-plugin")
diff --git a/validate/gst/validate/media-descriptor-parser.c b/validate/gst/validate/media-descriptor-parser.c
index 29d7849c66..c9b208a5b7 100644
--- a/validate/gst/validate/media-descriptor-parser.c
+++ b/validate/gst/validate/media-descriptor-parser.c
@@ -95,6 +95,43 @@ deserialize_streamnode (const gchar ** names, const gchar ** values)
return streamnode;
}
+static GstValidateSegmentNode *
+deserialize_segmentnode (const gchar ** names, const gchar ** values)
+{
+ gint i;
+ GstValidateSegmentNode *node = g_slice_new0 (GstValidateSegmentNode);
+
+ for (i = 0; names[i] != NULL; i++) {
+ if (!g_strcmp0 (names[i], "next-frame-id"))
+ node->next_frame_id = g_ascii_strtoull (values[i], NULL, 0);
+ else if (!g_strcmp0 (names[i], "flags"))
+ node->segment.flags = g_ascii_strtoull (values[i], NULL, 0);
+ else if (!g_strcmp0 (names[i], "rate"))
+ node->segment.rate = g_ascii_strtod (values[i], NULL);
+ else if (!g_strcmp0 (names[i], "applied-rate"))
+ node->segment.applied_rate = g_ascii_strtod (values[i], NULL);
+ else if (!g_strcmp0 (names[i], "format"))
+ node->segment.format = g_ascii_strtoull (values[i], NULL, 0);
+ else if (!g_strcmp0 (names[i], "base"))
+ node->segment.base = g_ascii_strtoull (values[i], NULL, 0);
+ else if (!g_strcmp0 (names[i], "offset"))
+ node->segment.offset = g_ascii_strtoull (values[i], NULL, 0);
+ else if (!g_strcmp0 (names[i], "start"))
+ node->segment.start = g_ascii_strtoull (values[i], NULL, 0);
+ else if (!g_strcmp0 (names[i], "stop"))
+ node->segment.stop = g_ascii_strtoull (values[i], NULL, 0);
+ else if (!g_strcmp0 (names[i], "time"))
+ node->segment.time = g_ascii_strtoull (values[i], NULL, 0);
+ else if (!g_strcmp0 (names[i], "position"))
+ node->segment.position = g_ascii_strtoull (values[i], NULL, 0);
+ else if (!g_strcmp0 (names[i], "duration"))
+ node->segment.duration = g_ascii_strtoull (values[i], NULL, 0);
+ }
+
+
+ return node;
+}
+
static GstValidateMediaTagsNode *
deserialize_tagsnode (const gchar ** names, const gchar ** values)
{
@@ -199,6 +236,13 @@ on_start_element_cb (GMarkupParseContext * context,
* 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, "segment") == 0) {
+ GstValidateMediaStreamNode *streamnode = filenode->streams->data;
+ GstValidateSegmentNode *node =
+ deserialize_segmentnode (attribute_names, attribute_values);
+
+ streamnode->segments = g_list_append (streamnode->segments, node);
+
} else if (g_strcmp0 (element_name, "frame") == 0) {
GstValidateMediaStreamNode *streamnode = filenode->streams->data;
diff --git a/validate/gst/validate/media-descriptor-writer.c b/validate/gst/validate/media-descriptor-writer.c
index f666f5a81a..4c93f314e8 100644
--- a/validate/gst/validate/media-descriptor-writer.c
+++ b/validate/gst/validate/media-descriptor-writer.c
@@ -146,8 +146,15 @@ serialize_filenode (GstValidateMediaDescriptorWriter * writer)
GstValidateMediaStreamNode
* snode = ((GstValidateMediaStreamNode *) tmp->data);
+
STR_APPEND2 (snode->str_open);
+ /* Segment are always prepended, let's bring them back to the right order */
+ STR_APPEND3 ("");
+ for (tmp2 = snode->segments; tmp2; tmp2 = tmp2->next)
+ STR_APPEND4 (((GstValidateSegmentNode *) tmp2->data)->str_open);
+ STR_APPEND3 ("");
+
for (tmp2 = snode->frames; tmp2; tmp2 = tmp2->next) {
STR_APPEND3 (((GstValidateMediaFrameNode *) tmp2->data)->str_open);
}
@@ -317,8 +324,28 @@ _uridecodebin_probe (GstPad * pad, GstPadProbeInfo * info,
(GstValidateMediaDescriptor *)
writer, pad);
if (streamnode) {
+ GstValidateSegmentNode *segment_node =
+ g_slice_new0 (GstValidateSegmentNode);
+
gst_event_parse_segment (event, &segment);
- gst_segment_copy_into (segment, &streamnode->segment);
+ gst_segment_copy_into (segment, &segment_node->segment);
+ segment_node->next_frame_id = g_list_length (streamnode->frames);
+
+ segment_node->str_open =
+ g_markup_printf_escaped ("", segment_node->next_frame_id,
+ segment->flags, segment->rate, segment->applied_rate,
+ segment->format, segment->base, segment->offset, segment->start,
+ segment->stop, segment->time, segment->position,
+ segment->duration);
+
+ streamnode->segments =
+ g_list_prepend (streamnode->segments, segment_node);
}
break;
}
@@ -519,8 +546,10 @@ _run_frame_analysis (GstValidateMediaDescriptorWriter * writer,
GstValidateRunner * runner, const gchar * uri)
{
GstBus *bus;
+ GList *tmp;
GstStateChangeReturn sret;
GstValidateMonitor *monitor;
+ GstValidateMediaFileNode *filenode;
GstElement *uridecodebin = gst_element_factory_make ("uridecodebin", NULL);
@@ -551,6 +580,15 @@ _run_frame_analysis (GstValidateMediaDescriptorWriter * writer,
}
g_main_loop_run (writer->priv->loop);
+
+ filenode = ((GstValidateMediaDescriptor *) writer)->filenode;
+ /* Segment are always prepended, let's reorder them. */
+ for (tmp = filenode->streams; tmp; tmp = tmp->next) {
+ GstValidateMediaStreamNode
+ * snode = ((GstValidateMediaStreamNode *) tmp->data);
+ snode->segments = g_list_reverse (snode->segments);
+ }
+
gst_element_set_state (writer->priv->pipeline, GST_STATE_NULL);
gst_object_unref (writer->priv->pipeline);
writer->priv->pipeline = NULL;
@@ -846,6 +884,7 @@ gst_validate_media_descriptor_writer_add_frame (GstValidateMediaDescriptorWriter
gchar *checksum;
guint id;
GstValidateMediaFrameNode *fnode;
+ GstSegment * segment;
g_return_val_if_fail (GST_IS_VALIDATE_MEDIA_DESCRIPTOR_WRITER (writer),
FALSE);
@@ -877,8 +916,11 @@ gst_validate_media_descriptor_writer_add_frame (GstValidateMediaDescriptorWriter
fnode->duration = GST_BUFFER_DURATION (buf);
fnode->pts = GST_BUFFER_PTS (buf);
fnode->dts = GST_BUFFER_DTS (buf);
+
+ g_assert (streamnode->segments);
+ segment = &((GstValidateSegmentNode *)streamnode->segments->data)->segment;
fnode->running_time =
- gst_segment_to_running_time (&streamnode->segment, GST_FORMAT_TIME,
+ gst_segment_to_running_time (segment, GST_FORMAT_TIME,
GST_BUFFER_PTS (buf));
fnode->is_keyframe =
(GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT) == FALSE);
diff --git a/validate/gst/validate/media-descriptor.c b/validate/gst/validate/media-descriptor.c
index b4cf758899..831812a6be 100644
--- a/validate/gst/validate/media-descriptor.c
+++ b/validate/gst/validate/media-descriptor.c
@@ -62,6 +62,15 @@ free_framenode (GstValidateMediaFrameNode * framenode)
g_slice_free (GstValidateMediaFrameNode, framenode);
}
+static inline void
+free_segmentnode (GstValidateSegmentNode * segmentnode)
+{
+ g_free (segmentnode->str_open);
+ g_free (segmentnode->str_close);
+
+ g_slice_free (GstValidateSegmentNode, segmentnode);
+}
+
static inline void
free_streamnode (GstValidateMediaStreamNode * streamnode)
{
@@ -69,6 +78,7 @@ free_streamnode (GstValidateMediaStreamNode * streamnode)
gst_caps_unref (streamnode->caps);
g_list_free_full (streamnode->frames, (GDestroyNotify) free_framenode);
+ g_list_free_full (streamnode->segments, (GDestroyNotify) free_segmentnode);
if (streamnode->pad)
gst_object_unref (streamnode->pad);
@@ -337,6 +347,103 @@ stream_id_is_equal (const gchar * uri, const gchar * rid, const gchar * cid)
return FALSE;
}
+static gboolean
+compare_segments (GstValidateMediaDescriptor * ref,
+ gint i,
+ GstValidateMediaStreamNode * rstream,
+ GstValidateSegmentNode * rsegment, GstValidateSegmentNode * csegment)
+{
+ if (rsegment->next_frame_id != csegment->next_frame_id) {
+ GST_VALIDATE_REPORT (ref, FILE_SEGMENT_INCORRECT,
+ "Segment %" GST_SEGMENT_FORMAT
+ " didn't come before the same frame ID, expected to come before %d, came before %d",
+ &rsegment->segment, rsegment->next_frame_id, csegment->next_frame_id);
+ return FALSE;
+ }
+#define CHECK_SEGMENT_FIELD(fieldname, format) \
+ if (rsegment->segment.fieldname != csegment->segment.fieldname) { \
+ GST_ERROR ("Expected: %" GST_SEGMENT_FORMAT " got: %" GST_SEGMENT_FORMAT, \
+ &rsegment->segment, &csegment->segment); \
+ GST_VALIDATE_REPORT (ref, FILE_SEGMENT_INCORRECT, \
+ "Stream %s segment %d has " #fieldname \
+ " mismatch, Expected " format " got: " format , \
+ rstream->id, i, rsegment->segment.fieldname, \
+ csegment->segment.fieldname); \
+ return FALSE; \
+ }
+
+ CHECK_SEGMENT_FIELD (flags, "%d");
+ CHECK_SEGMENT_FIELD (rate, "%f");
+ CHECK_SEGMENT_FIELD (applied_rate, "%f");
+ CHECK_SEGMENT_FIELD (base, "%" G_GUINT64_FORMAT);
+ CHECK_SEGMENT_FIELD (offset, "%" G_GUINT64_FORMAT);
+ CHECK_SEGMENT_FIELD (start, "%" G_GUINT64_FORMAT);
+ CHECK_SEGMENT_FIELD (stop, "%" G_GUINT64_FORMAT);
+ CHECK_SEGMENT_FIELD (time, "%" G_GUINT64_FORMAT);
+ CHECK_SEGMENT_FIELD (position, "%" G_GUINT64_FORMAT);
+ CHECK_SEGMENT_FIELD (duration, "%" G_GUINT64_FORMAT);
+
+ return TRUE;
+}
+
+static void
+append_segment_diff (GString * diff, char diffsign, GList * segments)
+{
+ GList *tmp;
+
+ for (tmp = segments; tmp; tmp = tmp->next) {
+ gchar *ssegment =
+ gst_info_strdup_printf ("%c %" GST_SEGMENT_FORMAT "\n", diffsign,
+ &((GstValidateSegmentNode *) tmp->data)->segment);
+ g_string_append (diff, ssegment);
+ g_free (ssegment);
+
+ }
+}
+
+static gboolean
+compare_segment_list (GstValidateMediaDescriptor * ref,
+ GstValidateMediaStreamNode * rstream, GstValidateMediaStreamNode * cstream)
+{
+ gint i;
+ GList *rsegments, *csegments;
+
+ /* Keep compatibility with media stream files that do not have segments */
+ if (rstream->segments
+ && g_list_length (rstream->segments) !=
+ g_list_length (cstream->segments)) {
+ GString *diff = g_string_new (NULL);
+
+ append_segment_diff (diff, '-', rstream->segments);
+ append_segment_diff (diff, '+', cstream->segments);
+ GST_VALIDATE_REPORT (ref, FILE_SEGMENT_INCORRECT,
+ "Stream reference has %i segments, compared one has %i segments\n%s",
+ g_list_length (rstream->segments), g_list_length (cstream->segments),
+ diff->str);
+ g_string_free (diff, TRUE);
+ }
+
+ for (i = 0, rsegments = rstream->segments, csegments = cstream->segments;
+ rsegments;
+ rsegments = rsegments->next, csegments = csegments->next, i++) {
+ GstValidateSegmentNode *rsegment, *csegment;
+
+ if (csegment == NULL) {
+ /* The list was checked to be of the same size */
+ g_assert_not_reached ();
+ return FALSE;
+ }
+
+ rsegment = rsegments->data;
+ csegment = csegments->data;
+
+ if (!compare_segments (ref, i, rstream, rsegment, csegment))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static gboolean
compare_frames (GstValidateMediaDescriptor * ref,
GstValidateMediaStreamNode *
@@ -445,6 +552,8 @@ compare_streams (GstValidateMediaDescriptor * ref,
/* We ignore the return value on purpose as this is not critical */
compare_tags (ref, rstream, cstream);
+ compare_segment_list (ref, rstream, cstream);
+
if (compare_frames_list (ref, rstream, cstream))
return 1;
return 0;
diff --git a/validate/gst/validate/media-descriptor.h b/validate/gst/validate/media-descriptor.h
index 3079cfab7f..25c7c9ad34 100644
--- a/validate/gst/validate/media-descriptor.h
+++ b/validate/gst/validate/media-descriptor.h
@@ -82,7 +82,7 @@ typedef struct
/* Attributes */
GstCaps *caps;
- GstSegment segment;
+ GList * segments;
gchar *id;
gchar *padname;
@@ -112,6 +112,16 @@ typedef struct
gchar *str_close;
} GstValidateMediaFrameNode;
+typedef struct
+{
+ gint next_frame_id;
+
+ GstSegment segment;
+
+ gchar *str_open;
+ gchar *str_close;
+} GstValidateSegmentNode;
+
GST_VALIDATE_API
void gst_validate_filenode_free (GstValidateMediaFileNode *
filenode);