mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-06 07:28:53 +00:00
matroskamux: set delta unit on all buffers except cluster start ones
This commit is contained in:
parent
d3daa12473
commit
ec23b22d29
3 changed files with 55 additions and 40 deletions
|
@ -212,7 +212,7 @@ gst_ebml_write_set_cache (GstEbmlWrite * ebml, guint size)
|
||||||
* Flush the cache.
|
* Flush the cache.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gst_ebml_write_flush_cache (GstEbmlWrite * ebml)
|
gst_ebml_write_flush_cache (GstEbmlWrite * ebml, gboolean is_keyframe)
|
||||||
{
|
{
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ gst_ebml_write_flush_cache (GstEbmlWrite * ebml)
|
||||||
if (ebml->last_write_result == GST_FLOW_OK) {
|
if (ebml->last_write_result == GST_FLOW_OK) {
|
||||||
if (ebml->need_newsegment) {
|
if (ebml->need_newsegment) {
|
||||||
GstEvent *ev;
|
GstEvent *ev;
|
||||||
|
GST_WARNING ("new segment being sent");
|
||||||
ev = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0);
|
ev = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0);
|
||||||
if (gst_pad_push_event (ebml->srcpad, ev))
|
if (gst_pad_push_event (ebml->srcpad, ev))
|
||||||
ebml->need_newsegment = FALSE;
|
ebml->need_newsegment = FALSE;
|
||||||
|
@ -234,6 +234,9 @@ gst_ebml_write_flush_cache (GstEbmlWrite * ebml)
|
||||||
if (ebml->writing_streamheader) {
|
if (ebml->writing_streamheader) {
|
||||||
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS);
|
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);
|
ebml->last_write_result = gst_pad_push (ebml->srcpad, buffer);
|
||||||
} else {
|
} else {
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
|
@ -403,6 +406,7 @@ gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf)
|
||||||
if (ebml->writing_streamheader) {
|
if (ebml->writing_streamheader) {
|
||||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
|
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);
|
ebml->last_write_result = gst_pad_push (ebml->srcpad, buf);
|
||||||
} else {
|
} else {
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
|
@ -446,13 +450,14 @@ gst_ebml_write_seek (GstEbmlWrite * ebml, guint64 pos)
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
GST_LOG ("Seek outside cache range. Clearing...");
|
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);
|
event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, pos, -1, 0);
|
||||||
if (gst_pad_push_event (ebml->srcpad, event)) {
|
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 {
|
} else {
|
||||||
GST_WARNING ("Seek to offset %" G_GUINT64_FORMAT " failed", pos);
|
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;
|
guint64 oldpos = ebml->pos;
|
||||||
GstBuffer *buf = gst_buffer_new_and_alloc (8);
|
GstBuffer *buf = gst_buffer_new_and_alloc (8);
|
||||||
|
|
||||||
|
GST_DEBUG ("replace_uint");
|
||||||
gst_ebml_write_seek (ebml, pos);
|
gst_ebml_write_seek (ebml, pos);
|
||||||
GST_BUFFER_SIZE (buf) = 0;
|
GST_BUFFER_SIZE (buf) = 0;
|
||||||
gst_ebml_write_set_uint (buf, num, 8);
|
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_DOCTYPEVERSION, version);
|
||||||
gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEREADVERSION, version);
|
gst_ebml_write_uint (ebml, GST_EBML_ID_DOCTYPEREADVERSION, version);
|
||||||
gst_ebml_write_master_finish (ebml, pos);
|
gst_ebml_write_master_finish (ebml, pos);
|
||||||
gst_ebml_write_flush_cache (ebml);
|
gst_ebml_write_flush_cache (ebml, FALSE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,8 @@ GstBuffer* gst_ebml_stop_streamheader (GstEbmlWrite *ebml);
|
||||||
*/
|
*/
|
||||||
void gst_ebml_write_set_cache (GstEbmlWrite *ebml,
|
void gst_ebml_write_set_cache (GstEbmlWrite *ebml,
|
||||||
guint size);
|
guint size);
|
||||||
void gst_ebml_write_flush_cache (GstEbmlWrite *ebml);
|
void gst_ebml_write_flush_cache (GstEbmlWrite *ebml,
|
||||||
|
gboolean is_keyframe);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Seeking.
|
* Seeking.
|
||||||
|
|
|
@ -2005,7 +2005,6 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
|
||||||
GstClockTime duration = 0;
|
GstClockTime duration = 0;
|
||||||
guint32 segment_uid[4];
|
guint32 segment_uid[4];
|
||||||
GTimeVal time = { 0, 0 };
|
GTimeVal time = { 0, 0 };
|
||||||
GstBuffer *streamheader_buffer;
|
|
||||||
|
|
||||||
if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
|
if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
|
||||||
ebml->caps = gst_caps_from_string ("video/webm");
|
ebml->caps = gst_caps_from_string ("video/webm");
|
||||||
|
@ -2016,7 +2015,6 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
|
||||||
doctype = mux->doctype;
|
doctype = mux->doctype;
|
||||||
GST_INFO_OBJECT (ebml, "DocType: %s, Version: %d",
|
GST_INFO_OBJECT (ebml, "DocType: %s, Version: %d",
|
||||||
doctype, mux->doctype_version);
|
doctype, mux->doctype_version);
|
||||||
gst_ebml_start_streamheader (ebml);
|
|
||||||
gst_ebml_write_header (ebml, doctype, mux->doctype_version);
|
gst_ebml_write_header (ebml, doctype, mux->doctype_version);
|
||||||
|
|
||||||
/* the rest of the header is cached */
|
/* the rest of the header is cached */
|
||||||
|
@ -2108,30 +2106,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
|
||||||
gst_ebml_write_master_finish (ebml, master);
|
gst_ebml_write_master_finish (ebml, master);
|
||||||
|
|
||||||
/* lastly, flush the cache */
|
/* lastly, flush the cache */
|
||||||
gst_ebml_write_flush_cache (ebml);
|
gst_ebml_write_flush_cache (ebml, FALSE);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2240,7 +2215,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_ebml_write_master_finish (ebml, master);
|
gst_ebml_write_master_finish (ebml, master);
|
||||||
gst_ebml_write_flush_cache (ebml);
|
gst_ebml_write_flush_cache (ebml, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tags */
|
/* tags */
|
||||||
|
@ -2271,6 +2246,7 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
|
||||||
* - all entries are local to the segment (so pos - segment_master).
|
* - all entries are local to the segment (so pos - segment_master).
|
||||||
* - so each entry is at 12 + 20 + num * 28. */
|
* - so each entry is at 12 + 20 + num * 28. */
|
||||||
if (!mux->is_live) {
|
if (!mux->is_live) {
|
||||||
|
GST_DEBUG_OBJECT (mux, "not live");
|
||||||
gst_ebml_replace_uint (ebml, mux->seekhead_pos + 32,
|
gst_ebml_replace_uint (ebml, mux->seekhead_pos + 32,
|
||||||
mux->info_pos - mux->segment_master);
|
mux->info_pos - mux->segment_master);
|
||||||
gst_ebml_replace_uint (ebml, mux->seekhead_pos + 60,
|
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_ebml_write_seek (ebml, my_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
GST_DEBUG_OBJECT (mux, "finishing segment");
|
||||||
/* finish segment - this also writes element length */
|
/* finish segment - this also writes element length */
|
||||||
gst_ebml_write_master_finish (ebml, mux->segment_pos);
|
gst_ebml_write_master_finish (ebml, mux->segment_pos);
|
||||||
}
|
}
|
||||||
|
@ -2496,6 +2473,34 @@ gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux,
|
||||||
return ret;
|
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:
|
* gst_matroska_mux_write_data:
|
||||||
* @mux: #GstMatroskaMux
|
* @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 */
|
/* start a new cluster every two seconds or at keyframe */
|
||||||
if (mux->cluster_time + GST_SECOND * 2 < GST_BUFFER_TIMESTAMP (buf)
|
if (mux->cluster_time + GST_SECOND * 2 < GST_BUFFER_TIMESTAMP (buf)
|
||||||
|| is_video_keyframe) {
|
|| is_video_keyframe) {
|
||||||
|
if (!mux->is_live)
|
||||||
gst_ebml_write_master_finish (ebml, mux->cluster);
|
gst_ebml_write_master_finish (ebml, mux->cluster);
|
||||||
mux->prev_cluster_size = ebml->pos - mux->cluster_pos;
|
mux->prev_cluster_size = ebml->pos - mux->cluster_pos;
|
||||||
mux->cluster_pos = ebml->pos;
|
mux->cluster_pos = ebml->pos;
|
||||||
gst_ebml_write_set_cache (ebml, 0x20);
|
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_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
|
||||||
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
|
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
|
||||||
GST_BUFFER_TIMESTAMP (buf) / mux->time_scale);
|
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);
|
mux->cluster_time = GST_BUFFER_TIMESTAMP (buf);
|
||||||
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_PREVSIZE,
|
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_PREVSIZE,
|
||||||
mux->prev_cluster_size);
|
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);
|
mux->cluster = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_CLUSTER);
|
||||||
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
|
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_CLUSTERTIMECODE,
|
||||||
GST_BUFFER_TIMESTAMP (buf) / mux->time_scale);
|
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);
|
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_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK,
|
||||||
GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
|
GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
|
||||||
gst_ebml_write_buffer (ebml, 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);
|
gst_ebml_write_buffer (ebml, buf);
|
||||||
|
|
||||||
return gst_ebml_last_write_result (ebml);
|
return gst_ebml_last_write_result (ebml);
|
||||||
} else {
|
} 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,
|
/* write and call order slightly unnatural,
|
||||||
* but avoids seek and minizes pushing */
|
* but avoids seek and minizes pushing */
|
||||||
blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP);
|
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_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
|
||||||
gst_ebml_write_buffer (ebml, hdr);
|
gst_ebml_write_buffer (ebml, hdr);
|
||||||
gst_ebml_write_master_finish_full (ebml, blockgroup, GST_BUFFER_SIZE (buf));
|
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);
|
gst_ebml_write_buffer (ebml, buf);
|
||||||
return gst_ebml_last_write_result (ebml);
|
return gst_ebml_last_write_result (ebml);
|
||||||
}
|
}
|
||||||
|
@ -2702,6 +2707,7 @@ static GstFlowReturn
|
||||||
gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
|
gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
|
||||||
{
|
{
|
||||||
GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
|
GstMatroskaMux *mux = GST_MATROSKA_MUX (user_data);
|
||||||
|
GstEbmlWrite *ebml = mux->ebml_write;
|
||||||
GstMatroskaPad *best;
|
GstMatroskaPad *best;
|
||||||
gboolean popped;
|
gboolean popped;
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
|
@ -2716,7 +2722,9 @@ gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data)
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
mux->state = GST_MATROSKA_MUX_STATE_HEADER;
|
mux->state = GST_MATROSKA_MUX_STATE_HEADER;
|
||||||
|
gst_ebml_start_streamheader (ebml);
|
||||||
gst_matroska_mux_start (mux);
|
gst_matroska_mux_start (mux);
|
||||||
|
gst_matroska_mux_stop_streamheader (mux);
|
||||||
mux->state = GST_MATROSKA_MUX_STATE_DATA;
|
mux->state = GST_MATROSKA_MUX_STATE_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue