On 31/07/16 23:22, Mark Thompson wrote:
> +void *ff_vaapi_decode_alloc_slice_buffer(AVCodecContext *avctx,
> + VAAPIDecodePicture *pic,
> + size_t params_size,
> + const void *slice_data,
> + size_t data_size)
> +{
> + VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
> + VAAPIDecodeSlice *slice = NULL;
> + VAStatus vas;
> + void *addr = NULL;
> + VASliceParameterBufferBase *slice_param;
> +
> + if (pic->nb_slices == pic->slices_allocated) {
> + if (pic->slices_allocated > 0)
> + pic->slices_allocated *= 2;
> + else
> + pic->slices_allocated = 64;
> +
> + pic->slices = av_realloc_array(pic->slices,
> + pic->slices_allocated,
> + sizeof(*pic->slices));
> + if (!pic->slices)
> + return NULL;
> + }
> +
> + av_assert0(pic->nb_slices < pic->slices_allocated);
> + slice = &pic->slices[pic->nb_slices];
> + slice->param_buffer = VA_INVALID_ID;
> + slice->data_buffer = VA_INVALID_ID;
> +
> + vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
> + VASliceParameterBufferType, params_size,
> + 1, NULL, &slice->param_buffer);
> + if (vas != VA_STATUS_SUCCESS) {
> + av_log(avctx, AV_LOG_ERROR, "Failed to create slice "
> + "parameter buffer: %d (%s).\n", vas, vaErrorStr(vas));
> + goto fail;
> + }
> +
> + av_log(avctx, AV_LOG_DEBUG, "Slice %d param buffer (%zu bytes) "
> + "is %#x.\n", pic->nb_slices, params_size,
> + slice->param_buffer);
> +
> + vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
> + VASliceDataBufferType, data_size,
> + 1, (void*)slice_data, &slice->data_buffer);
> + if (vas != VA_STATUS_SUCCESS) {
> + av_log(avctx, AV_LOG_ERROR, "Failed to create slice "
> + "data buffer (size %zu): %d (%s).\n",
> + data_size, vas, vaErrorStr(vas));
> + goto fail;
> + }
> +
> + av_log(avctx, AV_LOG_DEBUG, "Slice %d data buffer (%zu bytes) "
> + "is %#x.\n", pic->nb_slices, data_size,
> + slice->data_buffer);
> +
> + vas = vaMapBuffer(ctx->hwctx->display,
> + slice->param_buffer, &addr);
> + if (vas != VA_STATUS_SUCCESS) {
> + av_log(avctx, AV_LOG_ERROR, "Failed to map slice parameter "
> + "buffer: %d (%s).\n", vas, vaErrorStr(vas));
> + goto fail;
> + }
> +
> + slice_param = addr;
> + slice_param->slice_data_size = data_size;
> + slice_param->slice_data_offset = 0;
> + slice_param->slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
> +
> + ++pic->nb_slices;
> +
> + return addr;
> +
> +fail:
> + if (slice) {
> + if (addr)
> + vaUnmapBuffer(ctx->hwctx->display,
> + slice->param_buffer);
> + if (slice->param_buffer != VA_INVALID_ID)
> + vaDestroyBuffer(ctx->hwctx->display,
> + slice->param_buffer);
> + if (slice->data_buffer != VA_INVALID_ID)
> + vaDestroyBuffer(ctx->hwctx->display,
> + slice->data_buffer);
> + }
> + return NULL;
> +}
This gets caught out somewhat by interlacing in H.264. The two fields of a
frame get the same VAAPIDecodePicture (hwaccel_picture_private), and then the
slices have to be rendered separately to the same surface. This currently
crashes because of the slice allocation - resetting slices_allocated in the
decode issue fixes it, but I don't really like how the picture structure is
being reused.
I'll see if I can come up with a nicer way of dealing with it (though I do
mostly want to ignore the problem on "interlacing is an abomination" grounds).
- Mark
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel