mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 22:36:33 +00:00
tests: Add test for rtpbasepayload/-depayload
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=720162
This commit is contained in:
parent
c734f9fba8
commit
1966b85b20
2 changed files with 396 additions and 0 deletions
|
@ -110,6 +110,7 @@ check_PROGRAMS = \
|
|||
libs/pbutils \
|
||||
libs/profile \
|
||||
libs/rtp \
|
||||
libs/rtp-basepayloading \
|
||||
libs/rtsp \
|
||||
libs/sdp \
|
||||
libs/tag \
|
||||
|
@ -251,6 +252,13 @@ libs_rtp_LDADD = \
|
|||
$(top_builddir)/gst-libs/gst/rtp/libgstrtp-@GST_API_VERSION@.la \
|
||||
$(GST_BASE_LIBS) $(LDADD)
|
||||
|
||||
libs_rtp_basepayloading_CFLAGS = \
|
||||
$(GST_PLUGINS_BASE_CFLAGS) \
|
||||
$(AM_CFLAGS)
|
||||
libs_rtp_basepayloading_LDADD = \
|
||||
$(top_builddir)/gst-libs/gst/rtp/libgstrtp-@GST_API_VERSION@.la \
|
||||
$(GST_BASE_LIBS) $(LDADD)
|
||||
|
||||
libs_rtsp_CFLAGS = \
|
||||
$(GST_PLUGINS_BASE_CFLAGS) \
|
||||
$(AM_CFLAGS)
|
||||
|
|
388
tests/check/libs/rtp-basepayloading.c
Normal file
388
tests/check/libs/rtp-basepayloading.c
Normal file
|
@ -0,0 +1,388 @@
|
|||
/* GStreamer RTP base payloader unit tests
|
||||
* Copyright (C) 2013 Sebastian Rasmussen <sebras@hotmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General
|
||||
* Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/check/gstcheck.h>
|
||||
#include <gst-libs/gst/rtp/gstrtpbuffer.h>
|
||||
#include <gst-libs/gst/rtp/gstrtpbasepayload.h>
|
||||
#include <gst-libs/gst/rtp/gstrtpbasedepayload.h>
|
||||
|
||||
/* GstRtpDummyPay */
|
||||
|
||||
#define GST_TYPE_RTP_DUMMY_PAY \
|
||||
(gst_rtp_dummy_pay_get_type())
|
||||
#define GST_RTP_DUMMY_PAY(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_DUMMY_PAY,GstRtpDummyPay))
|
||||
#define GST_RTP_DUMMY_PAY_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_DUMMY_PAY,GstRtpDummyPayClass))
|
||||
#define GST_IS_RTP_DUMMY_PAY(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_DUMMY_PAY))
|
||||
#define GST_IS_RTP_DUMMY_PAY_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_DUMMY_PAY))
|
||||
|
||||
typedef struct _GstRtpDummyPay GstRtpDummyPay;
|
||||
typedef struct _GstRtpDummyPayClass GstRtpDummyPayClass;
|
||||
|
||||
struct _GstRtpDummyPay
|
||||
{
|
||||
GstRTPBasePayload payload;
|
||||
};
|
||||
|
||||
struct _GstRtpDummyPayClass
|
||||
{
|
||||
GstRTPBasePayloadClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_rtp_dummy_pay_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (GstRtpDummyPay, gst_rtp_dummy_pay, GST_TYPE_RTP_BASE_PAYLOAD);
|
||||
|
||||
static GstFlowReturn gst_rtp_dummy_pay_handle_buffer (GstRTPBasePayload * pay,
|
||||
GstBuffer * buffer);
|
||||
|
||||
static GstStaticPadTemplate gst_rtp_dummy_pay_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static GstStaticPadTemplate gst_rtp_dummy_pay_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static void
|
||||
gst_rtp_dummy_pay_class_init (GstRtpDummyPayClass * klass)
|
||||
{
|
||||
GstElementClass *gstelement_class;
|
||||
GstRTPBasePayloadClass *gstrtpbasepayload_class;
|
||||
|
||||
gstelement_class = GST_ELEMENT_CLASS (klass);
|
||||
gstrtpbasepayload_class = GST_RTP_BASE_PAYLOAD_CLASS (klass);
|
||||
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&gst_rtp_dummy_pay_sink_template));
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&gst_rtp_dummy_pay_src_template));
|
||||
|
||||
gstrtpbasepayload_class->handle_buffer = gst_rtp_dummy_pay_handle_buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_rtp_dummy_pay_init (GstRtpDummyPay * pay)
|
||||
{
|
||||
gst_rtp_base_payload_set_options (GST_RTP_BASE_PAYLOAD (pay), "application",
|
||||
TRUE, "dummy", 42);
|
||||
}
|
||||
|
||||
static GstRtpDummyPay *
|
||||
rtp_dummy_pay_new (void)
|
||||
{
|
||||
return g_object_new (GST_TYPE_RTP_DUMMY_PAY, NULL);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_rtp_dummy_pay_handle_buffer (GstRTPBasePayload * pay, GstBuffer * buffer)
|
||||
{
|
||||
GstBuffer *paybuffer;
|
||||
|
||||
if (!gst_pad_has_current_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (pay))) {
|
||||
if (!gst_rtp_base_payload_set_outcaps (GST_RTP_BASE_PAYLOAD (pay), NULL)) {
|
||||
gst_buffer_unref (buffer);
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
}
|
||||
}
|
||||
|
||||
paybuffer = gst_rtp_buffer_new_allocate (0, 0, 0);
|
||||
GST_BUFFER_PTS (paybuffer) = GST_BUFFER_PTS (buffer);
|
||||
GST_BUFFER_OFFSET (paybuffer) = GST_BUFFER_OFFSET (buffer);
|
||||
gst_buffer_append (paybuffer, buffer);
|
||||
|
||||
return gst_rtp_base_payload_push (pay, paybuffer);
|
||||
}
|
||||
|
||||
/* GstRtpDummyDepay */
|
||||
|
||||
#define GST_TYPE_RTP_DUMMY_DEPAY \
|
||||
(gst_rtp_dummy_depay_get_type())
|
||||
#define GST_RTP_DUMMY_DEPAY(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RTP_DUMMY_DEPAY,GstRtpDummyDepay))
|
||||
#define GST_RTP_DUMMY_DEPAY_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RTP_DUMMY_DEPAY,GstRtpDummyDepayClass))
|
||||
#define GST_IS_RTP_DUMMY_DEPAY(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RTP_DUMMY_DEPAY))
|
||||
#define GST_IS_RTP_DUMMY_DEPAY_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RTP_DUMMY_DEPAY))
|
||||
|
||||
typedef struct _GstRtpDummyDepay GstRtpDummyDepay;
|
||||
typedef struct _GstRtpDummyDepayClass GstRtpDummyDepayClass;
|
||||
|
||||
struct _GstRtpDummyDepay
|
||||
{
|
||||
GstRTPBaseDepayload depayload;
|
||||
};
|
||||
|
||||
struct _GstRtpDummyDepayClass
|
||||
{
|
||||
GstRTPBaseDepayloadClass parent_class;
|
||||
};
|
||||
|
||||
GType gst_rtp_dummy_depay_get_type (void);
|
||||
|
||||
G_DEFINE_TYPE (GstRtpDummyDepay, gst_rtp_dummy_depay,
|
||||
GST_TYPE_RTP_BASE_DEPAYLOAD);
|
||||
|
||||
static GstBuffer *gst_rtp_dummy_depay_process (GstRTPBaseDepayload * depayload,
|
||||
GstBuffer * buf);
|
||||
|
||||
static GstStaticPadTemplate gst_rtp_dummy_depay_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static GstStaticPadTemplate gst_rtp_dummy_depay_src_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS_ANY);
|
||||
|
||||
static void
|
||||
gst_rtp_dummy_depay_class_init (GstRtpDummyDepayClass * klass)
|
||||
{
|
||||
GstElementClass *gstelement_class;
|
||||
GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
|
||||
|
||||
gstelement_class = GST_ELEMENT_CLASS (klass);
|
||||
gstrtpbasedepayload_class = GST_RTP_BASE_DEPAYLOAD_CLASS (klass);
|
||||
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&gst_rtp_dummy_depay_sink_template));
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&gst_rtp_dummy_depay_src_template));
|
||||
|
||||
gstrtpbasedepayload_class->process = gst_rtp_dummy_depay_process;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_rtp_dummy_depay_init (GstRtpDummyDepay * depay)
|
||||
{
|
||||
}
|
||||
|
||||
static GstRtpDummyDepay *
|
||||
rtp_dummy_depay_new (void)
|
||||
{
|
||||
return g_object_new (GST_TYPE_RTP_DUMMY_DEPAY, NULL);
|
||||
}
|
||||
|
||||
static GstBuffer *
|
||||
gst_rtp_dummy_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf)
|
||||
{
|
||||
GstRTPBuffer rtp = { NULL };
|
||||
GstBuffer *outbuf;
|
||||
|
||||
gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
|
||||
outbuf = gst_rtp_buffer_get_payload_buffer (&rtp);
|
||||
gst_rtp_buffer_unmap (&rtp);
|
||||
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
/* Tests */
|
||||
|
||||
static gboolean
|
||||
bus_callback (GstBus * bus, GstMessage * message, gpointer user_data)
|
||||
{
|
||||
GMainLoop *mainloop = (GMainLoop *) user_data;
|
||||
gboolean result;
|
||||
|
||||
switch (GST_MESSAGE_TYPE (message)) {
|
||||
case GST_MESSAGE_ERROR:
|
||||
{
|
||||
GError *err;
|
||||
gchar *debug;
|
||||
gchar *element_name;
|
||||
|
||||
element_name = message->src ? gst_object_get_name (message->src) : NULL;
|
||||
gst_message_parse_error (message, &err, &debug);
|
||||
fail ("Error from element %s: %s\n%s", GST_STR_NULL (element_name),
|
||||
err->message, debug ? debug : "");
|
||||
g_error_free (err);
|
||||
g_free (debug);
|
||||
g_free (element_name);
|
||||
|
||||
g_main_loop_quit (mainloop);
|
||||
result = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case GST_MESSAGE_EOS:
|
||||
g_main_loop_quit (mainloop);
|
||||
result = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
push_buffer (GstElement * src, GstClockTime timestamp)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
GstFlowReturn ret;
|
||||
|
||||
GST_LOG ("pushing buffer %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));
|
||||
|
||||
buf = gst_buffer_new_allocate (NULL, 0, NULL);
|
||||
GST_BUFFER_PTS (buf) = timestamp;
|
||||
g_signal_emit_by_name (src, "push-buffer", buf, &ret);
|
||||
fail_unless_equals_int (ret, GST_FLOW_OK);
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
|
||||
static void
|
||||
await_buffer (GstElement * sink, GstClockTime timestamp)
|
||||
{
|
||||
GstSample *sample = NULL;
|
||||
GstBuffer *buf;
|
||||
|
||||
GST_LOG ("awaiting buffer %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp));
|
||||
|
||||
g_signal_emit_by_name (sink, "pull-sample", &sample);
|
||||
fail_if (sample == NULL);
|
||||
buf = gst_sample_get_buffer (sample);
|
||||
GST_LOG ("got buffer %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (GST_BUFFER_PTS (buf)));
|
||||
fail_unless_equals_int (GST_BUFFER_PTS (buf), timestamp);
|
||||
gst_sample_unref (sample);
|
||||
}
|
||||
|
||||
static void
|
||||
push_eos (GstElement * src)
|
||||
{
|
||||
GstFlowReturn ret;
|
||||
|
||||
GST_LOG ("pushing EOS");
|
||||
|
||||
g_signal_emit_by_name (src, "end-of-stream", &ret);
|
||||
fail_unless_equals_int (ret, GST_FLOW_OK);
|
||||
}
|
||||
|
||||
static void
|
||||
await_eos (GstElement * sink)
|
||||
{
|
||||
GstSample *sample = NULL;
|
||||
gboolean eos;
|
||||
|
||||
GST_LOG ("awaiting EOS");
|
||||
|
||||
g_signal_emit_by_name (sink, "pull-sample", &sample);
|
||||
fail_if (sample != NULL);
|
||||
g_object_get (sink, "eos", &eos, NULL);
|
||||
fail_unless (eos);
|
||||
}
|
||||
|
||||
GST_START_TEST (rtp_base_test)
|
||||
{
|
||||
GstElement *pipeline, *src, *pay, *depay, *sink;
|
||||
GMainLoop *mainloop;
|
||||
GstBus *bus;
|
||||
GstCaps *caps;
|
||||
|
||||
pipeline = gst_pipeline_new (NULL);
|
||||
fail_unless (GST_IS_PIPELINE (pipeline));
|
||||
|
||||
src = gst_element_factory_make ("appsrc", NULL);
|
||||
fail_unless (src != NULL);
|
||||
|
||||
pay = GST_ELEMENT (rtp_dummy_pay_new ());
|
||||
fail_unless (GST_IS_RTP_DUMMY_PAY (pay));
|
||||
|
||||
depay = GST_ELEMENT (rtp_dummy_depay_new ());
|
||||
fail_unless (GST_IS_RTP_DUMMY_DEPAY (depay));
|
||||
|
||||
sink = gst_element_factory_make ("appsink", NULL);
|
||||
|
||||
caps = gst_caps_from_string ("application/x-raw");
|
||||
g_object_set (src, "do-timestamp", TRUE, "caps", caps, "format",
|
||||
GST_FORMAT_TIME, NULL);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
g_object_set (sink, "sync", FALSE, "emit-signals", TRUE, NULL);
|
||||
|
||||
gst_bin_add_many (GST_BIN (pipeline), src, pay, depay, sink, NULL);
|
||||
|
||||
fail_unless (gst_element_link (src, pay));
|
||||
fail_unless (gst_element_link (pay, depay));
|
||||
fail_unless (gst_element_link (depay, sink));
|
||||
|
||||
mainloop = g_main_loop_new (NULL, FALSE);
|
||||
fail_unless (mainloop != NULL);
|
||||
|
||||
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
|
||||
gst_bus_add_watch (bus, bus_callback, (gpointer) mainloop);
|
||||
gst_object_unref (bus);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
|
||||
fail_unless (gst_element_seek (src, 1.0, GST_FORMAT_TIME,
|
||||
GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE,
|
||||
GST_CLOCK_TIME_NONE));
|
||||
|
||||
push_buffer (src, 0 * GST_SECOND);
|
||||
await_buffer (sink, 0 * GST_SECOND);
|
||||
|
||||
push_buffer (src, 1 * GST_SECOND);
|
||||
await_buffer (sink, 1 * GST_SECOND);
|
||||
|
||||
push_eos (src);
|
||||
await_eos (sink);
|
||||
|
||||
g_main_loop_run (mainloop);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
|
||||
g_main_loop_unref (mainloop);
|
||||
|
||||
gst_object_unref (pipeline);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
rtp_basepayloading_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("rtp_base_payloading_test");
|
||||
TCase *tc_chain = tcase_create ("");
|
||||
|
||||
tcase_set_timeout (tc_chain, 60);
|
||||
|
||||
suite_add_tcase (s, tc_chain);
|
||||
tcase_add_test (tc_chain, rtp_base_test);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
GST_CHECK_MAIN (rtp_basepayloading)
|
Loading…
Reference in a new issue