• 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_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_src_parent_class parent_class
28 
29 GST_DEBUG_CATEGORY_STATIC(gst_mem_src_debug_category);
30 #define GST_CAT_DEFAULT gst_mem_src_debug_category
31 
32 struct _GstMemSrcPrivate {
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(GstMemSrc, gst_mem_src, GST_TYPE_BASE_SRC);
57 
58 static guint gst_mem_src_signals[LAST_SIGNAL] = { 0 };
59 static void gst_mem_src_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
60 static void gst_mem_src_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
61 static gboolean gst_mem_src_query(GstBaseSrc *src, GstQuery *query);
62 static gboolean gst_mem_src_is_seekable(GstBaseSrc *basesrc);
63 static gboolean gst_mem_src_negotiate(GstBaseSrc *basesrc);
64 static void gst_mem_src_dispose(GObject *object);
65 
gst_mem_src_class_init(GstMemSrcClass * klass)66 static void gst_mem_src_class_init(GstMemSrcClass *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_src_debug_category, "memsrc", 0, "mem src base class");
72     gobject_class->set_property = gst_mem_src_set_property;
73     gobject_class->get_property = gst_mem_src_get_property;
74     gobject_class->dispose = gst_mem_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_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_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(GstMemSrcClass, pull_buffer), nullptr, nullptr, nullptr,
104             GST_TYPE_BUFFER, 0, G_TYPE_NONE);
105 
106     gst_mem_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(GstMemSrcClass, push_buffer), nullptr, nullptr, nullptr,
110             GST_TYPE_FLOW_RETURN, 1, GST_TYPE_BUFFER);
111 
112     gstbasesrc_class->is_seekable = gst_mem_src_is_seekable;
113     gstbasesrc_class->query = gst_mem_src_query;
114     gstbasesrc_class->negotiate = gst_mem_src_negotiate;
115 }
116 
gst_mem_src_init(GstMemSrc * memsrc)117 static void gst_mem_src_init(GstMemSrc *memsrc)
118 {
119     g_return_if_fail(memsrc != nullptr);
120     auto priv = reinterpret_cast<GstMemSrcPrivate *>(gst_mem_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_src_buffer_available(GstMemSrc * memsrc)133 GstFlowReturn gst_mem_src_buffer_available(GstMemSrc *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     if (priv->buffer_available) {
140         ret = priv->buffer_available(memsrc, priv->user_data);
141     } else {
142         GST_OBJECT_LOCK(memsrc);
143         gboolean emit = priv->emit_signals;
144         GST_OBJECT_UNLOCK(memsrc);
145         if (emit) {
146             g_signal_emit(memsrc, gst_mem_src_signals[SIGNAL_BUFFER_AVAILABLE], 0, &ret);
147         }
148     }
149     return ret;
150 }
151 
gst_mem_src_negotiate(GstBaseSrc * basesrc)152 static gboolean gst_mem_src_negotiate(GstBaseSrc *basesrc)
153 {
154     g_return_val_if_fail(basesrc != nullptr, FALSE);
155     GstMemSrc *memsrc = GST_MEM_SRC(basesrc);
156     return gst_base_src_set_caps(basesrc, memsrc->caps);
157 }
158 
gst_mem_src_set_caps(GstMemSrc * memsrc,const GstCaps * caps)159 void gst_mem_src_set_caps(GstMemSrc *memsrc, const GstCaps *caps)
160 {
161     g_return_if_fail(memsrc != nullptr);
162     GST_OBJECT_LOCK(memsrc);
163     GstCaps *old_caps = memsrc->caps;
164     if (caps != nullptr) {
165         memsrc->caps = gst_caps_copy(caps);
166     } else {
167         memsrc->caps = nullptr;
168     }
169     if (old_caps != nullptr) {
170         gst_caps_unref(old_caps);
171     }
172     GST_OBJECT_UNLOCK(memsrc);
173 }
174 
gst_mem_src_set_emit_signals(GstMemSrc * memsrc,gboolean emit)175 void gst_mem_src_set_emit_signals(GstMemSrc *memsrc, gboolean emit)
176 {
177     g_return_if_fail(memsrc != nullptr && memsrc->priv != nullptr);
178     auto priv = memsrc->priv;
179     GST_OBJECT_LOCK(memsrc);
180     priv->emit_signals = emit;
181     GST_OBJECT_UNLOCK(memsrc);
182 }
183 
gst_mem_src_set_buffer_size(GstMemSrc * memsrc,guint size)184 void gst_mem_src_set_buffer_size(GstMemSrc *memsrc, guint size)
185 {
186     g_return_if_fail(memsrc != nullptr);
187     GST_OBJECT_LOCK(memsrc);
188     memsrc->buffer_size = size;
189     GST_OBJECT_UNLOCK(memsrc);
190 }
191 
gst_mem_src_set_buffer_num(GstMemSrc * memsrc,guint num)192 void gst_mem_src_set_buffer_num(GstMemSrc *memsrc, guint num)
193 {
194     g_return_if_fail(memsrc != nullptr);
195     GST_OBJECT_LOCK(memsrc);
196     memsrc->buffer_num = num;
197     GST_OBJECT_UNLOCK(memsrc);
198 }
199 
gst_mem_src_is_seekable(GstBaseSrc * basesrc)200 static gboolean gst_mem_src_is_seekable(GstBaseSrc *basesrc)
201 {
202     (void)basesrc;
203     return FALSE;
204 }
205 
gst_mem_src_dispose(GObject * object)206 static void gst_mem_src_dispose(GObject *object)
207 {
208     GstMemSrc *memsrc = GST_MEM_SRC(object);
209     g_return_if_fail(memsrc != nullptr && memsrc->priv != nullptr);
210     auto priv = memsrc->priv;
211 
212     GST_OBJECT_LOCK(memsrc);
213     if (memsrc->caps) {
214         gst_caps_unref(memsrc->caps);
215         memsrc->caps = nullptr;
216     }
217     if (priv->notify) {
218         priv->notify(priv->user_data);
219     }
220     priv->user_data = nullptr;
221     priv->notify = nullptr;
222     GST_OBJECT_UNLOCK(memsrc);
223 
224     G_OBJECT_CLASS(parent_class)->dispose(object);
225 }
226 
gst_mem_src_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)227 static void gst_mem_src_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
228 {
229     GstMemSrc *memsrc = GST_MEM_SRC(object);
230     g_return_if_fail(memsrc != nullptr);
231     (void)pspec;
232     switch (prop_id) {
233         case PROP_CAPS:
234             gst_mem_src_set_caps(memsrc, gst_value_get_caps(value));
235             break;
236         case PROP_EMIT_SIGNALS:
237             gst_mem_src_set_emit_signals(memsrc, g_value_get_boolean(value));
238             break;
239         case PROP_BUFFER_SIZE:
240             gst_mem_src_set_buffer_size(memsrc, g_value_get_uint(value));
241             break;
242         case PROP_BUFFER_NUM:
243             gst_mem_src_set_buffer_num(memsrc, g_value_get_uint(value));
244             break;
245         default:
246             break;
247     }
248 }
249 
gst_mem_src_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)250 static void gst_mem_src_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
251 {
252     GstMemSrc *memsrc = GST_MEM_SRC(object);
253     g_return_if_fail(memsrc != nullptr);
254     g_return_if_fail(value != nullptr);
255     (void)pspec;
256     switch (prop_id) {
257         case PROP_BUFFER_SIZE:
258             g_value_set_uint(value, memsrc->buffer_size);
259             GST_DEBUG_OBJECT(object, "set buffer size: %u", memsrc->buffer_size);
260             break;
261         case PROP_BUFFER_NUM:
262             g_value_set_uint(value, memsrc->buffer_num);
263             GST_DEBUG_OBJECT(object, "set buffer num: %u", memsrc->buffer_num);
264             break;
265         default:
266             break;
267     }
268 }
269 
gst_mem_src_query(GstBaseSrc * src,GstQuery * query)270 static gboolean gst_mem_src_query(GstBaseSrc *src, GstQuery *query)
271 {
272     g_return_val_if_fail(src != nullptr, FALSE);
273     g_return_val_if_fail(query != nullptr, FALSE);
274     g_return_val_if_fail(GST_BASE_SRC_CLASS(parent_class) != nullptr, FALSE);
275     switch (GST_QUERY_TYPE(query)) {
276         case GST_QUERY_SCHEDULING: {
277             gst_query_set_scheduling(query, GST_SCHEDULING_FLAG_SEQUENTIAL, 1, -1, 0);
278             gst_query_add_scheduling_mode(query, GST_PAD_MODE_PUSH);
279             return TRUE;
280         }
281         default: {
282             return GST_BASE_SRC_CLASS(parent_class)->query(src, query);
283         }
284     }
285     return TRUE;
286 }
287 
gst_mem_src_set_callback(GstMemSrc * memsrc,BufferAvailable callback,gpointer user_data,GDestroyNotify notify)288 void gst_mem_src_set_callback(GstMemSrc *memsrc, BufferAvailable callback,
289     gpointer user_data, GDestroyNotify notify)
290 {
291     g_return_if_fail(memsrc != nullptr && memsrc->priv != nullptr);
292     auto priv = memsrc->priv;
293     GST_OBJECT_LOCK(memsrc);
294     priv->user_data = user_data;
295     priv->notify = notify;
296     priv->buffer_available = callback;
297     GST_OBJECT_UNLOCK(memsrc);
298 }
299 
300 
gst_mem_src_pull_buffer(GstMemSrc * memsrc)301 GstBuffer *gst_mem_src_pull_buffer(GstMemSrc *memsrc)
302 {
303     GST_DEBUG_OBJECT(memsrc, "Pull buffer");
304     g_return_val_if_fail(memsrc != nullptr, nullptr);
305     GstMemSrcClass *memclass = GST_MEM_SRC_GET_CLASS(memsrc);
306 
307     g_return_val_if_fail(memclass != nullptr, nullptr);
308     if (memclass->pull_buffer) {
309         return memclass->pull_buffer(memsrc);
310     }
311     GST_ERROR_OBJECT(memsrc, "there is no pull buffer function");
312     return nullptr;
313 }
314 
gst_mem_src_push_buffer(GstMemSrc * memsrc,GstBuffer * buffer)315 GstFlowReturn gst_mem_src_push_buffer(GstMemSrc *memsrc, GstBuffer *buffer)
316 {
317     GST_DEBUG_OBJECT(memsrc, "Push buffer");
318     g_return_val_if_fail(memsrc != nullptr, GST_FLOW_ERROR);
319     GstMemSrcClass *memclass = GST_MEM_SRC_GET_CLASS(memsrc);
320 
321     g_return_val_if_fail(memclass != nullptr, GST_FLOW_ERROR);
322     if (memclass->push_buffer) {
323         return memclass->push_buffer(memsrc, buffer);
324     }
325     GST_ERROR_OBJECT(memsrc, "there is no push buffer function");
326     return GST_FLOW_ERROR;
327 }