* Flush the cache.
*/
void
-gst_ebml_write_flush_cache (GstEbmlWrite * ebml)
+gst_ebml_write_flush_cache (GstEbmlWrite * ebml, gboolean is_keyframe)
{
GstBuffer *buffer;
if (ebml->last_write_result == GST_FLOW_OK) {
if (ebml->need_newsegment) {
GstEvent *ev;
-
+ GST_WARNING ("new segment being sent");
ev = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0);
if (gst_pad_push_event (ebml->srcpad, ev))
ebml->need_newsegment = FALSE;
if (ebml->writing_streamheader) {
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS);
}
+ if (!is_keyframe) {
+ GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
+ }
ebml->last_write_result = gst_pad_push (ebml->srcpad, buffer);
} else {
gst_buffer_unref (buffer);
if (ebml->writing_streamheader) {
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
}
+ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
ebml->last_write_result = gst_pad_push (ebml->srcpad, buf);
} else {
gst_buffer_unref (buf);
return;
} else {
GST_LOG ("Seek outside cache range. Clearing...");
- gst_ebml_write_flush_cache (ebml);
+ gst_ebml_write_flush_cache (ebml, FALSE);
}
}
event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, pos, -1, 0);
if (gst_pad_push_event (ebml->srcpad, event)) {
- GST_DEBUG ("Seek'd to offset %" G_GUINT64_FORMAT, pos);
+ GST_DEBUG ("Seek'd to offset %" G_GUINT64_FORMAT " from %" G_GUINT64_FORMAT,
+ pos, ebml->pos);
} else {
GST_WARNING ("Seek to offset %" G_GUINT64_FORMAT " failed", pos);
}
guint64 oldpos = ebml->pos;
GstBuffer *buf = gst_buffer_new_and_alloc (8);
+ GST_DEBUG ("replace_uint");
gst_ebml_write_seek (ebml, pos);
GST_BUFFER_SIZE (buf) = 0;
gst_ebml_write_set_uint (buf, num, 8);
gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEVERSION, version);
gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEREADVERSION, version);
gst_ebml_write_master_finish (ebml, pos);
- gst_ebml_write_flush_cache (ebml);
+ gst_ebml_write_flush_cache (ebml, FALSE);
}
GstClockTime duration = 0;
guint32 segment_uid[4];
GTimeVal time = { 0, 0 };
- GstBuffer *streamheader_buffer;
if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
ebml->caps = gst_caps_from_string ("video/webm");
doctype = mux->doctype;
GST_INFO_OBJECT (ebml, "DocType: %s, Version: %d",
doctype, mux->doctype_version);
- gst_ebml_start_streamheader (ebml);
gst_ebml_write_header (ebml, doctype, mux->doctype_version);
/* the rest of the header is cached */
gst_ebml_write_master_finish (ebml, master);
/* lastly, flush the cache */
- gst_ebml_write_flush_cache (ebml);
- streamheader_buffer = gst_ebml_stop_streamheader (ebml);
- /* lets set the pad caps, which is how the buffer caps is set currently :( */
- {
- GstCaps *caps;
- GstStructure *s;
- GValue streamheader = { 0 };
- GValue bufval = { 0 };
- if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
- caps = gst_caps_from_string ("video/webm");
- } else {
- caps = gst_caps_from_string ("video/x-matroska");
- }
- s = gst_caps_get_structure (caps, 0);
- g_value_init (&streamheader, GST_TYPE_ARRAY);
- g_value_init (&bufval, GST_TYPE_BUFFER);
- gst_value_set_buffer (&bufval, streamheader_buffer);
- gst_value_array_append_value (&streamheader, &bufval);
- g_value_unset (&bufval);
- gst_structure_set_value (s, "streamheader", &streamheader);
- g_value_unset (&streamheader);
- gst_caps_unref (ebml->caps);
- ebml->caps = caps;
- }
+ gst_ebml_write_flush_cache (ebml, FALSE);
}
static void
}
gst_ebml_write_master_finish (ebml, master);
- gst_ebml_write_flush_cache (ebml);
+ gst_ebml_write_flush_cache (ebml, FALSE);
}
/* tags */
* - all entries are local to the segment (so pos - segment_master).
* - so each entry is at 12 + 20 + num * 28. */
if (!mux->is_live) {
+ GST_DEBUG_OBJECT (mux, "not live");
gst_ebml_replace_uint (ebml, mux->seekhead_pos + 32,
mux->info_pos - mux->segment_master);
gst_ebml_replace_uint (ebml, mux->seekhead_pos + 60,
gst_ebml_write_seek (ebml, my_pos);
}
}
+ GST_DEBUG_OBJECT (mux, "finishing segment");
/* finish segment - this also writes element length */
gst_ebml_write_master_finish (ebml, mux->segment_pos);
}
return ret;
}
+static void
+gst_matroska_mux_stop_streamheader (GstMatroskaMux * mux)
+{
+ GstCaps *caps;
+ GstStructure *s;
+ GValue streamheader = { 0 };
+ GValue bufval = { 0 };
+ GstBuffer *streamheader_buffer;
+ GstEbmlWrite *ebml = mux->ebml_write;
+
+ streamheader_buffer = gst_ebml_stop_streamheader (ebml);
+ if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
+ caps = gst_caps_from_string ("video/webm");
+ } else {
+ caps = gst_caps_from_string ("video/x-matroska");
+ }
+ s = gst_caps_get_structure (caps, 0);
+ g_value_init (&streamheader, GST_TYPE_ARRAY);
+ g_value_init (&bufval, GST_TYPE_BUFFER);
+ gst_value_set_buffer (&bufval, streamheader_buffer);
+ gst_value_array_append_value (&streamheader, &bufval);
+ g_value_unset (&bufval);
+ gst_structure_set_value (s, "streamheader", &streamheader);
+ g_value_unset (&streamheader);
+ gst_caps_unref (ebml->caps);
+ ebml->caps = caps;
+}
+
/**
* gst_matroska_mux_write_data:
* @mux: #GstMatroskaMux
/* start a new cluster every two seconds or at keyframe */
if (mux->cluster_time + GST_SECOND * 2 < GST_BUFFER_TIMESTAMP (buf)
|| is_video_keyframe) {
-
- gst_ebml_write_master_finish (ebml, mux->cluster);
+ if (!mux->is_live)
+ gst_ebml_write_master_finish (ebml, mux->cluster);
mux->prev_cluster_size = ebml->pos - mux->cluster_pos;
mux->cluster_pos = ebml->pos;
gst_ebml_write_set_cache (ebml, 0x20);
gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
GST_BUFFER_TIMESTAMP (buf) / mux->time_scale);
- gst_ebml_write_flush_cache (ebml);
+ gst_ebml_write_flush_cache (ebml, TRUE);
mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_PREVSIZE,
mux->prev_cluster_size);
mux->cluster = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
GST_BUFFER_TIMESTAMP (buf) / mux->time_scale);
- gst_ebml_write_flush_cache (ebml);
+ gst_ebml_write_flush_cache (ebml, TRUE);
mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
}
gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK,
GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
gst_ebml_write_buffer (ebml, hdr);
- gst_ebml_write_flush_cache (ebml);
+ gst_ebml_write_flush_cache (ebml, FALSE);
gst_ebml_write_buffer (ebml, buf);
return gst_ebml_last_write_result (ebml);
} else {
- gst_ebml_write_set_cache (ebml, 0x40);
+ gst_ebml_write_set_cache (ebml, GST_BUFFER_SIZE (buf) * 2);
/* write and call order slightly unnatural,
* but avoids seek and minizes pushing */
blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP);
GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
gst_ebml_write_buffer (ebml, hdr);
gst_ebml_write_master_finish_full (ebml, blockgroup, GST_BUFFER_SIZE (buf));
- gst_ebml_write_flush_cache (ebml);
+ gst_ebml_write_flush_cache (ebml, FALSE);
gst_ebml_write_buffer (ebml, buf);
return gst_ebml_last_write_result (ebml);
}
gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
{
GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
+ GstEbmlWrite *ebml = mux->ebml_write;
GstMatroskaPad *best;
gboolean popped;
GstFlowReturn ret;
return GST_FLOW_ERROR;
}
mux->state = GST_MATROSKA_MUX_STATE_HEADER;
+ gst_ebml_start_streamheader (ebml);
gst_matroska_mux_start (mux);
+ gst_matroska_mux_stop_streamheader (mux);
mux->state = GST_MATROSKA_MUX_STATE_DATA;
}