mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 17:20:36 +00:00
tests: add more unit test for playbin
Add unit test for autoplugging of video_decoder/video_sink combination based on capsfeatures.
This commit is contained in:
parent
567be29db2
commit
eabd2a5c7b
2 changed files with 254 additions and 1 deletions
|
@ -329,7 +329,7 @@ elements_libvisual_CFLAGS = $(CFLAGS) $(AM_CFLAGS)
|
||||||
elements_playbin_LDADD = $(GST_BASE_LIBS) $(LDADD)
|
elements_playbin_LDADD = $(GST_BASE_LIBS) $(LDADD)
|
||||||
elements_playbin_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS)
|
elements_playbin_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS)
|
||||||
|
|
||||||
elements_playbin_complex_LDADD = $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_API_VERSION@.la $(GST_BASE_LIBS) $(LDADD)
|
elements_playbin_complex_LDADD = $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_API_VERSION@.la $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_API_VERSION@.la $(GST_BASE_LIBS) $(LDADD)
|
||||||
elements_playbin_complex_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS)
|
elements_playbin_complex_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS)
|
||||||
|
|
||||||
elements_decodebin_LDADD = $(GST_BASE_LIBS) $(LDADD)
|
elements_decodebin_LDADD = $(GST_BASE_LIBS) $(LDADD)
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <gst/base/gstpushsrc.h>
|
#include <gst/base/gstpushsrc.h>
|
||||||
#include <gst/base/gstbasesink.h>
|
#include <gst/base/gstbasesink.h>
|
||||||
#include <gst/audio/streamvolume.h>
|
#include <gst/audio/streamvolume.h>
|
||||||
|
#include <gst/video/gstvideodecoder.h>
|
||||||
|
|
||||||
#ifndef GST_DISABLE_REGISTRY
|
#ifndef GST_DISABLE_REGISTRY
|
||||||
|
|
||||||
|
@ -37,6 +38,10 @@ static GType gst_codec_demuxer_get_type (void);
|
||||||
static GType gst_codec_sink_get_type (void);
|
static GType gst_codec_sink_get_type (void);
|
||||||
static GType gst_audio_codec_sink_get_type (void);
|
static GType gst_audio_codec_sink_get_type (void);
|
||||||
static GType gst_video_codec_sink_get_type (void);
|
static GType gst_video_codec_sink_get_type (void);
|
||||||
|
static GType gst_video_decoder1_get_type (void);
|
||||||
|
static GType gst_video_decoder2_get_type (void);
|
||||||
|
static GType gst_video_sink1_get_type (void);
|
||||||
|
static GType gst_video_sink2_get_type (void);
|
||||||
|
|
||||||
typedef struct _GstCapsSrc GstCapsSrc;
|
typedef struct _GstCapsSrc GstCapsSrc;
|
||||||
typedef GstPushSrcClass GstCapsSrcClass;
|
typedef GstPushSrcClass GstCapsSrcClass;
|
||||||
|
@ -590,10 +595,202 @@ gst_codec_demuxer_init (GstCodecDemuxer * demux)
|
||||||
gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
|
gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct _GstVideoDecoder1 GstVideoDecoder1;
|
||||||
|
typedef GstVideoDecoderClass GstVideoDecoder1Class;
|
||||||
|
|
||||||
|
typedef struct _GstVideoDecoder2 GstVideoDecoder2;
|
||||||
|
typedef GstVideoDecoderClass GstVideoDecoder2Class;
|
||||||
|
|
||||||
|
typedef struct _GstVideoSink1 GstVideoSink1;
|
||||||
|
typedef GstBaseSinkClass GstVideoSink1Class;
|
||||||
|
|
||||||
|
typedef struct _GstVideoSink2 GstVideoSink2;
|
||||||
|
typedef GstBaseSinkClass GstVideoSink2Class;
|
||||||
|
|
||||||
|
struct _GstVideoDecoder1
|
||||||
|
{
|
||||||
|
GstVideoDecoder parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstVideoDecoder2
|
||||||
|
{
|
||||||
|
GstVideoDecoder parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstVideoSink1
|
||||||
|
{
|
||||||
|
GstBaseSink parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstVideoSink2
|
||||||
|
{
|
||||||
|
GstBaseSink parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GST_CAPS_FEATURE_MEMORY_FAKE "memory:FakeMem"
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GstVideoDecoder1, gst_video_decoder1, GST_TYPE_VIDEO_DECODER);
|
||||||
|
G_DEFINE_TYPE (GstVideoDecoder2, gst_video_decoder2, GST_TYPE_VIDEO_DECODER);
|
||||||
|
G_DEFINE_TYPE (GstVideoSink1, gst_video_sink1, GST_TYPE_BASE_SINK);
|
||||||
|
G_DEFINE_TYPE (GstVideoSink2, gst_video_sink2, GST_TYPE_BASE_SINK);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_video_sink1_class_init (GstVideoSink1Class * klass)
|
||||||
|
{
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK, GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
|
||||||
|
(GST_CAPS_FEATURE_MEMORY_FAKE,
|
||||||
|
GST_VIDEO_FORMATS_ALL) ";"
|
||||||
|
GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL))
|
||||||
|
);
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&sink_templ));
|
||||||
|
|
||||||
|
gst_element_class_set_static_metadata (element_class,
|
||||||
|
"Fake Video Sink1", "Sink/Video",
|
||||||
|
"fake sink1", "Sreerenj Balachandran <sreerenj.balachandran@intel.com>");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_video_sink1_init (GstVideoSink1 * sink)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_video_sink2_class_init (GstVideoSink2Class * klass)
|
||||||
|
{
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK, GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL)));
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&sink_templ));
|
||||||
|
|
||||||
|
gst_element_class_set_static_metadata (element_class,
|
||||||
|
"Fake Video Sink2", "Sink/Video",
|
||||||
|
"fake sink2", "Sreerenj Balachandran <sreerenj.balachandran@intel.com>");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_video_sink2_init (GstVideoSink2 * sink)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
fake_theora_dec_handle_frame (GstVideoDecoder * bdec,
|
||||||
|
GstVideoCodecFrame * frame)
|
||||||
|
{
|
||||||
|
/* the width and height are hard-coded for ../../files/theora-vorbis.ogg */
|
||||||
|
gst_video_codec_state_unref (gst_video_decoder_set_output_state (bdec,
|
||||||
|
GST_VIDEO_FORMAT_NV12, 320, 240, NULL));
|
||||||
|
gst_video_decoder_allocate_output_frame (bdec, frame);
|
||||||
|
return gst_video_decoder_finish_frame (bdec, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_video_decoder1_class_init (GstVideoDecoder1Class * klass)
|
||||||
|
{
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
GstVideoDecoderClass *vd_class = GST_VIDEO_DECODER_CLASS (klass);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK, GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("video/x-theora"));
|
||||||
|
|
||||||
|
static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES
|
||||||
|
(GST_CAPS_FEATURE_MEMORY_FAKE,
|
||||||
|
GST_VIDEO_FORMATS_ALL) ";"
|
||||||
|
GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL)));
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&sink_templ));
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&src_templ));
|
||||||
|
gst_element_class_set_static_metadata (element_class,
|
||||||
|
"Fake theora video decoder1", "Codec/Decoder/Video",
|
||||||
|
"decode theora stream",
|
||||||
|
"Sreerenj Balachandran <sreerenj.balachandran@intel.com>");
|
||||||
|
|
||||||
|
vd_class->handle_frame = fake_theora_dec_handle_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_video_decoder1_init (GstVideoDecoder1 * dec1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_video_decoder2_class_init (GstVideoDecoder2Class * klass)
|
||||||
|
{
|
||||||
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
GstVideoDecoderClass *vd_class = GST_VIDEO_DECODER_CLASS (klass);
|
||||||
|
|
||||||
|
static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
|
GST_PAD_SINK, GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS ("video/x-theora"));
|
||||||
|
|
||||||
|
static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL)));
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&sink_templ));
|
||||||
|
gst_element_class_add_pad_template (element_class,
|
||||||
|
gst_static_pad_template_get (&src_templ));
|
||||||
|
gst_element_class_set_static_metadata (element_class,
|
||||||
|
"Fake theora video decoder2", "Codec/Decoder/Video",
|
||||||
|
"decode theora stream",
|
||||||
|
"Sreerenj Balachandran <sreerenj.balachandran@intel.com>");
|
||||||
|
|
||||||
|
vd_class->handle_frame = fake_theora_dec_handle_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_video_decoder2_init (GstVideoDecoder2 * dec2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/****
|
/****
|
||||||
* Start of the tests
|
* Start of the tests
|
||||||
***/
|
***/
|
||||||
|
|
||||||
|
static void
|
||||||
|
pipeline_deep_notify_caps_cb (GstObject * pipeline,
|
||||||
|
GstObject * object, GParamSpec * pspec, GstElement ** dec)
|
||||||
|
{
|
||||||
|
GstObject *pad_parent;
|
||||||
|
|
||||||
|
if (!GST_IS_PAD (object))
|
||||||
|
return;
|
||||||
|
|
||||||
|
pad_parent = gst_object_get_parent (object);
|
||||||
|
|
||||||
|
if (GST_IS_ELEMENT (pad_parent) && *dec == NULL) {
|
||||||
|
GstElementFactory *factory;
|
||||||
|
GstElement *element;
|
||||||
|
const gchar *klass;
|
||||||
|
|
||||||
|
element = GST_ELEMENT_CAST (pad_parent);
|
||||||
|
if ((factory = gst_element_get_factory (element)) &&
|
||||||
|
(klass =
|
||||||
|
gst_element_factory_get_metadata (factory,
|
||||||
|
GST_ELEMENT_METADATA_KLASS)) && strstr (klass, "Video")
|
||||||
|
&& strstr (klass, "Decoder")) {
|
||||||
|
*dec = gst_object_ref (element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pad_parent)
|
||||||
|
gst_object_unref (pad_parent);
|
||||||
|
}
|
||||||
|
|
||||||
static GstElement *
|
static GstElement *
|
||||||
create_playbin (const gchar * uri, gboolean set_sink)
|
create_playbin (const gchar * uri, gboolean set_sink)
|
||||||
{
|
{
|
||||||
|
@ -627,6 +824,61 @@ create_playbin (const gchar * uri, gboolean set_sink)
|
||||||
return playbin;
|
return playbin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GST_START_TEST (test_autoplug_decoder_sink_combination)
|
||||||
|
{
|
||||||
|
GstElement *playbin;
|
||||||
|
GstElement *decoder = NULL;
|
||||||
|
GstElement *sink;
|
||||||
|
gchar *path, *uri;
|
||||||
|
|
||||||
|
fail_unless (gst_element_register (NULL, "faketheoradec1",
|
||||||
|
GST_RANK_PRIMARY + 1, gst_video_decoder1_get_type ()));
|
||||||
|
fail_unless (gst_element_register (NULL, "faketheoradec2",
|
||||||
|
GST_RANK_PRIMARY + 1, gst_video_decoder2_get_type ()));
|
||||||
|
fail_unless (gst_element_register (NULL, "fakevideosink1",
|
||||||
|
GST_RANK_PRIMARY + 1, gst_video_sink1_get_type ()));
|
||||||
|
fail_unless (gst_element_register (NULL, "fakevideosink2",
|
||||||
|
GST_RANK_PRIMARY + 1, gst_video_sink2_get_type ()));
|
||||||
|
|
||||||
|
path = g_build_filename (GST_TEST_FILES_PATH, "theora-vorbis.ogg", NULL);
|
||||||
|
uri = gst_filename_to_uri (path, NULL);
|
||||||
|
g_free (path);
|
||||||
|
|
||||||
|
playbin = create_playbin (uri, FALSE);
|
||||||
|
|
||||||
|
g_signal_connect (playbin, "deep-notify::caps",
|
||||||
|
G_CALLBACK (pipeline_deep_notify_caps_cb), &decoder);
|
||||||
|
|
||||||
|
fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY),
|
||||||
|
GST_STATE_CHANGE_SUCCESS);
|
||||||
|
fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PLAYING),
|
||||||
|
GST_STATE_CHANGE_ASYNC);
|
||||||
|
fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL, -1),
|
||||||
|
GST_STATE_CHANGE_SUCCESS);
|
||||||
|
|
||||||
|
/* there shouldn't be any errors */
|
||||||
|
fail_if (gst_bus_poll (GST_ELEMENT_BUS (playbin), GST_MESSAGE_ERROR,
|
||||||
|
0) != NULL);
|
||||||
|
|
||||||
|
g_object_get (G_OBJECT (playbin), "video-sink", &sink, NULL);
|
||||||
|
fail_unless (sink != NULL);
|
||||||
|
{
|
||||||
|
fail_unless (G_TYPE_FROM_INSTANCE (sink) == gst_video_sink1_get_type ());
|
||||||
|
gst_object_unref (sink);
|
||||||
|
}
|
||||||
|
|
||||||
|
fail_unless (decoder != NULL);
|
||||||
|
{
|
||||||
|
fail_unless (G_TYPE_FROM_INSTANCE (decoder) ==
|
||||||
|
gst_video_decoder1_get_type ());
|
||||||
|
gst_object_unref (decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_element_set_state (playbin, GST_STATE_NULL);
|
||||||
|
gst_object_unref (playbin);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
GST_START_TEST (test_raw_single_video_stream_manual_sink)
|
GST_START_TEST (test_raw_single_video_stream_manual_sink)
|
||||||
{
|
{
|
||||||
GstMessage *msg;
|
GstMessage *msg;
|
||||||
|
@ -2513,6 +2765,7 @@ playbin_complex_suite (void)
|
||||||
test_raw_compressed_video_stream_demuxer_manual_sink);
|
test_raw_compressed_video_stream_demuxer_manual_sink);
|
||||||
|
|
||||||
tcase_add_test (tc_chain, test_raw_raw_audio_stream_adder_manual_sink);
|
tcase_add_test (tc_chain, test_raw_raw_audio_stream_adder_manual_sink);
|
||||||
|
tcase_add_test (tc_chain, test_autoplug_decoder_sink_combination);
|
||||||
|
|
||||||
/* These tests need something like the stream-activate event
|
/* These tests need something like the stream-activate event
|
||||||
* and are racy otherwise */
|
* and are racy otherwise */
|
||||||
|
|
Loading…
Reference in a new issue