[FFmpeg-devel] [PATCH 1/2] libavutil/libavfilter: opencl wrapper based on comments on 20130330

Stefano Sabatini stefasab at gmail.com
Sat Mar 30 14:14:28 CET 2013


On date Saturday 2013-03-30 18:47:42 +0800, Wei Gao encoded:
> 

> From 9f092f2e65c09a5462ed243801cf954145a547e4 Mon Sep 17 00:00:00 2001
> From: highgod0401 <highgod0401 at gmail.com>
> Date: Sat, 30 Mar 2013 18:28:18 +0800
> Subject: [PATCH 1/2] opencl wrapper based on comments on 20130330
> 
> ---
>  configure          |   4 +
>  libavutil/Makefile |   3 +
>  libavutil/opencl.c | 730 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  libavutil/opencl.h | 205 +++++++++++++++
>  4 files changed, 942 insertions(+)
>  create mode 100644 libavutil/opencl.c
>  create mode 100644 libavutil/opencl.h
> 
[...]
> +int av_opencl_buffer_create(cl_mem *cl_buf, size_t cl_buf_size, int flags, void *host_ptr)
> +{
> +    cl_int status;
> +    *cl_buf = clCreateBuffer(gpu_env.context, flags, cl_buf_size, host_ptr, &status);
> +    if (status != CL_SUCCESS) {
> +        av_log(&openclutils, AV_LOG_ERROR, "Could not create OpenCL buffer: %s\n", opencl_errstr(status));
> +        return AVERROR_EXTERNAL;
> +    }
> +    return 0;
> +}
> +

> +void av_opencl_buffer_release(cl_mem cl_buf)
> +{
> +    cl_int status = 0;

> +    if (!cl_buf)

this is never true, since cl_buf is an address to the stack.

> +        return;

> +    status = clReleaseMemObject(cl_buf);
> +    if (status != CL_SUCCESS) {
> +        av_log(&openclutils, AV_LOG_ERROR, "Could not release OpenCL buffer: %s\n", opencl_errstr(status));
> +    }
> +}

Maybe you mean:

void av_opencl_buffer_release(cl_mem *cl_buf)
{
...
status = clReleaseMemObject(*cl_buf);
...
}

which should be safer since doesn't leave the unchanged value of
cl_buf in the environment.

