diff options
author | Sebastian Dröge <sebastian@centricular.com> | 2016-03-13 10:51:30 +0200 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2016-03-14 12:45:33 +0200 |
commit | 1d4fb48718a2f8e5610c1fe2761640dd0435a9c4 (patch) | |
tree | 55c8fea503c501b04a0fa921cabb4fcf32015289 /gst | |
parent | 916746e73165ca95a061bc2f975354524c8e3a57 (diff) |
multihandlesink: Only don't send HEADER buffers normally if they are actually streamheaders from the caps
And also consider HEADER buffers without DELTA_UNIT flag as sync points. This
fixes sync-mode=2 with mpegtsmux for example, which has no streamheaders but
puts the HEADER flag on its keyframes.
https://bugzilla.gnome.org/show_bug.cgi?id=763278
Diffstat (limited to 'gst')
-rw-r--r-- | gst/tcp/gstmultihandlesink.c | 75 | ||||
-rw-r--r-- | gst/tcp/gstmultihandlesink.h | 2 |
2 files changed, 65 insertions, 12 deletions
diff --git a/gst/tcp/gstmultihandlesink.c b/gst/tcp/gstmultihandlesink.c index 6ddbc981b..651d0ac08 100644 --- a/gst/tcp/gstmultihandlesink.c +++ b/gst/tcp/gstmultihandlesink.c @@ -114,6 +114,8 @@ #include <netinet/in.h> #endif +#include <string.h> + #define NOT_IMPLEMENTED 0 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", @@ -1140,13 +1142,9 @@ gst_multi_handle_sink_client_queue_buffer (GstMultiHandleSink * mhsink, static gboolean is_sync_frame (GstMultiHandleSink * sink, GstBuffer * buffer) { - if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) { + if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) return FALSE; - } else if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_HEADER)) { - return TRUE; - } - - return FALSE; + return TRUE; } /* find the keyframe in the list of buffers starting the @@ -1844,10 +1842,64 @@ restart: } } +static gboolean +buffer_is_in_caps (GstMultiHandleSink * sink, GstBuffer * buf) +{ + GstCaps *caps; + GstStructure *s; + const GValue *v; + + caps = gst_pad_get_current_caps (GST_BASE_SINK_PAD (sink)); + if (!caps) + return FALSE; + s = gst_caps_get_structure (caps, 0); + if (!gst_structure_has_field (s, "streamheader")) { + gst_caps_unref (caps); + return FALSE; + } + + v = gst_structure_get_value (s, "streamheader"); + if (GST_VALUE_HOLDS_ARRAY (v)) { + guint n = gst_value_array_get_size (v); + guint i; + GstMapInfo map; + + gst_buffer_map (buf, &map, GST_MAP_READ); + + for (i = 0; i < n; i++) { + const GValue *v2 = gst_value_array_get_value (v, i); + GstBuffer *buf2; + GstMapInfo map2; + + if (!GST_VALUE_HOLDS_BUFFER (v2)) + continue; + + buf2 = gst_value_get_buffer (v2); + if (buf == buf2) { + gst_caps_unref (caps); + return TRUE; + } + gst_buffer_map (buf2, &map2, GST_MAP_READ); + if (map.size == map2.size && memcmp (map.data, map2.data, map.size) == 0) { + gst_buffer_unmap (buf2, &map2); + gst_buffer_unmap (buf, &map); + gst_caps_unref (caps); + return TRUE; + } + gst_buffer_unmap (buf2, &map2); + } + gst_buffer_unmap (buf, &map); + } + + gst_caps_unref (caps); + + return FALSE; +} + static GstFlowReturn gst_multi_handle_sink_render (GstBaseSink * bsink, GstBuffer * buf) { - gboolean in_caps; + gboolean is_header, in_caps; #if 0 GstCaps *bufcaps, *padcaps; #endif @@ -1868,8 +1920,9 @@ gst_multi_handle_sink_render (GstBaseSink * bsink, GstBuffer * buf) goto no_caps; #endif - /* get IN_CAPS first, code below might mess with the flags */ - in_caps = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_HEADER); + /* get HEADER first, code below might mess with the flags */ + is_header = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_HEADER); + in_caps = is_header && buffer_is_in_caps (sink, buf); #if 0 /* stamp the buffer with previous caps if no caps set */ @@ -1909,7 +1962,7 @@ gst_multi_handle_sink_render (GstBaseSink * bsink, GstBuffer * buf) /* if we get IN_CAPS buffers, but the previous buffer was not IN_CAPS, * it means we're getting new streamheader buffers, and we should clear * the old ones */ - if (in_caps && !sink->previous_buffer_in_caps) { + if (is_header && !sink->previous_buffer_is_header) { GST_DEBUG_OBJECT (sink, "receiving new HEADER buffers, clearing old streamheader"); g_slist_foreach (sink->streamheader, (GFunc) gst_mini_object_unref, NULL); @@ -1918,7 +1971,7 @@ gst_multi_handle_sink_render (GstBaseSink * bsink, GstBuffer * buf) } /* save the current in_caps */ - sink->previous_buffer_in_caps = in_caps; + sink->previous_buffer_is_header = is_header; /* if the incoming buffer is marked as IN CAPS, then we assume for now * it's a streamheader that needs to be sent to each new client, so we diff --git a/gst/tcp/gstmultihandlesink.h b/gst/tcp/gstmultihandlesink.h index bd125eb2c..e64d44a4c 100644 --- a/gst/tcp/gstmultihandlesink.h +++ b/gst/tcp/gstmultihandlesink.h @@ -203,7 +203,7 @@ struct _GstMultiHandleSink { GCancellable *cancellable; GSList *streamheader; /* GSList of GstBuffers to use as streamheader */ - gboolean previous_buffer_in_caps; + gboolean previous_buffer_is_header; gint qos_dscp; |