10#include <gst/gstvalue.h>
11#include <gst/base/gstbasesrc.h>
13#include <QtCore/qdatetime.h>
14#include <QtCore/qdebug.h>
15#include <QtCore/qsize.h>
16#include <QtCore/qtimer.h>
17#include <QtCore/qdebug.h>
18#include <QtCore/qdir.h>
19#include <QtCore/qstandardpaths.h>
20#include <QtCore/qurl.h>
22#define MAX_BUFFERS_IN_QUEUE 4
41 QGstElement audioconvert(
"audioconvert",
"audioconvert");
62 m_outputBin =
QGstBin(
"audio-output-bin");
63 m_outputBin.
add(m_audioConvert);
68 g_object_set(m_playbin.
object(),
"audio-sink", m_outputBin.
element(), NULL);
69 g_signal_connect(m_playbin.
object(),
"deep-notify::source",
70 (GCallback)&QGstreamerAudioDecoder::configureAppSrcElement, (gpointer)
this);
74 m_playbin.
set(
"volume", volume);
81#if QT_CONFIG(gstreamer_app)
86#if QT_CONFIG(gstreamer_app)
87void QGstreamerAudioDecoder::configureAppSrcElement(GObject*
object, GObject *orig, GParamSpec *pspec,
QGstreamerAudioDecoder *self)
97 g_object_get(orig,
"source", &appsrc, NULL);
99 auto *qAppSrc = self->appsrc();
100 qAppSrc->setExternalAppSrc(appsrc);
101 qAppSrc->setup(self->mDevice);
103 g_object_unref(G_OBJECT(appsrc));
109 GstMessage* gm =
message.rawMessage();
111 if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_DURATION) {
113 }
else if (GST_MESSAGE_SRC(gm) == m_playbin.
object()) {
114 switch (GST_MESSAGE_TYPE(gm)) {
115 case GST_MESSAGE_STATE_CHANGED:
125 states <<
"GST_STATE_VOID_PENDING" <<
"GST_STATE_NULL" <<
"GST_STATE_READY" <<
"GST_STATE_PAUSED" <<
"GST_STATE_PLAYING";
127 qDebug() <<
QString(
"state changed: old: %1 new: %2 pending: %3") \
135 case GST_STATE_VOID_PENDING:
137 case GST_STATE_READY:
139 case GST_STATE_PLAYING:
142 case GST_STATE_PAUSED:
148 m_durationQueries = 5;
157 case GST_MESSAGE_EOS:
162 case GST_MESSAGE_ERROR: {
165 gst_message_parse_error(gm, &err, &
debug);
166 if (err->domain == GST_STREAM_ERROR && err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND)
175 case GST_MESSAGE_WARNING:
179 gst_message_parse_warning (gm, &err, &
debug);
186 case GST_MESSAGE_INFO:
190 gst_message_parse_info (gm, &err, &
debug);
200 }
else if (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ERROR) {
203 gst_message_parse_error(gm, &err, &
debug);
205 if (err->domain == GST_STREAM_ERROR) {
207 case GST_STREAM_ERROR_DECRYPT:
208 case GST_STREAM_ERROR_DECRYPT_NOKEY:
211 case GST_STREAM_ERROR_FORMAT:
212 case GST_STREAM_ERROR_DEMUX:
213 case GST_STREAM_ERROR_DECODE:
214 case GST_STREAM_ERROR_WRONG_TYPE:
215 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
216 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
222 }
else if (err->domain == GST_CORE_ERROR) {
224 case GST_CORE_ERROR_MISSING_PLUGIN:
253 bool isSignalRequired = (mSource !=
fileName);
255 if (isSignalRequired)
268 bool isSignalRequired = (mDevice !=
device);
270 if (isSignalRequired)
280 }
else if (mDevice) {
290 m_appSrc = maybeAppSrc.value();
297 m_playbin.
set(
"uri",
"appsrc://");
305 setAudioFlags(
false);
307 gst_app_sink_set_caps(m_appSink, caps.get());
311 gst_app_sink_set_caps(m_appSink,
nullptr);
315 if (m_playbin.
setState(GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
316 qWarning() <<
"GStreamer; Unable to start decoding process";
328 if (m_buffersAvailable != 0) {
329 m_buffersAvailable = 0;
333 if (m_position != -1) {
338 if (m_duration != -1) {
363 int buffersAvailable;
366 buffersAvailable = m_buffersAvailable;
370 m_buffersAvailable--;
374 if (buffersAvailable) {
375 if (buffersAvailable == 1)
378 const char* bufferData =
nullptr;
381 GstSample *sample = gst_app_sink_pull_sample(m_appSink);
382 GstBuffer *
buffer = gst_sample_get_buffer(sample);
384 gst_buffer_map(
buffer, &mapInfo, GST_MAP_READ);
385 bufferData = (
const char*)mapInfo.data;
386 bufferSize = mapInfo.size;
400 gst_buffer_unmap(
buffer, &mapInfo);
401 gst_sample_unref(sample);
410 return m_buffersAvailable > 0;
434 int buffersAvailable;
437 buffersAvailable = decoder->m_buffersAvailable;
438 decoder->m_buffersAvailable++;
442 if (!buffersAvailable)
448void QGstreamerAudioDecoder::setAudioFlags(
bool wantNativeAudio)
460void QGstreamerAudioDecoder::addAppSink()
465 m_appSink = (GstAppSink*)gst_element_factory_make(
"appsink",
nullptr);
470 gst_app_sink_set_callbacks(m_appSink, &
callbacks,
this,
nullptr);
472 gst_base_sink_set_sync(GST_BASE_SINK(m_appSink), FALSE);
474 gst_bin_add(m_outputBin.
bin(), GST_ELEMENT(m_appSink));
475 gst_element_link(m_audioConvert.
element(), GST_ELEMENT(m_appSink));
478void QGstreamerAudioDecoder::removeAppSink()
483 gst_element_unlink(m_audioConvert.
element(), GST_ELEMENT(m_appSink));
484 gst_bin_remove(m_outputBin.
bin(), GST_ELEMENT(m_appSink));
489void QGstreamerAudioDecoder::updateDuration()
499 m_durationQueries = 0;
501 if (m_durationQueries > 0) {
503 int delay = 25 << (5 - m_durationQueries);
509qint64 QGstreamerAudioDecoder::getPositionFromBuffer(GstBuffer*
buffer)
521#include "moc_qgstreameraudiodecoder_p.cpp"
IOBluetoothDevice * device
The QAudioDecoder class implements decoding audio.
Error
Defines a media player error condition.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
static QMaybe< QGstAppSrc * > create(QObject *parent=nullptr)
void addGhostPad(const QGstElement &child, const char *name)
void add(const QGstElement &element)
GstElement * element() const
int getInt(const char *property) const
void set(const char *property, const char *str)
GstObject * object() const
GstStateChangeReturn setState(GstState state)
void installMessageFilter(QGstreamerSyncMessageFilter *filter)
void dumpGraph(const char *fileName)
void setSourceDevice(QIODevice *device) override
QAudioFormat audioFormat() const override
static GstFlowReturn new_sample(GstAppSink *sink, gpointer user_data)
virtual ~QGstreamerAudioDecoder()
QIODevice * sourceDevice() const override
void setSource(const QUrl &fileName) override
qint64 duration() const override
QUrl source() const override
void setAudioFormat(const QAudioFormat &format) override
static QMaybe< QPlatformAudioDecoder * > create(QAudioDecoder *parent)
bool bufferAvailable() const override
QAudioBuffer read() override
qint64 position() const override
bool processBusMessage(const QGstreamerMessage &message) override
\inmodule QtCore \reentrant
bool isOpen() const
Returns true if the device is open; otherwise returns false.
bool isReadable() const
Returns true if data can be read from the device; otherwise returns false.
QObject * parent() const
Returns a pointer to the parent object.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
bool singleShot
whether the timer is a single-shot timer
QByteArray toEncoded(FormattingOptions options=FullyEncoded) const
Returns the encoded representation of the URL if it's valid; otherwise an empty QByteArray is returne...
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
void clear()
Resets the content of the QUrl.
void newState(QList< State > &states, const char *token, const char *lexem, bool pre)
Q_MULTIMEDIA_EXPORT QGstCaps capsForAudioFormat(const QAudioFormat &format)
Q_MULTIMEDIA_EXPORT QAudioFormat audioFormatForSample(GstSample *sample)
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void * user_data
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage return DBusPendingCall * pending
QString errorMessageCannotFindElement(std::string_view element)
@ GST_PLAY_FLAG_NATIVE_AUDIO
@ GST_PLAY_FLAG_BUFFERING
@ GST_PLAY_FLAG_NATIVE_VIDEO
@ GST_PLAY_FLAG_SOFT_VOLUME
#define MAX_BUFFERS_IN_QUEUE
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum format
PromiseCallbacks callbacks
QLatin1StringView QLatin1String
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent