dashdemux: parse xs:dateTime's timezone indicator

The lexical form of xs:dateTime is YYYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]
timezone indicator (+|-)hh:mm] needs to be parsed.

https://bugzilla.gnome.org/show_bug.cgi?id=791602
This commit is contained in:
Jun Xie 2017-12-14 15:18:38 +08:00 committed by Edward Hervey
parent cc58bd6ae0
commit cbcc01173b
2 changed files with 110 additions and 3 deletions

View file

@ -831,7 +831,7 @@ error:
The dateTime data type is used to specify a date and a time.
The dateTime is specified in the following form "YYYY-MM-DDThh:mm:ss" where:
The lexical form of xs:dateTime is YYYY-MM-DDThh:mm:ss[Z|(+|-)hh:mm]
* YYYY indicates the year
* MM indicates the month
@ -841,7 +841,7 @@ error:
* mm indicates the minute
* ss indicates the second
Note: All components are required!
The time zone may be specified as Z (UTC) or (+|-)hh:mm
*/
static gboolean
gst_mpdparser_get_xml_prop_dateTime (xmlNode * a_node,
@ -853,6 +853,8 @@ gst_mpdparser_get_xml_prop_dateTime (xmlNode * a_node,
gint year, month, day, hour, minute;
gdouble second;
gboolean exists = FALSE;
gfloat tzoffset = 0.0;
gint gmt_offset_hour = -99, gmt_offset_min = -99;
prop_string = xmlGetProp (a_node, (const xmlChar *) property_name);
if (prop_string) {
@ -902,9 +904,50 @@ gst_mpdparser_get_xml_prop_dateTime (xmlNode * a_node,
GST_LOG (" - %s: %4d/%02d/%02d %02d:%02d:%09.6lf", property_name,
year, month, day, hour, minute, second);
if (strrchr (str, '+') || strrchr (str, '-')){
/* reuse some code from gst-plugins-base/gst-libs/gst/tag/gstxmptag.c */
gint gmt_offset = -1;
gchar *plus_pos = NULL;
gchar *neg_pos = NULL;
gchar *pos = NULL;
GST_LOG ("Checking for timezone information");
/* check if there is timezone info */
plus_pos = strrchr (str, '+');
neg_pos = strrchr (str, '-');
if (plus_pos)
pos = plus_pos + 1;
else if (neg_pos)
pos = neg_pos + 1;
if (pos && strlen (pos) >= 3) {
gint ret_tz;
if (pos[2] == ':')
ret_tz = sscanf (pos, "%d:%d", &gmt_offset_hour, &gmt_offset_min);
else
ret_tz = sscanf (pos, "%02d%02d", &gmt_offset_hour, &gmt_offset_min);
GST_DEBUG ("Parsing timezone: %s", pos);
if (ret_tz == 2) {
if (neg_pos != NULL && neg_pos + 1 == pos) {
gmt_offset_hour *= -1;
gmt_offset_min *= -1;
}
gmt_offset = gmt_offset_hour * 60 + gmt_offset_min;
tzoffset = gmt_offset / 60.0;
GST_LOG ("Timezone offset: %f (%d minutes)", tzoffset, gmt_offset);
} else
GST_WARNING ("Failed to parse timezone information");
}
}
exists = TRUE;
*property_value =
gst_date_time_new (0, year, month, day, hour, minute, second);
gst_date_time_new (tzoffset, year, month, day, hour, minute, second);
xmlFree (prop_string);
}
@ -917,6 +960,7 @@ error:
return FALSE;
}
/*
Duration Data Type

View file

@ -5770,6 +5770,68 @@ GST_START_TEST (dash_mpdparser_xlink_period)
GST_END_TEST;
/*
* Test parsing xsd:datetime with timezoneoffset.
*
*/
GST_START_TEST (dash_mpdparser_datetime_with_tz_offset)
{
GstDateTime *availabilityStartTime;
GstDateTime *availabilityEndTime;
const gchar *xml =
"<?xml version=\"1.0\"?>"
"<MPD xmlns=\"urn:mpeg:dash:schema:mpd:2011\""
" profiles=\"urn:mpeg:dash:profile:isoff-main:2011\""
" schemaLocation=\"TestSchemaLocation\""
" xmlns:xsi=\"TestNamespaceXSI\""
" xmlns:ext=\"TestNamespaceEXT\""
" id=\"testId\""
" type=\"static\""
" availabilityStartTime=\"2015-03-24T1:10:50+08:00\""
" availabilityEndTime=\"2015-03-24T1:10:50.123456-04:30\""
" mediaPresentationDuration=\"P0Y1M2DT12H10M20.5S\""
" minimumUpdatePeriod=\"P0Y1M2DT12H10M20.5S\""
" minBufferTime=\"P0Y1M2DT12H10M20.5S\""
" timeShiftBufferDepth=\"P0Y1M2DT12H10M20.5S\""
" suggestedPresentationDelay=\"P0Y1M2DT12H10M20.5S\""
" maxSegmentDuration=\"P0Y1M2DT12H10M20.5S\""
" maxSubsegmentDuration=\"P0Y1M2DT12H10M20.5S\"></MPD>";
gboolean ret;
GstMpdClient *mpdclient = gst_mpd_client_new ();
ret = gst_mpd_parse (mpdclient, xml, (gint) strlen (xml));
assert_equals_int (ret, TRUE);
availabilityStartTime = mpdclient->mpd_node->availabilityStartTime;
assert_equals_int (gst_date_time_get_year (availabilityStartTime), 2015);
assert_equals_int (gst_date_time_get_month (availabilityStartTime), 3);
assert_equals_int (gst_date_time_get_day (availabilityStartTime), 24);
assert_equals_int (gst_date_time_get_hour (availabilityStartTime), 1);
assert_equals_int (gst_date_time_get_minute (availabilityStartTime), 10);
assert_equals_int (gst_date_time_get_second (availabilityStartTime), 50);
assert_equals_int (gst_date_time_get_microsecond (availabilityStartTime), 0);
assert_equals_float (gst_date_time_get_time_zone_offset (availabilityStartTime), 8.0);
availabilityEndTime = mpdclient->mpd_node->availabilityEndTime;
assert_equals_int (gst_date_time_get_year (availabilityEndTime), 2015);
assert_equals_int (gst_date_time_get_month (availabilityEndTime), 3);
assert_equals_int (gst_date_time_get_day (availabilityEndTime), 24);
assert_equals_int (gst_date_time_get_hour (availabilityEndTime), 1);
assert_equals_int (gst_date_time_get_minute (availabilityEndTime), 10);
assert_equals_int (gst_date_time_get_second (availabilityEndTime), 50);
assert_equals_int (gst_date_time_get_microsecond (availabilityEndTime),
123456);
assert_equals_float (gst_date_time_get_time_zone_offset (availabilityEndTime), -4.5);
gst_mpd_client_free (mpdclient);
}
GST_END_TEST;
/*
* create a test suite containing all dash testcases
*/
@ -5791,6 +5853,7 @@ dash_suite (void)
/* tests parsing attributes from each element type */
tcase_add_test (tc_simpleMPD, dash_mpdparser_mpd);
tcase_add_test (tc_simpleMPD, dash_mpdparser_datetime_with_tz_offset);
tcase_add_test (tc_simpleMPD, dash_mpdparser_programInformation);
tcase_add_test (tc_simpleMPD, dash_mpdparser_baseURL);
tcase_add_test (tc_simpleMPD, dash_mpdparser_location);