> +
> +int av_opencl_buffer_write(cl_mem dst_cl_buf, uint8_t *src_buf, size_t buf_size)
> +{
> +    cl_int status;
> +    void *mapped = clEnqueueMapBuffer(gpu_env.command_queue, dst_cl_buf,
> +                                      CL_TRUE,CL_MAP_WRITE, 0, sizeof(uint8_t) * buf_size,
> +                                      0, NULL, NULL, &status);
> +
> +    if (status != CL_SUCCESS) {
> +        av_log(&openclutils, AV_LOG_ERROR, "Could not map OpenCL buffer: %s\n", opencl_errstr(status));
> +        return AVERROR_EXTERNAL;
> +    }
> +    memcpy(mapped, src_buf, buf_size);
> +
> +    status = clEnqueueUnmapMemObject(gpu_env.command_queue, dst_cl_buf, mapped, 0, NULL, NULL);
> +    if (status != CL_SUCCESS) {
> +        av_log(&openclutils, AV_LOG_ERROR, "Could not unmap OpenCL buffer: %s\n", opencl_errstr(status));
> +        return AVERROR_EXTERNAL;
> +    }
> +    return 0;
> +}
> +
> +int av_opencl_buffer_read(uint8_t *dst_buf, cl_mem src_cl_buf, size_t buf_size)
> +{
> +    cl_int status;
> +    void *mapped = clEnqueueMapBuffer(gpu_env.command_queue, src_cl_buf,
> +                                      CL_TRUE,CL_MAP_READ, 0, buf_size,
> +                                      0, NULL, NULL, &status);
> +
> +    if (status != CL_SUCCESS) {
> +        av_log(&openclutils, AV_LOG_ERROR, "Could not map OpenCL buffer: %s\n", opencl_errstr(status));
> +        return AVERROR_EXTERNAL;
> +    }
> +    memcpy(dst_buf, mapped, buf_size);
> +
> +    status = clEnqueueUnmapMemObject(gpu_env.command_queue, src_cl_buf, mapped, 0, NULL, NULL);
> +    if (status != CL_SUCCESS) {
> +        av_log(&openclutils, AV_LOG_ERROR, "Could not unmap OpenCL buffer: %s\n", opencl_errstr(status));
> +        return AVERROR_EXTERNAL;
> +    }
> +    return 0;
> +}
> +
> +int av_opencl_buffer_write_image(cl_mem dst_cl_buf, size_t cl_buffer_size,
> +                                        uint8_t **src_data, int *plane_size, int plane_num, int offset)
> +{
> +    int i, buffer_size = 0;
> +    uint8_t *temp;
> +    cl_int status;
> +    void *mapped;
> +    if ((unsigned int)plane_num > 8) {
> +        return AVERROR(EINVAL);
> +    }
> +    for (i = 0;i < plane_num;i++) {
> +        buffer_size += plane_size[i];
> +    }
> +    if (buffer_size > cl_buffer_size) {
> +        av_log(&openclutils, AV_LOG_ERROR, "Cannot write image to OpenCL buffer: buffer too small\n");
> +        return AVERROR(EINVAL);
> +    }
> +    mapped = clEnqueueMapBuffer(gpu_env.command_queue, dst_cl_buf,
> +                                      CL_TRUE,CL_MAP_WRITE, 0, buffer_size + offset,
> +                                      0, NULL, NULL, &status);
> +    if (status != CL_SUCCESS) {
> +        av_log(&openclutils, AV_LOG_ERROR, "Could not map OpenCL buffer: %s\n", opencl_errstr(status));
> +        return AVERROR_EXTERNAL;
> +    }
> +    temp = mapped;
> +    temp += offset;
> +    for (i = 0; i < plane_num; i++) {
> +        memcpy(temp, src_data[i], plane_size[i]);
> +        temp += plane_size[i];
> +    }
> +    status = clEnqueueUnmapMemObject(gpu_env.command_queue, dst_cl_buf, mapped, 0, NULL, NULL);
> +    if (status != CL_SUCCESS) {
> +        av_log(&openclutils, AV_LOG_ERROR, "Could not unmap OpenCL buffer: %s\n", opencl_errstr(status));
> +        return AVERROR_EXTERNAL;
> +    }
> +    return 0;
> +}
> +
> +int av_opencl_buffer_read_image(uint8_t **dst_data, int *plane_size, int plane_num,
> +                                       cl_mem src_cl_buf, size_t cl_buffer_size)
> +{
> +    int i,buffer_size = 0,ret = 0;
> +    uint8_t *temp;
> +    void *mapped;
> +    cl_int status;
> +    if ((unsigned int)plane_num > 8) {
> +        return AVERROR(EINVAL);
> +    }
> +    for (i = 0;i < plane_num;i++) {
> +        buffer_size += plane_size[i];
> +    }
> +    if (buffer_size > cl_buffer_size) {
> +        av_log(&openclutils, AV_LOG_ERROR, "Cannot write image to CPU buffer: OpenCL buffer too small\n");
> +        return AVERROR(EINVAL);
> +    }
> +    mapped = clEnqueueMapBuffer(gpu_env.command_queue, src_cl_buf,
> +                                      CL_TRUE,CL_MAP_READ, 0, buffer_size,
> +                                      0, NULL, NULL, &status);
> +
> +    if (status != CL_SUCCESS) {
> +        av_log(&openclutils, AV_LOG_ERROR, "Could not map OpenCL buffer: %s\n", opencl_errstr(status));
> +        return AVERROR_EXTERNAL;
> +    }
> +    temp = mapped;
> +    if (ret >= 0) {
> +        for (i = 0;i < plane_num;i++) {
> +            memcpy(dst_data[i], temp, plane_size[i]);
> +            temp += plane_size[i];
> +        }
> +    }
> +    status = clEnqueueUnmapMemObject(gpu_env.command_queue, src_cl_buf, mapped, 0, NULL, NULL);
> +    if (status != CL_SUCCESS) {
> +        av_log(&openclutils, AV_LOG_ERROR, "Could not unmap OpenCL buffer: %s\n", opencl_errstr(status));
> +        return AVERROR_EXTERNAL;
> +    }
> +    return 0;
> +}
> +
> diff --git a/libavutil/opencl.h b/libavutil/opencl.h
> new file mode 100644
> index 0000000..5fa835f
> --- /dev/null
> +++ b/libavutil/opencl.h
[...]
> +/**
> + *  Create OpenCL buffer, the buffer is used to save the data which is used or created by OpenCL kernel.
> + *
> + * @param cl_buf         the pointer of OpenCL buffer, call av_opencl_buffer_release to release the buffer.
> + * @param cl_buf_size  size in bytes of the OpenCL buffer to create
> + * @param flags           the flags which used to control buffer attribute

flags used to control buffer attributes

> + * @param host_ptr      the host pointer of OpenCL buffer
> + * @return  >=0 on success, a negative error code in case of failure
> + */
> +int av_opencl_buffer_create(cl_mem *cl_buf, size_t cl_buf_size, int flags, void *host_ptr);
> +

> +/**
> + * Read data from OpenCL buffer to memory buffer.
> + *
> + * @param src_buf           pointer to destination buffer (CPU memory)
> + * @param dst_cl_buf        pointer to source OpenCL buffer
> + * @param buf_size          size in bytes of the source and destination buffers
> + * @return >=0 on success, a negative error code in case of failure
> + */
> +int av_opencl_buffer_write(cl_mem dst_cl_buf, uint8_t *src_buf, size_t buf_size);

Inconsisent documentation and mismatch between documentation and
implementation, the current documentation is backward.

