| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-23 14:56:49 +02:00
										 |  |  | #include "config_components.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | #include "libavutil/avassert.h"
 | 
					
						
							|  |  |  | #include "libavutil/common.h"
 | 
					
						
							| 
									
										
										
										
											2017-02-11 15:13:12 +00:00
										 |  |  | #include "libavutil/pixdesc.h"
 | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "avcodec.h"
 | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  | #include "decode.h"
 | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | #include "internal.h"
 | 
					
						
							|  |  |  | #include "vaapi_decode.h"
 | 
					
						
							| 
									
										
										
										
											2020-01-15 15:02:02 +08:00
										 |  |  | #include "vaapi_hevc.h"
 | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ff_vaapi_decode_make_param_buffer(AVCodecContext *avctx, | 
					
						
							|  |  |  |                                       VAAPIDecodePicture *pic, | 
					
						
							|  |  |  |                                       int type, | 
					
						
							|  |  |  |                                       const void *data, | 
					
						
							|  |  |  |                                       size_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; | 
					
						
							|  |  |  |     VAStatus vas; | 
					
						
							|  |  |  |     VABufferID buffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     av_assert0(pic->nb_param_buffers + 1 <= MAX_PARAM_BUFFERS); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, | 
					
						
							|  |  |  |                          type, size, 1, (void*)data, &buffer); | 
					
						
							|  |  |  |     if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "Failed to create parameter " | 
					
						
							|  |  |  |                "buffer (type %d): %d (%s).\n", | 
					
						
							|  |  |  |                type, vas, vaErrorStr(vas)); | 
					
						
							|  |  |  |         return AVERROR(EIO); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pic->param_buffers[pic->nb_param_buffers++] = buffer; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     av_log(avctx, AV_LOG_DEBUG, "Param buffer (type %d, %zu bytes) " | 
					
						
							|  |  |  |            "is %#x.\n", type, size, buffer); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ff_vaapi_decode_make_slice_buffer(AVCodecContext *avctx, | 
					
						
							|  |  |  |                                       VAAPIDecodePicture *pic, | 
					
						
							|  |  |  |                                       const void *params_data, | 
					
						
							|  |  |  |                                       size_t params_size, | 
					
						
							|  |  |  |                                       const void *slice_data, | 
					
						
							|  |  |  |                                       size_t slice_size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; | 
					
						
							|  |  |  |     VAStatus vas; | 
					
						
							|  |  |  |     int index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     av_assert0(pic->nb_slices <= pic->slices_allocated); | 
					
						
							|  |  |  |     if (pic->nb_slices == pic->slices_allocated) { | 
					
						
							|  |  |  |         if (pic->slices_allocated > 0) | 
					
						
							|  |  |  |             pic->slices_allocated *= 2; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             pic->slices_allocated = 64; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         pic->slice_buffers = | 
					
						
							|  |  |  |             av_realloc_array(pic->slice_buffers, | 
					
						
							|  |  |  |                              pic->slices_allocated, | 
					
						
							|  |  |  |                              2 * sizeof(*pic->slice_buffers)); | 
					
						
							|  |  |  |         if (!pic->slice_buffers) | 
					
						
							|  |  |  |             return AVERROR(ENOMEM); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     av_assert0(pic->nb_slices + 1 <= pic->slices_allocated); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     index = 2 * pic->nb_slices; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, | 
					
						
							|  |  |  |                          VASliceParameterBufferType, | 
					
						
							|  |  |  |                          params_size, 1, (void*)params_data, | 
					
						
							|  |  |  |                          &pic->slice_buffers[index]); | 
					
						
							|  |  |  |     if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "Failed to create slice " | 
					
						
							|  |  |  |                "parameter buffer: %d (%s).\n", vas, vaErrorStr(vas)); | 
					
						
							|  |  |  |         return AVERROR(EIO); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     av_log(avctx, AV_LOG_DEBUG, "Slice %d param buffer (%zu bytes) " | 
					
						
							|  |  |  |            "is %#x.\n", pic->nb_slices, params_size, | 
					
						
							|  |  |  |            pic->slice_buffers[index]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context, | 
					
						
							|  |  |  |                          VASliceDataBufferType, | 
					
						
							|  |  |  |                          slice_size, 1, (void*)slice_data, | 
					
						
							|  |  |  |                          &pic->slice_buffers[index + 1]); | 
					
						
							|  |  |  |     if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "Failed to create slice " | 
					
						
							|  |  |  |                "data buffer (size %zu): %d (%s).\n", | 
					
						
							|  |  |  |                slice_size, vas, vaErrorStr(vas)); | 
					
						
							|  |  |  |         vaDestroyBuffer(ctx->hwctx->display, | 
					
						
							|  |  |  |                         pic->slice_buffers[index]); | 
					
						
							|  |  |  |         return AVERROR(EIO); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     av_log(avctx, AV_LOG_DEBUG, "Slice %d data buffer (%zu bytes) " | 
					
						
							|  |  |  |            "is %#x.\n", pic->nb_slices, slice_size, | 
					
						
							|  |  |  |            pic->slice_buffers[index + 1]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ++pic->nb_slices; | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void ff_vaapi_decode_destroy_buffers(AVCodecContext *avctx, | 
					
						
							|  |  |  |                                             VAAPIDecodePicture *pic) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; | 
					
						
							|  |  |  |     VAStatus vas; | 
					
						
							|  |  |  |     int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < pic->nb_param_buffers; i++) { | 
					
						
							|  |  |  |         vas = vaDestroyBuffer(ctx->hwctx->display, | 
					
						
							|  |  |  |                               pic->param_buffers[i]); | 
					
						
							|  |  |  |         if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |             av_log(avctx, AV_LOG_ERROR, "Failed to destroy " | 
					
						
							|  |  |  |                    "parameter buffer %#x: %d (%s).\n", | 
					
						
							|  |  |  |                    pic->param_buffers[i], vas, vaErrorStr(vas)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < 2 * pic->nb_slices; i++) { | 
					
						
							|  |  |  |         vas = vaDestroyBuffer(ctx->hwctx->display, | 
					
						
							|  |  |  |                               pic->slice_buffers[i]); | 
					
						
							|  |  |  |         if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |             av_log(avctx, AV_LOG_ERROR, "Failed to destroy slice " | 
					
						
							|  |  |  |                    "slice buffer %#x: %d (%s).\n", | 
					
						
							|  |  |  |                    pic->slice_buffers[i], vas, vaErrorStr(vas)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ff_vaapi_decode_issue(AVCodecContext *avctx, | 
					
						
							|  |  |  |                           VAAPIDecodePicture *pic) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; | 
					
						
							|  |  |  |     VAStatus vas; | 
					
						
							|  |  |  |     int err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     av_log(avctx, AV_LOG_DEBUG, "Decode to surface %#x.\n", | 
					
						
							|  |  |  |            pic->output_surface); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context, | 
					
						
							|  |  |  |                          pic->output_surface); | 
					
						
							|  |  |  |     if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "Failed to begin picture decode " | 
					
						
							|  |  |  |                "issue: %d (%s).\n", vas, vaErrorStr(vas)); | 
					
						
							|  |  |  |         err = AVERROR(EIO); | 
					
						
							|  |  |  |         goto fail_with_picture; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, | 
					
						
							|  |  |  |                           pic->param_buffers, pic->nb_param_buffers); | 
					
						
							|  |  |  |     if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "Failed to upload decode " | 
					
						
							|  |  |  |                "parameters: %d (%s).\n", vas, vaErrorStr(vas)); | 
					
						
							|  |  |  |         err = AVERROR(EIO); | 
					
						
							|  |  |  |         goto fail_with_picture; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context, | 
					
						
							|  |  |  |                           pic->slice_buffers, 2 * pic->nb_slices); | 
					
						
							|  |  |  |     if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "Failed to upload slices: " | 
					
						
							|  |  |  |                "%d (%s).\n", vas, vaErrorStr(vas)); | 
					
						
							|  |  |  |         err = AVERROR(EIO); | 
					
						
							|  |  |  |         goto fail_with_picture; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vas = vaEndPicture(ctx->hwctx->display, ctx->va_context); | 
					
						
							|  |  |  |     if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "Failed to end picture decode " | 
					
						
							|  |  |  |                "issue: %d (%s).\n", vas, vaErrorStr(vas)); | 
					
						
							|  |  |  |         err = AVERROR(EIO); | 
					
						
							| 
									
										
										
										
											2017-10-01 22:51:20 +01:00
										 |  |  |         if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks & | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |             AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) | 
					
						
							|  |  |  |             goto fail; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             goto fail_at_end; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-01 22:51:20 +01:00
										 |  |  |     if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks & | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |         AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) | 
					
						
							|  |  |  |         ff_vaapi_decode_destroy_buffers(avctx, pic); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-19 10:01:23 +08:00
										 |  |  |     err = 0; | 
					
						
							|  |  |  |     goto exit; | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | fail_with_picture: | 
					
						
							|  |  |  |     vas = vaEndPicture(ctx->hwctx->display, ctx->va_context); | 
					
						
							|  |  |  |     if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "Failed to end picture decode " | 
					
						
							|  |  |  |                "after error: %d (%s).\n", vas, vaErrorStr(vas)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | fail: | 
					
						
							|  |  |  |     ff_vaapi_decode_destroy_buffers(avctx, pic); | 
					
						
							|  |  |  | fail_at_end: | 
					
						
							| 
									
										
										
										
											2018-09-19 10:01:23 +08:00
										 |  |  | exit: | 
					
						
							|  |  |  |     pic->nb_param_buffers = 0; | 
					
						
							|  |  |  |     pic->nb_slices        = 0; | 
					
						
							|  |  |  |     pic->slices_allocated = 0; | 
					
						
							|  |  |  |     av_freep(&pic->slice_buffers); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |     return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ff_vaapi_decode_cancel(AVCodecContext *avctx, | 
					
						
							|  |  |  |                            VAAPIDecodePicture *pic) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ff_vaapi_decode_destroy_buffers(avctx, pic); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pic->nb_param_buffers = 0; | 
					
						
							|  |  |  |     pic->nb_slices        = 0; | 
					
						
							|  |  |  |     pic->slices_allocated = 0; | 
					
						
							|  |  |  |     av_freep(&pic->slice_buffers); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-19 20:04:31 +00:00
										 |  |  | static const struct { | 
					
						
							|  |  |  |     uint32_t fourcc; | 
					
						
							|  |  |  |     enum AVPixelFormat pix_fmt; | 
					
						
							|  |  |  | } vaapi_format_map[] = { | 
					
						
							|  |  |  | #define MAP(va, av) { VA_FOURCC_ ## va, AV_PIX_FMT_ ## av }
 | 
					
						
							|  |  |  |     // 4:0:0
 | 
					
						
							|  |  |  |     MAP(Y800, GRAY8), | 
					
						
							|  |  |  |     // 4:2:0
 | 
					
						
							|  |  |  |     MAP(NV12, NV12), | 
					
						
							|  |  |  |     MAP(YV12, YUV420P), | 
					
						
							|  |  |  |     MAP(IYUV, YUV420P), | 
					
						
							|  |  |  | #ifdef VA_FOURCC_I420
 | 
					
						
							|  |  |  |     MAP(I420, YUV420P), | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     MAP(IMC3, YUV420P), | 
					
						
							|  |  |  |     // 4:1:1
 | 
					
						
							|  |  |  |     MAP(411P, YUV411P), | 
					
						
							|  |  |  |     // 4:2:2
 | 
					
						
							|  |  |  |     MAP(422H, YUV422P), | 
					
						
							|  |  |  | #ifdef VA_FOURCC_YV16
 | 
					
						
							|  |  |  |     MAP(YV16, YUV422P), | 
					
						
							| 
									
										
										
										
											2020-01-15 15:02:02 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |     MAP(YUY2, YUYV422), | 
					
						
							|  |  |  | #ifdef VA_FOURCC_Y210
 | 
					
						
							|  |  |  |     MAP(Y210,    Y210), | 
					
						
							| 
									
										
										
										
											2022-08-19 17:01:07 -07:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifdef VA_FOURCC_Y212
 | 
					
						
							|  |  |  |     MAP(Y212,    Y212), | 
					
						
							| 
									
										
										
										
											2018-02-19 20:04:31 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  |     // 4:4:0
 | 
					
						
							|  |  |  |     MAP(422V, YUV440P), | 
					
						
							|  |  |  |     // 4:4:4
 | 
					
						
							|  |  |  |     MAP(444P, YUV444P), | 
					
						
							| 
									
										
										
										
											2022-08-19 16:55:44 -07:00
										 |  |  | #ifdef VA_FOURCC_XYUV
 | 
					
						
							|  |  |  |     MAP(XYUV, VUYX), | 
					
						
							| 
									
										
										
										
											2022-08-19 17:01:07 -07:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #ifdef VA_FOURCC_Y410
 | 
					
						
							|  |  |  |     MAP(Y410,    XV30), | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #ifdef VA_FOURCC_Y412
 | 
					
						
							|  |  |  |     MAP(Y412,    XV36), | 
					
						
							| 
									
										
										
										
											2022-08-19 16:55:44 -07:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-02-19 20:04:31 +00:00
										 |  |  |     // 4:2:0 10-bit
 | 
					
						
							|  |  |  | #ifdef VA_FOURCC_P010
 | 
					
						
							|  |  |  |     MAP(P010, P010), | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2022-08-19 17:01:07 -07:00
										 |  |  | #ifdef VA_FOURCC_P012
 | 
					
						
							|  |  |  |     MAP(P012, P012), | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-02-19 20:04:31 +00:00
										 |  |  | #ifdef VA_FOURCC_I010
 | 
					
						
							|  |  |  |     MAP(I010, YUV420P10), | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #undef MAP
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int vaapi_decode_find_best_format(AVCodecContext *avctx, | 
					
						
							|  |  |  |                                          AVHWDeviceContext *device, | 
					
						
							|  |  |  |                                          VAConfigID config_id, | 
					
						
							|  |  |  |                                          AVHWFramesContext *frames) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     AVVAAPIDeviceContext *hwctx = device->hwctx; | 
					
						
							|  |  |  |     VAStatus vas; | 
					
						
							|  |  |  |     VASurfaceAttrib *attr; | 
					
						
							|  |  |  |     enum AVPixelFormat source_format, best_format, format; | 
					
						
							|  |  |  |     uint32_t best_fourcc, fourcc; | 
					
						
							|  |  |  |     int i, j, nb_attr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     source_format = avctx->sw_pix_fmt; | 
					
						
							|  |  |  |     av_assert0(source_format != AV_PIX_FMT_NONE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vas = vaQuerySurfaceAttributes(hwctx->display, config_id, | 
					
						
							|  |  |  |                                    NULL, &nb_attr); | 
					
						
							|  |  |  |     if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: " | 
					
						
							|  |  |  |                "%d (%s).\n", vas, vaErrorStr(vas)); | 
					
						
							|  |  |  |         return AVERROR(ENOSYS); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     attr = av_malloc_array(nb_attr, sizeof(*attr)); | 
					
						
							|  |  |  |     if (!attr) | 
					
						
							|  |  |  |         return AVERROR(ENOMEM); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     vas = vaQuerySurfaceAttributes(hwctx->display, config_id, | 
					
						
							|  |  |  |                                    attr, &nb_attr); | 
					
						
							|  |  |  |     if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "Failed to query surface attributes: " | 
					
						
							|  |  |  |                "%d (%s).\n", vas, vaErrorStr(vas)); | 
					
						
							|  |  |  |         av_freep(&attr); | 
					
						
							|  |  |  |         return AVERROR(ENOSYS); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     best_format = AV_PIX_FMT_NONE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < nb_attr; i++) { | 
					
						
							|  |  |  |         if (attr[i].type != VASurfaceAttribPixelFormat) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         fourcc = attr[i].value.value.i; | 
					
						
							|  |  |  |         for (j = 0; j < FF_ARRAY_ELEMS(vaapi_format_map); j++) { | 
					
						
							|  |  |  |             if (fourcc == vaapi_format_map[j].fourcc) | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (j >= FF_ARRAY_ELEMS(vaapi_format_map)) { | 
					
						
							|  |  |  |             av_log(avctx, AV_LOG_DEBUG, "Ignoring unknown format %#x.\n", | 
					
						
							|  |  |  |                    fourcc); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         format = vaapi_format_map[j].pix_fmt; | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_DEBUG, "Considering format %#x -> %s.\n", | 
					
						
							|  |  |  |                fourcc, av_get_pix_fmt_name(format)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         best_format = av_find_best_pix_fmt_of_2(format, best_format, | 
					
						
							|  |  |  |                                                 source_format, 0, NULL); | 
					
						
							|  |  |  |         if (format == best_format) | 
					
						
							|  |  |  |             best_fourcc = fourcc; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     av_freep(&attr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (best_format == AV_PIX_FMT_NONE) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "No usable formats for decoding!\n"); | 
					
						
							|  |  |  |         return AVERROR(EINVAL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     av_log(avctx, AV_LOG_DEBUG, "Picked %s (%#x) as best match for %s.\n", | 
					
						
							|  |  |  |            av_get_pix_fmt_name(best_format), best_fourcc, | 
					
						
							|  |  |  |            av_get_pix_fmt_name(source_format)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     frames->sw_format = best_format; | 
					
						
							|  |  |  |     if (avctx->internal->hwaccel_priv_data) { | 
					
						
							|  |  |  |         VAAPIDecodeContext    *ctx = avctx->internal->hwaccel_priv_data; | 
					
						
							|  |  |  |         AVVAAPIFramesContext *avfc = frames->hwctx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ctx->pixel_format_attribute = (VASurfaceAttrib) { | 
					
						
							|  |  |  |             .type          = VASurfaceAttribPixelFormat, | 
					
						
							| 
									
										
										
										
											2022-08-04 20:24:48 -07:00
										 |  |  |             .flags         = VA_SURFACE_ATTRIB_SETTABLE, | 
					
						
							|  |  |  |             .value.type    = VAGenericValueTypeInteger, | 
					
						
							| 
									
										
										
										
											2018-02-19 20:04:31 +00:00
										 |  |  |             .value.value.i = best_fourcc, | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         avfc->attributes    = &ctx->pixel_format_attribute; | 
					
						
							|  |  |  |         avfc->nb_attributes = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | static const struct { | 
					
						
							|  |  |  |     enum AVCodecID codec_id; | 
					
						
							|  |  |  |     int codec_profile; | 
					
						
							|  |  |  |     VAProfile va_profile; | 
					
						
							| 
									
										
										
										
											2020-01-15 15:02:02 +08:00
										 |  |  |     VAProfile (*profile_parser)(AVCodecContext *avctx); | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | } vaapi_profile_map[] = { | 
					
						
							| 
									
										
										
										
											2020-01-15 15:02:02 +08:00
										 |  |  | #define MAP(c, p, v, ...) { AV_CODEC_ID_ ## c, FF_PROFILE_ ## p, VAProfile ## v, __VA_ARGS__ }
 | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |     MAP(MPEG2VIDEO,  MPEG2_SIMPLE,    MPEG2Simple ), | 
					
						
							|  |  |  |     MAP(MPEG2VIDEO,  MPEG2_MAIN,      MPEG2Main   ), | 
					
						
							|  |  |  |     MAP(H263,        UNKNOWN,         H263Baseline), | 
					
						
							|  |  |  |     MAP(MPEG4,       MPEG4_SIMPLE,    MPEG4Simple ), | 
					
						
							|  |  |  |     MAP(MPEG4,       MPEG4_ADVANCED_SIMPLE, | 
					
						
							|  |  |  |                                MPEG4AdvancedSimple), | 
					
						
							|  |  |  |     MAP(MPEG4,       MPEG4_MAIN,      MPEG4Main   ), | 
					
						
							|  |  |  |     MAP(H264,        H264_CONSTRAINED_BASELINE, | 
					
						
							|  |  |  |                            H264ConstrainedBaseline), | 
					
						
							|  |  |  |     MAP(H264,        H264_MAIN,       H264Main    ), | 
					
						
							|  |  |  |     MAP(H264,        H264_HIGH,       H264High    ), | 
					
						
							|  |  |  | #if VA_CHECK_VERSION(0, 37, 0)
 | 
					
						
							|  |  |  |     MAP(HEVC,        HEVC_MAIN,       HEVCMain    ), | 
					
						
							|  |  |  |     MAP(HEVC,        HEVC_MAIN_10,    HEVCMain10  ), | 
					
						
							| 
									
										
										
										
											2020-01-15 15:02:40 +08:00
										 |  |  |     MAP(HEVC,        HEVC_MAIN_STILL_PICTURE, | 
					
						
							|  |  |  |                                       HEVCMain    ), | 
					
						
							| 
									
										
										
										
											2020-01-15 15:02:02 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-04-12 23:47:00 +08:00
										 |  |  | #if VA_CHECK_VERSION(1, 2, 0) && CONFIG_HEVC_VAAPI_HWACCEL
 | 
					
						
							| 
									
										
										
										
											2020-01-15 15:02:02 +08:00
										 |  |  |     MAP(HEVC,        HEVC_REXT,       None, | 
					
						
							| 
									
										
										
										
											2023-02-16 13:46:35 +08:00
										 |  |  |                  ff_vaapi_parse_hevc_rext_scc_profile ), | 
					
						
							|  |  |  |     MAP(HEVC,        HEVC_SCC,        None, | 
					
						
							|  |  |  |                  ff_vaapi_parse_hevc_rext_scc_profile ), | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2017-11-23 23:47:52 +00:00
										 |  |  |     MAP(MJPEG,       MJPEG_HUFFMAN_BASELINE_DCT, | 
					
						
							|  |  |  |                                       JPEGBaseline), | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |     MAP(WMV3,        VC1_SIMPLE,      VC1Simple   ), | 
					
						
							|  |  |  |     MAP(WMV3,        VC1_MAIN,        VC1Main     ), | 
					
						
							|  |  |  |     MAP(WMV3,        VC1_COMPLEX,     VC1Advanced ), | 
					
						
							|  |  |  |     MAP(WMV3,        VC1_ADVANCED,    VC1Advanced ), | 
					
						
							|  |  |  |     MAP(VC1,         VC1_SIMPLE,      VC1Simple   ), | 
					
						
							|  |  |  |     MAP(VC1,         VC1_MAIN,        VC1Main     ), | 
					
						
							|  |  |  |     MAP(VC1,         VC1_COMPLEX,     VC1Advanced ), | 
					
						
							|  |  |  |     MAP(VC1,         VC1_ADVANCED,    VC1Advanced ), | 
					
						
							|  |  |  |     MAP(VP8,         UNKNOWN,       VP8Version0_3 ), | 
					
						
							|  |  |  | #if VA_CHECK_VERSION(0, 38, 0)
 | 
					
						
							|  |  |  |     MAP(VP9,         VP9_0,           VP9Profile0 ), | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | #if VA_CHECK_VERSION(0, 39, 0)
 | 
					
						
							| 
									
										
										
										
											2022-07-23 11:24:33 -07:00
										 |  |  |     MAP(VP9,         VP9_1,           VP9Profile1 ), | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |     MAP(VP9,         VP9_2,           VP9Profile2 ), | 
					
						
							| 
									
										
										
										
											2022-08-19 17:01:07 -07:00
										 |  |  |     MAP(VP9,         VP9_3,           VP9Profile3 ), | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-10-29 14:54:25 +08:00
										 |  |  | #if VA_CHECK_VERSION(1, 8, 0)
 | 
					
						
							|  |  |  |     MAP(AV1,         AV1_MAIN,        AV1Profile0), | 
					
						
							|  |  |  |     MAP(AV1,         AV1_HIGH,        AV1Profile1), | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | #undef MAP
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Set *va_config and the frames_ref fields from the current codec parameters | 
					
						
							|  |  |  |  * in avctx. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static int vaapi_decode_make_config(AVCodecContext *avctx, | 
					
						
							|  |  |  |                                     AVBufferRef *device_ref, | 
					
						
							|  |  |  |                                     VAConfigID *va_config, | 
					
						
							|  |  |  |                                     AVBufferRef *frames_ref) | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     AVVAAPIHWConfig       *hwconfig    = NULL; | 
					
						
							|  |  |  |     AVHWFramesConstraints *constraints = NULL; | 
					
						
							|  |  |  |     VAStatus vas; | 
					
						
							|  |  |  |     int err, i, j; | 
					
						
							|  |  |  |     const AVCodecDescriptor *codec_desc; | 
					
						
							| 
									
										
										
										
											2020-01-15 15:02:02 +08:00
										 |  |  |     VAProfile *profile_list = NULL, matched_va_profile, va_profile; | 
					
						
							|  |  |  |     int profile_count, exact_match, matched_ff_profile, codec_profile; | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  |     AVHWDeviceContext    *device = (AVHWDeviceContext*)device_ref->data; | 
					
						
							|  |  |  |     AVVAAPIDeviceContext *hwctx = device->hwctx; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |     codec_desc = avcodec_descriptor_get(avctx->codec_id); | 
					
						
							|  |  |  |     if (!codec_desc) { | 
					
						
							|  |  |  |         err = AVERROR(EINVAL); | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  |     profile_count = vaMaxNumProfiles(hwctx->display); | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |     profile_list  = av_malloc_array(profile_count, | 
					
						
							|  |  |  |                                     sizeof(VAProfile)); | 
					
						
							|  |  |  |     if (!profile_list) { | 
					
						
							|  |  |  |         err = AVERROR(ENOMEM); | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  |     vas = vaQueryConfigProfiles(hwctx->display, | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |                                 profile_list, &profile_count); | 
					
						
							|  |  |  |     if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "Failed to query profiles: " | 
					
						
							|  |  |  |                "%d (%s).\n", vas, vaErrorStr(vas)); | 
					
						
							|  |  |  |         err = AVERROR(ENOSYS); | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 01:04:44 +00:00
										 |  |  |     matched_va_profile = VAProfileNone; | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |     exact_match = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < FF_ARRAY_ELEMS(vaapi_profile_map); i++) { | 
					
						
							|  |  |  |         int profile_match = 0; | 
					
						
							|  |  |  |         if (avctx->codec_id != vaapi_profile_map[i].codec_id) | 
					
						
							|  |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2017-11-18 17:52:27 +00:00
										 |  |  |         if (avctx->profile == vaapi_profile_map[i].codec_profile || | 
					
						
							|  |  |  |             vaapi_profile_map[i].codec_profile == FF_PROFILE_UNKNOWN) | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |             profile_match = 1; | 
					
						
							| 
									
										
										
										
											2020-01-15 15:02:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         va_profile = vaapi_profile_map[i].profile_parser ? | 
					
						
							|  |  |  |                      vaapi_profile_map[i].profile_parser(avctx) : | 
					
						
							|  |  |  |                      vaapi_profile_map[i].va_profile; | 
					
						
							|  |  |  |         codec_profile = vaapi_profile_map[i].codec_profile; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |         for (j = 0; j < profile_count; j++) { | 
					
						
							| 
									
										
										
										
											2020-01-15 15:02:02 +08:00
										 |  |  |             if (va_profile == profile_list[j]) { | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |                 exact_match = profile_match; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (j < profile_count) { | 
					
						
							| 
									
										
										
										
											2020-01-15 15:02:02 +08:00
										 |  |  |             matched_va_profile = va_profile; | 
					
						
							|  |  |  |             matched_ff_profile = codec_profile; | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |             if (exact_match) | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     av_freep(&profile_list); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 01:04:44 +00:00
										 |  |  |     if (matched_va_profile == VAProfileNone) { | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |         av_log(avctx, AV_LOG_ERROR, "No support for codec %s " | 
					
						
							|  |  |  |                "profile %d.\n", codec_desc->name, avctx->profile); | 
					
						
							|  |  |  |         err = AVERROR(ENOSYS); | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!exact_match) { | 
					
						
							| 
									
										
										
										
											2017-03-27 20:46:11 +01:00
										 |  |  |         if (avctx->hwaccel_flags & | 
					
						
							|  |  |  |             AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH) { | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |             av_log(avctx, AV_LOG_VERBOSE, "Codec %s profile %d not " | 
					
						
							|  |  |  |                    "supported for hardware decode.\n", | 
					
						
							|  |  |  |                    codec_desc->name, avctx->profile); | 
					
						
							|  |  |  |             av_log(avctx, AV_LOG_WARNING, "Using possibly-" | 
					
						
							|  |  |  |                    "incompatible profile %d instead.\n", | 
					
						
							| 
									
										
										
										
											2017-11-09 01:04:44 +00:00
										 |  |  |                    matched_ff_profile); | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             av_log(avctx, AV_LOG_VERBOSE, "Codec %s profile %d not " | 
					
						
							|  |  |  |                    "supported for hardware decode.\n", | 
					
						
							|  |  |  |                    codec_desc->name, avctx->profile); | 
					
						
							|  |  |  |             err = AVERROR(EINVAL); | 
					
						
							|  |  |  |             goto fail; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-09 01:04:44 +00:00
										 |  |  |     vas = vaCreateConfig(hwctx->display, matched_va_profile, | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  |                          VAEntrypointVLD, NULL, 0, | 
					
						
							|  |  |  |                          va_config); | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |     if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "Failed to create decode " | 
					
						
							|  |  |  |                "configuration: %d (%s).\n", vas, vaErrorStr(vas)); | 
					
						
							|  |  |  |         err = AVERROR(EIO); | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  |     hwconfig = av_hwdevice_hwconfig_alloc(device_ref); | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |     if (!hwconfig) { | 
					
						
							|  |  |  |         err = AVERROR(ENOMEM); | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  |     hwconfig->config_id = *va_config; | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     constraints = | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  |         av_hwdevice_get_hwframe_constraints(device_ref, hwconfig); | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |     if (!constraints) { | 
					
						
							| 
									
										
										
										
											2017-02-11 15:13:12 +00:00
										 |  |  |         err = AVERROR(ENOMEM); | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (avctx->coded_width  < constraints->min_width  || | 
					
						
							|  |  |  |         avctx->coded_height < constraints->min_height || | 
					
						
							|  |  |  |         avctx->coded_width  > constraints->max_width  || | 
					
						
							|  |  |  |         avctx->coded_height > constraints->max_height) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "Hardware does not support image " | 
					
						
							|  |  |  |                "size %dx%d (constraints: width %d-%d height %d-%d).\n", | 
					
						
							|  |  |  |                avctx->coded_width, avctx->coded_height, | 
					
						
							|  |  |  |                constraints->min_width,  constraints->max_width, | 
					
						
							|  |  |  |                constraints->min_height, constraints->max_height); | 
					
						
							|  |  |  |         err = AVERROR(EINVAL); | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!constraints->valid_sw_formats || | 
					
						
							|  |  |  |         constraints->valid_sw_formats[0] == AV_PIX_FMT_NONE) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "Hardware does not offer any " | 
					
						
							|  |  |  |                "usable surface formats.\n"); | 
					
						
							|  |  |  |         err = AVERROR(EINVAL); | 
					
						
							|  |  |  |         goto fail; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  |     if (frames_ref) { | 
					
						
							|  |  |  |         AVHWFramesContext *frames = (AVHWFramesContext *)frames_ref->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         frames->format = AV_PIX_FMT_VAAPI; | 
					
						
							|  |  |  |         frames->width = avctx->coded_width; | 
					
						
							|  |  |  |         frames->height = avctx->coded_height; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-19 20:04:31 +00:00
										 |  |  |         err = vaapi_decode_find_best_format(avctx, device, | 
					
						
							|  |  |  |                                             *va_config, frames); | 
					
						
							|  |  |  |         if (err < 0) | 
					
						
							|  |  |  |             goto fail; | 
					
						
							| 
									
										
										
										
											2017-02-11 15:13:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  |         frames->initial_pool_size = 1; | 
					
						
							|  |  |  |         // Add per-codec number of surfaces used for storing reference frames.
 | 
					
						
							|  |  |  |         switch (avctx->codec_id) { | 
					
						
							|  |  |  |         case AV_CODEC_ID_H264: | 
					
						
							|  |  |  |         case AV_CODEC_ID_HEVC: | 
					
						
							| 
									
										
										
										
											2021-10-12 16:24:01 +08:00
										 |  |  |         case AV_CODEC_ID_AV1: | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  |             frames->initial_pool_size += 16; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case AV_CODEC_ID_VP9: | 
					
						
							|  |  |  |             frames->initial_pool_size += 8; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case AV_CODEC_ID_VP8: | 
					
						
							|  |  |  |             frames->initial_pool_size += 3; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             frames->initial_pool_size += 2; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     av_hwframe_constraints_free(&constraints); | 
					
						
							|  |  |  |     av_freep(&hwconfig); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | fail: | 
					
						
							|  |  |  |     av_hwframe_constraints_free(&constraints); | 
					
						
							|  |  |  |     av_freep(&hwconfig); | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  |     if (*va_config != VA_INVALID_ID) { | 
					
						
							|  |  |  |         vaDestroyConfig(hwctx->display, *va_config); | 
					
						
							|  |  |  |         *va_config = VA_INVALID_ID; | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     av_freep(&profile_list); | 
					
						
							|  |  |  |     return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  | int ff_vaapi_common_frame_params(AVCodecContext *avctx, | 
					
						
							|  |  |  |                                  AVBufferRef *hw_frames_ctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     AVHWFramesContext *hw_frames = (AVHWFramesContext *)hw_frames_ctx->data; | 
					
						
							|  |  |  |     AVHWDeviceContext *device_ctx = hw_frames->device_ctx; | 
					
						
							|  |  |  |     AVVAAPIDeviceContext *hwctx; | 
					
						
							|  |  |  |     VAConfigID va_config = VA_INVALID_ID; | 
					
						
							|  |  |  |     int err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (device_ctx->type != AV_HWDEVICE_TYPE_VAAPI) | 
					
						
							|  |  |  |         return AVERROR(EINVAL); | 
					
						
							|  |  |  |     hwctx = device_ctx->hwctx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     err = vaapi_decode_make_config(avctx, hw_frames->device_ref, &va_config, | 
					
						
							|  |  |  |                                    hw_frames_ctx); | 
					
						
							|  |  |  |     if (err) | 
					
						
							|  |  |  |         return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (va_config != VA_INVALID_ID) | 
					
						
							|  |  |  |         vaDestroyConfig(hwctx->display, va_config); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | int ff_vaapi_decode_init(AVCodecContext *avctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; | 
					
						
							|  |  |  |     VAStatus vas; | 
					
						
							|  |  |  |     int err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ctx->va_config  = VA_INVALID_ID; | 
					
						
							|  |  |  |     ctx->va_context = VA_INVALID_ID; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  |     err = ff_decode_get_hw_frames_ctx(avctx, AV_HWDEVICE_TYPE_VAAPI); | 
					
						
							|  |  |  |     if (err < 0) | 
					
						
							| 
									
										
										
										
											2016-08-24 23:30:29 +01:00
										 |  |  |         goto fail; | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  |     ctx->frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data; | 
					
						
							|  |  |  |     ctx->hwfc   = ctx->frames->hwctx; | 
					
						
							|  |  |  |     ctx->device = ctx->frames->device_ctx; | 
					
						
							|  |  |  |     ctx->hwctx  = ctx->device->hwctx; | 
					
						
							| 
									
										
										
										
											2017-02-11 15:13:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  |     err = vaapi_decode_make_config(avctx, ctx->frames->device_ref, | 
					
						
							| 
									
										
										
										
											2022-01-11 14:55:37 +08:00
										 |  |  |                                    &ctx->va_config, NULL); | 
					
						
							| 
									
										
										
										
											2017-10-19 16:38:20 +02:00
										 |  |  |     if (err) | 
					
						
							|  |  |  |         goto fail; | 
					
						
							| 
									
										
										
										
											2017-02-11 15:13:12 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-24 23:30:29 +01:00
										 |  |  |     vas = vaCreateContext(ctx->hwctx->display, ctx->va_config, | 
					
						
							|  |  |  |                           avctx->coded_width, avctx->coded_height, | 
					
						
							|  |  |  |                           VA_PROGRESSIVE, | 
					
						
							|  |  |  |                           ctx->hwfc->surface_ids, | 
					
						
							|  |  |  |                           ctx->hwfc->nb_surfaces, | 
					
						
							|  |  |  |                           &ctx->va_context); | 
					
						
							|  |  |  |     if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |         av_log(avctx, AV_LOG_ERROR, "Failed to create decode " | 
					
						
							|  |  |  |                "context: %d (%s).\n", vas, vaErrorStr(vas)); | 
					
						
							|  |  |  |         err = AVERROR(EIO); | 
					
						
							|  |  |  |         goto fail; | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-24 23:30:29 +01:00
										 |  |  |     av_log(avctx, AV_LOG_DEBUG, "Decode context initialised: " | 
					
						
							|  |  |  |            "%#x/%#x.\n", ctx->va_config, ctx->va_context); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | fail: | 
					
						
							|  |  |  |     ff_vaapi_decode_uninit(avctx); | 
					
						
							|  |  |  |     return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int ff_vaapi_decode_uninit(AVCodecContext *avctx) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; | 
					
						
							|  |  |  |     VAStatus vas; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-24 23:30:29 +01:00
										 |  |  |     if (ctx->va_context != VA_INVALID_ID) { | 
					
						
							|  |  |  |         vas = vaDestroyContext(ctx->hwctx->display, ctx->va_context); | 
					
						
							|  |  |  |         if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |             av_log(avctx, AV_LOG_ERROR, "Failed to destroy decode " | 
					
						
							|  |  |  |                    "context %#x: %d (%s).\n", | 
					
						
							|  |  |  |                    ctx->va_context, vas, vaErrorStr(vas)); | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2016-08-24 23:30:29 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (ctx->va_config != VA_INVALID_ID) { | 
					
						
							|  |  |  |         vas = vaDestroyConfig(ctx->hwctx->display, ctx->va_config); | 
					
						
							|  |  |  |         if (vas != VA_STATUS_SUCCESS) { | 
					
						
							|  |  |  |             av_log(avctx, AV_LOG_ERROR, "Failed to destroy decode " | 
					
						
							|  |  |  |                    "configuration %#x: %d (%s).\n", | 
					
						
							|  |  |  |                    ctx->va_config, vas, vaErrorStr(vas)); | 
					
						
							| 
									
										
										
										
											2016-08-06 18:18:40 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } |