1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include "config.h"
20
21 #include "libavutil/hwcontext.h"
22 #include "libavutil/hwcontext_cuda_internal.h"
23 #include "libavutil/cuda_check.h"
24
25 #if CONFIG_PTX_COMPRESSION
26 #include <zlib.h>
27 #define CHUNK_SIZE 1024 * 64
28 #endif
29
30 #include "load_helper.h"
31
32 #define CHECK_CU(x) FF_CUDA_CHECK_DL(avctx, cu, x)
33
ff_cuda_load_module(void * avctx,AVCUDADeviceContext * hwctx,CUmodule * cu_module,const unsigned char * data,const unsigned int length)34 int ff_cuda_load_module(void *avctx, AVCUDADeviceContext *hwctx, CUmodule *cu_module,
35 const unsigned char *data, const unsigned int length)
36 {
37 CudaFunctions *cu = hwctx->internal->cuda_dl;
38
39 #if CONFIG_PTX_COMPRESSION
40 z_stream stream = { 0 };
41 uint8_t *buf, *tmp;
42 uint64_t buf_size;
43 int ret;
44
45 if (inflateInit2(&stream, 32 + 15) != Z_OK) {
46 av_log(avctx, AV_LOG_ERROR, "Error during zlib initialisation: %s\n", stream.msg);
47 return AVERROR(ENOSYS);
48 }
49
50 buf_size = CHUNK_SIZE * 4;
51 buf = av_realloc(NULL, buf_size);
52 if (!buf) {
53 inflateEnd(&stream);
54 return AVERROR(ENOMEM);
55 }
56
57 stream.next_in = data;
58 stream.avail_in = length;
59
60 do {
61 stream.avail_out = buf_size - stream.total_out;
62 stream.next_out = buf + stream.total_out;
63
64 ret = inflate(&stream, Z_FINISH);
65 if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) {
66 av_log(avctx, AV_LOG_ERROR, "zlib inflate error(%d): %s\n", ret, stream.msg);
67 inflateEnd(&stream);
68 av_free(buf);
69 return AVERROR(EINVAL);
70 }
71
72 if (stream.avail_out == 0) {
73 buf_size += CHUNK_SIZE;
74 tmp = av_realloc(buf, buf_size);
75 if (!tmp) {
76 inflateEnd(&stream);
77 av_free(buf);
78 return AVERROR(ENOMEM);
79 }
80 buf = tmp;
81 }
82 } while (ret != Z_STREAM_END);
83
84 // NULL-terminate string
85 // there is guaranteed to be space for this, due to condition in loop
86 buf[stream.total_out] = 0;
87
88 inflateEnd(&stream);
89
90 ret = CHECK_CU(cu->cuModuleLoadData(cu_module, buf));
91 av_free(buf);
92 return ret;
93 #else
94 return CHECK_CU(cu->cuModuleLoadData(cu_module, data));
95 #endif
96 }
97