[gstreamermm] Gst::BaseSrc: fix refs of {get_caps, fixate}() return values
- From: Marcin Kolny <mkolny src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gstreamermm] Gst::BaseSrc: fix refs of {get_caps, fixate}() return values
- Date: Mon, 29 Jun 2015 09:27:17 +0000 (UTC)
commit 65dc5d8c76dc2d8e91d1e665eec5b0ab39e81de3
Author: Michał Wróbel <michal wrobel flytronic pl>
Date: Sat Jun 27 23:52:24 2015 +0200
Gst::BaseSrc: fix refs of {get_caps,fixate}() return values
This is https://bugzilla.gnome.org/show_bug.cgi?id=751601 in progress.
* gstreamer/src/basesrc.ccg: initialize pointer.
* gstreamer/src/basesrc.hg: fix virtual methods: get_caps and fixate.
* tests/Makefile.am: add appsrc test to a build.
* tests/plugins/derivedfromappsrc.h:
* tests/plugins/test-plugin-appsrc.cc:
* tests/plugins/test-plugin-derivedfromappsrc.cc: add a few appsrc
tests.
The patch includes unit tests which should fail if the fixes done in
gstreamer/src/basesrc.{ccg,hg} are not applied.
gstreamer/src/basesrc.ccg | 2 +-
gstreamer/src/basesrc.hg | 7 +-
tests/Makefile.am | 2 +
tests/plugins/derivedfromappsrc.h | 30 ++++++
tests/plugins/test-plugin-appsrc.cc | 80 ++++++++++++----
tests/plugins/test-plugin-derivedfromappsrc.cc | 119 ++++++++++++++++++++++++
6 files changed, 215 insertions(+), 25 deletions(-)
---
diff --git a/gstreamer/src/basesrc.ccg b/gstreamer/src/basesrc.ccg
index 9d81a9f..37dfa00 100644
--- a/gstreamer/src/basesrc.ccg
+++ b/gstreamer/src/basesrc.ccg
@@ -192,7 +192,7 @@ FlowReturn Gst::BaseSrc::create_vfunc(guint64 offset, guint size, Glib::RefPtr<G
if(base && base->create)
{
- GstBuffer* gst_buffer;
+ GstBuffer* gst_buffer = NULL;
Gst::FlowReturn const result =
static_cast<FlowReturn>((*base->create)(gobj(),offset, size,&gst_buffer));
buffer = Glib::wrap(gst_buffer, false); // Don't take copy because callback returns a newly created copy.
diff --git a/gstreamer/src/basesrc.hg b/gstreamer/src/basesrc.hg
index 8ad7cf4..6ab8741 100644
--- a/gstreamer/src/basesrc.hg
+++ b/gstreamer/src/basesrc.hg
@@ -179,11 +179,12 @@ public:
_WRAP_PROPERTY("typefind", bool)
#m4 _CONVERSION(`Glib::RefPtr<Gst::Caps>', `GstCaps*', `Glib::unwrap($3)')
+#m4 _CONVERSION(`GstCaps*', `const Glib::RefPtr<Gst::Caps>&', `Glib::wrap($3, true)')
+
/** Called to get the caps to report.
*/
- _WRAP_VFUNC(Glib::RefPtr<Gst::Caps> get_caps(Glib::RefPtr<Gst::Caps> caps) const, "get_caps")
+ _WRAP_VFUNC(Glib::RefPtr<Gst::Caps> get_caps(const Glib::RefPtr<Gst::Caps>& caps) const, "get_caps",
refreturn_ctype)
-#m4 _CONVERSION(`GstCaps*', `const Glib::RefPtr<Gst::Caps>&', `Glib::wrap($3, true)')
/** Notify subclass of changed output caps.
*/
_WRAP_VFUNC(bool set_caps(const Glib::RefPtr<Gst::Caps>& caps), "set_caps")
@@ -242,7 +243,7 @@ public:
/** Called during negotiation if caps need fixating. Implement instead of
* setting a fixate function on the source pad.
*/
- _WRAP_VFUNC(Glib::RefPtr<Gst::Caps> fixate(const Glib::RefPtr<Gst::Caps>& caps), "fixate")
+ _WRAP_VFUNC(Glib::RefPtr<Gst::Caps> fixate(const Glib::RefPtr<Gst::Caps>& caps), "fixate", refreturn_ctype)
/** Clear the previous unlock request. Subclasses should clear any state they
* set during unlock_vfunc(), such as clearing command queues.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index aff11d3..52f5d1e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -43,6 +43,7 @@ check_PROGRAMS = \
\
test-plugin-appsink \
test-plugin-appsrc \
+ test-plugin-derivedfromappsrc \
test-plugin-derivedfrombasetransform \
test-plugin-pushsrc \
test-plugin-register \
@@ -80,6 +81,7 @@ test_urihandler_SOURCES = test-urihandler.cc
test_plugin_appsink_SOURCES = plugins/test-plugin-appsink.cc
$(TEST_MAIN_SOURCE)
test_plugin_appsrc_SOURCES = plugins/test-plugin-appsrc.cc
$(TEST_MAIN_SOURCE)
+test_plugin_derivedfromappsrc_SOURCES = plugins/test-plugin-derivedfromappsrc.cc
$(TEST_MAIN_SOURCE)
test_plugin_derivedfrombasetransform_SOURCES = plugins/test-plugin-derivedfrombasetransform.cc
$(TEST_MAIN_SOURCE)
test_plugin_pushsrc_SOURCES = plugins/test-plugin-pushsrc.cc
$(TEST_MAIN_SOURCE)
test_plugin_register_SOURCES = plugins/test-plugin-register.cc
$(TEST_MAIN_SOURCE)
diff --git a/tests/plugins/derivedfromappsrc.h b/tests/plugins/derivedfromappsrc.h
new file mode 100644
index 0000000..aca87ad
--- /dev/null
+++ b/tests/plugins/derivedfromappsrc.h
@@ -0,0 +1,30 @@
+#ifndef TESTS_PLUGINS_DERIVEDFROMAPPSRC_H_
+#define TESTS_PLUGINS_DERIVEDFROMAPPSRC_H_
+
+#include <gst/app/gstappsrc.h>
+#include <gstreamermm.h>
+#include <gstreamermm/private/appsrc_p.h>
+#include <assert.h>
+
+class DerivedFromAppSrc : public Gst::AppSrc
+{
+public:
+ static void base_init(Gst::ElementClass<DerivedFromAppSrc> *klass)
+ {
+ klass->set_metadata("derivedfromappsrc_longname",
+ "derivedfromappsrc_classification", "derivedfromappsrc_detail_description",
"derivedfromappsrc_detail_author");
+ }
+
+ explicit DerivedFromAppSrc(GstAppSrc *gobj)
+ : Glib::ObjectBase(typeid (DerivedFromAppSrc)), // type must be registered before use
+ Gst::AppSrc(gobj)
+ {
+ }
+
+ static bool register_element(Glib::RefPtr<Gst::Plugin> plugin)
+ {
+ return Gst::ElementFactory::register_element(plugin, "derivedfromappsrc", 10,
Gst::register_mm_type<DerivedFromAppSrc>("derivedfromappsrc"));
+ }
+};
+
+#endif /* TESTS_PLUGINS_DERIVEDFROMAPPSRC_H_ */
diff --git a/tests/plugins/test-plugin-appsrc.cc b/tests/plugins/test-plugin-appsrc.cc
index 324c80b..b12e3e7 100644
--- a/tests/plugins/test-plugin-appsrc.cc
+++ b/tests/plugins/test-plugin-appsrc.cc
@@ -15,21 +15,22 @@ using Glib::RefPtr;
class AppSrcPluginTest : public ::testing::Test
{
protected:
- RefPtr<Element> source_element;
+ RefPtr<Element> source;
+ RefPtr<Element> sink;
RefPtr<Pipeline> pipeline;
void CreatePipelineWithElements()
{
pipeline = Gst::Pipeline::create();
- RefPtr<Element> sink = Gst::ElementFactory::create_element("fakesink", "sink");
- source_element = ElementFactory::create_element("appsrc", "source");
+ sink = ElementFactory::create_element("fakesink", "sink");
+ source = ElementFactory::create_element("appsrc", "source");
ASSERT_TRUE(sink);
- ASSERT_TRUE(source_element);
+ ASSERT_TRUE(source);
- ASSERT_NO_THROW(pipeline->add(source_element)->add(sink));
- ASSERT_NO_THROW(source_element->link(sink));
+ ASSERT_NO_THROW(pipeline->add(source)->add(sink));
+ ASSERT_NO_THROW(source->link(sink));
}
};
@@ -38,7 +39,7 @@ TEST_F(AppSrcPluginTest, CorrectCreatedAppSrcElement)
RefPtr<AppSrc> source = AppSrc::create("source");
ASSERT_TRUE(source);
- source_element = ElementFactory::create_element("appsrc", "source");
+ RefPtr<Element> source_element = ElementFactory::create_element("appsrc", "source");
ASSERT_TRUE(source_element);
source = source.cast_dynamic(source_element);
@@ -50,33 +51,70 @@ TEST_F(AppSrcPluginTest, CreatePipelineWithAppSrcElement)
CreatePipelineWithElements();
}
-TEST_F(AppSrcPluginTest, SimpleDataFlowInPipelineWitAppSrcElement)
+TEST_F(AppSrcPluginTest, SrcPadQueryCapsShouldReturnProperCapsObjects)
{
CreatePipelineWithElements();
- pipeline->set_state(Gst::STATE_PLAYING);
+ RefPtr<BaseSrc> basesrc;
+ basesrc = basesrc.cast_dynamic(source);
+ ASSERT_TRUE(basesrc);
+
+ RefPtr<Pad> src_pad = basesrc->get_src_pad();
+ ASSERT_TRUE(src_pad);
+ ASSERT_TRUE(GST_IS_PAD(src_pad->gobj()));
+ RefPtr<Caps> caps = src_pad->query_caps(Caps::create_any());
+ ASSERT_TRUE(caps);
+ ASSERT_TRUE(caps->gobj());
+ ASSERT_TRUE(GST_IS_CAPS(caps->gobj()));
+ RefPtr<Caps> template_caps = Glib::wrap(gst_pad_get_pad_template_caps(src_pad->gobj()), false);
+
+ src_pad.reset();
+ basesrc.reset();
+ sink.reset();
+ pipeline.reset();
+
+ // query_caps may return just another ref to template_caps
+ if (caps == template_caps)
+ {
+ // ...but template_caps might be just another ref to static caps with some higher unknown refcount
+ //EXPECT_EQ(2, caps->get_refcount());
+ }
+ else
+ {
+ EXPECT_EQ(1, caps->get_refcount());
+ }
+}
+
+TEST_F(AppSrcPluginTest, SimpleDataFlowInPipelineWithAppSrcElement)
+{
+ CreatePipelineWithElements();
+
+ EXPECT_EQ(STATE_CHANGE_ASYNC, pipeline->set_state(STATE_PLAYING));
std::string data = "hello world";
RefPtr<Buffer> buf = Buffer::create(data.length() + 1);
- RefPtr<MapInfo> mapinfo(new Gst::MapInfo());
- buf->map(mapinfo, MAP_WRITE);
+ ASSERT_TRUE(buf);
+ RefPtr<MapInfo> mapinfo(new MapInfo());
+ ASSERT_TRUE(buf->map(mapinfo, MAP_WRITE));
strcpy((char *)mapinfo->get_data(), data.c_str());
RefPtr<AppSrc> appsrc;
- appsrc = appsrc.cast_dynamic(source_element);
- appsrc->push_buffer(buf);
+ appsrc = appsrc.cast_dynamic(source);
+ ASSERT_TRUE(appsrc);
+
+ EXPECT_EQ(FLOW_OK, appsrc->push_buffer(buf));
{
- State state;
- StateChangeReturn ret=pipeline->get_state(state, state, 1*SECOND);
- ASSERT_EQ(ret, STATE_CHANGE_SUCCESS);
+ State state, pending;
+ StateChangeReturn ret = pipeline->get_state(state, pending, 1*SECOND);
+ EXPECT_EQ(STATE_CHANGE_SUCCESS, ret);
+ EXPECT_EQ(STATE_PLAYING, state);
}
- appsrc->end_of_stream();
+ EXPECT_EQ(FLOW_OK, appsrc->end_of_stream());
- RefPtr<Gst::Message> msg = pipeline->get_bus()->poll((Gst::MessageType)(Gst::MESSAGE_EOS |
Gst::MESSAGE_ERROR) , 1*Gst::SECOND);
+ RefPtr<Message> msg = pipeline->get_bus()->poll((MessageType)(MESSAGE_EOS | MESSAGE_ERROR) , 1*SECOND);
ASSERT_TRUE(msg);
- ASSERT_EQ(msg->get_message_type(), Gst::MESSAGE_EOS);
- pipeline->set_state(Gst::STATE_NULL);
+ EXPECT_EQ(MESSAGE_EOS, msg->get_message_type());
+ EXPECT_EQ(STATE_CHANGE_SUCCESS, pipeline->set_state(STATE_NULL));
}
-
diff --git a/tests/plugins/test-plugin-derivedfromappsrc.cc b/tests/plugins/test-plugin-derivedfromappsrc.cc
new file mode 100644
index 0000000..8b7ab4b
--- /dev/null
+++ b/tests/plugins/test-plugin-derivedfromappsrc.cc
@@ -0,0 +1,119 @@
+#include <gtest/gtest.h>
+#include <gstreamermm.h>
+#include <gstreamermm/appsrc.h>
+
+#include "derivedfromappsrc.h"
+
+using namespace Gst;
+using Glib::RefPtr;
+
+class DerivedFromAppSrcPluginTest : public ::testing::Test
+{
+protected:
+ RefPtr<Element> source;
+ RefPtr<Element> sink;
+ RefPtr<Pipeline> pipeline;
+
+ void CreatePipelineWithElements()
+ {
+ pipeline = Pipeline::create();
+
+ sink = ElementFactory::create_element("fakesink", "sink");
+ source = ElementFactory::create_element("derivedfromappsrc", "source");
+
+ ASSERT_TRUE(sink);
+ ASSERT_TRUE(source);
+
+ ASSERT_NO_THROW(pipeline->add(source)->add(sink));
+ ASSERT_NO_THROW(source->link(sink));
+ }
+
+ virtual void SetUp()
+ {
+ Plugin::register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR, "derivedfromappsrc",
+ "derivedfromappsrc is an example of C++ element derived from Gst::AppSrc",
+ sigc::ptr_fun(&DerivedFromAppSrc::register_element), "0.123",
+ "LGPL", "source?", "package?", "http://example.com");
+ }
+};
+
+TEST_F(DerivedFromAppSrcPluginTest, CreateRegisteredElement)
+{
+ RefPtr<Element> source_element = ElementFactory::create_element("derivedfromappsrc", "source");
+
+ ASSERT_TRUE(source_element);
+}
+
+TEST_F(DerivedFromAppSrcPluginTest, CreatePipelineWithRegisteredElement)
+{
+ CreatePipelineWithElements();
+}
+
+TEST_F(DerivedFromAppSrcPluginTest, SrcPadQueryCapsShouldReturnProperCapsObjects)
+{
+ CreatePipelineWithElements();
+
+ RefPtr<BaseSrc> basesrc;
+ basesrc = basesrc.cast_dynamic(source);
+ ASSERT_TRUE(basesrc);
+
+ RefPtr<Pad> src_pad = basesrc->get_src_pad();
+ ASSERT_TRUE(src_pad);
+ ASSERT_TRUE(GST_IS_PAD(src_pad->gobj()));
+ RefPtr<Caps> caps = src_pad->query_caps(Caps::create_any());
+ ASSERT_TRUE(caps);
+ ASSERT_TRUE(caps->gobj());
+ ASSERT_TRUE(GST_IS_CAPS(caps->gobj()));
+ RefPtr<Caps> template_caps = Glib::wrap(gst_pad_get_pad_template_caps(src_pad->gobj()), false);
+
+ src_pad.reset();
+ basesrc.reset();
+ sink.reset();
+ pipeline.reset();
+
+ // query_caps may return just another ref to template_caps
+ if (caps == template_caps)
+ {
+ // ...but template_caps might be just another ref to static caps with some higher unknown refcount
+ //EXPECT_EQ(2, caps->get_refcount());
+ }
+ else
+ {
+ EXPECT_EQ(1, caps->get_refcount());
+ }
+}
+
+TEST_F(DerivedFromAppSrcPluginTest, SimpleDataFlowInPipelineWithAppSrcElement)
+{
+ CreatePipelineWithElements();
+
+ EXPECT_EQ(STATE_CHANGE_ASYNC, pipeline->set_state(STATE_PLAYING));
+
+ std::string data = "hello world";
+ RefPtr<Buffer> buf = Buffer::create(data.length() + 1);
+ ASSERT_TRUE(buf);
+ RefPtr<MapInfo> mapinfo(new MapInfo());
+ ASSERT_TRUE(buf->map(mapinfo, MAP_WRITE));
+ strcpy((char *)mapinfo->get_data(), data.c_str());
+
+ RefPtr<AppSrc> appsrc;
+ appsrc = appsrc.cast_dynamic(source);
+ ASSERT_TRUE(appsrc);
+
+ EXPECT_EQ(FLOW_OK, appsrc->push_buffer(buf));
+
+ {
+ State state, pending;
+ StateChangeReturn ret = pipeline->get_state(state, pending, 1*SECOND);
+ EXPECT_EQ(STATE_CHANGE_SUCCESS, ret);
+ EXPECT_EQ(STATE_PLAYING, state);
+ }
+
+ EXPECT_EQ(FLOW_OK, appsrc->end_of_stream());
+
+ RefPtr<Message> msg = pipeline->get_bus()->poll((MessageType)(MESSAGE_EOS | MESSAGE_ERROR) , 1*SECOND);
+ ASSERT_TRUE(msg);
+ EXPECT_EQ(MESSAGE_EOS, msg->get_message_type());
+ EXPECT_EQ(STATE_CHANGE_SUCCESS, pipeline->set_state(STATE_NULL));
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]