11#include <gst/gstvalue.h>
12#include <gst/base/gstbasesrc.h>
14#include <QtCore/qdatetime.h>
15#include <QtCore/qdebug.h>
16#include <QtCore/qsize.h>
17#include <QtCore/qtimer.h>
18#include <QtCore/qdebug.h>
19#include <QtCore/qdir.h>
20#include <QtCore/qstandardpaths.h>
21#include <QtCore/qurl.h>
22#include <QtCore/qloggingcategory.h>
58 m_playbin(
std::move(playbin)),
59 m_audioConvert(
std::move(audioconvert))
68 m_outputBin.
add(m_audioConvert);
73 g_object_set(m_playbin.
object(),
"audio-sink", m_outputBin.
element(), NULL);
75 m_deepNotifySourceConnection = m_playbin.
connect(
76 "deep-notify::source", (GCallback)&configureAppSrcElement, (gpointer)
this);
80 m_playbin.
set(
"volume", volume);
89#if QT_CONFIG(gstreamer_app)
94#if QT_CONFIG(gstreamer_app)
95void QGstreamerAudioDecoder::configureAppSrcElement([[maybe_unused]] GObject *
object, GObject *orig,
96 [[maybe_unused]] GParamSpec *pspec,
104 g_object_get(orig,
"source", &appsrc, NULL);
106 auto *qAppSrc = self->m_appSrc;
107 qAppSrc->setExternalAppSrc(QGstAppSrc{
108 qGstSafeCast<GstAppSrc>(appsrc.get()),
109 QGstAppSrc::NeedsRef,
111 qAppSrc->setup(
self->mDevice);
117 qCDebug(qLcGstreamerAudioDecoder) <<
"received bus message:" <<
message;
119 GstMessage *gm =
message.message();
122 case GST_MESSAGE_DURATION: {
127 case GST_MESSAGE_ERROR: {
132 gst_message_parse_error(gm, &err, &
debug);
134 if (
message.source() == m_playbin) {
135 if (err.
get()->domain == GST_STREAM_ERROR
136 && err.
get()->code == GST_STREAM_ERROR_CODEC_NOT_FOUND)
138 tr(
"Cannot play stream of type: <unknown>"));
144 if (err.
get()->domain == GST_STREAM_ERROR) {
145 switch (err.
get()->code) {
146 case GST_STREAM_ERROR_DECRYPT:
147 case GST_STREAM_ERROR_DECRYPT_NOKEY:
150 case GST_STREAM_ERROR_FORMAT:
151 case GST_STREAM_ERROR_DEMUX:
152 case GST_STREAM_ERROR_DECODE:
153 case GST_STREAM_ERROR_WRONG_TYPE:
154 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
155 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
161 }
else if (err.
get()->domain == GST_CORE_ERROR) {
162 switch (err.
get()->code) {
163 case GST_CORE_ERROR_MISSING_PLUGIN:
177 if (
message.source() == m_playbin)
178 return handlePlaybinMessage(
message);
186 GstMessage *gm =
message.message();
188 switch (GST_MESSAGE_TYPE(gm)) {
189 case GST_MESSAGE_STATE_CHANGED: {
198 case GST_STATE_VOID_PENDING:
200 case GST_STATE_READY:
202 case GST_STATE_PLAYING:
205 case GST_STATE_PAUSED:
211 m_durationQueries = 5;
220 case GST_MESSAGE_EOS:
225 case GST_MESSAGE_ERROR:
226 Q_UNREACHABLE_RETURN(
false);
228 case GST_MESSAGE_WARNING:
232 case GST_MESSAGE_INFO: {
233 if (qLcGstreamerAudioDecoder().isDebugEnabled())
256 bool isSignalRequired = (mSource !=
fileName);
258 if (isSignalRequired)
271 bool isSignalRequired = (mDevice !=
device);
273 if (isSignalRequired)
283 }
else if (mDevice) {
293 m_appSrc = maybeAppSrc.value();
300 m_playbin.
set(
"uri",
"appsrc://");
308 setAudioFlags(
false);
310 m_appSink.setCaps(caps);
314 m_appSink.setCaps({});
318 if (m_playbin.
setState(GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
319 qWarning() <<
"GStreamer; Unable to start decoding process";
328 m_currentSessionId += 1;
332 if (m_buffersAvailable != 0) {
333 m_buffersAvailable = 0;
337 if (m_position != -1) {
342 if (m_duration != -1) {
367 if (m_buffersAvailable == 0)
370 m_buffersAvailable -= 1;
372 if (m_buffersAvailable == 0)
376 GstBuffer *
buffer = gst_sample_get_buffer(sample.
get());
378 gst_buffer_map(
buffer, &mapInfo, GST_MAP_READ);
379 const char *bufferData = (
const char *)mapInfo.data;
380 int bufferSize = mapInfo.size;
394 gst_buffer_unmap(
buffer, &mapInfo);
415GstFlowReturn QGstreamerAudioDecoder::newSample(GstAppSink *)
421 if (sessionId != m_currentSessionId)
424 m_buffersAvailable += 1;
432GstFlowReturn QGstreamerAudioDecoder::new_sample(GstAppSink *
sink, gpointer
user_data)
435 qCDebug(qLcGstreamerAudioDecoder) <<
"QGstreamerAudioDecoder::new_sample";
436 return decoder->newSample(
sink);
439void QGstreamerAudioDecoder::setAudioFlags(
bool wantNativeAudio)
451void QGstreamerAudioDecoder::addAppSink()
453 using namespace std::chrono_literals;
458 qCDebug(qLcGstreamerAudioDecoder) <<
"QGstreamerAudioDecoder::addAppSink";
459 m_appSink = QGstAppSink::create(
"decoderAppSink");
462 m_appSink.setCallbacks(
callbacks,
this,
nullptr);
464#if GST_CHECK_VERSION(1, 24, 0)
465 static constexpr auto maxBufferTime = 500ms;
466 m_appSink.setMaxBufferTime(maxBufferTime);
472 static constexpr bool sync =
false;
473 m_appSink.setSync(sync);
476 m_outputBin.add(m_appSink);
477 qLinkGstElements(m_audioConvert, m_appSink);
481void QGstreamerAudioDecoder::removeAppSink()
486 qCDebug(qLcGstreamerAudioDecoder) <<
"QGstreamerAudioDecoder::removeAppSink";
489 qUnlinkGstElements(m_audioConvert, m_appSink);
490 m_outputBin.stopAndRemoveElements(m_appSink);
495void QGstreamerAudioDecoder::updateDuration()
505 m_durationQueries = 0;
507 if (m_durationQueries > 0) {
509 int delay = 25 << (5 - m_durationQueries);
515qint64 QGstreamerAudioDecoder::getPositionFromBuffer(GstBuffer*
buffer)
527#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< QGstAppSource * > create(QObject *parent=nullptr)
std::enable_if_t<(std::is_base_of_v< QGstElement, Ts > &&...), void add)(const Ts &...ts)
static QGstBin create(const char *name)
void addGhostPad(const QGstElement &child, const char *name)
GstElement * element() const
static QGstElement createFromFactory(const char *factory, const char *name=nullptr)
QGstPipeline getPipeline() const
QGObjectHandlerConnection connect(const char *name, GCallback callback, gpointer userData)
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 removeMessageFilter(QGstreamerSyncMessageFilter *filter)
void modifyPipelineWhileNotRunning(Functor &&fn)
static QGstPipeline adopt(GstPipeline *)
void setSourceDevice(QIODevice *device) override
QAudioFormat audioFormat() const override
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)
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...
bool singleShot
whether the timer is a single-shot timer
Type get() const noexcept
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)
QGstCaps capsForAudioFormat(const QAudioFormat &format)
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
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
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 Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
GLuint GLsizei const GLchar * message
GLint GLsizei GLsizei GLenum format
GLsizei GLenum GLboolean sink
PromiseCallbacks callbacks
QLatin1StringView QLatin1String
Type get() const noexcept