diff --git a/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json b/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json index c3de626f3e..222a2f76ef 100644 --- a/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json +++ b/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json @@ -15138,6 +15138,18 @@ "type": "gboolean", "writable": true }, + "drop-out-of-segment": { + "blurb": "Drop out of segment buffers", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + }, "duplicate": { "blurb": "Number of duplicated frames", "conditionally-available": false, diff --git a/subprojects/gst-plugins-base/gst/videorate/gstvideorate.c b/subprojects/gst-plugins-base/gst/videorate/gstvideorate.c index b87b0248b4..f1c8532a40 100644 --- a/subprojects/gst-plugins-base/gst/videorate/gstvideorate.c +++ b/subprojects/gst-plugins-base/gst/videorate/gstvideorate.c @@ -101,6 +101,7 @@ enum #define DEFAULT_RATE 1.0 #define DEFAULT_MAX_DUPLICATION_TIME 0 #define DEFAULT_MAX_CLOSING_SEGMENT_DUPLICATION_DURATION GST_SECOND +#define DEFAULT_DROP_OUT_OF_SEGMENT FALSE enum { @@ -117,7 +118,8 @@ enum PROP_MAX_RATE, PROP_RATE, PROP_MAX_DUPLICATION_TIME, - PROP_MAX_CLOSING_SEGMENT_DUPLICATION_DURATION + PROP_MAX_CLOSING_SEGMENT_DUPLICATION_DURATION, + PROP_DROP_OUT_OF_SEGMENT }; static GstStaticPadTemplate gst_video_rate_src_template = @@ -318,6 +320,19 @@ gst_video_rate_class_init (GstVideoRateClass * klass) G_MAXUINT64, DEFAULT_MAX_CLOSING_SEGMENT_DUPLICATION_DURATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstVideoRate:drop-out-of-segment: + * + * Drop all frames that are out of segment + * + * Since: 1.24 + */ + g_object_class_install_property (object_class, PROP_DROP_OUT_OF_SEGMENT, + g_param_spec_boolean ("drop-out-of-segment", + "Drop out of segment buffers", "Drop out of segment buffers", + DEFAULT_DROP_OUT_OF_SEGMENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + gst_element_class_set_static_metadata (element_class, "Video rate adjuster", "Filter/Effect/Video", "Drops/duplicates/adjusts timestamps on video frames to make a perfect stream", @@ -660,6 +675,7 @@ gst_video_rate_init (GstVideoRate * videorate) videorate->silent = DEFAULT_SILENT; videorate->new_pref = DEFAULT_NEW_PREF; videorate->drop_only = DEFAULT_DROP_ONLY; + videorate->drop_out_of_segment = DEFAULT_DROP_OUT_OF_SEGMENT; videorate->average_period = DEFAULT_AVERAGE_PERIOD; videorate->average_period_set = DEFAULT_AVERAGE_PERIOD; videorate->max_rate = DEFAULT_MAX_RATE; @@ -682,7 +698,7 @@ static GstFlowReturn gst_video_rate_push_buffer (GstVideoRate * videorate, GstBuffer * outbuf, gboolean duplicate, GstClockTime next_intime, gboolean invalid_duration) { - GstFlowReturn res; + GstFlowReturn res = GST_FLOW_OK; GstClockTime push_ts; GST_BUFFER_OFFSET (outbuf) = videorate->out; @@ -760,6 +776,17 @@ gst_video_rate_push_buffer (GstVideoRate * videorate, GstBuffer * outbuf, "old is best, dup, pushing buffer outgoing ts %" GST_TIME_FORMAT, GST_TIME_ARGS (push_ts)); + if (videorate->drop_out_of_segment + && !gst_segment_clip (&videorate->segment, GST_FORMAT_TIME, + GST_BUFFER_PTS (outbuf), + GST_BUFFER_PTS (outbuf) + GST_BUFFER_DURATION (outbuf), NULL, NULL)) { + GST_INFO_OBJECT (videorate, "Buffer is out of segment, dropping"); + + gst_buffer_unref (outbuf); + + return res; + } + res = gst_pad_push (GST_BASE_TRANSFORM_SRC_PAD (videorate), outbuf); return res; @@ -2036,6 +2063,10 @@ gst_video_rate_set_property (GObject * object, videorate->max_closing_segment_duplication_duration = g_value_get_uint64 (value); break; + case PROP_DROP_OUT_OF_SEGMENT:{ + videorate->drop_out_of_segment = g_value_get_boolean (value); + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2102,6 +2133,9 @@ gst_video_rate_get_property (GObject * object, g_value_set_uint64 (value, videorate->max_closing_segment_duplication_duration); break; + case PROP_DROP_OUT_OF_SEGMENT: + g_value_set_boolean (value, videorate->drop_out_of_segment); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/subprojects/gst-plugins-base/gst/videorate/gstvideorate.h b/subprojects/gst-plugins-base/gst/videorate/gstvideorate.h index 11f260f6b0..ec7e256f21 100644 --- a/subprojects/gst-plugins-base/gst/videorate/gstvideorate.h +++ b/subprojects/gst-plugins-base/gst/videorate/gstvideorate.h @@ -69,6 +69,7 @@ struct _GstVideoRate gdouble new_pref; gboolean skip_to_first; gboolean drop_only; + gboolean drop_out_of_segment; guint64 average_period_set; int max_rate; diff --git a/subprojects/gst-plugins-base/tests/validate/meson.build b/subprojects/gst-plugins-base/tests/validate/meson.build index 1385a85847..f732daae44 100644 --- a/subprojects/gst-plugins-base/tests/validate/meson.build +++ b/subprojects/gst-plugins-base/tests/validate/meson.build @@ -21,6 +21,7 @@ tests = [ 'videorate/duplicate_on_eos_disbaled', 'videorate/duplicate_on_eos_half_sec', 'videorate/fill_segment_after_caps_changed_before_eos', + 'videorate/drop_out_of_segment', 'compositor/renogotiate_failing_unsupported_src_format', 'giosrc/read-growing-file', 'encodebin/set-encoder-properties', diff --git a/subprojects/gst-plugins-base/tests/validate/videorate/drop_out_of_segment.validatetest b/subprojects/gst-plugins-base/tests/validate/videorate/drop_out_of_segment.validatetest new file mode 100644 index 0000000000..9a98483a3d --- /dev/null +++ b/subprojects/gst-plugins-base/tests/validate/videorate/drop_out_of_segment.validatetest @@ -0,0 +1,24 @@ +meta, + args = { + "appsrc name=src format=time handle-segment-change=true automatic-eos=false ! \ + videorate drop-out-of-segment=true name=videorate ! video/x-raw,framerate=1/1 ! $(videosink) name=sink", + }, + configs = { + "$(validateflow), pad=videorate:sink, buffers-checksum=as-id, ignored-event-types={ tag }", + "$(validateflow), pad=videorate:src, buffers-checksum=as-id, ignored-event-types={ tag }", + }, + handles-states=true + +foreach, + i=<1.0, 2.0, 3.0, 4.0, 5.0>, + actions = { + [ + appsrc-push, target-element-name=src, fill-mode=counter, size=115200, pts="$(i)", duration=1.0, + caps=(GstCaps)[video/x-raw,format=I420,framerate=1/1,width=320,height=240], + segment=[segment, stop=1.0, format=(GstFormat)time], + ], + } + +play + +appsrc-eos, target-element-name=src diff --git a/subprojects/gst-plugins-base/tests/validate/videorate/drop_out_of_segment/flow-expectations/log-videorate-sink-expected b/subprojects/gst-plugins-base/tests/validate/videorate/drop_out_of_segment/flow-expectations/log-videorate-sink-expected new file mode 100644 index 0000000000..b1ea7cb661 --- /dev/null +++ b/subprojects/gst-plugins-base/tests/validate/videorate/drop_out_of_segment/flow-expectations/log-videorate-sink-expected @@ -0,0 +1,9 @@ +event stream-start: GstEventStreamStart, flags=(GstStreamFlags)GST_STREAM_FLAG_NONE, group-id=(uint)1; +event caps: video/x-raw, format=(string)I420, framerate=(fraction)1/1, height=(int)240, width=(int)320; +event segment: format=TIME, start=0:00:00.000000000, offset=0:00:00.000000000, stop=0:00:01.000000000, time=0:00:00.000000000, base=0:00:00.000000000, position=0:00:00.000000000 +buffer: content-id=0, pts=0:00:01.000000000, dur=0:00:01.000000000, flags=discont +buffer: content-id=1, pts=0:00:02.000000000, dur=0:00:01.000000000 +buffer: content-id=2, pts=0:00:03.000000000, dur=0:00:01.000000000 +buffer: content-id=3, pts=0:00:04.000000000, dur=0:00:01.000000000 +buffer: content-id=4, pts=0:00:05.000000000, dur=0:00:01.000000000 +event eos: (no structure) diff --git a/subprojects/gst-plugins-base/tests/validate/videorate/drop_out_of_segment/flow-expectations/log-videorate-src-expected b/subprojects/gst-plugins-base/tests/validate/videorate/drop_out_of_segment/flow-expectations/log-videorate-src-expected new file mode 100644 index 0000000000..427361e17b --- /dev/null +++ b/subprojects/gst-plugins-base/tests/validate/videorate/drop_out_of_segment/flow-expectations/log-videorate-src-expected @@ -0,0 +1,5 @@ +event stream-start: GstEventStreamStart, flags=(GstStreamFlags)GST_STREAM_FLAG_NONE, group-id=(uint)1; +event caps: video/x-raw, format=(string)I420, framerate=(fraction)1/1, height=(int)240, width=(int)320; +event segment: format=TIME, start=0:00:00.000000000, offset=0:00:00.000000000, stop=0:00:01.000000000, time=0:00:00.000000000, base=0:00:00.000000000, position=0:00:00.000000000 +buffer: content-id=0, pts=0:00:00.000000000, dur=0:00:01.000000000, flags=discont +event eos: (no structure)