On 09/03/17 19:20, Anton Khirnov wrote:
> 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?

Yep, ok.

>> +    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?

Hmm, yeah, probably (with s/frames/device/).  (This was significantly saner 
before it did all the pixdesc stuff.)

>> +            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?

Yeah.

>> +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?

The linesize is not really meaningful here at all now, I'll just remove it.

Image planes are just required to be aligned as a single element of the plane, 
which must be aligned to the size of a single component multiplied by the 
number of components rounded up to the next power of two.  This is somewhat 
weaker than the normal constraints in libav for SIMD.

>> +    }
>> +
>> +    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

Yeah, that would be better.

Thanks,

- Mark
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to