summaryrefslogtreecommitdiffstats
path: root/gst
diff options
context:
space:
mode:
authorArwed v. Merkatz <v.merkatz@gmx.net>2004-09-01 12:10:21 +0000
committerArwed v. Merkatz <v.merkatz@gmx.net>2004-09-01 12:10:21 +0000
commite83fb2a3c26a1a704a59e3eb03465782535e62e0 (patch)
tree2c553a98df11deb0083bc39fc03a84cb874f2978 /gst
parent5488fa27bc7f727adb4edd2e14da4012119e52d7 (diff)
Write track and segment UIDs, write muxing date, write TRACKDEFAULTDURATION for TTA audio, write BLOCKDURATION if known.
Original commit message from CVS: Write track and segment UIDs, write muxing date, write TRACKDEFAULTDURATION for TTA audio, write BLOCKDURATION if known.
Diffstat (limited to 'gst')
-rw-r--r--gst/matroska/ebml-ids.h3
-rw-r--r--gst/matroska/ebml-read.c9
-rw-r--r--gst/matroska/ebml-write.c3
-rw-r--r--gst/matroska/matroska-ids.h1
-rw-r--r--gst/matroska/matroska-mux.c70
5 files changed, 77 insertions, 9 deletions
diff --git a/gst/matroska/ebml-ids.h b/gst/matroska/ebml-ids.h
index 329f036c..0dd120c3 100644
--- a/gst/matroska/ebml-ids.h
+++ b/gst/matroska/ebml-ids.h
@@ -42,6 +42,9 @@ G_BEGIN_DECLS
/* general EBML types */
#define GST_EBML_ID_VOID 0xEC
+/* EbmlDate offset from the unix epoch in seconds, 2001/01/01 00:00:00 UTC */
+#define GST_EBML_DATE_OFFSET 978307200
+
G_END_DECLS
#endif /* __GST_EBML_IDS_H__ */
diff --git a/gst/matroska/ebml-read.c b/gst/matroska/ebml-read.c
index 00d353dd..db5d4a5c 100644
--- a/gst/matroska/ebml-read.c
+++ b/gst/matroska/ebml-read.c
@@ -591,13 +591,18 @@ gst_ebml_read_utf8 (GstEbmlRead * ebml, guint32 * id, gchar ** str)
}
/*
- * Read the next element as a date (nanoseconds since 1/1/2000).
+ * Read the next element as a date.
+ * Returns the seconds since the unix epoch.
*/
gboolean
gst_ebml_read_date (GstEbmlRead * ebml, guint32 * id, gint64 * date)
{
- return gst_ebml_read_sint (ebml, id, date);
+ gint64 ebml_date;
+ gboolean res = gst_ebml_read_sint (ebml, id, &ebml_date);
+
+ *date = (ebml_date / GST_SECOND) + GST_EBML_DATE_OFFSET;
+ return res;
}
/*
diff --git a/gst/matroska/ebml-write.c b/gst/matroska/ebml-write.c
index 30a9c420..1ca54ca3 100644
--- a/gst/matroska/ebml-write.c
+++ b/gst/matroska/ebml-write.c
@@ -430,10 +430,11 @@ gst_ebml_write_utf8 (GstEbmlWrite * ebml, guint32 id, const gchar * str)
gst_ebml_write_ascii (ebml, id, str);
}
+/* date should be in seconds since the unix epoch */
void
gst_ebml_write_date (GstEbmlWrite * ebml, guint32 id, gint64 date)
{
- gst_ebml_write_sint (ebml, id, date);
+ gst_ebml_write_sint (ebml, id, (date - GST_EBML_DATE_OFFSET) * GST_SECOND);
}
/*
diff --git a/gst/matroska/matroska-ids.h b/gst/matroska/matroska-ids.h
index ba55f20b..6c423385 100644
--- a/gst/matroska/matroska-ids.h
+++ b/gst/matroska/matroska-ids.h
@@ -45,6 +45,7 @@
#define GST_MATROSKA_ID_WRITINGAPP 0x5741
#define GST_MATROSKA_ID_MUXINGAPP 0x4D80
#define GST_MATROSKA_ID_DATEUTC 0x4461
+#define GST_MATROSKA_ID_SEGMENTUID 0x73A4
/* ID in the tracks master */
#define GST_MATROSKA_ID_TRACKENTRY 0xAE
diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c
index fc39cb67..a37e008e 100644
--- a/gst/matroska/matroska-mux.c
+++ b/gst/matroska/matroska-mux.c
@@ -114,6 +114,8 @@ GST_STATIC_PAD_TEMPLATE ("subtitle_%d",
GST_PAD_REQUEST,
GST_STATIC_CAPS_ANY);
+static GArray *used_uids;
+
/* gobject magic foo */
static void gst_matroska_mux_base_init (GstMatroskaMuxClass * klass);
static void gst_matroska_mux_class_init (GstMatroskaMuxClass * klass);
@@ -139,6 +141,9 @@ static void gst_matroska_mux_get_property (GObject * object,
/* reset muxer */
static void gst_matroska_mux_reset (GstElement * element);
+/* uid generation */
+static guint32 gst_matroska_mux_create_uid ();
+
static GstEbmlWriteClass *parent_class = NULL;
/*static guint gst_matroska_mux_signals[LAST_SIGNAL] = { 0 };*/
@@ -242,6 +247,28 @@ gst_matroska_mux_init (GstMatroskaMux * mux)
gst_matroska_mux_reset (GST_ELEMENT (mux));
}
+static guint32
+gst_matroska_mux_create_uid ()
+{
+ guint32 uid = 0;
+ GRand *rand = g_rand_new ();
+
+ while (!uid) {
+ guint i;
+
+ uid = g_rand_int (rand);
+ for (i = 0; i < used_uids->len; i++) {
+ if (g_array_index (used_uids, guint32, i) == uid) {
+ uid = 0;
+ break;
+ }
+ }
+ g_array_append_val (used_uids, uid);
+ }
+ g_free (rand);
+ return uid;
+}
+
static void
gst_matroska_mux_reset (GstElement * element)
{
@@ -289,6 +316,13 @@ gst_matroska_mux_reset (GstElement * element)
/* reset timers */
mux->time_scale = 1000000;
mux->duration = 0;
+
+ /* reset uid array */
+ if (used_uids) {
+ g_free (used_uids);
+ }
+ /* arbitrary size, 10 should be enough in most cases */
+ used_uids = g_array_sized_new (FALSE, FALSE, sizeof (guint32), 10);
}
static GstPadLinkReturn
@@ -468,6 +502,7 @@ gst_matroska_mux_audio_pad_link (GstPad * pad, const GstCaps * caps)
audiocontext->samplerate = samplerate;
audiocontext->channels = channels;
audiocontext->bitdepth = 0;
+ context->default_duration = 0;
if (!strcmp (mimetype, "audio/mpeg")) {
gint mpegversion = 0;
@@ -530,6 +565,9 @@ gst_matroska_mux_audio_pad_link (GstPad * pad, const GstCaps * caps)
} else if (!strcmp (mimetype, "audio/x-raw-tta")) {
gint width;
+ /* TTA frame duration */
+ context->default_duration = 1.04489795918367346939 * GST_SECOND;
+
gst_structure_get_int (structure, "width", &width);
audiocontext->bitdepth = width;
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_TTA);
@@ -610,16 +648,19 @@ gst_matroska_mux_track_header (GstMatroskaMux * mux,
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKNUMBER, context->num);
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKTYPE, context->type);
+ gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKUID,
+ gst_matroska_mux_create_uid ());
+ if (context->default_duration) {
+ gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKDEFAULTDURATION,
+ context->default_duration);
+ }
+
/* type-specific stuff */
switch (context->type) {
case GST_MATROSKA_TRACK_TYPE_VIDEO:{
GstMatroskaTrackVideoContext *videocontext =
(GstMatroskaTrackVideoContext *) context;
- /* framerate, but not in the video part */
- gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKDEFAULTDURATION,
- context->default_duration);
-
master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKVIDEO);
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOPIXELWIDTH,
videocontext->pixel_width);
@@ -697,6 +738,9 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
gint i;
guint tracknum = 1;
gdouble duration = 0;
+ guint32 *segment_uid = (guint32 *) g_malloc (16);
+ GRand *rand = g_rand_new ();
+ GTimeVal time = { 0, 0 };
/* we start with a EBML header */
gst_ebml_write_header (ebml, "matroska", 1);
@@ -723,6 +767,12 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
/* segment info */
mux->info_pos = ebml->pos;
master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_INFO);
+ for (i = 0; i < 4; i++) {
+ segment_uid[i] = g_rand_int (rand);
+ }
+ g_free (rand);
+ gst_ebml_write_binary (ebml, GST_MATROSKA_ID_SEGMENTUID,
+ (guint8 *) segment_uid, 16);
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TIMECODESCALE, mux->time_scale);
mux->duration_pos = ebml->pos;
/* get duration */
@@ -752,8 +802,8 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_WRITINGAPP, app);
}
}
- /* FIXME: how do I get this? Automatic? Via tags? */
- /*gst_ebml_write_date (ebml, GST_MATROSKA_ID_DATEUTC, 0); */
+ g_get_current_time (&time);
+ gst_ebml_write_date (ebml, GST_MATROSKA_ID_DATEUTC, time.tv_sec);
gst_ebml_write_master_finish (ebml, master);
/* tracks */
@@ -956,6 +1006,14 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux)
GST_BUFFER_DATA (hdr)[3] = 0;
gst_ebml_write_buffer (ebml, hdr);
gst_ebml_write_buffer (ebml, buf);
+ if (GST_BUFFER_DURATION_IS_VALID (buf)) {
+ guint64 block_duration = GST_BUFFER_DURATION (buf);
+
+ if (block_duration != mux->sink[i].track->default_duration) {
+ gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION,
+ block_duration / mux->time_scale);
+ }
+ }
gst_ebml_write_master_finish (ebml, blockgroup);
gst_ebml_write_master_finish (ebml, cluster);
}