diff --git a/server/module-elements/src/gst-plugins/kmscompositemixer.c b/server/module-elements/src/gst-plugins/kmscompositemixer.c index 4c32112f88..ee10670574 100644 --- a/server/module-elements/src/gst-plugins/kmscompositemixer.c +++ b/server/module-elements/src/gst-plugins/kmscompositemixer.c @@ -40,12 +40,12 @@ GST_DEBUG_CATEGORY_STATIC (kms_composite_mixer_debug_category); #define GST_CAT_DEFAULT kms_composite_mixer_debug_category #define KMS_COMPOSITE_MIXER_GET_PRIVATE(obj) (\ - G_TYPE_INSTANCE_GET_PRIVATE ( \ - (obj), \ - KMS_TYPE_COMPOSITE_MIXER, \ - KmsCompositeMixerPrivate \ - ) \ -) + G_TYPE_INSTANCE_GET_PRIVATE ( \ + (obj), \ + KMS_TYPE_COMPOSITE_MIXER, \ + KmsCompositeMixerPrivate \ + ) \ + ) #define AUDIO_SINK_PAD_PREFIX_COMP "audio_sink_" #define VIDEO_SINK_PAD_PREFIX_COMP "video_sink_" @@ -97,7 +97,7 @@ struct _KmsCompositeMixerPrivate KmsLoop *loop; GRecMutex mutex; gint n_elems; - gint output_width, output_height; + gint output_width, output_height, output_framerate; }; /* class initialization */ @@ -131,7 +131,7 @@ typedef struct _KmsCompositeMixerData kms_ref_struct_unref (KMS_REF_STRUCT_CAST (data)) static void -kms_destroy_composite_mixer_data (KmsCompositeMixerData * data) +kms_destroy_composite_mixer_data (KmsCompositeMixerData *data) { g_slice_free (KmsCompositeMixerData, data); } @@ -211,7 +211,7 @@ kms_composite_mixer_recalculate_sizes (gpointer data) } static gboolean -remove_elements_from_pipeline (KmsCompositeMixerData * port_data) +remove_elements_from_pipeline (KmsCompositeMixerData *port_data) { KmsCompositeMixer *self = port_data->mixer; @@ -259,7 +259,7 @@ remove_elements_from_pipeline (KmsCompositeMixerData * port_data) } static GstPadProbeReturn -cb_EOS_received (GstPad * pad, GstPadProbeInfo * info, gpointer data) +cb_EOS_received (GstPad *pad, GstPadProbeInfo *info, gpointer data) { KmsCompositeMixerData *port_data = (KmsCompositeMixerData *) data; KmsCompositeMixer *self = port_data->mixer; @@ -296,7 +296,7 @@ cb_EOS_received (GstPad * pad, GstPadProbeInfo * info, gpointer data) } static GstPadProbeReturn -cb_latency (GstPad * pad, GstPadProbeInfo * info, gpointer data) +cb_latency (GstPad *pad, GstPadProbeInfo *info, gpointer data) { if (GST_QUERY_TYPE (GST_PAD_PROBE_INFO_QUERY (info)) != GST_QUERY_LATENCY) { return GST_PAD_PROBE_OK; @@ -358,6 +358,7 @@ kms_composite_mixer_port_data_destroy (gpointer data) self->priv->n_elems--; kms_composite_mixer_recalculate_sizes (self); } + KMS_COMPOSITE_MIXER_UNLOCK (self); if (!result) { @@ -379,6 +380,7 @@ kms_composite_mixer_port_data_destroy (gpointer data) (GDestroyNotify) kms_ref_struct_unref); } } + gst_element_unlink (port_data->capsfilter, port_data->tee); g_object_unref (pad); } else { @@ -394,6 +396,7 @@ kms_composite_mixer_port_data_destroy (gpointer data) if (port_data->link_probe_id > 0) { gst_pad_remove_probe (port_data->tee_sink_pad, port_data->link_probe_id); } + KMS_COMPOSITE_MIXER_UNLOCK (self); gst_element_unlink (port_data->capsfilter, port_data->tee); @@ -423,8 +426,8 @@ kms_composite_mixer_port_data_destroy (gpointer data) } static GstPadProbeReturn -link_to_videomixer (GstPad * pad, GstPadProbeInfo * info, - KmsCompositeMixerData * data) +link_to_videomixer (GstPad *pad, GstPadProbeInfo *info, + KmsCompositeMixerData *data) { GstPadTemplate *sink_pad_template; KmsCompositeMixer *mixer; @@ -502,7 +505,7 @@ create_gint (gint value) } static void -kms_composite_mixer_unhandle_port (KmsBaseHub * mixer, gint id) +kms_composite_mixer_unhandle_port (KmsBaseHub *mixer, gint id) { KmsCompositeMixer *self = KMS_COMPOSITE_MIXER (mixer); @@ -519,7 +522,7 @@ kms_composite_mixer_unhandle_port (KmsBaseHub * mixer, gint id) } static KmsCompositeMixerData * -kms_composite_mixer_port_data_create (KmsCompositeMixer * mixer, gint id) +kms_composite_mixer_port_data_create (KmsCompositeMixer *mixer, gint id) { KmsCompositeMixerData *data; GstPad *tee_src; @@ -533,7 +536,6 @@ kms_composite_mixer_port_data_create (KmsCompositeMixer * mixer, gint id) data->removing = FALSE; data->eos_managed = FALSE; - // Link AUDIO input padname = g_strdup_printf (AUDIO_SINK_PAD, data->id); @@ -541,7 +543,6 @@ kms_composite_mixer_port_data_create (KmsCompositeMixer * mixer, gint id) mixer->priv->audiomixer, padname, FALSE); g_free (padname); - // Link VIDEO input data->tee = kms_utils_element_factory_make ("tee", PLUGIN_NAME); @@ -564,6 +565,7 @@ kms_composite_mixer_port_data_create (KmsCompositeMixer * mixer, gint id) gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT, mixer->priv->output_width, "height", G_TYPE_INT, mixer->priv->output_height, + "framerate", GST_TYPE_FRACTION, mixer->priv->output_framerate, 1, "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL); g_object_set (data->capsfilter, "caps", filtercaps, NULL); gst_caps_unref (filtercaps); @@ -581,48 +583,50 @@ kms_composite_mixer_port_data_create (KmsCompositeMixer * mixer, gint id) "sink"); g_object_unref (tee_src); - data->link_probe_id = gst_pad_add_probe (data->tee_sink_pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_BLOCK, (GstPadProbeCallback) link_to_videomixer, KMS_COMPOSITE_MIXER_REF (data), (GDestroyNotify) kms_ref_struct_unref); - // Link DATA input kms_base_hub_link_data_sink (KMS_BASE_HUB (mixer), data->id, mixer->priv->datamixer_sink, "sink_%u", TRUE); - return data; } static gint -get_stream_id_from_padname (const gchar * name) +get_stream_id_from_padname (const gchar *name) { gint64 id; - if (name == NULL) + if (name == NULL) { return -1; + } - if (!g_str_has_prefix (name, AUDIO_SRC_PAD_PREFIX)) + if (!g_str_has_prefix (name, AUDIO_SRC_PAD_PREFIX)) { return -1; + } id = g_ascii_strtoll (name + LENGTH_AUDIO_SRC_PAD_PREFIX, NULL, 10); - if (id > G_MAXINT) + + if (id > G_MAXINT) { return -1; + } return id; } static void -pad_added_cb (GstElement * element, GstPad * pad, gpointer data) +pad_added_cb (GstElement *element, GstPad *pad, gpointer data) { gint id; KmsCompositeMixer *self = KMS_COMPOSITE_MIXER (data); - if (gst_pad_get_direction (pad) != GST_PAD_SRC) + if (gst_pad_get_direction (pad) != GST_PAD_SRC) { return; + } id = get_stream_id_from_padname (GST_OBJECT_NAME (pad)); @@ -636,14 +640,13 @@ pad_added_cb (GstElement * element, GstPad * pad, gpointer data) } static void -pad_removed_cb (GstElement * element, GstPad * pad, gpointer data) +pad_removed_cb (GstElement *element, GstPad *pad, gpointer data) { GST_DEBUG ("Removed pad %" GST_PTR_FORMAT, pad); } static gint -kms_composite_mixer_handle_port (KmsBaseHub * mixer, - GstElement * mixer_end_point) +kms_composite_mixer_handle_port (KmsBaseHub *mixer, GstElement *mixer_end_point) { KmsCompositeMixer *self = KMS_COMPOSITE_MIXER (mixer); KmsCompositeMixerData *port_data; @@ -697,7 +700,8 @@ kms_composite_mixer_handle_port (KmsBaseHub * mixer, gst_caps_new_simple ("video/x-raw", "width", G_TYPE_INT, self->priv->output_width, "height", G_TYPE_INT, self->priv->output_height, - "framerate", GST_TYPE_FRACTION, 15, 1, NULL); + "framerate", GST_TYPE_FRACTION, self->priv->output_framerate, 1, + NULL); g_object_set (G_OBJECT (capsfilter), "caps", filtercaps, NULL); gst_caps_unref (filtercaps); @@ -721,6 +725,7 @@ kms_composite_mixer_handle_port (KmsBaseHub * mixer, gst_element_sync_state_with_parent (capsfilter); gst_element_sync_state_with_parent (self->priv->videotestsrc); } + gst_element_sync_state_with_parent (self->priv->videomixer); gst_element_sync_state_with_parent (self->priv->mixer_video_agnostic); @@ -770,7 +775,7 @@ kms_composite_mixer_handle_port (KmsBaseHub * mixer, } static void -kms_composite_mixer_dispose (GObject * object) +kms_composite_mixer_dispose (GObject *object) { KmsCompositeMixer *self = KMS_COMPOSITE_MIXER (object); @@ -783,7 +788,7 @@ kms_composite_mixer_dispose (GObject * object) } static void -kms_composite_mixer_finalize (GObject * object) +kms_composite_mixer_finalize (GObject *object) { KmsCompositeMixer *self = KMS_COMPOSITE_MIXER (object); @@ -797,8 +802,55 @@ kms_composite_mixer_finalize (GObject * object) G_OBJECT_CLASS (kms_composite_mixer_parent_class)->finalize (object); } +void +kms_composite_mixer_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + KmsCompositeMixer *compositeMixer = KMS_COMPOSITE_MIXER (object); + + switch (property_id) { + case PROP_WIDTH:{ + compositeMixer->priv->output_width = g_value_get_int (value); + break; + } + case PROP_HEIGHT: + compositeMixer->priv->output_height = g_value_get_int (value); + break; + case PROP_FRAMERATE: + compositeMixer->priv->output_framerate = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +kms_composite_mixer_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + KmsCompositeMixer *compositeMixer = KMS_COMPOSITE_MIXER (object); + + switch (property_id) { + case PROP_WIDTH: + g_value_set_int (value, compositeMixer->priv->output_width); + break; + case PROP_HEIGHT:{ + g_value_set_int (value, compositeMixer->priv->output_height); + break; + } + case PROP_FRAMERATE:{ + g_value_set_int (value, compositeMixer->priv->output_framerate); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + static void -kms_composite_mixer_class_init (KmsCompositeMixerClass * klass) +kms_composite_mixer_class_init (KmsCompositeMixerClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); KmsBaseHubClass *base_hub_class = KMS_BASE_HUB_CLASS (klass); @@ -811,6 +863,21 @@ kms_composite_mixer_class_init (KmsCompositeMixerClass * klass) gobject_class->dispose = GST_DEBUG_FUNCPTR (kms_composite_mixer_dispose); gobject_class->finalize = GST_DEBUG_FUNCPTR (kms_composite_mixer_finalize); + gobject_class->set_property = kms_composite_mixer_set_property; + gobject_class->get_property = kms_composite_mixer_get_property; + + g_object_class_install_property (gobject_class, PROP_WIDTH, + g_param_spec_int ("width", "width", + "Width of the screen", + 0, G_MAXINT, 0, G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY)); + g_object_class_install_property (gobject_class, PROP_HEIGHT, + g_param_spec_int ("height", "height", + "Height of the screen", + 0, G_MAXINT, 0, G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY)); + g_object_class_install_property (gobject_class, PROP_FRAMERATE, + g_param_spec_int ("framerate", "framerate", + "Framerate of the screen", + 0, G_MAXINT, 0, G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY)); base_hub_class->handle_port = GST_DEBUG_FUNCPTR (kms_composite_mixer_handle_port); base_hub_class->unhandle_port = @@ -830,7 +897,7 @@ kms_composite_mixer_class_init (KmsCompositeMixerClass * klass) } static void -kms_composite_mixer_init (KmsCompositeMixer * self) +kms_composite_mixer_init (KmsCompositeMixer *self) { self->priv = KMS_COMPOSITE_MIXER_GET_PRIVATE (self); @@ -841,13 +908,14 @@ kms_composite_mixer_init (KmsCompositeMixer * self) //TODO:Obtain the dimensions of the bigger input stream self->priv->output_height = 600; self->priv->output_width = 800; + self->priv->output_framerate = 15; self->priv->n_elems = 0; self->priv->loop = kms_loop_new (); } gboolean -kms_composite_mixer_plugin_init (GstPlugin * plugin) +kms_composite_mixer_plugin_init (GstPlugin *plugin) { return gst_element_register (plugin, PLUGIN_NAME, GST_RANK_NONE, KMS_TYPE_COMPOSITE_MIXER); diff --git a/server/module-elements/src/gst-plugins/kmscompositemixer.h b/server/module-elements/src/gst-plugins/kmscompositemixer.h index 05dff27107..e302bafbe9 100644 --- a/server/module-elements/src/gst-plugins/kmscompositemixer.h +++ b/server/module-elements/src/gst-plugins/kmscompositemixer.h @@ -57,6 +57,15 @@ typedef struct _KmsCompositeMixer KmsCompositeMixer; typedef struct _KmsCompositeMixerClass KmsCompositeMixerClass; typedef struct _KmsCompositeMixerPrivate KmsCompositeMixerPrivate; +enum +{ + PROP_ZERO, + PROP_WIDTH, + PROP_HEIGHT, + PROP_FRAMERATE, + N_PROPERTIES +}; + struct _KmsCompositeMixer { KmsBaseHub parent; diff --git a/server/module-elements/src/server/config/Composite.conf.ini b/server/module-elements/src/server/config/Composite.conf.ini new file mode 100644 index 0000000000..82a82d0bf8 --- /dev/null +++ b/server/module-elements/src/server/config/Composite.conf.ini @@ -0,0 +1,4 @@ +width=10 +height=10 +framerate=10 +; Default resolution and framerate diff --git a/server/module-elements/src/server/implementation/objects/CompositeImpl.cpp b/server/module-elements/src/server/implementation/objects/CompositeImpl.cpp index 393b42395a..ddb17f669d 100644 --- a/server/module-elements/src/server/implementation/objects/CompositeImpl.cpp +++ b/server/module-elements/src/server/implementation/objects/CompositeImpl.cpp @@ -28,28 +28,66 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); #define FACTORY_NAME "compositemixer" +#define WIDTH_PROPERTY "width" +#define HEIGHT_PROPERTY "height" +#define FRAMERATE_PROPERTY "framerate" + namespace kurento { CompositeImpl::CompositeImpl (const boost::property_tree::ptree &conf, - std::shared_ptr mediaPipeline) : HubImpl (conf, - std::dynamic_pointer_cast (mediaPipeline), FACTORY_NAME) + std::shared_ptr mediaPipeline, + int width, + int height, + int framerate) + : HubImpl (conf, + std::dynamic_pointer_cast (mediaPipeline), + FACTORY_NAME), + width (width), height (height), framerate (framerate) { + if (this->width == 0) { + kurento::MediaObjectImpl::getConfigValue (&this->width, WIDTH_PROPERTY, conf); + } + + if (this->width != 0) { + g_object_set (G_OBJECT (element), WIDTH_PROPERTY, this->width, NULL); + } + + if (this->height == 0) { + kurento::MediaObjectImpl::getConfigValue (&this->height, HEIGHT_PROPERTY, conf); + } + + if (this->height != 0) { + g_object_set (G_OBJECT (element), HEIGHT_PROPERTY, this->height, NULL); + } + + if (this->framerate == 0) { + kurento::MediaObjectImpl::getConfigValue (&this->framerate, FRAMERATE_PROPERTY, + conf); + } + + if (this->framerate != 0) { + g_object_set (G_OBJECT (element), FRAMERATE_PROPERTY, this->framerate, + NULL); + } } MediaObjectImpl * CompositeImplFactory::createObject (const boost::property_tree::ptree &conf, - std::shared_ptr mediaPipeline) const + std::shared_ptr mediaPipeline, + int width = DEFAULT_WIDTH, + int height = DEFAULT_HEIGHT, + int framerate = DEFAULT_FRAMERATE) const { - return new CompositeImpl (conf, mediaPipeline); + return new CompositeImpl (conf, mediaPipeline, width, height, framerate); } CompositeImpl::StaticConstructor CompositeImpl::staticConstructor; -CompositeImpl::StaticConstructor::StaticConstructor() +CompositeImpl::StaticConstructor::StaticConstructor () { GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0, GST_DEFAULT_NAME); } -} /* kurento */ +} // namespace kurento diff --git a/server/module-elements/src/server/implementation/objects/CompositeImpl.hpp b/server/module-elements/src/server/implementation/objects/CompositeImpl.hpp index 630c656480..c6fb78aa41 100644 --- a/server/module-elements/src/server/implementation/objects/CompositeImpl.hpp +++ b/server/module-elements/src/server/implementation/objects/CompositeImpl.hpp @@ -27,6 +27,10 @@ namespace kurento class MediaPipeline; class CompositeImpl; +const int64_t DEFAULT_WIDTH = 800; +const int64_t DEFAULT_HEIGHT = 600; +const int64_t DEFAULT_FRAMERATE = 15; + void Serialize (std::shared_ptr &object, JsonSerializer &serializer); @@ -36,7 +40,9 @@ class CompositeImpl : public HubImpl, public virtual Composite public: CompositeImpl (const boost::property_tree::ptree &conf, - std::shared_ptr mediaPipeline); + std::shared_ptr mediaPipeline, + int width = DEFAULT_WIDTH, int height = DEFAULT_HEIGHT, + int framerate = DEFAULT_FRAMERATE); virtual ~CompositeImpl () {}; @@ -51,7 +57,7 @@ class CompositeImpl : public HubImpl, public virtual Composite virtual void Serialize (JsonSerializer &serializer); private: - + int width, height, framerate; class StaticConstructor { public: diff --git a/server/module-elements/src/server/interface/elements.Composite.kmd.json b/server/module-elements/src/server/interface/elements.Composite.kmd.json index ea8446384d..7452ad89ad 100644 --- a/server/module-elements/src/server/interface/elements.Composite.kmd.json +++ b/server/module-elements/src/server/interface/elements.Composite.kmd.json @@ -12,6 +12,28 @@ "name": "mediaPipeline", "doc": "the :rom:cls:`MediaPipeline` to which the dispatcher belongs", "type": "MediaPipeline" + }, + { + "name": "width", + "doc": "screen width", + "type": "int", + "optional": true, + "defaultValue": 800 + }, + { + "name": "height", + "doc": "screen height", + "type": "int", + "optional": true, + "defaultValue": 600 + + }, + { + "name": "framerate", + "doc": "frames per second", + "type": "int", + "optional": true, + "defaultValue": 15 } ] } diff --git a/server/module-elements/tests/server/composite.cpp b/server/module-elements/tests/server/composite.cpp index 7f0bda1c64..7e86a30c90 100644 --- a/server/module-elements/tests/server/composite.cpp +++ b/server/module-elements/tests/server/composite.cpp @@ -57,7 +57,7 @@ BOOST_GLOBAL_FIXTURE (GF); GF::GF() { boost::property_tree::ptree ac, audioCodecs, vc, videoCodecs; - gst_init(nullptr, nullptr); + gst_init (nullptr, nullptr); moduleManager.loadModulesFromDirectories ("../../src/server:../../.."); @@ -80,12 +80,28 @@ createComposite () constructorParams ["mediaPipeline"] = mediaPipelineId; composite = moduleManager.getFactory ("Composite")->createObject ( - config, "", - constructorParams ); + config, "", + constructorParams ); return std::dynamic_pointer_cast (composite); } +static std::shared_ptr +createComposite (int64_t width, int64_t height, int64_t framerate) +{ + std::shared_ptr composite; + Json::Value constructorParams; + constructorParams ["mediaPipeline"] = mediaPipelineId; + constructorParams ["width"] = width; + constructorParams ["height"] = height; + constructorParams ["framerate"] = framerate; + + composite = moduleManager.getFactory ("Composite")->createObject ( + config, "", + constructorParams ); + + return std::dynamic_pointer_cast (composite); +} static void releaseComposite (std::shared_ptr &ep) { @@ -105,8 +121,8 @@ createHubPort (std::shared_ptr composite) constructorParams ["hub"] = composite->getId(); port = moduleManager.getFactory ("HubPort")->createObject ( - config, "", - constructorParams ); + config, "", + constructorParams ); return std::dynamic_pointer_cast (port); } @@ -121,7 +137,8 @@ releaseHubPort (std::shared_ptr &ep) } -static std::shared_ptr createTestSrc() { +static std::shared_ptr createTestSrc() +{ std::shared_ptr src = std::dynamic_pointer_cast (MediaSet::getMediaSet()->ref (new MediaElementImpl ( boost::property_tree::ptree(), @@ -146,10 +163,11 @@ static void dumpPipeline (std::shared_ptr pipeline, std::string fileName) { std::string pipelineDot; - std::shared_ptr details (new GstreamerDotDetails ("SHOW_ALL")); + std::shared_ptr details (new + GstreamerDotDetails ("SHOW_ALL") ); pipelineDot = pipeline->getGstreamerDot (details); - std::ofstream out(fileName); + std::ofstream out (fileName); out << pipelineDot; out.close (); @@ -159,15 +177,18 @@ dumpPipeline (std::shared_ptr pipeline, std::string fileName) void dumpPipeline (std::string pipelineId, std::string fileName) { - std::shared_ptr pipeline = std::dynamic_pointer_cast (MediaSet::getMediaSet ()->getMediaObject (pipelineId)); + std::shared_ptr pipeline = + std::dynamic_pointer_cast + (MediaSet::getMediaSet ()->getMediaObject (pipelineId) ); dumpPipeline (pipeline, fileName); // MediaSet::getMediaSet ()->release (pipelineId); } -static std::shared_ptr getMediaElement (std::shared_ptr element) +static std::shared_ptr getMediaElement ( + std::shared_ptr element) { - return std::dynamic_pointer_cast (element); + return std::dynamic_pointer_cast (element); } @@ -180,8 +201,8 @@ createPassThrough (std::string mediaPipelineId) constructorParams ["mediaPipeline"] = mediaPipelineId; pt = moduleManager.getFactory ("PassThrough")->createObject ( - config, "", - constructorParams ); + config, "", + constructorParams ); return std::dynamic_pointer_cast (pt); } @@ -199,6 +220,7 @@ releasePassTrhough (std::shared_ptr &ep) static void composite_setup () + { std::atomic media_state_changed (false); std::condition_variable cv; @@ -207,40 +229,44 @@ composite_setup () std::shared_ptr composite = createComposite (); std::shared_ptr src1 = createTestSrc(); std::shared_ptr src2 = createTestSrc(); - std::shared_ptr pt = createPassThrough(mediaPipelineId); + std::shared_ptr pt = createPassThrough (mediaPipelineId); std::shared_ptr port1 = createHubPort (composite); std::shared_ptr port2 = createHubPort (composite); bool audio_flowing = false; bool video_flowing = false; - sigc::connection conn = getMediaElement(pt)->signalMediaFlowInStateChanged.connect([&] ( - MediaFlowInStateChanged event) { - std::shared_ptr state = event.getState(); - if (state->getValue() == MediaFlowState::FLOWING) { - BOOST_CHECK (state->getValue() == MediaFlowState::FLOWING); - if (event.getMediaType ()->getValue() == MediaType::AUDIO) { - BOOST_TEST_MESSAGE ("Audio flowing"); - audio_flowing = true; - } else if (event.getMediaType ()->getValue() == MediaType::VIDEO) { - BOOST_TEST_MESSAGE ("Video flowing"); - video_flowing = true; - } - } else if (state->getValue() == MediaFlowState::NOT_FLOWING) { - if (event.getMediaType ()->getValue() == MediaType::AUDIO) { - BOOST_TEST_MESSAGE ("Audio not flowing"); - audio_flowing = false; - } else if (event.getMediaType ()->getValue() == MediaType::VIDEO) { - BOOST_TEST_MESSAGE ("Video not flowing"); - video_flowing = false; - } - } - if (audio_flowing && video_flowing) { - media_state_changed = true; - cv.notify_one(); - } - } - ); + sigc::connection conn = getMediaElement ( + pt)->signalMediaFlowInStateChanged.connect ([&] ( + MediaFlowInStateChanged event) { + std::shared_ptr state = event.getState(); + + if (state->getValue() == MediaFlowState::FLOWING) { + BOOST_CHECK (state->getValue() == MediaFlowState::FLOWING); + + if (event.getMediaType ()->getValue() == MediaType::AUDIO) { + BOOST_TEST_MESSAGE ("Audio flowing"); + audio_flowing = true; + } else if (event.getMediaType ()->getValue() == MediaType::VIDEO) { + BOOST_TEST_MESSAGE ("Video flowing"); + video_flowing = true; + } + } else if (state->getValue() == MediaFlowState::NOT_FLOWING) { + if (event.getMediaType ()->getValue() == MediaType::AUDIO) { + BOOST_TEST_MESSAGE ("Audio not flowing"); + audio_flowing = false; + } else if (event.getMediaType ()->getValue() == MediaType::VIDEO) { + BOOST_TEST_MESSAGE ("Video not flowing"); + video_flowing = false; + } + } + + if (audio_flowing && video_flowing) { + media_state_changed = true; + cv.notify_one(); + } + } + ); src1->connect (port1); src2->connect (port2); @@ -249,34 +275,114 @@ composite_setup () dumpPipeline (mediaPipelineId, "composite_start.dot"); // First stream - cv.wait_for (lck, std::chrono::seconds(10), [&] () { + cv.wait_for (lck, std::chrono::seconds (10), [&] () { return media_state_changed.load(); }); conn.disconnect (); dumpPipeline (mediaPipelineId, "composite_end.dot"); - if (!((getMediaElement(pt)->isMediaFlowingIn (std::make_shared(MediaType::AUDIO))) && ((getMediaElement(pt)->isMediaFlowingIn (std::make_shared(MediaType::VIDEO)))))) { + if (! ( (getMediaElement (pt)->isMediaFlowingIn (std::make_shared + (MediaType::AUDIO) ) ) + && ( (getMediaElement (pt)->isMediaFlowingIn (std::make_shared + (MediaType::VIDEO) ) ) ) ) ) { BOOST_ERROR ("Media is not flowing out from composite"); } - - releasePassTrhough(pt); - releaseHubPort(port1); - releaseHubPort(port2); + + releasePassTrhough (pt); + releaseHubPort (port1); + releaseHubPort (port2); releaseComposite (composite); - releaseTestSrc(src1); - releaseTestSrc(src2); + releaseTestSrc (src1); + releaseTestSrc (src2); } +static void composite_param_setup () +{ + std::atomic media_state_changed (false); + std::condition_variable cv; + std::mutex mtx; + std::unique_lock lck (mtx); + std::shared_ptr composite = createComposite (1200, 215, 60); + std::shared_ptr src1 = createTestSrc(); + std::shared_ptr src2 = createTestSrc(); + std::shared_ptr pt = createPassThrough (mediaPipelineId); + std::shared_ptr port1 = createHubPort (composite); + std::shared_ptr port2 = createHubPort (composite); + bool audio_flowing = false; + bool video_flowing = false; + + sigc::connection conn = getMediaElement ( + pt)->signalMediaFlowInStateChanged.connect ([&] ( + MediaFlowInStateChanged event) { + std::shared_ptr state = event.getState(); + + if (state->getValue() == MediaFlowState::FLOWING) { + BOOST_CHECK (state->getValue() == MediaFlowState::FLOWING); + + if (event.getMediaType ()->getValue() == MediaType::AUDIO) { + BOOST_TEST_MESSAGE ("Audio flowing"); + audio_flowing = true; + } else if (event.getMediaType ()->getValue() == MediaType::VIDEO) { + BOOST_TEST_MESSAGE ("Video flowing"); + video_flowing = true; + } + } else if (state->getValue() == MediaFlowState::NOT_FLOWING) { + if (event.getMediaType ()->getValue() == MediaType::AUDIO) { + BOOST_TEST_MESSAGE ("Audio not flowing"); + audio_flowing = false; + } else if (event.getMediaType ()->getValue() == MediaType::VIDEO) { + BOOST_TEST_MESSAGE ("Video not flowing"); + video_flowing = false; + } + } + + if (audio_flowing && video_flowing) { + media_state_changed = true; + cv.notify_one(); + } + } + ); + + src1->connect (port1); + src2->connect (port2); + port1->connect (pt); + + + dumpPipeline (mediaPipelineId, "composite_start.dot"); + // First stream + cv.wait_for (lck, std::chrono::seconds (10), [&] () { + return media_state_changed.load(); + }); + conn.disconnect (); + + dumpPipeline (mediaPipelineId, "composite_end.dot"); + + if (! ( (getMediaElement (pt)->isMediaFlowingIn (std::make_shared + (MediaType::AUDIO) ) ) + && ( (getMediaElement (pt)->isMediaFlowingIn (std::make_shared + (MediaType::VIDEO) ) ) ) ) ) { + BOOST_ERROR ("Media is not flowing out from composite"); + } + + + + releasePassTrhough (pt); + releaseHubPort (port1); + releaseHubPort (port2); + releaseComposite (composite); + releaseTestSrc (src1); + releaseTestSrc (src2); +} test_suite * -init_unit_test_suite ( int , char *[] ) +init_unit_test_suite ( int, char *[] ) { test_suite *test = BOOST_TEST_SUITE ( "RecorderEndpoint" ); test->add (BOOST_TEST_CASE ( &composite_setup), 0, /* timeout */ 100); - + test->add (BOOST_TEST_CASE ( &composite_param_setup), 0, /* timeout */ 100); return test; }