5#include <QtCore/qcoreapplication.h>
6#include <QtCore/qjniobject.h>
7#include <QtCore/qjnienvironment.h>
8#include <QtCore/private/qandroidextras_p.h>
25 : m_format(AMediaFormat_new())
31 AMediaCodec_delete(m_codec);
36 AMediaExtractor_delete(m_extractor);
37 m_extractor =
nullptr;
41 AMediaFormat_delete(m_format);
51 const media_status_t err = AMediaCodec_stop(m_codec);
53 qCWarning(adLogger) <<
"stop() error: " << err;
59 "org/qtproject/qt/android/multimedia/QtMultimediaUtils",
61 "(Landroid/content/Context;Ljava/lang/String;)Ljava/lang/String;",
62 QNativeInterface::QAndroidApplication::context().
object(),
63 QJniObject::fromString(
source.path()).object());
68 m_formatError =
tr(
"Cannot set source, invalid mime type for the source provided.");
73 m_extractor = AMediaExtractor_new();
88 media_status_t status = AMediaExtractor_setDataSourceFd(m_extractor,
fd, 0,
92 if (status != AMEDIA_OK) {
94 AMediaExtractor_delete(m_extractor);
95 m_extractor =
nullptr;
97 m_formatError =
tr(
"Setting source for Audio Decoder failed.");
101void Decoder::createDecoder()
104 m_format = AMediaExtractor_getTrackFormat(m_extractor, 0);
107 if (!AMediaFormat_getString(m_format, AMEDIAFORMAT_KEY_MIME, &
mime)) {
109 AMediaExtractor_delete(m_extractor);
110 m_extractor =
nullptr;
119 AMediaFormat_getInt64(m_format, AMEDIAFORMAT_KEY_DURATION, &durationUs);
123 if (!m_outputFormat.
isValid()) {
125 AMediaFormat_getInt32(m_format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sampleRate);
127 int32_t channelCount;
128 AMediaFormat_getInt32(m_format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &channelCount);
133 m_codec = AMediaCodec_createDecoderByType(
mime);
138 if (!m_formatError.
isEmpty()) {
155 media_status_t status = AMediaCodec_configure(m_codec, m_format,
nullptr ,
158 if (status != AMEDIA_OK) {
163 status = AMediaCodec_start(m_codec);
164 if (status != AMEDIA_OK) {
169 AMediaExtractor_selectTrack(m_extractor, 0);
173 while (!m_inputEOS) {
175 const ssize_t bufferIdx = AMediaCodec_dequeueInputBuffer(m_codec,
dequeueTimeout);
177 if (bufferIdx >= 0) {
178 size_t bufferSize = {};
179 uint8_t *
buffer = AMediaCodec_getInputBuffer(m_codec, bufferIdx, &bufferSize);
180 const int sample = AMediaExtractor_readSampleData(m_extractor,
buffer, bufferSize);
186 const int64_t presentationTimeUs = AMediaExtractor_getSampleTime(m_extractor);
187 AMediaCodec_queueInputBuffer(m_codec, bufferIdx, 0, sample, presentationTimeUs,
188 m_inputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
189 AMediaExtractor_advance(m_extractor);
192 AMediaCodecBufferInfo
info;
195 while (idx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED
196 || idx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
197 if (idx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED)
198 qCWarning(adLogger) <<
"dequeueOutputBuffer() status: outputFormat changed";
204 if (
info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM)
209 const uint8_t *bufferData = AMediaCodec_getOutputBuffer(m_codec, idx,
213 if (presentationTimeUs >= 0)
216 AMediaCodec_releaseOutputBuffer(m_codec, idx,
false);
218 }
else if (idx == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
219 qCWarning(adLogger) <<
"dequeueOutputBuffer() status: try again later";
223 "AMediaCodec_dequeueOutputBuffer() status: invalid buffer idx " << idx;
226 qCWarning(adLogger) <<
"dequeueInputBuffer() status: invalid buffer idx " << bufferIdx;
248 delete m_threadDecoder;
254 if (!requestPermissions())
279 if (!requestPermissions())
299 if (!m_threadDecoder) {
300 m_threadDecoder =
new QThread(
this);
302 m_threadDecoder->
start();
310 if (!
isDecoding() && m_position < 0 && m_duration < 0)
314 m_audioBuffer.
clear();
325 if (!m_audioBuffer.
isEmpty()) {
327 m_position =
buffer.second;
338 return m_audioBuffer.
size() > 0;
353 m_audioBuffer.
append(QPair<QAudioBuffer, int>(audioBuffer,
position));
358void QAndroidAudioDecoder::durationChanged(
qint64 duration)
370void QAndroidAudioDecoder::finished()
374 if (m_duration != -1)
375 emit durationChanged(m_duration);
382bool QAndroidAudioDecoder::requestPermissions()
384 const auto writeRes = QtAndroidPrivate::requestPermission(
QStringLiteral(
"android.permission.WRITE_EXTERNAL_STORAGE"));
385 if (writeRes.result() == QtAndroidPrivate::Authorized)
391void QAndroidAudioDecoder::decode()
402bool QAndroidAudioDecoder::createTempFile()
406 bool success =
file.
open(QIODevice::QIODevice::ReadWrite);
410 success &= (
file.
write(m_deviceBuffer) == m_deviceBuffer.
size());
415 m_deviceBuffer.
clear();
422void QAndroidAudioDecoder::readDevice() {
424 if (m_device->
atEnd()) {
426 if (!createTempFile()) {
427 m_deviceBuffer.
clear();
437#include "moc_qandroidaudiodecoder_p.cpp"
IOBluetoothDevice * device
void error(const QAudioDecoder::Error error, const QString &errorString)
void decodingChanged(bool decoding)
void positionChanged(const QAudioBuffer &buffer, qint64 position)
void setSource(const QUrl &source)
void durationChanged(const qint64 duration)
bool bufferAvailable() const override
void setSourceUrl(const QUrl &source)
virtual ~QAndroidAudioDecoder()
QAudioBuffer read() override
qint64 duration() const override
qint64 position() const override
void setSourceDevice(QIODevice *device) override
void setSource(const QUrl &fileName) override
QAndroidAudioDecoder(QAudioDecoder *parent)
The QAudioDecoder class implements decoding audio.
Error
Defines a media player error condition.
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
void clear()
Clears the contents of the byte array and makes it null.
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString tempPath()
Returns the absolute canonical path of the system's temporary directory.
int handle() const
Returns the file handle of the file.
void close() override
Calls QFileDevice::flush() and closes the file.
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
bool remove()
Removes the file specified by fileName().
QString fileName() const override
Returns the name set by setFileName() or to the QFile constructors.
qint64 size() const override
\reimp
\inmodule QtCore \reentrant
void readyRead()
This signal is emitted once every time new data is available for reading from the device's current re...
bool isOpen() const
Returns true if the device is open; otherwise returns false.
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
bool isReadable() const
Returns true if data can be read from the device; otherwise returns false.
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
virtual qint64 bytesAvailable() const
Returns the number of bytes that are available for reading.
QString errorString() const
Returns a human-readable description of the last device error that occurred.
virtual bool atEnd() const
Returns true if the current read and write position is at the end of the device (i....
qsizetype size() const noexcept
bool isEmpty() const noexcept
void append(parameter_type t)
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
QThread * thread() const
Returns the thread in which the object lives.
bool moveToThread(QThread *thread QT6_DECL_NEW_OVERLOAD_TAIL)
Changes the thread affinity for this object and its children and returns true on success.
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
void start(Priority=InheritPriority)
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
bool singleShot
whether the timer is a single-shot timer
void clear()
Resets the content of the QUrl.
list append(new Employee("Blackpool", "Stephen"))
Combined button and popup list for selecting options.
static QT_BEGIN_NAMESPACE const char tempFile[]
constexpr int dequeueTimeout
DBusConnection const char DBusError * error
#define Q_LOGGING_CATEGORY(name,...)
#define qCWarning(category,...)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLsizei GLsizei GLchar * source
GLsizei const GLchar *const * path
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define QStringLiteral(str)
application x qt windows mime
[2]
myObject disconnect()
[26]