@@ -167,6 +167,15 @@ static const uint8_t bwh_tab[2][N_BS_SIZES][2] = {
167167 }
168168};
169169
170+ static void vp9_unref_frame (AVCodecContext * ctx , VP9Frame * f )
171+ {
172+ ff_thread_release_buffer (ctx , & f -> tf );
173+ av_buffer_unref (& f -> extradata );
174+ av_buffer_unref (& f -> hwaccel_priv_buf );
175+ f -> segmentation_map = NULL ;
176+ f -> hwaccel_picture_private = NULL ;
177+ }
178+
170179static int vp9_alloc_frame (AVCodecContext * ctx , VP9Frame * f )
171180{
172181 VP9Context * s = ctx -> priv_data ;
@@ -176,21 +185,28 @@ static int vp9_alloc_frame(AVCodecContext *ctx, VP9Frame *f)
176185 return ret ;
177186 sz = 64 * s -> sb_cols * s -> sb_rows ;
178187 if (!(f -> extradata = av_buffer_allocz (sz * (1 + sizeof (struct VP9mvrefPair ))))) {
179- ff_thread_release_buffer (ctx , & f -> tf );
180- return AVERROR (ENOMEM );
188+ goto fail ;
181189 }
182190
183191 f -> segmentation_map = f -> extradata -> data ;
184192 f -> mv = (struct VP9mvrefPair * ) (f -> extradata -> data + sz );
185193
194+ if (ctx -> hwaccel ) {
195+ const AVHWAccel * hwaccel = ctx -> hwaccel ;
196+ av_assert0 (!f -> hwaccel_picture_private );
197+ if (hwaccel -> frame_priv_data_size ) {
198+ f -> hwaccel_priv_buf = av_buffer_allocz (hwaccel -> frame_priv_data_size );
199+ if (!f -> hwaccel_priv_buf )
200+ goto fail ;
201+ f -> hwaccel_picture_private = f -> hwaccel_priv_buf -> data ;
202+ }
203+ }
204+
186205 return 0 ;
187- }
188206
189- static void vp9_unref_frame (AVCodecContext * ctx , VP9Frame * f )
190- {
191- ff_thread_release_buffer (ctx , & f -> tf );
192- av_buffer_unref (& f -> extradata );
193- f -> segmentation_map = NULL ;
207+ fail :
208+ vp9_unref_frame (ctx , f );
209+ return AVERROR (ENOMEM );
194210}
195211
196212static int vp9_ref_frame (AVCodecContext * ctx , VP9Frame * dst , VP9Frame * src )
@@ -200,30 +216,59 @@ static int vp9_ref_frame(AVCodecContext *ctx, VP9Frame *dst, VP9Frame *src)
200216 if ((res = ff_thread_ref_frame (& dst -> tf , & src -> tf )) < 0 ) {
201217 return res ;
202218 } else if (!(dst -> extradata = av_buffer_ref (src -> extradata ))) {
203- vp9_unref_frame (ctx , dst );
204- return AVERROR (ENOMEM );
219+ goto fail ;
205220 }
206221
207222 dst -> segmentation_map = src -> segmentation_map ;
208223 dst -> mv = src -> mv ;
209224 dst -> uses_2pass = src -> uses_2pass ;
210225
226+ if (src -> hwaccel_picture_private ) {
227+ dst -> hwaccel_priv_buf = av_buffer_ref (src -> hwaccel_priv_buf );
228+ if (!dst -> hwaccel_priv_buf )
229+ goto fail ;
230+ dst -> hwaccel_picture_private = dst -> hwaccel_priv_buf -> data ;
231+ }
232+
211233 return 0 ;
234+
235+ fail :
236+ vp9_unref_frame (ctx , dst );
237+ return AVERROR (ENOMEM );
212238}
213239
214240static int update_size (AVCodecContext * ctx , int w , int h , enum AVPixelFormat fmt )
215241{
242+ #define HWACCEL_MAX (CONFIG_VP9_DXVA2_HWACCEL + CONFIG_VP9_D3D11VA_HWACCEL)
243+ enum AVPixelFormat pix_fmts [HWACCEL_MAX + 2 ], * fmtp = pix_fmts ;
216244 VP9Context * s = ctx -> priv_data ;
217245 uint8_t * p ;
218246 int bytesperpixel = s -> bytesperpixel ;
219247
220248 av_assert0 (w > 0 && h > 0 );
221249
222- if (s -> intra_pred_data [0 ] && w == ctx -> width && h == ctx -> height && ctx -> pix_fmt == fmt )
250+ if (s -> intra_pred_data [0 ] && w == ctx -> width && h == ctx -> height && ( ctx -> pix_fmt == fmt || ( ctx -> hwaccel && ctx -> sw_pix_fmt == fmt )) )
223251 return 0 ;
224252
225- ctx -> width = w ;
226- ctx -> height = h ;
253+ ctx -> coded_width = ctx -> width = w ;
254+ ctx -> coded_height = ctx -> height = h ;
255+
256+ if (fmt == AV_PIX_FMT_YUV420P ) {
257+ #if CONFIG_VP9_DXVA2_HWACCEL
258+ * fmtp ++ = AV_PIX_FMT_DXVA2_VLD ;
259+ #endif
260+ #if CONFIG_VP9_D3D11VA_HWACCEL
261+ * fmtp ++ = AV_PIX_FMT_D3D11VA_VLD ;
262+ #endif
263+
264+ * fmtp ++ = fmt ;
265+ * fmtp = AV_PIX_FMT_NONE ;
266+
267+ fmt = ff_thread_get_format (ctx , pix_fmts );
268+ if (fmt < 0 )
269+ return fmt ;
270+ }
271+
227272 ctx -> pix_fmt = fmt ;
228273 s -> sb_cols = (w + 63 ) >> 6 ;
229274 s -> sb_rows = (h + 63 ) >> 6 ;
@@ -450,7 +495,7 @@ static int decode_frame_header(AVCodecContext *ctx,
450495{
451496 VP9Context * s = ctx -> priv_data ;
452497 int c , i , j , k , l , m , n , w , h , max , size2 , res , sharp ;
453- enum AVPixelFormat fmt = ctx -> pix_fmt ;
498+ enum AVPixelFormat fmt = ctx -> sw_pix_fmt ;
454499 int last_invisible ;
455500 const uint8_t * data2 ;
456501
@@ -577,8 +622,9 @@ static int decode_frame_header(AVCodecContext *ctx,
577622 for (i = 0 ; i < 3 ; i ++ ) {
578623 AVFrame * ref = s -> s .refs [s -> s .h .refidx [i ]].f ;
579624 int refw = ref -> width , refh = ref -> height ;
625+ const AVPixFmtDescriptor * desc = av_pix_fmt_desc_get (ref -> format );
580626
581- if (ref -> format != fmt ) {
627+ if (ref -> format != fmt && (! desc || !( desc -> flags & AV_PIX_FMT_FLAG_HWACCEL ) || fmt != AV_PIX_FMT_YUV420P ) ) {
582628 av_log (ctx , AV_LOG_ERROR ,
583629 "Ref pixfmt (%s) did not match current frame (%s)" ,
584630 av_get_pix_fmt_name (ref -> format ),
@@ -3978,6 +4024,19 @@ static int vp9_decode_frame(AVCodecContext *ctx, void *frame,
39784024 return res ;
39794025 }
39804026
4027+ if (ctx -> hwaccel ) {
4028+ res = ctx -> hwaccel -> start_frame (ctx , NULL , 0 );
4029+ if (res < 0 )
4030+ return res ;
4031+ res = ctx -> hwaccel -> decode_slice (ctx , pkt -> data , pkt -> size );
4032+ if (res < 0 )
4033+ return res ;
4034+ res = ctx -> hwaccel -> end_frame (ctx );
4035+ if (res < 0 )
4036+ return res ;
4037+ goto finish ;
4038+ }
4039+
39814040 // main tile decode loop
39824041 bytesperpixel = s -> bytesperpixel ;
39834042 memset (s -> above_partition_ctx , 0 , s -> cols );
@@ -4147,6 +4206,7 @@ static int vp9_decode_frame(AVCodecContext *ctx, void *frame,
41474206 } while (s -> pass ++ == 1 );
41484207 ff_thread_report_progress (& s -> s .frames [CUR_FRAME ].tf , INT_MAX , 0 );
41494208
4209+ finish :
41504210 // ref frame setup
41514211 for (i = 0 ; i < 8 ; i ++ ) {
41524212 if (s -> s .refs [i ].f -> buf [0 ])
0 commit comments