20#include <freerdp/config.h>
22#if defined(WITH_SWSCALE) && defined(WITH_SWSCALE_LOADING)
24#include <winpr/library.h>
25#include <winpr/assert.h>
26#include <freerdp/log.h>
28#include "image_ffmpeg.h"
30#if !defined(__has_include)
31#define __has_include(x) 0
34#if __has_include(<libswscale/version.h>)
35#include <libswscale/version.h>
38#if __has_include(<libavutil/version.h>)
39#include <libavutil/version.h>
42#define TAG FREERDP_TAG("codec.image")
44typedef struct SwsContext* (*pSws_getContext)(
int srcW,
int srcH,
int srcFormat,
int dstW,
int dstH,
45 int dstFormat,
int flags,
void* srcFilter,
46 void* dstFilter,
const double* param);
47typedef int (*pSws_scale)(
struct SwsContext* c,
const uint8_t*
const srcSlice[],
48 const int srcStride[],
int srcSliceY,
int srcSliceH, uint8_t*
const dst[],
49 const int dstStride[]);
50typedef void (*pSws_freeContext)(
struct SwsContext* c);
51typedef int (*pAv_image_fill_linesizes)(
int linesizes[4],
int pix_fmt,
int width);
52typedef int (*pAv_image_fill_pointers)(uint8_t* data[4],
int pix_fmt,
int height, uint8_t* ptr,
53 const int linesizes[4]);
58 pSws_getContext getContext;
60 pSws_freeContext freeContext;
68 pAv_image_fill_linesizes fill_linesizes;
69 pAv_image_fill_pointers fill_pointers;
74static SWSCALE_LIBRARY g_swscale = WINPR_C_ARRAY_INIT;
75static AVUTIL_LIBRARY g_avutil = WINPR_C_ARRAY_INIT;
77#define STRINGIFY(x) #x
78#define TOSTRING(x) STRINGIFY(x)
80#if defined(LIBSWSCALE_VERSION_MAJOR)
81#define SWSCALE_VERSION_STR TOSTRING(LIBSWSCALE_VERSION_MAJOR)
84static const char* swscale_library_names[] = {
86#if defined(SWSCALE_VERSION_STR)
87 "swscale-" SWSCALE_VERSION_STR
".dll",
94#elif defined(__APPLE__)
95#if defined(SWSCALE_VERSION_STR)
96 "libswscale." SWSCALE_VERSION_STR
".dylib",
100 "libswscale.8.dylib",
101 "libswscale.7.dylib",
104#if defined(SWSCALE_VERSION_STR)
105 "libswscale.so." SWSCALE_VERSION_STR,
115static BOOL swscale_load_library(
const char* name)
119 WLog_DBG(TAG,
"Attempting to load swscale library: %s", name);
121 g_swscale.lib = LoadLibraryA(name);
124 WLog_DBG(TAG,
"Failed to load %s", name);
128 g_swscale.getContext = (pSws_getContext)(
void*)GetProcAddress(g_swscale.lib,
"sws_getContext");
129 g_swscale.scale = (pSws_scale)(
void*)GetProcAddress(g_swscale.lib,
"sws_scale");
130 g_swscale.freeContext =
131 (pSws_freeContext)(
void*)GetProcAddress(g_swscale.lib,
"sws_freeContext");
133 if (!g_swscale.getContext || !g_swscale.scale || !g_swscale.freeContext)
135 WLog_WARN(TAG,
"Failed to load required functions from %s", name);
136 FreeLibrary(g_swscale.lib);
137 g_swscale.lib =
nullptr;
141 WLog_INFO(TAG,
"Successfully loaded swscale library: %s", name);
145BOOL freerdp_swscale_init(
void)
147 if (g_swscale.initialized)
148 return g_swscale.available;
150 g_swscale.initialized = TRUE;
151 g_swscale.available = FALSE;
153 WLog_DBG(TAG,
"Searching for swscale library in default locations");
154 for (
size_t i = 0; i < ARRAYSIZE(swscale_library_names); i++)
156 if (swscale_load_library(swscale_library_names[i]))
158 g_swscale.available = TRUE;
163 WLog_INFO(TAG,
"swscale library not found");
168BOOL freerdp_swscale_available(
void)
170 return freerdp_swscale_init() && g_swscale.available;
173struct SwsContext* freerdp_sws_getContext(
int srcW,
int srcH,
int srcFormat,
int dstW,
int dstH,
174 int dstFormat,
int flags,
void* srcFilter,
175 void* dstFilter,
const double* param)
177 if (!freerdp_swscale_available())
179 WLog_WARN(TAG,
"sws_getContext called but swscale not available");
183 WINPR_ASSERT(g_swscale.getContext);
184 return g_swscale.getContext(srcW, srcH, srcFormat, dstW, dstH, dstFormat, flags, srcFilter,
188int freerdp_sws_scale(
struct SwsContext* ctx,
const uint8_t*
const srcSlice[],
189 const int srcStride[],
int srcSliceY,
int srcSliceH, uint8_t*
const dst[],
190 const int dstStride[])
192 if (!freerdp_swscale_available())
194 WLog_WARN(TAG,
"sws_scale called but swscale not available");
200 WLog_WARN(TAG,
"sws_scale called with nullptr context");
204 WINPR_ASSERT(g_swscale.scale);
205 return g_swscale.scale(ctx, srcSlice, srcStride, srcSliceY, srcSliceH, dst, dstStride);
208void freerdp_sws_freeContext(
struct SwsContext* ctx)
210 if (!freerdp_swscale_available())
216 WINPR_ASSERT(g_swscale.freeContext);
217 g_swscale.freeContext(ctx);
224#if defined(LIBAVUTIL_VERSION_MAJOR)
225#define AVUTIL_VERSION_STR TOSTRING(LIBAVUTIL_VERSION_MAJOR)
228static const char* avutil_library_names[] = {
230#if defined(AVUTIL_VERSION_STR)
231 "avutil-" AVUTIL_VERSION_STR
".dll",
238#elif defined(__APPLE__)
239#if defined(AVUTIL_VERSION_STR)
240 "libavutil." AVUTIL_VERSION_STR
".dylib",
243 "libavutil.59.dylib",
244 "libavutil.58.dylib",
245 "libavutil.57.dylib",
248#if defined(AVUTIL_VERSION_STR)
249 "libavutil.so." AVUTIL_VERSION_STR,
259static BOOL avutil_load_library(
const char* name)
263 WLog_DBG(TAG,
"Attempting to load avutil library: %s", name);
265 g_avutil.lib = LoadLibraryA(name);
268 WLog_DBG(TAG,
"Failed to load %s", name);
272 g_avutil.fill_linesizes =
273 (pAv_image_fill_linesizes)(
void*)GetProcAddress(g_avutil.lib,
"av_image_fill_linesizes");
274 g_avutil.fill_pointers =
275 (pAv_image_fill_pointers)(
void*)GetProcAddress(g_avutil.lib,
"av_image_fill_pointers");
277 if (!g_avutil.fill_linesizes || !g_avutil.fill_pointers)
279 WLog_WARN(TAG,
"Failed to load required functions from %s", name);
280 FreeLibrary(g_avutil.lib);
281 g_avutil.lib =
nullptr;
285 WLog_INFO(TAG,
"Successfully loaded avutil library: %s", name);
289BOOL freerdp_avutil_init(
void)
291 if (g_avutil.initialized)
292 return g_avutil.available;
294 g_avutil.initialized = TRUE;
295 g_avutil.available = FALSE;
297 WLog_DBG(TAG,
"Searching for avutil library in default locations");
298 for (
size_t i = 0; i < ARRAYSIZE(avutil_library_names); i++)
300 if (avutil_load_library(avutil_library_names[i]))
302 g_avutil.available = TRUE;
307 WLog_INFO(TAG,
"avutil library not found");
312BOOL freerdp_avutil_available(
void)
314 return freerdp_avutil_init() && g_avutil.available;
317int freerdp_av_image_fill_linesizes(
int linesizes[4],
int pix_fmt,
int width)
319 if (!freerdp_avutil_available())
321 WLog_WARN(TAG,
"av_image_fill_linesizes called but avutil not available");
325 WINPR_ASSERT(g_avutil.fill_linesizes);
326 return g_avutil.fill_linesizes(linesizes, pix_fmt, width);
329int freerdp_av_image_fill_pointers(uint8_t* data[4],
int pix_fmt,
int height, uint8_t* ptr,
330 const int linesizes[4])
332 if (!freerdp_avutil_available())
334 WLog_WARN(TAG,
"av_image_fill_pointers called but avutil not available");
338 WINPR_ASSERT(g_avutil.fill_pointers);
339 return g_avutil.fill_pointers(data, pix_fmt, height, ptr, linesizes);