Quoting Mark Thompson (2017-03-05 00:57:47)
> ---
> configure | 5 +-
> doc/APIchanges | 4 +
> libavutil/Makefile | 2 +
> libavutil/hwcontext.c | 4 +
> libavutil/hwcontext.h | 1 +
> libavutil/hwcontext_internal.h | 1 +
> libavutil/hwcontext_opencl.c | 1182
> ++++++++++++++++++++++++++++++++++++++++
> libavutil/hwcontext_opencl.h | 117 ++++
> libavutil/version.h | 2 +-
> 9 files changed, 1316 insertions(+), 2 deletions(-)
> create mode 100644 libavutil/hwcontext_opencl.c
> create mode 100644 libavutil/hwcontext_opencl.h
>
> +static int opencl_frames_get_constraints(AVHWDeviceContext *hwdev,
> + const void *hwconfig,
> + AVHWFramesConstraints *constraints)
> +{
> + AVOpenCLDeviceContext *hwctx = hwdev->hwctx;
> + cl_uint nb_image_formats;
> + cl_image_format *image_formats = NULL;
> + cl_int cle;
> + enum AVPixelFormat pix_fmt;
> + int err, pix_fmts_found;
> + size_t max_width, max_height;
> +
> + cle = clGetDeviceInfo(hwctx->device_id, CL_DEVICE_IMAGE2D_MAX_WIDTH,
> + sizeof(max_width), &max_width, NULL);
> + if (cle != CL_SUCCESS) {
> + av_log(hwdev, AV_LOG_ERROR, "Failed to query maximum "
> + "supported image width: %d.\n", cle);
> + } else {
> + constraints->max_width = max_width;
> + }
> + cle = clGetDeviceInfo(hwctx->device_id, CL_DEVICE_IMAGE2D_MAX_HEIGHT,
> + sizeof(max_height), &max_height, NULL);
> + if (cle != CL_SUCCESS) {
> + av_log(hwdev, AV_LOG_ERROR, "Failed to query maximum "
> + "supported image height: %d.\n", cle);
> + } else {
> + constraints->max_height = max_height;
> + }
> + av_log(hwdev, AV_LOG_DEBUG, "Maximum supported image size %dx%d.\n",
> + constraints->max_width, constraints->max_height);
> +
> + cle = clGetSupportedImageFormats(hwctx->context,
> + CL_MEM_READ_WRITE,
> + CL_MEM_OBJECT_IMAGE2D,
> + 0, NULL, &nb_image_formats);
> + if (cle != CL_SUCCESS) {
> + av_log(hwdev, AV_LOG_ERROR, "Failed to query supported "
> + "image formats: %d.\n", cle);
> + err = AVERROR(ENOSYS);
> + goto fail;
> + }
> + if (nb_image_formats == 0) {
> + av_log(hwdev, AV_LOG_ERROR, "No image support in OpenCL "
> + "driver (zero supported image formats).\n");
> + err = AVERROR(ENOSYS);
> + goto fail;
> + }
> +
> + image_formats =
> + av_malloc(nb_image_formats * sizeof(*image_formats));
av_malloc_array?
> + if (!image_formats) {
> + err = AVERROR(ENOMEM);
> + goto fail;
> + }
> +
> + cle = clGetSupportedImageFormats(hwctx->context,
> + CL_MEM_READ_WRITE,
> + CL_MEM_OBJECT_IMAGE2D,
> + nb_image_formats,
> + image_formats, NULL);
> + if (cle != CL_SUCCESS) {
> + av_log(hwdev, AV_LOG_ERROR, "Failed to query supported "
> + "image formats: %d.\n", cle);
> + err = AVERROR(ENOSYS);
> + goto fail;
> + }
> +
> + pix_fmts_found = 0;
> + for (pix_fmt = 0; pix_fmt < AV_PIX_FMT_NB; pix_fmt++) {
> + cl_image_format image_format;
> + cl_image_desc image_desc;
> + int plane, i;
> +
> + for (plane = 0;; plane++) {
> + err = opencl_get_plane_format(pix_fmt, plane, 0, 0,
> + &image_format,
> + &image_desc);
Wouldn't it make sense to call this just once during frames context
init?
> + if (err < 0)
> + break;
> +
> + for (i = 0; i < nb_image_formats; i++) {
> + if (image_formats[i].image_channel_order ==
> + image_format.image_channel_order &&
> + image_formats[i].image_channel_data_type ==
> + image_format.image_channel_data_type)
> + break;
> + }
> + if (i == nb_image_formats) {
> + err = AVERROR(EINVAL);
> + break;
> + }
> + }
> + if (err != AVERROR(ENOENT))
> + continue;
> +
> + av_log(hwdev, AV_LOG_DEBUG, "Format %s supported.\n",
> + av_get_pix_fmt_name(pix_fmt));
> +
> + constraints->valid_sw_formats =
> + av_realloc_array(constraints->valid_sw_formats,
> + pix_fmts_found + 2,
> + sizeof(*constraints->valid_sw_formats));
leaks on failure
av_reallocp_array() perhaps?
> +static int opencl_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
> +{
> + AVOpenCLFrameDescriptor *desc;
> + int plane;
> +
> + frame->buf[0] = av_buffer_pool_get(hwfc->pool);
> + if (!frame->buf[0])
> + return AVERROR(ENOMEM);
> +
> + desc = (AVOpenCLFrameDescriptor*)frame->buf[0]->data;
> +
> + for (plane = 0; plane < AV_NUM_DATA_POINTERS &&
> + desc->image[plane]; plane++) {
> + frame->data[plane] = (uint8_t*)desc->image[plane];
> + frame->linesize[plane] = hwfc->width;
This looks wrong, at least for subsampled formats. And what about
alignment, is not needed?
> + }
> +
> + frame->format = AV_PIX_FMT_OPENCL;
> + frame->width = hwfc->width;
> + frame->height = hwfc->height;
> +
> + return 0;
> +}
> +
> +static int opencl_transfer_get_formats(AVHWFramesContext *hwfc,
> + enum AVHWFrameTransferDirection dir,
> + enum AVPixelFormat **formats)
> +{
> + enum AVPixelFormat *fmts;
> +
> + fmts = av_malloc_array(2, sizeof(*fmts));
> + if (!fmts)
> + return AVERROR(ENOMEM);
> +
> + fmts[0] = hwfc->sw_format;
> + fmts[1] = AV_PIX_FMT_NONE;
> +
> + *formats = fmts;
> + return 0;
> +}
> +
> +static cl_command_queue opencl_get_command_queue(AVHWFramesContext *hwfc)
> +{
> + AVOpenCLFramesContext *fc = hwfc->hwctx;
> + AVOpenCLDeviceContext *dc = hwfc->device_ctx->hwctx;
> + OpenCLDeviceContext *ctx = hwfc->device_ctx->internal->priv;
> +
> + if (fc->command_queue)
> + return fc->command_queue;
> + if (dc->command_queue)
> + return dc->command_queue;
> + av_assert0(ctx->command_queue);
> + return ctx->command_queue;
> +}
nit: perhaps it'd be more elegant to use clRetainCommandQueue to keep an
internal reference and avoid this
--
Anton Khirnov
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel