Merge pull request #336169 from emilazy/push-okvwnpyymvzm
This commit is contained in:
commit
955740008a
@ -1,4 +1,4 @@
|
||||
{ stdenv, SDL2_image_2_6, SDL2_ttf, SDL2_net, fpc, haskell, ffmpeg_4, libglut
|
||||
{ stdenv, SDL2_image_2_6, SDL2_ttf, SDL2_net, fpc, haskell, ffmpeg_7, libglut
|
||||
, lib, fetchurl, cmake, pkg-config, lua5_1, SDL2, SDL2_mixer
|
||||
, zlib, libpng, libGL, libGLU, physfs
|
||||
, qtbase, qttools, wrapQtAppsHook
|
||||
@ -21,13 +21,19 @@ stdenv.mkDerivation rec {
|
||||
sha256 = "sha256-IB/l5FvYyls9gbGOwGvWu8n6fCxjvwGQBeL4C+W88hI=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
# Add support for ffmpeg 6.0
|
||||
# https://github.com/hedgewars/hw/pull/74
|
||||
./support-ffmpeg-6.patch
|
||||
];
|
||||
|
||||
nativeBuildInputs = [ cmake pkg-config qttools wrapQtAppsHook ];
|
||||
|
||||
buildInputs = [
|
||||
SDL2_ttf SDL2_net SDL2 SDL2_mixer SDL2_image_2_6
|
||||
fpc lua5_1
|
||||
llvm # hard-requirement on aarch64, for some reason not strictly necessary on x86-64
|
||||
ffmpeg_4 libglut physfs
|
||||
ffmpeg_7 libglut physfs
|
||||
qtbase
|
||||
] ++ lib.optional withServer ghc;
|
||||
|
||||
|
456
pkgs/games/hedgewars/support-ffmpeg-6.patch
Normal file
456
pkgs/games/hedgewars/support-ffmpeg-6.patch
Normal file
@ -0,0 +1,456 @@
|
||||
From 71691fad8654031328f4af077fc32aaf29cdb7d0 Mon Sep 17 00:00:00 2001
|
||||
From: Pekka Ristola <pekkarr@protonmail.com>
|
||||
Date: Tue, 9 May 2023 20:11:47 +0300
|
||||
Subject: [PATCH] Add support for ffmpeg 6.0
|
||||
|
||||
- Use the new send_frame/receive_packet API for encoding
|
||||
- Use the new channel layout API for audio
|
||||
- Fix audio recording
|
||||
- Copy codec parameters to the stream parameters
|
||||
- Set correct pts for audio frames
|
||||
- Read audio samples from file directly to the refcounted AVFrame buffer instead of the `g_pSamples` buffer
|
||||
- Use global AVPackets allocated with `av_packet_alloc`
|
||||
- Stop trying to write more audio frames when `WriteAudioFrame` fails with a negative error code
|
||||
- Fix segfault with `g_pContainer->url`. The field has to be allocated with `av_malloc` before writing to it. It's set to `NULL` by default.
|
||||
- Properly free allocations with `avcodec_free_context` and `avformat_free_context`
|
||||
---
|
||||
hedgewars/avwrapper/avwrapper.c | 234 +++++++++++++++++++++++++++-----
|
||||
1 file changed, 203 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/hedgewars/avwrapper/avwrapper.c b/hedgewars/avwrapper/avwrapper.c
|
||||
index 6c0fe739b4..3daeb07b75 100644
|
||||
--- a/hedgewars/avwrapper/avwrapper.c
|
||||
+++ b/hedgewars/avwrapper/avwrapper.c
|
||||
@@ -42,15 +42,19 @@
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
static AVFormatContext* g_pContainer;
|
||||
-static AVOutputFormat* g_pFormat;
|
||||
+static const AVOutputFormat* g_pFormat;
|
||||
static AVStream* g_pAStream;
|
||||
static AVStream* g_pVStream;
|
||||
static AVFrame* g_pAFrame;
|
||||
static AVFrame* g_pVFrame;
|
||||
-static AVCodec* g_pACodec;
|
||||
-static AVCodec* g_pVCodec;
|
||||
+static const AVCodec* g_pACodec;
|
||||
+static const AVCodec* g_pVCodec;
|
||||
static AVCodecContext* g_pAudio;
|
||||
static AVCodecContext* g_pVideo;
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 58
|
||||
+static AVPacket* g_pAPacket;
|
||||
+static AVPacket* g_pVPacket;
|
||||
+#endif
|
||||
|
||||
static int g_Width, g_Height;
|
||||
static uint32_t g_Frequency, g_Channels;
|
||||
@@ -58,8 +62,13 @@ static int g_VQuality;
|
||||
static AVRational g_Framerate;
|
||||
|
||||
static FILE* g_pSoundFile;
|
||||
+#if LIBAVUTIL_VERSION_MAJOR < 53
|
||||
static int16_t* g_pSamples;
|
||||
+#endif
|
||||
static int g_NumSamples;
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 53
|
||||
+static int64_t g_NextAudioPts;
|
||||
+#endif
|
||||
|
||||
|
||||
// compatibility section
|
||||
@@ -93,6 +102,8 @@ static void rescale_ts(AVPacket *pkt, AVRational ctb, AVRational stb)
|
||||
if (pkt->duration > 0)
|
||||
pkt->duration = av_rescale_q(pkt->duration, ctb, stb);
|
||||
}
|
||||
+
|
||||
+#define avcodec_free_context(ctx) do { avcodec_close(*ctx); av_freep(ctx); } while (0)
|
||||
#endif
|
||||
|
||||
#ifndef AV_CODEC_CAP_DELAY
|
||||
@@ -165,8 +176,42 @@ static void Log(const char* pFmt, ...)
|
||||
AddFileLogRaw(Buffer);
|
||||
}
|
||||
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 58
|
||||
+static int EncodeAndWriteFrame(
|
||||
+ const AVStream* pStream,
|
||||
+ AVCodecContext* pCodecContext,
|
||||
+ const AVFrame* pFrame,
|
||||
+ AVPacket* pPacket)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = avcodec_send_frame(pCodecContext, pFrame);
|
||||
+ if (ret < 0)
|
||||
+ return FatalError("avcodec_send_frame failed: %d", ret);
|
||||
+ while (1)
|
||||
+ {
|
||||
+ ret = avcodec_receive_packet(pCodecContext, pPacket);
|
||||
+ if (ret == AVERROR(EAGAIN))
|
||||
+ return 1;
|
||||
+ else if (ret == AVERROR_EOF)
|
||||
+ return 0;
|
||||
+ else if (ret < 0)
|
||||
+ return FatalError("avcodec_receive_packet failed: %d", ret);
|
||||
+
|
||||
+ av_packet_rescale_ts(pPacket, pCodecContext->time_base, pStream->time_base);
|
||||
+
|
||||
+ // Write the compressed frame to the media file.
|
||||
+ pPacket->stream_index = pStream->index;
|
||||
+ ret = av_interleaved_write_frame(g_pContainer, pPacket);
|
||||
+ if (ret != 0)
|
||||
+ return FatalError("Error while writing frame: %d", ret);
|
||||
+ }
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
static void AddAudioStream()
|
||||
{
|
||||
+ int ret;
|
||||
g_pAStream = avformat_new_stream(g_pContainer, g_pACodec);
|
||||
if(!g_pAStream)
|
||||
{
|
||||
@@ -176,20 +221,44 @@ static void AddAudioStream()
|
||||
g_pAStream->id = 1;
|
||||
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 59
|
||||
- const AVCodec *audio_st_codec = avcodec_find_decoder(g_pAStream->codecpar->codec_id);
|
||||
- g_pAudio = avcodec_alloc_context3(audio_st_codec);
|
||||
- avcodec_parameters_to_context(g_pAudio, g_pAStream->codecpar);
|
||||
+ g_pAudio = avcodec_alloc_context3(g_pACodec);
|
||||
#else
|
||||
g_pAudio = g_pAStream->codec;
|
||||
-#endif
|
||||
|
||||
avcodec_get_context_defaults3(g_pAudio, g_pACodec);
|
||||
g_pAudio->codec_id = g_pACodec->id;
|
||||
+#endif
|
||||
|
||||
// put parameters
|
||||
g_pAudio->sample_fmt = AV_SAMPLE_FMT_S16;
|
||||
g_pAudio->sample_rate = g_Frequency;
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 60
|
||||
+ const AVChannelLayout* pChLayout = g_pACodec->ch_layouts;
|
||||
+ if (pChLayout)
|
||||
+ {
|
||||
+ for (; pChLayout->nb_channels; pChLayout++)
|
||||
+ {
|
||||
+ if (pChLayout->nb_channels == g_Channels)
|
||||
+ {
|
||||
+ ret = av_channel_layout_copy(&g_pAudio->ch_layout, pChLayout);
|
||||
+ if (ret != 0)
|
||||
+ {
|
||||
+ Log("Channel layout copy failed: %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ if (!g_pAudio->ch_layout.nb_channels)
|
||||
+ {
|
||||
+ // no suitable layout found
|
||||
+ g_pAudio->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC;
|
||||
+ g_pAudio->ch_layout.nb_channels = g_Channels;
|
||||
+ }
|
||||
+#else
|
||||
g_pAudio->channels = g_Channels;
|
||||
+#endif
|
||||
|
||||
// set time base as invers of sample rate
|
||||
g_pAudio->time_base.den = g_pAStream->time_base.den = g_Frequency;
|
||||
@@ -213,6 +282,15 @@ static void AddAudioStream()
|
||||
return;
|
||||
}
|
||||
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 58
|
||||
+ ret = avcodec_parameters_from_context(g_pAStream->codecpar, g_pAudio);
|
||||
+ if (ret < 0)
|
||||
+ {
|
||||
+ Log("Could not copy parameters from codec context: %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 54
|
||||
if (g_pACodec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)
|
||||
#else
|
||||
@@ -221,13 +299,46 @@ static void AddAudioStream()
|
||||
g_NumSamples = 4096;
|
||||
else
|
||||
g_NumSamples = g_pAudio->frame_size;
|
||||
- g_pSamples = (int16_t*)av_malloc(g_NumSamples*g_Channels*sizeof(int16_t));
|
||||
g_pAFrame = av_frame_alloc();
|
||||
if (!g_pAFrame)
|
||||
{
|
||||
Log("Could not allocate frame\n");
|
||||
return;
|
||||
}
|
||||
+#if LIBAVUTIL_VERSION_MAJOR >= 53
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 60
|
||||
+ ret = av_channel_layout_copy(&g_pAFrame->ch_layout, &g_pAudio->ch_layout);
|
||||
+ if (ret != 0)
|
||||
+ {
|
||||
+ Log("Channel layout copy for frame failed: %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+#else
|
||||
+ g_pAFrame->channels = g_pAudio->channels;
|
||||
+#endif
|
||||
+ g_pAFrame->format = g_pAudio->sample_fmt;
|
||||
+ g_pAFrame->sample_rate = g_pAudio->sample_rate;
|
||||
+ g_pAFrame->nb_samples = g_NumSamples;
|
||||
+ ret = av_frame_get_buffer(g_pAFrame, 1);
|
||||
+ if (ret < 0)
|
||||
+ {
|
||||
+ Log("Failed to allocate frame buffer: %d\n", ret);
|
||||
+ return;
|
||||
+ }
|
||||
+#else
|
||||
+ g_pSamples = (int16_t*)av_malloc(g_NumSamples*g_Channels*sizeof(int16_t));
|
||||
+#endif
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 58
|
||||
+ g_pAPacket = av_packet_alloc();
|
||||
+ if (!g_pAPacket)
|
||||
+ {
|
||||
+ Log("Could not allocate audio packet\n");
|
||||
+ return;
|
||||
+ }
|
||||
+#endif
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 53
|
||||
+ g_NextAudioPts = 0;
|
||||
+#endif
|
||||
}
|
||||
|
||||
// returns non-zero if there is more sound, -1 in case of error
|
||||
@@ -236,22 +347,46 @@ static int WriteAudioFrame()
|
||||
if (!g_pAStream)
|
||||
return 0;
|
||||
|
||||
- AVPacket Packet;
|
||||
- av_init_packet(&Packet);
|
||||
- Packet.data = NULL;
|
||||
- Packet.size = 0;
|
||||
+ int ret;
|
||||
+ int16_t* pData;
|
||||
+#if LIBAVUTIL_VERSION_MAJOR >= 53
|
||||
+ ret = av_frame_make_writable(g_pAFrame);
|
||||
+ if (ret < 0)
|
||||
+ return FatalError("Could not make audio frame writable: %d", ret);
|
||||
+ pData = (int16_t*) g_pAFrame->data[0];
|
||||
+#else
|
||||
+ pData = g_pSamples;
|
||||
+#endif
|
||||
|
||||
- int NumSamples = fread(g_pSamples, 2*g_Channels, g_NumSamples, g_pSoundFile);
|
||||
+ int NumSamples = fread(pData, 2*g_Channels, g_NumSamples, g_pSoundFile);
|
||||
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 53
|
||||
AVFrame* pFrame = NULL;
|
||||
if (NumSamples > 0)
|
||||
{
|
||||
g_pAFrame->nb_samples = NumSamples;
|
||||
+ g_pAFrame->pts = g_NextAudioPts;
|
||||
+ g_NextAudioPts += NumSamples;
|
||||
+#if LIBAVUTIL_VERSION_MAJOR < 53
|
||||
avcodec_fill_audio_frame(g_pAFrame, g_Channels, AV_SAMPLE_FMT_S16,
|
||||
- (uint8_t*)g_pSamples, NumSamples*2*g_Channels, 1);
|
||||
+ (uint8_t*)pData, NumSamples*2*g_Channels, 1);
|
||||
+#endif
|
||||
pFrame = g_pAFrame;
|
||||
}
|
||||
+#endif
|
||||
+
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 58
|
||||
+ ret = EncodeAndWriteFrame(g_pAStream, g_pAudio, pFrame, g_pAPacket);
|
||||
+ if (ret < 0)
|
||||
+ return FatalError("Audio frame processing failed");
|
||||
+ return ret;
|
||||
+#else
|
||||
+ AVPacket Packet;
|
||||
+ av_init_packet(&Packet);
|
||||
+ Packet.data = NULL;
|
||||
+ Packet.size = 0;
|
||||
+
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 53
|
||||
// when NumSamples == 0 we still need to call encode_audio2 to flush
|
||||
int got_packet;
|
||||
if (avcodec_encode_audio2(g_pAudio, &Packet, pFrame, &got_packet) != 0)
|
||||
@@ -266,7 +401,7 @@ static int WriteAudioFrame()
|
||||
int BufferSize = OUTBUFFER_SIZE;
|
||||
if (g_pAudio->frame_size == 0)
|
||||
BufferSize = NumSamples*g_Channels*2;
|
||||
- Packet.size = avcodec_encode_audio(g_pAudio, g_OutBuffer, BufferSize, g_pSamples);
|
||||
+ Packet.size = avcodec_encode_audio(g_pAudio, g_OutBuffer, BufferSize, pData);
|
||||
if (Packet.size == 0)
|
||||
return 1;
|
||||
if (g_pAudio->coded_frame && g_pAudio->coded_frame->pts != AV_NOPTS_VALUE)
|
||||
@@ -280,25 +415,25 @@ static int WriteAudioFrame()
|
||||
if (av_interleaved_write_frame(g_pContainer, &Packet) != 0)
|
||||
return FatalError("Error while writing audio frame");
|
||||
return 1;
|
||||
+#endif
|
||||
}
|
||||
|
||||
// add a video output stream
|
||||
static int AddVideoStream()
|
||||
{
|
||||
+ int ret;
|
||||
g_pVStream = avformat_new_stream(g_pContainer, g_pVCodec);
|
||||
if (!g_pVStream)
|
||||
return FatalError("Could not allocate video stream");
|
||||
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 59
|
||||
- const AVCodec *video_st_codec = avcodec_find_decoder(g_pVStream->codecpar->codec_id);
|
||||
- g_pVideo = avcodec_alloc_context3(video_st_codec);
|
||||
- avcodec_parameters_to_context(g_pVideo, g_pVStream->codecpar);
|
||||
+ g_pVideo = avcodec_alloc_context3(g_pVCodec);
|
||||
#else
|
||||
g_pVideo = g_pVStream->codec;
|
||||
-#endif
|
||||
|
||||
avcodec_get_context_defaults3(g_pVideo, g_pVCodec);
|
||||
g_pVideo->codec_id = g_pVCodec->id;
|
||||
+#endif
|
||||
|
||||
// put parameters
|
||||
// resolution must be a multiple of two
|
||||
@@ -361,6 +496,12 @@ static int AddVideoStream()
|
||||
if (avcodec_open2(g_pVideo, g_pVCodec, NULL) < 0)
|
||||
return FatalError("Could not open video codec %s", g_pVCodec->long_name);
|
||||
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 58
|
||||
+ ret = avcodec_parameters_from_context(g_pVStream->codecpar, g_pVideo);
|
||||
+ if (ret < 0)
|
||||
+ return FatalError("Could not copy parameters from codec context: %d", ret);
|
||||
+#endif
|
||||
+
|
||||
g_pVFrame = av_frame_alloc();
|
||||
if (!g_pVFrame)
|
||||
return FatalError("Could not allocate frame");
|
||||
@@ -370,6 +511,12 @@ static int AddVideoStream()
|
||||
g_pVFrame->height = g_Height;
|
||||
g_pVFrame->format = AV_PIX_FMT_YUV420P;
|
||||
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 58
|
||||
+ g_pVPacket = av_packet_alloc();
|
||||
+ if (!g_pVPacket)
|
||||
+ return FatalError("Could not allocate packet");
|
||||
+#endif
|
||||
+
|
||||
return avcodec_default_get_buffer2(g_pVideo, g_pVFrame, 0);
|
||||
}
|
||||
|
||||
@@ -380,6 +527,10 @@ static int WriteFrame(AVFrame* pFrame)
|
||||
// write interleaved audio frame
|
||||
if (g_pAStream)
|
||||
{
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 58
|
||||
+ if (!g_pAPacket)
|
||||
+ return FatalError("Error while writing video frame: g_pAPacket does not exist");
|
||||
+#endif
|
||||
VideoTime = (double)g_pVFrame->pts * g_pVStream->time_base.num/g_pVStream->time_base.den;
|
||||
do
|
||||
{
|
||||
@@ -388,7 +539,7 @@ static int WriteFrame(AVFrame* pFrame)
|
||||
AudioTime = (double)g_pAFrame->pts * g_pAStream->time_base.num/g_pAStream->time_base.den;
|
||||
ret = WriteAudioFrame();
|
||||
}
|
||||
- while (AudioTime < VideoTime && ret);
|
||||
+ while (AudioTime < VideoTime && ret > 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@@ -396,13 +547,18 @@ static int WriteFrame(AVFrame* pFrame)
|
||||
if (!g_pVStream)
|
||||
return 0;
|
||||
|
||||
+ g_pVFrame->pts++;
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 58
|
||||
+ ret = EncodeAndWriteFrame(g_pVStream, g_pVideo, pFrame, g_pVPacket);
|
||||
+ if (ret < 0)
|
||||
+ return FatalError("Video frame processing failed");
|
||||
+ return ret;
|
||||
+#else
|
||||
AVPacket Packet;
|
||||
av_init_packet(&Packet);
|
||||
Packet.data = NULL;
|
||||
Packet.size = 0;
|
||||
|
||||
- g_pVFrame->pts++;
|
||||
-#if LIBAVCODEC_VERSION_MAJOR < 58
|
||||
if (g_pFormat->flags & AVFMT_RAWPICTURE)
|
||||
{
|
||||
/* raw video case. The API will change slightly in the near
|
||||
@@ -417,7 +573,6 @@ static int WriteFrame(AVFrame* pFrame)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
-#endif
|
||||
{
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 54
|
||||
int got_packet;
|
||||
@@ -447,6 +602,7 @@ static int WriteFrame(AVFrame* pFrame)
|
||||
|
||||
return 1;
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
|
||||
AVWRAP_DECL int AVWrapper_WriteFrame(uint8_t *buf)
|
||||
@@ -539,9 +695,13 @@ AVWRAP_DECL int AVWrapper_Init(
|
||||
char ext[16];
|
||||
strncpy(ext, g_pFormat->extensions, 16);
|
||||
ext[15] = 0;
|
||||
- ext[strcspn(ext,",")] = 0;
|
||||
+ size_t extLen = strcspn(ext, ",");
|
||||
+ ext[extLen] = 0;
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 59
|
||||
- snprintf(g_pContainer->url, sizeof(g_pContainer->url), "%s.%s", pFilename, ext);
|
||||
+ // pFilename + dot + ext + null byte
|
||||
+ size_t urlLen = strlen(pFilename) + 1 + extLen + 1;
|
||||
+ g_pContainer->url = av_malloc(urlLen);
|
||||
+ snprintf(g_pContainer->url, urlLen, "%s.%s", pFilename, ext);
|
||||
#else
|
||||
snprintf(g_pContainer->filename, sizeof(g_pContainer->filename), "%s.%s", pFilename, ext);
|
||||
#endif
|
||||
@@ -636,21 +796,33 @@ AVWRAP_DECL int AVWrapper_Close()
|
||||
// free everything
|
||||
if (g_pVStream)
|
||||
{
|
||||
- avcodec_close(g_pVideo);
|
||||
- av_free(g_pVideo);
|
||||
- av_free(g_pVStream);
|
||||
+ avcodec_free_context(&g_pVideo);
|
||||
av_frame_free(&g_pVFrame);
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 58
|
||||
+ av_packet_free(&g_pVPacket);
|
||||
+#endif
|
||||
}
|
||||
if (g_pAStream)
|
||||
{
|
||||
- avcodec_close(g_pAudio);
|
||||
- av_free(g_pAudio);
|
||||
- av_free(g_pAStream);
|
||||
+ avcodec_free_context(&g_pAudio);
|
||||
av_frame_free(&g_pAFrame);
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 58
|
||||
+ av_packet_free(&g_pAPacket);
|
||||
+#endif
|
||||
+#if LIBAVUTIL_VERSION_MAJOR < 53
|
||||
av_free(g_pSamples);
|
||||
+#endif
|
||||
fclose(g_pSoundFile);
|
||||
}
|
||||
|
||||
+#if LIBAVCODEC_VERSION_MAJOR >= 59
|
||||
+ avformat_free_context(g_pContainer);
|
||||
+#else
|
||||
+ if (g_pVStream)
|
||||
+ av_free(g_pVStream);
|
||||
+ if (g_pAStream)
|
||||
+ av_free(g_pAStream);
|
||||
av_free(g_pContainer);
|
||||
+#endif
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user