From 9cd36cdd68603725e2d9996f76d1e1d04d8d7fd0 Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Sun, 13 Dec 2020 23:05:59 +0100 Subject: [PATCH] add server read tests with gstreamer --- serverconf_test.go | 13 ++++ testimages/ffmpeg/Dockerfile | 2 +- testimages/gstreamer/Dockerfile | 33 +++++++++- testimages/gstreamer/exitafterframe.c | 95 +++++++++++++++++++++++++++ testimages/gstreamer/start.sh | 2 +- 5 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 testimages/gstreamer/exitafterframe.c diff --git a/serverconf_test.go b/serverconf_test.go index 80acc7ae..06bc7171 100644 --- a/serverconf_test.go +++ b/serverconf_test.go @@ -277,8 +277,12 @@ func TestServerPublishReadTCP(t *testing.T) { }{ {"ffmpeg", "ffmpeg", false}, {"ffmpeg", "ffmpeg", true}, + {"ffmpeg", "gstreamer", false}, + {"ffmpeg", "gstreamer", true}, {"gstreamer", "ffmpeg", false}, {"gstreamer", "ffmpeg", true}, + {"gstreamer", "gstreamer", false}, + {"gstreamer", "gstreamer", true}, } { encryptedStr := func() string { if ca.encrypted { @@ -342,6 +346,15 @@ func TestServerPublishReadTCP(t *testing.T) { require.NoError(t, err) defer cnt2.close() require.Equal(t, 0, cnt2.wait()) + + case "gstreamer": + cnt2, err := newContainer("gstreamer", "read", []string{ + "rtspsrc location=" + proto + "://127.0.0.1:8554/teststream protocols=tcp tls-validation-flags=0 latency=0 " + + "! application/x-rtp,media=video ! decodebin ! exitafterframe ! fakesink", + }) + require.NoError(t, err) + defer cnt2.close() + require.Equal(t, 0, cnt2.wait()) } }) } diff --git a/testimages/ffmpeg/Dockerfile b/testimages/ffmpeg/Dockerfile index 1f380e26..31c0786e 100644 --- a/testimages/ffmpeg/Dockerfile +++ b/testimages/ffmpeg/Dockerfile @@ -1,4 +1,4 @@ -FROM amd64/alpine:3.12 +FROM alpine:3.12 RUN apk add --no-cache \ ffmpeg diff --git a/testimages/gstreamer/Dockerfile b/testimages/gstreamer/Dockerfile index 565dee4b..7fe8be39 100644 --- a/testimages/gstreamer/Dockerfile +++ b/testimages/gstreamer/Dockerfile @@ -1,12 +1,43 @@ -FROM amd64/ubuntu:20.04 +###################################### +FROM ubuntu:20.04 AS exitafterframe + +RUN apt update && apt install -y --no-install-recommends \ + pkg-config \ + gcc \ + libgstreamer-plugins-base1.0-dev \ + && rm -rf /var/lib/apt/lists/* + +COPY exitafterframe.c /s/ +RUN cd /s \ + && gcc \ + exitafterframe.c \ + -o libexitafterframe.so \ + -Ofast \ + -s \ + -Werror \ + -Wall \ + -Wextra \ + -Wno-unused-parameter \ + -fPIC \ + -shared \ + -Wl,--no-undefined \ + $(pkg-config --cflags --libs gstreamer-1.0) \ + && mv libexitafterframe.so /usr/lib/x86_64-linux-gnu/gstreamer-1.0/ \ + && rm -rf /s + +###################################### +FROM ubuntu:20.04 RUN apt update && apt install -y --no-install-recommends \ gstreamer1.0-tools \ gstreamer1.0-plugins-good \ gstreamer1.0-plugins-bad \ gstreamer1.0-rtsp \ + gstreamer1.0-libav \ && rm -rf /var/lib/apt/lists/* +COPY --from=exitafterframe /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libexitafterframe.so /usr/lib/x86_64-linux-gnu/gstreamer-1.0/ + COPY emptyvideo.ts / COPY start.sh / diff --git a/testimages/gstreamer/exitafterframe.c b/testimages/gstreamer/exitafterframe.c new file mode 100644 index 00000000..eb3626bf --- /dev/null +++ b/testimages/gstreamer/exitafterframe.c @@ -0,0 +1,95 @@ + +#include +#include + +GType gst_exitafterframe_get_type (); + +#define GST_TYPE_EXITAFTERFRAME (gst_exitafterframe_get_type()) +#define GST_EXITAFTERFRAME(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_EXITAFTERFRAME,GstExitAfterFrame)) + +typedef struct +{ + GstElement element; + GstPad *srcpad; + GstPad *sinkpad; + +} GstExitAfterFrame; + +typedef struct +{ + GstElementClass parent_class; + +} GstExitAfterFrameClass; + +#define gst_exitafterframe_parent_class parent_class +G_DEFINE_TYPE (GstExitAfterFrame, gst_exitafterframe, GST_TYPE_ELEMENT); + +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE( + "sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS("video/x-raw") +); + +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE( + "src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS("video/x-raw") +); + +static GstFlowReturn +gst_exitafterframe_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) +{ + GstExitAfterFrame *filter = GST_EXITAFTERFRAME (parent); + exit(0); + return gst_pad_push (filter->srcpad, buf); +} + +static void +gst_exitafterframe_class_init(GstExitAfterFrameClass* klass) { + GstElementClass* element_class = (GstElementClass*)klass; + + gst_element_class_set_details_simple( + element_class, + "Plugin", + "FIXME:Generic", + "FIXME:Generic Template Element", + "AUTHOR_NAME AUTHOR_EMAIL" + ); + + gst_element_class_add_pad_template(element_class, + gst_static_pad_template_get(&src_factory)); + gst_element_class_add_pad_template(element_class, + gst_static_pad_template_get(&sink_factory)); +} + +static void +gst_exitafterframe_init (GstExitAfterFrame* filter) +{ + GstElement* element = GST_ELEMENT(filter); + + g_print("[lasermqtt] init()\n"); + + filter->sinkpad = gst_pad_new_from_static_template(&sink_factory, "sink"); + gst_pad_set_chain_function(filter->sinkpad, gst_exitafterframe_chain); + GST_PAD_SET_PROXY_CAPS(filter->sinkpad); + gst_element_add_pad(element, filter->sinkpad); + + filter->srcpad = gst_pad_new_from_static_template(&src_factory, "src"); + GST_PAD_SET_PROXY_CAPS(filter->srcpad); + gst_element_add_pad(element, filter->srcpad); +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "exitafterframe", GST_RANK_NONE, + GST_TYPE_EXITAFTERFRAME); +} + +#define PACKAGE "exitafterframe" + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, exitafterframe, + "exitafterframe", plugin_init, "1.0", "LGPL", "exitafterframe", + "http://example.com") diff --git a/testimages/gstreamer/start.sh b/testimages/gstreamer/start.sh index c66f6f0d..db4a5bc1 100644 --- a/testimages/gstreamer/start.sh +++ b/testimages/gstreamer/start.sh @@ -1,3 +1,3 @@ #!/bin/sh -e -exec gst-launch-1.0 $@ +exec gst-launch-1.0 $@ 2>&1