mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-04 05:22:30 +00:00
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.
This commit is contained in:
parent
5488fa27bc
commit
e83fb2a3c2
6 changed files with 91 additions and 9 deletions
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
||||||
|
2004-09-01 Arwed v. Merkatz <v.merkatz@gmx.net>
|
||||||
|
|
||||||
|
* gst/matroska/ebml-ids.h:
|
||||||
|
* gst/matroska/ebml-read.c: (gst_ebml_read_date):
|
||||||
|
* gst/matroska/ebml-write.c: (gst_ebml_write_date):
|
||||||
|
automatically convert unix time <-> ebml time when reading/writing a date
|
||||||
|
* gst/matroska/matroska-ids.h:
|
||||||
|
* gst/matroska/matroska-mux.c: (gst_matroska_mux_create_uid),
|
||||||
|
(gst_matroska_mux_reset), (gst_matroska_mux_audio_pad_link),
|
||||||
|
(gst_matroska_mux_track_header), (gst_matroska_mux_start),
|
||||||
|
(gst_matroska_mux_write_data):
|
||||||
|
Write track and segment UIDs, write muxing date, write
|
||||||
|
TRACKDEFAULTDURATION for TTA audio, write BLOCKDURATION if known.
|
||||||
|
|
||||||
2004-08-31 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
2004-08-31 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
|
||||||
* ext/alsa/gstalsamixer.c: (gst_alsa_mixer_build_list):
|
* ext/alsa/gstalsamixer.c: (gst_alsa_mixer_build_list):
|
||||||
|
|
|
@ -42,6 +42,9 @@ G_BEGIN_DECLS
|
||||||
/* general EBML types */
|
/* general EBML types */
|
||||||
#define GST_EBML_ID_VOID 0xEC
|
#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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_EBML_IDS_H__ */
|
#endif /* __GST_EBML_IDS_H__ */
|
||||||
|
|
|
@ -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
|
gboolean
|
||||||
gst_ebml_read_date (GstEbmlRead * ebml, guint32 * id, gint64 * date)
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -430,10 +430,11 @@ gst_ebml_write_utf8 (GstEbmlWrite * ebml, guint32 id, const gchar * str)
|
||||||
gst_ebml_write_ascii (ebml, id, str);
|
gst_ebml_write_ascii (ebml, id, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* date should be in seconds since the unix epoch */
|
||||||
void
|
void
|
||||||
gst_ebml_write_date (GstEbmlWrite * ebml, guint32 id, gint64 date)
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#define GST_MATROSKA_ID_WRITINGAPP 0x5741
|
#define GST_MATROSKA_ID_WRITINGAPP 0x5741
|
||||||
#define GST_MATROSKA_ID_MUXINGAPP 0x4D80
|
#define GST_MATROSKA_ID_MUXINGAPP 0x4D80
|
||||||
#define GST_MATROSKA_ID_DATEUTC 0x4461
|
#define GST_MATROSKA_ID_DATEUTC 0x4461
|
||||||
|
#define GST_MATROSKA_ID_SEGMENTUID 0x73A4
|
||||||
|
|
||||||
/* ID in the tracks master */
|
/* ID in the tracks master */
|
||||||
#define GST_MATROSKA_ID_TRACKENTRY 0xAE
|
#define GST_MATROSKA_ID_TRACKENTRY 0xAE
|
||||||
|
|
|
@ -114,6 +114,8 @@ GST_STATIC_PAD_TEMPLATE ("subtitle_%d",
|
||||||
GST_PAD_REQUEST,
|
GST_PAD_REQUEST,
|
||||||
GST_STATIC_CAPS_ANY);
|
GST_STATIC_CAPS_ANY);
|
||||||
|
|
||||||
|
static GArray *used_uids;
|
||||||
|
|
||||||
/* gobject magic foo */
|
/* gobject magic foo */
|
||||||
static void gst_matroska_mux_base_init (GstMatroskaMuxClass * klass);
|
static void gst_matroska_mux_base_init (GstMatroskaMuxClass * klass);
|
||||||
static void gst_matroska_mux_class_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 */
|
/* reset muxer */
|
||||||
static void gst_matroska_mux_reset (GstElement * element);
|
static void gst_matroska_mux_reset (GstElement * element);
|
||||||
|
|
||||||
|
/* uid generation */
|
||||||
|
static guint32 gst_matroska_mux_create_uid ();
|
||||||
|
|
||||||
static GstEbmlWriteClass *parent_class = NULL;
|
static GstEbmlWriteClass *parent_class = NULL;
|
||||||
|
|
||||||
/*static guint gst_matroska_mux_signals[LAST_SIGNAL] = { 0 };*/
|
/*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));
|
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
|
static void
|
||||||
gst_matroska_mux_reset (GstElement * element)
|
gst_matroska_mux_reset (GstElement * element)
|
||||||
{
|
{
|
||||||
|
@ -289,6 +316,13 @@ gst_matroska_mux_reset (GstElement * element)
|
||||||
/* reset timers */
|
/* reset timers */
|
||||||
mux->time_scale = 1000000;
|
mux->time_scale = 1000000;
|
||||||
mux->duration = 0;
|
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
|
static GstPadLinkReturn
|
||||||
|
@ -468,6 +502,7 @@ gst_matroska_mux_audio_pad_link (GstPad * pad, const GstCaps * caps)
|
||||||
audiocontext->samplerate = samplerate;
|
audiocontext->samplerate = samplerate;
|
||||||
audiocontext->channels = channels;
|
audiocontext->channels = channels;
|
||||||
audiocontext->bitdepth = 0;
|
audiocontext->bitdepth = 0;
|
||||||
|
context->default_duration = 0;
|
||||||
|
|
||||||
if (!strcmp (mimetype, "audio/mpeg")) {
|
if (!strcmp (mimetype, "audio/mpeg")) {
|
||||||
gint mpegversion = 0;
|
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")) {
|
} else if (!strcmp (mimetype, "audio/x-raw-tta")) {
|
||||||
gint width;
|
gint width;
|
||||||
|
|
||||||
|
/* TTA frame duration */
|
||||||
|
context->default_duration = 1.04489795918367346939 * GST_SECOND;
|
||||||
|
|
||||||
gst_structure_get_int (structure, "width", &width);
|
gst_structure_get_int (structure, "width", &width);
|
||||||
audiocontext->bitdepth = width;
|
audiocontext->bitdepth = width;
|
||||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_TTA);
|
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_TRACKNUMBER, context->num);
|
||||||
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TRACKTYPE, context->type);
|
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 */
|
/* type-specific stuff */
|
||||||
switch (context->type) {
|
switch (context->type) {
|
||||||
case GST_MATROSKA_TRACK_TYPE_VIDEO:{
|
case GST_MATROSKA_TRACK_TYPE_VIDEO:{
|
||||||
GstMatroskaTrackVideoContext *videocontext =
|
GstMatroskaTrackVideoContext *videocontext =
|
||||||
(GstMatroskaTrackVideoContext *) context;
|
(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);
|
master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TRACKVIDEO);
|
||||||
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOPIXELWIDTH,
|
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_VIDEOPIXELWIDTH,
|
||||||
videocontext->pixel_width);
|
videocontext->pixel_width);
|
||||||
|
@ -697,6 +738,9 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
|
||||||
gint i;
|
gint i;
|
||||||
guint tracknum = 1;
|
guint tracknum = 1;
|
||||||
gdouble duration = 0;
|
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 */
|
/* we start with a EBML header */
|
||||||
gst_ebml_write_header (ebml, "matroska", 1);
|
gst_ebml_write_header (ebml, "matroska", 1);
|
||||||
|
@ -723,6 +767,12 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
|
||||||
/* segment info */
|
/* segment info */
|
||||||
mux->info_pos = ebml->pos;
|
mux->info_pos = ebml->pos;
|
||||||
master = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_INFO);
|
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);
|
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_TIMECODESCALE, mux->time_scale);
|
||||||
mux->duration_pos = ebml->pos;
|
mux->duration_pos = ebml->pos;
|
||||||
/* get duration */
|
/* get duration */
|
||||||
|
@ -752,8 +802,8 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
|
||||||
gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_WRITINGAPP, app);
|
gst_ebml_write_utf8 (ebml, GST_MATROSKA_ID_WRITINGAPP, app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* FIXME: how do I get this? Automatic? Via tags? */
|
g_get_current_time (&time);
|
||||||
/*gst_ebml_write_date (ebml, GST_MATROSKA_ID_DATEUTC, 0); */
|
gst_ebml_write_date (ebml, GST_MATROSKA_ID_DATEUTC, time.tv_sec);
|
||||||
gst_ebml_write_master_finish (ebml, master);
|
gst_ebml_write_master_finish (ebml, master);
|
||||||
|
|
||||||
/* tracks */
|
/* tracks */
|
||||||
|
@ -956,6 +1006,14 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux)
|
||||||
GST_BUFFER_DATA (hdr)[3] = 0;
|
GST_BUFFER_DATA (hdr)[3] = 0;
|
||||||
gst_ebml_write_buffer (ebml, hdr);
|
gst_ebml_write_buffer (ebml, hdr);
|
||||||
gst_ebml_write_buffer (ebml, buf);
|
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, blockgroup);
|
||||||
gst_ebml_write_master_finish (ebml, cluster);
|
gst_ebml_write_master_finish (ebml, cluster);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue