diff options
author | Stian Selnes <stian@pexip.com> | 2018-08-13 16:35:11 +0300 |
---|---|---|
committer | Mathieu Duponchelle <mathieu@centricular.com> | 2020-10-30 19:46:30 +0300 |
commit | 95579a00c0753630a3f3f59cbf222b47468dc5aa (patch) | |
tree | 418d5a7b6dcfff160d81e0af9f9315d6644d7e89 /tests | |
parent | d77fcf251b33691bbe52f21e061b79564000c9e8 (diff) |
rtpvp9depay: Improve SVC parsing, aggregate all layers
- Fix start and end of picture to support multiple layers. Start of
picture is the first packet of the base layer, while end of picture
is when the marker bit is set (last packet of the enhancement
layers).
- All "layers" (aka "frames") of a picture are pushed downstream in a
single buffer when picture is complete.
- Forgive SID=0 for enhancement layers (invalid, but Chrome and
Firefox sends it)
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/773>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/check/elements/rtpvp9.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/tests/check/elements/rtpvp9.c b/tests/check/elements/rtpvp9.c index f50ce3ba0..45c2c1bd2 100644 --- a/tests/check/elements/rtpvp9.c +++ b/tests/check/elements/rtpvp9.c @@ -343,6 +343,110 @@ GST_START_TEST (test_depay_resend_gap_event) GST_END_TEST; +GST_START_TEST (test_depay_svc_merge_layers) +{ + /* This simulates a simple SVC stream, for simplicity we handcraft a couple + * of rtp packets. */ + + /* First packet contains a complete base layer I-frame (s-bit and e-bit). + * Note the marker bit is not set to indicate that there will be more + * packets for this picture. */ + guint8 layer0[] = { + 0x80, 0x74, 0x00, 0x00, 0x49, 0x88, 0xd9, 0xf8, 0xa0, 0x6c, 0x65, 0x6c, + 0xac, 0x80, 0x01, 0x00, 0x01, 0x02, 0x49, 0x3f, 0x1c, 0x12, 0x0e, 0x0c, + 0xd0, 0x1b, 0xb9, 0x80, 0x80, 0xb0, 0x18, 0x0f, 0xa6, 0x4d, 0x01, 0xa5 + }; + /* s-bit, e-bit, d-bit and sid=1 set to indicate a complete enhancement + * frame. marker bit set to indicate last packet of picture. */ + guint8 layer1_with_marker[] = { + 0x80, 0xf4, 0x00, 0x01, 0x49, 0x88, 0xd9, 0xf8, 0xa0, 0x6c, 0x65, 0x6c, + 0xac, 0x80, 0x01, 0x03, 0x01, 0x02, 0x49, 0x3f, 0x1c, 0x12, 0x0e, 0x0c, + 0xd0, 0x1b, 0xb9, 0x80, 0x80, 0xb0, 0x18, 0x0f, 0xa6, 0x4d, 0x01, 0xa5 + }; + + GstBuffer *buf; + GstHarness *h = gst_harness_new ("rtpvp9depay"); + gst_harness_set_src_caps_str (h, RTP_VP9_CAPS_STR); + + /* The first packet contains a complete base layer frame that. Since the + * marker bit is not set, it will wait for an enhancement layer before it + * pushes it downstream. */ + gst_harness_push (h, gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, + layer0, sizeof (layer0), 0, sizeof (layer0), NULL, NULL)); + fail_unless_equals_int (0, gst_harness_buffers_received (h)); + + /* Next packet contains a complete enhancement frame. The picture is + * complete (marker bit set) and can be pushed */ + gst_harness_push (h, gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, + layer1_with_marker, sizeof (layer1_with_marker), 0, + sizeof (layer1_with_marker), NULL, NULL)); + fail_unless_equals_int (1, gst_harness_buffers_received (h)); + + /* The buffer should contain both layer 0 and layer 1. */ + buf = gst_harness_pull (h); + fail_unless_equals_int (19 * 2, gst_buffer_get_size (buf)); + gst_buffer_unref (buf); + + gst_harness_teardown (h); +} + +GST_END_TEST; + + +GST_START_TEST (test_depay_svc_forgive_invalid_sid) +{ + /* This simulates an invalid stream received from FF61 and Chromium 66 + * (Electron). The RTP header signals the same spatial layer ID for all + * packets of a picture (SID=0), but the s-bit, e-bit and d-bit suggests + * there is a second layer. The conservative approach would be to drop the + * enhancement layers since we don't want to push a bitstream we're + * uncertain of to the decoder. However, this reduces the quality + * significantly and also sometimes results in an encoder/decoder mismatch + * (altough it shouldn't). */ + + /* The first packet contains a complete base layer frame. Since the + * marker bit is not set, it will wait for an enhancement layer before it + * pushes it downstream. s-bit, e-bit set, no marker*/ + guint8 layer0[] = { + 0x80, 0x74, 0x00, 0x00, 0x49, 0x88, 0xd9, 0xf8, 0xa0, 0x6c, 0x65, 0x6c, + 0xac, 0x80, 0x01, 0x00, 0x01, 0x02, 0x49, 0x3f, 0x1c, 0x12, 0x0e, 0x0c, + 0xd0, 0x1b, 0xb9, 0x80, 0x80, 0xb0, 0x18, 0x0f, 0xa6, 0x4d, 0x01, 0xa5 + }; + + /* Next packet contains a complete enhancement frame. The picture is + * complete (marker bit set) and picture can be pushed. However, the SID is + * invalid (SID=0, but should be SID=1). Let's forgive that and push the + * packet downstream anyway. s-bit, e-bit, d-bit and sid=0 and marker + * bit. */ + guint8 layer1_with_sid0_and_marker[] = { + 0x80, 0xf4, 0x00, 0x01, 0x49, 0x88, 0xd9, 0xf8, 0xa0, 0x6c, 0x65, 0x6c, + 0xac, 0x80, 0x01, 0x01, 0x01, 0x02, 0x49, 0x3f, 0x1c, 0x12, 0x0e, 0x0c, + 0xd0, 0x1b, 0xb9, 0x80, 0x80, 0xb0, 0x18, 0x0f, 0xa6, 0x4d, 0x01, 0xa5 + }; + + GstBuffer *buf; + GstHarness *h = gst_harness_new ("rtpvp9depay"); + gst_harness_set_src_caps_str (h, RTP_VP9_CAPS_STR); + + gst_harness_push (h, gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, + layer0, sizeof (layer0), 0, sizeof (layer0), NULL, NULL)); + fail_unless_equals_int (0, gst_harness_buffers_received (h)); + + gst_harness_push (h, gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, + layer1_with_sid0_and_marker, sizeof (layer1_with_sid0_and_marker), 0, + sizeof (layer1_with_sid0_and_marker), NULL, NULL)); + fail_unless_equals_int (1, gst_harness_buffers_received (h)); + + /* The buffer should contain both layer 0 and layer 1. */ + buf = gst_harness_pull (h); + fail_unless_equals_int (19 * 2, gst_buffer_get_size (buf)); + gst_buffer_unref (buf); + + gst_harness_teardown (h); +} + +GST_END_TEST; + static Suite * rtpvp9_suite (void) { @@ -355,6 +459,8 @@ rtpvp9_suite (void) G_N_ELEMENTS (stop_gap_events_test_data)); tcase_add_loop_test (tc_chain, test_depay_resend_gap_event, 0, G_N_ELEMENTS (resend_gap_event_test_data)); + tcase_add_test (tc_chain, test_depay_svc_merge_layers); + tcase_add_test (tc_chain, test_depay_svc_forgive_invalid_sid); return s; } |