| /* GStreamer ReplayGain volume adjustment |
| * |
| * Copyright (C) 2007 Rene Stadler <mail@renestadler.de> |
| * |
| * rgvolume.c: Unit test for the rgvolume element |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public License |
| * as published by the Free Software Foundation; either version 2.1 of |
| * the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| * 02110-1301 USA |
| */ |
| |
| #include <gst/check/gstcheck.h> |
| #include <gst/audio/audio.h> |
| |
| #include <math.h> |
| |
| static GList *events = NULL; |
| |
| /* For ease of programming we use globals to keep refs for our floating src and |
| * sink pads we create; otherwise we always have to do get_pad, get_peer, and |
| * then remove references in every test function */ |
| static GstPad *mysrcpad, *mysinkpad; |
| |
| #define RG_VOLUME_CAPS_TEMPLATE_STRING \ |
| "audio/x-raw, " \ |
| "format = (string) "GST_AUDIO_NE (F32) ", " \ |
| "layout = (string) interleaved, " \ |
| "channels = (int) [ 1, MAX ], " \ |
| "rate = (int) [ 1, MAX ]" |
| |
| static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", |
| GST_PAD_SINK, |
| GST_PAD_ALWAYS, |
| GST_STATIC_CAPS (RG_VOLUME_CAPS_TEMPLATE_STRING) |
| ); |
| static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", |
| GST_PAD_SRC, |
| GST_PAD_ALWAYS, |
| GST_STATIC_CAPS (RG_VOLUME_CAPS_TEMPLATE_STRING) |
| ); |
| |
| static GstBuffer *test_buffer_new (gfloat value); |
| |
| /* gstcheck sets up a chain function that appends buffers to a global list. |
| * This is our equivalent of that for event handling. */ |
| static gboolean |
| event_func (GstPad * pad, GstObject * parent, GstEvent * event) |
| { |
| GST_DEBUG ("received event %p (%s)", event, GST_EVENT_TYPE_NAME (event)); |
| events = g_list_append (events, event); |
| |
| return TRUE; |
| } |
| |
| static GstElement * |
| setup_rgvolume (void) |
| { |
| GstElement *element; |
| |
| GST_DEBUG ("setup_rgvolume"); |
| element = gst_check_setup_element ("rgvolume"); |
| mysrcpad = gst_check_setup_src_pad (element, &srctemplate); |
| mysinkpad = gst_check_setup_sink_pad (element, &sinktemplate); |
| |
| /* Capture events, to test tag filtering behavior: */ |
| gst_pad_set_event_function (mysinkpad, event_func); |
| |
| gst_pad_set_active (mysrcpad, TRUE); |
| gst_pad_set_active (mysinkpad, TRUE); |
| |
| return element; |
| } |
| |
| static void |
| send_empty_buffer (void) |
| { |
| GstBuffer *buf; |
| |
| buf = test_buffer_new (0.0); |
| gst_buffer_resize (buf, 0, 0); |
| GST_BUFFER_DURATION (buf) = 0; |
| GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET (buf); |
| fail_unless (gst_pad_push (mysrcpad, buf) == GST_FLOW_OK); |
| |
| fail_unless (g_list_length (buffers) == 1); |
| fail_unless (buffers->data == buf); |
| gst_mini_object_unref ((GstMiniObject *) buffers->data); |
| buffers = g_list_remove (buffers, buf); |
| } |
| |
| static void |
| cleanup_rgvolume (GstElement * element) |
| { |
| GST_DEBUG ("cleanup_rgvolume"); |
| |
| g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); |
| g_list_free (buffers); |
| buffers = NULL; |
| |
| g_list_foreach (events, (GFunc) gst_mini_object_unref, NULL); |
| g_list_free (events); |
| events = NULL; |
| |
| gst_pad_set_active (mysrcpad, FALSE); |
| gst_pad_set_active (mysinkpad, FALSE); |
| gst_check_teardown_src_pad (element); |
| gst_check_teardown_sink_pad (element); |
| gst_check_teardown_element (element); |
| } |
| |
| static void |
| set_playing_state (GstElement * element) |
| { |
| fail_unless (gst_element_set_state (element, |
| GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, |
| "Could not set state to PLAYING"); |
| } |
| |
| static void |
| set_null_state (GstElement * element) |
| { |
| fail_unless (gst_element_set_state (element, |
| GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, |
| "Could not set state to NULL"); |
| } |
| |
| static void |
| send_flush_events (GstElement * element) |
| { |
| gboolean res; |
| |
| res = gst_pad_push_event (mysrcpad, gst_event_new_flush_start ()); |
| fail_unless (res, "flush-start even not handled"); |
| |
| res = gst_pad_push_event (mysrcpad, gst_event_new_flush_stop (TRUE)); |
| fail_unless (res, "flush-stop event not handled"); |
| } |
| |
| static void |
| send_stream_start_event (GstElement * element) |
| { |
| gboolean res; |
| |
| res = gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test")); |
| fail_unless (res, "STREAM_START event not handled"); |
| } |
| |
| static void |
| send_caps_event (GstElement * element) |
| { |
| GstCaps *caps; |
| gboolean res; |
| |
| caps = gst_caps_from_string ("audio/x-raw, format = " GST_AUDIO_NE (F32) ", " |
| "layout = interleaved, rate = 8000, channels = 1"); |
| res = gst_pad_push_event (mysrcpad, gst_event_new_caps (caps)); |
| fail_unless (res, "CAPS event not handled"); |
| gst_caps_unref (caps); |
| } |
| |
| static void |
| send_segment_event (GstElement * element) |
| { |
| GstSegment segment; |
| gboolean res; |
| |
| gst_segment_init (&segment, GST_FORMAT_TIME); |
| res = gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)); |
| fail_unless (res, "SEGMENT event not handled"); |
| } |
| |
| static void |
| send_eos_event (GstElement * element) |
| { |
| GstEvent *event = gst_event_new_eos (); |
| |
| fail_unless (gst_pad_push_event (mysrcpad, event), |
| "Pushing EOS event failed"); |
| } |
| |
| static GstEvent * |
| send_tag_event (GstElement * element, GstEvent * event) |
| { |
| GList *l; |
| GstTagList *tag_list; |
| gdouble dummy; |
| |
| g_return_val_if_fail (event->type == GST_EVENT_TAG, NULL); |
| |
| fail_unless (gst_pad_push_event (mysrcpad, event), |
| "Pushing tag event failed"); |
| |
| event = NULL; |
| |
| for (l = g_list_last (events); l; l = l->prev) { |
| if (GST_EVENT_TYPE (l->data) == GST_EVENT_TAG) { |
| event = l->data; |
| events = g_list_delete_link (events, l); |
| break; |
| } |
| } |
| |
| /* Event got filtered out */ |
| if (event == NULL) |
| return NULL; |
| |
| fail_unless (event->type == GST_EVENT_TAG); |
| gst_event_parse_tag (event, &tag_list); |
| |
| /* The element is supposed to filter out ReplayGain related tags. */ |
| fail_if (gst_tag_list_get_double (tag_list, GST_TAG_TRACK_GAIN, &dummy), |
| "tag event still contains track gain tag"); |
| fail_if (gst_tag_list_get_double (tag_list, GST_TAG_TRACK_PEAK, &dummy), |
| "tag event still contains track peak tag"); |
| fail_if (gst_tag_list_get_double (tag_list, GST_TAG_ALBUM_GAIN, &dummy), |
| "tag event still contains album gain tag"); |
| fail_if (gst_tag_list_get_double (tag_list, GST_TAG_ALBUM_PEAK, &dummy), |
| "tag event still contains album peak tag"); |
| |
| return event; |
| } |
| |
| static GstBuffer * |
| test_buffer_new (gfloat value) |
| { |
| GstBuffer *buf; |
| GstMapInfo map; |
| gfloat *data; |
| gint i; |
| |
| buf = gst_buffer_new_and_alloc (8 * sizeof (gfloat)); |
| gst_buffer_map (buf, &map, GST_MAP_WRITE); |
| data = (gfloat *) map.data; |
| for (i = 0; i < 8; i++) |
| data[i] = value; |
| gst_buffer_unmap (buf, &map); |
| |
| |
| ASSERT_BUFFER_REFCOUNT (buf, "buf", 1); |
| |
| return buf; |
| } |
| |
| #define MATCH_GAIN(g1, g2) ((g1 < g2 + 1e-6) && (g2 < g1 + 1e-6)) |
| |
| static void |
| fail_unless_target_gain (GstElement * element, gdouble expected_gain) |
| { |
| gdouble prop_gain; |
| |
| g_object_get (element, "target-gain", &prop_gain, NULL); |
| |
| fail_unless (MATCH_GAIN (prop_gain, expected_gain), |
| "Target gain is %.2f dB, expected %.2f dB", prop_gain, expected_gain); |
| } |
| |
| static void |
| fail_unless_result_gain (GstElement * element, gdouble expected_gain) |
| { |
| GstBuffer *input_buf, *output_buf; |
| gfloat *data; |
| gfloat input_sample, output_sample; |
| gdouble gain, prop_gain; |
| gboolean is_passthrough, expect_passthrough; |
| gint i; |
| GstMapInfo map; |
| |
| fail_unless (g_list_length (buffers) == 0); |
| |
| input_sample = 1.0; |
| input_buf = test_buffer_new (input_sample); |
| |
| /* We keep an extra reference to detect passthrough mode. */ |
| gst_buffer_ref (input_buf); |
| /* Pushing steals a reference. */ |
| fail_unless (gst_pad_push (mysrcpad, input_buf) == GST_FLOW_OK); |
| gst_buffer_unref (input_buf); |
| |
| /* The output buffer ends up on the global buffer list. */ |
| fail_unless (g_list_length (buffers) == 1); |
| output_buf = buffers->data; |
| fail_if (output_buf == NULL); |
| |
| buffers = g_list_remove (buffers, output_buf); |
| ASSERT_BUFFER_REFCOUNT (output_buf, "output_buf", 1); |
| |
| fail_unless_equals_int (gst_buffer_get_size (output_buf), |
| 8 * sizeof (gfloat)); |
| |
| gst_buffer_map (output_buf, &map, GST_MAP_READ); |
| data = (gfloat *) map.data; |
| |
| output_sample = *data; |
| fail_if (output_sample == 0.0, "First output sample is zero"); |
| for (i = 1; i < 8; i++) { |
| fail_unless (output_sample == data[i], "Output samples not uniform"); |
| }; |
| gst_buffer_unmap (output_buf, &map); |
| |
| gain = 20. * log10 (output_sample / input_sample); |
| fail_unless (MATCH_GAIN (gain, expected_gain), |
| "Applied gain is %.2f dB, expected %.2f dB", gain, expected_gain); |
| g_object_get (element, "result-gain", &prop_gain, NULL); |
| fail_unless (MATCH_GAIN (prop_gain, expected_gain), |
| "Result gain is %.2f dB, expected %.2f dB", prop_gain, expected_gain); |
| |
| is_passthrough = (output_buf == input_buf); |
| expect_passthrough = MATCH_GAIN (expected_gain, +0.00); |
| fail_unless (is_passthrough == expect_passthrough, |
| expect_passthrough |
| ? "Expected operation in passthrough mode" |
| : "Incorrect passthrough behaviour"); |
| |
| gst_buffer_unref (output_buf); |
| } |
| |
| static void |
| fail_unless_gain (GstElement * element, gdouble expected_gain) |
| { |
| fail_unless_target_gain (element, expected_gain); |
| fail_unless_result_gain (element, expected_gain); |
| } |
| |
| /* Start of tests. */ |
| |
| GST_START_TEST (test_no_buffer) |
| { |
| GstElement *element = setup_rgvolume (); |
| |
| set_playing_state (element); |
| set_null_state (element); |
| set_playing_state (element); |
| send_eos_event (element); |
| |
| cleanup_rgvolume (element); |
| } |
| |
| GST_END_TEST; |
| |
| GST_START_TEST (test_events) |
| { |
| GstElement *element = setup_rgvolume (); |
| GstEvent *event; |
| GstEvent *new_event; |
| GstTagList *tag_list; |
| gchar *artist; |
| |
| set_playing_state (element); |
| send_stream_start_event (element); |
| send_caps_event (element); |
| send_segment_event (element); |
| |
| send_empty_buffer (); |
| |
| tag_list = gst_tag_list_new_empty (); |
| gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, |
| GST_TAG_TRACK_GAIN, +4.95, GST_TAG_TRACK_PEAK, 0.59463, |
| GST_TAG_ALBUM_GAIN, -1.54, GST_TAG_ALBUM_PEAK, 0.693415, |
| GST_TAG_ARTIST, "Foobar", NULL); |
| event = gst_event_new_tag (tag_list); |
| new_event = send_tag_event (element, event); |
| gst_event_parse_tag (new_event, &tag_list); |
| fail_unless (gst_tag_list_get_string (tag_list, GST_TAG_ARTIST, &artist)); |
| fail_unless (g_str_equal (artist, "Foobar")); |
| g_free (artist); |
| gst_event_unref (new_event); |
| |
| /* Same as above, but with a non-writable event. */ |
| |
| tag_list = gst_tag_list_new_empty (); |
| gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, |
| GST_TAG_TRACK_GAIN, +4.95, GST_TAG_TRACK_PEAK, 0.59463, |
| GST_TAG_ALBUM_GAIN, -1.54, GST_TAG_ALBUM_PEAK, 0.693415, |
| GST_TAG_ARTIST, "Foobar", NULL); |
| gst_tag_list_ref (tag_list); |
| event = gst_event_new_tag (tag_list); |
| new_event = send_tag_event (element, event); |
| |
| /* Make sure our tags weren't modified in place while we still got a ref */ |
| fail_unless_equals_int (5, gst_tag_list_n_tags (tag_list)); |
| gst_tag_list_unref (tag_list); |
| |
| gst_event_parse_tag (new_event, &tag_list); |
| fail_unless (gst_tag_list_get_string (tag_list, GST_TAG_ARTIST, &artist)); |
| fail_unless (g_str_equal (artist, "Foobar")); |
| g_free (artist); |
| gst_event_unref (new_event); |
| |
| cleanup_rgvolume (element); |
| } |
| |
| GST_END_TEST; |
| |
| GST_START_TEST (test_simple) |
| { |
| GstElement *element = setup_rgvolume (); |
| GstTagList *tag_list; |
| |
| g_object_set (element, "album-mode", FALSE, "headroom", +0.00, |
| "pre-amp", -6.00, "fallback-gain", +1.23, NULL); |
| set_playing_state (element); |
| send_stream_start_event (element); |
| send_caps_event (element); |
| send_segment_event (element); |
| |
| send_empty_buffer (); |
| |
| tag_list = gst_tag_list_new_empty (); |
| gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, |
| GST_TAG_TRACK_GAIN, -3.45, GST_TAG_TRACK_PEAK, 1.0, |
| GST_TAG_ALBUM_GAIN, +2.09, GST_TAG_ALBUM_PEAK, 1.0, NULL); |
| fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL); |
| fail_unless_gain (element, -9.45); /* pre-amp + track gain */ |
| send_eos_event (element); |
| |
| g_object_set (element, "album-mode", TRUE, NULL); |
| |
| send_flush_events (element); |
| send_segment_event (element); |
| |
| tag_list = gst_tag_list_new_empty (); |
| gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, |
| GST_TAG_TRACK_GAIN, -3.45, GST_TAG_TRACK_PEAK, 1.0, |
| GST_TAG_ALBUM_GAIN, +2.09, GST_TAG_ALBUM_PEAK, 1.0, NULL); |
| fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL); |
| fail_unless_gain (element, -3.91); /* pre-amp + album gain */ |
| |
| /* Switching back to track mode in the middle of a stream: */ |
| g_object_set (element, "album-mode", FALSE, NULL); |
| fail_unless_gain (element, -9.45); /* pre-amp + track gain */ |
| send_eos_event (element); |
| |
| cleanup_rgvolume (element); |
| } |
| |
| GST_END_TEST; |
| |
| /* If there are no gain tags at all, the fallback gain is used. */ |
| |
| GST_START_TEST (test_fallback_gain) |
| { |
| GstElement *element = setup_rgvolume (); |
| GstTagList *tag_list; |
| |
| /* First some track where fallback does _not_ apply. */ |
| |
| g_object_set (element, "album-mode", FALSE, "headroom", 10.00, |
| "pre-amp", -6.00, "fallback-gain", -3.00, NULL); |
| set_playing_state (element); |
| send_stream_start_event (element); |
| send_caps_event (element); |
| send_segment_event (element); |
| |
| send_empty_buffer (); |
| |
| tag_list = gst_tag_list_new_empty (); |
| gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, |
| GST_TAG_TRACK_GAIN, +3.5, GST_TAG_TRACK_PEAK, 1.0, |
| GST_TAG_ALBUM_GAIN, -0.5, GST_TAG_ALBUM_PEAK, 1.0, NULL); |
| fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL); |
| fail_unless_gain (element, -2.50); /* pre-amp + track gain */ |
| send_eos_event (element); |
| |
| /* Now a track completely missing tags. */ |
| send_flush_events (element); |
| send_segment_event (element); |
| |
| fail_unless_gain (element, -9.00); /* pre-amp + fallback-gain */ |
| |
| /* Changing the fallback gain in the middle of a stream, going to pass-through |
| * mode: */ |
| g_object_set (element, "fallback-gain", +6.00, NULL); |
| fail_unless_gain (element, +0.00); /* pre-amp + fallback-gain */ |
| send_eos_event (element); |
| |
| /* Verify that result gain is set to +0.00 with pre-amp + fallback-gain > |
| * +0.00 and no headroom. */ |
| send_flush_events (element); |
| send_segment_event (element); |
| |
| g_object_set (element, "fallback-gain", +12.00, "headroom", +0.00, NULL); |
| fail_unless_target_gain (element, +6.00); /* pre-amp + fallback-gain */ |
| fail_unless_result_gain (element, +0.00); |
| send_eos_event (element); |
| |
| cleanup_rgvolume (element); |
| } |
| |
| GST_END_TEST; |
| |
| /* If album gain is to be preferred but not available, the track gain is to be |
| * taken instead. */ |
| |
| GST_START_TEST (test_fallback_track) |
| { |
| GstElement *element = setup_rgvolume (); |
| GstTagList *tag_list; |
| |
| g_object_set (element, "album-mode", TRUE, "headroom", +0.00, |
| "pre-amp", -6.00, "fallback-gain", +1.23, NULL); |
| set_playing_state (element); |
| send_stream_start_event (element); |
| send_caps_event (element); |
| send_segment_event (element); |
| |
| send_empty_buffer (); |
| |
| tag_list = gst_tag_list_new_empty (); |
| gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, |
| GST_TAG_TRACK_GAIN, +2.11, GST_TAG_TRACK_PEAK, 1.0, NULL); |
| fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL); |
| fail_unless_gain (element, -3.89); /* pre-amp + track gain */ |
| |
| send_eos_event (element); |
| |
| cleanup_rgvolume (element); |
| } |
| |
| GST_END_TEST; |
| |
| /* If track gain is to be preferred but not available, the album gain is to be |
| * taken instead. */ |
| |
| GST_START_TEST (test_fallback_album) |
| { |
| GstElement *element = setup_rgvolume (); |
| GstTagList *tag_list; |
| |
| g_object_set (element, "album-mode", FALSE, "headroom", +0.00, |
| "pre-amp", -6.00, "fallback-gain", +1.23, NULL); |
| set_playing_state (element); |
| send_stream_start_event (element); |
| send_caps_event (element); |
| send_segment_event (element); |
| |
| send_empty_buffer (); |
| |
| tag_list = gst_tag_list_new_empty (); |
| gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, |
| GST_TAG_ALBUM_GAIN, +3.73, GST_TAG_ALBUM_PEAK, 1.0, NULL); |
| fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL); |
| fail_unless_gain (element, -2.27); /* pre-amp + album gain */ |
| |
| send_eos_event (element); |
| |
| cleanup_rgvolume (element); |
| } |
| |
| GST_END_TEST; |
| |
| GST_START_TEST (test_headroom) |
| { |
| GstElement *element = setup_rgvolume (); |
| GstTagList *tag_list; |
| |
| g_object_set (element, "album-mode", FALSE, "headroom", +0.00, |
| "pre-amp", +0.00, "fallback-gain", +1.23, NULL); |
| set_playing_state (element); |
| send_stream_start_event (element); |
| send_caps_event (element); |
| send_segment_event (element); |
| |
| send_empty_buffer (); |
| |
| tag_list = gst_tag_list_new_empty (); |
| gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, |
| GST_TAG_TRACK_GAIN, +3.50, GST_TAG_TRACK_PEAK, 1.0, NULL); |
| fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL); |
| fail_unless_target_gain (element, +3.50); /* pre-amp + track gain */ |
| fail_unless_result_gain (element, +0.00); |
| send_eos_event (element); |
| |
| send_flush_events (element); |
| send_segment_event (element); |
| |
| g_object_set (element, "headroom", +2.00, NULL); |
| tag_list = gst_tag_list_new_empty (); |
| gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, |
| GST_TAG_TRACK_GAIN, +9.18, GST_TAG_TRACK_PEAK, 0.687149, NULL); |
| fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL); |
| fail_unless_target_gain (element, +9.18); /* pre-amp + track gain */ |
| /* Result is 20. * log10 (1. / peak) + headroom. */ |
| fail_unless_result_gain (element, 5.2589816238303335); |
| send_eos_event (element); |
| |
| send_flush_events (element); |
| send_segment_event (element); |
| |
| g_object_set (element, "album-mode", TRUE, NULL); |
| tag_list = gst_tag_list_new_empty (); |
| gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, |
| GST_TAG_ALBUM_GAIN, +5.50, GST_TAG_ALBUM_PEAK, 1.0, NULL); |
| fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL); |
| fail_unless_target_gain (element, +5.50); /* pre-amp + album gain */ |
| fail_unless_result_gain (element, +2.00); /* headroom */ |
| send_eos_event (element); |
| |
| cleanup_rgvolume (element); |
| } |
| |
| GST_END_TEST; |
| |
| GST_START_TEST (test_reference_level) |
| { |
| GstElement *element = setup_rgvolume (); |
| GstTagList *tag_list; |
| |
| g_object_set (element, |
| "album-mode", FALSE, |
| "headroom", +0.00, "pre-amp", +0.00, "fallback-gain", +1.23, NULL); |
| set_playing_state (element); |
| |
| send_stream_start_event (element); |
| send_caps_event (element); |
| send_segment_event (element); |
| |
| send_empty_buffer (); |
| |
| tag_list = gst_tag_list_new_empty (); |
| gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, |
| GST_TAG_TRACK_GAIN, 0.00, GST_TAG_TRACK_PEAK, 0.2, |
| GST_TAG_REFERENCE_LEVEL, 83., NULL); |
| fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL); |
| /* Because our authorative reference is 89 dB, we bump it up by +6 dB. */ |
| fail_unless_gain (element, +6.00); /* pre-amp + track gain */ |
| send_eos_event (element); |
| |
| g_object_set (element, "album-mode", TRUE, NULL); |
| |
| /* Same as above, but with album gain. */ |
| send_flush_events (element); |
| send_segment_event (element); |
| |
| tag_list = gst_tag_list_new_empty (); |
| gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, |
| GST_TAG_TRACK_GAIN, 1.23, GST_TAG_TRACK_PEAK, 0.1, |
| GST_TAG_ALBUM_GAIN, 0.00, GST_TAG_ALBUM_PEAK, 0.2, |
| GST_TAG_REFERENCE_LEVEL, 83., NULL); |
| fail_unless (send_tag_event (element, gst_event_new_tag (tag_list)) == NULL); |
| fail_unless_gain (element, +6.00); /* pre-amp + album gain */ |
| |
| cleanup_rgvolume (element); |
| } |
| |
| GST_END_TEST; |
| |
| static Suite * |
| rgvolume_suite (void) |
| { |
| Suite *s = suite_create ("rgvolume"); |
| TCase *tc_chain = tcase_create ("general"); |
| |
| suite_add_tcase (s, tc_chain); |
| |
| tcase_add_test (tc_chain, test_no_buffer); |
| tcase_add_test (tc_chain, test_events); |
| tcase_add_test (tc_chain, test_simple); |
| tcase_add_test (tc_chain, test_fallback_gain); |
| tcase_add_test (tc_chain, test_fallback_track); |
| tcase_add_test (tc_chain, test_fallback_album); |
| tcase_add_test (tc_chain, test_headroom); |
| tcase_add_test (tc_chain, test_reference_level); |
| |
| return s; |
| } |
| |
| GST_CHECK_MAIN (rgvolume); |