1 /* GStreamer
2 * Copyright (C) <2019> Seungha Yang <seungha.yang@navercorp.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 /**
21 * element-cudaupload:
22 *
23 * Uploads data to NVIDA GPU via CUDA APIs
24 *
25 * Since: 1.20
26 */
27
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
31
32 #include "gstcudaupload.h"
33
34 GST_DEBUG_CATEGORY_STATIC (gst_cuda_upload_debug);
35 #define GST_CAT_DEFAULT gst_cuda_upload_debug
36
37 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
38 GST_PAD_SINK,
39 GST_PAD_ALWAYS,
40 GST_STATIC_CAPS ("video/x-raw; video/x-raw("
41 GST_CAPS_FEATURE_MEMORY_CUDA_MEMORY ")"));
42
43 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
44 GST_PAD_SRC,
45 GST_PAD_ALWAYS,
46 GST_STATIC_CAPS ("video/x-raw(" GST_CAPS_FEATURE_MEMORY_CUDA_MEMORY ")"));
47
48 G_DEFINE_TYPE (GstCudaUpload, gst_cuda_upload, GST_TYPE_CUDA_BASE_TRANSFORM);
49
50 static GstCaps *gst_cuda_upload_transform_caps (GstBaseTransform * trans,
51 GstPadDirection direction, GstCaps * caps, GstCaps * filter);
52
53 static void
gst_cuda_upload_class_init(GstCudaUploadClass * klass)54 gst_cuda_upload_class_init (GstCudaUploadClass * klass)
55 {
56 GstElementClass *element_class;
57 GstBaseTransformClass *trans_class;
58
59 element_class = GST_ELEMENT_CLASS (klass);
60 trans_class = GST_BASE_TRANSFORM_CLASS (klass);
61
62 gst_element_class_add_static_pad_template (element_class, &sink_template);
63 gst_element_class_add_static_pad_template (element_class, &src_template);
64
65 gst_element_class_set_static_metadata (element_class,
66 "CUDA uploader", "Filter/Video",
67 "Uploads data into NVIDA GPU via CUDA APIs",
68 "Seungha Yang <seungha.yang@navercorp.com>");
69
70 trans_class->passthrough_on_same_caps = TRUE;
71
72 trans_class->transform_caps =
73 GST_DEBUG_FUNCPTR (gst_cuda_upload_transform_caps);
74
75 gst_type_mark_as_plugin_api (GST_TYPE_CUDA_BASE_TRANSFORM, 0);
76 GST_DEBUG_CATEGORY_INIT (gst_cuda_upload_debug,
77 "cudaupload", 0, "cudaupload Element");
78 }
79
80 static void
gst_cuda_upload_init(GstCudaUpload * upload)81 gst_cuda_upload_init (GstCudaUpload * upload)
82 {
83 }
84
85 static GstCaps *
_set_caps_features(const GstCaps * caps,const gchar * feature_name)86 _set_caps_features (const GstCaps * caps, const gchar * feature_name)
87 {
88 GstCaps *tmp = gst_caps_copy (caps);
89 guint n = gst_caps_get_size (tmp);
90 guint i = 0;
91
92 for (i = 0; i < n; i++)
93 gst_caps_set_features (tmp, i,
94 gst_caps_features_from_string (feature_name));
95
96 return tmp;
97 }
98
99 static GstCaps *
gst_cuda_upload_transform_caps(GstBaseTransform * trans,GstPadDirection direction,GstCaps * caps,GstCaps * filter)100 gst_cuda_upload_transform_caps (GstBaseTransform * trans,
101 GstPadDirection direction, GstCaps * caps, GstCaps * filter)
102 {
103 GstCaps *result, *tmp;
104
105 GST_DEBUG_OBJECT (trans,
106 "Transforming caps %" GST_PTR_FORMAT " in direction %s", caps,
107 (direction == GST_PAD_SINK) ? "sink" : "src");
108
109 if (direction == GST_PAD_SINK) {
110 tmp = _set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_CUDA_MEMORY);
111 tmp = gst_caps_merge (gst_caps_ref (caps), tmp);
112 } else {
113 GstCaps *newcaps;
114 tmp = gst_caps_ref (caps);
115
116 newcaps = _set_caps_features (caps, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
117 tmp = gst_caps_merge (tmp, newcaps);
118 }
119
120 if (filter) {
121 result = gst_caps_intersect_full (filter, tmp, GST_CAPS_INTERSECT_FIRST);
122 gst_caps_unref (tmp);
123 } else {
124 result = tmp;
125 }
126
127 GST_DEBUG_OBJECT (trans, "returning caps: %" GST_PTR_FORMAT, result);
128
129 return result;
130 }
131