diff --git a/src/picture.c b/src/picture.c index 90688d2..6e744fc 100644 --- a/src/picture.c +++ b/src/picture.c @@ -147,8 +147,10 @@ VAStatus sunxi_cedrus_EndPicture(VADriverContextP ctx, VAContextID context) struct v4l2_plane plane[1]; struct v4l2_plane planes[2]; struct v4l2_ext_control ctrl; - struct v4l2_ext_controls extCtrls; + struct v4l2_ext_controls ctrls; + struct media_request_new media_request; object_config_p obj_config; + int request_fd; obj_context = CONTEXT(context); assert(obj_context); @@ -170,8 +172,17 @@ VAStatus sunxi_cedrus_EndPicture(VADriverContextP ctx, VAContextID context) * order the different RenderPicture will be called. */ + if(driver_data->request_fds[obj_surface->input_buf_index] < 0) { + assert(ioctl(driver_data->mem2mem_fd, VIDIOC_NEW_REQUEST, &media_request)==0); + driver_data->request_fds[obj_surface->input_buf_index] = media_request.fd; + } + + request_fd = driver_data->request_fds[obj_surface->input_buf_index]; + memset(plane, 0, sizeof(struct v4l2_plane)); memset(planes, 0, 2 * sizeof(struct v4l2_plane)); + memset(&ctrl, 0, sizeof(struct v4l2_ext_control)); + memset(&ctrls, 0, sizeof(struct v4l2_ext_control)); memset(&(out_buf), 0, sizeof(out_buf)); out_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; @@ -179,7 +190,6 @@ VAStatus sunxi_cedrus_EndPicture(VADriverContextP ctx, VAContextID context) out_buf.index = obj_surface->input_buf_index; out_buf.length = 1; out_buf.m.planes = plane; - out_buf.request = obj_surface->request; switch(obj_config->profile) { case VAProfileMPEG2Simple: @@ -212,25 +222,33 @@ VAStatus sunxi_cedrus_EndPicture(VADriverContextP ctx, VAContextID context) cap_buf.length = 2; cap_buf.m.planes = planes; - assert(ioctl(driver_data->mem2mem_fd, VIDIOC_QUERYBUF, &cap_buf)==0); + ctrls.controls = &ctrl; + ctrls.count = 1; + ctrls.request_fd = request_fd; - extCtrls.controls = &ctrl; - extCtrls.count = 1; - extCtrls.request = obj_surface->request; - assert(ioctl(driver_data->mem2mem_fd, VIDIOC_S_EXT_CTRLS, &extCtrls)==0); + assert(ioctl(driver_data->mem2mem_fd, VIDIOC_S_EXT_CTRLS, &ctrls)==0); + + out_buf.request_fd = request_fd; if(ioctl(driver_data->mem2mem_fd, VIDIOC_QBUF, &cap_buf)) { obj_surface->status = VASurfaceSkipped; sunxi_cedrus_msg("Error when queuing output: %s\n", strerror(errno)); + + ioctl(request_fd, MEDIA_REQUEST_IOC_REINIT, NULL); return VA_STATUS_ERROR_UNKNOWN; } + if(ioctl(driver_data->mem2mem_fd, VIDIOC_QBUF, &out_buf)) { obj_surface->status = VASurfaceSkipped; sunxi_cedrus_msg("Error when queuing input: %s\n", strerror(errno)); + ioctl(driver_data->mem2mem_fd, VIDIOC_DQBUF, &cap_buf); + ioctl(request_fd, MEDIA_REQUEST_IOC_REINIT, NULL); return VA_STATUS_ERROR_UNKNOWN; } + assert(ioctl(request_fd, MEDIA_REQUEST_IOC_SUBMIT, NULL)==0); + /* For now, assume that we are done with rendering right away */ obj_context->current_render_target = -1; diff --git a/src/sunxi_cedrus_drv_video.c b/src/sunxi_cedrus_drv_video.c index 5660677..497ebdd 100644 --- a/src/sunxi_cedrus_drv_video.c +++ b/src/sunxi_cedrus_drv_video.c @@ -187,6 +187,9 @@ VAStatus VA_DRIVER_INIT_FUNC(VADriverContextP ctx) driver_data->mem2mem_fd = open("/dev/video0", O_RDWR | O_NONBLOCK, 0); assert(driver_data->mem2mem_fd >= 0); + for (int i = 0; i < INPUT_BUFFERS_NB; i++) + driver_data->request_fds[i] = -1; + assert(ioctl(driver_data->mem2mem_fd, VIDIOC_QUERYCAP, &cap)==0); if (!(cap.capabilities & V4L2_CAP_VIDEO_M2M_MPLANE)) { diff --git a/src/sunxi_cedrus_drv_video.h b/src/sunxi_cedrus_drv_video.h index 4e5da2b..60b546b 100644 --- a/src/sunxi_cedrus_drv_video.h +++ b/src/sunxi_cedrus_drv_video.h @@ -28,6 +28,7 @@ #include #include "object_heap.h" +#include "context.h" #include @@ -54,6 +55,7 @@ struct sunxi_cedrus_driver_data { char *chroma_bufs[VIDEO_MAX_FRAME]; unsigned int num_dst_bufs; int mem2mem_fd; + int request_fds[INPUT_BUFFERS_NB]; }; #endif /* _SUNXI_CEDRUS_DRV_VIDEO_H_ */ diff --git a/src/surface.c b/src/surface.c index be114cb..ea234de 100644 --- a/src/surface.c +++ b/src/surface.c @@ -165,6 +165,8 @@ VAStatus sunxi_cedrus_SyncSurface(VADriverContextP ctx, struct v4l2_plane planes[2]; fd_set read_fds; struct timeval tv = {0, 300000}; + int request_fd; + int rc; memset(plane, 0, sizeof(struct v4l2_plane)); memset(planes, 0, 2 * sizeof(struct v4l2_plane)); @@ -172,11 +174,19 @@ VAStatus sunxi_cedrus_SyncSurface(VADriverContextP ctx, obj_surface = SURFACE(render_target); assert(obj_surface); + if(obj_surface->status == VASurfaceSkipped) + return VA_STATUS_ERROR_UNKNOWN; + + request_fd = driver_data->request_fds[obj_surface->input_buf_index]; + if(request_fd < 0) + return VA_STATUS_ERROR_UNKNOWN; + FD_ZERO(&read_fds); - FD_SET(driver_data->mem2mem_fd, &read_fds); - if(obj_surface->status != VASurfaceSkipped) - select(driver_data->mem2mem_fd + 1, &read_fds, NULL, NULL, &tv); - else + FD_SET(request_fd, &read_fds); + + rc = select(request_fd + 1, &read_fds, NULL, NULL, &tv); + // FIXME: Properly dispose of the buffers here? + if(rc < 0) return VA_STATUS_ERROR_UNKNOWN; memset(&(buf), 0, sizeof(buf)); @@ -205,6 +215,8 @@ VAStatus sunxi_cedrus_SyncSurface(VADriverContextP ctx, return VA_STATUS_ERROR_UNKNOWN; } + assert(ioctl(request_fd, MEDIA_REQUEST_IOC_REINIT, NULL)==0); + return VA_STATUS_SUCCESS; }