diff --git a/src/buffer.c b/src/buffer.c index 2a65b07..1820db7 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -72,10 +72,12 @@ VAStatus sunxi_cedrus_CreateBuffer(VADriverContextP ctx, VAContextID context, return VA_STATUS_ERROR_ALLOCATION_FAILED; obj_buffer->buffer_data = NULL; + obj_buffer->buffer_map = NULL; obj_buffer->type = type; obj_buffer->max_num_elements = num_elements; obj_buffer->num_elements = num_elements; obj_buffer->size = size; + obj_buffer->map_size = 0; if(obj_buffer->type == VASliceDataBufferType) { object_context_p obj_context; @@ -93,13 +95,19 @@ VAStatus sunxi_cedrus_CreateBuffer(VADriverContextP ctx, VAContextID context, assert(ioctl(driver_data->mem2mem_fd, VIDIOC_QUERYBUF, &buf)==0); - obj_buffer->buffer_data = mmap(NULL, size * num_elements, + obj_buffer->map_size = driver_data->slice_offset[buf.index] + size * num_elements; + obj_buffer->buffer_map = mmap(NULL, obj_buffer->map_size, PROT_READ | PROT_WRITE, MAP_SHARED, driver_data->mem2mem_fd, buf.m.planes[0].m.mem_offset); - } else - obj_buffer->buffer_data = realloc(obj_buffer->buffer_data, size * num_elements); - if (obj_buffer->buffer_data == NULL) + obj_buffer->buffer_data = obj_buffer->buffer_map + driver_data->slice_offset[buf.index]; + driver_data->slice_offset[buf.index] += size * num_elements; + } else { + obj_buffer->buffer_map = NULL; + obj_buffer->buffer_data = malloc(size * num_elements); + } + + if (obj_buffer->buffer_data == NULL || obj_buffer->buffer_map == MAP_FAILED) return VA_STATUS_ERROR_ALLOCATION_FAILED; if (data) @@ -158,11 +166,12 @@ void sunxi_cedrus_destroy_buffer(struct sunxi_cedrus_driver_data *driver_data, object_buffer_p obj_buffer) { if (obj_buffer->buffer_data != NULL) { - if(obj_buffer->type == VASliceDataBufferType) - munmap(obj_buffer->buffer_data, obj_buffer->size); - else + if (obj_buffer->type != VASliceDataBufferType) free(obj_buffer->buffer_data); + else if (obj_buffer->buffer_map != NULL && obj_buffer->map_size > 0) + munmap(obj_buffer->buffer_map, obj_buffer->map_size); + obj_buffer->buffer_map = NULL; obj_buffer->buffer_data = NULL; } diff --git a/src/buffer.h b/src/buffer.h index e39c238..82438e1 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -37,10 +37,12 @@ struct object_buffer { struct object_base base; void *buffer_data; + void *buffer_map; int max_num_elements; int num_elements; VABufferType type; unsigned int size; + unsigned int map_size; }; typedef struct object_buffer *object_buffer_p; diff --git a/src/picture.c b/src/picture.c index e20ae01..19dc709 100644 --- a/src/picture.c +++ b/src/picture.c @@ -197,7 +197,10 @@ VAStatus sunxi_cedrus_EndPicture(VADriverContextP ctx, VAContextID context) switch(obj_config->profile) { case VAProfileMPEG2Simple: case VAProfileMPEG2Main: - out_buf.m.planes[0].bytesused = obj_context->mpeg2_frame_hdr.slice_len/8; + obj_context->mpeg2_frame_hdr.slice_pos = 0; + obj_context->mpeg2_frame_hdr.slice_len = driver_data->slice_offset[obj_surface->input_buf_index] * 8; + + out_buf.m.planes[0].bytesused = driver_data->slice_offset[obj_surface->input_buf_index]; ctrl.id = V4L2_CID_MPEG_VIDEO_MPEG2_FRAME_HDR; ctrl.ptr = &obj_context->mpeg2_frame_hdr; ctrl.size = sizeof(obj_context->mpeg2_frame_hdr); @@ -218,6 +221,8 @@ VAStatus sunxi_cedrus_EndPicture(VADriverContextP ctx, VAContextID context) break; } + driver_data->slice_offset[obj_surface->input_buf_index] = 0; + memset(&(cap_buf), 0, sizeof(cap_buf)); cap_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; cap_buf.memory = V4L2_MEMORY_MMAP; diff --git a/src/sunxi_cedrus_drv_video.c b/src/sunxi_cedrus_drv_video.c index 6be2b36..cc5ce20 100644 --- a/src/sunxi_cedrus_drv_video.c +++ b/src/sunxi_cedrus_drv_video.c @@ -185,8 +185,10 @@ 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++) + for (int i = 0; i < INPUT_BUFFERS_NB; i++) { driver_data->request_fds[i] = -1; + driver_data->slice_offset[i] = 0; + } 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 60b546b..f115bdf 100644 --- a/src/sunxi_cedrus_drv_video.h +++ b/src/sunxi_cedrus_drv_video.h @@ -56,6 +56,7 @@ struct sunxi_cedrus_driver_data { unsigned int num_dst_bufs; int mem2mem_fd; int request_fds[INPUT_BUFFERS_NB]; + int slice_offset[INPUT_BUFFERS_NB]; }; #endif /* _SUNXI_CEDRUS_DRV_VIDEO_H_ */