summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Kiagiadakis <george.kiagiadakis@collabora.co.uk>2011-01-17 16:34:44 +0200
committerGeorge Kiagiadakis <george.kiagiadakis@collabora.co.uk>2011-01-17 16:34:44 +0200
commitd6f80df4e811902be4b186a2ae34bf9481938128 (patch)
treec296b7f7a50b28f6b916db18dfa55a4d29ec52ef
parent8de2c5dac62775b8da5006ec483d404ae435ebd2 (diff)
Implement QGst::Utils::ApplicationSource.
-rw-r--r--src/QGst/CMakeLists.txt8
-rw-r--r--src/QGst/QtGStreamerUtils-0.10.pc.in1
-rw-r--r--src/QGst/Utils/ApplicationSource1
-rw-r--r--src/QGst/Utils/applicationsource.cpp264
-rw-r--r--src/QGst/Utils/applicationsource.h167
-rw-r--r--src/QGst/enums.h21
6 files changed, 460 insertions, 2 deletions
diff --git a/src/QGst/CMakeLists.txt b/src/QGst/CMakeLists.txt
index 3ad7158..05cc32d 100644
--- a/src/QGst/CMakeLists.txt
+++ b/src/QGst/CMakeLists.txt
@@ -39,6 +39,7 @@ set(QtGStreamerUi_SRCS
set(QtGStreamerUtils_SRCS
Utils/applicationsink.cpp
+ Utils/applicationsource.cpp
)
set(QtGStreamer_INSTALLED_HEADERS
@@ -82,7 +83,8 @@ set(QtGStreamer_INSTALLED_HEADERS
Ui/global.h
Ui/videowidget.h Ui/VideoWidget
- Utils/applicationsink.h Utils/ApplicationSink
+ Utils/applicationsink.h Utils/ApplicationSink
+ Utils/applicationsource.h Utils/ApplicationSource
)
set(QtGStreamer_CODEGEN_HEADERS
@@ -124,6 +126,7 @@ set(QtGStreamer_CODEGEN_INCLUDES
-Igst/interfaces/colorbalance.h
-Igst/interfaces/videoorientation.h
-Igst/interfaces/propertyprobe.h
+ -Igst/app/gstappsrc.h
-IQGlib/Quark
)
@@ -161,7 +164,8 @@ automoc4_add_library(QtGStreamerUtils ${SHARED_OR_STATIC} ${QtGStreamerUtils_SRC
set_target_properties(QtGStreamerUtils PROPERTIES OUTPUT_NAME QtGStreamerUtils-${QTGSTREAMER_API_VERSION}
SOVERSION ${QTGSTREAMER_UTILS_SOVERSION}
VERSION ${QTGSTREAMER_VERSION})
-target_link_libraries(QtGStreamerUtils ${QTGSTREAMER_LIBRARY} ${GSTREAMER_APP_LIBRARY})
+target_link_libraries(QtGStreamerUtils ${QTGSTREAMER_LIBRARY} ${GSTREAMER_LIBRARY} ${GSTREAMER_APP_LIBRARY})
+target_link_libraries(QtGStreamerUtils LINK_INTERFACE_LIBRARIES ${QTGSTREAMER_LIBRARY})
# Install
install(TARGETS QtGStreamer DESTINATION ${LIB_INSTALL_DIR} EXPORT ${EXPORT_TARGET_SET})
diff --git a/src/QGst/QtGStreamerUtils-0.10.pc.in b/src/QGst/QtGStreamerUtils-0.10.pc.in
index 473de67..2254a38 100644
--- a/src/QGst/QtGStreamerUtils-0.10.pc.in
+++ b/src/QGst/QtGStreamerUtils-0.10.pc.in
@@ -6,6 +6,7 @@ includedir=@INCLUDES_INSTALL_DIR@
Name: QtGStreamerUtils-0.10
Description: QtGStreamer's high level utility classes
Requires: QtGStreamer-0.10
+Requires.private: gstreamer-0.10 gstreamer-app-0.10
Version: @QTGSTREAMER_VERSION@
Cflags: -I${includedir}
Libs: -L${libdir} -lQtGStreamerUtils-0.10
diff --git a/src/QGst/Utils/ApplicationSource b/src/QGst/Utils/ApplicationSource
new file mode 100644
index 0000000..cd1b994
--- /dev/null
+++ b/src/QGst/Utils/ApplicationSource
@@ -0,0 +1 @@
+#include "applicationsource.h"
diff --git a/src/QGst/Utils/applicationsource.cpp b/src/QGst/Utils/applicationsource.cpp
new file mode 100644
index 0000000..51fead2
--- /dev/null
+++ b/src/QGst/Utils/applicationsource.cpp
@@ -0,0 +1,264 @@
+/*
+ Copyright (C) 2011 Collabora Ltd. <info@collabora.co.uk>
+ @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "applicationsource.h"
+#include "../elementfactory.h"
+#include <gst/app/gstappsrc.h>
+
+namespace QGst {
+namespace Utils {
+
+#ifndef DOXYGEN_RUN
+
+struct QTGSTREAMERUTILS_NO_EXPORT ApplicationSource::Priv
+{
+public:
+ ElementPtr m_appsrc;
+
+ void lazyConstruct(ApplicationSource *self);
+ void setCallbacks(ApplicationSource *self);
+
+ inline GstAppSrc *appSrc()
+ {
+ return reinterpret_cast<GstAppSrc*>(static_cast<GstElement*>(m_appsrc));
+ }
+
+private:
+ static void need_data(GstAppSrc *src, guint length, gpointer user_data);
+ static void enough_data(GstAppSrc *src, gpointer user_data);
+ static gboolean seek_data(GstAppSrc *src, guint64 offset, gpointer user_data);
+};
+
+void ApplicationSource::Priv::lazyConstruct(ApplicationSource *self)
+{
+ if (!m_appsrc) {
+ m_appsrc = QGst::ElementFactory::make("appsrc");
+ if (!m_appsrc) {
+ qWarning() << "Failed to construct appsrc";
+ }
+ setCallbacks(self);
+ }
+}
+
+void ApplicationSource::Priv::setCallbacks(ApplicationSource *self)
+{
+ if (m_appsrc) {
+ static GstAppSrcCallbacks callbacks = { &need_data, &enough_data, &seek_data };
+ gst_app_src_set_callbacks(appSrc(), &callbacks, self, NULL);
+ }
+}
+
+void ApplicationSource::Priv::need_data(GstAppSrc *src, guint length, gpointer user_data)
+{
+ Q_UNUSED(src);
+ static_cast<ApplicationSource*>(user_data)->needData(length);
+}
+
+void ApplicationSource::Priv::enough_data(GstAppSrc *src, gpointer user_data)
+{
+ Q_UNUSED(src);
+ static_cast<ApplicationSource*>(user_data)->enoughData();
+}
+
+gboolean ApplicationSource::Priv::seek_data(GstAppSrc *src, guint64 offset, gpointer user_data)
+{
+ Q_UNUSED(src);
+ return static_cast<ApplicationSource*>(user_data)->seekData(offset) ? TRUE : FALSE;
+}
+
+#endif //DOXYGEN_RUN
+
+ApplicationSource::ApplicationSource()
+ : d(new Priv)
+{
+}
+
+ApplicationSource::~ApplicationSource()
+{
+ delete d;
+}
+
+ElementPtr ApplicationSource::element() const
+{
+ d->lazyConstruct(const_cast<ApplicationSource*>(this));
+ return d->m_appsrc;
+}
+
+void ApplicationSource::setElement(const ElementPtr & appsrc)
+{
+ Q_ASSERT(!appsrc || QGlib::Type::fromInstance(appsrc).isA(GST_TYPE_APP_SRC));
+ d->m_appsrc = appsrc;
+ d->setCallbacks(this);
+}
+
+CapsPtr ApplicationSource::caps() const
+{
+ CapsPtr c;
+ if (d->appSrc()) {
+ c = CapsPtr::wrap(gst_app_src_get_caps(d->appSrc()), false);
+ }
+ return c;
+}
+
+void ApplicationSource::setCaps(const CapsPtr & caps)
+{
+ d->lazyConstruct(this);
+ if (d->appSrc()) {
+ gst_app_src_set_caps(d->appSrc(), caps);
+ }
+}
+
+quint64 ApplicationSource::minLatency() const
+{
+ guint64 ret = -1;
+ if (d->appSrc()) {
+ gst_app_src_get_latency(d->appSrc(), &ret, NULL);
+ }
+ return ret;
+}
+
+quint64 ApplicationSource::maxLatency() const
+{
+ guint64 ret = -1;
+ if (d->appSrc()) {
+ gst_app_src_get_latency(d->appSrc(), NULL, &ret);
+ }
+ return ret;
+}
+
+void ApplicationSource::setLatency(quint64 min, quint64 max)
+{
+ d->lazyConstruct(this);
+ if (d->appSrc()) {
+ gst_app_src_set_latency(d->appSrc(), min, max);
+ }
+}
+
+qint64 ApplicationSource::size() const
+{
+ return d->appSrc() ? gst_app_src_get_size(d->appSrc()) : -1;
+}
+
+void ApplicationSource::setSize(qint64 size)
+{
+ d->lazyConstruct(this);
+ if (d->appSrc()) {
+ gst_app_src_set_size(d->appSrc(), size);
+ }
+}
+
+AppStreamType ApplicationSource::streamType() const
+{
+ return d->appSrc() ? static_cast<AppStreamType>(gst_app_src_get_stream_type(d->appSrc()))
+ : AppStreamTypeStream;
+}
+
+void ApplicationSource::setStreamType(AppStreamType type)
+{
+ d->lazyConstruct(this);
+ if (d->appSrc()) {
+ gst_app_src_set_stream_type(d->appSrc(), static_cast<GstAppStreamType>(type));
+ }
+}
+
+quint64 ApplicationSource::maxBytes() const
+{
+ return d->appSrc() ? gst_app_src_get_max_bytes(d->appSrc()) : 0;
+}
+
+void ApplicationSource::setMaxBytes(quint64 max)
+{
+ d->lazyConstruct(this);
+ if (d->appSrc()) {
+ gst_app_src_set_max_bytes(d->appSrc(), max);
+ }
+}
+
+bool ApplicationSource::blockEnabled() const
+{
+ return d->m_appsrc ? d->m_appsrc->property("block").toBool() : false;
+}
+
+void ApplicationSource::enableBlock(bool enable)
+{
+ d->lazyConstruct(this);
+ if (d->m_appsrc) {
+ d->m_appsrc->setProperty("block", enable);
+ }
+}
+
+bool ApplicationSource::isLive() const
+{
+ return d->m_appsrc ? d->m_appsrc->property("is-live").toBool() : false;
+}
+
+void ApplicationSource::setLive(bool islive)
+{
+ d->lazyConstruct(this);
+ if (d->m_appsrc) {
+ d->m_appsrc->setProperty("is-live", islive);
+ }
+}
+
+uint ApplicationSource::minPercent() const
+{
+ return d->m_appsrc ? d->m_appsrc->property("min-percent").toUInt() : 0;
+}
+
+void ApplicationSource::setMinPercent(uint min)
+{
+ d->lazyConstruct(this);
+ if (d->m_appsrc) {
+ d->m_appsrc->setProperty("min-percent", min);
+ }
+}
+
+FlowReturn ApplicationSource::pushBuffer(const BufferPtr & buffer)
+{
+ if (d->appSrc()) {
+ return static_cast<FlowReturn>(gst_app_src_push_buffer(d->appSrc(), gst_buffer_ref(buffer)));
+ } else {
+ return FlowWrongState;
+ }
+}
+
+FlowReturn ApplicationSource::endOfStream()
+{
+ if (d->appSrc()) {
+ return static_cast<FlowReturn>(gst_app_src_end_of_stream(d->appSrc()));
+ } else {
+ return FlowWrongState;
+ }
+}
+
+void ApplicationSource::needData(uint length)
+{
+ Q_UNUSED(length);
+}
+
+void ApplicationSource::enoughData()
+{
+}
+
+bool ApplicationSource::seekData(quint64 offset)
+{
+ Q_UNUSED(offset);
+ return false;
+}
+
+} //namespace Utils
+} //namespace QGst
diff --git a/src/QGst/Utils/applicationsource.h b/src/QGst/Utils/applicationsource.h
new file mode 100644
index 0000000..37594da
--- /dev/null
+++ b/src/QGst/Utils/applicationsource.h
@@ -0,0 +1,167 @@
+/*
+ Copyright (C) 2011 Collabora Ltd. <info@collabora.co.uk>
+ @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+ by the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef QGST_UTILS_APPLICATIONSOURCE_H
+#define QGST_UTILS_APPLICATIONSOURCE_H
+
+#include "global.h"
+#include "../element.h"
+#include "../buffer.h"
+
+namespace QGst {
+namespace Utils {
+
+/*! \headerfile applicationsource.h <QGst/Utils/ApplicationSource>
+ * \brief Helper class for using a GstAppSrc
+ *
+ */
+class QTGSTREAMERUTILS_EXPORT ApplicationSource
+{
+public:
+ ApplicationSource();
+ virtual ~ApplicationSource();
+
+ /*! \returns the appsrc element */
+ ElementPtr element() const;
+
+ /*! Sets the appsrc element that will be used by this class */
+ void setElement(const ElementPtr & appsrc);
+
+
+ /*! \returns the caps that the appsrc is configured to produce */
+ CapsPtr caps() const;
+
+ /*! Sets the capabilities of this source. After calling this method,
+ * this appsrc will only be able to produce buffers with these capabilities.
+ * \a caps must be fixed and the caps on the buffers must match the \a caps or left NULL.
+ */
+ void setCaps(const CapsPtr & caps);
+
+
+ /*! \returns the minimum latency of this element */
+ quint64 minLatency() const;
+
+ /*! \returns the maximum latency of this element */
+ quint64 maxLatency() const;
+
+ /*! Configure the minimum and maximum latency. If \a min is set to -1,
+ * the default latency calculations for pseudo-live sources will be used. */
+ void setLatency(quint64 min, quint64 max);
+
+
+ /*! \returns the size of the stream in bytes.
+ * A value of -1 means that the size is not known. */
+ qint64 size() const;
+
+ /*! Set the size of the stream in bytes.
+ * A value of -1 means that the size is not known. */
+ void setSize(qint64 size);
+
+
+ /*! \returns the stream type of this appsrc */
+ AppStreamType streamType() const;
+
+ /*! Set the stream type on appsrc. For seekable streams,
+ * the seekData() method must be reimplemented. */
+ void setStreamType(AppStreamType type);
+
+
+ /*! \returns the maximum amount of bytes that can be queued in appsrc */
+ quint64 maxBytes() const;
+
+ /*! Set the maximum amount of bytes that can be queued in appsrc. After
+ * the maximum amount of bytes are queued, the enoughData() method of
+ * this class will be called. */
+ void setMaxBytes(quint64 max);
+
+
+ /*! \returns true if appsrc is configured to block any calls
+ * to pushBuffer() when the maximum amount of bytes are queued. */
+ bool blockEnabled() const;
+
+ /*! Enables or disables blocking calls to pushBuffer()
+ * when the maximum amount of bytes are queued. */
+ void enableBlock(bool enable);
+
+
+ /*! \returns true if the appsrc is configured to act as a live source */
+ bool isLive() const;
+
+ /*! Sets whether appsrc will act as a live source */
+ void setLive(bool islive);
+
+
+ /*! \returns the minimum percent of maxBytes() that
+ * when reached, needData() will be called */
+ uint minPercent() const;
+
+ /*! Sets the minimum percent of maxBytes() that
+ * when reached, needData() will be called */
+ void setMinPercent(uint min);
+
+
+ /*! Adds a buffer to the queue of buffers that the appsrc element will
+ * push to its source pad. When the block property is TRUE, this function
+ * can block until free space becomes available in the queue.
+ *
+ * \returns FlowOk when the buffer was successfuly queued, FlowWrongState when
+ * appsrc is not PAUSED or PLAYING or FlowUnexpected when EOS occured.
+ */
+ FlowReturn pushBuffer(const BufferPtr & buffer);
+
+ /*! Indicates to the appsrc element that the last buffer queued
+ * in the element is the last buffer of the stream.
+ *
+ * \returns FlowOk when the EOS was successfuly queued or
+ * FlowWrongState when appsrc is not PAUSED or PLAYING.
+ */
+ FlowReturn endOfStream();
+
+protected:
+ /*! Called when the appsrc needs more data. A buffer or EOS should be pushed
+ * to appsrc from this thread or another thread. length is just a hint and when
+ * it is set to -1, any number of bytes can be pushed into appsrc. */
+ virtual void needData(uint length);
+
+ /*! Called when appsrc has enough data. It is recommended that the application
+ * stops calling pushBuffer() until the needData() method is called again to
+ * avoid excessive buffer queueing. */
+ virtual void enoughData();
+
+ /*! Called when a seek should be performed to the offset. The next pushBuffer()
+ * should produce buffers from the new offset. This method is only called for
+ * seekable stream types. */
+ virtual bool seekData(quint64 offset);
+
+private:
+ /* vtable padding */
+ virtual void reservedVirtual1() {}
+ virtual void reservedVirtual2() {}
+ virtual void reservedVirtual3() {}
+ virtual void reservedVirtual4() {}
+
+private:
+ struct Priv;
+ friend struct Priv;
+ Priv *const d;
+ Q_DISABLE_COPY(ApplicationSource)
+};
+
+} //namespace Utils
+} //namespace QGst
+
+#endif // QGST_UTILS_APPLICATIONSOURCE_H
diff --git a/src/QGst/enums.h b/src/QGst/enums.h
index 08465a3..fbb3875 100644
--- a/src/QGst/enums.h
+++ b/src/QGst/enums.h
@@ -394,4 +394,25 @@ namespace QGst {
Q_DECLARE_OPERATORS_FOR_FLAGS(QGst::TagFlags)
QGLIB_REGISTER_TYPE(QGst::TagFlags) //codegen: GType=GST_TYPE_TAG_FLAG
+namespace QGst {
+ enum AppStreamType {
+ /*! No seeking is supported in the stream, such as a live stream. */
+ AppStreamTypeStream,
+ /*! The stream is seekable but seeking might not be very
+ * fast, such as data from a webserver. */
+ AppStreamTypeSeekable,
+ /*! The stream is seekable and seeking is fast, such as in a local file. */
+ AppStreamTypeRandomAccess
+ };
+}
+//FIXME: GST_TYPE_APP_STREAM_TYPE is not exported from libgstapp,
+//so we have to reside in this method...
+namespace QGlib {
+ template <>
+ struct GetTypeImpl<QGst::AppStreamType>
+ {
+ inline operator Type() { return Type::fromName("GstAppStreamType"); }
+ };
+}
+
#endif