From ffee27b79ef09dfc64a2ae75876c579272a7ffc5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20Gl=C3=B6ckner?= <daniel-gl@gmx.net>
Date: Fri, 3 Mar 2023 10:29:09 +0100
Subject: [PATCH] Add units for FFmpeg 6.0

---
 configure.ac                      |   4 +-
 src/lib/ffmpeg-6.0/avcodec.pas    | 257 ++++++++++++++++++++++++++++++
 src/lib/ffmpeg-6.0/avformat.pas   | 114 +++++++++++++
 src/lib/ffmpeg-6.0/avio.pas       |  47 ++++++
 src/lib/ffmpeg-6.0/avutil.pas     | 186 +++++++++++++++++++++
 src/lib/ffmpeg-6.0/rational.pas   |  32 ++++
 src/lib/ffmpeg-6.0/swresample.pas |  61 +++++++
 src/lib/ffmpeg-6.0/swscale.pas    |  53 ++++++
 8 files changed, 753 insertions(+), 1 deletion(-)
 create mode 100644 src/lib/ffmpeg-6.0/avcodec.pas
 create mode 100644 src/lib/ffmpeg-6.0/avformat.pas
 create mode 100644 src/lib/ffmpeg-6.0/avio.pas
 create mode 100644 src/lib/ffmpeg-6.0/avutil.pas
 create mode 100644 src/lib/ffmpeg-6.0/rational.pas
 create mode 100644 src/lib/ffmpeg-6.0/swresample.pas
 create mode 100644 src/lib/ffmpeg-6.0/swscale.pas

diff --git a/configure.ac b/configure.ac
index 0b8ca0cdc..f402d0f63 100644
--- a/configure.ac
+++ b/configure.ac
@@ -298,7 +298,9 @@ AC_SUBST_DEFINE(HAVE_SWRESAMPLE, $libswresample_HAVE)
 # map avutil library version to ffmpeg version
 AC_MSG_CHECKING([version of ffmpeg])
 # the order is ([avutil], [avcodec], [avformat], [swscale], [swresample])
-if   FFMPEG_LIBS_COMPATIBLE([57017100], [59018100], [59016100], [6004100], [4003100]); then
+if   FFMPEG_LIBS_COMPATIBLE([58002100], [60003100], [60003100], [7001100], [4010100]); then
+    FFMPEG_VERSION="6.0"
+elif FFMPEG_LIBS_COMPATIBLE([57017100], [59018100], [59016100], [6004100], [4003100]); then
     FFMPEG_VERSION="5.0"
 elif FFMPEG_LIBS_COMPATIBLE([56014100], [58018100], [58012100], [5001100], [3001100]); then
     FFMPEG_VERSION="4.0"
