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
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to