1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * GStreamer
3*4882a593Smuzhiyun * Copyright (C) 2016 Igalia
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Authors:
6*4882a593Smuzhiyun * Víctor Manuel Jáquez Leal <vjaquez@igalia.com>
7*4882a593Smuzhiyun * Javier Martin <javiermartin@by.com.es>
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * This library is free software; you can redistribute it and/or
10*4882a593Smuzhiyun * modify it under the terms of the GNU Library General Public
11*4882a593Smuzhiyun * License as published by the Free Software Foundation; either
12*4882a593Smuzhiyun * version 2 of the License, or (at your option) any later version.
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * This library is distributed in the hope that it will be useful,
15*4882a593Smuzhiyun * but WITHOUT ANY WARRANTY; without even the implied warranty of
16*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17*4882a593Smuzhiyun * Library General Public License for more details.
18*4882a593Smuzhiyun *
19*4882a593Smuzhiyun * You should have received a copy of the GNU Library General Public
20*4882a593Smuzhiyun * License along with this library; if not, write to the
21*4882a593Smuzhiyun * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
22*4882a593Smuzhiyun * Boston, MA 02110-1301, USA.
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun */
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #ifdef HAVE_CONFIG_H
27*4882a593Smuzhiyun #include "config.h"
28*4882a593Smuzhiyun #endif
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #include <gst/video/gstvideometa.h>
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #include "gstkmsbufferpool.h"
33*4882a593Smuzhiyun #include "gstkmsallocator.h"
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun GST_DEBUG_CATEGORY_STATIC (gst_kms_buffer_pool_debug);
36*4882a593Smuzhiyun #define GST_CAT_DEFAULT gst_kms_buffer_pool_debug
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun struct _GstKMSBufferPoolPrivate
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun GstVideoInfo vinfo;
41*4882a593Smuzhiyun GstAllocator *allocator;
42*4882a593Smuzhiyun gboolean add_videometa;
43*4882a593Smuzhiyun gboolean has_prime_export;
44*4882a593Smuzhiyun };
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #define parent_class gst_kms_buffer_pool_parent_class
47*4882a593Smuzhiyun G_DEFINE_TYPE_WITH_CODE (GstKMSBufferPool, gst_kms_buffer_pool,
48*4882a593Smuzhiyun GST_TYPE_VIDEO_BUFFER_POOL, G_ADD_PRIVATE (GstKMSBufferPool);
49*4882a593Smuzhiyun GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "kmsbufferpool", 0,
50*4882a593Smuzhiyun "KMS buffer pool"));
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun static const gchar **
gst_kms_buffer_pool_get_options(GstBufferPool * pool)53*4882a593Smuzhiyun gst_kms_buffer_pool_get_options (GstBufferPool * pool)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun static const gchar *options[] = { GST_BUFFER_POOL_OPTION_VIDEO_META,
56*4882a593Smuzhiyun GST_BUFFER_POOL_OPTION_KMS_BUFFER,
57*4882a593Smuzhiyun GST_BUFFER_POOL_OPTION_KMS_PRIME_EXPORT,
58*4882a593Smuzhiyun NULL
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun return options;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun static gboolean
gst_kms_buffer_pool_set_config(GstBufferPool * pool,GstStructure * config)64*4882a593Smuzhiyun gst_kms_buffer_pool_set_config (GstBufferPool * pool, GstStructure * config)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun GstKMSBufferPool *vpool;
67*4882a593Smuzhiyun GstKMSBufferPoolPrivate *priv;
68*4882a593Smuzhiyun GstCaps *caps;
69*4882a593Smuzhiyun GstVideoInfo vinfo;
70*4882a593Smuzhiyun GstAllocator *allocator;
71*4882a593Smuzhiyun GstAllocationParams params;
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun vpool = GST_KMS_BUFFER_POOL_CAST (pool);
74*4882a593Smuzhiyun priv = vpool->priv;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun if (!gst_buffer_pool_config_get_params (config, &caps, NULL, NULL, NULL))
77*4882a593Smuzhiyun goto wrong_config;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun if (!caps)
80*4882a593Smuzhiyun goto no_caps;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /* now parse the caps from the config */
83*4882a593Smuzhiyun if (!gst_video_info_from_caps (&vinfo, caps))
84*4882a593Smuzhiyun goto wrong_caps;
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun allocator = NULL;
87*4882a593Smuzhiyun gst_buffer_pool_config_get_allocator (config, &allocator, ¶ms);
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun /* not our allocator, not our buffers */
90*4882a593Smuzhiyun if (allocator && GST_IS_KMS_ALLOCATOR (allocator)) {
91*4882a593Smuzhiyun if (priv->allocator)
92*4882a593Smuzhiyun gst_object_unref (priv->allocator);
93*4882a593Smuzhiyun priv->allocator = gst_object_ref (allocator);
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun if (!priv->allocator)
96*4882a593Smuzhiyun goto no_allocator;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun priv->vinfo = vinfo;
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun /* enable metadata based on config of the pool */
101*4882a593Smuzhiyun priv->add_videometa = gst_buffer_pool_config_has_option (config,
102*4882a593Smuzhiyun GST_BUFFER_POOL_OPTION_VIDEO_META);
103*4882a593Smuzhiyun priv->has_prime_export = gst_buffer_pool_config_has_option (config,
104*4882a593Smuzhiyun GST_BUFFER_POOL_OPTION_KMS_PRIME_EXPORT);
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun return GST_BUFFER_POOL_CLASS (parent_class)->set_config (pool, config);
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun /* ERRORS */
109*4882a593Smuzhiyun wrong_config:
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun GST_WARNING_OBJECT (pool, "invalid config");
112*4882a593Smuzhiyun return FALSE;
113*4882a593Smuzhiyun }
114*4882a593Smuzhiyun no_caps:
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun GST_WARNING_OBJECT (pool, "no caps in config");
117*4882a593Smuzhiyun return FALSE;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun wrong_caps:
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun GST_WARNING_OBJECT (pool,
122*4882a593Smuzhiyun "failed getting geometry from caps %" GST_PTR_FORMAT, caps);
123*4882a593Smuzhiyun return FALSE;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun no_allocator:
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun GST_WARNING_OBJECT (pool, "no valid allocator in pool");
128*4882a593Smuzhiyun return FALSE;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun static GstFlowReturn
gst_kms_buffer_pool_alloc_buffer(GstBufferPool * pool,GstBuffer ** buffer,GstBufferPoolAcquireParams * params)133*4882a593Smuzhiyun gst_kms_buffer_pool_alloc_buffer (GstBufferPool * pool, GstBuffer ** buffer,
134*4882a593Smuzhiyun GstBufferPoolAcquireParams * params)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun GstKMSBufferPool *vpool;
137*4882a593Smuzhiyun GstKMSBufferPoolPrivate *priv;
138*4882a593Smuzhiyun GstVideoInfo *info;
139*4882a593Smuzhiyun GstMemory *mem;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun vpool = GST_KMS_BUFFER_POOL_CAST (pool);
142*4882a593Smuzhiyun priv = vpool->priv;
143*4882a593Smuzhiyun info = &priv->vinfo;
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun mem = gst_kms_allocator_bo_alloc (priv->allocator, info);
146*4882a593Smuzhiyun if (!mem)
147*4882a593Smuzhiyun goto no_memory;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun if (vpool->priv->has_prime_export) {
150*4882a593Smuzhiyun GstMemory *dmabufmem;
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun dmabufmem = gst_kms_allocator_dmabuf_export (priv->allocator, mem);
153*4882a593Smuzhiyun if (dmabufmem)
154*4882a593Smuzhiyun mem = dmabufmem;
155*4882a593Smuzhiyun else
156*4882a593Smuzhiyun GST_WARNING_OBJECT (pool, "Failed to export DMABuf from Dumb buffer.");
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun *buffer = gst_buffer_new ();
160*4882a593Smuzhiyun gst_buffer_append_memory (*buffer, mem);
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun if (priv->add_videometa) {
163*4882a593Smuzhiyun GST_DEBUG_OBJECT (pool, "adding GstVideoMeta");
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun gst_buffer_add_video_meta_full (*buffer, GST_VIDEO_FRAME_FLAG_NONE,
166*4882a593Smuzhiyun GST_VIDEO_INFO_FORMAT (info),
167*4882a593Smuzhiyun GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info),
168*4882a593Smuzhiyun GST_VIDEO_INFO_N_PLANES (info), info->offset, info->stride);
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun return GST_FLOW_OK;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun /* ERROR */
174*4882a593Smuzhiyun no_memory:
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun GST_WARNING_OBJECT (pool, "can't create memory");
177*4882a593Smuzhiyun return GST_FLOW_ERROR;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun static void
gst_kms_buffer_pool_finalize(GObject * object)182*4882a593Smuzhiyun gst_kms_buffer_pool_finalize (GObject * object)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun GstKMSBufferPool *pool;
185*4882a593Smuzhiyun GstKMSBufferPoolPrivate *priv;
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun pool = GST_KMS_BUFFER_POOL (object);
188*4882a593Smuzhiyun priv = pool->priv;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun if (priv->allocator)
191*4882a593Smuzhiyun gst_object_unref (priv->allocator);
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun G_OBJECT_CLASS (parent_class)->finalize (object);
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun static void
gst_kms_buffer_pool_init(GstKMSBufferPool * pool)197*4882a593Smuzhiyun gst_kms_buffer_pool_init (GstKMSBufferPool * pool)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun pool->priv = gst_kms_buffer_pool_get_instance_private (pool);
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun static void
gst_kms_buffer_pool_class_init(GstKMSBufferPoolClass * klass)203*4882a593Smuzhiyun gst_kms_buffer_pool_class_init (GstKMSBufferPoolClass * klass)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun GObjectClass *gobject_class;
206*4882a593Smuzhiyun GstBufferPoolClass *gstbufferpool_class;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun gobject_class = (GObjectClass *) klass;
209*4882a593Smuzhiyun gstbufferpool_class = (GstBufferPoolClass *) klass;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun gobject_class->finalize = gst_kms_buffer_pool_finalize;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun gstbufferpool_class->get_options = gst_kms_buffer_pool_get_options;
214*4882a593Smuzhiyun gstbufferpool_class->set_config = gst_kms_buffer_pool_set_config;
215*4882a593Smuzhiyun gstbufferpool_class->alloc_buffer = gst_kms_buffer_pool_alloc_buffer;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun GstBufferPool *
gst_kms_buffer_pool_new(void)219*4882a593Smuzhiyun gst_kms_buffer_pool_new (void)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun GstBufferPool *pool;
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun pool = g_object_new (GST_TYPE_KMS_BUFFER_POOL, NULL);
224*4882a593Smuzhiyun gst_object_ref_sink (pool);
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun return pool;
227*4882a593Smuzhiyun }
228