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(),
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();
77 fd = QJniObject::callStaticMethod<jint>(
"org/qtproject/qt/android/QtNative",
78 "openFdForContentUrl",
79 "(Landroid/content/Context;Ljava/lang/String;Ljava/lang/String;)I",
80 QNativeInterface::QAndroidApplication::context(),
81 QJniObject::fromString(
source.path()).object(),
84 fd =
open(
source.path().toStdString().c_str(), O_RDONLY);
92 media_status_t status = AMediaExtractor_setDataSourceFd(m_extractor,
fd, 0,
96 if (status != AMEDIA_OK) {
98 AMediaExtractor_delete(m_extractor);
99 m_extractor =
nullptr;
101 m_formatError =
tr(
"Setting source for Audio Decoder failed.");
105void Decoder::createDecoder()
108 m_format = AMediaExtractor_getTrackFormat(m_extractor, 0);
111 if (!AMediaFormat_getString(m_format, AMEDIAFORMAT_KEY_MIME, &
mime)) {
113 AMediaExtractor_delete(m_extractor);
114 m_extractor =
nullptr;
123 AMediaFormat_getInt64(m_format, AMEDIAFORMAT_KEY_DURATION, &durationUs);
127 if (!m_outputFormat.
isValid()) {
129 AMediaFormat_getInt32(m_format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sampleRate);
131 int32_t channelCount;
132 AMediaFormat_getInt32(m_format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &channelCount);
137 m_codec = AMediaCodec_createDecoderByType(
mime);
142 if (!m_formatError.
isEmpty()) {
159 media_status_t status = AMediaCodec_configure(m_codec, m_format,
nullptr ,
162 if (status != AMEDIA_OK) {
167 status = AMediaCodec_start(m_codec);
168 if (status != AMEDIA_OK) {
173 AMediaExtractor_selectTrack(m_extractor, 0);
177 while (!m_inputEOS) {
179 const ssize_t bufferIdx = AMediaCodec_dequeueInputBuffer(m_codec,
dequeueTimeout);
181 if (bufferIdx >= 0) {
182 size_t bufferSize = {};
183 uint8_t *
buffer = AMediaCodec_getInputBuffer(m_codec, bufferIdx, &bufferSize);
184 const int sample = AMediaExtractor_readSampleData(m_extractor,
buffer, bufferSize);
190 const int64_t presentationTimeUs = AMediaExtractor_getSampleTime(m_extractor);
191 AMediaCodec_queueInputBuffer(m_codec, bufferIdx, 0, sample, presentationTimeUs,
192 m_inputEOS ? AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM : 0);
193 AMediaExtractor_advance(m_extractor);
196 AMediaCodecBufferInfo
info;
199 while (idx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED
200 || idx == AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED) {
201 if (idx == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED)
202 qCWarning(adLogger) <<
"dequeueOutputBuffer() status: outputFormat changed";
208 if (
info.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM)
213 const uint8_t *bufferData = AMediaCodec_getOutputBuffer(m_codec, idx,
217 if (presentationTimeUs >= 0)
220 AMediaCodec_releaseOutputBuffer(m_codec, idx,
false);
222 }
else if (idx == AMEDIACODEC_INFO_TRY_AGAIN_LATER) {
223 qCWarning(adLogger) <<
"dequeueOutputBuffer() status: try again later";
227 "AMediaCodec_dequeueOutputBuffer() status: invalid buffer idx " << idx;
230 qCWarning(adLogger) <<
"dequeueInputBuffer() status: invalid buffer idx " << bufferIdx;
252 delete m_threadDecoder;
258 if (!requestPermissions())
283 if (!requestPermissions())
303 if (!m_threadDecoder) {
304 m_threadDecoder =
new QThread(
this);
306 m_threadDecoder->
start();
314 if (!
isDecoding() && m_position < 0 && m_duration < 0)
318 m_audioBuffer.
clear();
329 if (!m_audioBuffer.
isEmpty()) {
331 m_position =
buffer.second;
342 return m_audioBuffer.
size() > 0;
362void QAndroidAudioDecoder::durationChanged(
qint64 duration)
374void QAndroidAudioDecoder::finished()
378 if (m_duration != -1)
379 emit durationChanged(m_duration);
386bool QAndroidAudioDecoder::requestPermissions()
388 const auto writeRes = QtAndroidPrivate::requestPermission(
QStringLiteral(
"android.permission.WRITE_EXTERNAL_STORAGE"));
389 if (writeRes.result() == QtAndroidPrivate::Authorized)
395void QAndroidAudioDecoder::decode()
406bool QAndroidAudioDecoder::createTempFile()
410 bool success =
file.
open(QIODevice::QIODevice::ReadWrite);
414 success &= (
file.
write(m_deviceBuffer) == m_deviceBuffer.
size());
419 m_deviceBuffer.
clear();
426void QAndroidAudioDecoder::readDevice() {
428 if (m_device->
atEnd()) {
430 if (!createTempFile()) {
431 m_deviceBuffer.
clear();
441#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.
void close() override
Calls QFileDevice::flush() and closes the file.
qint64 size() const
Returns the file size in bytes.
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)
void moveToThread(QThread *thread)
Changes the thread affinity for this object and its children.
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.
\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 isEmpty() const
Returns true if the string has no characters; otherwise returns false.
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
std::pair< T1, T2 > QPair
#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)
file open(QIODevice::ReadOnly)
QFileInfo info(fileName)
[8]
application x qt windows mime
[2]
myObject disconnect()
[26]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent