diff --git a/libavfilter/cuda/load_helper.c b/libavfilter/cuda/load_helper.c index 115523d642..d64dce72b6 100644 --- a/libavfilter/cuda/load_helper.c +++ b/libavfilter/cuda/load_helper.c @@ -24,8 +24,7 @@ #include "libavutil/mem.h" #if CONFIG_SHADER_COMPRESSION -#include -#define CHUNK_SIZE 1024 * 64 +#include "libavutil/zlib_utils.h" #endif #include "load_helper.h" @@ -38,58 +37,15 @@ int ff_cuda_load_module(void *avctx, AVCUDADeviceContext *hwctx, CUmodule *cu_mo CudaFunctions *cu = hwctx->internal->cuda_dl; #if CONFIG_SHADER_COMPRESSION - z_stream stream = { 0 }; - uint8_t *buf, *tmp; - uint64_t buf_size; - int ret; + uint8_t *out; + size_t out_len; + int ret = ff_zlib_expand(avctx, &out, &out_len, + data, length); + if (ret < 0) + return ret; - if (inflateInit2(&stream, 32 + 15) != Z_OK) { - av_log(avctx, AV_LOG_ERROR, "Error during zlib initialisation: %s\n", stream.msg); - return AVERROR(ENOSYS); - } - - buf_size = CHUNK_SIZE * 4; - buf = av_realloc(NULL, buf_size); - if (!buf) { - inflateEnd(&stream); - return AVERROR(ENOMEM); - } - - stream.next_in = data; - stream.avail_in = length; - - do { - stream.avail_out = buf_size - stream.total_out; - stream.next_out = buf + stream.total_out; - - ret = inflate(&stream, Z_FINISH); - if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) { - av_log(avctx, AV_LOG_ERROR, "zlib inflate error(%d): %s\n", ret, stream.msg); - inflateEnd(&stream); - av_free(buf); - return AVERROR(EINVAL); - } - - if (stream.avail_out == 0) { - buf_size += CHUNK_SIZE; - tmp = av_realloc(buf, buf_size); - if (!tmp) { - inflateEnd(&stream); - av_free(buf); - return AVERROR(ENOMEM); - } - buf = tmp; - } - } while (ret != Z_STREAM_END); - - // NULL-terminate string - // there is guaranteed to be space for this, due to condition in loop - buf[stream.total_out] = 0; - - inflateEnd(&stream); - - ret = CHECK_CU(cu->cuModuleLoadData(cu_module, buf)); - av_free(buf); + ret = CHECK_CU(cu->cuModuleLoadData(cu_module, out)); + av_free(out); return ret; #else return CHECK_CU(cu->cuModuleLoadData(cu_module, data)); diff --git a/libavutil/Makefile b/libavutil/Makefile index ee77e51c08..c5241895ff 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -234,6 +234,7 @@ STLIBOBJS-$(CONFIG_SWSCALE) += half2float.o SHLIBOBJS-$(HAVE_GNU_WINDRES) += avutilres.o SKIPHEADERS += objc.h +SKIPHEADERS-$(CONFIG_ZLIB) += zlib_utils.h SKIPHEADERS-$(HAVE_CUDA_H) += hwcontext_cuda.h SKIPHEADERS-$(CONFIG_CUDA) += hwcontext_cuda_internal.h \ cuda_check.h @@ -252,6 +253,7 @@ SKIPHEADERS-$(CONFIG_VULKAN) += hwcontext_vulkan.h vulkan.h \ vulkan_loader.h SKIPHEADERS-$(CONFIG_LIBSHADERC) += vulkan_spirv.h SKIPHEADERS-$(CONFIG_LIBGLSLANG) += vulkan_spirv.h +SKIPHEADERS-$(CONFIG_SHADER_COMPRESSION) += zlib_utils.h TESTPROGS = adler32 \ aes \ diff --git a/libavutil/zlib_utils.h b/libavutil/zlib_utils.h new file mode 100644 index 0000000000..41b97cfd09 --- /dev/null +++ b/libavutil/zlib_utils.h @@ -0,0 +1,88 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVUTIL_ZLIB_UTILS_H +#define AVUTIL_ZLIB_UTILS_H + +#include +#include "log.h" +#include "error.h" +#include "mem.h" + +#include +#define CHUNK_SIZE 1024 * 64 + +static inline int ff_zlib_expand(void *ctx, uint8_t **out, size_t *out_len, + const uint8_t *src, int src_len) +{ + int ret; + + z_stream stream = { 0 }; + if (inflateInit2(&stream, 32 + 15) != Z_OK) { + av_log(ctx, AV_LOG_ERROR, "Error during zlib initialisation: %s\n", + stream.msg); + return AVERROR(ENOSYS); + } + + uint64_t buf_size = CHUNK_SIZE * 4; + uint8_t *buf = av_realloc(NULL, buf_size); + if (!buf) { + inflateEnd(&stream); + return AVERROR(ENOMEM); + } + + stream.next_in = src; + stream.avail_in = src_len; + + do { + stream.avail_out = buf_size - stream.total_out; + stream.next_out = buf + stream.total_out; + + ret = inflate(&stream, Z_FINISH); + if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) { + av_log(ctx, AV_LOG_ERROR, "zlib inflate error(%d): %s\n", + ret, stream.msg); + inflateEnd(&stream); + av_free(buf); + return AVERROR(EINVAL); + } + + if (stream.avail_out == 0) { + buf_size += CHUNK_SIZE; + uint8_t *tmp = av_realloc(buf, buf_size); + if (!tmp) { + inflateEnd(&stream); + av_free(buf); + return AVERROR(ENOMEM); + } + buf = tmp; + } + } while (ret != Z_STREAM_END); + + // NULL-terminate string + // there is guaranteed to be space for this, due to condition in loop + buf[stream.total_out] = 0; + + inflateEnd(&stream); + + *out = buf; + *out_len = stream.total_out; + + return 0; +} +#endif /* AVUTIL_ZLIB_UTILS_H */