-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFetchFfmpegVersions.cmake
More file actions
262 lines (208 loc) · 9.59 KB
/
Copy pathFetchFfmpegVersions.cmake
File metadata and controls
262 lines (208 loc) · 9.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# This file provides function that parses ffmpeg-versions.txt and process FFmpeg versions.
# For each FFmpeg version:
# 1. All headers libraries are downloaded to (ROOT)/external/ffmpeg-(version)
# 2. Automatically created loader file in (ROOT)/external/ffmpeg-(version)/ffmpeg-(version)-loader.cc
# 3. Fill (ROOT)/external/ffmpeg-versions.h and (ROOT)/external/ffmpeg-versions-register.cc
#
# Example content of ffmpeg-versions.txt
# 3.2 : release/3.2
# 3.4 : release/3.4
# 8.1 : master
# 4.4 : release/4.4
# 5.1 : release/5.1
function(process_ffmpeg_versions)
# Define parameters
set(oneValueArgs VERSIONS_FILE)
set(multiValueArgs)
cmake_parse_arguments(ARG "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT ARG_VERSIONS_FILE)
message(FATAL_ERROR "VERSIONS_FILE parameter is required")
endif()
if(NOT EXISTS "${ARG_VERSIONS_FILE}")
message(FATAL_ERROR "Versions file not found: ${ARG_VERSIONS_FILE}")
endif()
# Recreate ffmpeg-versions.h
file(WRITE "${FFMPEGLOADER_EXTERNAL_BASE_DIR}/ffmpeg-versions.h"
"// THIS FILE IS CREATED AUTOMATICALLY BY CMAKE SCRIPTS. DO NOT EDIT
#ifndef FFMPEG_VERSIONS_HEADER
#define FFMPEG_VERSIONS_HEADER
#include <memory>
#include <vector>
#include <avc/i_avc_module_provider.h>
#include <i_avc_module_data_wrapper_factory.h>
extern std::vector<std::shared_ptr<avc::IAvcModuleDataWrapperFactory> > g_ffmpeg_data_wrappers;
")
# Recreate ffmpeg-versions-register.cc
file(WRITE "${FFMPEGLOADER_EXTERNAL_BASE_DIR}/ffmpeg-versions-register.cc"
"// THIS FILE IS CREATED AUTOMATICALLY BY CMAKE SCRIPTS. DO NOT EDIT
#include \"ffmpeg-versions.h\"
std::shared_ptr<avc::IAvcModuleDataWrapperFactory> AvcModuleProviderDataWrapFactory_Static_Create();
void AvcDataProvidersGlobalInit() {
if (g_ffmpeg_data_wrappers.size() != 0)
return;
#if !defined(AVC_LIBRARIES_STATIC_LINK) || AVC_LIBRARIES_STATIC_LINK==0
" )
# Start version file processing
# Read the entire file
file(READ "${ARG_VERSIONS_FILE}" file_content)
# Split into lines
string(REPLACE "\n" ";" lines_list "${file_content}")
# Process each line
foreach(line IN LISTS lines_list)
# Remove leading/trailing whitespace
string(STRIP "${line}" stripped_line)
# Skip empty lines and comments
if("${stripped_line}" STREQUAL "" OR "${stripped_line}" MATCHES "^#")
continue()
endif()
# Split line by colon
string(REPLACE ":" ";" line_parts "${stripped_line}")
list(LENGTH line_parts parts_count)
if(parts_count LESS 2)
message(WARNING "Skipping invalid line: ${stripped_line}")
continue()
endif()
# Extract version and tag
list(GET line_parts 0 raw_version)
list(GET line_parts 1 raw_tag)
# Remove whitespace
string(STRIP "${raw_version}" FFMPEG_VERSION)
string(STRIP "${raw_tag}" FFMPEG_TAG)
# Skip if version or tag is empty
if("${FFMPEG_VERSION}" STREQUAL "" OR "${FFMPEG_TAG}" STREQUAL "")
message(WARNING "Skipping line with empty version or tag: ${stripped_line}")
continue()
endif()
message(STATUS "Processing FFmpeg version: ${FFMPEG_VERSION}, tag: ${FFMPEG_TAG}")
# Here you can call your processing function
process_ffmpeg_version("${FFMPEG_VERSION}" "${FFMPEG_TAG}")
endforeach()
# Finalize ffmpeg-versions.h
file(APPEND "${FFMPEGLOADER_EXTERNAL_BASE_DIR}/ffmpeg-versions.h" "
#endif //FFMPEG_VERSIONS_HEADER
")
# Finalize ffmpeg-versions-register.cc
file(APPEND "${FFMPEGLOADER_EXTERNAL_BASE_DIR}/ffmpeg-versions-register.cc"
"#else // !defined(AVC_LIBRARIES_STATIC_LINK) || AVC_LIBRARIES_STATIC_LINK==0
g_ffmpeg_data_wrappers.push_back(AvcModuleProviderDataWrapFactory_Static_Create());
#endif //AVC_LIBRARIES_STATIC_LINK
}
" )
endfunction()
# Function to process each FFmpeg version
# This function downloads headers files from specified FFmpeg version
function(process_ffmpeg_version version tag)
message(STATUS "=== Download headers from FFmpeg ${version} ===")
string(REPLACE "." "_" FFMPEG_CUR_VERSION_UNDERSCORE ${version}) # 3.2 -> 3_2
if(NOT EXISTS "${FFMPEGLOADER_EXTERNAL_BASE_DIR}/ffmpeg-${version}")
fetch_git_partial(
GIT_URL "https://github.com/FFmpeg/FFmpeg.git"
TAG "${tag}"
SRC_PATHS
"libavcodec"
"libavdevice"
"libavfilter"
"libavformat"
"libavutil"
"libswresample"
"libswscale"
DEST_DIR "${FFMPEGLOADER_EXTERNAL_BASE_DIR}/ffmpeg-${version}"
TEMP_DIR "${FFMPEGLOADER_PROJECT_ROOT_DIR}/tmp"
FILE_PATTERNS "*.h"
)
patch_ffmpeg_headers("${FFMPEGLOADER_EXTERNAL_BASE_DIR}/ffmpeg-${version}")
# Create libavutil/avconfig.h for each FFmpeg version
file(WRITE "${FFMPEGLOADER_EXTERNAL_BASE_DIR}/ffmpeg-${version}/libavutil/avconfig.h" "
#ifndef AVUTIL_AVCONFIG_H
#define AVUTIL_AVCONFIG_H
#define AV_HAVE_BIGENDIAN 0
#define AV_HAVE_FAST_UNALIGNED 1
#endif /*AVUTIL_AVCONFIG_H*/
")
# Create loader source file
file(WRITE "${FFMPEGLOADER_EXTERNAL_BASE_DIR}/ffmpeg-${version}/ffmpeg-${FFMPEG_CUR_VERSION_UNDERSCORE}-loader.cc"
"
#define AVC_MODULE_DATA_WRAPPER_NAMESPACE ffmpeg_${FFMPEG_CUR_VERSION_UNDERSCORE}
#define AVC_MODULE_DATA_WRAPPER_CLASSNAME AvcModuleProviderDataWrap_${FFMPEG_CUR_VERSION_UNDERSCORE}
#define AVC_MODULE_DATA_WRAPPER_FACTORYNAME AvcModuleProviderDataWrapFactory_${FFMPEG_CUR_VERSION_UNDERSCORE}
#include \"loader_common.h\"
extern \"C\" {
namespace AVC_MODULE_DATA_WRAPPER_NAMESPACE {
#include \"libavutil/avutil.h\"
#include \"libavdevice/avdevice.h\"
#include \"libavcodec/avcodec.h\"
#include \"libavformat/avformat.h\"
#include \"libavutil/imgutils.h\"
#include \"libswscale/swscale.h\"
#include \"libavutil/hwcontext.h\"
struct SwrContext;
#include \"libswresample/swresample.h\"
}// namespace
}// extern \"C\"
#include \"avc_module_data_wrapper.hpp\"
")
endif() # EXISTS "${FFMPEGLOADER_EXTERNAL_BASE_DIR}/ffmpeg-${version}"
# Declare this version factory create function in ffmpeg-versions.h
file(APPEND "${FFMPEGLOADER_EXTERNAL_BASE_DIR}/ffmpeg-versions.h" "std::shared_ptr<avc::IAvcModuleDataWrapperFactory> AvcModuleProviderDataWrapFactory_${FFMPEG_CUR_VERSION_UNDERSCORE}_Create();
")
# Add version registration procedure to ffmpeg-versions-register.cc
file(APPEND "${FFMPEGLOADER_EXTERNAL_BASE_DIR}/ffmpeg-versions-register.cc" " g_ffmpeg_data_wrappers.push_back(AvcModuleProviderDataWrapFactory_${FFMPEG_CUR_VERSION_UNDERSCORE}_Create());
")
message(STATUS "Finished processing FFmpeg ${version}")
endfunction()
# patching FFmpeg headers
function(patch_ffmpeg_headers ffmpeg_source_dir)
message(DEBUG "Cross-platform FFmpeg header patching in ${ffmpeg_source_dir}...")
set(FFMPEG_LIBS
libavcodec libavformat libavutil
libavdevice libavfilter
libswscale libswresample libpostproc
)
foreach(lib IN LISTS FFMPEG_LIBS)
set(lib_path "${ffmpeg_source_dir}/${lib}")
if(EXISTS "${lib_path}" AND IS_DIRECTORY "${lib_path}")
message(DEBUG "Patching ${lib}...")
file(GLOB_RECURSE HEADER_FILES "${lib_path}/*.h")
foreach(header IN LISTS HEADER_FILES)
# normalize path
file(TO_CMAKE_PATH "${header}" header_cmake_path)
# relative path from FFmpeg root
file(RELATIVE_PATH rel_path "${ffmpeg_source_dir}" "${header_cmake_path}")
file(TO_NATIVE_PATH "${rel_path}" rel_native_path)
get_filename_component(header_dir "${rel_path}" DIRECTORY)
if(header_dir)
# replace all separators to / for consistency
string(REPLACE "\\" "/" header_dir_unix "${header_dir}")
# counting subdirectories
string(REPLACE "/" ";" dir_list "${header_dir_unix}")
list(LENGTH dir_list depth)
else()
set(depth 0)
endif()
# relative path to root
set(relative_prefix "")
if(depth GREATER 0)
foreach(i RANGE 1 ${depth})
set(relative_prefix "${relative_prefix}../")
endforeach()
endif()
file(READ "${header}" content)
set(original_content "${content}")
foreach(target_lib IN LISTS FFMPEG_LIBS)
string(REPLACE
"#include \"${target_lib}/"
"#include \"${relative_prefix}${target_lib}/"
content
"${content}"
)
endforeach()
# check for changes
if(NOT content STREQUAL original_content)
file(WRITE "${header}" "${content}")
message(DEBUG " Patched: ${rel_path}")
endif()
endforeach()
endif()
endforeach()
message(DEBUG " FFmpeg header patching completed!")
endfunction()