It should be something like:
/**
 * Write OpenCL buffer with data from src_buf.
 *
 * @param dst_cl_buf        pointer to OpenCL destination buffer
 * @param src_buf           pointer to source buffer
 * @param buf_size          size in bytes of the source and destination buffers
 * @return >=0 on success, a negative error code in case of failure
 */
int av_opencl_buffer_write(cl_mem dst_cl_buf, uint8_t *src_buf, size_t buf_size);

> +
> +/**
> + * Read data from OpenCL buffer to memory buffer.
> + *
> + * @param dst_buf           pointer to destination buffer (CPU memory)
> + * @param src_cl_buf        pointer to source OpenCL buffer
> + * @param buf_size          size in bytes of the source and destination buffers
> + * @return >=0 on success, a negative error code in case of failure
> + */
> +int av_opencl_buffer_read(uint8_t *dst_buf, cl_mem src_cl_buf, size_t buf_size);
> +

> +/**
> + *  Write data from memory to OpenCL buffer. Src is frames buffer(data[0],data[1]...), dst is OpenCL buffer.
> + *
> + * @param dst_cl_buf                the pointer of destination buffer (GPU memory).
> + * @param cl_buffer_size           size in bytes of OpenCL buffer

> + * @param src_data                        picture or audio data for each plane

why do you mention audio data if the function is about image data?

Unless you want to generalize the function, in that case it could be
named:
av_opencl_buffer_write_frame()

Also in that case you should drop the limitation to 8 planes, since
audio data can contain an arbitrary number of channels (and thus
planes, in case of planar audio).

> + * @param plane_size                size in bytes of each plane
> + * @param plane_num               the input plane number, the value of this parameter should be 1 to 8
> + * @param offset                      the offset of OpenCL buffer start position
> + * @return  >=0 on success,  a negative error code in case of failure
> + */
> +int av_opencl_buffer_write_image(cl_mem dst_cl_buf, size_t cl_buffer_size,
> +                                        uint8_t **src_data, int *plane_size, int plane_num, int offset);

/**
 * Write image data from memory to OpenCL buffer.
 *
 * The source must be an array of pointers to image plane buffers.
 *
 * @param dst_cl_buf         pointer to destination OpenCL buffer
 * @param dst_cl_buf_size    size in bytes of OpenCL buffer
 * @param src_data           array of pointers to source plane buffers
 * @param src_plane_sizes    array of sizes in bytes of the source plane buffers
 * @param src_plane_num      number of source image planes
 * @param dst_cl_buf_offset  the offset of the OpenCL buffer start position
 * @return >=0 on success, a negative error code in case of failure
 */
int av_opencl_buffer_write_image(cl_mem dst_cl_buf, size_t dst_cl_buf_size,
                                 uint8_t **src_data, int *src_plane_size, int src_plane_num, int dst_cl_offset);

dst_cl_offset could be moved just after the other dst_ parameters.

> +
> +/**
> + *  Read frame data from OpenCL buffer to frame buffer, src buffer is OpenCL buffer, dst buffer is frame buffer(data[0],data[1]....).
> + *
> + * @param dst_data                    picture or audio data for each plane
> + * @param plane_size                 size in bytes of each plane
> + * @param plane_num                 the input plane number, the value of this parameter should be 1 to 8
> + * @param src_cl_inbuf                the pointer of OpenCL buffer.
> + * @param cl_buffer_size             size in bytes of OpenCL buffer
> + * @return  >=0 on success, a negative error code in case of failure
> + */
> +int av_opencl_buffer_read_image(uint8_t **dst_data, int *plane_size, int plane_num,
> +                                       cl_mem src_cl_buf, size_t cl_buffer_size);

/**
 * Read image data from OpenCL buffer.
 *
 * src buffer is OpenCL buffer, dst buffer is frame buffer(data[0],data[1]....).
 *
 * @param dst_data           array of pointers to destination plane buffers
 * @param dst_plane_sizes    array of pointers to destination plane buffers
 * @param dst_plane_num      number of destination image planes
 * @param src_cl_buf         pointer to source OpenCL buffer
 * @param src_cl_buf_size    size in bytes of OpenCL buffer
 * @return >=0 on success, a negative error code in case of failure
 */
int av_opencl_buffer_read_image(uint8_t **dst_data, int *dst_plane_sizes, int plane_num,
                                cl_mem src_cl_buf, size_t src_cl_buf_size);

> +/**
> + *  Release OpenCL buffer.
> + *
> + * @param cl_buf      the OpenCL buffer need to be released, this buffer is created in function av_opencl_buffer_create
> + */
> +void av_opencl_buffer_release(cl_mem cl_buf);

/**
 * Release OpenCL buffer.
 *
 * @param cl_buf  OpenCL buffer to release, which was previously filled with av_opencl_buffer_create()
 */
void av_opencl_buffer_release(cl_mem cl_buf);

[...]
-- 
FFmpeg = Frenzy & Friendly Minimal Perfectionist Exploitable Gargoyle


More information about the ffmpeg-devel mailing list