1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
From 58d8ea72ec78cb17cf75c82c67a69e9bd383c3b3 Mon Sep 17 00:00:00 2001
From: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
Date: Thu, 1 Sep 2016 20:09:03 +0300
Subject: [PATCH 10/10] omxvideodec: support creating buffers using sink
Used for zero-copy output to wayland/weston
Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
---
omx/gstomxbufferpool.c | 107 +++++++++++++++++++++++++++++++++++++++++++++---
omx/gstomxvideodec.c | 11 ++++-
2 files changed, 111 insertions(+), 7 deletions(-)
diff --git a/omx/gstomxbufferpool.c b/omx/gstomxbufferpool.c
index eb2fe9d..60b25ef 100644
--- a/omx/gstomxbufferpool.c
+++ b/omx/gstomxbufferpool.c
@@ -372,6 +372,73 @@ GstOMXBuffer *gst_omx_buffer_get_omxbuffer (GstBuffer * buffer)
return omx_buf;
}
+#ifdef HAVE_MMNGRBUF
+static GstBuffer *
+gst_omx_buffer_pool_request_videosink_buffer_creation (GstOMXBufferPool * pool,
+ gint dmabuf_fd[GST_VIDEO_MAX_PLANES], gpointer plane_buf[GST_VIDEO_MAX_PLANES], gint stride[GST_VIDEO_MAX_PLANES])
+{
+ GstQuery *query;
+ GValue val = { 0, };
+ GstStructure *structure;
+ const GValue *value;
+ GstBuffer *buffer;
+ GArray *dmabuf_array;
+ GArray *stride_array;
+ GArray *planebuf_array;
+ gint n_planes;
+ gint i;
+
+ g_value_init (&val, G_TYPE_POINTER);
+ g_value_set_pointer (&val, (gpointer) pool->allocator);
+
+ dmabuf_array = g_array_new (FALSE, FALSE, sizeof (gint));
+ stride_array = g_array_new (FALSE, FALSE, sizeof (gint));
+ planebuf_array = g_array_new (FALSE, FALSE, sizeof (gpointer));
+
+ n_planes = GST_VIDEO_INFO_N_PLANES (&pool->video_info);
+ for (i = 0; i < n_planes; i++) {
+ g_array_append_val (dmabuf_array, dmabuf_fd[i]);
+ g_array_append_val (stride_array, stride[i]);
+ g_array_append_val (planebuf_array, plane_buf[i]);
+ }
+
+ structure = gst_structure_new ("videosink_buffer_creation_request",
+ "width", G_TYPE_INT, pool->port->port_def.format.video.nFrameWidth,
+ "height", G_TYPE_INT, pool->port->port_def.format.video.nFrameHeight,
+ "stride", G_TYPE_ARRAY, stride_array,
+ "dmabuf", G_TYPE_ARRAY, dmabuf_array,
+ "planebuf", G_TYPE_ARRAY, planebuf_array,
+ "allocator", G_TYPE_POINTER, &val,
+ "format", G_TYPE_STRING,
+ gst_video_format_to_string (pool->video_info.finfo->format),
+ "n_planes", G_TYPE_INT, n_planes, NULL);
+
+ query = gst_query_new_custom (GST_QUERY_CUSTOM, structure);
+
+ GST_DEBUG_OBJECT (pool, "send a videosink_buffer_creation_request query");
+
+ if (!gst_pad_peer_query (GST_VIDEO_DECODER_SRC_PAD (pool->element), query)) {
+ GST_ERROR_OBJECT (pool, "videosink_buffer_creation_request query failed");
+ return NULL;
+ }
+
+ value = gst_structure_get_value (structure, "buffer");
+ buffer = gst_value_get_buffer (value);
+ if (buffer == NULL) {
+ GST_ERROR_OBJECT (pool,
+ "could not get a buffer from videosink_buffer_creation query");
+ return NULL;
+ }
+
+ gst_query_unref (query);
+
+ g_array_free (dmabuf_array, TRUE);
+ g_array_free (stride_array, TRUE);
+
+ return buffer;
+}
+#endif
+
#if defined (HAVE_MMNGRBUF) && defined (HAVE_VIDEODEC_EXT)
static gboolean
gst_omx_buffer_pool_export_dmabuf (GstOMXBufferPool * pool,
@@ -406,6 +473,7 @@ gst_omx_buffer_pool_create_buffer_contain_dmabuf (GstOMXBufferPool * self,
gint plane_size_ext[GST_VIDEO_MAX_PLANES];
gint dmabuf_id[GST_VIDEO_MAX_PLANES];
gint page_offset[GST_VIDEO_MAX_PLANES];
+ gint plane_buf[GST_VIDEO_MAX_PLANES];
GstBuffer *new_buf;
gint i;
gint page_size;
@@ -450,6 +518,7 @@ gst_omx_buffer_pool_create_buffer_contain_dmabuf (GstOMXBufferPool * self,
else
plane_size[i] = stride[i] *
GST_VIDEO_INFO_COMP_HEIGHT (&self->video_info, i);
+ plane_buf[i] = omx_buf->omx_buf->pBuffer + offset[i];
/* When downstream plugins do mapping from dmabuf fd it requires
* mapping from boundary page and size align for page size so
@@ -472,14 +541,40 @@ gst_omx_buffer_pool_create_buffer_contain_dmabuf (GstOMXBufferPool * self,
gst_buffer_append_memory (new_buf, mem);
}
- g_ptr_array_add (self->buffers, new_buf);
- gst_buffer_add_video_meta_full (new_buf, GST_VIDEO_FRAME_FLAG_NONE,
- GST_VIDEO_INFO_FORMAT (&self->video_info),
- GST_VIDEO_INFO_WIDTH (&self->video_info),
- GST_VIDEO_INFO_HEIGHT (&self->video_info),
- GST_VIDEO_INFO_N_PLANES (&self->video_info), offset, stride);
+ if (self->vsink_buf_req_supported) {
+ new_buf = gst_omx_buffer_pool_request_videosink_buffer_creation (self,
+ dmabuf_fd, plane_buf, stride);
+ if (!new_buf) {
+ GST_ERROR_OBJECT (self, "creating dmabuf using videosink failed");
+ goto err;
+ }
+ new_buf->pool = self;
+ } else {
+ new_buf = gst_buffer_new ();
+ for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&self->video_info); i++) {
+ GstMemory *mem;
+ /* Set offset's information */
+ mem = gst_dmabuf_allocator_alloc (self->allocator, dmabuf_fd[i],
+ plane_size_ext[i]);
+ mem->offset = page_offset[i];
+ mem->size = plane_size[i];
+ gst_buffer_append_memory (new_buf, mem);
+ }
+
+ gst_buffer_add_video_meta_full (new_buf, GST_VIDEO_FRAME_FLAG_NONE,
+ GST_VIDEO_INFO_FORMAT (&self->video_info),
+ GST_VIDEO_INFO_WIDTH (&self->video_info),
+ GST_VIDEO_INFO_HEIGHT (&self->video_info),
+ GST_VIDEO_INFO_N_PLANES (&self->video_info), offset, stride);
+ }
+ GST_ERROR_OBJECT (self, "got buffer %p from pool %p",
+ new_buf, new_buf->pool);
+ g_ptr_array_add (self->buffers, new_buf);
return new_buf;
+
+err:
+ return NULL;
}
#endif
diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c
index 25b6b30..44b706a 100644
--- a/omx/gstomxvideodec.c
+++ b/omx/gstomxvideodec.c
@@ -2350,6 +2350,8 @@ gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query)
&GST_OMX_BUFFER_POOL (self->out_port_pool)->vsink_buf_req_supported);
gst_object_unref (pool);
update_pool = TRUE;
+ GST_ERROR_OBJECT (self, "vsink_buf_req_supported %d",
+ GST_OMX_BUFFER_POOL (self->out_port_pool)->vsink_buf_req_supported);
}
/* Set pool parameters to our own configuration */
@@ -2372,7 +2374,14 @@ gst_omx_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query)
}
GST_OMX_BUFFER_POOL (self->out_port_pool)->allocating = TRUE;
- gst_buffer_pool_set_active (self->out_port_pool, TRUE);
+ /* This now allocates all the buffers */
+ if (!gst_buffer_pool_set_active (self->out_port_pool, TRUE)) {
+ GST_INFO_OBJECT (self, "Failed to activate internal pool");
+ gst_object_unref (self->out_port_pool);
+ self->out_port_pool = NULL;
+ } else {
+ GST_OMX_BUFFER_POOL (self->out_port_pool)->allocating = FALSE;
+ }
/* This video buffer pool created below will not be used, just setting to
* the gstvideodecoder class through a query, because it is
--
1.7.10.4
|