OpenShot Library | libopenshot 0.5.0
Loading...
Searching...
No Matches
FFmpegUtilities.h
Go to the documentation of this file.
1
8
9// Copyright (c) 2008-2024 OpenShot Studios, LLC
10//
11// SPDX-License-Identifier: LGPL-3.0-or-later
12
13#ifndef OPENSHOT_FFMPEG_UTILITIES_H
14#define OPENSHOT_FFMPEG_UTILITIES_H
15
16#include "OpenShotVersion.h" // For FFMPEG_USE_SWRESAMPLE
17
18// Required for libavformat to build on Windows
19#ifndef INT64_C
20#define INT64_C(c) (c ## LL)
21#define UINT64_C(c) (c ## ULL)
22#endif
23
24#ifndef IS_FFMPEG_3_2
25#define IS_FFMPEG_3_2 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 64, 101))
26#endif
27
28#ifndef USE_HW_ACCEL
29#define USE_HW_ACCEL (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 107, 100))
30#endif
31
32#ifndef USE_SW
33#define USE_SW FFMPEG_USE_SWRESAMPLE
34#endif
35
36#define HAVE_CH_LAYOUT (LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100))
37
38// Include the FFmpeg headers
39extern "C" {
40 #include <libavcodec/avcodec.h>
41 #include <libavformat/avformat.h>
42 #include <libavutil/display.h>
43
44#if (LIBAVFORMAT_VERSION_MAJOR >= 57)
45 #include <libavutil/hwcontext.h> //PM
46#endif
47 #include <libswscale/swscale.h>
48
49#if USE_SW
50 #include <libswresample/swresample.h>
51#else
52 #include <libavresample/avresample.h>
53#endif
54
55 #include <libavutil/mathematics.h>
56 #include <libavutil/pixfmt.h>
57 #include <libavutil/pixdesc.h>
58
59 // libavutil changed folders at some point
60#if LIBAVFORMAT_VERSION_MAJOR >= 53
61 #include <libavutil/opt.h>
62#else
63 #include <libavcodec/opt.h>
64#endif
65
66 // channel header refactored
67#if LIBAVFORMAT_VERSION_MAJOR >= 54
68 #include <libavutil/channel_layout.h>
69#endif
70
71#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 0, 0)
72 #include <libavutil/spherical.h>
73#endif
74
75#if IS_FFMPEG_3_2
76 #include "libavutil/imgutils.h"
77#endif
78}
79
80// This was removed from newer versions of FFmpeg (but still used in libopenshot)
81#ifndef AVCODEC_MAX_AUDIO_FRAME_SIZE
82 // 1 second of 48khz 32bit audio
83 #define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000
84#endif
85#ifndef AV_ERROR_MAX_STRING_SIZE
86 #define AV_ERROR_MAX_STRING_SIZE 64
87#endif
88#ifndef AUDIO_PACKET_ENCODING_SIZE
89 // 48khz * S16 (2 bytes) * max channels (8)
90 #define AUDIO_PACKET_ENCODING_SIZE 768000
91#endif
92
93// This wraps an unsafe C macro to be C++ compatible function
94inline static const std::string av_err2string(int errnum)
95{
96 char errbuf[AV_ERROR_MAX_STRING_SIZE];
97 av_strerror(errnum, errbuf, AV_ERROR_MAX_STRING_SIZE);
98 return static_cast<std::string>(errbuf);
99}
100
101// Redefine the C macro to use our new C++ function
102#undef av_err2str
103#define av_err2str(errnum) av_err2string(errnum).c_str()
104
105// Define this for compatibility
106#ifndef PixelFormat
107 #define PixelFormat AVPixelFormat
108#endif
109#ifndef PIX_FMT_RGBA
110 #define PIX_FMT_RGBA AV_PIX_FMT_RGBA
111#endif
112#ifndef PIX_FMT_NONE
113 #define PIX_FMT_NONE AV_PIX_FMT_NONE
114#endif
115#ifndef PIX_FMT_RGB24
116 #define PIX_FMT_RGB24 AV_PIX_FMT_RGB24
117#endif
118#ifndef PIX_FMT_YUV420P
119 #define PIX_FMT_YUV420P AV_PIX_FMT_YUV420P
120#endif
121#ifndef PIX_FMT_YUV444P
122 #define PIX_FMT_YUV444P AV_PIX_FMT_YUV444P
123#endif
124
125// Does ffmpeg pixel format contain an alpha channel?
126inline static bool ffmpeg_has_alpha(PixelFormat pix_fmt) {
127 const AVPixFmtDescriptor *fmt_desc = av_pix_fmt_desc_get(pix_fmt);
128 return bool(fmt_desc->flags & AV_PIX_FMT_FLAG_ALPHA);
129}
130
131// FFmpeg's libavutil/common.h defines an RSHIFT incompatible with Ruby's
132// definition in ruby/config.h, so we move it to FF_RSHIFT
133#ifdef RSHIFT
134 #define FF_RSHIFT(a, b) RSHIFT(a, b)
135 #undef RSHIFT
136#endif
137
138// libswresample/libavresample API switching
139#if USE_SW
140 #define SWR_CONVERT(ctx, out, linesize, out_count, in, linesize2, in_count) \
141 swr_convert(ctx, out, out_count, (const uint8_t **)in, in_count)
142 #define SWR_ALLOC() swr_alloc()
143 #define SWR_CLOSE(ctx) {}
144 #define SWR_FREE(ctx) swr_free(ctx)
145 #define SWR_INIT(ctx) swr_init(ctx)
146 #define SWRCONTEXT SwrContext
147
148#else
149 #define SWR_CONVERT(ctx, out, linesize, out_count, in, linesize2, in_count) \
150 avresample_convert(ctx, out, linesize, out_count, (uint8_t **)in, linesize2, in_count)
151 #define SWR_ALLOC() avresample_alloc_context()
152 #define SWR_CLOSE(ctx) avresample_close(ctx)
153 #define SWR_FREE(ctx) avresample_free(ctx)
154 #define SWR_INIT(ctx) avresample_open(ctx)
155 #define SWRCONTEXT AVAudioResampleContext
156#endif
157
158
159#if (LIBAVFORMAT_VERSION_MAJOR >= 58)
160 #define AV_REGISTER_ALL
161 #define AVCODEC_REGISTER_ALL
162 #define AV_FILENAME url
163 #define AV_SET_FILENAME(oc, f) oc->AV_FILENAME = av_strdup(f)
164 #define MY_INPUT_BUFFER_PADDING_SIZE AV_INPUT_BUFFER_PADDING_SIZE
165 #define AV_ALLOCATE_FRAME() av_frame_alloc()
166 #define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) \
167 av_image_alloc(av_frame->data, av_frame->linesize, width, height, pix_fmt, 32)
168 #define AV_RESET_FRAME(av_frame) av_frame_unref(av_frame)
169 #define AV_FREE_FRAME(av_frame) av_frame_free(av_frame)
170 #define AV_FREE_PACKET(av_packet) av_packet_unref(av_packet)
171 #define AV_FREE_CONTEXT(av_context) avcodec_free_context(&av_context)
172 #define AV_GET_CODEC_TYPE(av_stream) av_stream->codecpar->codec_type
173 #define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codecpar->codec_id
174 #define AV_GET_CODEC_CONTEXT(av_stream, av_codec) \
175 ({ AVCodecContext *context = avcodec_alloc_context3(av_codec); \
176 avcodec_parameters_to_context(context, av_stream->codecpar); \
177 context; })
178 #define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec) av_codec;
179 #define AV_GET_CODEC_FROM_STREAM(av_stream,codec_in)
180 #define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context) av_stream->codecpar
181 #define AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context) (AVPixelFormat) av_stream->codecpar->format
182 #define AV_GET_SAMPLE_FORMAT(av_stream, av_context) av_stream->codecpar->format
183 #define AV_GET_IMAGE_SIZE(pix_fmt, width, height) \
184 av_image_get_buffer_size(pix_fmt, width, height, 1)
185 #define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height) \
186 av_image_fill_arrays(av_frame->data, av_frame->linesize, buffer, pix_fmt, width, height, 1)
187 #define AV_OUTPUT_CONTEXT(output_context, path) avformat_alloc_output_context2( output_context, NULL, NULL, path)
188 #define AV_OPTION_FIND(priv_data, name) av_opt_find(priv_data, name, NULL, 0, 0)
189 #define AV_OPTION_SET( av_stream, priv_data, name, value, avcodec) \
190 av_opt_set(priv_data, name, value, 0); \
191 avcodec_parameters_from_context(av_stream->codecpar, avcodec);
192 #define ALLOC_CODEC_CTX(ctx, codec, stream) \
193 ctx = avcodec_alloc_context3(codec);
194 #define AV_COPY_PARAMS_FROM_CONTEXT(av_stream, av_codec_ctx) \
195 avcodec_parameters_from_context(av_stream->codecpar, av_codec_ctx);
196
197#elif IS_FFMPEG_3_2
198 #define AV_REGISTER_ALL av_register_all();
199 #define AVCODEC_REGISTER_ALL avcodec_register_all();
200 #define AV_FILENAME filename
201 #define AV_SET_FILENAME(oc, f) snprintf(oc->AV_FILENAME, sizeof(oc->AV_FILENAME), "%s", f)
202 #define MY_INPUT_BUFFER_PADDING_SIZE FF_INPUT_BUFFER_PADDING_SIZE
203 #define AV_ALLOCATE_FRAME() av_frame_alloc()
204 #define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) \
205 av_image_alloc(av_frame->data, av_frame->linesize, width, height, pix_fmt, 32)
206 #define AV_RESET_FRAME(av_frame) av_frame_unref(av_frame)
207 #define AV_FREE_FRAME(av_frame) av_frame_free(av_frame)
208 #define AV_FREE_PACKET(av_packet) av_packet_unref(av_packet)
209 #define AV_FREE_CONTEXT(av_context) avcodec_free_context(&av_context)
210 #define AV_GET_CODEC_TYPE(av_stream) av_stream->codecpar->codec_type
211 #define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codecpar->codec_id
212 #define AV_GET_CODEC_CONTEXT(av_stream, av_codec) \
213 ({ AVCodecContext *context = avcodec_alloc_context3(av_codec); \
214 avcodec_parameters_to_context(context, av_stream->codecpar); \
215 context; })
216 #define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec) av_codec;
217 #define AV_GET_CODEC_FROM_STREAM(av_stream,codec_in)
218 #define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context) av_stream->codecpar
219 #define AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context) \
220 (AVPixelFormat) av_stream->codecpar->format
221 #define AV_GET_SAMPLE_FORMAT(av_stream, av_context) av_stream->codecpar->format
222 #define AV_GET_IMAGE_SIZE(pix_fmt, width, height) av_image_get_buffer_size(pix_fmt, width, height, 1)
223 #define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height) \
224 av_image_fill_arrays(av_frame->data, av_frame->linesize, buffer, pix_fmt, width, height, 1)
225 #define AV_OUTPUT_CONTEXT(output_context, path) \
226 avformat_alloc_output_context2( output_context, NULL, NULL, path)
227 #define AV_OPTION_FIND(priv_data, name) av_opt_find(priv_data, name, NULL, 0, 0)
228 #define AV_OPTION_SET( av_stream, priv_data, name, value, avcodec) \
229 av_opt_set(priv_data, name, value, 0); \
230 avcodec_parameters_from_context(av_stream->codecpar, avcodec);
231 #define ALLOC_CODEC_CTX(ctx, codec, stream) \
232 ctx = avcodec_alloc_context3(codec);
233 #define AV_COPY_PARAMS_FROM_CONTEXT(av_stream, av_codec) \
234 avcodec_parameters_from_context(av_stream->codecpar, av_codec);
235
236#elif LIBAVFORMAT_VERSION_MAJOR >= 55
237 #define AV_REGISTER_ALL av_register_all();
238 #define AVCODEC_REGISTER_ALL avcodec_register_all();
239 #define AV_FILENAME filename
240 #define AV_SET_FILENAME(oc, f) snprintf(oc->AV_FILENAME, sizeof(oc->AV_FILENAME), "%s", f)
241 #define MY_INPUT_BUFFER_PADDING_SIZE FF_INPUT_BUFFER_PADDING_SIZE
242 #define AV_ALLOCATE_FRAME() av_frame_alloc()
243 #define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) \
244 avpicture_alloc((AVPicture *) av_frame, pix_fmt, width, height)
245 #define AV_RESET_FRAME(av_frame) av_frame_unref(av_frame)
246 #define AV_FREE_FRAME(av_frame) av_frame_free(av_frame)
247 #define AV_FREE_PACKET(av_packet) av_packet_unref(av_packet)
248 #define AV_FREE_CONTEXT(av_context) avcodec_close(av_context)
249 #define AV_GET_CODEC_TYPE(av_stream) av_stream->codec->codec_type
250 #define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codec->codec_id
251 #define AV_GET_CODEC_CONTEXT(av_stream, av_codec) av_stream->codec
252 #define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec) av_stream->codec
253 #define AV_GET_CODEC_FROM_STREAM(av_stream, codec_in) codec_in = av_stream->codec;
254 #define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context) av_context
255 #define AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context) av_context->pix_fmt
256 #define AV_GET_SAMPLE_FORMAT(av_stream, av_context) av_context->sample_fmt
257 #define AV_GET_IMAGE_SIZE(pix_fmt, width, height) avpicture_get_size(pix_fmt, width, height)
258 #define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height) \
259 avpicture_fill((AVPicture *) av_frame, buffer, pix_fmt, width, height)
260 #define AV_OUTPUT_CONTEXT(output_context, path) oc = avformat_alloc_context()
261 #define AV_OPTION_FIND(priv_data, name) av_opt_find(priv_data, name, NULL, 0, 0)
262 #define AV_OPTION_SET(av_stream, priv_data, name, value, avcodec) av_opt_set (priv_data, name, value, 0)
263 #define ALLOC_CODEC_CTX(ctx, av_codec, stream) \
264 avcodec_get_context_defaults3(av_st->codec, av_codec); \
265 ctx = av_st->codec;
266 #define AV_COPY_PARAMS_FROM_CONTEXT(av_stream, av_codec)
267
268#else
269 #define AV_REGISTER_ALL av_register_all();
270 #define AVCODEC_REGISTER_ALL avcodec_register_all();
271 #define AV_FILENAME filename
272 #define AV_SET_FILENAME(oc, f) snprintf(oc->AV_FILENAME, sizeof(oc->AV_FILENAME), "%s", f)
273 #define MY_INPUT_BUFFER_PADDING_SIZE FF_INPUT_BUFFER_PADDING_SIZE
274 #define AV_ALLOCATE_FRAME() avcodec_alloc_frame()
275 #define AV_ALLOCATE_IMAGE(av_frame, pix_fmt, width, height) \
276 avpicture_alloc((AVPicture *) av_frame, pix_fmt, width, height)
277 #define AV_RESET_FRAME(av_frame) avcodec_get_frame_defaults(av_frame)
278 #define AV_FREE_FRAME(av_frame) avcodec_free_frame(av_frame)
279 #define AV_FREE_PACKET(av_packet) av_free_packet(av_packet)
280 #define AV_FREE_CONTEXT(av_context) avcodec_close(av_context)
281 #define AV_GET_CODEC_TYPE(av_stream) av_stream->codec->codec_type
282 #define AV_FIND_DECODER_CODEC_ID(av_stream) av_stream->codec->codec_id
283 #define AV_GET_CODEC_CONTEXT(av_stream, av_codec) av_stream->codec
284 #define AV_GET_CODEC_PAR_CONTEXT(av_stream, av_codec) av_stream->codec
285 #define AV_GET_CODEC_FROM_STREAM(av_stream, codec_in ) codec_in = av_stream->codec;
286 #define AV_GET_CODEC_ATTRIBUTES(av_stream, av_context) av_context
287 #define AV_GET_CODEC_PIXEL_FORMAT(av_stream, av_context) av_context->pix_fmt
288 #define AV_GET_SAMPLE_FORMAT(av_stream, av_context) av_context->sample_fmt
289 #define AV_GET_IMAGE_SIZE(pix_fmt, width, height) avpicture_get_size(pix_fmt, width, height)
290 #define AV_COPY_PICTURE_DATA(av_frame, buffer, pix_fmt, width, height) \
291 avpicture_fill((AVPicture *) av_frame, buffer, pix_fmt, width, height)
292 #define AV_OUTPUT_CONTEXT(output_context, path) oc = avformat_alloc_context()
293 #define AV_OPTION_FIND(priv_data, name) av_opt_find(priv_data, name, NULL, 0, 0)
294 #define AV_OPTION_SET(av_stream, priv_data, name, value, avcodec) av_opt_set (priv_data, name, value, 0)
295 #define ALLOC_CODEC_CTX(ctx, av_codec, stream) \
296 avcodec_get_context_defaults3(stream->codec, av_codec); \
297 ctx = stream->codec;
298 #define AV_COPY_PARAMS_FROM_CONTEXT(av_stream, av_codec)
299#endif
300
301// Aligned memory allocation helpers (cross-platform)
302#if defined(_WIN32)
303#include <malloc.h>
304#endif
305
306inline static void* aligned_malloc(size_t size, size_t alignment = 32)
307{
308#if defined(_WIN32)
309 return _aligned_malloc(size, alignment);
310#elif defined(__APPLE__) || defined(__linux__)
311 void* ptr = nullptr;
312 if (posix_memalign(&ptr, alignment, size) != 0)
313 return nullptr;
314 return ptr;
315#else
316#error "aligned_malloc not implemented on this platform"
317#endif
318}
319
320#endif // OPENSHOT_FFMPEG_UTILITIES_H
#define AV_ERROR_MAX_STRING_SIZE
#define PixelFormat
Header file that includes the version number of libopenshot.