• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "gst_mem_pool_src.h"
17 #include <gst/video/video.h>
18 #include "media_errors.h"
19 #include "scope_guard.h"
20 
21 using namespace OHOS;
22 namespace {
23     constexpr int32_t DEFAULT_BUFFER_SIZE = 41920;
24     constexpr int32_t DEFAULT_BUFFER_NUM = 8;
25 }
26 
27 #define gst_mem_pool_src_parent_class parent_class
28 
29 GST_DEBUG_CATEGORY_STATIC(gst_mem_pool_src_debug_category);
30 #define GST_CAT_DEFAULT gst_mem_pool_src_debug_category
31 
32 struct _GstMemPoolSrcPrivate {
33     BufferAvailable buffer_available;
34     gboolean emit_signals;
35     gpointer user_data;
36     GDestroyNotify notify;
37 };
38 
39 enum {
40     /* signals */
41     SIGNAL_BUFFER_AVAILABLE,
42     /* actions */
43     SIGNAL_PULL_BUFFER,
44     SIGNAL_PUSH_BUFFER,
45     LAST_SIGNAL
46 };
47 
48 enum {
49     PROP_0,
50     PROP_CAPS,
51     PROP_EMIT_SIGNALS,
52     PROP_BUFFER_NUM,
53     PROP_BUFFER_SIZE,
54 };
55 
56 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(GstMemPoolSrc, gst_mem_pool_src, GST_TYPE_BASE_SRC);
57 
58 static guint gst_mem_pool_src_signals[LAST_SIGNAL] = { 0 };
59 static void gst_mem_pool_src_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
60 static void gst_mem_pool_src_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
61 static gboolean gst_mem_pool_src_query(GstBaseSrc *src, GstQuery *query);
62 static gboolean gst_mem_pool_src_is_seekable(GstBaseSrc *basesrc);
63 static gboolean gst_mem_pool_src_negotiate(GstBaseSrc *basesrc);
64 static void gst_mem_pool_src_dispose(GObject *object);
65 
gst_mem_pool_src_class_init(GstMemPoolSrcClass * klass)66 static void gst_mem_pool_src_class_init(GstMemPoolSrcClass *klass)
67 {
68     g_return_if_fail(klass != nullptr);
69     GObjectClass *gobject_class = reinterpret_cast<GObjectClass *>(klass);
70     GstBaseSrcClass *gstbasesrc_class = reinterpret_cast<GstBaseSrcClass *>(klass);
71     GST_DEBUG_CATEGORY_INIT(gst_mem_pool_src_debug_category, "mempoolsrc", 0, "mem pool src base class");
72     gobject_class->set_property = gst_mem_pool_src_set_property;
73     gobject_class->get_property = gst_mem_pool_src_get_property;
74     gobject_class->dispose = gst_mem_pool_src_dispose;
75 
76     g_object_class_install_property(gobject_class, PROP_BUFFER_SIZE,
77         g_param_spec_uint("buffer-size", "buffer size",
78             "buffer size", 0, G_MAXINT32, 0,
79             (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
80 
81     g_object_class_install_property(gobject_class, PROP_BUFFER_NUM,
82         g_param_spec_uint("buffer-num", "buffer num",
83             "buffer num", 0, G_MAXINT32, 0,
84             (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
85 
86     g_object_class_install_property(gobject_class, PROP_CAPS,
87         g_param_spec_boxed("caps", "Caps",
88             "The allowed caps for the src pad", GST_TYPE_CAPS,
89             (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
90 
91     g_object_class_install_property(gobject_class, PROP_EMIT_SIGNALS,
92         g_param_spec_boolean("emit-signals", "Emit signals",
93             "Emit new-preroll and new-sample signals", FALSE,
94             (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
95 
96     gst_mem_pool_src_signals[SIGNAL_BUFFER_AVAILABLE] =
97         g_signal_new("buffer-available", G_TYPE_FROM_CLASS(gobject_class), G_SIGNAL_RUN_LAST,
98             0, nullptr, nullptr, nullptr, GST_TYPE_FLOW_RETURN, 0, G_TYPE_NONE);
99 
100     gst_mem_pool_src_signals[SIGNAL_PULL_BUFFER] =
101         g_signal_new("pull-buffer", G_TYPE_FROM_CLASS(gobject_class),
102             static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
103             G_STRUCT_OFFSET(GstMemPoolSrcClass, pull_buffer), nullptr, nullptr, nullptr,
104             GST_TYPE_BUFFER, 0, G_TYPE_NONE);
105 
106     gst_mem_pool_src_signals[SIGNAL_PUSH_BUFFER] =
107         g_signal_new("push-buffer", G_TYPE_FROM_CLASS(gobject_class),
108             static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
109             G_STRUCT_OFFSET(GstMemPoolSrcClass, push_buffer), nullptr, nullptr, nullptr,
110             GST_TYPE_FLOW_RETURN, 1, GST_TYPE_BUFFER);
111 
112     gstbasesrc_class->is_seekable = gst_mem_pool_src_is_seekable;
113     gstbasesrc_class->query = gst_mem_pool_src_query;
114     gstbasesrc_class->negotiate = gst_mem_pool_src_negotiate;
115 }
116 
gst_mem_pool_src_init(GstMemPoolSrc * memsrc)117 static void gst_mem_pool_src_init(GstMemPoolSrc *memsrc)
118 {
119     g_return_if_fail(memsrc != nullptr);
120     auto priv = reinterpret_cast<GstMemPoolSrcPrivate *>(gst_mem_pool_src_get_instance_private(memsrc));
121     g_return_if_fail(priv != nullptr);
122     gst_base_src_set_format(GST_BASE_SRC(memsrc), GST_FORMAT_TIME);
123     gst_base_src_set_live(GST_BASE_SRC(memsrc), TRUE);
124     memsrc->buffer_size = DEFAULT_BUFFER_SIZE;
125     memsrc->buffer_num = DEFAULT_BUFFER_NUM;
126     memsrc->priv = priv;
127     priv->buffer_available = nullptr;
128     priv->user_data = nullptr;
129     priv->notify = nullptr;
130     priv->emit_signals = FALSE;
131 }
132 
gst_mem_pool_src_buffer_available(GstMemPoolSrc * memsrc)133 GstFlowReturn gst_mem_pool_src_buffer_available(GstMemPoolSrc *memsrc)
134 {
135     GST_DEBUG_OBJECT(memsrc, "Buffer available");
136     g_return_val_if_fail(memsrc != nullptr && memsrc->priv != nullptr, GST_FLOW_ERROR);
137     GstFlowReturn ret = GST_FLOW_OK;
138     auto priv = memsrc->priv;
139     gboolean emit = FALSE;
140     if (priv->buffer_available) {
141         ret = priv->buffer_available(memsrc, priv->user_data);
142     } else {
143         GST_OBJECT_LOCK(memsrc);
144         emit = priv->emit_signals;
145         GST_OBJECT_UNLOCK(memsrc);
146         if (emit) {
147             g_signal_emit(memsrc, gst_mem_pool_src_signals[SIGNAL_BUFFER_AVAILABLE], 0, &ret);
148         }
149     }
150     return ret;
151 }
152 
gst_mem_pool_src_negotiate(GstBaseSrc * basesrc)153 static gboolean gst_mem_pool_src_negotiate(GstBaseSrc *basesrc)
154 {
155     g_return_val_if_fail(basesrc != nullptr, FALSE);
156     GstMemPoolSrc *memsrc = GST_MEM_POOL_SRC(basesrc);
157     return gst_base_src_set_caps(basesrc, memsrc->caps);
158 }
159 
gst_mem_pool_src_set_caps(GstMemPoolSrc * memsrc,const GstCaps * caps)160 void gst_mem_pool_src_set_caps(GstMemPoolSrc *memsrc, const GstCaps *caps)
161 {
162     g_return_if_fail(memsrc != nullptr);
163     GST_DEBUG_OBJECT(memsrc, "Setting caps to %s", gst_caps_to_string(caps));
164     GST_OBJECT_LOCK(memsrc);
165     GstCaps *old_caps = memsrc->caps;
166     if (caps != nullptr) {
167         memsrc->caps = gst_caps_copy(caps);
168     } else {
169         memsrc->caps = nullptr;
170     }
171     if (old_caps != nullptr) {
172         gst_caps_unref(old_caps);
173     }
174     GST_OBJECT_UNLOCK(memsrc);
175 }
176 
gst_mem_pool_src_set_emit_signals(GstMemPoolSrc * memsrc,gboolean emit)177 void gst_mem_pool_src_set_emit_signals(GstMemPoolSrc *memsrc, gboolean emit)
178 {
179     g_return_if_fail(memsrc != nullptr && memsrc->priv != nullptr);
180     auto priv = memsrc->priv;
181     GST_OBJECT_LOCK(memsrc);
182     priv->emit_signals = emit;
183     GST_OBJECT_UNLOCK(memsrc);
184 }
185 
gst_mem_pool_src_set_buffer_size(GstMemPoolSrc * memsrc,guint size)186 void gst_mem_pool_src_set_buffer_size(GstMemPoolSrc *memsrc, guint size)
187 {
188     g_return_if_fail(memsrc != nullptr);
189     GST_OBJECT_LOCK(memsrc);
190     memsrc->buffer_size = size;
191     GST_OBJECT_UNLOCK(memsrc);
192 }
193 
gst_mem_pool_src_set_buffer_num(GstMemPoolSrc * memsrc,guint num)194 void gst_mem_pool_src_set_buffer_num(GstMemPoolSrc *memsrc, guint num)
195 {
196     g_return_if_fail(memsrc != nullptr);
197     GST_OBJECT_LOCK(memsrc);
198     memsrc->buffer_num = num;
199     GST_OBJECT_UNLOCK(memsrc);
200 }
201 
gst_mem_pool_src_is_seekable(GstBaseSrc * basesrc)202 static gboolean gst_mem_pool_src_is_seekable(GstBaseSrc *basesrc)
203 {
204     (void)basesrc;
205     return FALSE;
206 }
207 
gst_mem_pool_src_dispose(GObject * object)208 static void gst_mem_pool_src_dispose(GObject *object)
209 {
210     GstMemPoolSrc *memsrc = GST_MEM_POOL_SRC(object);
211     g_return_if_fail(memsrc != nullptr && memsrc->priv != nullptr);
212     auto priv = memsrc->priv;
213 
214     GST_OBJECT_LOCK(memsrc);
215     if (memsrc->caps) {
216         gst_caps_unref(memsrc->caps);
217         memsrc->caps = nullptr;
218     }
219     if (priv->notify) {
220         priv->notify(priv->user_data);
221     }
222     priv->user_data = nullptr;
223     priv->notify = nullptr;
224     GST_OBJECT_UNLOCK(memsrc);
225 
226     G_OBJECT_CLASS(parent_class)->dispose(object);
227 }
228 
gst_mem_pool_src_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)229 static void gst_mem_pool_src_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
230 {
231     GstMemPoolSrc *memsrc = GST_MEM_POOL_SRC(object);
232     g_return_if_fail(memsrc != nullptr);
233     (void)pspec;
234     switch (prop_id) {
235         case PROP_CAPS:
236             gst_mem_pool_src_set_caps(memsrc, gst_value_get_caps(value));
237             break;
238         case PROP_EMIT_SIGNALS:
239             gst_mem_pool_src_set_emit_signals(memsrc, g_value_get_boolean(value));
240             break;
241         case PROP_BUFFER_SIZE:
242             gst_mem_pool_src_set_buffer_size(memsrc, g_value_get_uint(value));
243             break;
244         case PROP_BUFFER_NUM:
245             gst_mem_pool_src_set_buffer_num(memsrc, g_value_get_uint(value));
246             break;
247         default:
248             break;
249     }
250 }
251 
gst_mem_pool_src_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)252 static void gst_mem_pool_src_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
253 {
254     GstMemPoolSrc *memsrc = GST_MEM_POOL_SRC(object);
255     g_return_if_fail(memsrc != nullptr);
256     g_return_if_fail(value != nullptr);
257     (void)pspec;
258     switch (prop_id) {
259         case PROP_BUFFER_SIZE:
260             g_value_set_uint(value, memsrc->buffer_size);
261             GST_DEBUG_OBJECT(object, "set buffer size: %u", memsrc->buffer_size);
262             break;
263         case PROP_BUFFER_NUM:
264             g_value_set_uint(value, memsrc->buffer_num);
265             GST_DEBUG_OBJECT(object, "set buffer num: %u", memsrc->buffer_num);
266             break;
267         default:
268             break;
269     }
270 }
271 
gst_mem_pool_src_query(GstBaseSrc * src,GstQuery * query)272 static gboolean gst_mem_pool_src_query(GstBaseSrc *src, GstQuery *query)
273 {
274     g_return_val_if_fail(src != nullptr, FALSE);
275     g_return_val_if_fail(query != nullptr, FALSE);
276     g_return_val_if_fail(GST_BASE_SRC_CLASS(parent_class) != nullptr, FALSE);
277     switch (GST_QUERY_TYPE(query)) {
278         case GST_QUERY_SCHEDULING: {
279             gst_query_set_scheduling(query, GST_SCHEDULING_FLAG_SEQUENTIAL, 1, -1, 0);
280             gst_query_add_scheduling_mode(query, GST_PAD_MODE_PUSH);
281             return TRUE;
282         }
283         default: {
284             return GST_BASE_SRC_CLASS(parent_class)->query(src, query);
285         }
286     }
287     return TRUE;
288 }
289 
gst_mem_pool_src_set_callback(GstMemPoolSrc * memsrc,BufferAvailable callback,gpointer user_data,GDestroyNotify notify)290 void gst_mem_pool_src_set_callback(GstMemPoolSrc *memsrc, BufferAvailable callback,
291     gpointer user_data, GDestroyNotify notify)
292 {
293     g_return_if_fail(memsrc != nullptr && memsrc->priv != nullptr);
294     auto priv = memsrc->priv;
295     GST_OBJECT_LOCK(memsrc);
296     priv->user_data = user_data;
297     priv->notify = notify;
298     priv->buffer_available = callback;
299     GST_OBJECT_UNLOCK(memsrc);
300 }
301 
302 
gst_mem_pool_src_pull_buffer(GstMemPoolSrc * memsrc)303 GstBuffer *gst_mem_pool_src_pull_buffer(GstMemPoolSrc *memsrc)
304 {
305     GST_DEBUG_OBJECT(memsrc, "Pull buffer");
306     g_return_val_if_fail(memsrc != nullptr, nullptr);
307     GstMemPoolSrcClass *memclass = GST_MEM_POOL_SRC_GET_CLASS(memsrc);
308 
309     g_return_val_if_fail(memclass != nullptr, nullptr);
310     if (memclass->pull_buffer) {
311         return memclass->pull_buffer(memsrc);
312     }
313     GST_ERROR_OBJECT(memsrc, "there is no pull buffer function");
314     return nullptr;
315 }
316 
gst_mem_pool_src_push_buffer(GstMemPoolSrc * memsrc,GstBuffer * buffer)317 GstFlowReturn gst_mem_pool_src_push_buffer(GstMemPoolSrc *memsrc, GstBuffer *buffer)
318 {
319     GST_DEBUG_OBJECT(memsrc, "Push buffer");
320     g_return_val_if_fail(memsrc != nullptr, GST_FLOW_ERROR);
321     GstMemPoolSrcClass *memclass = GST_MEM_POOL_SRC_GET_CLASS(memsrc);
322 
323     g_return_val_if_fail(memclass != nullptr, GST_FLOW_ERROR);
324     if (memclass->push_buffer) {
325         return memclass->push_buffer(memsrc, buffer);
326     }
327     GST_ERROR_OBJECT(memsrc, "there is no push buffer function");
328     return GST_FLOW_ERROR;
329 }