Commit efb048c2 for libheif

commit efb048c25e583655496e47a52eb9eb283a5be8da
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Mon Sep 21 18:47:06 2026 +0200

    FFmpeg decoder plugin: do not reference the exported heif_error_success object (#1854)

    Dynamic plugins are compiled with LIBHEIF_EXPORTS, so inside plugin code
    LIBHEIF_API expands to __declspec(dllexport) on MSVC. Exported functions
    still resolve through the import library's jump thunks, but exported data
    has no thunk, and the reference to heif_error_success in the FFmpeg decoder
    and in nalu_utils.cc fails to link when the decoder is built as a plugin.
    On Linux this went unnoticed because the loader resolves the symbol from
    libheif at dlopen time.

    Use a file-local success object instead, as the other plugins do.
    nalu_utils.cc is compiled into both libheif and the plugin, so it gets its
    own local object rather than depending on heif_plugin.h.

    Fixes #1854

diff --git a/libheif/plugins/decoder_ffmpeg.cc b/libheif/plugins/decoder_ffmpeg.cc
index 58634ec1..27fcac48 100644
--- a/libheif/plugins/decoder_ffmpeg.cc
+++ b/libheif/plugins/decoder_ffmpeg.cc
@@ -42,6 +42,11 @@ extern "C"
 }


+// Plugins are compiled with LIBHEIF_EXPORTS, so on MSVC a reference to the exported
+// data object heif_error_success does not resolve against libheif (issue #1854).
+// Use a file-local success object instead.
+static const heif_error kSuccess = {heif_error_Ok, heif_suberror_Unspecified, "Success"};
+
 struct ffmpeg_decoder
 {
   // --- input data
@@ -198,7 +203,7 @@ static heif_error ffmpeg_new_decoder2(void** dec, const heif_decoder_plugin_opti
   }


-  return heif_error_success;
+  return kSuccess;
 }

 static heif_error ffmpeg_new_decoder(void** dec)
@@ -333,7 +338,7 @@ static heif_error ffmpeg_push_data2(void *decoder_raw, const void *data, size_t

   decoder->input_data.emplace_back(std::move(pkt));

-  return heif_error_success;
+  return kSuccess;
 }

 static heif_error ffmpeg_push_data(void *decoder_raw, const void *data, size_t size)
@@ -607,7 +612,7 @@ static heif_error ffmpeg_av_decode(ffmpeg_decoder* decoder, AVCodecContext* av_d
                           av_frame->width, av_frame->height, shift, byte_swap);
     }

-    return heif_error_success;
+    return kSuccess;
   }

   heif_chroma chroma = ffmpeg_get_chroma_format(pix_fmt);
@@ -680,7 +685,7 @@ static heif_error ffmpeg_av_decode(ffmpeg_decoder* decoder, AVCodecContext* av_d
                           w, h, shift, byte_swap);
     }

-    return heif_error_success;
+    return kSuccess;
   }
   else {
     const char* fmt_name = av_get_pix_fmt_name(static_cast<AVPixelFormat>(av_frame->format));
@@ -707,7 +712,7 @@ static heif_error ffmpeg_decode_next_image2(void* decoder_raw,
   heif_color_profile_nclx* nclx = NULL;
   int ret = 0;

-  heif_error err = heif_error_success;
+  heif_error err = kSuccess;

   if (!decoder->input_data.empty()) {
     uint8_t* parse_av_data = NULL;
diff --git a/libheif/plugins/nalu_utils.cc b/libheif/plugins/nalu_utils.cc
index f4f3731d..b5369dde 100644
--- a/libheif/plugins/nalu_utils.cc
+++ b/libheif/plugins/nalu_utils.cc
@@ -23,6 +23,11 @@
 #include <utility>
 #include "nalu_utils.h"

+// Plugins are compiled with LIBHEIF_EXPORTS, so on MSVC a reference to the exported
+// data object heif_error_success does not resolve against libheif (issue #1854).
+// Use a file-local success object instead.
+static const heif_error kSuccess = {heif_error_Ok, heif_suberror_Unspecified, "Success"};
+
 NalUnit::NalUnit()
 {
     nal_data_ptr = NULL;
@@ -91,7 +96,7 @@ const heif_error NalMap::parseHevcNalu(const uint8_t *cdata, size_t size)
         ptr += nal_size;
     }

-    return heif_error_success;
+    return kSuccess;
 }

 void NalMap::clear() { map.clear(); }
\ No newline at end of file