diff options
author | Artem Dyomin <artem.dyomin@qt.io> | 2023-07-31 16:07:22 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-08-02 10:33:28 +0000 |
commit | 0562c1112ce30a6e9ea842722eb236e0b5fa1265 (patch) | |
tree | 8d246ff33e5e772b07d48ac166a9b2eb4857c7d8 | |
parent | 106ef9957c284870fd8d991b639f97fac2c1739c (diff) |
Move VideoFrameEncoder::Data members to VideoFrameEncoder
Dynamically allocated VideoFrameEncoder::Data is not need for this
case, let's simplify and move all members to the class.
Change-Id: I7bfa8f6a92ba0a449dd84843109b1344c86ad5bd
Reviewed-by: Artem Dyomin <artem.dyomin@qt.io>
Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
(cherry picked from commit 87adcdcf6ffa7d026b22917249fbbee1e5fd1dfd)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
4 files changed, 175 insertions, 174 deletions
diff --git a/src/plugins/multimedia/ffmpeg/qffmpegencoder.cpp b/src/plugins/multimedia/ffmpeg/qffmpegencoder.cpp index 902daa5ad..cd0e040bb 100644 --- a/src/plugins/multimedia/ffmpeg/qffmpegencoder.cpp +++ b/src/plugins/multimedia/ffmpeg/qffmpegencoder.cpp @@ -495,13 +495,15 @@ VideoEncoder::VideoEncoder(Encoder *encoder, const QMediaEncoderSettings &settin frameRate = 30.; } - frameEncoder = new VideoFrameEncoder(settings, format.frameSize(), frameRate, ffmpegPixelFormat, - swFormat, encoder->formatContext); + frameEncoder = VideoFrameEncoder::create(settings, format.frameSize(), frameRate, + ffmpegPixelFormat, swFormat, encoder->formatContext); } -VideoEncoder::~VideoEncoder() +VideoEncoder::~VideoEncoder() = default; + +bool VideoEncoder::isValid() const { - delete frameEncoder; + return frameEncoder != nullptr; } void VideoEncoder::addFrame(const QVideoFrame &frame) @@ -522,11 +524,6 @@ void VideoEncoder::addFrame(const QVideoFrame &frame) } } -bool VideoEncoder::isValid() const -{ - return !frameEncoder->isNull(); -} - QVideoFrame VideoEncoder::takeFrame() { QMutexLocker locker(&queueMutex); @@ -588,7 +585,7 @@ void VideoEncoder::loop() if (!frame.isValid()) return; - if (frameEncoder->isNull()) + if (!isValid()) return; // qCDebug(qLcFFmpegEncoder) << "new video buffer" << frame.startTime(); diff --git a/src/plugins/multimedia/ffmpeg/qffmpegencoder_p.h b/src/plugins/multimedia/ffmpeg/qffmpegencoder_p.h index 36471ac98..a2b64c09a 100644 --- a/src/plugins/multimedia/ffmpeg/qffmpegencoder_p.h +++ b/src/plugins/multimedia/ffmpeg/qffmpegencoder_p.h @@ -18,9 +18,12 @@ #include "qffmpeg_p.h" #include "qffmpeghwaccel_p.h" +#include "private/qmultimediautils_p.h" + #include <private/qplatformmediarecorder_p.h> #include <qaudioformat.h> #include <qaudiobuffer.h> +#include <qmediarecorder.h> #include <queue> @@ -165,7 +168,6 @@ private: QMediaEncoderSettings settings; }; - class VideoEncoder : public EncoderThread { mutable QMutex queueMutex; @@ -177,10 +179,10 @@ public: const QVideoFrameFormat &format, std::optional<AVPixelFormat> hwFormat); ~VideoEncoder() override; - void addFrame(const QVideoFrame &frame); - bool isValid() const; + void addFrame(const QVideoFrame &frame); + void setPaused(bool b) override { EncoderThread::setPaused(b); @@ -197,7 +199,7 @@ private: bool shouldWait() const override; void loop() override; - VideoFrameEncoder *frameEncoder = nullptr; + std::unique_ptr<VideoFrameEncoder> frameEncoder; QAtomicInteger<qint64> baseTime = std::numeric_limits<qint64>::min(); qint64 lastFrameTime = 0; diff --git a/src/plugins/multimedia/ffmpeg/qffmpegvideoframeencoder.cpp b/src/plugins/multimedia/ffmpeg/qffmpegvideoframeencoder.cpp index fa596e276..6ef0b25bc 100644 --- a/src/plugins/multimedia/ffmpeg/qffmpegvideoframeencoder.cpp +++ b/src/plugins/multimedia/ffmpeg/qffmpegvideoframeencoder.cpp @@ -16,62 +16,71 @@ static Q_LOGGING_CATEGORY(qLcVideoFrameEncoder, "qt.multimedia.ffmpeg.videoencod namespace QFFmpeg { -VideoFrameEncoder::VideoFrameEncoder(const QMediaEncoderSettings &encoderSettings, - const QSize &sourceSize, qreal sourceFrameRate, - AVPixelFormat sourceFormat, AVPixelFormat sourceSWFormat, - AVFormatContext *formatContext) - : d(new Data) +std::unique_ptr<VideoFrameEncoder> +VideoFrameEncoder::create(const QMediaEncoderSettings &encoderSettings, const QSize &sourceSize, + qreal sourceFrameRate, AVPixelFormat sourceFormat, + AVPixelFormat sourceSWFormat, AVFormatContext *formatContext) { Q_ASSERT(isSwPixelFormat(sourceSWFormat)); Q_ASSERT(isHwPixelFormat(sourceFormat) || sourceSWFormat == sourceFormat); - d->settings = encoderSettings; - d->sourceSize = sourceSize; + std::unique_ptr<VideoFrameEncoder> result(new VideoFrameEncoder); - if (!d->settings.videoResolution().isValid()) - d->settings.setVideoResolution(d->sourceSize); + result->m_settings = encoderSettings; + result->m_sourceSize = sourceSize; + result->m_sourceFormat = sourceFormat; + result->m_sourceSWFormat = sourceSWFormat; - if (d->settings.videoFrameRate() <= 0.) - d->settings.setVideoFrameRate(sourceFrameRate); + if (!result->m_settings.videoResolution().isValid()) + result->m_settings.setVideoResolution(sourceSize); - d->sourceFormat = sourceFormat; - d->sourceSWFormat = sourceSWFormat; + if (result->m_settings.videoFrameRate() <= 0.) + result->m_settings.setVideoFrameRate(sourceFrameRate); - if (!initCodec() || !initTargetFormats() || !initCodecContext(formatContext)) { - d = {}; - return; + if (!result->initCodec() || !result->initTargetFormats() + || !result->initCodecContext(formatContext)) { + return nullptr; } - updateConversions(); + // TODO: make VideoFrameEncoder::private and do openning here + // if (!open()) { + // m_error = QMediaRecorder::FormatError; + // m_errorStr = QLatin1StringView("Cannot open codec"); + // return; + // } + + result->updateConversions(); + + return result; } bool VideoFrameEncoder::initCodec() { - const auto qVideoCodec = d->settings.videoCodec(); + const auto qVideoCodec = m_settings.videoCodec(); const auto codecID = QFFmpegMediaFormatInfo::codecIdForVideoCodec(qVideoCodec); - const auto resolution = d->settings.videoResolution(); + const auto resolution = m_settings.videoResolution(); - std::tie(d->codec, d->accel) = findHwEncoder(codecID, resolution); + std::tie(m_codec, m_accel) = findHwEncoder(codecID, resolution); - if (!d->codec) - d->codec = findSwEncoder(codecID, d->sourceSWFormat); + if (!m_codec) + m_codec = findSwEncoder(codecID, m_sourceSWFormat); - if (!d->codec) { + if (!m_codec) { qWarning() << "Could not find encoder for codecId" << codecID; return false; } - qCDebug(qLcVideoFrameEncoder) << "found encoder" << d->codec->name << "for id" << d->codec->id; + qCDebug(qLcVideoFrameEncoder) << "found encoder" << m_codec->name << "for id" << m_codec->id; #ifdef Q_OS_WINDOWS // TODO: investigate, there might be more encoders not supporting odd resolution - if (strcmp(d->codec->name, "h264_mf") == 0) { + if (strcmp(m_codec->name, "h264_mf") == 0) { auto makeEven = [](int size) { return size & ~1; }; const QSize fixedResolution(makeEven(resolution.width()), makeEven(resolution.height())); if (fixedResolution != resolution) { - qCDebug(qLcVideoFrameEncoder) << "Fix odd video resolution for codec" << d->codec->name << ":" - << resolution << "->" << fixedResolution; - d->settings.setVideoResolution(fixedResolution); + qCDebug(qLcVideoFrameEncoder) << "Fix odd video resolution for codec" << m_codec->name + << ":" << resolution << "->" << fixedResolution; + m_settings.setVideoResolution(fixedResolution); } } #endif @@ -81,30 +90,29 @@ bool VideoFrameEncoder::initCodec() bool VideoFrameEncoder::initTargetFormats() { - d->targetFormat = - findTargetFormat(d->sourceFormat, d->sourceSWFormat, d->codec, d->accel.get()); + m_targetFormat = findTargetFormat(m_sourceFormat, m_sourceSWFormat, m_codec, m_accel.get()); - if (d->targetFormat == AV_PIX_FMT_NONE) { - qWarning() << "Could not find target format for codecId" << d->codec->id; + if (m_targetFormat == AV_PIX_FMT_NONE) { + qWarning() << "Could not find target format for codecId" << m_codec->id; return false; } - Q_ASSERT(isHwPixelFormat(d->targetFormat) == !!d->accel); + Q_ASSERT(isHwPixelFormat(m_targetFormat) == !!m_accel); - if (d->accel) { - d->targetSWFormat = findTargetSWFormat(d->sourceSWFormat, d->codec, *d->accel); + if (m_accel) { + m_targetSWFormat = findTargetSWFormat(m_sourceSWFormat, m_codec, *m_accel); - if (d->targetSWFormat == AV_PIX_FMT_NONE) { - qWarning() << "Cannot find software target format. sourceSWFormat:" << d->sourceSWFormat - << "targetFormat:" << d->targetFormat; + if (m_targetSWFormat == AV_PIX_FMT_NONE) { + qWarning() << "Cannot find software target format. sourceSWFormat:" << m_sourceSWFormat + << "targetFormat:" << m_targetFormat; return false; } - d->accel->createFramesContext(d->targetSWFormat, d->settings.videoResolution()); - if (!d->accel->hwFramesContextAsBuffer()) + m_accel->createFramesContext(m_targetSWFormat, m_settings.videoResolution()); + if (!m_accel->hwFramesContextAsBuffer()) return false; } else { - d->targetSWFormat = d->targetFormat; + m_targetSWFormat = m_targetFormat; } return true; @@ -114,33 +122,33 @@ VideoFrameEncoder::~VideoFrameEncoder() = default; bool QFFmpeg::VideoFrameEncoder::initCodecContext(AVFormatContext *formatContext) { - d->stream = avformat_new_stream(formatContext, nullptr); - d->stream->id = formatContext->nb_streams - 1; + m_stream = avformat_new_stream(formatContext, nullptr); + m_stream->id = formatContext->nb_streams - 1; //qCDebug(qLcVideoFrameEncoder) << "Video stream: index" << d->stream->id; - d->stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; - d->stream->codecpar->codec_id = d->codec->id; + m_stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + m_stream->codecpar->codec_id = m_codec->id; // Apples HEVC decoders don't like the hev1 tag ffmpeg uses by default, use hvc1 as the more commonly accepted tag - if (d->codec->id == AV_CODEC_ID_HEVC) - d->stream->codecpar->codec_tag = MKTAG('h','v','c','1'); + if (m_codec->id == AV_CODEC_ID_HEVC) + m_stream->codecpar->codec_tag = MKTAG('h', 'v', 'c', '1'); - const auto resolution = d->settings.videoResolution(); + const auto resolution = m_settings.videoResolution(); // ### Fix hardcoded values - d->stream->codecpar->format = d->targetFormat; - d->stream->codecpar->width = resolution.width(); - d->stream->codecpar->height = resolution.height(); - d->stream->codecpar->sample_aspect_ratio = AVRational{1, 1}; - float requestedRate = d->settings.videoFrameRate(); + m_stream->codecpar->format = m_targetFormat; + m_stream->codecpar->width = resolution.width(); + m_stream->codecpar->height = resolution.height(); + m_stream->codecpar->sample_aspect_ratio = AVRational{ 1, 1 }; + float requestedRate = m_settings.videoFrameRate(); constexpr int TimeScaleFactor = 1000; // Allows not to follow fixed rate - d->stream->time_base = AVRational{ 1, static_cast<int>(requestedRate * TimeScaleFactor) }; + m_stream->time_base = AVRational{ 1, static_cast<int>(requestedRate * TimeScaleFactor) }; float delta = 1e10; - if (d->codec->supported_framerates) { + if (m_codec->supported_framerates) { // codec only supports fixed frame rates - auto *best = d->codec->supported_framerates; + auto *best = m_codec->supported_framerates; qCDebug(qLcVideoFrameEncoder) << "Finding fixed rate:"; - for (auto *f = d->codec->supported_framerates; f->num != 0; f++) { + for (auto *f = m_codec->supported_framerates; f->num != 0; f++) { auto maybeRate = toFloat(*f); if (!maybeRate) continue; @@ -152,34 +160,35 @@ bool QFFmpeg::VideoFrameEncoder::initCodecContext(AVFormatContext *formatContext } } qCDebug(qLcVideoFrameEncoder) << "Fixed frame rate required. Requested:" << requestedRate << "Using:" << best->num << "/" << best->den; - d->stream->time_base = *best; + m_stream->time_base = *best; requestedRate = toFloat(*best).value_or(0.f); } - Q_ASSERT(d->codec); - d->codecContext.reset(avcodec_alloc_context3(d->codec)); - if (!d->codecContext) { + Q_ASSERT(m_codec); + m_codecContext.reset(avcodec_alloc_context3(m_codec)); + if (!m_codecContext) { qWarning() << "Could not allocate codec context"; return false; } - avcodec_parameters_to_context(d->codecContext.get(), d->stream->codecpar); - d->codecContext->time_base = d->stream->time_base; - qCDebug(qLcVideoFrameEncoder) << "requesting time base" << d->codecContext->time_base.num << d->codecContext->time_base.den; + avcodec_parameters_to_context(m_codecContext.get(), m_stream->codecpar); + m_codecContext->time_base = m_stream->time_base; + qCDebug(qLcVideoFrameEncoder) << "requesting time base" << m_codecContext->time_base.num + << m_codecContext->time_base.den; auto [num, den] = qRealToFraction(requestedRate); - d->codecContext->framerate = { num, den }; - d->codecContext->pix_fmt = d->targetFormat; - d->codecContext->width = resolution.width(); - d->codecContext->height = resolution.height(); + m_codecContext->framerate = { num, den }; + m_codecContext->pix_fmt = m_targetFormat; + m_codecContext->width = resolution.width(); + m_codecContext->height = resolution.height(); - if (d->accel) { - auto deviceContext = d->accel->hwDeviceContextAsBuffer(); + if (m_accel) { + auto deviceContext = m_accel->hwDeviceContextAsBuffer(); Q_ASSERT(deviceContext); - d->codecContext->hw_device_ctx = av_buffer_ref(deviceContext); + m_codecContext->hw_device_ctx = av_buffer_ref(deviceContext); - auto framesContext = d->accel->hwFramesContextAsBuffer(); + auto framesContext = m_accel->hwFramesContextAsBuffer(); Q_ASSERT(deviceContext); - d->codecContext->hw_frames_ctx = av_buffer_ref(framesContext); + m_codecContext->hw_frames_ctx = av_buffer_ref(framesContext); } return true; @@ -187,55 +196,54 @@ bool QFFmpeg::VideoFrameEncoder::initCodecContext(AVFormatContext *formatContext bool VideoFrameEncoder::open() { - if (!d) { - qWarning() << "Cannot open null VideoFrameEncoder"; + if (!m_codecContext) return false; - } + AVDictionaryHolder opts; - applyVideoEncoderOptions(d->settings, d->codec->name, d->codecContext.get(), opts); - int res = avcodec_open2(d->codecContext.get(), d->codec, opts); + applyVideoEncoderOptions(m_settings, m_codec->name, m_codecContext.get(), opts); + int res = avcodec_open2(m_codecContext.get(), m_codec, opts); if (res < 0) { - d->codecContext.reset(); + m_codecContext.reset(); qWarning() << "Couldn't open codec for writing" << err2str(res); return false; } - qCDebug(qLcVideoFrameEncoder) << "video codec opened" << res << "time base" << d->codecContext->time_base.num << d->codecContext->time_base.den; - d->stream->time_base = d->stream->time_base; + qCDebug(qLcVideoFrameEncoder) << "video codec opened" << res << "time base" + << m_codecContext->time_base.num << m_codecContext->time_base.den; + m_stream->time_base = m_stream->time_base; return true; } qint64 VideoFrameEncoder::getPts(qint64 us) const { - Q_ASSERT(d); - qint64 div = 1'000'000 * d->stream->time_base.num; - return div != 0 ? (us * d->stream->time_base.den + div / 2) / div : 0; + qint64 div = 1'000'000 * m_stream->time_base.num; + return div != 0 ? (us * m_stream->time_base.den + div / 2) / div : 0; } const AVRational &VideoFrameEncoder::getTimeBase() const { - return d->stream->time_base; + return m_stream->time_base; } int VideoFrameEncoder::sendFrame(AVFrameUPtr frame) { - if (!d || !d->codecContext) { + if (!m_codecContext) { qWarning() << "codec context is not initialized!"; return AVERROR(EINVAL); } if (!frame) - return avcodec_send_frame(d->codecContext.get(), frame.get()); + return avcodec_send_frame(m_codecContext.get(), frame.get()); - if (frame->format != d->sourceFormat) { - qWarning() << "Frame format has changed:" << d->sourceFormat << "->" << frame->format; + if (frame->format != m_sourceFormat) { + qWarning() << "Frame format has changed:" << m_sourceFormat << "->" << frame->format; return AVERROR(EINVAL); } const QSize frameSize(frame->width, frame->height); - if (frameSize != d->sourceSize) { + if (frameSize != m_sourceSize) { qCDebug(qLcVideoFrameEncoder) << "Update conversions on the fly. Source size" - << d->sourceSize << "->" << frameSize; - d->sourceSize = frameSize; + << m_sourceSize << "->" << frameSize; + m_sourceSize = frameSize; updateConversions(); } @@ -243,7 +251,7 @@ int VideoFrameEncoder::sendFrame(AVFrameUPtr frame) AVRational timeBase = {}; getAVFrameTime(*frame, pts, timeBase); - if (d->downloadFromHW) { + if (m_downloadFromHW) { auto f = makeAVFrame(); int err = av_hwframe_transfer_data(f.get(), frame.get(), 0); @@ -255,15 +263,15 @@ int VideoFrameEncoder::sendFrame(AVFrameUPtr frame) frame = std::move(f); } - if (d->converter) { + if (m_converter) { auto f = makeAVFrame(); - f->format = d->targetSWFormat; - f->width = d->settings.videoResolution().width(); - f->height = d->settings.videoResolution().height(); + f->format = m_targetSWFormat; + f->width = m_settings.videoResolution().width(); + f->height = m_settings.videoResolution().height(); av_frame_get_buffer(f.get(), 0); - const auto scaledHeight = sws_scale(d->converter.get(), frame->data, frame->linesize, 0, + const auto scaledHeight = sws_scale(m_converter.get(), frame->data, frame->linesize, 0, frame->height, f->data, f->linesize); if (scaledHeight != f->height) @@ -272,8 +280,8 @@ int VideoFrameEncoder::sendFrame(AVFrameUPtr frame) frame = std::move(f); } - if (d->uploadToHW) { - auto *hwFramesContext = d->accel->hwFramesContextAsBuffer(); + if (m_uploadToHW) { + auto *hwFramesContext = m_accel->hwFramesContextAsBuffer(); Q_ASSERT(hwFramesContext); auto f = makeAVFrame(); @@ -302,28 +310,28 @@ int VideoFrameEncoder::sendFrame(AVFrameUPtr frame) << timeBase.den; setAVFrameTime(*frame, pts, timeBase); - return avcodec_send_frame(d->codecContext.get(), frame.get()); + return avcodec_send_frame(m_codecContext.get(), frame.get()); } AVPacketUPtr VideoFrameEncoder::retrievePacket() { - if (!d || !d->codecContext) + if (!m_codecContext) return nullptr; auto getPacket = [&]() { AVPacketUPtr packet(av_packet_alloc()); - const int ret = avcodec_receive_packet(d->codecContext.get(), packet.get()); + const int ret = avcodec_receive_packet(m_codecContext.get(), packet.get()); if (ret < 0) { if (ret != AVERROR(EOF) && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) qCDebug(qLcVideoFrameEncoder) << "Error receiving packet" << ret << err2str(ret); return AVPacketUPtr{}; } - auto ts = timeStampMs(packet->pts, d->stream->time_base); + auto ts = timeStampMs(packet->pts, m_stream->time_base); qCDebug(qLcVideoFrameEncoder) << "got a packet" << packet->pts << packet->dts << (ts ? *ts : 0); - packet->stream_index = d->stream->id; + packet->stream_index = m_stream->id; return packet; }; @@ -362,43 +370,43 @@ AVPacketUPtr VideoFrameEncoder::retrievePacket() void VideoFrameEncoder::updateConversions() { - const bool needToScale = d->sourceSize != d->settings.videoResolution(); - const bool zeroCopy = d->sourceFormat == d->targetFormat && !needToScale; + const bool needToScale = m_sourceSize != m_settings.videoResolution(); + const bool zeroCopy = m_sourceFormat == m_targetFormat && !needToScale; - d->converter.reset(); + m_converter.reset(); if (zeroCopy) { - d->downloadFromHW = false; - d->uploadToHW = false; + m_downloadFromHW = false; + m_uploadToHW = false; - qCDebug(qLcVideoFrameEncoder) << "zero copy encoding, format" << d->targetFormat; + qCDebug(qLcVideoFrameEncoder) << "zero copy encoding, format" << m_targetFormat; // no need to initialize any converters return; } - d->downloadFromHW = d->sourceFormat != d->sourceSWFormat; - d->uploadToHW = d->targetFormat != d->targetSWFormat; + m_downloadFromHW = m_sourceFormat != m_sourceSWFormat; + m_uploadToHW = m_targetFormat != m_targetSWFormat; - if (d->sourceSWFormat != d->targetSWFormat || needToScale) { - const auto targetSize = d->settings.videoResolution(); + if (m_sourceSWFormat != m_targetSWFormat || needToScale) { + const auto targetSize = m_settings.videoResolution(); qCDebug(qLcVideoFrameEncoder) - << "video source and encoder use different formats:" << d->sourceSWFormat - << d->targetSWFormat << "or sizes:" << d->sourceSize << targetSize; + << "video source and encoder use different formats:" << m_sourceSWFormat + << m_targetSWFormat << "or sizes:" << m_sourceSize << targetSize; - d->converter.reset(sws_getContext(d->sourceSize.width(), d->sourceSize.height(), - d->sourceSWFormat, targetSize.width(), - targetSize.height(), d->targetSWFormat, SWS_FAST_BILINEAR, - nullptr, nullptr, nullptr)); + m_converter.reset(sws_getContext(m_sourceSize.width(), m_sourceSize.height(), + m_sourceSWFormat, targetSize.width(), targetSize.height(), + m_targetSWFormat, SWS_FAST_BILINEAR, nullptr, nullptr, + nullptr)); } qCDebug(qLcVideoFrameEncoder) << "VideoFrameEncoder conversions initialized:" - << "sourceFormat:" << d->sourceFormat - << (isHwPixelFormat(d->sourceFormat) ? "(hw)" : "(sw)") - << "targetFormat:" << d->targetFormat - << (isHwPixelFormat(d->targetFormat) ? "(hw)" : "(sw)") - << "sourceSWFormat:" << d->sourceSWFormat - << "targetSWFormat:" << d->targetSWFormat - << "converter:" << d->converter.get(); + << "sourceFormat:" << m_sourceFormat + << (isHwPixelFormat(m_sourceFormat) ? "(hw)" : "(sw)") + << "targetFormat:" << m_targetFormat + << (isHwPixelFormat(m_targetFormat) ? "(hw)" : "(sw)") + << "sourceSWFormat:" << m_sourceSWFormat + << "targetSWFormat:" << m_targetSWFormat + << "converter:" << m_converter.get(); } } // namespace QFFmpeg diff --git a/src/plugins/multimedia/ffmpeg/qffmpegvideoframeencoder_p.h b/src/plugins/multimedia/ffmpeg/qffmpegvideoframeencoder_p.h index 6b3bef9ff..a977e13cd 100644 --- a/src/plugins/multimedia/ffmpeg/qffmpegvideoframeencoder_p.h +++ b/src/plugins/multimedia/ffmpeg/qffmpegvideoframeencoder_p.h @@ -24,41 +24,19 @@ namespace QFFmpeg { class VideoFrameEncoder { - class Data final - { - public: - QAtomicInt ref = 0; - QMediaEncoderSettings settings; - QSize sourceSize; - - std::unique_ptr<HWAccel> accel; - const AVCodec *codec = nullptr; - AVStream *stream = nullptr; - AVCodecContextUPtr codecContext; - std::unique_ptr<SwsContext, decltype(&sws_freeContext)> converter = { nullptr, - &sws_freeContext }; - AVPixelFormat sourceFormat = AV_PIX_FMT_NONE; - AVPixelFormat sourceSWFormat = AV_PIX_FMT_NONE; - AVPixelFormat targetFormat = AV_PIX_FMT_NONE; - AVPixelFormat targetSWFormat = AV_PIX_FMT_NONE; - bool downloadFromHW = false; - bool uploadToHW = false; - }; - - QExplicitlySharedDataPointer<Data> d; public: - VideoFrameEncoder() = default; - VideoFrameEncoder(const QMediaEncoderSettings &encoderSettings, const QSize &sourceSize, - qreal sourceFrameRate, AVPixelFormat sourceFormat, AVPixelFormat swFormat, - AVFormatContext *formatContext); + static std::unique_ptr<VideoFrameEncoder> create(const QMediaEncoderSettings &encoderSettings, + const QSize &sourceSize, qreal sourceFrameRate, + AVPixelFormat sourceFormat, + AVPixelFormat sourceSWFormat, + AVFormatContext *formatContext); + ~VideoFrameEncoder(); bool open(); - bool isNull() const { return !d; } - - AVPixelFormat sourceFormat() const { return d ? d->sourceFormat : AV_PIX_FMT_NONE; } - AVPixelFormat targetFormat() const { return d ? d->targetFormat : AV_PIX_FMT_NONE; } + AVPixelFormat sourceFormat() const { return m_sourceFormat; } + AVPixelFormat targetFormat() const { return m_targetFormat; } qint64 getPts(qint64 ms) const; @@ -68,6 +46,8 @@ public: AVPacketUPtr retrievePacket(); private: + VideoFrameEncoder() = default; + void updateConversions(); bool initCodec(); @@ -77,11 +57,25 @@ private: bool initCodecContext(AVFormatContext *formatContext); private: + QMediaEncoderSettings m_settings; + QSize m_sourceSize; + + std::unique_ptr<HWAccel> m_accel; + const AVCodec *m_codec = nullptr; + AVStream *m_stream = nullptr; + AVCodecContextUPtr m_codecContext; + std::unique_ptr<SwsContext, decltype(&sws_freeContext)> m_converter = { nullptr, + &sws_freeContext }; + AVPixelFormat m_sourceFormat = AV_PIX_FMT_NONE; + AVPixelFormat m_sourceSWFormat = AV_PIX_FMT_NONE; + AVPixelFormat m_targetFormat = AV_PIX_FMT_NONE; + AVPixelFormat m_targetSWFormat = AV_PIX_FMT_NONE; + bool m_downloadFromHW = false; + bool m_uploadToHW = false; + int64_t m_prevPacketDts = AV_NOPTS_VALUE; int64_t m_packetDtsOffset = 0; }; - - } QT_END_NAMESPACE |