1 From ab3cf8044667bff4a9e2e5108c55dd198fa353be Mon Sep 17 00:00:00 2001
2 From: Damian Hobson-Garcia <dhobsong@igel.co.jp>
3 Date: Thu, 11 May 2017 12:05:56 +0900
4 Subject: [PATCH 3/4] gst-recorder: Use USERPTR instead of DMABUF for VSP
7 The RCar-Gen3 encoder requires buffers to be allocated and managed
8 externally when using dmabuf buffers. Since different sized buffers
9 are required for each output, the VSP cannot allocate these buffers
10 externally. The encoder provides its own buffers in USERPTR mode, so
13 src/gst-recorder.c | 100 +++++++++++++++++++++++++++++++++--------------------
14 1 file changed, 63 insertions(+), 37 deletions(-)
16 diff --git a/src/gst-recorder.c b/src/gst-recorder.c
17 index 2e3b359..271fb69 100644
18 --- a/src/gst-recorder.c
19 +++ b/src/gst-recorder.c
20 @@ -314,7 +314,7 @@ vsp_init(const char *devname)
21 weston_log("failed to open subdev '%s'\n", buf);
24 - else if ((vsp->output.fd = open(media_entity_get_devname(entity), O_RDWR | O_NONBLOCK)) < 0)
25 + else if ((vsp->output.fd = open(media_entity_get_devname(entity), O_RDWR )) < 0)
27 weston_log("failed to open device '%s'\n", media_entity_get_devname(entity));
29 @@ -467,7 +467,8 @@ vsp_request_buffers(vsp_data_t *vsp, vsp_port_n port, unsigned int num)
30 memset(&reqbuf, 0, sizeof(reqbuf));
31 reqbuf.type = (port == VSP_PORT_INPUT) ?
32 V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
33 - reqbuf.memory = V4L2_MEMORY_DMABUF;
34 + reqbuf.memory = (port == VSP_PORT_INPUT) ?
35 + V4L2_MEMORY_DMABUF : V4L2_MEMORY_USERPTR;
37 if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
38 weston_log("VSP: %s REQBUFS failed: %d\n",
39 @@ -539,7 +540,8 @@ vsp_input_buffer_dequeue_dmafd(vsp_data_t *vsp)
41 /* ...enqueue output buffer */
43 -vsp_output_buffer_queue_dmafd(vsp_data_t *vsp, int i, int dmafd[])
44 +vsp_output_buffer_queue_userptr(vsp_data_t *vsp, int i, void * omx_mem,
45 + int y_plane_size, int c_plane_size)
47 vsp_media_pad_t *pad = &vsp->output;
48 struct v4l2_plane planes[2];
49 @@ -549,16 +551,23 @@ vsp_output_buffer_queue_dmafd(vsp_data_t *vsp, int i, int dmafd[])
50 memset(&buf, 0, sizeof(buf));
51 memset(planes, 0, sizeof(planes));
52 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
53 - buf.memory = V4L2_MEMORY_DMABUF;
54 + buf.memory = V4L2_MEMORY_USERPTR;
56 buf.m.planes = planes;
57 buf.length = VSP_OUTPUT_BUFFERS_PLANE;
58 - buf.m.planes[0].m.fd = dmafd[0];
59 - buf.m.planes[1].m.fd = dmafd[1];
61 + buf.m.planes[0].m.userptr = (unsigned long) omx_mem;
62 + buf.m.planes[1].m.userptr = (unsigned long) omx_mem + y_plane_size;
64 + buf.m.planes[0].bytesused = y_plane_size;
65 + buf.m.planes[0].length = y_plane_size;
67 + buf.m.planes[1].bytesused = c_plane_size;
68 + buf.m.planes[1].length = c_plane_size;
70 /* ...submit buffer */
71 if (ioctl(pad->fd, VIDIOC_QBUF, &buf) < 0) {
72 - weston_log("VSP: output dmafd queue failed: %d\n", errno);
73 + weston_log("VSP: output buffer queue failed: %d\n", errno);
77 @@ -567,7 +576,7 @@ vsp_output_buffer_queue_dmafd(vsp_data_t *vsp, int i, int dmafd[])
79 /* ...dequeue output buffer */
81 -vsp_output_buffer_dequeue_dmafd(vsp_data_t *vsp)
82 +vsp_output_buffer_dequeue_userptr(vsp_data_t *vsp)
84 vsp_media_pad_t *pad = &vsp->output;
85 struct v4l2_buffer buf;
86 @@ -577,12 +586,12 @@ vsp_output_buffer_dequeue_dmafd(vsp_data_t *vsp)
87 memset(&buf, 0, sizeof(buf));
88 memset(planes, 0, sizeof(planes));
89 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
90 - buf.memory = V4L2_MEMORY_DMABUF;
91 + buf.memory = V4L2_MEMORY_USERPTR;
92 buf.m.planes = planes;
93 buf.length = VSP_OUTPUT_BUFFERS_PLANE;
95 if (ioctl(pad->fd, VIDIOC_DQBUF, &buf) < 0) {
96 - weston_log("VSP: output dmafd de-queue failed: %d\n", errno);
97 + weston_log("VSP: output buffer de-queue failed: %d\n", errno);
101 @@ -879,33 +888,25 @@ err:
105 -gst_recorder_omx_buffer_acquire(struct gst_recorder *r, GstBuffer **ret_buf, int fd[])
106 +gst_recorder_omx_buffer_acquire(struct gst_recorder *r, GstBuffer **ret_buf, GstMapInfo *info)
114 ret = gst_buffer_pool_acquire_buffer(r->omx_pool, &buf, NULL);
115 if (ret != GST_FLOW_OK) {
116 - weston_log("OMX buffer acquire failed\n");
118 + weston_log("GStreamer buffer acquire failed\n");
122 - n_mem = gst_buffer_n_memory(buf);
124 - weston_log("Buffer with no mem!\n");
125 + if (!gst_buffer_is_writable(buf)) {
126 + weston_log("GStreamer buffer not writable\n");
130 - for (i = 0; i < n_mem; i++) {
131 - mem = gst_buffer_peek_memory (buf, i);
132 - if (!gst_is_dmabuf_memory (mem)) {
133 - weston_log("Mem not dmabuf\n");
136 - fd[i] = gst_dmabuf_memory_get_fd (mem);
137 + if (!gst_buffer_map(buf, info, GST_MAP_WRITE)) {
138 + weston_log("Cannot map GStreamer buffer\n");
143 @@ -959,7 +960,7 @@ gst_recorder_create(struct gst_recorder_settings *settings)
147 - "omxh264enc target-bitrate=%d control-rate=2 name=my_encoder ! "
148 + "omxh264enc target-bitrate=%d control-rate=2 no-copy=true name=my_encoder ! "
149 "video/x-h264,width=%d,height=%d ! ",
150 r->set->bitrate, r->set->crop.width, r->set->crop.height);
152 @@ -1012,6 +1013,12 @@ gst_recorder_create(struct gst_recorder_settings *settings)
153 "framerate", GST_TYPE_FRACTION, 0, DEFAULT_FPS,
156 + g_object_set(G_OBJECT(r->appsrc),
158 + "format", GST_FORMAT_TIME,
162 r->appsrc_pad = gst_element_get_static_pad(GST_ELEMENT_CAST(r->appsrc), "src");
164 weston_log("Failed to get src0 pad of appsrc\n");
165 @@ -1088,14 +1095,23 @@ gst_recorder_process_dmafd(struct gst_recorder *r, int fd, int stride)
175 - if (gst_recorder_omx_buffer_acquire(r, &buf, omx_fd) < 0) {
176 + if (gst_recorder_omx_buffer_acquire(r, &buf, &info) < 0) {
177 weston_log("VSP: can not acquire GST buffer, dropping frame\n");
181 + ysize = r->set->crop.width * r->set->crop.height;
182 +#ifdef VSP_OUTPUT_NV16
188 pthread_mutex_lock(&r->vsp->mutex);
190 if (vsp_set_formats(r->vsp, r->set->width, r->set->height, &r->set->crop) < 0) {
191 @@ -1116,7 +1132,7 @@ gst_recorder_process_dmafd(struct gst_recorder *r, int fd, int stride)
194 /* queue output biffer */
195 - if (vsp_output_buffer_queue_dmafd(r->vsp, 0, omx_fd) < 0) {
196 + if (vsp_output_buffer_queue_userptr(r->vsp, 0, info.data, ysize, csize) < 0) {
197 weston_log("can not queue OMX buffer %d to VSP\n", 0);
198 gst_recorder_omx_buffer_release(r, buf);
200 @@ -1147,11 +1163,15 @@ gst_recorder_process_dmafd(struct gst_recorder *r, int fd, int stride)
204 - if (vsp_output_buffer_dequeue_dmafd(r->vsp) < 0) {
205 - weston_log("VSP: failed to dequeu output buffer\n");
206 + if (vsp_output_buffer_dequeue_userptr(r->vsp) < 0) {
207 + weston_log("VSP: failed to dequeue output buffer\n");
208 + gst_buffer_unmap(buf, &info);
209 gst_recorder_omx_buffer_release(r, buf);
213 + gst_buffer_unmap(buf, &info);
214 + gst_buffer_set_size(buf, ysize + csize);
217 gst_recorder_set_timestamp(r, buf);
219 @@ -1174,6 +1194,7 @@ gst_recorder_process_dmafd(struct gst_recorder *r, int fd, int stride)
220 vsp_request_buffers(r->vsp, VSP_PORT_OUTPUT, 0);
222 pthread_mutex_unlock(&r->vsp->mutex);
227 @@ -1181,6 +1202,7 @@ err_vsp:
228 /* finish vsp here */
230 pthread_mutex_unlock(&r->vsp->mutex);
235 @@ -1197,9 +1219,13 @@ gst_recorder_frame_dmafd(struct gst_recorder *r, int fd, int stride)
239 - /* The mutex is never released while encoding, so this point should
240 - * never be reached if input.valid is true. */
241 - assert(!r->input.valid);
242 + /* It is possible that the frame callback can be called mutiple
243 + * times before the worker thread wakes up. In this case
244 + * drop all buf the first frame */
245 + if(r->input.valid) {
250 r->input.prime_fd = fd;
251 r->input.stride = stride;
252 @@ -1209,5 +1235,5 @@ gst_recorder_frame_dmafd(struct gst_recorder *r, int fd, int stride)
254 pthread_mutex_unlock(&r->mutex);