2424#include "mem.h"
2525#include "pixdesc.h"
2626#include "pixfmt.h"
27+ #include "imgutils.h"
2728
2829#define CUDA_FRAME_ALIGNMENT 256
2930
@@ -117,7 +118,6 @@ static AVBufferRef *cuda_pool_alloc(void *opaque, int size)
117118static int cuda_frames_init (AVHWFramesContext * ctx )
118119{
119120 CUDAFramesContext * priv = ctx -> internal -> priv ;
120- int aligned_width = FFALIGN (ctx -> width , CUDA_FRAME_ALIGNMENT );
121121 int i ;
122122
123123 for (i = 0 ; i < FF_ARRAY_ELEMS (supported_formats ); i ++ ) {
@@ -133,29 +133,10 @@ static int cuda_frames_init(AVHWFramesContext *ctx)
133133 av_pix_fmt_get_chroma_sub_sample (ctx -> sw_format , & priv -> shift_width , & priv -> shift_height );
134134
135135 if (!ctx -> pool ) {
136- int size ;
136+ int size = av_image_get_buffer_size ( ctx -> sw_format , ctx -> width , ctx -> height , CUDA_FRAME_ALIGNMENT ) ;
137137
138- switch (ctx -> sw_format ) {
139- case AV_PIX_FMT_NV12 :
140- case AV_PIX_FMT_YUV420P :
141- size = aligned_width * ctx -> height * 3 / 2 ;
142- break ;
143- case AV_PIX_FMT_YUV444P :
144- case AV_PIX_FMT_P010 :
145- case AV_PIX_FMT_P016 :
146- size = aligned_width * ctx -> height * 3 ;
147- break ;
148- case AV_PIX_FMT_YUV444P16 :
149- size = aligned_width * ctx -> height * 6 ;
150- break ;
151- case AV_PIX_FMT_0RGB32 :
152- case AV_PIX_FMT_0BGR32 :
153- size = aligned_width * ctx -> height * 4 ;
154- break ;
155- default :
156- av_log (ctx , AV_LOG_ERROR , "BUG: Pixel format missing from size calculation." );
157- return AVERROR_BUG ;
158- }
138+ if (size < 0 )
139+ return size ;
159140
160141 ctx -> internal -> pool_internal = av_buffer_pool_init2 (size , ctx , cuda_pool_alloc , NULL );
161142 if (!ctx -> internal -> pool_internal )
@@ -167,54 +148,22 @@ static int cuda_frames_init(AVHWFramesContext *ctx)
167148
168149static int cuda_get_buffer (AVHWFramesContext * ctx , AVFrame * frame )
169150{
170- int aligned_width ;
171- int width_in_bytes = ctx -> width ;
172-
173- if (ctx -> sw_format == AV_PIX_FMT_P010 ||
174- ctx -> sw_format == AV_PIX_FMT_P016 ||
175- ctx -> sw_format == AV_PIX_FMT_YUV444P16 ) {
176- width_in_bytes *= 2 ;
177- }
178- aligned_width = FFALIGN (width_in_bytes , CUDA_FRAME_ALIGNMENT );
151+ int res ;
179152
180153 frame -> buf [0 ] = av_buffer_pool_get (ctx -> pool );
181154 if (!frame -> buf [0 ])
182155 return AVERROR (ENOMEM );
183156
184- switch (ctx -> sw_format ) {
185- case AV_PIX_FMT_NV12 :
186- case AV_PIX_FMT_P010 :
187- case AV_PIX_FMT_P016 :
188- frame -> data [0 ] = frame -> buf [0 ]-> data ;
189- frame -> data [1 ] = frame -> data [0 ] + aligned_width * ctx -> height ;
190- frame -> linesize [0 ] = aligned_width ;
191- frame -> linesize [1 ] = aligned_width ;
192- break ;
193- case AV_PIX_FMT_YUV420P :
194- frame -> data [0 ] = frame -> buf [0 ]-> data ;
195- frame -> data [2 ] = frame -> data [0 ] + aligned_width * ctx -> height ;
196- frame -> data [1 ] = frame -> data [2 ] + aligned_width * ctx -> height / 4 ;
197- frame -> linesize [0 ] = aligned_width ;
198- frame -> linesize [1 ] = aligned_width / 2 ;
199- frame -> linesize [2 ] = aligned_width / 2 ;
200- break ;
201- case AV_PIX_FMT_YUV444P :
202- case AV_PIX_FMT_YUV444P16 :
203- frame -> data [0 ] = frame -> buf [0 ]-> data ;
204- frame -> data [1 ] = frame -> data [0 ] + aligned_width * ctx -> height ;
205- frame -> data [2 ] = frame -> data [1 ] + aligned_width * ctx -> height ;
206- frame -> linesize [0 ] = aligned_width ;
207- frame -> linesize [1 ] = aligned_width ;
208- frame -> linesize [2 ] = aligned_width ;
209- break ;
210- case AV_PIX_FMT_0BGR32 :
211- case AV_PIX_FMT_0RGB32 :
212- frame -> data [0 ] = frame -> buf [0 ]-> data ;
213- frame -> linesize [0 ] = aligned_width * 4 ;
214- break ;
215- default :
216- av_frame_unref (frame );
217- return AVERROR_BUG ;
157+ res = av_image_fill_arrays (frame -> data , frame -> linesize , frame -> buf [0 ]-> data ,
158+ ctx -> sw_format , ctx -> width , ctx -> height , CUDA_FRAME_ALIGNMENT );
159+ if (res < 0 )
160+ return res ;
161+
162+ // YUV420P is a special case.
163+ // Nvenc expects the U/V planes in swapped order from how ffmpeg expects them.
164+ if (ctx -> sw_format == AV_PIX_FMT_YUV420P ) {
165+ FFSWAP (uint8_t * , frame -> data [1 ], frame -> data [2 ]);
166+ FFSWAP (int , frame -> linesize [1 ], frame -> linesize [2 ]);
218167 }
219168
220169 frame -> format = AV_PIX_FMT_CUDA ;
0 commit comments