From 6d3ea5bf46c00eb3cc722b66047742ca75a6ab08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=AE=E7=94=9F=E8=8B=A5=E6=A2=A6?= <1070753498@qq.com> Date: Mon, 21 Aug 2023 18:38:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=80=E5=A7=8B=E9=87=8D=E6=9E=84=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .calng-tidy => .clang-tidy | 17 ++- .github/workflows/cmake.yml | 6 +- .github/workflows/qmake.yml | 4 +- examples/player/mainwindow.cpp | 6 - examples/player/slider.cpp | 5 + ffmpeg/CMakeLists.txt | 8 +- ffmpeg/audiodecoder.cpp | 10 +- ffmpeg/audiofifo.cc | 6 +- ffmpeg/audioframeconverter.cpp | 6 +- ffmpeg/decoder.h | 2 +- ffmpeg/decodersubtitleframe.cc | 2 +- ffmpeg/frame.cc | 179 ++++++++++++++--------- ffmpeg/frame.hpp | 22 +-- ffmpeg/gpu/hardwaredecode.cc | 13 +- ffmpeg/packet.cpp | 91 +++++++++--- ffmpeg/packet.h | 9 +- ffmpeg/subtitle.cpp | 29 ++-- ffmpeg/subtitle.h | 22 +-- ffmpeg/subtitle/ass.cc | 16 +- ffmpeg/subtitle/assdata.hpp | 10 +- ffmpeg/videodecoder.cpp | 2 - ffmpeg/videoformat.hpp | 48 ++++-- ffmpeg/videoframeconverter.cc | 16 +- ffmpeg/videorender/openglrender.cc | 6 +- ffmpeg/videorender/videopreviewwidget.cc | 8 +- ffmpeg/videorender/videorender.cc | 2 +- ffmpeg/videorender/widgetrender.cc | 2 +- utils/countdownlatch.hpp | 2 +- 28 files changed, 335 insertions(+), 214 deletions(-) rename .calng-tidy => .clang-tidy (51%) diff --git a/.calng-tidy b/.clang-tidy similarity index 51% rename from .calng-tidy rename to .clang-tidy index 2c2e0e9..fbfab1e 100644 --- a/.calng-tidy +++ b/.clang-tidy @@ -1,5 +1,12 @@ -Checks: '-*,clang-diagnostic-*,bugprone-*,modernize-*,performance-*,readability-*,llvm-*,misc-*,-misc-unused-parameters,-misc-non-private-member-variables-in-classes' - # 类名改为大驼峰 +--- +Checks: '-*,clang-analyzer-*,readability-*,performance-*,modernize-*,bugprone-*,cert-,cppcoreguidelines-,portability-*,llvm-*,google-*' +WarningsAsErrors: '' +HeaderFilterRegex: '.' +AnalyzeTemporaryDtors: false +FormatStyle: file +User: user +CheckOptions: + # 类名改为大驼峰 - key: readability-identifier-naming.ClassCase value: CamelCase # 函数名改为小驼峰 @@ -15,3 +22,9 @@ Checks: '-*,clang-diagnostic-*,bugprone-*,modernize-*,performance-*,readability- value: '1' - key: modernize-use-trailing-return-type.UseEastWestConst value: '1' + - key: readability-identifier-naming.ClassMemberPrefix + value: 'm_' + - key: readability-identifier-naming.ConstexprVariablePrefix + value: 'k' + - key: readability-identifier-naming.GlobalVariablePrefix + value: 'g_' diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 729ce6c..1bf41ac 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -5,14 +5,14 @@ on: push: paths-ignore: # 下列文件的变更不触发部署,可以自行添加 - 'doc/**' - - '.clang-format' + - '.clang*' - '.gitignore' - 'LICENSE' - 'README*' pull_request: paths-ignore: # 下列文件的变更不触发部署,可以自行添加 - 'doc/**' - - '.clang-format' + - '.clang*' - '.gitignore' - 'LICENSE' - 'README*' @@ -31,7 +31,7 @@ jobs: qt_ver: - 6.5.2 build_type: - - "Release" + - "RelWithDebInfo" generators: - "Ninja" diff --git a/.github/workflows/qmake.yml b/.github/workflows/qmake.yml index d606e8f..08894f9 100644 --- a/.github/workflows/qmake.yml +++ b/.github/workflows/qmake.yml @@ -5,14 +5,14 @@ on: push: paths-ignore: # 下列文件的变更不触发部署,可以自行添加 - 'doc' - - '.clang-format' + - '.clang*' - '.gitignore' - 'LICENSE' - 'README*' pull_request: paths-ignore: # 下列文件的变更不触发部署,可以自行添加 - 'doc' - - '.clang-format' + - '.clang*' - '.gitignore' - 'LICENSE' - 'README*' diff --git a/examples/player/mainwindow.cpp b/examples/player/mainwindow.cpp index 401ef3f..d39b59a 100644 --- a/examples/player/mainwindow.cpp +++ b/examples/player/mainwindow.cpp @@ -410,9 +410,6 @@ void MainWindow::buildConnect() d_ptr->controlWidget, [this](const QStringList &tracks) { qDeleteAll(d_ptr->audioTracksGroup->actions()); - if (tracks.size() < 2) { - return; - } for (const auto &item : qAsConst(tracks)) { auto action = new QAction(item, this); action->setCheckable(true); @@ -438,9 +435,6 @@ void MainWindow::buildConnect() d_ptr->controlWidget, [this](const QStringList &tracks) { qDeleteAll(d_ptr->subTracksGroup->actions()); - if (tracks.size() < 2) { - return; - } for (const auto &item : qAsConst(tracks)) { auto action = new QAction(item, this); action->setCheckable(true); diff --git a/examples/player/slider.cpp b/examples/player/slider.cpp index 01e3a87..696f660 100644 --- a/examples/player/slider.cpp +++ b/examples/player/slider.cpp @@ -93,6 +93,11 @@ void Slider::enterEvent(QEnterEvent *event) void Slider::leaveEvent(QEvent *e) { QSlider::leaveEvent(e); + + auto pos = QCursor::pos(); + if (rect().contains(mapFromGlobal(pos))) { + return; + } emit onLeave(); unsetCursor(); } diff --git a/ffmpeg/CMakeLists.txt b/ffmpeg/CMakeLists.txt index c997c4d..1786ee4 100644 --- a/ffmpeg/CMakeLists.txt +++ b/ffmpeg/CMakeLists.txt @@ -93,7 +93,9 @@ target_link_libraries( unofficial::brotli::brotlidec unofficial::brotli::brotlienc) -if(CMAKE_HOST_APPLE) +if(CMAKE_HOST_WIN32) + target_compile_definitions(ffmpeg PRIVATE "FFMPEG_LIBRARY") +elseif(CMAKE_HOST_APPLE) target_link_libraries( ffmpeg PRIVATE ${Foundation_LIBRARY} @@ -112,7 +114,3 @@ if(CMAKE_HOST_APPLE) ${CoreVideo_LIBRARY} ${CoreServices_LIBRARY}) endif() - -if(CMAKE_HOST_WIN32) - target_compile_definitions(ffmpeg PRIVATE "FFMPEG_LIBRARY") -endif() diff --git a/ffmpeg/audiodecoder.cpp b/ffmpeg/audiodecoder.cpp index ac5ad82..2b7d4f0 100644 --- a/ffmpeg/audiodecoder.cpp +++ b/ffmpeg/audiodecoder.cpp @@ -9,12 +9,14 @@ namespace Ffmpeg { class AudioDecoder::AudioDecoderPrivate { public: - AudioDecoderPrivate(QObject *parent) - : owner(parent) + AudioDecoderPrivate(AudioDecoder *q) + : q_ptr(q) { - decoderAudioFrame = new DecoderAudioFrame(owner); + decoderAudioFrame = new DecoderAudioFrame(q_ptr); } - QObject *owner; + + AudioDecoder *q_ptr; + DecoderAudioFrame *decoderAudioFrame; }; diff --git a/ffmpeg/audiofifo.cc b/ffmpeg/audiofifo.cc index f9601c4..cddd16c 100644 --- a/ffmpeg/audiofifo.cc +++ b/ffmpeg/audiofifo.cc @@ -13,8 +13,8 @@ namespace Ffmpeg { class AudioFifo::AudioFifoPrivtate { public: - AudioFifoPrivtate(QObject *parent) - : owner(parent) + AudioFifoPrivtate(AudioFifo *q) + : q_ptr(q) {} ~AudioFifoPrivtate() @@ -26,7 +26,7 @@ class AudioFifo::AudioFifoPrivtate void setError(int errorCode) { AVErrorManager::instance()->setErrorCode(errorCode); } - QObject *owner; + AudioFifo *q_ptr; AVAudioFifo *audioFifo = nullptr; }; diff --git a/ffmpeg/audioframeconverter.cpp b/ffmpeg/audioframeconverter.cpp index b837a24..07e92b4 100644 --- a/ffmpeg/audioframeconverter.cpp +++ b/ffmpeg/audioframeconverter.cpp @@ -102,13 +102,13 @@ QAudioFormat::SampleFormat getSampleFormat(AVSampleFormat format) class AudioFrameConverter::AudioFrameConverterPrivate { public: - AudioFrameConverterPrivate(QObject *parent) - : owner(parent) + AudioFrameConverterPrivate(AudioFrameConverter *q) + : q_ptr(q) {} void setError(int errorCode) { AVErrorManager::instance()->setErrorCode(errorCode); } - QObject *owner; + AudioFrameConverter *q_ptr; SwrContext *swrContext; QAudioFormat format; diff --git a/ffmpeg/decoder.h b/ffmpeg/decoder.h index ee493f0..ed7d461 100644 --- a/ffmpeg/decoder.h +++ b/ffmpeg/decoder.h @@ -31,7 +31,7 @@ template class Decoder : public QThread { public: - Decoder(QObject *parent = nullptr) + explicit Decoder(QObject *parent = nullptr) : QThread(parent) {} virtual ~Decoder() override { stopDecoder(); } diff --git a/ffmpeg/decodersubtitleframe.cc b/ffmpeg/decodersubtitleframe.cc index d8bbe00..4010527 100644 --- a/ffmpeg/decodersubtitleframe.cc +++ b/ffmpeg/decodersubtitleframe.cc @@ -18,7 +18,7 @@ namespace Ffmpeg { class DecoderSubtitleFrame::DecoderSubtitleFramePrivate { public: - DecoderSubtitleFramePrivate(QObject *parent) + explicit DecoderSubtitleFramePrivate(QObject *parent) : owner(parent) {} diff --git a/ffmpeg/frame.cc b/ffmpeg/frame.cc index 44be07e..0fef7c7 100644 --- a/ffmpeg/frame.cc +++ b/ffmpeg/frame.cc @@ -1,5 +1,6 @@ #include "frame.hpp" #include "averrormanager.hpp" +#include "videoformat.hpp" #include @@ -10,18 +11,18 @@ extern "C" { namespace Ffmpeg { -struct Frame::FramePrivate +class Frame::FramePrivate { - ~FramePrivate() { reset(); } - - void reset() +public: + FramePrivate(Frame *q) + : q_ptr(q) + {} + ~FramePrivate() { - pts = 0; - duration = 0; - format = QImage::Format_Invalid; - Q_ASSERT(frame != nullptr); - freeImageAlloc(); - av_frame_free(&frame); + if (frame) { + freeImageAlloc(); + av_frame_free(&frame); + } } void freeImageAlloc() @@ -34,82 +35,95 @@ struct Frame::FramePrivate void setError(int errorCode) { AVErrorManager::instance()->setErrorCode(errorCode); } + Frame *q_ptr; + AVFrame *frame; bool imageAlloc = false; - double pts = 0; - double duration = 0; - - QImage::Format format = QImage::Format_Invalid; bool useNull = false; }; Frame::Frame() - : d_ptr(new FramePrivate) + : d_ptr(new FramePrivate(this)) { d_ptr->frame = av_frame_alloc(); - Q_ASSERT(d_ptr->frame != nullptr); } -Frame::Frame(const QImage &image) - : d_ptr(new FramePrivate) +Frame::Frame(const Frame &other) + : d_ptr(new FramePrivate(this)) { d_ptr->frame = av_frame_alloc(); - Q_ASSERT(d_ptr->frame != nullptr); - auto img = image; - img.convertTo(QImage::Format_RGBA8888); - d_ptr->frame->width = img.width(); - d_ptr->frame->height = img.height(); - d_ptr->frame->format = AV_PIX_FMT_RGBA; - av_frame_get_buffer(d_ptr->frame, 0); - memcpy(d_ptr->frame->data[0], img.bits(), d_ptr->frame->width * d_ptr->frame->height * 4); + av_frame_ref(d_ptr->frame, other.d_ptr->frame); } -Frame::Frame(const Frame &other) - : d_ptr(new FramePrivate) +Frame::Frame(Frame &&other) + : d_ptr(new FramePrivate(this)) { - d_ptr->frame = av_frame_clone(other.d_ptr->frame); - d_ptr->pts = other.d_ptr->pts; - d_ptr->duration = other.d_ptr->duration; - d_ptr->format = other.d_ptr->format; - d_ptr->useNull = other.d_ptr->useNull; + d_ptr->frame = other.d_ptr->frame; + other.d_ptr->frame = nullptr; } +Frame::~Frame() {} + Frame &Frame::operator=(const Frame &other) { - d_ptr->reset(); - d_ptr->frame = av_frame_clone(other.d_ptr->frame); - d_ptr->pts = other.d_ptr->pts; - d_ptr->duration = other.d_ptr->duration; - d_ptr->format = other.d_ptr->format; - d_ptr->useNull = other.d_ptr->useNull; + if (this != &other) { + d_ptr->freeImageAlloc(); + av_frame_unref(d_ptr->frame); + av_frame_ref(d_ptr->frame, other.d_ptr->frame); + } + return *this; } -Frame::~Frame() {} +Frame &Frame::operator=(Frame &&other) +{ + if (this != &other) { + d_ptr->freeImageAlloc(); + d_ptr->frame = other.d_ptr->frame; + other.d_ptr->frame = nullptr; + } + + return *this; +} void Frame::copyPropsFrom(Frame *src) { + Q_ASSERT(src != nullptr); auto srcFrame = src->avFrame(); + Q_ASSERT(srcFrame != nullptr); + Q_ASSERT(d_ptr->frame != nullptr); + av_frame_copy_props(d_ptr->frame, srcFrame); - d_ptr->frame->width = srcFrame->width; - d_ptr->frame->height = srcFrame->height; d_ptr->frame->pts = srcFrame->pts; - d_ptr->frame->pkt_dts = srcFrame->pkt_dts; + d_ptr->frame->pkt_duration = srcFrame->pkt_duration; + d_ptr->frame->pict_type = srcFrame->pict_type; d_ptr->frame->key_frame = srcFrame->key_frame; + d_ptr->frame->width = srcFrame->width; + d_ptr->frame->height = srcFrame->height; + d_ptr->frame->format = srcFrame->format; } bool Frame::imageAlloc(const QSize &size, AVPixelFormat pix_fmt, int align) { - Q_ASSERT(size.isValid()); + Q_ASSERT(d_ptr->frame != nullptr); + Q_ASSERT(size.width() > 0); + Q_ASSERT(size.height() > 0); + Q_ASSERT(pix_fmt != AV_PIX_FMT_NONE); + + auto ret = av_image_alloc(d_ptr->frame->data, + d_ptr->frame->linesize, + size.width(), + size.height(), + pix_fmt, + align); + if (ret < 0) { + d_ptr->setError(ret); + return false; + } + d_ptr->imageAlloc = true; - int ret = av_image_alloc(d_ptr->frame->data, - d_ptr->frame->linesize, - size.width(), - size.height(), - pix_fmt, - align); - return ret >= 0; + return true; } void Frame::freeImageAlloc() @@ -129,25 +143,25 @@ void Frame::unref() void Frame::setPts(double pts) { - d_ptr->pts = pts; + d_ptr->frame->pts = pts * AV_TIME_BASE; } double Frame::pts() { - return d_ptr->pts; + return d_ptr->frame->pts / (double) AV_TIME_BASE; } void Frame::setDuration(double duration) { - d_ptr->duration = duration; + d_ptr->frame->pkt_duration = duration * AV_TIME_BASE; } double Frame::duration() { - return d_ptr->duration; + return d_ptr->frame->pkt_duration / (double) AV_TIME_BASE; } -int Frame::format() const +int Frame::format() { return d_ptr->frame->format; } @@ -157,27 +171,26 @@ void Frame::setAVFrameNull() d_ptr->useNull = true; } -void Frame::setQImageFormat(QImage::Format format) -{ - d_ptr->format = format; -} - -QImage::Format Frame::qImageformat() const -{ - return d_ptr->format; -} - -QImage Frame::convertToImage() const +QImage Frame::toImage() { - if (d_ptr->format == QImage::Format_Invalid) { + Q_ASSERT(d_ptr->frame != nullptr); + Q_ASSERT(d_ptr->frame->data[0] != nullptr); + Q_ASSERT(d_ptr->frame->width > 0); + Q_ASSERT(d_ptr->frame->height > 0); + Q_ASSERT(d_ptr->frame->format != AV_PIX_FMT_NONE); + + auto format = VideoFormat::qFormatMaps.value(static_cast(d_ptr->frame->format), + QImage::Format_Invalid); + if (format == QImage::Format_Invalid) { return QImage(); } - return QImage((uchar *) d_ptr->frame->data[0], - d_ptr->frame->width, - d_ptr->frame->height, - d_ptr->frame->linesize[0], - d_ptr->format); + QImage image(d_ptr->frame->data[0], + d_ptr->frame->width, + d_ptr->frame->height, + d_ptr->frame->linesize[0], + format); + return image; } bool Frame::getBuffer() @@ -204,4 +217,24 @@ AVFrame *Frame::avFrame() return d_ptr->frame; } +Frame *Frame::fromQImage(const QImage &image) +{ + Q_ASSERT(!image.isNull()); + Q_ASSERT(image.format() != QImage::Format_Invalid); + + auto img = image; + img.convertTo(QImage::Format_RGBA8888); + + auto framePtr = std::make_unique(); + auto avFrame = framePtr->avFrame(); + avFrame->width = img.width(); + avFrame->height = img.height(); + avFrame->format = AV_PIX_FMT_RGBA; + framePtr->getBuffer(); + + memcpy(avFrame->data[0], img.bits(), avFrame->width * avFrame->height * 4); + + return framePtr.release(); +} + } // namespace Ffmpeg diff --git a/ffmpeg/frame.hpp b/ffmpeg/frame.hpp index bf30ded..1266921 100644 --- a/ffmpeg/frame.hpp +++ b/ffmpeg/frame.hpp @@ -16,16 +16,20 @@ namespace Ffmpeg { class FFMPEG_EXPORT Frame { public: - explicit Frame(); - Frame(const QImage &image); + Frame(); Frame(const Frame &other); - Frame &operator=(const Frame &other); + Frame(Frame &&other); ~Frame(); + Frame &operator=(const Frame &other); + Frame &operator=(Frame &&other); + void copyPropsFrom(Frame *src); bool isKey(); + void unref(); + bool imageAlloc(const QSize &size, AVPixelFormat pix_fmt = AV_PIX_FMT_RGBA, int align = 1); void freeImageAlloc(); @@ -37,22 +41,20 @@ class FFMPEG_EXPORT Frame void setDuration(double duration); double duration(); - int format() const; + int format(); void setAVFrameNull(); - void setQImageFormat(QImage::Format format); - QImage::Format qImageformat() const; - QImage convertToImage() const; // maybe null + QImage toImage(); // maybe null bool getBuffer(); - void unref(); - AVFrame *avFrame(); + static Frame *fromQImage(const QImage &image); + private: - struct FramePrivate; + class FramePrivate; QScopedPointer d_ptr; }; diff --git a/ffmpeg/gpu/hardwaredecode.cc b/ffmpeg/gpu/hardwaredecode.cc index 0f1a85c..2859d2d 100644 --- a/ffmpeg/gpu/hardwaredecode.cc +++ b/ffmpeg/gpu/hardwaredecode.cc @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -32,17 +33,18 @@ AVPixelFormat get_hw_format(AVCodecContext *ctx, const enum AVPixelFormat *pix_f class HardWareDecode::HardWareDecodePrivate { public: - HardWareDecodePrivate(QObject *parent) - : owner(parent) + HardWareDecodePrivate(HardWareDecode *q) + : q_ptr(q) { - bufferRef = new BufferRef(owner); + bufferRef = new BufferRef(q_ptr); } ~HardWareDecodePrivate() { hw_pix_fmt = AV_PIX_FMT_NONE; } void setError(int errorCode) { AVErrorManager::instance()->setErrorCode(errorCode); } - QObject *owner; + HardWareDecode *q_ptr; + QVector hwDeviceTypes = Utils::getCurrentHWDeviceTypes(); AVHWDeviceType hwDeviceType = AV_HWDEVICE_TYPE_NONE; BufferRef *bufferRef; @@ -66,7 +68,8 @@ bool HardWareDecode::initPixelFormat(const AVCodec *decoder) } for (AVHWDeviceType type : qAsConst(d_ptr->hwDeviceTypes)) { hw_pix_fmt = Utils::getPixelFormat(decoder, type); - if (hw_pix_fmt != AV_PIX_FMT_NONE) { + if (hw_pix_fmt != AV_PIX_FMT_NONE + && VideoFrameConverter::isSupportedInput_pix_fmt(hw_pix_fmt)) { d_ptr->hwDeviceType = type; break; } diff --git a/ffmpeg/packet.cpp b/ffmpeg/packet.cpp index 17792c7..db722f4 100644 --- a/ffmpeg/packet.cpp +++ b/ffmpeg/packet.cpp @@ -11,90 +11,133 @@ namespace Ffmpeg { class Packet::PacketPrivate { public: - PacketPrivate() {} - ~PacketPrivate() { reset(); } - - void reset() + PacketPrivate(Packet *q) + : q_ptr(q) + {} + ~PacketPrivate() { - pts = 0; - duration = 0; - Q_ASSERT(nullptr != packet); - av_packet_free(&packet); + if (packet) { + av_packet_free(&packet); + } } + Packet *q_ptr; AVPacket *packet = nullptr; - double pts = 0; - double duration = 0; }; Packet::Packet() - : d_ptr(new PacketPrivate) + : d_ptr(new PacketPrivate(this)) { d_ptr->packet = av_packet_alloc(); - Q_ASSERT(nullptr != d_ptr->packet); + + if (!d_ptr->packet) { + qWarning() << "Could not allocate packet"; + } + + av_init_packet(d_ptr->packet); } Packet::Packet(const Packet &other) - : d_ptr(new PacketPrivate) + : d_ptr(new PacketPrivate(this)) { d_ptr->packet = av_packet_clone(other.d_ptr->packet); - d_ptr->pts = other.d_ptr->pts; - d_ptr->duration = other.d_ptr->duration; + + if (!d_ptr->packet) { + qWarning() << "Could not clone packet"; + } +} + +Packet::Packet(Packet &&other) + : d_ptr(new PacketPrivate(this)) +{ + d_ptr->packet = other.d_ptr->packet; + other.d_ptr->packet = nullptr; } +Packet::~Packet() {} + Packet &Packet::operator=(const Packet &other) { - d_ptr->reset(); - d_ptr->packet = av_packet_clone(other.d_ptr->packet); - d_ptr->pts = other.d_ptr->pts; - d_ptr->duration = other.d_ptr->duration; + if (this != &other) { + d_ptr->packet = av_packet_clone(other.d_ptr->packet); + + if (!d_ptr->packet) { + qWarning() << "Could not clone packet"; + } + } + return *this; } -Packet::~Packet() {} +Packet &Packet::operator=(Packet &&other) +{ + if (this != &other) { + d_ptr->packet = other.d_ptr->packet; + other.d_ptr->packet = nullptr; + } + + return *this; +} + +bool Packet::isValid() +{ + if (nullptr == d_ptr->packet) { + return false; + } + return d_ptr->packet->size > 0; +} bool Packet::isKey() { + Q_ASSERT(nullptr != d_ptr->packet); return d_ptr->packet->flags & AV_PKT_FLAG_KEY; } void Packet::unref() { + Q_ASSERT(nullptr != d_ptr->packet); av_packet_unref(d_ptr->packet); } void Packet::setPts(double pts) { - d_ptr->pts = pts; + Q_ASSERT(nullptr != d_ptr->packet); + d_ptr->packet->pts = pts * AV_TIME_BASE; } double Packet::pts() { - return d_ptr->pts; + Q_ASSERT(nullptr != d_ptr->packet); + return d_ptr->packet->pts / (double) AV_TIME_BASE; } void Packet::setDuration(double duration) { - d_ptr->duration = duration; + Q_ASSERT(nullptr != d_ptr->packet); + d_ptr->packet->duration = duration * AV_TIME_BASE; } double Packet::duration() { - return d_ptr->duration; + Q_ASSERT(nullptr != d_ptr->packet); + return d_ptr->packet->duration / (double) AV_TIME_BASE; } void Packet::setStreamIndex(int index) { + Q_ASSERT(nullptr != d_ptr->packet); d_ptr->packet->stream_index = index; } int Packet::streamIndex() const { + Q_ASSERT(nullptr != d_ptr->packet); return d_ptr->packet->stream_index; } void Packet::rescaleTs(const AVRational &srcTimeBase, const AVRational &dstTimeBase) { + Q_ASSERT(nullptr != d_ptr->packet); av_packet_rescale_ts(d_ptr->packet, srcTimeBase, dstTimeBase); } diff --git a/ffmpeg/packet.h b/ffmpeg/packet.h index 8020853..d26656a 100644 --- a/ffmpeg/packet.h +++ b/ffmpeg/packet.h @@ -13,11 +13,16 @@ namespace Ffmpeg { class FFMPEG_EXPORT Packet { public: - explicit Packet(); + Packet(); Packet(const Packet &other); - Packet &operator=(const Packet &other); + Packet(Packet &&other); ~Packet(); + Packet &operator=(const Packet &other); + Packet &operator=(Packet &&other); + + bool isValid(); + bool isKey(); void unref(); diff --git a/ffmpeg/subtitle.cpp b/ffmpeg/subtitle.cpp index e614b7b..80cb548 100644 --- a/ffmpeg/subtitle.cpp +++ b/ffmpeg/subtitle.cpp @@ -17,8 +17,8 @@ namespace Ffmpeg { class Subtitle::SubtitlePrivate { public: - SubtitlePrivate(QObject *parent) - : owner(parent) + explicit SubtitlePrivate(Subtitle *q) + : q_ptr(q) {} ~SubtitlePrivate() { freeSubtitle(); } @@ -63,7 +63,7 @@ class Subtitle::SubtitlePrivate { pts = QString::asprintf("%.2f", pts).toDouble(); // libass只支持0.01秒,还要四舍五入 for (size_t i = 0; i < subtitle.num_rects; i++) { - AVSubtitleRect *sub_rect = subtitle.rects[i]; + auto sub_rect = subtitle.rects[i]; QByteArray text; switch (sub_rect->type) { case AVSubtitleType::SUBTITLE_TEXT: @@ -81,7 +81,8 @@ class Subtitle::SubtitlePrivate } } - QObject *owner; + Subtitle *q_ptr; + AVSubtitle subtitle; double pts = 0; double duration = 0; @@ -101,7 +102,7 @@ Subtitle::Subtitle(QObject *parent) , d_ptr(new SubtitlePrivate(this)) {} -Subtitle::~Subtitle() {} +Subtitle::~Subtitle() = default; void Subtitle::setDefault(double pts, double duration, const QString &text) { @@ -121,12 +122,12 @@ void Subtitle::parse(SwsContext *swsContext) } } -QByteArrayList Subtitle::texts() const +auto Subtitle::texts() const -> QByteArrayList { return d_ptr->texts; } -AVSubtitle *Subtitle::avSubtitle() +auto Subtitle::avSubtitle() -> AVSubtitle * { return &d_ptr->subtitle; } @@ -136,17 +137,17 @@ void Subtitle::clear() return d_ptr->freeSubtitle(); } -double Subtitle::pts() +auto Subtitle::pts() -> double { return d_ptr->pts; } -double Subtitle::duration() +auto Subtitle::duration() -> double { return d_ptr->duration; } -Subtitle::Type Subtitle::type() const +auto Subtitle::type() const -> Subtitle::Type { return d_ptr->type; } @@ -159,12 +160,12 @@ void Subtitle::setVideoResolutionRatio(const QSize &size) d_ptr->videoResolutionRatio = size; } -QSize Subtitle::videoResolutionRatio() const +auto Subtitle::videoResolutionRatio() const -> QSize { return d_ptr->videoResolutionRatio; } -bool Subtitle::resolveAss(Ass *ass) +auto Subtitle::resolveAss(Ass *ass) -> bool { if (d_ptr->type != Type::ASS) { return false; @@ -190,7 +191,7 @@ AssDataInfoList Subtitle::list() const return d_ptr->assList; } -QImage Subtitle::generateImage() const +auto Subtitle::generateImage() const -> QImage { if (d_ptr->type != Type::ASS) { return QImage(); @@ -214,7 +215,7 @@ QImage Subtitle::generateImage() const return d_ptr->image; } -QImage Subtitle::image() const +auto Subtitle::image() const -> QImage { return d_ptr->image; } diff --git a/ffmpeg/subtitle.h b/ffmpeg/subtitle.h index 23956f0..0ab2e0b 100644 --- a/ffmpeg/subtitle.h +++ b/ffmpeg/subtitle.h @@ -21,31 +21,31 @@ class FFMPEG_EXPORT Subtitle : public QObject enum Type { Unknown, Graphics, TEXT, ASS }; explicit Subtitle(QObject *parent = nullptr); - ~Subtitle(); + ~Subtitle() override; void setDefault(double pts, double duration, const QString &text); void parse(SwsContext *swsContext); - QByteArrayList texts() const; + [[nodiscard]] auto texts() const -> QByteArrayList; void setVideoResolutionRatio(const QSize &size); - QSize videoResolutionRatio() const; + [[nodiscard]] auto videoResolutionRatio() const -> QSize; - bool resolveAss(Ass *ass); + auto resolveAss(Ass *ass) -> bool; void setAssDataInfoList(const AssDataInfoList &list); - AssDataInfoList list() const; + [[nodiscard]] AssDataInfoList list() const; - QImage generateImage() const; - QImage image() const; + [[nodiscard]] auto generateImage() const -> QImage; + [[nodiscard]] auto image() const -> QImage; void clear(); - Type type() const; + [[nodiscard]] auto type() const -> Type; - double pts(); - double duration(); + auto pts() -> double; + auto duration() -> double; - AVSubtitle *avSubtitle(); + auto avSubtitle() -> AVSubtitle *; private: class SubtitlePrivate; diff --git a/ffmpeg/subtitle/ass.cc b/ffmpeg/subtitle/ass.cc index fbf5aad..59342fc 100644 --- a/ffmpeg/subtitle/ass.cc +++ b/ffmpeg/subtitle/ass.cc @@ -47,14 +47,14 @@ void print_font_providers(ASS_Library *ass_library) class Ass::AssPrivate { public: - AssPrivate(QObject *parent) - : owner(parent) + explicit AssPrivate(Ass *q) + : q_ptr(q) { qInfo() << "ass_library_version: " << ass_library_version(); print_font_providers(ass_library); ass_library = ass_library_init(); - ass_set_message_cb(ass_library, msg_callback, NULL); + ass_set_message_cb(ass_library, msg_callback, nullptr); ass_set_extract_fonts(ass_library, 1); ass_renderer = ass_renderer_init(ass_library); @@ -64,7 +64,7 @@ class Ass::AssPrivate // acc_track->styles[0].ScaleX = acc_track->styles[0].ScaleY = 1; /* Initialize fonts */ - ass_set_fonts(ass_renderer, nullptr, nullptr, 1, NULL, 1); + ass_set_fonts(ass_renderer, nullptr, nullptr, 1, nullptr, 1); } ~AssPrivate() { @@ -74,7 +74,7 @@ class Ass::AssPrivate ass_library_done(ass_library); } - QObject *owner; + Ass *q_ptr; ASS_Library *ass_library; ASS_Renderer *ass_renderer; @@ -87,7 +87,7 @@ Ass::Ass(QObject *parent) , d_ptr(new AssPrivate(this)) {} -Ass::~Ass() {} +Ass::~Ass() = default; void Ass::init(uint8_t *extradata, int extradata_size) { @@ -117,8 +117,8 @@ void Ass::setFont(const QString &fontFamily) void Ass::addFont(const QByteArray &name, const QByteArray &data) { ass_add_font(d_ptr->ass_library, - (char *) name.constData(), - (char *) data.constData(), + const_cast(name.constData()), + const_cast(data.constData()), data.size()); } diff --git a/ffmpeg/subtitle/assdata.hpp b/ffmpeg/subtitle/assdata.hpp index 5331e6e..4063278 100644 --- a/ffmpeg/subtitle/assdata.hpp +++ b/ffmpeg/subtitle/assdata.hpp @@ -9,13 +9,13 @@ namespace Ffmpeg { class AssData : public QSharedData { public: - AssData() {} + AssData() = default; AssData(const AssData &other) : QSharedData(other) , rgba(other.rgba) , rect(other.rect) {} - ~AssData() {} + ~AssData() = default; QByteArray rgba; QRect rect; @@ -36,13 +36,13 @@ class AssDataInfo AssDataInfo(const AssDataInfo &other) : d_ptr(other.d_ptr) {} - ~AssDataInfo() {} + ~AssDataInfo() = default; void setRGBA(const QByteArray &rgba) { d_ptr->rgba = rgba; } - QByteArray rgba() const { return d_ptr->rgba; } + [[nodiscard]] auto rgba() const -> QByteArray { return d_ptr->rgba; } void setRect(const QRect &rect) { d_ptr->rect = rect; } - QRect rect() const { return d_ptr->rect; } + [[nodiscard]] auto rect() const -> QRect { return d_ptr->rect; } private: QExplicitlySharedDataPointer d_ptr; diff --git a/ffmpeg/videodecoder.cpp b/ffmpeg/videodecoder.cpp index 044c229..0a55328 100644 --- a/ffmpeg/videodecoder.cpp +++ b/ffmpeg/videodecoder.cpp @@ -57,8 +57,6 @@ void VideoDecoder::runDecoder() auto frames(m_contextInfo->decodeFrame(packetPtr.data())); for (auto frame : frames) { Ffmpeg::calculateTime(frame, m_contextInfo, m_formatContext); - frame->setQImageFormat(VideoFormat::qFormatMaps.value(AVPixelFormat(frame->format()), - QImage::Format_Invalid)); d_ptr->decoderVideoFrame->append(frame); } diff --git a/ffmpeg/videoformat.hpp b/ffmpeg/videoformat.hpp index b81e645..709229a 100644 --- a/ffmpeg/videoformat.hpp +++ b/ffmpeg/videoformat.hpp @@ -12,21 +12,39 @@ namespace Ffmpeg { namespace VideoFormat { -static const QMap qFormatMaps = { - {AV_PIX_FMT_NONE, QImage::Format_Invalid}, - {AV_PIX_FMT_RGB24, QImage::Format_RGB888}, - {AV_PIX_FMT_BGR24, QImage::Format_BGR888}, - {AV_PIX_FMT_RGB32, QImage::Format_RGB32}, - {AV_PIX_FMT_RGBA, QImage::Format_RGBA8888}, - {AV_PIX_FMT_RGB565BE, QImage::Format_RGB16}, - {AV_PIX_FMT_RGB565LE, QImage::Format_RGB16}, - {AV_PIX_FMT_RGB555BE, QImage::Format_RGB555}, - {AV_PIX_FMT_RGB0, QImage::Format_RGBX8888}, - {AV_PIX_FMT_RGBA64BE, QImage::Format_RGBA64}, - {AV_PIX_FMT_RGBA64LE, QImage::Format_RGBA64}, -}; - -} +// AVPixelFormat convert to QImage::Format conversion table +static const QMap qFormatMaps + = {{AV_PIX_FMT_NONE, QImage::Format_Invalid}, + {AV_PIX_FMT_RGB24, QImage::Format_RGB888}, + {AV_PIX_FMT_BGR24, QImage::Format_RGB888}, + {AV_PIX_FMT_GRAY8, QImage::Format_Grayscale8}, + {AV_PIX_FMT_MONOWHITE, QImage::Format_Mono}, + {AV_PIX_FMT_MONOBLACK, QImage::Format_Mono}, + {AV_PIX_FMT_PAL8, QImage::Format_Indexed8}, + {AV_PIX_FMT_ARGB, QImage::Format_ARGB32}, + {AV_PIX_FMT_RGBA, QImage::Format_RGBA8888}, + {AV_PIX_FMT_ABGR, QImage::Format_RGB32}, + {AV_PIX_FMT_BGRA, QImage::Format_RGB32}, + {AV_PIX_FMT_GRAY16BE, QImage::Format_Grayscale16}, + {AV_PIX_FMT_GRAY16LE, QImage::Format_Grayscale16}, + {AV_PIX_FMT_RGB565BE, QImage::Format_RGB16}, + {AV_PIX_FMT_RGB565LE, QImage::Format_RGB16}, + {AV_PIX_FMT_RGB555BE, QImage::Format_RGB16}, + {AV_PIX_FMT_RGB555LE, QImage::Format_RGB16}, + {AV_PIX_FMT_BGR565BE, QImage::Format_RGB16}, + {AV_PIX_FMT_BGR565LE, QImage::Format_RGB16}, + {AV_PIX_FMT_BGR555BE, QImage::Format_RGB16}, + {AV_PIX_FMT_BGR555LE, QImage::Format_RGB16}, + {AV_PIX_FMT_RGB0, QImage::Format_RGB32}, + {AV_PIX_FMT_BGR0, QImage::Format_RGB32}, + {AV_PIX_FMT_0RGB, QImage::Format_RGB32}, + {AV_PIX_FMT_0BGR, QImage::Format_RGB32}, + {AV_PIX_FMT_RGBA64BE, QImage::Format_RGBA64}, + {AV_PIX_FMT_RGBA64LE, QImage::Format_RGBA64}, + {AV_PIX_FMT_BGRA64BE, QImage::Format_RGBA64}, + {AV_PIX_FMT_BGRA64LE, QImage::Format_RGBA64}}; + +} // namespace VideoFormat } // namespace Ffmpeg diff --git a/ffmpeg/videoframeconverter.cc b/ffmpeg/videoframeconverter.cc index 93ea0c7..7668fa8 100644 --- a/ffmpeg/videoframeconverter.cc +++ b/ffmpeg/videoframeconverter.cc @@ -119,13 +119,13 @@ int VideoFrameConverter::scale(Frame *in, Frame *out) Q_ASSERT(d_ptr->swsContext != nullptr); auto inFrame = in->avFrame(); auto outFrame = out->avFrame(); - int ret = sws_scale(d_ptr->swsContext, - static_cast(inFrame->data), - inFrame->linesize, - 0, - inFrame->height, - outFrame->data, - outFrame->linesize); + auto ret = sws_scale(d_ptr->swsContext, + static_cast(inFrame->data), + inFrame->linesize, + 0, + inFrame->height, + outFrame->data, + outFrame->linesize); if (ret < 0) { d_ptr->setError(ret); } @@ -135,8 +135,6 @@ int VideoFrameConverter::scale(Frame *in, Frame *out) outFrame->pts = inFrame->pts; out->setPts(in->pts()); out->setDuration(in->duration()); - out->setQImageFormat( - VideoFormat::qFormatMaps.value(AVPixelFormat(outFrame->format), QImage::Format_Invalid)); return ret; } diff --git a/ffmpeg/videorender/openglrender.cc b/ffmpeg/videorender/openglrender.cc index 19c5a67..c7e4b85 100644 --- a/ffmpeg/videorender/openglrender.cc +++ b/ffmpeg/videorender/openglrender.cc @@ -92,7 +92,11 @@ QSharedPointer OpenglRender::convertSupported_pix_fmt(QSharedPointerframeConverterPtr->flush(frame.data(), size, dst_pix_fmt); } QSharedPointer frameRgbPtr(new Frame); - frameRgbPtr->imageAlloc(size, dst_pix_fmt); + auto ret = frameRgbPtr->imageAlloc(size, dst_pix_fmt); + if (!ret) { + qWarning() << "imageAlloc failed"; + return QSharedPointer(); + } d_ptr->frameConverterPtr->scale(frame.data(), frameRgbPtr.data()); // qDebug() << frameRgbPtr->avFrame()->width << frameRgbPtr->avFrame()->height // << frameRgbPtr->avFrame()->format; diff --git a/ffmpeg/videorender/videopreviewwidget.cc b/ffmpeg/videorender/videopreviewwidget.cc index 2b973e3..231391c 100644 --- a/ffmpeg/videorender/videopreviewwidget.cc +++ b/ffmpeg/videorender/videopreviewwidget.cc @@ -60,9 +60,12 @@ class PreviewTask : public QRunnable private: void loop(FormatContext *formatContext, AVContextInfo *videoInfo) { - while (m_runing && !m_videoPreviewWidgetPtr.isNull() + while (!m_videoPreviewWidgetPtr.isNull() && m_taskId == m_videoPreviewWidgetPtr->currentTaskId()) { auto framePtr(getKeyFrame(formatContext, videoInfo)); + if (!m_runing) { + return; + } if (framePtr.isNull()) { continue; } @@ -81,7 +84,7 @@ class PreviewTask : public QRunnable frameRgbPtr->imageAlloc(dstSize, dst_pix_fmt); //frameConverterPtr->flush(framePtr.data(), dstSize); frameConverterPtr->scale(framePtr.data(), frameRgbPtr.data()); - auto image = frameRgbPtr->convertToImage(); + auto image = frameRgbPtr->toImage(); if (!m_videoPreviewWidgetPtr.isNull() && m_taskId == m_videoPreviewWidgetPtr->currentTaskId()) { image.setDevicePixelRatio(m_videoPreviewWidgetPtr->devicePixelRatio()); @@ -96,6 +99,7 @@ class PreviewTask : public QRunnable QSharedPointer framePtr; QScopedPointer packetPtr(new Packet); if (!formatContext->readFrame(packetPtr.get()) || m_videoPreviewWidgetPtr.isNull()) { + m_runing = false; return framePtr; } if (!formatContext->checkPktPlayRange(packetPtr.get())) { diff --git a/ffmpeg/videorender/videorender.cc b/ffmpeg/videorender/videorender.cc index c18292d..06ac3d6 100644 --- a/ffmpeg/videorender/videorender.cc +++ b/ffmpeg/videorender/videorender.cc @@ -61,7 +61,7 @@ void VideoRender::setImage(const QImage &image) if (image.isNull()) { return; } - QSharedPointer frame(new Frame(image)); + QSharedPointer frame(Frame::fromQImage(image)); setFrame(frame); } diff --git a/ffmpeg/videorender/widgetrender.cc b/ffmpeg/videorender/widgetrender.cc index 826314b..615543f 100644 --- a/ffmpeg/videorender/widgetrender.cc +++ b/ffmpeg/videorender/widgetrender.cc @@ -138,7 +138,7 @@ void WidgetRender::updateSubTitleFrame(QSharedPointer frame) void WidgetRender::displayFrame(QSharedPointer framePtr) { d_ptr->framePtr = framePtr; - d_ptr->videoImage = framePtr->convertToImage(); + d_ptr->videoImage = framePtr->toImage(); d_ptr->videoImage.setDevicePixelRatio(devicePixelRatio()); update(); } diff --git a/utils/countdownlatch.hpp b/utils/countdownlatch.hpp index 155218f..eed7e6f 100644 --- a/utils/countdownlatch.hpp +++ b/utils/countdownlatch.hpp @@ -11,7 +11,7 @@ class UTILS_EXPORT CountDownLatch { Q_DISABLE_COPY_MOVE(CountDownLatch) public: - CountDownLatch(int count); + explicit CountDownLatch(int count); ~CountDownLatch(); void wait();