diff options
author | George Kiagiadakis <george.kiagiadakis@collabora.co.uk> | 2011-01-17 16:34:44 +0200 |
---|---|---|
committer | George Kiagiadakis <george.kiagiadakis@collabora.co.uk> | 2011-01-17 16:34:44 +0200 |
commit | d6f80df4e811902be4b186a2ae34bf9481938128 (patch) | |
tree | c296b7f7a50b28f6b916db18dfa55a4d29ec52ef | |
parent | 8de2c5dac62775b8da5006ec483d404ae435ebd2 (diff) |
Implement QGst::Utils::ApplicationSource.
-rw-r--r-- | src/QGst/CMakeLists.txt | 8 | ||||
-rw-r--r-- | src/QGst/QtGStreamerUtils-0.10.pc.in | 1 | ||||
-rw-r--r-- | src/QGst/Utils/ApplicationSource | 1 | ||||
-rw-r--r-- | src/QGst/Utils/applicationsource.cpp | 264 | ||||
-rw-r--r-- | src/QGst/Utils/applicationsource.h | 167 | ||||
-rw-r--r-- | src/QGst/enums.h | 21 |
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 |