#define GST_MATROSKA_ID_CODECDOWNLOADURL 0x26B240
/* semi-draft */
#define GST_MATROSKA_ID_CODECDECODEALL 0xAA
+#define GST_MATROSKA_ID_SEEKPREROLL 0x56BB
+#define GST_MATROSKA_ID_CODECDELAY 0x56AA
/* IDs in the TrackTranslate master */
#define GST_MATROSKA_ID_TRACKTRANSLATEEDITIONUID 0x66FC
/* semi-draft */
#define GST_MATROSKA_ID_CODECSTATE 0xA4
#define GST_MATROSKA_ID_SLICES 0x8E
+#define GST_MATROSKA_ID_DISCARDPADDING 0x75A2
/* IDs in the BlockAdditions master */
#define GST_MATROSKA_ID_BLOCKMORE 0xA6
guint64 default_duration;
guint64 pos;
gdouble timecodescale;
+ guint64 seek_preroll;
+ guint64 codec_delay;
gboolean set_discont; /* TRUE = set DISCONT flag on next buffer */
context->codec_priv = g_malloc0 (context->codec_priv_size);
gst_buffer_extract (buf, 0, context->codec_priv, -1);
+ context->codec_delay =
+ GST_READ_UINT16_LE ((guint8 *) context->codec_priv + 10);
+ context->codec_delay =
+ gst_util_uint64_scale_round (context->codec_delay, GST_SECOND, 48000);
+ context->seek_preroll = 80 * GST_MSECOND;
+
return TRUE;
/* ERRORS */
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_AUDIOBITDEPTH,
audiocontext->bitdepth);
}
+
gst_ebml_write_master_finish (ebml, master);
break;
if (context->codec_priv)
gst_ebml_write_binary (ebml, GST_MATROSKA_ID_CODECPRIVATE,
context->codec_priv, context->codec_priv_size);
+
+ if (context->seek_preroll) {
+ gst_ebml_write_uint (ebml, GST_MATROSKA_ID_SEEKPREROLL,
+ context->seek_preroll);
+ }
+
+ if (context->codec_delay) {
+ gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CODECDELAY,
+ context->codec_delay);
+ }
}
#if 0
gboolean write_duration;
gint16 relative_timestamp;
gint64 relative_timestamp64;
- guint64 block_duration;
+ guint64 block_duration, duration_diff = 0;
gboolean is_video_keyframe = FALSE;
gboolean is_video_invisible = FALSE;
GstMatroskamuxPad *pad;
gint flags = 0;
GstClockTime buffer_timestamp;
+ GstAudioClippingMeta *cmeta = NULL;
/* write data */
pad = GST_MATROSKAMUX_PAD_CAST (collect_pad->collect.pad);
return GST_FLOW_OK;
}
+ if (!strcmp (collect_pad->track->codec_id, GST_MATROSKA_CODEC_ID_AUDIO_OPUS)
+ && collect_pad->track->codec_delay) {
+ /* All timestamps should include the codec delay */
+ if (buffer_timestamp > collect_pad->track->codec_delay) {
+ buffer_timestamp += collect_pad->track->codec_delay;
+ } else {
+ buffer_timestamp = 0;
+ duration_diff = collect_pad->track->codec_delay - buffer_timestamp;
+ }
+ }
+
/* set the timestamp for outgoing buffers */
ebml->timestamp = buffer_timestamp;
write_duration = FALSE;
block_duration = 0;
if (pad->frame_duration && GST_BUFFER_DURATION_IS_VALID (buf)) {
- block_duration = gst_util_uint64_scale (GST_BUFFER_DURATION (buf),
- 1, mux->time_scale);
+ block_duration = GST_BUFFER_DURATION (buf) + duration_diff;
+ block_duration = gst_util_uint64_scale (block_duration, 1, mux->time_scale);
/* small difference should be ok. */
if (block_duration > collect_pad->default_duration_scaled + 1 ||
if (is_video_invisible)
flags |= 0x08;
- if (mux->doctype_version > 1 && !write_duration) {
+ if (!strcmp (collect_pad->track->codec_id, GST_MATROSKA_CODEC_ID_AUDIO_OPUS)) {
+ cmeta = gst_buffer_get_audio_clipping_meta (buf);
+ g_assert (!cmeta || cmeta->format == GST_FORMAT_DEFAULT);
+
+ /* Start clipping is done via header and CodecDelay */
+ if (cmeta && !cmeta->end)
+ cmeta = NULL;
+ }
+
+ if (mux->doctype_version > 1 && !write_duration && !cmeta) {
if (is_video_keyframe)
flags |= 0x80;
relative_timestamp, flags);
if (write_duration)
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION, block_duration);
+
+ if (!strcmp (collect_pad->track->codec_id, GST_MATROSKA_CODEC_ID_AUDIO_OPUS)
+ && cmeta) {
+ /* Start clipping is done via header and CodecDelay */
+ if (cmeta->end) {
+ guint64 end =
+ gst_util_uint64_scale_round (cmeta->end, GST_SECOND, 48000);
+ gst_ebml_write_sint (ebml, GST_MATROSKA_ID_DISCARDPADDING, end);
+ }
+ }
+
gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK,
gst_buffer_get_size (buf) + gst_buffer_get_size (hdr));
gst_ebml_write_buffer (ebml, hdr);