From 2fa7ea95c891981684a55b41977172d040c2cc55 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Sun, 25 May 2025 18:49:20 -0400 Subject: Support Windows XP (Old FFmpeg and build fixes) Signed-off-by: Andrew Opalach --- src/codec/ffmpeg/avio.c | 12 ++++++------ src/codec/ffmpeg/avio.h | 5 +++-- src/codec/ffmpeg/common.c | 4 ++++ src/codec/ffmpeg/decoder.c | 4 ++-- src/codec/ffmpeg/decoder.h | 4 ++-- src/codec/ffmpeg/demuxer.c | 7 +++++++ src/codec/ffmpeg/encoder.c | 29 +++++++++++++++-------------- src/codec/ffmpeg/encoder.h | 2 +- src/codec/ffmpeg/meson.build | 20 +++++++++++++++----- src/codec/ffmpeg/packet_ext.c | 18 ++++++++++++++++-- src/codec/ffmpeg/packet_ext.h | 3 +-- src/codec/ffmpeg/resampler.c | 33 +++++++++++++++++++++------------ 12 files changed, 93 insertions(+), 48 deletions(-) (limited to 'src/codec/ffmpeg') diff --git a/src/codec/ffmpeg/avio.c b/src/codec/ffmpeg/avio.c index 154152e..86130d8 100644 --- a/src/codec/ffmpeg/avio.c +++ b/src/codec/ffmpeg/avio.c @@ -2,20 +2,20 @@ #include "../../cache/handle.h" -s32 camu_avio_read(void *data, u8 *buf, s32 count) +s32 camu_avio_read(void *opaque, u8 *buf, s32 count) { - struct cch_handle *handle = (struct cch_handle *)data; + struct cch_handle *handle = (struct cch_handle *)opaque; return cch_handle_read(handle, buf, count); } -s32 camu_avio_write(void *data, const u8 *buf, s32 count) +s32 camu_avio_write(void *opaque, u8 *buf, s32 count) { - struct cch_handle *handle = (struct cch_handle *)data; + struct cch_handle *handle = (struct cch_handle *)opaque; return cch_handle_write(handle, buf, count); } -s64 camu_avio_seek(void *data, s64 offset, s32 whence) +s64 camu_avio_seek(void *opaque, s64 offset, s32 whence) { - struct cch_handle *handle = (struct cch_handle *)data; + struct cch_handle *handle = (struct cch_handle *)opaque; return (s64)cch_handle_seek(handle, offset, whence); } diff --git a/src/codec/ffmpeg/avio.h b/src/codec/ffmpeg/avio.h index 04aeeb4..bb67c58 100644 --- a/src/codec/ffmpeg/avio.h +++ b/src/codec/ffmpeg/avio.h @@ -2,5 +2,6 @@ #include -s32 camu_avio_read(void *data, u8 *buf, s32 buf_size); -s64 camu_avio_seek(void *data, s64 offset, s32 whence); +s32 camu_avio_read(void *opaque, u8 *buf, s32 buf_size); +s32 camu_avio_write(void *opaque, u8 *buf, s32 count); +s64 camu_avio_seek(void *opaque, s64 offset, s32 whence); diff --git a/src/codec/ffmpeg/common.c b/src/codec/ffmpeg/common.c index 259ba90..5226df6 100644 --- a/src/codec/ffmpeg/common.c +++ b/src/codec/ffmpeg/common.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "common.h" @@ -55,5 +56,8 @@ void camu_ff_set_log_callback(void (*callback)(void *, s32, const char *, va_lis void camu_ff_common_init(void) { log_info("Using FFmpeg version "FFMPEG_VERSION"."); +#ifdef CAMU_OLD_FFMPEG + av_register_all(); +#endif camu_ff_set_log_callback(av_log_callback); } diff --git a/src/codec/ffmpeg/decoder.c b/src/codec/ffmpeg/decoder.c index c22d1c1..e097e0c 100644 --- a/src/codec/ffmpeg/decoder.c +++ b/src/codec/ffmpeg/decoder.c @@ -10,11 +10,11 @@ #endif #ifdef CAMU_FF_DECODER_HWACCEL -#if defined CAMU_RENDERER_VULKAN +#if defined STELA_API_VULKAN static const char *hwdevces[] = { "vulkan" }; #elif defined NAUNET_ON_WINDOWS static const char *hwdevces[] = { "d3d11va" }; -#elif defined CAMU_RENDERER_OPENGL +#elif defined STELA_API_OPENGL static const char *hwdevces[] = { "vaapi" }; #endif diff --git a/src/codec/ffmpeg/decoder.h b/src/codec/ffmpeg/decoder.h index ab60ef3..4797060 100644 --- a/src/codec/ffmpeg/decoder.h +++ b/src/codec/ffmpeg/decoder.h @@ -4,8 +4,8 @@ #include "../codec.h" -#ifndef CAMU_SINK_NO_VIDEO -//#define CAMU_FF_DECODER_HWACCEL +#ifdef CAMU_USE_HWACCEL +#define CAMU_FF_DECODER_HWACCEL #endif struct camu_ff_decoder { diff --git a/src/codec/ffmpeg/demuxer.c b/src/codec/ffmpeg/demuxer.c index bf2039f..a5821a2 100644 --- a/src/codec/ffmpeg/demuxer.c +++ b/src/codec/ffmpeg/demuxer.c @@ -88,6 +88,13 @@ static bool ff_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handl for (u32 i = 0; i < av->format_context->nb_streams; i++) { AVStream *stream = av->format_context->streams[i]; enum AVMediaType type = stream->codecpar->codec_type; +#ifdef CAMU_OLD_FFMPEG + // This is probably not correct. + if (stream->codecpar->channel_layout == 0) { + stream->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; + stream->codecpar->channels = 2; + } +#endif u64 duration = 0; if (type == AVMEDIA_TYPE_AUDIO || type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_SUBTITLE) { // Try to detect attached images. diff --git a/src/codec/ffmpeg/encoder.c b/src/codec/ffmpeg/encoder.c index 50e80e4..5d90785 100644 --- a/src/codec/ffmpeg/encoder.c +++ b/src/codec/ffmpeg/encoder.c @@ -32,7 +32,7 @@ bool camu_ff_encoder_init(struct camu_ff_encoder *enc, char *encoder_name, char } enc->codec_context->sample_rate = 48000; - av_channel_layout_default(&enc->codec_context->ch_layout, CHANNELS); + camu_default_channel_layout(&AV_CODECPAR_CHANNEL_LAYOUT(enc->codec_context), CHANNELS); enc->codec_context->sample_fmt = AV_SAMPLE_FMT_FLT; enc->codec_context->bit_rate = bitrate; enc->codec_context->frame_size = SAMPLES_PER_FRAME; @@ -62,19 +62,20 @@ bool camu_ff_encoder_init(struct camu_ff_encoder *enc, char *encoder_name, char av_dict_free(&opts); AVCodecContext *out_codec = enc->codec_context; - - enc->fmt.req.format = out_codec->sample_fmt; - enc->fmt.req.sample_rate = out_codec->sample_rate; - av_channel_layout_copy(&enc->fmt.req.channel_layout, &out_codec->ch_layout); - enc->fmt.req.channel_count = out_codec->ch_layout.nb_channels; - - enc->frame = av_frame_alloc(); - enc->frame->format = enc->fmt.req.format; - enc->frame->sample_rate = enc->fmt.req.sample_rate; - av_channel_layout_copy(&enc->frame->ch_layout, &enc->fmt.req.channel_layout); - av_samples_alloc(enc->frame->data, NULL, enc->frame->ch_layout.nb_channels, SAMPLES_PER_FRAME, enc->frame->format, 1); - enc->frame->nb_samples = SAMPLES_PER_FRAME; - enc->frame->pts = 0; + AVFrame *frame = av_frame_alloc(); + frame->format = out_codec->sample_fmt; + frame->sample_rate = out_codec->sample_rate; + camu_copy_channel_layout(&AV_CODECPAR_CHANNEL_LAYOUT(frame), &AV_CODECPAR_CHANNEL_LAYOUT(out_codec)); + av_samples_alloc(frame->data, NULL, AV_CODECPAR_CHANNELS(out_codec), SAMPLES_PER_FRAME, frame->format, 1); + frame->nb_samples = SAMPLES_PER_FRAME; + frame->pts = 0; + + enc->fmt.format = frame->format; + enc->fmt.sample_rate = frame->sample_rate; + camu_copy_channel_layout(&enc->fmt.channel_layout, &AV_CODECPAR_CHANNEL_LAYOUT(frame)); + enc->fmt.channel_count = AV_CODECPAR_CHANNELS(frame); + + enc->frame = frame; return true; err: diff --git a/src/codec/ffmpeg/encoder.h b/src/codec/ffmpeg/encoder.h index 5f7d06f..3ace4d8 100644 --- a/src/codec/ffmpeg/encoder.h +++ b/src/codec/ffmpeg/encoder.h @@ -9,7 +9,7 @@ struct camu_ff_encoder { AVCodecContext *codec_context; const AVOutputFormat *output_format; - struct camu_resampler_format fmt; + struct camu_audio_format fmt; AVFrame *frame; void (*callback)(void *, AVPacket *); diff --git a/src/codec/ffmpeg/meson.build b/src/codec/ffmpeg/meson.build index eb68fad..56a75b2 100644 --- a/src/codec/ffmpeg/meson.build +++ b/src/codec/ffmpeg/meson.build @@ -3,6 +3,9 @@ ffmpeg_src = [ 'packet_ext.c', ] ffmpeg_args = ['-DCAMU_HAVE_FFMPEG'] +if get_option('codec-hwaccel').enabled() + ffmpeg_args += ['-DCAMU_USE_HWACCEL'] +endif ffmpeg_deps = [] ffmpeg_server_src = [ @@ -16,8 +19,7 @@ ffmpeg_client_src = [ ffmpeg_src, 'decoder.c', 'resampler.c', - 'scaler.c', - 'encoder.c' + 'scaler.c' ] ffmpeg_client_deps = [] @@ -38,7 +40,12 @@ libavcodec = dependency('libavcodec', required: false) libswresample = dependency('libswresample', required: false) libswscale = dependency('libswscale', required: false) if not (libavutil.found() and libavformat.found() and libavcodec.found() and libswresample.found() and libswscale.found()) - ffmpeg_proj = subproject('ffmpeg', required: false) + if get_option('win32-compat') + ffmpeg_proj = subproject('ffmpeg-compat', required: false) + ffmpeg_args += ['-DCAMU_OLD_FFMPEG'] + else + ffmpeg_proj = subproject('ffmpeg', required: false) + endif if ffmpeg_proj.found() libavutil = ffmpeg_proj.get_variable('avutil') libavformat = ffmpeg_proj.get_variable('avformat') @@ -48,9 +55,12 @@ if not (libavutil.found() and libavformat.found() and libavcodec.found() and lib libswscale = ffmpeg_proj.get_variable('swscale') # Only used to set include dirs for FFmpeg. ffmpeg_deps += [ffmpeg_proj.get_variable('ffmpeg_include')] - # We explicitly enable zlib in the FFmpeg build. + # We explicitly enable zlib and maybe bzlib in the FFmpeg build. ffmpeg_deps += [dependency('zlib')] - if is_windows + if not get_option('sink-only') + ffmpeg_deps += [dependency('bzip2')] + endif + if is_windows and not get_option('win32-compat') # Extra static dependencies for Windows. ffmpeg_client_deps += [compiler.find_library('bcrypt')] elif is_android diff --git a/src/codec/ffmpeg/packet_ext.c b/src/codec/ffmpeg/packet_ext.c index acf5bbd..a1a6a5e 100644 --- a/src/codec/ffmpeg/packet_ext.c +++ b/src/codec/ffmpeg/packet_ext.c @@ -16,7 +16,7 @@ void nn_packet_write_av_codec_parameters(struct nn_packet *packet, AVCodecParame NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->width); NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->height); NNWT_PACKET_WRITE_TYPE(packet, AVRational, codecpar->sample_aspect_ratio); -#if LIBAVCODEC_VERSION_INT >= 60 +#if !defined CAMU_OLD_FFMPEG && LIBAVCODEC_VERSION_INT >= 60 NNWT_PACKET_WRITE_TYPE(packet, AVRational, codecpar->framerate); #endif NNWT_PACKET_WRITE_TYPE(packet, enum AVFieldOrder, codecpar->field_order); @@ -26,6 +26,7 @@ void nn_packet_write_av_codec_parameters(struct nn_packet *packet, AVCodecParame NNWT_PACKET_WRITE_TYPE(packet, enum AVColorSpace, codecpar->color_space); NNWT_PACKET_WRITE_TYPE(packet, enum AVChromaLocation, codecpar->chroma_location); NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->video_delay); +#ifndef CAMU_OLD_FFMPEG // Incomplete. NNWT_PACKET_WRITE_TYPE(packet, enum AVChannelOrder, codecpar->ch_layout.order); if (codecpar->ch_layout.order == AV_CHANNEL_ORDER_NATIVE) { @@ -33,6 +34,10 @@ void nn_packet_write_av_codec_parameters(struct nn_packet *packet, AVCodecParame } else { NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->ch_layout.nb_channels); } +#else + NNWT_PACKET_WRITE_TYPE(packet, u64, codecpar->channel_layout); + NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->channels); +#endif NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->sample_rate); NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->block_align); NNWT_PACKET_WRITE_TYPE(packet, s32, codecpar->frame_size); @@ -98,7 +103,9 @@ void nn_packet_write_av_packet(struct nn_packet *packet, AVPacket *pkt) } NNWT_PACKET_WRITE_TYPE(packet, s64, pkt->duration); NNWT_PACKET_WRITE_TYPE(packet, s64, pkt->pos); +#ifndef CAMU_OLD_FFMPEG NNWT_PACKET_WRITE_TYPE(packet, AVRational, pkt->time_base); +#endif } void nn_packet_read_av_codec_parameters(struct nn_packet *packet, AVCodecParameters *codecpar) @@ -120,7 +127,7 @@ void nn_packet_read_av_codec_parameters(struct nn_packet *packet, AVCodecParamet NNWT_PACKET_READ_TYPE(packet, s32, codecpar->width); NNWT_PACKET_READ_TYPE(packet, s32, codecpar->height); NNWT_PACKET_READ_TYPE(packet, AVRational, codecpar->sample_aspect_ratio); -#if LIBAVCODEC_VERSION_INT >= 60 +#if !defined CAMU_OLD_FFMPEG && LIBAVCODEC_VERSION_INT >= 60 NNWT_PACKET_READ_TYPE(packet, AVRational, codecpar->framerate); #endif NNWT_PACKET_READ_TYPE(packet, enum AVFieldOrder, codecpar->field_order); @@ -130,6 +137,7 @@ void nn_packet_read_av_codec_parameters(struct nn_packet *packet, AVCodecParamet NNWT_PACKET_READ_TYPE(packet, enum AVColorSpace, codecpar->color_space); NNWT_PACKET_READ_TYPE(packet, enum AVChromaLocation, codecpar->chroma_location); NNWT_PACKET_READ_TYPE(packet, s32, codecpar->video_delay); +#ifndef CAMU_OLD_FFMPEG enum AVChannelOrder order; NNWT_PACKET_READ_TYPE(packet, enum AVChannelOrder, order); if (order == AV_CHANNEL_ORDER_NATIVE) { @@ -141,6 +149,10 @@ void nn_packet_read_av_codec_parameters(struct nn_packet *packet, AVCodecParamet NNWT_PACKET_READ_TYPE(packet, s32, nb_channels); av_channel_layout_default(&codecpar->ch_layout, nb_channels); } +#else + NNWT_PACKET_READ_TYPE(packet, u64, codecpar->channel_layout); + NNWT_PACKET_READ_TYPE(packet, s32, codecpar->channels); +#endif NNWT_PACKET_READ_TYPE(packet, s32, codecpar->sample_rate); NNWT_PACKET_READ_TYPE(packet, s32, codecpar->block_align); NNWT_PACKET_READ_TYPE(packet, s32, codecpar->frame_size); @@ -214,5 +226,7 @@ void nn_packet_read_av_packet(struct nn_packet *packet, AVPacket *pkt) } NNWT_PACKET_READ_TYPE(packet, s64, pkt->duration); NNWT_PACKET_READ_TYPE(packet, s64, pkt->pos); +#ifndef CAMU_OLD_FFMPEG NNWT_PACKET_READ_TYPE(packet, AVRational, pkt->time_base); +#endif } diff --git a/src/codec/ffmpeg/packet_ext.h b/src/codec/ffmpeg/packet_ext.h index fab9b36..540cdcb 100644 --- a/src/codec/ffmpeg/packet_ext.h +++ b/src/codec/ffmpeg/packet_ext.h @@ -1,8 +1,7 @@ #pragma once #include -#include -#include +#include #include #include diff --git a/src/codec/ffmpeg/resampler.c b/src/codec/ffmpeg/resampler.c index eacc75b..48cca8e 100644 --- a/src/codec/ffmpeg/resampler.c +++ b/src/codec/ffmpeg/resampler.c @@ -12,26 +12,35 @@ static bool ff_resampler_init(struct camu_resampler *resamp, struct camu_resampl camu_audio_format_copy(&av->fmt, &fmt->req); - s32 ret = swr_alloc_set_opts2(&av->resample_context, - &fmt->req.channel_layout, fmt->req.format, fmt->req.sample_rate, - &fmt->in.channel_layout, fmt->in.format, fmt->in.sample_rate, 0, NULL); - if (ret != 0) { - log_error("Failed to configure resampler context."); - return false; - } + SwrContext *swr = swr_alloc(); + +#ifndef CAMU_OLD_FFMPEG + av_opt_set_chlayout(swr, "in_chlayout", &fmt->in.channel_layout, 0); + av_opt_set_chlayout(swr, "out_chlayout", &fmt->req.channel_layout, 0); +#else + av_opt_set_channel_layout(swr, "in_channel_layout", fmt->in.channel_layout, 0); + av_opt_set_channel_layout(swr, "out_channel_layout", fmt->req.channel_layout, 0); +#endif + av_opt_set_int(swr, "in_sample_rate", fmt->in.sample_rate, 0); + av_opt_set_int(swr, "out_sample_rate", fmt->req.sample_rate, 0); + av_opt_set_sample_fmt(swr, "in_sample_fmt", fmt->in.format, 0); + av_opt_set_sample_fmt(swr, "out_sample_fmt", fmt->req.format, 0); #ifdef CAMU_HAVE_SOXR // Slower but more accurate resampler. - av_opt_set_int(av->resample_context, "resampler", SWR_ENGINE_SOXR, 0); + av_opt_set_int(swr, "resampler", SWR_ENGINE_SOXR, 0); log_info("Using SoX resampler."); #endif - if (swr_init(av->resample_context) != 0) { - swr_free(&av->resample_context); - log_error("Failed to init resampler context."); + s32 ret = swr_init(swr); + if (ret != 0) { + swr_free(&swr); + log_error("Failed to init resampler context (%s).", av_err2str(ret)); return false; } + av->resample_context = swr; + return true; } @@ -44,7 +53,7 @@ static inline void alloc_sample_data(struct camu_ff_resampler *av, s32 sample_co { if (av->sample_count >= sample_count) return; free_sample_data(av); - s32 nb_channels = av->fmt.channel_layout.nb_channels; + s32 nb_channels = av->fmt.channel_count; av_samples_alloc(av->data, NULL, nb_channels, sample_count, av->fmt.format, 32); av->sample_count = sample_count; } -- cgit v1.2.3-101-g0448