summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbdunahu <bdunahu@operationnull.com>2026-06-25 22:30:30 -0400
committerCayetano Santos <csantosb@inventati.org>2026-07-02 10:42:33 +0200
commitd11a4d858be332b2c3ccb72671ea61bb645d4c1b (patch)
tree2e08fe0a3f45f7180e6fab6f4916a4b3eefc4fe4
parentd410120a9e5d456bf87effc8229cf84b9acb8d44 (diff)
gnu: hedgewars: Fix build.
* gnu/packages/patches/hedgewars-fix-pascalbasic-name-conflict.patch: New file. * gnu/packages/patches/hedgewars-support-ffmpegv6.patch: New file. * gnu/local.mk: Register new patchfiles. * gnu/packages/games.scm (hedgewars)[source]: Apply them. [#:configure-flags]: Set NOVERSIONINFOUPDATE to ON. [#:phases]: Add 'import-control-dot-monad'. [inputs]: Remove ffmpeg-4; add ffmpeg. Fixes: guix/guix!9342 Merges: guix/guix!9654 Signed-off-by: Cayetano Santos <csantosb@inventati.org>
-rw-r--r--gnu/local.mk2
-rw-r--r--gnu/packages/games.scm33
-rw-r--r--gnu/packages/patches/hedgewars-fix-pascalbasic-name-conflict.patch51
-rw-r--r--gnu/packages/patches/hedgewars-support-ffmpegv6.patch456
4 files changed, 538 insertions, 4 deletions
diff --git a/gnu/local.mk b/gnu/local.mk
index 678a1849efe..767076c95b8 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1598,6 +1598,8 @@ dist_patch_DATA = \
1598 %D%/packages/patches/hdf4-reproducibility.patch \ 1598 %D%/packages/patches/hdf4-reproducibility.patch \
1599 %D%/packages/patches/hdf4-shared-fortran.patch \ 1599 %D%/packages/patches/hdf4-shared-fortran.patch \
1600 %D%/packages/patches/hal-disable-googletest.patch \ 1600 %D%/packages/patches/hal-disable-googletest.patch \
1601 %D%/packages/patches/hedgewars-fix-pascalbasic-name-conflict.patch \
1602 %D%/packages/patches/hedgewars-support-ffmpegv6.patch \
1601 %D%/packages/patches/hdf5-config-date.patch \ 1603 %D%/packages/patches/hdf5-config-date.patch \
1602 %D%/packages/patches/hdf-eos2-build-shared.patch \ 1604 %D%/packages/patches/hdf-eos2-build-shared.patch \
1603 %D%/packages/patches/hdf-eos2-remove-gctp.patch \ 1605 %D%/packages/patches/hdf-eos2-remove-gctp.patch \
diff --git a/gnu/packages/games.scm b/gnu/packages/games.scm
index 0bac113b9f9..badcd8dc5a2 100644
--- a/gnu/packages/games.scm
+++ b/gnu/packages/games.scm
@@ -11820,6 +11820,10 @@ play with up to four players simultaneously. It has network support.")
11820(define-public hedgewars 11820(define-public hedgewars
11821 (package 11821 (package
11822 (name "hedgewars") 11822 (name "hedgewars")
11823 ;; TODO: Delete phase 'import-control-dot-monad' on versions >1.0.3.
11824 ;; TODO: Remove patch 'hedgewars-support-ffmpegv6' on versions >1.0.2.
11825 ;; TODO: Remove patch 'hedgewars-fix-pascalbasic-name-conflict'
11826 ;; on versions >1.0.3.
11823 (version "1.0.2") 11827 (version "1.0.2")
11824 (source (origin 11828 (source (origin
11825 (method url-fetch) 11829 (method url-fetch)
@@ -11827,17 +11831,38 @@ play with up to four players simultaneously. It has network support.")
11827 "hedgewars-src-" version ".tar.bz2")) 11831 "hedgewars-src-" version ".tar.bz2"))
11828 (sha256 11832 (sha256
11829 (base32 11833 (base32
11830 "04pjpkjhpy720n803gv35iygmjdvsrmw13mih4ympjnqbgjfa7r0")))) 11834 "04pjpkjhpy720n803gv35iygmjdvsrmw13mih4ympjnqbgjfa7r0"))
11835 (patches
11836 (search-patches "hedgewars-fix-pascalbasic-name-conflict.patch"
11837 "hedgewars-support-ffmpegv6.patch"))))
11831 (build-system qt-build-system) 11838 (build-system qt-build-system)
11832 (arguments 11839 (arguments
11833 (list 11840 (list
11834 ;; XXX: Engine is built as Pascal source code, requiring Free Pascal 11841 ;; XXX: Engine is built as Pascal source code, requiring Free Pascal
11835 ;; Compiler, which we haven't packaged yet. With the flag below, we use 11842 ;; Compiler, which we haven't packaged yet. With the flag below, we use
11836 ;; a Pascal to C translator and Clang instead. 11843 ;; a Pascal to C translator and Clang instead.
11837 #:configure-flags #~(list "-DBUILD_ENGINE_C=ON" 11844 #:configure-flags
11838 "-Dhaskell_flags=-dynamic;-fPIC") 11845 #~'("-DBUILD_ENGINE_C=ON"
11846 "-DNOVERSIONINFOUPDATE=ON"
11847 "-Dhaskell_flags=-dynamic;-fPIC")
11839 #:phases 11848 #:phases
11840 #~(modify-phases %standard-phases 11849 #~(modify-phases %standard-phases
11850 (add-after 'unpack 'import-control-dot-monad
11851 (lambda _
11852 (with-directory-excursion "gameServer"
11853 (substitute* '("ClientIO.hs"
11854 "HandlerUtils.hs"
11855 "HWProtoChecker.hs"
11856 "HWProtoCore.hs"
11857 "HWProtoLobbyState.hs"
11858 "HandlerUtils.hs"
11859 "ServerState.hs"
11860 "Votes.hs"
11861 "../tools/pas2c/Pas2C.hs")
11862 ;; All files define `import Control.Monad.{something}`.
11863 ;; Our symbols are in Control.Monad now as well.
11864 (("import Control\\.Monad" all)
11865 (string-append all "\n" "import Control.Monad"))))))
11841 (replace 'check 11866 (replace 'check
11842 (lambda* (#:key tests? #:allow-other-keys) 11867 (lambda* (#:key tests? #:allow-other-keys)
11843 (when tests? 11868 (when tests?
@@ -11851,7 +11876,7 @@ play with up to four players simultaneously. It has network support.")
11851 (string-append "../hedgewars-src-" #$version) 11876 (string-append "../hedgewars-src-" #$version)
11852 (install-file "misc/hedgewars.png" icons)))))))) 11877 (install-file "misc/hedgewars.png" icons))))))))
11853 (inputs 11878 (inputs
11854 (list ffmpeg-4 11879 (list ffmpeg
11855 freeglut 11880 freeglut
11856 ghc-entropy 11881 ghc-entropy
11857 ghc-hslogger 11882 ghc-hslogger
diff --git a/gnu/packages/patches/hedgewars-fix-pascalbasic-name-conflict.patch b/gnu/packages/patches/hedgewars-fix-pascalbasic-name-conflict.patch
new file mode 100644
index 00000000000..3c06e3cd563
--- /dev/null
+++ b/gnu/packages/patches/hedgewars-fix-pascalbasic-name-conflict.patch
@@ -0,0 +1,51 @@
1From ab3fac1e3b354890a3925235881673b97691dba2 Mon Sep 17 00:00:00 2001
2From: unc0rr <unc0rr@gmail.com>
3Date: Fri, 16 Jun 2023 08:10:45 +0200
4Subject: [PATCH] Fix pas2c build erroring after parsec added function we
5 already define
6
7---
8 tools/pas2c/PascalBasics.hs | 2 +-
9 tools/pas2c/PascalParser.hs | 2 +-
10 tools/pas2c/PascalPreprocessor.hs | 2 +-
11 3 files changed, 3 insertions(+), 3 deletions(-)
12
13diff --git a/tools/pas2c/PascalBasics.hs b/tools/pas2c/PascalBasics.hs
14index f4eba72f87..eaf4d596db 100644
15--- a/tools/pas2c/PascalBasics.hs
16+++ b/tools/pas2c/PascalBasics.hs
17@@ -2,7 +2,7 @@
18 module PascalBasics where
19
20 import Text.Parsec.Combinator
21-import Text.Parsec.Char
22+import Text.Parsec.Char hiding (string')
23 import Text.Parsec.Prim
24 import Text.Parsec.Token
25 import Text.Parsec.Language
26diff --git a/tools/pas2c/PascalParser.hs b/tools/pas2c/PascalParser.hs
27index 2edd7a2479..c97bb359aa 100644
28--- a/tools/pas2c/PascalParser.hs
29+++ b/tools/pas2c/PascalParser.hs
30@@ -4,7 +4,7 @@ module PascalParser (
31 )
32 where
33
34-import Text.Parsec
35+import Text.Parsec hiding (string')
36 import Text.Parsec.Token
37 import Text.Parsec.Expr
38 import Control.Monad
39diff --git a/tools/pas2c/PascalPreprocessor.hs b/tools/pas2c/PascalPreprocessor.hs
40index 4db8eaa8ae..93a176209c 100644
41--- a/tools/pas2c/PascalPreprocessor.hs
42+++ b/tools/pas2c/PascalPreprocessor.hs
43@@ -1,7 +1,7 @@
44 {-# LANGUAGE ScopedTypeVariables #-}
45 module PascalPreprocessor where
46
47-import Text.Parsec
48+import Text.Parsec hiding (string')
49 import Control.Monad.IO.Class
50 import Control.Monad
51 import System.IO
diff --git a/gnu/packages/patches/hedgewars-support-ffmpegv6.patch b/gnu/packages/patches/hedgewars-support-ffmpegv6.patch
new file mode 100644
index 00000000000..d656a6c7cc8
--- /dev/null
+++ b/gnu/packages/patches/hedgewars-support-ffmpegv6.patch
@@ -0,0 +1,456 @@
1From 9445c40eb179047e85c47acedb724eee42e3f0df Mon Sep 17 00:00:00 2001
2From: Pekka Ristola <pekkarr@protonmail.com>
3Date: Mon, 27 Jan 2025 19:08:05 +0100
4Subject: [PATCH] Add support for ffmpeg 6.0 - Use the new
5 send_frame/receive_packet API for encoding - Use the new channel layout API
6 for audio - Fix audio recording - Copy codec parameters to the stream
7 parameters - Set correct pts for audio frames - Read audio samples from
8 file directly to the refcounted AVFrame buffer instead of the `g_pSamples`
9 buffer - Use global AVPackets allocated with `av_packet_alloc` - Stop trying
10 to write more audio frames when `WriteAudioFrame` fails with a negative error
11 code - Fix segfault with `g_pContainer->url`. The field has to be allocated
12 with `av_malloc` before writing to it. It's set to `NULL` by default. -
13 Properly free allocations with `avcodec_free_context` and
14 `avformat_free_context`
15
16---
17 hedgewars/avwrapper/avwrapper.c | 234 +++++++++++++++++++++++++++-----
18 1 file changed, 203 insertions(+), 31 deletions(-)
19
20diff --git a/hedgewars/avwrapper/avwrapper.c b/hedgewars/avwrapper/avwrapper.c
21index 6c0fe739b4..3daeb07b75 100644
22--- a/hedgewars/avwrapper/avwrapper.c
23+++ b/hedgewars/avwrapper/avwrapper.c
24@@ -42,15 +42,19 @@
25 #define UNUSED(x) (void)(x)
26
27 static AVFormatContext* g_pContainer;
28-static AVOutputFormat* g_pFormat;
29+static const AVOutputFormat* g_pFormat;
30 static AVStream* g_pAStream;
31 static AVStream* g_pVStream;
32 static AVFrame* g_pAFrame;
33 static AVFrame* g_pVFrame;
34-static AVCodec* g_pACodec;
35-static AVCodec* g_pVCodec;
36+static const AVCodec* g_pACodec;
37+static const AVCodec* g_pVCodec;
38 static AVCodecContext* g_pAudio;
39 static AVCodecContext* g_pVideo;
40+#if LIBAVCODEC_VERSION_MAJOR >= 58
41+static AVPacket* g_pAPacket;
42+static AVPacket* g_pVPacket;
43+#endif
44
45 static int g_Width, g_Height;
46 static uint32_t g_Frequency, g_Channels;
47@@ -58,8 +62,13 @@ static int g_VQuality;
48 static AVRational g_Framerate;
49
50 static FILE* g_pSoundFile;
51+#if LIBAVUTIL_VERSION_MAJOR < 53
52 static int16_t* g_pSamples;
53+#endif
54 static int g_NumSamples;
55+#if LIBAVCODEC_VERSION_MAJOR >= 53
56+static int64_t g_NextAudioPts;
57+#endif
58
59
60 // compatibility section
61@@ -93,6 +102,8 @@ static void rescale_ts(AVPacket *pkt, AVRational ctb, AVRational stb)
62 if (pkt->duration > 0)
63 pkt->duration = av_rescale_q(pkt->duration, ctb, stb);
64 }
65+
66+#define avcodec_free_context(ctx) do { avcodec_close(*ctx); av_freep(ctx); } while (0)
67 #endif
68
69 #ifndef AV_CODEC_CAP_DELAY
70@@ -165,8 +176,42 @@ static void Log(const char* pFmt, ...)
71 AddFileLogRaw(Buffer);
72 }
73
74+#if LIBAVCODEC_VERSION_MAJOR >= 58
75+static int EncodeAndWriteFrame(
76+ const AVStream* pStream,
77+ AVCodecContext* pCodecContext,
78+ const AVFrame* pFrame,
79+ AVPacket* pPacket)
80+{
81+ int ret;
82+
83+ ret = avcodec_send_frame(pCodecContext, pFrame);
84+ if (ret < 0)
85+ return FatalError("avcodec_send_frame failed: %d", ret);
86+ while (1)
87+ {
88+ ret = avcodec_receive_packet(pCodecContext, pPacket);
89+ if (ret == AVERROR(EAGAIN))
90+ return 1;
91+ else if (ret == AVERROR_EOF)
92+ return 0;
93+ else if (ret < 0)
94+ return FatalError("avcodec_receive_packet failed: %d", ret);
95+
96+ av_packet_rescale_ts(pPacket, pCodecContext->time_base, pStream->time_base);
97+
98+ // Write the compressed frame to the media file.
99+ pPacket->stream_index = pStream->index;
100+ ret = av_interleaved_write_frame(g_pContainer, pPacket);
101+ if (ret != 0)
102+ return FatalError("Error while writing frame: %d", ret);
103+ }
104+}
105+#endif
106+
107 static void AddAudioStream()
108 {
109+ int ret;
110 g_pAStream = avformat_new_stream(g_pContainer, g_pACodec);
111 if(!g_pAStream)
112 {
113@@ -176,20 +221,44 @@ static void AddAudioStream()
114 g_pAStream->id = 1;
115
116 #if LIBAVCODEC_VERSION_MAJOR >= 59
117- const AVCodec *audio_st_codec = avcodec_find_decoder(g_pAStream->codecpar->codec_id);
118- g_pAudio = avcodec_alloc_context3(audio_st_codec);
119- avcodec_parameters_to_context(g_pAudio, g_pAStream->codecpar);
120+ g_pAudio = avcodec_alloc_context3(g_pACodec);
121 #else
122 g_pAudio = g_pAStream->codec;
123-#endif
124
125 avcodec_get_context_defaults3(g_pAudio, g_pACodec);
126 g_pAudio->codec_id = g_pACodec->id;
127+#endif
128
129 // put parameters
130 g_pAudio->sample_fmt = AV_SAMPLE_FMT_S16;
131 g_pAudio->sample_rate = g_Frequency;
132+#if LIBAVCODEC_VERSION_MAJOR >= 60
133+ const AVChannelLayout* pChLayout = g_pACodec->ch_layouts;
134+ if (pChLayout)
135+ {
136+ for (; pChLayout->nb_channels; pChLayout++)
137+ {
138+ if (pChLayout->nb_channels == g_Channels)
139+ {
140+ ret = av_channel_layout_copy(&g_pAudio->ch_layout, pChLayout);
141+ if (ret != 0)
142+ {
143+ Log("Channel layout copy failed: %d\n", ret);
144+ return;
145+ }
146+ break;
147+ }
148+ }
149+ }
150+ if (!g_pAudio->ch_layout.nb_channels)
151+ {
152+ // no suitable layout found
153+ g_pAudio->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
154+ g_pAudio->ch_layout.nb_channels = g_Channels;
155+ }
156+#else
157 g_pAudio->channels = g_Channels;
158+#endif
159
160 // set time base as invers of sample rate
161 g_pAudio->time_base.den = g_pAStream->time_base.den = g_Frequency;
162@@ -213,6 +282,15 @@ static void AddAudioStream()
163 return;
164 }
165
166+#if LIBAVCODEC_VERSION_MAJOR >= 58
167+ ret = avcodec_parameters_from_context(g_pAStream->codecpar, g_pAudio);
168+ if (ret < 0)
169+ {
170+ Log("Could not copy parameters from codec context: %d\n", ret);
171+ return;
172+ }
173+#endif
174+
175 #if LIBAVCODEC_VERSION_MAJOR >= 54
176 if (g_pACodec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)
177 #else
178@@ -221,13 +299,46 @@ static void AddAudioStream()
179 g_NumSamples = 4096;
180 else
181 g_NumSamples = g_pAudio->frame_size;
182- g_pSamples = (int16_t*)av_malloc(g_NumSamples*g_Channels*sizeof(int16_t));
183 g_pAFrame = av_frame_alloc();
184 if (!g_pAFrame)
185 {
186 Log("Could not allocate frame\n");
187 return;
188 }
189+#if LIBAVUTIL_VERSION_MAJOR >= 53
190+#if LIBAVCODEC_VERSION_MAJOR >= 60
191+ ret = av_channel_layout_copy(&g_pAFrame->ch_layout, &g_pAudio->ch_layout);
192+ if (ret != 0)
193+ {
194+ Log("Channel layout copy for frame failed: %d\n", ret);
195+ return;
196+ }
197+#else
198+ g_pAFrame->channels = g_pAudio->channels;
199+#endif
200+ g_pAFrame->format = g_pAudio->sample_fmt;
201+ g_pAFrame->sample_rate = g_pAudio->sample_rate;
202+ g_pAFrame->nb_samples = g_NumSamples;
203+ ret = av_frame_get_buffer(g_pAFrame, 1);
204+ if (ret < 0)
205+ {
206+ Log("Failed to allocate frame buffer: %d\n", ret);
207+ return;
208+ }
209+#else
210+ g_pSamples = (int16_t*)av_malloc(g_NumSamples*g_Channels*sizeof(int16_t));
211+#endif
212+#if LIBAVCODEC_VERSION_MAJOR >= 58
213+ g_pAPacket = av_packet_alloc();
214+ if (!g_pAPacket)
215+ {
216+ Log("Could not allocate audio packet\n");
217+ return;
218+ }
219+#endif
220+#if LIBAVCODEC_VERSION_MAJOR >= 53
221+ g_NextAudioPts = 0;
222+#endif
223 }
224
225 // returns non-zero if there is more sound, -1 in case of error
226@@ -236,22 +347,46 @@ static int WriteAudioFrame()
227 if (!g_pAStream)
228 return 0;
229
230- AVPacket Packet;
231- av_init_packet(&Packet);
232- Packet.data = NULL;
233- Packet.size = 0;
234+ int ret;
235+ int16_t* pData;
236+#if LIBAVUTIL_VERSION_MAJOR >= 53
237+ ret = av_frame_make_writable(g_pAFrame);
238+ if (ret < 0)
239+ return FatalError("Could not make audio frame writable: %d", ret);
240+ pData = (int16_t*) g_pAFrame->data[0];
241+#else
242+ pData = g_pSamples;
243+#endif
244
245- int NumSamples = fread(g_pSamples, 2*g_Channels, g_NumSamples, g_pSoundFile);
246+ int NumSamples = fread(pData, 2*g_Channels, g_NumSamples, g_pSoundFile);
247
248 #if LIBAVCODEC_VERSION_MAJOR >= 53
249 AVFrame* pFrame = NULL;
250 if (NumSamples > 0)
251 {
252 g_pAFrame->nb_samples = NumSamples;
253+ g_pAFrame->pts = g_NextAudioPts;
254+ g_NextAudioPts += NumSamples;
255+#if LIBAVUTIL_VERSION_MAJOR < 53
256 avcodec_fill_audio_frame(g_pAFrame, g_Channels, AV_SAMPLE_FMT_S16,
257- (uint8_t*)g_pSamples, NumSamples*2*g_Channels, 1);
258+ (uint8_t*)pData, NumSamples*2*g_Channels, 1);
259+#endif
260 pFrame = g_pAFrame;
261 }
262+#endif
263+
264+#if LIBAVCODEC_VERSION_MAJOR >= 58
265+ ret = EncodeAndWriteFrame(g_pAStream, g_pAudio, pFrame, g_pAPacket);
266+ if (ret < 0)
267+ return FatalError("Audio frame processing failed");
268+ return ret;
269+#else
270+ AVPacket Packet;
271+ av_init_packet(&Packet);
272+ Packet.data = NULL;
273+ Packet.size = 0;
274+
275+#if LIBAVCODEC_VERSION_MAJOR >= 53
276 // when NumSamples == 0 we still need to call encode_audio2 to flush
277 int got_packet;
278 if (avcodec_encode_audio2(g_pAudio, &Packet, pFrame, &got_packet) != 0)
279@@ -266,7 +401,7 @@ static int WriteAudioFrame()
280 int BufferSize = OUTBUFFER_SIZE;
281 if (g_pAudio->frame_size == 0)
282 BufferSize = NumSamples*g_Channels*2;
283- Packet.size = avcodec_encode_audio(g_pAudio, g_OutBuffer, BufferSize, g_pSamples);
284+ Packet.size = avcodec_encode_audio(g_pAudio, g_OutBuffer, BufferSize, pData);
285 if (Packet.size == 0)
286 return 1;
287 if (g_pAudio->coded_frame && g_pAudio->coded_frame->pts != AV_NOPTS_VALUE)
288@@ -280,25 +415,25 @@ static int WriteAudioFrame()
289 if (av_interleaved_write_frame(g_pContainer, &Packet) != 0)
290 return FatalError("Error while writing audio frame");
291 return 1;
292+#endif
293 }
294
295 // add a video output stream
296 static int AddVideoStream()
297 {
298+ int ret;
299 g_pVStream = avformat_new_stream(g_pContainer, g_pVCodec);
300 if (!g_pVStream)
301 return FatalError("Could not allocate video stream");
302
303 #if LIBAVCODEC_VERSION_MAJOR >= 59
304- const AVCodec *video_st_codec = avcodec_find_decoder(g_pVStream->codecpar->codec_id);
305- g_pVideo = avcodec_alloc_context3(video_st_codec);
306- avcodec_parameters_to_context(g_pVideo, g_pVStream->codecpar);
307+ g_pVideo = avcodec_alloc_context3(g_pVCodec);
308 #else
309 g_pVideo = g_pVStream->codec;
310-#endif
311
312 avcodec_get_context_defaults3(g_pVideo, g_pVCodec);
313 g_pVideo->codec_id = g_pVCodec->id;
314+#endif
315
316 // put parameters
317 // resolution must be a multiple of two
318@@ -361,6 +496,12 @@ static int AddVideoStream()
319 if (avcodec_open2(g_pVideo, g_pVCodec, NULL) < 0)
320 return FatalError("Could not open video codec %s", g_pVCodec->long_name);
321
322+#if LIBAVCODEC_VERSION_MAJOR >= 58
323+ ret = avcodec_parameters_from_context(g_pVStream->codecpar, g_pVideo);
324+ if (ret < 0)
325+ return FatalError("Could not copy parameters from codec context: %d", ret);
326+#endif
327+
328 g_pVFrame = av_frame_alloc();
329 if (!g_pVFrame)
330 return FatalError("Could not allocate frame");
331@@ -370,6 +511,12 @@ static int AddVideoStream()
332 g_pVFrame->height = g_Height;
333 g_pVFrame->format = AV_PIX_FMT_YUV420P;
334
335+#if LIBAVCODEC_VERSION_MAJOR >= 58
336+ g_pVPacket = av_packet_alloc();
337+ if (!g_pVPacket)
338+ return FatalError("Could not allocate packet");
339+#endif
340+
341 return avcodec_default_get_buffer2(g_pVideo, g_pVFrame, 0);
342 }
343
344@@ -380,6 +527,10 @@ static int WriteFrame(AVFrame* pFrame)
345 // write interleaved audio frame
346 if (g_pAStream)
347 {
348+#if LIBAVCODEC_VERSION_MAJOR >= 58
349+ if (!g_pAPacket)
350+ return FatalError("Error while writing video frame: g_pAPacket does not exist");
351+#endif
352 VideoTime = (double)g_pVFrame->pts * g_pVStream->time_base.num/g_pVStream->time_base.den;
353 do
354 {
355@@ -388,7 +539,7 @@ static int WriteFrame(AVFrame* pFrame)
356 AudioTime = (double)g_pAFrame->pts * g_pAStream->time_base.num/g_pAStream->time_base.den;
357 ret = WriteAudioFrame();
358 }
359- while (AudioTime < VideoTime && ret);
360+ while (AudioTime < VideoTime && ret > 0);
361 if (ret < 0)
362 return ret;
363 }
364@@ -396,13 +547,18 @@ static int WriteFrame(AVFrame* pFrame)
365 if (!g_pVStream)
366 return 0;
367
368+ g_pVFrame->pts++;
369+#if LIBAVCODEC_VERSION_MAJOR >= 58
370+ ret = EncodeAndWriteFrame(g_pVStream, g_pVideo, pFrame, g_pVPacket);
371+ if (ret < 0)
372+ return FatalError("Video frame processing failed");
373+ return ret;
374+#else
375 AVPacket Packet;
376 av_init_packet(&Packet);
377 Packet.data = NULL;
378 Packet.size = 0;
379
380- g_pVFrame->pts++;
381-#if LIBAVCODEC_VERSION_MAJOR < 58
382 if (g_pFormat->flags & AVFMT_RAWPICTURE)
383 {
384 /* raw video case. The API will change slightly in the near
385@@ -417,7 +573,6 @@ static int WriteFrame(AVFrame* pFrame)
386 return 0;
387 }
388 else
389-#endif
390 {
391 #if LIBAVCODEC_VERSION_MAJOR >= 54
392 int got_packet;
393@@ -447,6 +602,7 @@ static int WriteFrame(AVFrame* pFrame)
394
395 return 1;
396 }
397+#endif
398 }
399
400 AVWRAP_DECL int AVWrapper_WriteFrame(uint8_t *buf)
401@@ -539,9 +695,13 @@ AVWRAP_DECL int AVWrapper_Init(
402 char ext[16];
403 strncpy(ext, g_pFormat->extensions, 16);
404 ext[15] = 0;
405- ext[strcspn(ext,",")] = 0;
406+ size_t extLen = strcspn(ext, ",");
407+ ext[extLen] = 0;
408 #if LIBAVCODEC_VERSION_MAJOR >= 59
409- snprintf(g_pContainer->url, sizeof(g_pContainer->url), "%s.%s", pFilename, ext);
410+ // pFilename + dot + ext + null byte
411+ size_t urlLen = strlen(pFilename) + 1 + extLen + 1;
412+ g_pContainer->url = av_malloc(urlLen);
413+ snprintf(g_pContainer->url, urlLen, "%s.%s", pFilename, ext);
414 #else
415 snprintf(g_pContainer->filename, sizeof(g_pContainer->filename), "%s.%s", pFilename, ext);
416 #endif
417@@ -636,21 +796,33 @@ AVWRAP_DECL int AVWrapper_Close()
418 // free everything
419 if (g_pVStream)
420 {
421- avcodec_close(g_pVideo);
422- av_free(g_pVideo);
423- av_free(g_pVStream);
424+ avcodec_free_context(&g_pVideo);
425 av_frame_free(&g_pVFrame);
426+#if LIBAVCODEC_VERSION_MAJOR >= 58
427+ av_packet_free(&g_pVPacket);
428+#endif
429 }
430 if (g_pAStream)
431 {
432- avcodec_close(g_pAudio);
433- av_free(g_pAudio);
434- av_free(g_pAStream);
435+ avcodec_free_context(&g_pAudio);
436 av_frame_free(&g_pAFrame);
437+#if LIBAVCODEC_VERSION_MAJOR >= 58
438+ av_packet_free(&g_pAPacket);
439+#endif
440+#if LIBAVUTIL_VERSION_MAJOR < 53
441 av_free(g_pSamples);
442+#endif
443 fclose(g_pSoundFile);
444 }
445
446+#if LIBAVCODEC_VERSION_MAJOR >= 59
447+ avformat_free_context(g_pContainer);
448+#else
449+ if (g_pVStream)
450+ av_free(g_pVStream);
451+ if (g_pAStream)
452+ av_free(g_pAStream);
453 av_free(g_pContainer);
454+#endif
455 return 0;
456 }