6f8d1dc94e4ac77ae22f5eed6db6e3838c3d75d6
[AGL/meta-agl-demo.git] / recipes-graphics / wayland / weston / 0003-gst-recorder-Use-USERPTR-instead-of-DMABUF-for-VSP-o.patch
1 From f450d78f49ab55149b6b64251dd4c4f1ad04c9aa 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
5  output
6
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
11 switch to that.
12 ---
13  libweston/gst-recorder.c | 100 +++++++++++++++++++++++++++++------------------
14  1 file changed, 63 insertions(+), 37 deletions(-)
15
16 diff --git a/libweston/gst-recorder.c b/libweston/gst-recorder.c
17 index d46d4f0..d2cf8dc 100644
18 --- a/libweston/gst-recorder.c
19 +++ b/libweston/gst-recorder.c
20 @@ -311,7 +311,7 @@ vsp_init(const char *devname)
21                 weston_log("failed to open subdev '%s'\n", buf);
22                 goto error_media;
23         }
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)
26         {
27                 weston_log("failed to open device '%s'\n", media_entity_get_devname(entity));
28                 goto error_media;
29 @@ -464,7 +464,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;
36         reqbuf.count = num;
37         if (ioctl(fd, VIDIOC_REQBUFS, &reqbuf) < 0) {
38                 weston_log("VSP: %s REQBUFS failed: %d\n",
39 @@ -536,7 +537,8 @@ vsp_input_buffer_dequeue_dmafd(vsp_data_t *vsp)
40  
41  /* ...enqueue output buffer */
42  static int
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)
46  {
47         vsp_media_pad_t    *pad = &vsp->output;
48         struct v4l2_plane   planes[2];
49 @@ -546,16 +548,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;
55         buf.index = i;
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];
60 +
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;
63 +
64 +       buf.m.planes[0].bytesused = y_plane_size;
65 +       buf.m.planes[0].length = y_plane_size;
66 +
67 +       buf.m.planes[1].bytesused = c_plane_size;
68 +       buf.m.planes[1].length = c_plane_size;
69  
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);
74                 return -1;
75         }
76  
77 @@ -564,7 +573,7 @@ vsp_output_buffer_queue_dmafd(vsp_data_t *vsp, int i, int dmafd[])
78  
79  /* ...dequeue output buffer */
80  static int
81 -vsp_output_buffer_dequeue_dmafd(vsp_data_t *vsp)
82 +vsp_output_buffer_dequeue_userptr(vsp_data_t *vsp)
83  {
84         vsp_media_pad_t    *pad = &vsp->output;
85         struct v4l2_buffer  buf;
86 @@ -574,12 +583,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;
94  
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);
98                 return -1;
99         }
100  
101 @@ -876,33 +885,25 @@ err:
102  }
103  
104  static int
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)
107  {
108 -       unsigned int i;
109         GstFlowReturn ret;
110         GstBuffer *buf;
111 -       guint n_mem;
112 -       GstMemory *mem;
113  
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");
117 -               return -1;
118 +               weston_log("GStreamer buffer acquire failed\n");
119 +               goto err_release;
120         }
121  
122 -       n_mem = gst_buffer_n_memory(buf);
123 -       if (n_mem < 1) {
124 -               weston_log("Buffer with no mem!\n");
125 +       if (!gst_buffer_is_writable(buf)) {
126 +               weston_log("GStreamer buffer not writable\n");
127                 goto err_release;
128         }
129  
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");
134 -                       goto err_release;
135 -               }
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");
139 +               goto err_release;
140         }
141  
142         *ret_buf = buf;
143 @@ -956,7 +957,7 @@ gst_recorder_create(struct gst_recorder_settings *settings)
144  
145         /* omx */
146         ptr += sprintf(ptr,
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);
151  
152 @@ -1009,6 +1010,12 @@ gst_recorder_create(struct gst_recorder_settings *settings)
153                                         "framerate", GST_TYPE_FRACTION, 0, DEFAULT_FPS,
154                                         NULL), NULL);
155  
156 +       g_object_set(G_OBJECT(r->appsrc),
157 +                       "stream-type", 0,
158 +                       "format", GST_FORMAT_TIME,
159 +                       "is-live", TRUE,
160 +                       NULL);
161 +
162         r->appsrc_pad = gst_element_get_static_pad(GST_ELEMENT_CAST(r->appsrc), "src");
163         if (!r->appsrc_pad)
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)
166  {
167         int ret;
168         GstBuffer *buf;
169 -       int omx_fd[2];
170 +       GstMapInfo info;
171 +       int ysize;
172 +       int csize;
173  
174          /* get GST buffer */
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");
178                 return 0;
179         }
180  
181 +       ysize = r->set->crop.width * r->set->crop.height;
182 +#ifdef VSP_OUTPUT_NV16
183 +       csize = ysize;
184 +#else
185 +       csize = ysize / 2;
186 +#endif
187 +
188         pthread_mutex_lock(&r->vsp->mutex);
189         /* setup vsp */
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)
192         }
193  
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);
199                 goto err_vsp;
200 @@ -1147,11 +1163,15 @@ gst_recorder_process_dmafd(struct gst_recorder *r, int fd, int stride)
201         }
202  
203         /* dequeue output */
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);
210 -               /* fall through */
211         } else {
212 +
213 +               gst_buffer_unmap(buf, &info);
214 +               gst_buffer_set_size(buf, ysize + csize);
215 +
216                 /* set timestamp */
217                 gst_recorder_set_timestamp(r, buf);
218  
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);
221  
222         pthread_mutex_unlock(&r->vsp->mutex);
223 +       close(fd);
224         return 0;
225  
226  err_vsp:
227 @@ -1181,6 +1202,7 @@ err_vsp:
228         /* finish vsp here */
229  err:
230         pthread_mutex_unlock(&r->vsp->mutex);
231 +       close(fd);
232         return -1;
233  }
234  
235 @@ -1197,9 +1219,13 @@ gst_recorder_frame_dmafd(struct gst_recorder *r, int fd, int stride)
236                 goto unlock;
237         }
238                 
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) {
246 +               close(fd);
247 +               goto unlock;
248 +       }
249  
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)
253  unlock:
254         pthread_mutex_unlock(&r->mutex);
255  
256 -       return 0;
257 +       return ret;
258  }
259 -- 
260 2.9.2
261