matroskamux: Add property to set DateUTC

Add a property that makes it possible for an application to set the
DateUTC header field in matroska files. This is useful for live feeds,
where the DateUTC header can be set to a UTC timestamp, matching the
beginning of the file.

Needs gstreamer!323

Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/issues/481
This commit is contained in:
Linus Svensson 2018-05-31 10:29:43 +02:00
parent 0690bd1b21
commit 08060dd97b
3 changed files with 33 additions and 2 deletions

View file

@ -74,6 +74,7 @@ enum
PROP_MIN_CLUSTER_DURATION,
PROP_MAX_CLUSTER_DURATION,
PROP_OFFSET_TO_ZERO,
PROP_CREATION_TIME,
};
#define DEFAULT_DOCTYPE_VERSION 2
@ -369,6 +370,11 @@ gst_matroska_mux_class_init (GstMatroskaMuxClass * klass)
g_param_spec_boolean ("offset-to-zero", "Offset To Zero",
"Offsets all streams so that the " "earliest stream starts at 0.",
DEFAULT_OFFSET_TO_ZERO, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_CREATION_TIME,
g_param_spec_boxed ("creation-time", "Creation Time",
"Date and time of creation. This will be used for the DateUTC field."
" NULL means that the current time will be used.",
G_TYPE_DATE_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_matroska_mux_change_state);
@ -528,6 +534,7 @@ gst_matroska_mux_finalize (GObject * object)
gst_object_unref (mux->collect);
gst_object_unref (mux->ebml_write);
g_free (mux->writing_app);
g_clear_pointer (&mux->creation_time, g_date_time_unref);
if (mux->internal_toc) {
gst_toc_unref (mux->internal_toc);
@ -2960,6 +2967,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux, GstMatroskaPad * first_pad,
GstClockTime earliest_time = GST_CLOCK_TIME_NONE;
GstClockTime duration = 0;
guint32 segment_uid[4];
gint64 time;
gchar s_id[32];
GstToc *toc;
@ -3097,8 +3105,13 @@ gst_matroska_mux_start (GstMatroskaMux * mux, GstMatroskaPad * first_pad,
if (mux->writing_app && mux->writing_app[0]) {
gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_WRITINGAPP, mux->writing_app);
}
gst_ebml_write_date (ebml, GST_MATROSKA_ID_DATEUTC,
g_get_real_time () * GST_USECOND);
if (mux->creation_time != NULL) {
time = g_date_time_to_unix (mux->creation_time) * GST_SECOND;
time += g_date_time_get_microsecond (mux->creation_time) * GST_USECOND;
} else {
time = g_get_real_time () * GST_USECOND;
}
gst_ebml_write_date (ebml, GST_MATROSKA_ID_DATEUTC, time);
gst_ebml_write_master_finish (ebml, master);
/* tracks */
@ -4235,6 +4248,10 @@ gst_matroska_mux_set_property (GObject * object,
case PROP_OFFSET_TO_ZERO:
mux->offset_to_zero = g_value_get_boolean (value);
break;
case PROP_CREATION_TIME:
g_clear_pointer (&mux->creation_time, g_date_time_unref);
mux->creation_time = g_value_dup_boxed (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -4275,6 +4292,9 @@ gst_matroska_mux_get_property (GObject * object,
case PROP_OFFSET_TO_ZERO:
g_value_set_boolean (value, mux->offset_to_zero);
break;
case PROP_CREATION_TIME:
g_value_set_boxed (value, mux->creation_time);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;

View file

@ -91,6 +91,9 @@ struct _GstMatroskaMux {
/* Application name (for the writing application header element) */
gchar *writing_app;
/* Date (for the DateUTC header element) */
GDateTime *creation_time;
/* EBML DocType. */
const gchar *doctype;

View file

@ -1974,12 +1974,20 @@ gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common,
case GST_MATROSKA_ID_DATEUTC:{
gint64 time;
GstDateTime *datetime;
GstTagList *taglist;
if ((ret = gst_ebml_read_date (ebml, &id, &time)) != GST_FLOW_OK)
break;
GST_DEBUG_OBJECT (common->sinkpad, "DateUTC: %" G_GINT64_FORMAT, time);
common->created = time;
datetime =
gst_date_time_new_from_unix_epoch_utc_usecs (time / GST_USECOND);
taglist = gst_tag_list_new (GST_TAG_DATE_TIME, datetime, NULL);
gst_tag_list_set_scope (taglist, GST_TAG_SCOPE_GLOBAL);
gst_matroska_read_common_found_global_tag (common, el, taglist);
gst_date_time_unref (datetime);
break;
}