Coverage Report

Created: 2026-05-24 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libheif/libheif/plugin_registry.cc
Line
Count
Source
1
/*
2
 * HEIF codec.
3
 * Copyright (c) 2017 Dirk Farin <dirk.farin@gmail.com>
4
 *
5
 * This file is part of libheif.
6
 *
7
 * libheif is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Lesser General Public License as
9
 * published by the Free Software Foundation, either version 3 of
10
 * the License, or (at your option) any later version.
11
 *
12
 * libheif is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public License
18
 * along with libheif.  If not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
#include <utility>
22
#include <cstring>
23
#include <algorithm>
24
25
#include "plugin_registry.h"
26
#include "init.h"
27
28
#if HAVE_WEBCODECS
29
#include "plugins/decoder_webcodecs.h"
30
#endif
31
32
#if HAVE_LIBDE265
33
#include "plugins/decoder_libde265.h"
34
#endif
35
36
#if HAVE_X265
37
#include "plugins/encoder_x265.h"
38
#endif
39
40
#if HAVE_KVAZAAR
41
#include "plugins/encoder_kvazaar.h"
42
#endif
43
44
#if HAVE_UVG266
45
#include "plugins/encoder_uvg266.h"
46
#endif
47
48
#if HAVE_VVDEC
49
#include "plugins/decoder_vvdec.h"
50
#endif
51
52
#if HAVE_VVENC
53
#include "plugins/encoder_vvenc.h"
54
#endif
55
56
#if HAVE_AOM_ENCODER
57
#include "plugins/encoder_aom.h"
58
#endif
59
60
#if HAVE_AOM_DECODER
61
#include "plugins/decoder_aom.h"
62
#endif
63
64
#if HAVE_RAV1E
65
#include "plugins/encoder_rav1e.h"
66
#endif
67
68
#if HAVE_DAV1D
69
#include "plugins/decoder_dav1d.h"
70
#endif
71
72
#if HAVE_SvtEnc
73
#include "plugins/encoder_svt.h"
74
#endif
75
76
#if HAVE_FFMPEG_DECODER
77
#include "plugins/decoder_ffmpeg.h"
78
#endif
79
80
#if WITH_UNCOMPRESSED_CODEC
81
#include "plugins/encoder_uncompressed.h"
82
#include "plugins/decoder_uncompressed.h"
83
#endif
84
85
#if HAVE_JPEG_DECODER
86
#include "plugins/decoder_jpeg.h"
87
#endif
88
89
#if HAVE_JPEG_ENCODER
90
#include "plugins/encoder_jpeg.h"
91
#endif
92
93
#if HAVE_X264
94
#include "plugins/encoder_x264.h"
95
#endif
96
97
#if HAVE_OpenH264_DECODER
98
#include "plugins/decoder_openh264.h"
99
#endif
100
101
#if HAVE_OPENJPEG_ENCODER
102
#include "plugins/encoder_openjpeg.h"
103
#endif
104
105
#if HAVE_OPENJPEG_DECODER
106
#include "plugins/decoder_openjpeg.h"
107
#endif
108
109
#include "plugins/encoder_mask.h"
110
111
#if HAVE_OPENJPH_ENCODER
112
#include "plugins/encoder_openjph.h"
113
#endif
114
115
std::set<const heif_decoder_plugin*> s_decoder_plugins;
116
117
std::multiset<std::unique_ptr<heif_encoder_descriptor>,
118
              encoder_descriptor_priority_order> s_encoder_descriptors;
119
120
std::set<const heif_decoder_plugin*>& get_decoder_plugins()
121
36
{
122
36
  load_plugins_if_not_initialized_yet();
123
124
36
  return s_decoder_plugins;
125
36
}
126
127
extern std::multiset<std::unique_ptr<heif_encoder_descriptor>,
128
                     encoder_descriptor_priority_order>& get_encoder_descriptors()
129
0
{
130
0
  load_plugins_if_not_initialized_yet();
131
132
0
  return s_encoder_descriptors;
133
0
}
134
135
136
// Note: we cannot move this to 'heif_init' because we have to make sure that this is initialized
137
// AFTER the two global std::set above.
138
static class Register_Default_Plugins
139
{
140
public:
141
  Register_Default_Plugins()
142
254
  {
143
254
    register_default_plugins();
144
254
  }
145
} dummy;
146
147
148
void register_default_plugins()
149
254
{
150
#if HAVE_WEBCODECS
151
  register_decoder(get_decoder_plugin_webcodecs());
152
#endif
153
154
254
#if HAVE_LIBDE265
155
254
  register_decoder(get_decoder_plugin_libde265());
156
254
#endif
157
158
254
#if HAVE_X265
159
254
  register_encoder(get_encoder_plugin_x265());
160
254
#endif
161
162
#if HAVE_KVAZAAR
163
  register_encoder(get_encoder_plugin_kvazaar());
164
#endif
165
166
#if HAVE_UVG266
167
  register_encoder(get_encoder_plugin_uvg266());
168
#endif
169
170
254
#if HAVE_VVENC
171
254
  register_encoder(get_encoder_plugin_vvenc());
172
254
#endif
173
174
254
#if HAVE_VVDEC
175
254
  register_decoder(get_decoder_plugin_vvdec());
176
254
#endif
177
178
254
#if HAVE_AOM_ENCODER
179
254
  register_encoder(get_encoder_plugin_aom());
180
254
#endif
181
182
254
#if HAVE_AOM_DECODER
183
254
  register_decoder(get_decoder_plugin_aom());
184
254
#endif
185
186
#if HAVE_RAV1E
187
  register_encoder(get_encoder_plugin_rav1e());
188
#endif
189
190
254
#if HAVE_DAV1D
191
254
  register_decoder(get_decoder_plugin_dav1d());
192
254
#endif
193
194
#if HAVE_SvtEnc
195
  register_encoder(get_encoder_plugin_svt());
196
#endif
197
198
#if HAVE_FFMPEG_DECODER
199
  register_decoder(get_decoder_plugin_ffmpeg());
200
#endif
201
202
254
#if HAVE_JPEG_DECODER
203
254
  register_decoder(get_decoder_plugin_jpeg());
204
254
#endif
205
206
254
#if HAVE_JPEG_ENCODER
207
254
  register_encoder(get_encoder_plugin_jpeg());
208
254
#endif
209
210
254
#if HAVE_OPENJPEG_ENCODER
211
254
  register_encoder(get_encoder_plugin_openjpeg());
212
254
#endif
213
214
254
#if HAVE_OPENJPEG_DECODER
215
254
  register_decoder(get_decoder_plugin_openjpeg());
216
254
#endif
217
218
254
#if HAVE_OPENJPH_ENCODER
219
254
  register_encoder(get_encoder_plugin_openjph());
220
254
#endif
221
222
254
#if HAVE_OpenH264_DECODER
223
254
  register_decoder(get_decoder_plugin_openh264());
224
254
#endif
225
226
254
#if HAVE_X264
227
254
  register_encoder(get_encoder_plugin_x264());
228
254
#endif
229
230
254
#if WITH_UNCOMPRESSED_CODEC
231
254
  register_encoder(get_encoder_plugin_uncompressed());
232
254
  register_decoder(get_decoder_plugin_uncompressed());
233
254
#endif
234
235
254
  register_encoder(get_encoder_plugin_mask());
236
254
}
237
238
239
void register_decoder(const heif_decoder_plugin* decoder_plugin)
240
2.03k
{
241
2.03k
  if (decoder_plugin->init_plugin) {
242
1.77k
    (*decoder_plugin->init_plugin)();
243
1.77k
  }
244
245
2.03k
  s_decoder_plugins.insert(decoder_plugin);
246
2.03k
}
247
248
249
bool has_decoder(heif_compression_format type, const char* name_id)
250
0
{
251
0
  load_plugins_if_not_initialized_yet();
252
253
0
  for (const auto* plugin : s_decoder_plugins) {
254
0
    int priority = plugin->does_support_format(type);
255
0
    if (priority > 0 && strcmp(name_id, plugin->id_name) == 0) {
256
0
      return true;
257
0
    }
258
0
  }
259
260
0
  return false;
261
0
}
262
263
264
const heif_decoder_plugin* get_decoder(heif_compression_format type, const char* name_id)
265
48.4k
{
266
48.4k
  load_plugins_if_not_initialized_yet();
267
268
48.4k
  int highest_priority = 0;
269
48.4k
  const struct heif_decoder_plugin* best_plugin = nullptr;
270
271
387k
  for (const auto* plugin : s_decoder_plugins) {
272
273
387k
    int priority = plugin->does_support_format(type);
274
275
387k
    if (priority > 0 && name_id && plugin->plugin_api_version >= 3) {
276
0
      if (strcmp(name_id, plugin->id_name) == 0) {
277
0
        return plugin;
278
0
      }
279
0
    }
280
281
387k
    if (priority > highest_priority) {
282
48.4k
      highest_priority = priority;
283
48.4k
      best_plugin = plugin;
284
48.4k
    }
285
387k
  }
286
287
48.4k
  return best_plugin;
288
48.4k
}
289
290
291
void register_encoder(const heif_encoder_plugin* encoder_plugin)
292
2.28k
{
293
2.28k
  if (encoder_plugin->init_plugin) {
294
2.28k
    (*encoder_plugin->init_plugin)();
295
2.28k
  }
296
297
2.28k
  auto descriptor = std::unique_ptr<heif_encoder_descriptor>(new heif_encoder_descriptor);
298
2.28k
  descriptor->plugin = encoder_plugin;
299
300
2.28k
  s_encoder_descriptors.insert(std::move(descriptor));
301
2.28k
}
302
303
304
const heif_encoder_plugin* get_encoder(heif_compression_format type)
305
0
{
306
0
  auto filtered_encoder_descriptors = get_filtered_encoder_descriptors(type, nullptr);
307
0
  if (filtered_encoder_descriptors.size() > 0) {
308
0
    return filtered_encoder_descriptors[0]->plugin;
309
0
  }
310
0
  else {
311
0
    return nullptr;
312
0
  }
313
0
}
314
315
316
std::vector<const heif_encoder_descriptor*>
317
get_filtered_encoder_descriptors(heif_compression_format format,
318
                                 const char* name)
319
0
{
320
0
  load_plugins_if_not_initialized_yet();
321
322
0
  std::vector<const heif_encoder_descriptor*> filtered_descriptors;
323
324
0
  for (const auto& descr : s_encoder_descriptors) {
325
0
    const heif_encoder_plugin* plugin = descr->plugin;
326
327
0
    if (plugin->compression_format == format || format == heif_compression_undefined) {
328
0
      if (name == nullptr || strcmp(name, plugin->id_name) == 0) {
329
0
        filtered_descriptors.push_back(descr.get());
330
0
      }
331
0
    }
332
0
  }
333
334
335
  // Note: since our std::set<> is ordered by priority, we do not have to sort our output
336
337
0
  return filtered_descriptors;
338
0
}
339
340
341
void heif_unregister_decoder_plugins()
342
0
{
343
0
  for (const auto* plugin : s_decoder_plugins) {
344
0
    if (plugin->deinit_plugin) {
345
0
      (*plugin->deinit_plugin)();
346
0
    }
347
0
  }
348
0
  s_decoder_plugins.clear();
349
0
}
350
351
void heif_unregister_encoder_plugins()
352
0
{
353
0
  for (const auto& plugin : s_encoder_descriptors) {
354
0
    if (plugin->plugin->cleanup_plugin) {
355
0
      (*plugin->plugin->cleanup_plugin)();
356
0
    }
357
0
  }
358
0
  s_encoder_descriptors.clear();
359
0
}
360
361
#if ENABLE_PLUGIN_LOADING
362
void heif_unregister_encoder_plugin(const heif_encoder_plugin* plugin)
363
{
364
  if (plugin->cleanup_plugin) {
365
    (*plugin->cleanup_plugin)();
366
  }
367
368
  for (auto iter = s_encoder_descriptors.begin() ; iter != s_encoder_descriptors.end(); ++iter) {
369
    if ((*iter)->plugin == plugin) {
370
      s_encoder_descriptors.erase(iter);
371
      return;
372
    }
373
  }
374
}
375
#endif