diff --git a/gst/replaygain/gstrganalysis.c b/gst/replaygain/gstrganalysis.c index 2436778682..613c087679 100644 --- a/gst/replaygain/gstrganalysis.c +++ b/gst/replaygain/gstrganalysis.c @@ -288,6 +288,10 @@ gst_rg_analysis_class_init (GstRgAnalysisClass * klass) static void gst_rg_analysis_init (GstRgAnalysis * filter, GstRgAnalysisClass * gclass) { + GstBaseTransform *base = GST_BASE_TRANSFORM (filter); + + gst_base_transform_set_gap_aware (base, TRUE); + filter->num_tracks = 0; filter->forced = FORCED_DEFAULT; filter->reference_level = RG_REFERENCE_LEVEL; @@ -452,6 +456,10 @@ gst_rg_analysis_transform_ip (GstBaseTransform * base, GstBuffer * buf) if (filter->skip) return GST_FLOW_OK; + /* Buffers made up of silence have no influence on the analysis: */ + if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)) + return GST_FLOW_OK; + GST_LOG_OBJECT (filter, "processing buffer of size %u", GST_BUFFER_SIZE (buf)); diff --git a/gst/replaygain/gstrglimiter.c b/gst/replaygain/gstrglimiter.c index 609db3d701..d474b26edb 100644 --- a/gst/replaygain/gstrglimiter.c +++ b/gst/replaygain/gstrglimiter.c @@ -129,8 +129,12 @@ gst_rg_limiter_class_init (GstRgLimiterClass * klass) static void gst_rg_limiter_init (GstRgLimiter * filter, GstRgLimiterClass * gclass) { + GstBaseTransform *base = GST_BASE_TRANSFORM (filter); + + gst_base_transform_set_passthrough (base, FALSE); + gst_base_transform_set_gap_aware (base, TRUE); + filter->enabled = TRUE; - gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (filter), FALSE); } static void @@ -182,6 +186,9 @@ gst_rg_limiter_transform_ip (GstBaseTransform * base, GstBuffer * buf) if (!filter->enabled) return GST_FLOW_OK; + if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)) + return GST_FLOW_OK; + input = (gfloat *) GST_BUFFER_DATA (buf); count = GST_BUFFER_SIZE (buf) / sizeof (gfloat); diff --git a/tests/check/elements/rganalysis.c b/tests/check/elements/rganalysis.c index 96ea6dad46..1a44bd4e44 100644 --- a/tests/check/elements/rganalysis.c +++ b/tests/check/elements/rganalysis.c @@ -741,6 +741,46 @@ GST_START_TEST (test_empty_buffers) GST_END_TEST; +GST_START_TEST (test_gap_buffers) +{ + GstElement *element = setup_rganalysis (); + GstTagList *tag_list; + GstBuffer *buf; + gint accumulator = 0; + gint i; + + set_playing_state (element); + + for (i = 0; i < 60; i++) { + if (i % 3 == 0) { + /* We are cheating here; the element cannot know that these GAP buffers + * actually contain non-silence so it must skip them. */ + buf = test_buffer_square_float_mono (&accumulator, 44100, 512, 0.25); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_GAP); + push_buffer (buf); + + /* Verify that the base class does not lift the GAP flag: */ + fail_if (g_list_length (buffers) == 0); + if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)) + fail_unless (GST_BUFFER_FLAG_IS_SET (buffers->data, + GST_BUFFER_FLAG_GAP)); + } else { + push_buffer (test_buffer_const_float_mono (44100, 512, 0.0)); + } + } + + send_eos_event (element); + tag_list = poll_tags (element); + /* We pushed faked GAP buffers with non-silence and non-GAP buffers with + * silence, so the correct result is that the analysis only got silence: */ + fail_unless_track_peak (tag_list, 0.0); + fail_unless_track_gain (tag_list, SILENCE_GAIN); + + cleanup_rganalysis (element); +} + +GST_END_TEST; + /* Tests for correctness of the peak values. */ /* Float peak test. For stereo, one channel has the constant value of -1.369, @@ -1778,6 +1818,7 @@ rganalysis_suite (void) tcase_add_test (tc_chain, test_no_buffer_album_1); tcase_add_test (tc_chain, test_no_buffer_album_2); tcase_add_test (tc_chain, test_empty_buffers); + tcase_add_test (tc_chain, test_gap_buffers); tcase_add_test (tc_chain, test_peak_float); tcase_add_test (tc_chain, test_peak_int16_16); diff --git a/tests/check/elements/rglimiter.c b/tests/check/elements/rglimiter.c index 33b478d01e..9d8387858b 100644 --- a/tests/check/elements/rglimiter.c +++ b/tests/check/elements/rglimiter.c @@ -204,6 +204,36 @@ GST_START_TEST (test_limiting) GST_END_TEST; +GST_START_TEST (test_gap) +{ + GstElement *element = setup_rglimiter (); + GstBuffer *buf, *out_buf; + + set_playing_state (element); + + buf = create_test_buffer (); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_GAP); + fail_unless (gst_pad_push (mysrcpad, buf) == GST_FLOW_OK); + fail_unless (g_list_length (buffers) == 1); + out_buf = buffers->data; + fail_if (out_buf == NULL); + ASSERT_BUFFER_REFCOUNT (out_buf, "out_buf", 1); + + /* Verify that the baseclass does not lift the GAP flag: */ + fail_unless (GST_BUFFER_FLAG_IS_SET (out_buf, GST_BUFFER_FLAG_GAP)); + + g_assert (GST_BUFFER_SIZE (out_buf) == GST_BUFFER_SIZE (buf)); + /* We cheated by passing an input buffer with non-silence that has the GAP + * flag set. The element cannot know that however and must have skipped + * adjusting the buffer because of the flag, which we can easily verify: */ + fail_if (memcmp (GST_BUFFER_DATA (out_buf), + GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (out_buf)) != 0); + + cleanup_rglimiter (element); +} + +GST_END_TEST; + Suite * rglimiter_suite (void) { @@ -215,6 +245,7 @@ rglimiter_suite (void) tcase_add_test (tc_chain, test_no_buffer); tcase_add_test (tc_chain, test_disabled); tcase_add_test (tc_chain, test_limiting); + tcase_add_test (tc_chain, test_gap); return s; }