matroskamux: set delta unit on all buffers except cluster start ones

This commit is contained in:
Zaheer Abbas Merali 2010-05-21 14:35:34 +01:00
parent d3daa12473
commit ec23b22d29
3 changed files with 55 additions and 40 deletions

View file

@ -212,7 +212,7 @@ gst_ebml_write_set_cache (GstEbmlWrite * ebml, guint size)
* Flush the cache.
*/
void
gst_ebml_write_flush_cache (GstEbmlWrite * ebml)
gst_ebml_write_flush_cache (GstEbmlWrite * ebml, gboolean is_keyframe)
{
GstBuffer *buffer;
@ -226,7 +226,7 @@ gst_ebml_write_flush_cache (GstEbmlWrite * ebml)
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;
@ -234,6 +234,9 @@ gst_ebml_write_flush_cache (GstEbmlWrite * ebml)
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);
@ -403,6 +406,7 @@ gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf)
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);
@ -446,13 +450,14 @@ gst_ebml_write_seek (GstEbmlWrite * ebml, guint64 pos)
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);
}
@ -773,6 +778,7 @@ gst_ebml_replace_uint (GstEbmlWrite * ebml, guint64 pos, guint64 num)
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);
@ -810,5 +816,5 @@ gst_ebml_write_header (GstEbmlWrite * ebml, const gchar * doctype,
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);
}

View file

@ -84,7 +84,8 @@ GstBuffer* gst_ebml_stop_streamheader (GstEbmlWrite *ebml);
*/
void gst_ebml_write_set_cache (GstEbmlWrite *ebml,
guint size);
void gst_ebml_write_flush_cache (GstEbmlWrite *ebml);
void gst_ebml_write_flush_cache (GstEbmlWrite *ebml,
gboolean is_keyframe);
/*
* Seeking.

View file

@ -2005,7 +2005,6 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
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");
@ -2016,7 +2015,6 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
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 */
@ -2108,30 +2106,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
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
@ -2240,7 +2215,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
}
gst_ebml_write_master_finish (ebml, master);
gst_ebml_write_flush_cache (ebml);
gst_ebml_write_flush_cache (ebml, FALSE);
}
/* tags */
@ -2271,6 +2246,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
* - 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,
@ -2348,6 +2324,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
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);
}
@ -2496,6 +2473,34 @@ gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux,
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
@ -2563,8 +2568,8 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
/* 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);
@ -2572,7 +2577,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
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);
@ -2585,7 +2590,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
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);
}
@ -2662,12 +2667,12 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
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);
@ -2682,7 +2687,7 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
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);
}
@ -2702,6 +2707,7 @@ static GstFlowReturn
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;
@ -2716,7 +2722,9 @@ gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
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;
}