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