Backport from https://phabricator.services.mozilla.com/D216919 --- Waterfox-G6.0.17/media/ffvpx/libavcodec/vaapi_av1.c +++ Waterfox-G6.0.17/media/ffvpx/libavcodec/vaapi_av1.c @@ -14,16 +14,17 @@ * 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 */ #include "libavutil/frame.h" +#include "libavutil/mem.h" #include "libavutil/pixdesc.h" #include "hwconfig.h" #include "vaapi_decode.h" #include "internal.h" #include "av1dec.h" #include "thread.h" typedef struct VAAPIAV1FrameRef { @@ -38,16 +39,19 @@ * For film grain case, VAAPI generate 2 output for each frame, * current_frame will not apply film grain, and will be used for * references for next frames. Maintain the reference list without * applying film grain here. And current_display_picture will be * used to apply film grain and push to downstream. */ VAAPIAV1FrameRef ref_tab[AV1_NUM_REF_FRAMES]; AVFrame *tmp_frame; + + int nb_slice_params; + VASliceParameterBufferAV1 *slice_params; } VAAPIAV1DecContext; static VASurfaceID vaapi_av1_surface_id(AV1Frame *vf) { if (vf) return ff_vaapi_get_surface_id(vf->f); else return VA_INVALID_SURFACE; @@ -104,16 +108,18 @@ av_frame_free(&ctx->tmp_frame); for (int i = 0; i < FF_ARRAY_ELEMS(ctx->ref_tab); i++) { if (ctx->ref_tab[i].frame->buf[0]) ff_thread_release_buffer(avctx, ctx->ref_tab[i].frame); av_frame_free(&ctx->ref_tab[i].frame); } + av_freep(&ctx->slice_params); + return ff_vaapi_decode_uninit(avctx); } static int vaapi_av1_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size) { @@ -400,43 +406,56 @@ } static int vaapi_av1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { const AV1DecContext *s = avctx->priv_data; VAAPIDecodePicture *pic = s->cur_frame.hwaccel_picture_private; - VASliceParameterBufferAV1 slice_param; - int err = 0; + VAAPIAV1DecContext *ctx = avctx->internal->hwaccel_priv_data; + int err, nb_params; - for (int i = s->tg_start; i <= s->tg_end; i++) { - memset(&slice_param, 0, sizeof(VASliceParameterBufferAV1)); + nb_params = s->tg_end - s->tg_start + 1; + if (ctx->nb_slice_params < nb_params) { + ctx->slice_params = av_realloc_array(ctx->slice_params, + nb_params, + sizeof(*ctx->slice_params)); + if (!ctx->slice_params) { + ctx->nb_slice_params = 0; + err = AVERROR(ENOMEM); + goto fail; + } + ctx->nb_slice_params = nb_params; + } - slice_param = (VASliceParameterBufferAV1) { + for (int i = s->tg_start; i <= s->tg_end; i++) { + ctx->slice_params[i - s->tg_start] = (VASliceParameterBufferAV1) { .slice_data_size = s->tile_group_info[i].tile_size, .slice_data_offset = s->tile_group_info[i].tile_offset, .slice_data_flag = VA_SLICE_DATA_FLAG_ALL, .tile_row = s->tile_group_info[i].tile_row, .tile_column = s->tile_group_info[i].tile_column, .tg_start = s->tg_start, .tg_end = s->tg_end, }; - - err = ff_vaapi_decode_make_slice_buffer(avctx, pic, &slice_param, - sizeof(VASliceParameterBufferAV1), - buffer, - size); - if (err) { - ff_vaapi_decode_cancel(avctx, pic); - return err; - } } + err = ff_vaapi_decode_make_slice_buffer(avctx, pic, ctx->slice_params, nb_params, + sizeof(VASliceParameterBufferAV1), + buffer, + size); + if (err) + goto fail; + return 0; + +fail: + ff_vaapi_decode_cancel(avctx, pic); + return err; } const AVHWAccel ff_av1_vaapi_hwaccel = { .name = "av1_vaapi", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_AV1, .pix_fmt = AV_PIX_FMT_VAAPI, .start_frame = vaapi_av1_start_frame, --- Waterfox-G6.0.17/media/ffvpx/libavcodec/vaapi_decode.c +++ Waterfox-G6.0.17/media/ffvpx/libavcodec/vaapi_decode.c @@ -56,16 +56,17 @@ "is %#x.\n", type, size, buffer); return 0; } int ff_vaapi_decode_make_slice_buffer(AVCodecContext *avctx, VAAPIDecodePicture *pic, const void *params_data, + int nb_params, size_t params_size, const void *slice_data, size_t slice_size) { VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data; VAStatus vas; int index; @@ -84,17 +85,17 @@ 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, + params_size, nb_params, (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) " --- Waterfox-G6.0.17/media/ffvpx/libavcodec/vaapi_decode.h +++ Waterfox-G6.0.17/media/ffvpx/libavcodec/vaapi_decode.h @@ -68,16 +68,17 @@ VAAPIDecodePicture *pic, int type, const void *data, size_t size); int ff_vaapi_decode_make_slice_buffer(AVCodecContext *avctx, VAAPIDecodePicture *pic, const void *params_data, + int nb_params, size_t params_size, const void *slice_data, size_t slice_size); int ff_vaapi_decode_issue(AVCodecContext *avctx, VAAPIDecodePicture *pic); int ff_vaapi_decode_cancel(AVCodecContext *avctx, VAAPIDecodePicture *pic); --- Waterfox-G6.0.17/media/ffvpx/libavcodec/vaapi_vp8.c +++ Waterfox-G6.0.17/media/ffvpx/libavcodec/vaapi_vp8.c @@ -204,17 +204,17 @@ s->coder_state_at_header_end.bit_count - 8), .num_of_partitions = s->num_coeff_partitions + 1, }; sp.partition_size[0] = s->header_partition_size - ((sp.macroblock_offset + 7) / 8); for (i = 0; i < 8; i++) sp.partition_size[i+1] = s->coeff_partition_size[i]; - err = ff_vaapi_decode_make_slice_buffer(avctx, pic, &sp, sizeof(sp), data, data_size); + err = ff_vaapi_decode_make_slice_buffer(avctx, pic, &sp, 1, sizeof(sp), data, data_size); if (err) goto fail; return 0; fail: ff_vaapi_decode_cancel(avctx, pic); return err; --- Waterfox-G6.0.17/media/ffvpx/libavcodec/vaapi_vp9.c +++ Waterfox-G6.0.17/media/ffvpx/libavcodec/vaapi_vp9.c @@ -153,17 +153,17 @@ .chroma_dc_quant_scale = h->h.segmentation.feat[i].qmul[1][0], .chroma_ac_quant_scale = h->h.segmentation.feat[i].qmul[1][1], }; memcpy(slice_param.seg_param[i].filter_level, h->h.segmentation.feat[i].lflvl, sizeof(slice_param.seg_param[i].filter_level)); } err = ff_vaapi_decode_make_slice_buffer(avctx, pic, - &slice_param, sizeof(slice_param), + &slice_param, 1, sizeof(slice_param), buffer, size); if (err) { ff_vaapi_decode_cancel(avctx, pic); return err; } return 0; }