summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem Dyomin <artem.dyomin@qt.io>2024-03-07 11:32:00 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-03-15 21:04:04 +0000
commit6c46d2f5f50f059e2102f52ff29506959166747b (patch)
tree06f285fa3874d924f28939fdd70e172ebc04c1cc
parentcf35e43ab11ee5b2d9f920cbe359d0edb8b31830 (diff)
Add QIODevice output to the recording engine
The reasons for picking the change are: - ensuring code consistency to avoid merge conflicts - the ticket QTBUG-122224, which is going to be fixed in in the next patch. The IO is expected to be open, it's to be described in the documentation. Task-number: QTBUG-122224 Task-number: QTBUG-121827 Pick-to: 6.5 Change-Id: I82fbfac7b508032600dd8eb080528e23c0ee2e59 Reviewed-by: Artem Dyomin <artem.dyomin@qt.io> Reviewed-by: Bartlomiej Moskal <bartlomiej.moskal@qt.io> (cherry picked from commit 12211d0cdbbc0845b753d8e9fffa481c053be751) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit 140d47e915485d7e568208d199429b9823f3b65d)
-rw-r--r--src/plugins/multimedia/ffmpeg/qffmpegencoder.cpp9
-rw-r--r--src/plugins/multimedia/ffmpeg/qffmpegencoder_p.h4
-rw-r--r--src/plugins/multimedia/ffmpeg/qffmpegencodingformatcontext.cpp32
-rw-r--r--src/plugins/multimedia/ffmpeg/qffmpegencodingformatcontext_p.h4
-rw-r--r--src/plugins/multimedia/ffmpeg/qffmpegioutils.cpp11
-rw-r--r--src/plugins/multimedia/ffmpeg/qffmpegioutils_p.h2
6 files changed, 56 insertions, 6 deletions
diff --git a/src/plugins/multimedia/ffmpeg/qffmpegencoder.cpp b/src/plugins/multimedia/ffmpeg/qffmpegencoder.cpp
index d233ac895..85ac70f87 100644
--- a/src/plugins/multimedia/ffmpeg/qffmpegencoder.cpp
+++ b/src/plugins/multimedia/ffmpeg/qffmpegencoder.cpp
@@ -46,10 +46,15 @@ T dequeueIfPossible(std::queue<T> &queue)
} // namespace
-Encoder::Encoder(const QMediaEncoderSettings &settings, const QString &filePath)
+Encoder::Encoder(const QMediaEncoderSettings &settings, Output output)
: m_settings(settings), m_formatContext(settings.fileFormat())
{
- m_formatContext.openAVIO(filePath);
+ auto openAVIO = [this](const auto &output) { m_formatContext.openAVIO(output); };
+ std::visit(openAVIO, output);
+
+ if (!m_formatContext.isAVIOOpen())
+ qCWarning(qLcFFmpegEncoder) << "Unable to open IO device to record media";
+
m_muxer = new Muxer(this);
}
diff --git a/src/plugins/multimedia/ffmpeg/qffmpegencoder_p.h b/src/plugins/multimedia/ffmpeg/qffmpegencoder_p.h
index da9c26ac8..7d74baa03 100644
--- a/src/plugins/multimedia/ffmpeg/qffmpegencoder_p.h
+++ b/src/plugins/multimedia/ffmpeg/qffmpegencoder_p.h
@@ -27,6 +27,7 @@
#include <qmediarecorder.h>
#include <queue>
+#include <variant>
QT_BEGIN_NAMESPACE
@@ -58,7 +59,8 @@ class Encoder : public QObject
{
Q_OBJECT
public:
- Encoder(const QMediaEncoderSettings &settings, const QString &filePath);
+ using Output = std::variant<QString, QIODevice *>;
+ Encoder(const QMediaEncoderSettings &settings, Output output);
~Encoder();
void addAudioInput(QFFmpegAudioInput *input);
diff --git a/src/plugins/multimedia/ffmpeg/qffmpegencodingformatcontext.cpp b/src/plugins/multimedia/ffmpeg/qffmpegencodingformatcontext.cpp
index a06b46ef2..908fbe028 100644
--- a/src/plugins/multimedia/ffmpeg/qffmpegencodingformatcontext.cpp
+++ b/src/plugins/multimedia/ffmpeg/qffmpegencodingformatcontext.cpp
@@ -3,6 +3,8 @@
#include "qffmpegencodingformatcontext_p.h"
#include "qffmpegmediaformatinfo_p.h"
+#include "qffmpegioutils_p.h"
+#include "qiodevice.h"
#include "QtCore/qloggingcategory.h"
QT_BEGIN_NAMESPACE
@@ -11,6 +13,12 @@ namespace QFFmpeg {
static Q_LOGGING_CATEGORY(qLcEncodingFormatContext, "qt.multimedia.ffmpeg.encodingformatcontext");
+namespace {
+// In the example https://ffmpeg.org/doxygen/trunk/avio_read_callback_8c-example.html,
+// BufferSize = 4096 is suggested, however, it might be not optimal. To be investigated.
+constexpr size_t DefaultBufferSize = 4096;
+} // namespace
+
EncodingFormatContext::EncodingFormatContext(QMediaFormat::FileFormat fileFormat)
: m_avFormatContext(avformat_alloc_context())
{
@@ -46,12 +54,30 @@ void EncodingFormatContext::openAVIO(const QString &filePath)
m_avFormatContext->url = url.release();
}
+void EncodingFormatContext::openAVIO(QIODevice *device)
+{
+ Q_ASSERT(!isAVIOOpen());
+ Q_ASSERT(device);
+
+ if (!device->isWritable())
+ return;
+
+ auto buffer = static_cast<uint8_t *>(av_malloc(DefaultBufferSize));
+ m_avFormatContext->pb = avio_alloc_context(buffer, DefaultBufferSize, 1, device, nullptr,
+ &writeQIODevice, &seekQIODevice);
+}
+
void EncodingFormatContext::closeAVIO()
{
// Close the AVIOContext and release any file handles
- if (auto io = std::exchange(m_avFormatContext->pb, nullptr)) {
- const int res = avio_close(io);
- Q_ASSERT(res == 0);
+ if (isAVIOOpen()) {
+ if (m_avFormatContext->url && *m_avFormatContext->url != '\0') {
+ auto closeResult = avio_closep(&m_avFormatContext->pb);
+ Q_ASSERT(closeResult == 0);
+ } else {
+ av_free(std::exchange(m_avFormatContext->pb->buffer, nullptr));
+ avio_context_free(&m_avFormatContext->pb);
+ }
// delete url even though it might be delete by avformat_free_context to
// ensure consistency in openAVIO/closeAVIO.
diff --git a/src/plugins/multimedia/ffmpeg/qffmpegencodingformatcontext_p.h b/src/plugins/multimedia/ffmpeg/qffmpegencodingformatcontext_p.h
index 0993c03ac..bbfb08338 100644
--- a/src/plugins/multimedia/ffmpeg/qffmpegencodingformatcontext_p.h
+++ b/src/plugins/multimedia/ffmpeg/qffmpegencodingformatcontext_p.h
@@ -20,6 +20,8 @@
QT_BEGIN_NAMESPACE
+class QIODevice;
+
namespace QFFmpeg {
class EncodingFormatContext
@@ -30,6 +32,8 @@ public:
void openAVIO(const QString &filePath);
+ void openAVIO(QIODevice *device);
+
bool isAVIOOpen() const { return m_avFormatContext->pb != nullptr; }
void closeAVIO();
diff --git a/src/plugins/multimedia/ffmpeg/qffmpegioutils.cpp b/src/plugins/multimedia/ffmpeg/qffmpegioutils.cpp
index de332e91d..289821832 100644
--- a/src/plugins/multimedia/ffmpeg/qffmpegioutils.cpp
+++ b/src/plugins/multimedia/ffmpeg/qffmpegioutils.cpp
@@ -12,14 +12,25 @@ namespace QFFmpeg {
int readQIODevice(void *opaque, uint8_t *buf, int buf_size)
{
auto *dev = static_cast<QIODevice *>(opaque);
+ Q_ASSERT(dev);
+
if (dev->atEnd())
return AVERROR_EOF;
return dev->read(reinterpret_cast<char *>(buf), buf_size);
}
+int writeQIODevice(void *opaque, uint8_t *buf, int buf_size)
+{
+ auto dev = static_cast<QIODevice *>(opaque);
+ Q_ASSERT(dev);
+
+ return dev->write(reinterpret_cast<const char *>(buf), buf_size);
+}
+
int64_t seekQIODevice(void *opaque, int64_t offset, int whence)
{
QIODevice *dev = static_cast<QIODevice *>(opaque);
+ Q_ASSERT(dev);
if (dev->isSequential())
return AVERROR(EINVAL);
diff --git a/src/plugins/multimedia/ffmpeg/qffmpegioutils_p.h b/src/plugins/multimedia/ffmpeg/qffmpegioutils_p.h
index cf3136f39..3f6591244 100644
--- a/src/plugins/multimedia/ffmpeg/qffmpegioutils_p.h
+++ b/src/plugins/multimedia/ffmpeg/qffmpegioutils_p.h
@@ -23,6 +23,8 @@ namespace QFFmpeg {
int readQIODevice(void *opaque, uint8_t *buf, int buf_size);
+int writeQIODevice(void *opaque, uint8_t *buf, int buf_size);
+
int64_t seekQIODevice(void *opaque, int64_t offset, int whence);
} // namespace QFFmpeg