diff --git a/doc/APIchanges b/doc/APIchanges
index 1a9f0a303e..c3a1649079 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -14,6 +14,9 @@ libavutil:     2021-04-27
 
 API changes, most recent first:
 
+2022-xx-xx - xxxxxxxxx - lavu 57.xx.xxx - avutil.h
+  Deprecate av_fopen_utf8() without replacement.
+
 2022-03-16 - xxxxxxxxxx - all libraries - version_major.h
   Add lib<name>/version_major.h as new installed headers, which only
   contain the major version number (and corresponding API deprecation
diff --git a/fftools/fopen_utf8.h b/fftools/fopen_utf8.h
index db57fcaec4..cd18fe8ce1 100644
--- a/fftools/fopen_utf8.h
+++ b/fftools/fopen_utf8.h
@@ -21,7 +21,7 @@
 
 #include <stdio.h>
 
-/* The fopen_utf8 function here is essentially equivalent to av_fopen_utf8,
+/* The fopen_utf8 function here is essentially equivalent to avpriv_fopen_utf8,
  * except that it doesn't set O_CLOEXEC, and that it isn't exported
  * from a different library. (On Windows, each DLL might use a different
  * CRT, and FILE* handles can't be shared across them.) */
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index ee2ea51e69..78ccfa37d3 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -23,6 +23,7 @@ OBJS = allfilters.o                                                     \
        version.o                                                        \
        video.o                                                          \
 
+OBJS-$(HAVE_LIBC_MSVCRT)                     += file_open.o
 OBJS-$(HAVE_THREADS)                         += pthread.o
 
 # subsystems
diff --git a/libavfilter/file_open.c b/libavfilter/file_open.c
new file mode 100644
index 0000000000..494a5d37a4
--- /dev/null
+++ b/libavfilter/file_open.c
@@ -0,0 +1 @@
+#include "libavutil/file_open.c"
diff --git a/libavutil/avutil.h b/libavutil/avutil.h
index 4d633156d1..64b68bdbd3 100644
--- a/libavutil/avutil.h
+++ b/libavutil/avutil.h
@@ -331,12 +331,18 @@ unsigned av_int_list_length_for_size(unsigned elsize,
 #define av_int_list_length(list, term) \
     av_int_list_length_for_size(sizeof(*(list)), list, term)
 
+#if FF_API_AV_FOPEN_UTF8
 /**
  * Open a file using a UTF-8 filename.
  * The API of this function matches POSIX fopen(), errors are returned through
  * errno.
+ * @deprecated Avoid using it, as on Windows, the FILE* allocated by this
+ *             function may be allocated with a different CRT than the caller
+ *             who uses the FILE*. No replacement provided in public API.
  */
+attribute_deprecated
 FILE *av_fopen_utf8(const char *path, const char *mode);
+#endif
 
 /**
  * Return the fractional representation of the internal time base.
diff --git a/libavutil/file_open.c b/libavutil/file_open.c
index cc302f2f76..fb64c2e4ee 100644
--- a/libavutil/file_open.c
+++ b/libavutil/file_open.c
@@ -155,7 +155,7 @@ int avpriv_tempfile(const char *prefix, char **filename, int log_offset, void *l
     return fd; /* success */
 }
 
-FILE *av_fopen_utf8(const char *path, const char *mode)
+FILE *avpriv_fopen_utf8(const char *path, const char *mode)
 {
     int fd;
     int access;
@@ -188,3 +188,10 @@ FILE *av_fopen_utf8(const char *path, const char *mode)
         return NULL;
     return fdopen(fd, mode);
 }
+
+#if FF_API_AV_FOPEN_UTF8
+FILE *av_fopen_utf8(const char *path, const char *mode)
+{
+    return avpriv_fopen_utf8(path, mode);
+}
+#endif
diff --git a/libavutil/internal.h b/libavutil/internal.h
index 79c2130be0..b44cbaaa7b 100644
--- a/libavutil/internal.h
+++ b/libavutil/internal.h
@@ -37,6 +37,7 @@
 #include <stdint.h>
 #include <stddef.h>
 #include <assert.h>
+#include <stdio.h>
 #include "config.h"
 #include "attributes.h"
 #include "timer.h"
@@ -183,8 +184,10 @@ void avpriv_request_sample(void *avc,
 #pragma comment(linker, "/include:" EXTERN_PREFIX "avpriv_snprintf")
 #endif
 
+#define avpriv_fopen_utf8 ff_fopen_utf8
 #define avpriv_open ff_open
 #define avpriv_tempfile ff_tempfile
+
 #define PTRDIFF_SPECIFIER "Id"
 #define SIZE_SPECIFIER "Iu"
 #else
@@ -256,6 +259,11 @@ static av_always_inline av_const int64_t ff_rint64_clip(double a, int64_t amin,
 av_warn_unused_result
 int avpriv_open(const char *filename, int flags, ...);
 
+/**
+ * Open a file using a UTF-8 filename.
+ */
+FILE *avpriv_fopen_utf8(const char *path, const char *mode);
+
 /**
  * Wrapper to work around the lack of mkstemp() on mingw.
  * Also, tries to create file in /tmp first, if possible.
diff --git a/libavutil/version.h b/libavutil/version.h
index 6735c20090..8532051c00 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -113,6 +113,7 @@
 #define FF_API_FIFO_OLD_API             (LIBAVUTIL_VERSION_MAJOR < 58)
 #define FF_API_XVMC                     (LIBAVUTIL_VERSION_MAJOR < 58)
 #define FF_API_OLD_CHANNEL_LAYOUT       (LIBAVUTIL_VERSION_MAJOR < 58)
+#define FF_API_AV_FOPEN_UTF8            (LIBAVUTIL_VERSION_MAJOR < 58)
 
 /**
  * @}
diff --git a/tests/ref/fate/source b/tests/ref/fate/source
index 69dcdc4f27..16ea7ef9c1 100644
--- a/tests/ref/fate/source
+++ b/tests/ref/fate/source
@@ -8,6 +8,7 @@ libavcodec/reverse.c
 libavdevice/file_open.c
 libavdevice/reverse.c
 libavfilter/af_arnndn.c
+libavfilter/file_open.c
 libavfilter/log2_tab.c
 libavformat/file_open.c
 libavformat/golomb_tab.c
