mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-06-03 17:08:08 -04:00
heif: use heif_init/heif_deinit with libheif 1.13.0+
In recent libheif, application should use heif_init/heif_deinit calls. Unfortunately, these calls are not thread-safe in released 1.13.0 version yet (will be in the future) and HEIFHandler is often created in different threads. So we have to guard their use with a mutex.
This commit is contained in:
parent
20f74ce5e6
commit
9ab64dbf22
@ -52,6 +52,11 @@ private:
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
size_t HEIFHandler::m_initialized_count = 0;
|
||||||
|
bool HEIFHandler::m_plugins_queried = false;
|
||||||
|
bool HEIFHandler::m_heif_decoder_available = false;
|
||||||
|
bool HEIFHandler::m_heif_encoder_available = false;
|
||||||
|
|
||||||
HEIFHandler::HEIFHandler()
|
HEIFHandler::HEIFHandler()
|
||||||
: m_parseState(ParseHeicNotParsed)
|
: m_parseState(ParseHeicNotParsed)
|
||||||
, m_quality(100)
|
, m_quality(100)
|
||||||
@ -88,6 +93,21 @@ bool HEIFHandler::write(const QImage &image)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||||
|
startHeifLib();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool success = write_helper(image);
|
||||||
|
|
||||||
|
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||||
|
finishHeifLib();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HEIFHandler::write_helper(const QImage &image)
|
||||||
|
{
|
||||||
int save_depth; // 8 or 10bit per channel
|
int save_depth; // 8 or 10bit per channel
|
||||||
QImage::Format tmpformat; // format for temporary image
|
QImage::Format tmpformat; // format for temporary image
|
||||||
const bool save_alpha = image.hasAlphaChannel();
|
const bool save_alpha = image.hasAlphaChannel();
|
||||||
@ -356,8 +376,18 @@ bool HEIFHandler::ensureParsed() const
|
|||||||
|
|
||||||
HEIFHandler *that = const_cast<HEIFHandler *>(this);
|
HEIFHandler *that = const_cast<HEIFHandler *>(this);
|
||||||
|
|
||||||
return that->ensureDecoder();
|
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||||
|
startHeifLib();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool success = that->ensureDecoder();
|
||||||
|
|
||||||
|
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||||
|
finishHeifLib();
|
||||||
|
#endif
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HEIFHandler::ensureDecoder()
|
bool HEIFHandler::ensureDecoder()
|
||||||
{
|
{
|
||||||
if (m_parseState != ParseHeicNotParsed) {
|
if (m_parseState != ParseHeicNotParsed) {
|
||||||
@ -696,14 +726,100 @@ bool HEIFHandler::ensureDecoder()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HEIFHandler::isHeifDecoderAvailable()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&getHEIFHandlerMutex());
|
||||||
|
|
||||||
|
if (!m_plugins_queried) {
|
||||||
|
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||||
|
if (m_initialized_count == 0) {
|
||||||
|
heif_init(nullptr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_heif_encoder_available = heif_have_encoder_for_format(heif_compression_HEVC);
|
||||||
|
m_heif_decoder_available = heif_have_decoder_for_format(heif_compression_HEVC);
|
||||||
|
m_plugins_queried = true;
|
||||||
|
|
||||||
|
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||||
|
if (m_initialized_count == 0) {
|
||||||
|
heif_deinit();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_heif_decoder_available;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HEIFHandler::isHeifEncoderAvailable()
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&getHEIFHandlerMutex());
|
||||||
|
|
||||||
|
if (!m_plugins_queried) {
|
||||||
|
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||||
|
if (m_initialized_count == 0) {
|
||||||
|
heif_init(nullptr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_heif_decoder_available = heif_have_decoder_for_format(heif_compression_HEVC);
|
||||||
|
m_heif_encoder_available = heif_have_encoder_for_format(heif_compression_HEVC);
|
||||||
|
m_plugins_queried = true;
|
||||||
|
|
||||||
|
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||||
|
if (m_initialized_count == 0) {
|
||||||
|
heif_deinit();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_heif_encoder_available;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HEIFHandler::startHeifLib()
|
||||||
|
{
|
||||||
|
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||||
|
QMutexLocker locker(&getHEIFHandlerMutex());
|
||||||
|
|
||||||
|
if (m_initialized_count == 0) {
|
||||||
|
heif_init(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_initialized_count++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void HEIFHandler::finishHeifLib()
|
||||||
|
{
|
||||||
|
#if LIBHEIF_HAVE_VERSION(1, 13, 0)
|
||||||
|
QMutexLocker locker(&getHEIFHandlerMutex());
|
||||||
|
|
||||||
|
if (m_initialized_count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_initialized_count--;
|
||||||
|
if (m_initialized_count == 0) {
|
||||||
|
heif_deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
QMutex &HEIFHandler::getHEIFHandlerMutex()
|
||||||
|
{
|
||||||
|
static QMutex heif_handler_mutex;
|
||||||
|
return heif_handler_mutex;
|
||||||
|
}
|
||||||
|
|
||||||
QImageIOPlugin::Capabilities HEIFPlugin::capabilities(QIODevice *device, const QByteArray &format) const
|
QImageIOPlugin::Capabilities HEIFPlugin::capabilities(QIODevice *device, const QByteArray &format) const
|
||||||
{
|
{
|
||||||
if (format == "heif" || format == "heic") {
|
if (format == "heif" || format == "heic") {
|
||||||
Capabilities format_cap;
|
Capabilities format_cap;
|
||||||
if (heif_have_decoder_for_format(heif_compression_HEVC)) {
|
if (HEIFHandler::isHeifDecoderAvailable()) {
|
||||||
format_cap |= CanRead;
|
format_cap |= CanRead;
|
||||||
}
|
}
|
||||||
if (heif_have_encoder_for_format(heif_compression_HEVC)) {
|
if (HEIFHandler::isHeifEncoderAvailable()) {
|
||||||
format_cap |= CanWrite;
|
format_cap |= CanWrite;
|
||||||
}
|
}
|
||||||
return format_cap;
|
return format_cap;
|
||||||
@ -716,11 +832,11 @@ QImageIOPlugin::Capabilities HEIFPlugin::capabilities(QIODevice *device, const Q
|
|||||||
}
|
}
|
||||||
|
|
||||||
Capabilities cap;
|
Capabilities cap;
|
||||||
if (device->isReadable() && HEIFHandler::canRead(device) && heif_have_decoder_for_format(heif_compression_HEVC)) {
|
if (device->isReadable() && HEIFHandler::canRead(device) && HEIFHandler::isHeifDecoderAvailable()) {
|
||||||
cap |= CanRead;
|
cap |= CanRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device->isWritable() && heif_have_encoder_for_format(heif_compression_HEVC)) {
|
if (device->isWritable() && HEIFHandler::isHeifEncoderAvailable()) {
|
||||||
cap |= CanWrite;
|
cap |= CanWrite;
|
||||||
}
|
}
|
||||||
return cap;
|
return cap;
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QImageIOPlugin>
|
#include <QImageIOPlugin>
|
||||||
|
#include <QMutex>
|
||||||
|
|
||||||
class HEIFHandler : public QImageIOHandler
|
class HEIFHandler : public QImageIOHandler
|
||||||
{
|
{
|
||||||
@ -29,6 +30,9 @@ public:
|
|||||||
void setOption(ImageOption option, const QVariant &value) override;
|
void setOption(ImageOption option, const QVariant &value) override;
|
||||||
bool supportsOption(ImageOption option) const override;
|
bool supportsOption(ImageOption option) const override;
|
||||||
|
|
||||||
|
static bool isHeifDecoderAvailable();
|
||||||
|
static bool isHeifEncoderAvailable();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool isSupportedBMFFType(const QByteArray &header);
|
static bool isSupportedBMFFType(const QByteArray &header);
|
||||||
bool ensureParsed() const;
|
bool ensureParsed() const;
|
||||||
@ -43,6 +47,18 @@ private:
|
|||||||
ParseHeicState m_parseState;
|
ParseHeicState m_parseState;
|
||||||
int m_quality;
|
int m_quality;
|
||||||
QImage m_current_image;
|
QImage m_current_image;
|
||||||
|
|
||||||
|
bool write_helper(const QImage &image);
|
||||||
|
|
||||||
|
static void startHeifLib();
|
||||||
|
static void finishHeifLib();
|
||||||
|
static size_t m_initialized_count;
|
||||||
|
|
||||||
|
static bool m_plugins_queried;
|
||||||
|
static bool m_heif_decoder_available;
|
||||||
|
static bool m_heif_encoder_available;
|
||||||
|
|
||||||
|
static QMutex &getHEIFHandlerMutex();
|
||||||
};
|
};
|
||||||
|
|
||||||
class HEIFPlugin : public QImageIOPlugin
|
class HEIFPlugin : public QImageIOPlugin
|
||||||
|
Loading…
x
Reference in New Issue
Block a user