diff --git a/src/lib/ffmpeg-6.0/avcodec.pas b/src/lib/ffmpeg-6.0/avcodec.pas
new file mode 100644
index 000000000..d69a7eede
--- /dev/null
+++ b/src/lib/ffmpeg-6.0/avcodec.pas
@@ -0,0 +1,257 @@
+unit avcodec;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+{$IFDEF DARWIN}
+  {$linklib libavcodec}
+{$ENDIF}
+
+interface
+
+uses
+  ctypes,
+  avutil,
+  rational,
+  SysUtils,
+  UConfig;
+
+const
+  (* Supported version by this header *)
+  LIBAVCODEC_MAX_VERSION_MAJOR   = 60;
+  LIBAVCODEC_MAX_VERSION_MINOR   = 3;
+  LIBAVCODEC_MAX_VERSION_RELEASE = 100;
+  LIBAVCODEC_MAX_VERSION = (LIBAVCODEC_MAX_VERSION_MAJOR * VERSION_MAJOR) +
+                           (LIBAVCODEC_MAX_VERSION_MINOR * VERSION_MINOR) +
+                           (LIBAVCODEC_MAX_VERSION_RELEASE * VERSION_RELEASE);
+
+  (* Min. supported version by this header *)
+  LIBAVCODEC_MIN_VERSION_MAJOR   = 60;
+  LIBAVCODEC_MIN_VERSION_MINOR   = 0;
+  LIBAVCODEC_MIN_VERSION_RELEASE = 100;
+  LIBAVCODEC_MIN_VERSION = (LIBAVCODEC_MIN_VERSION_MAJOR * VERSION_MAJOR) +
+                            (LIBAVCODEC_MIN_VERSION_MINOR * VERSION_MINOR) +
+                            (LIBAVCODEC_MIN_VERSION_RELEASE * VERSION_RELEASE);
+
+(* Check if linked versions are supported *)
+{$IF (LIBAVCODEC_VERSION < LIBAVCODEC_MIN_VERSION)}
+  {$MESSAGE Error 'Linked version of libavcodec is too old!'}
+{$IFEND}
+
+(* Check if linked version is supported *)
+{$IF (LIBAVCODEC_VERSION > LIBAVCODEC_MAX_VERSION)}
+  {$MESSAGE Error 'Linked version of libavcodec is not yet supported!'}
+{$IFEND}
+
+const
+  FF_BUG_AUTODETECT = 1;
+type
+  TAVCodecID = (
+    AV_CODEC_ID_NONE
+  );
+  PAVPacket = ^TAVPacket;
+  TAVPacket = record
+    we_do_not_use_buf: pointer;
+    pts: cint64;
+    we_do_not_use_dts: cint64;
+    data: PByteArray;
+    size: cint;
+    stream_index: cint;
+    flags: cint;
+    we_do_not_use_side_data: pointer;
+    we_do_not_use_side_data_elems: cint;
+    we_do_not_use_duration: cint64;
+    we_do_not_use_pos: cint64;
+    we_do_not_use_opaque: pointer;
+    we_do_not_use_opaque_ref: pointer;
+    we_do_not_use_time_base: TAVRational;
+  end;
+  PAVPacketList = ^TAVPacketList;
+  TAVPacketList = record
+    pkt: TAVPacket;
+    next: ^TAVPacketList;
+  end;
+  PAVCodecDescriptor = ^TAVCodecDescriptor;
+  TAVCodecDescriptor = record
+    we_do_not_use_id: TAVCodecID;
+    we_do_not_use_type: TAVMediaType;
+    name: ^AnsiChar;
+    long_name: ^AnsiChar;
+    do_not_instantiate_this_record: incomplete_record;
+  end;
+  PAVCodecParameters = ^TAVCodecParameters;
+  TAVCodecParameters = record
+    codec_type: TAVMediaType;
+    codec_id: TAVCodecID;
+    do_not_instantiate_this_record: incomplete_record;
+  end;
+  PAVCodecContext = ^TAVCodecContext;
+  PPAVCodecContext = ^PAVCodecContext;
+  PAVCodec = ^TAVCodec;
+  TAVCodec = record
+    name: ^AnsiChar;
+    we_do_not_use_long_name: ^AnsiChar;
+    type_: TAVMediaType;
+    id: TAVCodecID;
+    we_do_not_use_capabilities: cint;
+    we_do_not_use_max_lowres: cuint8;
+    we_do_not_use_supported_framerates: ^TAVRational;
+    pix_fmts: ^TAVPixelFormat;
+    do_not_instantiate_this_record: incomplete_record;
+  end;
+  TAVCodecContext = record
+    we_do_not_use_av_class: pointer;
+    we_do_not_use_log_level_offset: cint;
+    codec_type: TAVMediaType;
+    codec: ^TAVCodec;
+    codec_id: TAVCodecID;
+    we_do_not_use_codec_tag: cuint;
+    we_do_not_use_priv_data: pointer;
+    we_do_not_use_internal: pointer;
+    we_do_not_use_opaque: pointer;
+    we_do_not_use_bit_rate: cint64;
+    we_do_not_use_bit_rate_tolerance: cint;
+    we_do_not_use_global_quality: cint;
+    we_do_not_use_compression_level: cint;
+    we_do_not_use_flags: cint;
+    we_do_not_use_flags2: cint;
+    we_do_not_use_extradata: pcuint8;
+    we_do_not_use_extradata_size: cint;
+    time_base: TAVRational;
+    we_do_not_use_ticks_per_frame: cint;
+    we_do_not_use_delay: cint;
+    width: cint;
+    height: cint;
+    we_do_not_use_coded_width: cint;
+    we_do_not_use_coded_height: cint;
+    we_do_not_use_gop_size: cint;
+    pix_fmt: TAVPixelFormat;
+    we_do_not_use_draw_horiz_band: cfunctionpointer;
+    get_format: function(s: PAVCodecContext; fmt: PAVPixelFormat): TAVPixelFormat; cdecl;
+    we_do_not_use_max_b_frames: cint;
+    we_do_not_use_b_quant_factor: cfloat;
+    we_do_not_use_b_quant_offset: cfloat;
+    we_do_not_use_has_b_frames: cint;
+    we_do_not_use_i_quant_factor: cfloat;
+    we_do_not_use_i_quant_offset: cfloat;
+    we_do_not_use_lumi_masking: cfloat;
+    we_do_not_use_temporal_cplx_masking: cfloat;
+    we_do_not_use_spatial_cplx_masking: cfloat;
+    we_do_not_use_p_masking: cfloat;
+    we_do_not_use_dark_masking: cfloat;
+    we_do_not_use_slice_count: cint;
+    we_do_not_use_slice_offset: pcint;
+    sample_aspect_ratio: TAVRational;
+    we_do_not_use_me_cmp: cint;
+    we_do_not_use_me_sub_cmp: cint;
+    we_do_not_use_mb_cmp: cint;
+    we_do_not_use_ildct_cmp: cint;
+    we_do_not_use_dia_size: cint;
+    we_do_not_use_last_predictor_count: cint;
+    we_do_not_use_me_pre_cmp: cint;
+    we_do_not_use_pre_dia_size: cint;
+    we_do_not_use_me_subpel_quality: cint;
+    we_do_not_use_me_range: cint;
+    we_do_not_use_slice_flags: cint;
+    we_do_not_use_mb_decision: cint;
+    we_do_not_use_intra_matrix: pcuint16;
+    we_do_not_use_inter_matrix: pcuint16;
+    we_do_not_use_intra_dc_precision: cint;
+    we_do_not_use_skip_top: cint;
+    we_do_not_use_skip_bottom: cint;
+    we_do_not_use_mb_lmin: cint;
+    we_do_not_use_mb_lmax: cint;
+    we_do_not_use_bidir_refine: cint;
+    we_do_not_use_keyint_min: cint;
+    we_do_not_use_refs: cint;
+    we_do_not_use_mv0_threshold: cint;
+    we_do_not_use_color_primaries: cenum;
+    we_do_not_use_color_trc: cenum;
+    we_do_not_use_colorspace: cenum;
+    we_do_not_use_color_range: cenum;
+    we_do_not_use_chroma_sample_location: cenum;
+    we_do_not_use_slices: cint;
+    we_do_not_use_field_order: cenum;
+    sample_rate: cint;
+    channels: cint;
+    sample_fmt: TAVSampleFormat;
+    we_do_not_use_frame_size: cint;
+    we_do_not_use_frame_number: cint;
+    we_do_not_use_block_align: cint;
+    we_do_not_use_cutoff: cint;
+    channel_layout: cuint64;
+    request_channel_layout: cuint64;
+    we_do_not_use_audio_service_type: cenum;
+    request_sample_fmt: TAVSampleFormat;
+    we_do_not_use_get_buffer2: cfunctionpointer;
+    we_do_not_use_qcompress: cfloat;
+    we_do_not_use_qblur: cfloat;
+    we_do_not_use_qmin: cint;
+    we_do_not_use_qmax: cint;
+    we_do_not_use_max_qdiff: cint;
+    we_do_not_use_rc_buffer_size: cint;
+    we_do_not_use_rc_override_count: cint;
+    we_do_not_use_rc_override: pointer;
+    we_do_not_use_rc_max_rate: cint64;
+    we_do_not_use_rc_min_rate: cint64;
+    we_do_not_use_rc_max_available_vbv_use: cfloat;
+    we_do_not_use_rc_min_vbv_overflow_use: cfloat;
+    we_do_not_use_rc_initial_buffer_occupancy: cint;
+    we_do_not_use_trellis: cint;
+    we_do_not_use_stats_out: pcchar;
+    we_do_not_use_stats_in: pcchar;
+    workaround_bugs: cint;
+    we_do_not_use_strict_std_compliance: cint;
+    we_do_not_use_error_concealment: cint;
+    debug: cint;
+    we_do_not_use_err_recognition: cint;
+    we_do_not_use_reordered_opaque: cint64;
+    we_do_not_use_hwaccel: pointer;
+    we_do_not_use_hwaccel_context: pointer;
+    we_do_not_use_error: array [0..AV_NUM_DATA_POINTERS-1] of cuint64;
+    we_do_not_use_dct_algo: cint;
+    we_do_not_use_idct_algo: cint;
+    we_do_not_use_bits_per_coded_sample: cint;
+    we_do_not_use_bits_per_raw_sample: cint;
+    we_do_not_use_lowres: cint;
+    thread_count: cint;
+    we_do_not_use_thread_type: cint;
+    we_do_not_use_active_thread_type: cint;
+    we_do_not_use_execute: cfunctionpointer;
+    we_do_not_use_execute2: cfunctionpointer;
+    we_do_not_use_nsse_weight: cint;
+    we_do_not_use_profile: cint;
+    we_do_not_use_level: cint;
+    we_do_not_use_skip_loop_filter: cenum;
+    we_do_not_use_skip_idct: cenum;
+    we_do_not_use_skip_frame: cenum;
+    we_do_not_use_subtitle_header: pcuint8;
+    we_do_not_use_subtitle_header_size: cint;
+    we_do_not_use_initial_padding: cint;
+    framerate: TAVRational;
+    do_not_instantiate_this_record: incomplete_record;
+  end;
+function av_packet_ref(dst: PAVPacket; src: PAVPacket): cint; cdecl; external av__codec;
+procedure av_packet_unref(pkt: PAVPacket); cdecl; external av__codec;
+procedure av_init_packet(var pkt: TAVPacket); cdecl; external av__codec; deprecated;
+function avcodec_version(): cuint; cdecl; external av__codec;
+function av_codec_is_decoder(codec: PAVCodec): cint; cdecl; external av__codec;
+function av_codec_iterate(opaque: ppointer): PAVCodec; cdecl; external av__codec;
+function avcodec_find_decoder(id: TAVCodecID): PAVCodec; cdecl; external av__codec;
+function avcodec_find_decoder_by_name(name: PAnsiChar): PAVCodec; cdecl; external av__codec;
+function avcodec_descriptor_get(id: TAVCodecID): PAVCodecDescriptor; cdecl; external av__codec;
+function avcodec_open2(avctx: PAVCodecContext; codec: PAVCodec; options: PPAVDictionary): cint; cdecl; external av__codec;
+function avcodec_close(avctx: PAVCodecContext): cint; cdecl; external av__codec;
+procedure avcodec_flush_buffers(avctx: PAVCodecContext); cdecl; external av__codec;
+function avcodec_receive_frame(avctx: PAVCodecContext; frame: PAVFrame): cint; cdecl; external av__codec;
+function avcodec_send_packet(avctx: PAVCodecContext; avpkt: PAVPacket): cint; cdecl; external av__codec;
+function avcodec_alloc_context3(codec: PAVCodec): PAVCodecContext; cdecl; external av__codec;
+procedure avcodec_free_context(avctx: PPAVCodecContext); cdecl; external av__codec;
+function avcodec_parameters_to_context(codec: PAVCodecContext; par: PAVCodecParameters): cint; cdecl; external av__codec;
+implementation
+end.
diff --git a/src/lib/ffmpeg-6.0/avformat.pas b/src/lib/ffmpeg-6.0/avformat.pas
new file mode 100644
index 000000000..66041b1e2
--- /dev/null
+++ b/src/lib/ffmpeg-6.0/avformat.pas
@@ -0,0 +1,114 @@
+unit avformat;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+{$IFDEF DARWIN}
+  {$linklib libavformat}
+{$ENDIF}
+
+interface
+
+uses
+  ctypes,
+  avcodec,
+  avio,
+  avutil,
+  rational,
+  UConfig;
+
+const
+  (* Max. supported version by this header *)
+  LIBAVFORMAT_MAX_VERSION_MAJOR   = 60;
+  LIBAVFORMAT_MAX_VERSION_MINOR   = 3;
+  LIBAVFORMAT_MAX_VERSION_RELEASE = 100;
+  LIBAVFORMAT_MAX_VERSION = (LIBAVFORMAT_MAX_VERSION_MAJOR * VERSION_MAJOR) +
+                            (LIBAVFORMAT_MAX_VERSION_MINOR * VERSION_MINOR) +
+                            (LIBAVFORMAT_MAX_VERSION_RELEASE * VERSION_RELEASE);
+
+  (* Min. supported version by this header *)
+  LIBAVFORMAT_MIN_VERSION_MAJOR   = 60;
+  LIBAVFORMAT_MIN_VERSION_MINOR   = 0;
+  LIBAVFORMAT_MIN_VERSION_RELEASE = 100;
+  LIBAVFORMAT_MIN_VERSION = (LIBAVFORMAT_MIN_VERSION_MAJOR * VERSION_MAJOR) +
+                            (LIBAVFORMAT_MIN_VERSION_MINOR * VERSION_MINOR) +
+                            (LIBAVFORMAT_MIN_VERSION_RELEASE * VERSION_RELEASE);
+
+(* Check if linked versions are supported *)
+{$IF (LIBAVFORMAT_VERSION < LIBAVFORMAT_MIN_VERSION)}
+  {$MESSAGE Error 'Linked version of libavformat is too old!'}
+{$IFEND}
+
+(* Check if linked versions are supported *)
+{$IF (LIBAVFORMAT_VERSION > LIBAVFORMAT_MAX_VERSION)}
+  {$MESSAGE Error 'Linked version of libavformat is not yet supported!'}
+{$IFEND}
+
+const
+  AVFMT_FLAG_GENPTS = 1;
+  AVSEEK_FLAG_ANY = 4;
+  AVSEEK_FLAG_BACKWARD = 1;
+type
+  PAVInputFormat = ^TAVInputFormat;
+  PAVStream = ^TAVStream;
+  PPAVStream = ^PAVStream;
+  PAVFormatContext = ^TAVFormatContext;
+  PPAVFormatContext = ^PAVFormatContext;
+  TAVFormatContext = record
+    we_do_not_use_av_class: pointer;
+    iformat: PAVInputFormat;
+    we_do_not_use_oformat: pointer;
+    we_do_not_use_priv_data: pointer;
+    pb: ^TAVIOContext;
+    we_do_not_use_ctx_flags: cint;
+    nb_streams: cuint;
+    streams: PPAVStream;
+    url: ^AnsiChar;
+    start_time: cint64;
+    duration: cint64;
+    we_do_not_use_bit_rate: cint64;
+    we_do_not_use_packet_size: cuint;
+    we_do_not_use_max_delay: cint;
+    flags: cint;
+    do_not_instantiate_this_record: incomplete_record;
+  end;
+  TAVStream = record
+    we_do_not_use_av_class: pointer;
+    we_do_not_use_index: cint;
+    we_do_not_use_id: cint;
+    codecpar: ^TAVCodecParameters;
+    we_do_not_use_priv_data: pointer;
+    time_base: TAVRational;
+    start_time: cint64;
+    we_do_not_use_duration: cint64;
+    we_do_not_use_nb_frames: cint64;
+    we_do_not_use_disposition: cint;
+    we_do_not_use_discard: cenum;
+    we_do_not_use_sample_aspect_ratio: TAVRational;
+    we_do_not_use_metadata: PAVDictionary;
+    we_do_not_use_avg_frame_rate: TAVRational;
+    we_do_not_use_attached_pic: TAVPacket;
+    we_do_not_use_side_data: pointer;
+    we_do_not_use_nb_side_data: cint;
+    we_do_not_use_event_flags: cint;
+    r_frame_rate: TAVRational;
+    do_not_instantiate_this_record: incomplete_record;
+  end;
+  TAVInputFormat = record
+    name: ^AnsiChar;
+    do_not_instantiate_this_record: incomplete_record;
+  end;
+function avformat_alloc_context(): PAVFormatContext; cdecl; external av__format;
+function avformat_open_input(ps: PPAVFormatContext; url: PAnsiChar; fmt: PAVInputFormat; options: PPAVDictionary): cint; cdecl; external av__format;
+procedure avformat_close_input(s: PPAVFormatContext); cdecl; external av__format;
+function avformat_version(): cuint; cdecl; external av__format;
+function avformat_find_stream_info(ic: PAVFormatContext; options: PPAVDictionary): cint; cdecl; external av__format;
+function av_read_frame(s: PAVFormatContext; var pkt: TAVPacket): cint; cdecl; external av__format;
+function av_seek_frame(s: PAVFormatContext; stream_index: cint; timestamp: cint64; flags: cint): cint; cdecl; external av__format;
+implementation
+end.
diff --git a/src/lib/ffmpeg-6.0/avio.pas b/src/lib/ffmpeg-6.0/avio.pas
new file mode 100644
index 000000000..bb0ba1de3
--- /dev/null
+++ b/src/lib/ffmpeg-6.0/avio.pas
@@ -0,0 +1,47 @@
+unit avio;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+{$IFDEF DARWIN}
+  {$linklib libavformat}
+{$ENDIF}
+
+interface
+
+uses
+  ctypes,
+  avutil,
+  SysUtils,
+  UConfig;
+const
+  AVSEEK_SIZE = 65536;
+type
+  PAVIOContext = ^TAVIOContext;
+  TAVIOContext = record
+    we_do_not_use_av_class: pointer;
+    buffer: ^cuchar;
+    we_do_not_use_buffer_size: cint;
+    we_do_not_use_buf_ptr: pcuchar;
+    we_do_not_use_buf_end: pcuchar;
+    opaque: pointer;
+    we_do_not_use_read_packet: cfunctionpointer;
+    we_do_not_use_write_packet: cfunctionpointer;
+    we_do_not_use_seek: cfunctionpointer;
+    pos: cint64;
+    eof_reached: cint;
+    error: cint;
+    do_not_instantiate_this_record: incomplete_record;
+  end;
+  TReadWriteFunc = function(opaque: pointer; buf: pbytearray; buf_size: cint): cint; cdecl;
+  TSeekFunc = function(opaque: pointer; offset: cint64; whence: cint): cint64; cdecl;
+function avio_alloc_context(buffer: pcuint8; buffer_size: cint; write_flag: cint; opaque: pointer; read_packet: TReadWriteFunc; write_packet: TReadWriteFunc; seek: TSeekFunc): PAVIOContext; cdecl; external av__format;
+function avio_feof(s: PAVIOContext): cint; cdecl; external av__format;
+function avio_size(s: PAVIOContext): cint64; cdecl; external av__format;
+implementation
+end.
diff --git a/src/lib/ffmpeg-6.0/avutil.pas b/src/lib/ffmpeg-6.0/avutil.pas
new file mode 100644
index 000000000..55878a02d
--- /dev/null
+++ b/src/lib/ffmpeg-6.0/avutil.pas
@@ -0,0 +1,186 @@
+unit avutil;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$MODESWITCH ADVANCEDRECORDS}
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+{$IFDEF DARWIN}
+  {$linklib libavutil}
+{$ENDIF}
+
+interface
+
+uses
+  ctypes,
+  rational,
+  {$IFDEF UNIX}
+  BaseUnix,
+  {$ENDIF}
+  SysUtils,
+  UConfig;
+
+
+const
+  (* Max. supported version by this header *)
+  LIBAVUTIL_MAX_VERSION_MAJOR   = 58;
+  LIBAVUTIL_MAX_VERSION_MINOR   = 2;
+  LIBAVUTIL_MAX_VERSION_RELEASE = 100;
+  LIBAVUTIL_MAX_VERSION = (LIBAVUTIL_MAX_VERSION_MAJOR * VERSION_MAJOR) +
+                          (LIBAVUTIL_MAX_VERSION_MINOR * VERSION_MINOR) +
+                          (LIBAVUTIL_MAX_VERSION_RELEASE * VERSION_RELEASE);
+
+  (* Min. supported version by this header *)
+  LIBAVUTIL_MIN_VERSION_MAJOR   = 57;
+  LIBAVUTIL_MIN_VERSION_MINOR   = 17;
+  LIBAVUTIL_MIN_VERSION_RELEASE = 100;
+  LIBAVUTIL_MIN_VERSION = (LIBAVUTIL_MIN_VERSION_MAJOR * VERSION_MAJOR) +
+                          (LIBAVUTIL_MIN_VERSION_MINOR * VERSION_MINOR) +
+                          (LIBAVUTIL_MIN_VERSION_RELEASE * VERSION_RELEASE);
+
+(* Check if linked versions are supported *)
+{$IF (LIBAVUTIL_VERSION < LIBAVUTIL_MIN_VERSION)}
+  {$MESSAGE Error 'Linked version of libavutil is too old!'}
+{$IFEND}
+
+{$IF (LIBAVUTIL_VERSION > LIBAVUTIL_MAX_VERSION)}
+  {$MESSAGE Error 'Linked version of libavutil is not yet supported!'}
+{$IFEND}
+
+type
+  (*
+   * We use this record as the last element of records that are not supposed
+   * to be allocated by pascal code either because the declaration of the
+   * record has never been completed or because FFmpeg does the allocation
+   * internally.
+   *
+   * The exceed_stack array has been declared as 10MB array because the default
+   * soft stack limit on Linux is less than that. So every time someone tries
+   * to allocate this structure on the stack, it will crash unless the soft
+   * limit has been raised.
+   *
+   * The existence of a constructor will cause Free Pascal to issue a warning
+   * if an element of this type has been created without calling the
+   * constructor.
+   *)
+  incomplete_record = record
+    exceed_stack: array [0..10000000] of byte;
+    constructor Never_Call(dummy: integer);
+  end;
+
+type
+  (*
+   * The C standard allows for function pointers to have a different size than
+   * data pointers. In practice the size differs only on exotic architectures.
+   *)
+  cfunctionpointer = procedure;cdecl;
+  (*
+   * Here we assume that the size of an enum is the same regardless of the
+   * values it needs to hold. This is not always the case. The AMD64 System V
+   * ABI says:
+   *
+   *     C++ and some implementations of C permit enums larger than an int.
+   *     The underlying type is bumped to an unsigned int, long int or
+   *     unsigned long int, in that order.
+   *
+   * Apart from that there are systems where the default enum size is smaller
+   * than an int. But these are unlikely to run FFmpeg.
+   *
+   * So don't use this type to replace enums that don't fit into 32 bits.
+   *)
+  cenum = cint;
+
+const
+  AVERROR_EOF = -(ord('E') or (ord('O') shl 8) or (ord('F') shl 16) or (ord(' ') shl 24));
+  AV_LOG_FATAL = 8;
+  AV_NOPTS_VALUE = -9223372036854775808;
+  AV_NUM_DATA_POINTERS = 8;
+  AV_TIME_BASE = 1000000;
+{$IFDEF UNIX}
+  EAGAIN = ESysEAGAIN;
+{$ELSE}
+  EAGAIN = 11;
+{$ENDIF}
+
+type
+  TAVSampleFormat = (
+    AV_SAMPLE_FMT_U8,
+    AV_SAMPLE_FMT_S16,
+    AV_SAMPLE_FMT_S32,
+    AV_SAMPLE_FMT_FLT,
+    AV_SAMPLE_FMT_DBL
+  );
+  PAVPixelFormat = ^TAVPixelFormat;
+  TAVPixelFormat = (
+    AV_PIX_FMT_RGB24 = 2,
+    AV_PIX_FMT_BGR24,
+    AV_PIX_FMT_RGBA = 26,
+    AV_PIX_FMT_BGRA = 28
+  );
+  TAVMediaType = (
+    AVMEDIA_TYPE_VIDEO,
+    AVMEDIA_TYPE_AUDIO
+  );
+  ppcuint8 = ^pcuint8;
+  PAVFrame = ^TAVFrame;
+  PPAVFrame = ^PAVFrame;
+  TAVFrame = record
+    data: array [0..AV_NUM_DATA_POINTERS-1] of ^cuint8;
+    linesize: array [0..AV_NUM_DATA_POINTERS-1] of cint;
+    extended_data: ^pcuint8;
+    we_do_not_use_width: cint;
+    we_do_not_use_height: cint;
+    nb_samples: cint;
+    we_do_not_use_format: cint;
+    we_do_not_use_key_frame: cint;
+    we_do_not_use_pict_type: cenum;
+    we_do_not_use_sample_aspect_ratio: TAVRational;
+    pts: cint64;
+    pkt_dts: cint64;
+    we_do_not_use_time_base: TAVRational;
+    we_do_not_use_coded_picture_number: cint;
+    we_do_not_use_display_picture_number: cint;
+    we_do_not_use_quality: cint;
+    we_do_not_use_opaque: pointer;
+    repeat_pict: cint;
+    do_not_instantiate_this_record: incomplete_record;
+  end;
+  PAVDictionary = ^TAVDictionary;
+  PPAVDictionary = ^PAVDictionary;
+  TAVDictionary = record
+    do_not_instantiate_this_record: incomplete_record;
+  end;
+procedure av_free(ptr: pointer); cdecl; external av__util;
+procedure av_freep(ptr: pointer); cdecl; external av__util;
+function av_malloc(size: csize_t): pointer; cdecl; external av__util;
+function avutil_version(): cuint; cdecl; external av__util;
+function av_frame_alloc(): PAVFrame; cdecl; external av__util;
+procedure av_frame_free(frame: PPAVFrame); cdecl; external av__util;
+function av_image_alloc(pointers: ppcuint8; linesizes: pcint; w: cint; h: cint; pix_fmt: TAVPixelFormat; align: cint): cint; cdecl; external av__util;
+function AVERROR(e: cint): cint; {$IFDEF HasInline}inline;{$ENDIF}
+function av_opt_set_int(obj: pointer; name: PAnsiChar; val: cint64; search_flags: cint): cint; cdecl; external av__util;
+function av_opt_set_channel_layout(obj: pointer; name: PAnsiChar; ch_layout: cint64; search_flags: cint): cint; cdecl; external av__util;
+function av_opt_set_sample_fmt(obj: pointer; name: PAnsiChar; fmt: TAVSampleFormat; search_flags: cint): cint; cdecl; external av__util;
+function av_samples_alloc(var audio_data: pcuint8; linesize: pcint; nb_channels: cint; nb_samples: cint; sample_fmt: TAVSampleFormat; align: cint): cint; cdecl; external av__util;
+function av_get_packed_sample_fmt(sample_fmt: TAVSampleFormat): TAVSampleFormat; cdecl; external av__util;
+function av_get_bytes_per_sample(sample_fmt: TAVSampleFormat): cint; cdecl; external av__util;
+procedure av_log_set_level(level: cint); cdecl; external av__util;
+implementation
+function AVERROR(e: cint): cint; {$IFDEF HasInline}inline;{$ENDIF}
+begin
+  if EAGAIN < 0 then
+    AVERROR := e
+  else
+    AVERROR := -e;
+end;
+
+constructor incomplete_record.Never_Call(dummy: integer);
+begin
+  abort;
+end;
+
+end.
diff --git a/src/lib/ffmpeg-6.0/rational.pas b/src/lib/ffmpeg-6.0/rational.pas
new file mode 100644
index 000000000..46c6ccba8
--- /dev/null
+++ b/src/lib/ffmpeg-6.0/rational.pas
@@ -0,0 +1,32 @@
+unit rational;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+interface
+
+uses
+  ctypes;
+type
+  TAVRational = record
+    num: csint;
+    den: csint;
+  end;
+function av_q2d(a: TAVRational): cdouble; {$IFDEF HasInline}inline;{$ENDIF}
+function av_inv_q(q: TAVRational): TAVRational; {$IFDEF HasInline}inline;{$ENDIF}
+implementation
+function av_q2d(a: TAVRational): cdouble; {$IFDEF HasInline}inline;{$ENDIF}
+begin
+  av_q2d := a.num / a.den;
+end;
+function av_inv_q(q: TAVRational): TAVRational; {$IFDEF HasInline}inline;{$ENDIF}
+begin
+  av_inv_q.num := q.den;
+  av_inv_q.den := q.num;
+end;
+end.
diff --git a/src/lib/ffmpeg-6.0/swresample.pas b/src/lib/ffmpeg-6.0/swresample.pas
new file mode 100644
index 000000000..1637a4e4e
--- /dev/null
+++ b/src/lib/ffmpeg-6.0/swresample.pas
@@ -0,0 +1,61 @@
+unit swresample;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+{$IFDEF DARWIN}
+  {$linklib libswresample}
+{$ENDIF}
+
+interface
+
+uses
+  ctypes,
+  avutil,
+  UConfig;
+
+const
+  (* Supported version by this header *)
+  LIBSWRESAMPLE_MAX_VERSION_MAJOR   = 4;
+  LIBSWRESAMPLE_MAX_VERSION_MINOR   = 10;
+  LIBSWRESAMPLE_MAX_VERSION_RELEASE = 100;
+  LIBSWRESAMPLE_MAX_VERSION = (LIBSWRESAMPLE_MAX_VERSION_MAJOR * VERSION_MAJOR) +
+                           (LIBSWRESAMPLE_MAX_VERSION_MINOR * VERSION_MINOR) +
+                           (LIBSWRESAMPLE_MAX_VERSION_RELEASE * VERSION_RELEASE);
+
+  (* Min. supported version by this header *)
+  LIBSWRESAMPLE_MIN_VERSION_MAJOR   = 0;
+  LIBSWRESAMPLE_MIN_VERSION_MINOR   = 15;
+  LIBSWRESAMPLE_MIN_VERSION_RELEASE = 100;
+  LIBSWRESAMPLE_MIN_VERSION = (LIBSWRESAMPLE_MIN_VERSION_MAJOR * VERSION_MAJOR) +
+                            (LIBSWRESAMPLE_MIN_VERSION_MINOR * VERSION_MINOR) +
+                            (LIBSWRESAMPLE_MIN_VERSION_RELEASE * VERSION_RELEASE);
+
+(* Check if linked versions are supported *)
+{$IF (LIBSWRESAMPLE_VERSION < LIBSWRESAMPLE_MIN_VERSION)}
+  {$MESSAGE Error 'Linked version of libswresample is too old!'}
+{$IFEND}
+
+(* Check if linked version is supported *)
+{$IF (LIBSWRESAMPLE_VERSION > LIBSWRESAMPLE_MAX_VERSION)}
+  {$MESSAGE Error 'Linked version of libswresample is not yet supported!'}
+{$IFEND}
+
+type
+  PSwrContext = ^TSwrContext;
+  PPSwrContext = ^PSwrContext;
+  TSwrContext = record
+    do_not_instantiate_this_record: incomplete_record;
+  end;
+function swr_alloc(): PSwrContext; cdecl; external sw__resample;
+function swr_alloc_set_opts(s: PSwrContext; out_ch_layout: cint64; out_sample_fmt: TAVSampleFormat; out_sample_rate: cint; in_ch_layout: cint64; in_sample_fmt: TAVSampleFormat; in_sample_rate: cint; log_offset: cint; log_ctx: pointer): PSwrContext; cdecl; external sw__resample;
+function swr_init(s: PSwrContext): cint; cdecl; external sw__resample;
+procedure swr_free(s: PPSwrContext); cdecl; external sw__resample;
+function swr_convert(s: PSwrContext; var out: pcuint8; out_count: cint; var in_: pcuint8; in_count: cint): cint; cdecl; external sw__resample;
+implementation
+end.
diff --git a/src/lib/ffmpeg-6.0/swscale.pas b/src/lib/ffmpeg-6.0/swscale.pas
new file mode 100644
index 000000000..07e2d157b
--- /dev/null
+++ b/src/lib/ffmpeg-6.0/swscale.pas
@@ -0,0 +1,53 @@
+unit swscale;
+
+{$IFDEF FPC}
+  {$MODE DELPHI}
+  {$PACKENUM 4}    (* use 4-byte enums *)
+  {$PACKRECORDS C} (* C/C++-compatible record packing *)
+{$ELSE}
+  {$MINENUMSIZE 4} (* use 4-byte enums *)
+{$ENDIF}
+
+{$IFDEF DARWIN}
+  {$linklib libswscale}
+{$ENDIF}
+
+interface
+
+uses
+  ctypes,
+  avutil,
+  UConfig;
+
+const
+  (* Max. supported version by this header *)
+  LIBSWSCALE_MAX_VERSION_MAJOR   =  7;
+  LIBSWSCALE_MAX_VERSION_MINOR   =  1;
+  LIBSWSCALE_MAX_VERSION_RELEASE =  100;
+  LIBSWSCALE_MAX_VERSION = (LIBSWSCALE_MAX_VERSION_MAJOR * VERSION_MAJOR) +
+                           (LIBSWSCALE_MAX_VERSION_MINOR * VERSION_MINOR) +
+                           (LIBSWSCALE_MAX_VERSION_RELEASE * VERSION_RELEASE);
+
+(* Check if linked versions are supported *)
+{$IF (LIBSWSCALE_VERSION > LIBSWSCALE_MAX_VERSION)}
+  {$MESSAGE Error 'Linked version of libswscale is not yet supported!'}
+{$IFEND}
+
+
+const
+  SWS_FAST_BILINEAR = 1;
+type
+  PSwsContext = ^TSwsContext;
+  TSwsContext = record
+    do_not_instantiate_this_record: incomplete_record;
+  end;
+  PSwsFilter = ^TSwsFilter;
+  TSwsFilter = record
+    do_not_instantiate_this_record: incomplete_record;
+  end;
+function swscale_version(): cuint; cdecl; external sw__scale;
+function sws_isSupportedInput(pix_fmt: TAVPixelFormat): cint; cdecl; external sw__scale;
+function sws_scale(c: PSwsContext; srcSlice: ppcuint8; srcStride: pcint; srcSliceY: cint; srcSliceH: cint; dst: ppcuint8; dstStride: pcint): cint; cdecl; external sw__scale;
+function sws_getContext(srcW: cint; srcH: cint; srcFormat: TAVPixelFormat; dstW: cint; dstH: cint; dstFormat: TAVPixelFormat; flags: cint; srcFilter: PSwsFilter; dstFilter: PSwsFilter; param: pcdouble): PSwsContext; cdecl; external sw__scale;
+implementation
+end.
