|
17 | 17 | */
|
18 | 18 |
|
19 | 19 | #include "libavutil/hwcontext.h"
|
| 20 | +#include "libavutil/pixdesc.h" |
20 | 21 |
|
21 | 22 | #include "ffmpeg.h"
|
22 | 23 |
|
23 |
| -typedef struct CUVIDContext { |
24 |
| - AVBufferRef *hw_frames_ctx; |
25 |
| -} CUVIDContext; |
26 |
| - |
27 | 24 | static void cuvid_uninit(AVCodecContext *avctx)
|
28 | 25 | {
|
29 |
| - InputStream *ist = avctx->opaque; |
30 |
| - CUVIDContext *ctx = ist->hwaccel_ctx; |
31 |
| - |
32 |
| - if (ctx) { |
33 |
| - av_buffer_unref(&ctx->hw_frames_ctx); |
34 |
| - av_freep(&ctx); |
35 |
| - } |
36 |
| - |
| 26 | + InputStream *ist = avctx->opaque; |
37 | 27 | av_buffer_unref(&ist->hw_frames_ctx);
|
38 |
| - |
39 |
| - ist->hwaccel_ctx = 0; |
40 |
| - ist->hwaccel_uninit = 0; |
41 | 28 | }
|
42 | 29 |
|
43 | 30 | int cuvid_init(AVCodecContext *avctx)
|
44 | 31 | {
|
45 |
| - InputStream *ist = avctx->opaque; |
46 |
| - CUVIDContext *ctx = ist->hwaccel_ctx; |
47 |
| - |
48 |
| - av_log(NULL, AV_LOG_TRACE, "Initializing cuvid hwaccel\n"); |
49 |
| - |
50 |
| - if (!ctx) { |
51 |
| - av_log(NULL, AV_LOG_ERROR, "CUVID transcoding is not initialized. " |
52 |
| - "-hwaccel cuvid should only be used for one-to-one CUVID transcoding " |
53 |
| - "with no (software) filters.\n"); |
54 |
| - return AVERROR(EINVAL); |
55 |
| - } |
56 |
| - |
57 |
| - return 0; |
58 |
| -} |
59 |
| - |
60 |
| -int cuvid_transcode_init(OutputStream *ost) |
61 |
| -{ |
62 |
| - InputStream *ist; |
63 |
| - const enum AVPixelFormat *pix_fmt; |
64 |
| - AVHWFramesContext *hwframe_ctx; |
65 |
| - AVBufferRef *device_ref = NULL; |
66 |
| - CUVIDContext *ctx = NULL; |
67 |
| - int ret = 0; |
68 |
| - |
69 |
| - av_log(NULL, AV_LOG_TRACE, "Initializing cuvid transcoding\n"); |
| 32 | + InputStream *ist = avctx->opaque; |
| 33 | + AVHWFramesContext *frames_ctx; |
| 34 | + int ret; |
70 | 35 |
|
71 |
| - if (ost->source_index < 0) |
72 |
| - return 0; |
| 36 | + av_log(avctx, AV_LOG_VERBOSE, "Initializing cuvid hwaccel\n"); |
73 | 37 |
|
74 |
| - ist = input_streams[ost->source_index]; |
75 |
| - |
76 |
| - /* check if the encoder supports CUVID */ |
77 |
| - if (!ost->enc->pix_fmts) |
78 |
| - goto cancel; |
79 |
| - for (pix_fmt = ost->enc->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++) |
80 |
| - if (*pix_fmt == AV_PIX_FMT_CUDA) |
81 |
| - break; |
82 |
| - if (*pix_fmt == AV_PIX_FMT_NONE) |
83 |
| - goto cancel; |
84 |
| - |
85 |
| - /* check if the decoder supports CUVID */ |
86 |
| - if (ist->hwaccel_id != HWACCEL_CUVID || !ist->dec || !ist->dec->pix_fmts) |
87 |
| - goto cancel; |
88 |
| - for (pix_fmt = ist->dec->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++) |
89 |
| - if (*pix_fmt == AV_PIX_FMT_CUDA) |
90 |
| - break; |
91 |
| - if (*pix_fmt == AV_PIX_FMT_NONE) |
92 |
| - goto cancel; |
93 |
| - |
94 |
| - av_log(NULL, AV_LOG_VERBOSE, "Setting up CUVID transcoding\n"); |
95 |
| - |
96 |
| - if (ist->hwaccel_ctx) { |
97 |
| - ctx = ist->hwaccel_ctx; |
98 |
| - } else { |
99 |
| - ctx = av_mallocz(sizeof(*ctx)); |
100 |
| - if (!ctx) { |
101 |
| - ret = AVERROR(ENOMEM); |
102 |
| - goto error; |
| 38 | + if (!hw_device_ctx) { |
| 39 | + ret = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_CUDA, |
| 40 | + ist->hwaccel_device, NULL, 0); |
| 41 | + if (ret < 0) { |
| 42 | + av_log(avctx, AV_LOG_ERROR, "Error creating a CUDA device\n"); |
| 43 | + return ret; |
103 | 44 | }
|
104 | 45 | }
|
105 | 46 |
|
106 |
| - if (!ctx->hw_frames_ctx) { |
107 |
| - ret = av_hwdevice_ctx_create(&device_ref, AV_HWDEVICE_TYPE_CUDA, |
108 |
| - ist->hwaccel_device, NULL, 0); |
109 |
| - if (ret < 0) |
110 |
| - goto error; |
| 47 | + av_buffer_unref(&ist->hw_frames_ctx); |
| 48 | + ist->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx); |
| 49 | + if (!ist->hw_frames_ctx) { |
| 50 | + av_log(avctx, AV_LOG_ERROR, "Error creating a CUDA frames context\n"); |
| 51 | + return AVERROR(ENOMEM); |
| 52 | + } |
111 | 53 |
|
112 |
| - ctx->hw_frames_ctx = av_hwframe_ctx_alloc(device_ref); |
113 |
| - if (!ctx->hw_frames_ctx) { |
114 |
| - av_log(NULL, AV_LOG_ERROR, "av_hwframe_ctx_alloc failed\n"); |
115 |
| - ret = AVERROR(ENOMEM); |
116 |
| - goto error; |
117 |
| - } |
118 |
| - av_buffer_unref(&device_ref); |
| 54 | + frames_ctx = (AVHWFramesContext*)ist->hw_frames_ctx->data; |
119 | 55 |
|
120 |
| - ist->hw_frames_ctx = av_buffer_ref(ctx->hw_frames_ctx); |
121 |
| - if (!ist->hw_frames_ctx) { |
122 |
| - av_log(NULL, AV_LOG_ERROR, "av_buffer_ref failed\n"); |
123 |
| - ret = AVERROR(ENOMEM); |
124 |
| - goto error; |
125 |
| - } |
| 56 | + frames_ctx->format = AV_PIX_FMT_CUDA; |
| 57 | + frames_ctx->sw_format = avctx->sw_pix_fmt; |
| 58 | + frames_ctx->width = avctx->width; |
| 59 | + frames_ctx->height = avctx->height; |
126 | 60 |
|
127 |
| - ist->hwaccel_ctx = ctx; |
128 |
| - ist->hwaccel_uninit = cuvid_uninit; |
| 61 | + av_log(avctx, AV_LOG_DEBUG, "Initializing CUDA frames context: sw_format = %s, width = %d, height = %d\n", |
| 62 | + av_get_pix_fmt_name(frames_ctx->sw_format), frames_ctx->width, frames_ctx->height); |
129 | 63 |
|
130 |
| - /* This is a bit hacky, av_hwframe_ctx_init is called by the cuvid decoder |
131 |
| - * once it has probed the necessary format information. But as filters/nvenc |
132 |
| - * need to know the format/sw_format, set them here so they are happy. |
133 |
| - * This is fine as long as CUVID doesn't add another supported pix_fmt. |
134 |
| - */ |
135 |
| - hwframe_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data; |
136 |
| - hwframe_ctx->format = AV_PIX_FMT_CUDA; |
137 |
| - hwframe_ctx->sw_format = ist->st->codecpar->format == AV_PIX_FMT_YUV420P10 ? AV_PIX_FMT_P010 : AV_PIX_FMT_NV12; |
| 64 | + ret = av_hwframe_ctx_init(ist->hw_frames_ctx); |
| 65 | + if (ret < 0) { |
| 66 | + av_log(avctx, AV_LOG_ERROR, "Error initializing a CUDA frame pool\n"); |
| 67 | + return ret; |
138 | 68 | }
|
139 | 69 |
|
140 |
| - return 0; |
141 |
| - |
142 |
| -error: |
143 |
| - av_freep(&ctx); |
144 |
| - av_buffer_unref(&device_ref); |
145 |
| - return ret; |
146 |
| - |
147 |
| -cancel: |
148 |
| - if (ist->hwaccel_id == HWACCEL_CUVID) { |
149 |
| - av_log(NULL, AV_LOG_ERROR, "CUVID hwaccel requested, but impossible to achieve.\n"); |
150 |
| - return AVERROR(EINVAL); |
151 |
| - } |
| 70 | + ist->hwaccel_uninit = cuvid_uninit; |
152 | 71 |
|
153 | 72 | return 0;
|
154 | 73 | }
|
0 commit comments