• 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_surface_src.h"
17 #include <gst/video/video.h>
18 #include <sync_fence.h>
19 #include "gst_consumer_surface_pool.h"
20 #include "gst_consumer_surface_allocator.h"
21 #include "media_errors.h"
22 #include "surface_buffer.h"
23 #include "buffer_type_meta.h"
24 #include "scope_guard.h"
25 #include "display_type.h"
26 #include "param_wrapper.h"
27 #include "media_log.h"
28 
29 #define gst_surface_src_parent_class parent_class
30 using namespace OHOS;
31 namespace {
32     constexpr guint DEFAULT_SURFACE_QUEUE_SIZE = 4;
33     constexpr int32_t DEFAULT_SURFACE_SIZE = 1024 * 1024;
34     constexpr int32_t DEFAULT_VIDEO_WIDTH = 1920;
35     constexpr int32_t DEFAULT_VIDEO_HEIGHT = 1080;
36     constexpr uint32_t STRIDE_ALIGN = 8;
37 }
38 
39 GST_DEBUG_CATEGORY_STATIC(gst_surface_src_debug_category);
40 #define GST_CAT_DEFAULT gst_surface_src_debug_category
41 
42 static GstStaticPadTemplate gst_src_template =
43 GST_STATIC_PAD_TEMPLATE("src",
44     GST_PAD_SRC,
45     GST_PAD_ALWAYS,
46     GST_STATIC_CAPS(GST_VIDEO_CAPS_MAKE(GST_VIDEO_FORMATS_ALL)));
47 
48 enum {
49     PROP_0,
50     PROP_SURFACE,
51     PROP_SURFACE_STRIDE,
52     PROP_SUSPEND,
53     PROP_REPEAT,
54     PROP_MAX_FRAME_RATE,
55     PROP_NOTIFY_EOS,
56 };
57 
58 G_DEFINE_TYPE(GstSurfaceSrc, gst_surface_src, GST_TYPE_MEM_SRC);
59 
60 static void gst_surface_src_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
61 static void gst_surface_src_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
62 static GstStateChangeReturn gst_surface_src_change_state(GstElement *element, GstStateChange transition);
63 static gboolean gst_surface_src_create_surface(GstSurfaceSrc *surfacesrc);
64 static GstBufferPool *gst_surface_src_create_pool(GstMemSrc *memsrc);
65 static gboolean gst_surface_src_init_pool(GstSurfaceSrc *surfacesrc);
66 static void gst_surface_src_destroy_surface(GstSurfaceSrc *src);
67 static void gst_surface_src_destroy_pool(GstSurfaceSrc *src);
68 static gboolean gst_surface_src_decide_allocation(GstBaseSrc *basesrc, GstQuery *query);
69 static GstFlowReturn gst_surface_src_fill(GstBaseSrc *src, guint64 offset, guint size, GstBuffer *buf);
70 static void gst_surface_src_init_surface(GstSurfaceSrc *src);
71 static gboolean gst_surface_src_send_event(GstElement *element, GstEvent *event);
72 static void gst_surface_mem_src_dump_buffer(GstBaseSrc *self, GstBuffer *buffer);
73 static void gst_surface_mem_src_dump_from_sys_param(GstSurfaceSrc *src);
74 
gst_surface_src_class_init(GstSurfaceSrcClass * klass)75 static void gst_surface_src_class_init(GstSurfaceSrcClass *klass)
76 {
77     g_return_if_fail(klass != nullptr);
78     GObjectClass *gobject_class = reinterpret_cast<GObjectClass*>(klass);
79     GstElementClass *gstelement_class = reinterpret_cast<GstElementClass*>(klass);
80     GstBaseSrcClass *gstbasesrc_class = reinterpret_cast<GstBaseSrcClass*>(klass);
81     GstMemSrcClass *gstmemsrc_class = reinterpret_cast<GstMemSrcClass*>(klass);
82     GST_DEBUG_CATEGORY_INIT(gst_surface_src_debug_category, "surfacepoolsrc", 0, "surface pool src base class");
83     gobject_class->get_property = gst_surface_src_get_property;
84     gobject_class->set_property = gst_surface_src_set_property;
85 
86     g_object_class_install_property(gobject_class, PROP_SURFACE,
87         g_param_spec_pointer("surface", "Surface", "Surface for buffer",
88             (GParamFlags)(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
89 
90     g_object_class_install_property(gobject_class, PROP_SURFACE_STRIDE,
91         g_param_spec_uint("surface-stride", "surface stride",
92             "surface buffer stride", 0, G_MAXINT32, STRIDE_ALIGN,
93             (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
94 
95     g_object_class_install_property(gobject_class, PROP_SUSPEND,
96         g_param_spec_boolean("suspend", "Suspend surface", "Suspend surface",
97             FALSE, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
98 
99     g_object_class_install_property(gobject_class, PROP_REPEAT,
100         g_param_spec_uint("repeat", "Repeat frame", "Repeat previous frame after given milliseconds",
101             0, G_MAXUINT32, 0, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
102 
103     g_object_class_install_property(gobject_class, PROP_MAX_FRAME_RATE,
104         g_param_spec_uint("max-framerate", "Max frame rate", "Max frame rate",
105             0, G_MAXUINT32, 0, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
106 
107     g_object_class_install_property(gobject_class, PROP_NOTIFY_EOS,
108         g_param_spec_boolean("notify-eos", "notify eos", "Need notify eos",
109             FALSE, (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)));
110 
111     gstelement_class->change_state = gst_surface_src_change_state;
112     gstelement_class->send_event = gst_surface_src_send_event;
113     gstbasesrc_class->fill = gst_surface_src_fill;
114     gstbasesrc_class->decide_allocation = gst_surface_src_decide_allocation;
115     gstmemsrc_class->create_pool = gst_surface_src_create_pool;
116     gst_element_class_set_static_metadata(gstelement_class,
117         "surface mem source", "Source/Surface/Pool",
118         "Retrieve frame from surface buffer queue with raw data", "OpenHarmony");
119 
120     gst_element_class_add_static_pad_template(gstelement_class, &gst_src_template);
121 }
122 
gst_surface_src_init(GstSurfaceSrc * surfacesrc)123 static void gst_surface_src_init(GstSurfaceSrc *surfacesrc)
124 {
125     GST_DEBUG_OBJECT(surfacesrc, "Init, id = %d", static_cast<int32_t>(FAKE_POINTER(surfacesrc)));
126     g_return_if_fail(surfacesrc != nullptr);
127     surfacesrc->pool = nullptr;
128     surfacesrc->stride = STRIDE_ALIGN;
129     surfacesrc->need_flush = FALSE;
130     surfacesrc->flushing = FALSE;
131     gst_surface_mem_src_dump_from_sys_param(surfacesrc);
132 }
133 
gst_surface_src_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)134 static void gst_surface_src_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
135 {
136     GstSurfaceSrc *src = GST_SURFACE_SRC(object);
137     g_return_if_fail(src != nullptr);
138     g_return_if_fail(value != nullptr);
139     (void)pspec;
140     switch (prop_id) {
141         case PROP_SURFACE:
142             g_value_set_pointer(value, src->producerSurface.GetRefPtr());
143             break;
144         case PROP_SURFACE_STRIDE:
145             g_value_set_uint(value, src->stride);
146             break;
147         default:
148             break;
149     }
150 }
151 
gst_surface_src_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)152 static void gst_surface_src_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
153 {
154     GstSurfaceSrc *src = GST_SURFACE_SRC(object);
155     g_return_if_fail(src != nullptr && value != nullptr);
156     (void)pspec;
157     switch (prop_id) {
158         case PROP_SURFACE_STRIDE:
159             src->stride = g_value_get_uint(value);
160             if (src->stride > INT32_MAX) {
161                 src->stride = STRIDE_ALIGN;
162             }
163             break;
164         case PROP_SUSPEND:
165             g_return_if_fail(src->pool != nullptr);
166             g_object_set(src->pool, "suspend", g_value_get_boolean(value), nullptr);
167             break;
168         case PROP_REPEAT:
169             g_return_if_fail(src->pool != nullptr);
170             g_object_set(src->pool, "repeat", g_value_get_uint(value), nullptr);
171             break;
172         case PROP_MAX_FRAME_RATE:
173             g_return_if_fail(src->pool != nullptr);
174             g_object_set(src->pool, "max-framerate", g_value_get_uint(value), nullptr);
175             break;
176         case PROP_NOTIFY_EOS:
177             g_return_if_fail(src->pool != nullptr);
178             g_object_set(src->pool, "notify-eos", g_value_get_boolean(value), nullptr);
179             break;
180         default:
181             break;
182     }
183 }
184 
gst_surface_src_fill(GstBaseSrc * src,guint64 offset,guint size,GstBuffer * buf)185 static GstFlowReturn gst_surface_src_fill(GstBaseSrc *src, guint64 offset, guint size, GstBuffer *buf)
186 {
187     (void)src;
188     (void)offset;
189     (void)size;
190     gst_surface_mem_src_dump_buffer(src, buf);
191 
192     GstBufferTypeMeta *meta = gst_buffer_get_buffer_type_meta(buf);
193     if (meta != nullptr && (meta->bufferFlag & BUFFER_FLAG_EOS)) {
194         GST_DEBUG_OBJECT(src, "EOS buffer");
195         return GST_FLOW_EOS;
196     }
197     return GST_FLOW_OK;
198 }
199 
gst_surface_src_change_state(GstElement * element,GstStateChange transition)200 static GstStateChangeReturn gst_surface_src_change_state(GstElement *element, GstStateChange transition)
201 {
202     GstSurfaceSrc *surfacesrc = GST_SURFACE_SRC(element);
203     g_return_val_if_fail(surfacesrc != nullptr, GST_STATE_CHANGE_FAILURE);
204     switch (transition) {
205         case GST_STATE_CHANGE_NULL_TO_READY:
206             g_return_val_if_fail(gst_surface_src_create_surface(surfacesrc) == TRUE, GST_STATE_CHANGE_FAILURE);
207             g_return_val_if_fail(gst_surface_src_init_pool(surfacesrc) == TRUE, GST_STATE_CHANGE_FAILURE);
208             break;
209         case GST_STATE_CHANGE_READY_TO_PAUSED:
210             gst_surface_src_init_surface(surfacesrc);
211             break;
212         default:
213             break;
214     }
215     GstStateChangeReturn ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
216 
217     switch (transition) {
218         case GST_STATE_CHANGE_READY_TO_NULL:
219             gst_surface_src_destroy_pool(surfacesrc);
220             gst_surface_src_destroy_surface(surfacesrc);
221             if (surfacesrc->dump.enable_dump == TRUE) {
222                 if (surfacesrc->dump.dump_file != nullptr) {
223                     fclose(surfacesrc->dump.dump_file);
224                     surfacesrc->dump.dump_file = nullptr;
225                 }
226             }
227             GST_OBJECT_LOCK(surfacesrc);
228             surfacesrc->need_flush = FALSE;
229             GST_OBJECT_UNLOCK(surfacesrc);
230             break;
231         default:
232             break;
233     }
234 
235     return ret;
236 }
237 
gst_surface_src_create_surface(GstSurfaceSrc * surfacesrc)238 static gboolean gst_surface_src_create_surface(GstSurfaceSrc *surfacesrc)
239 {
240     g_return_val_if_fail(surfacesrc != nullptr, FALSE);
241     sptr<Surface> consumerSurface = Surface::CreateSurfaceAsConsumer();
242     g_return_val_if_fail(consumerSurface != nullptr, FALSE);
243     sptr<IBufferProducer> producer = consumerSurface->GetProducer();
244     g_return_val_if_fail(producer != nullptr, FALSE);
245     sptr<Surface> producerSurface = Surface::CreateSurfaceAsProducer(producer);
246     g_return_val_if_fail(producerSurface != nullptr, FALSE);
247     surfacesrc->consumerSurface = consumerSurface;
248     surfacesrc->producerSurface = producerSurface;
249 
250     SurfaceError ret = surfacesrc->consumerSurface->SetQueueSize(DEFAULT_SURFACE_QUEUE_SIZE);
251     if (ret != SURFACE_ERROR_OK) {
252         GST_WARNING_OBJECT(surfacesrc, "set queue size fail");
253     }
254     GST_DEBUG_OBJECT(surfacesrc, "create surface");
255     return TRUE;
256 }
257 
gst_surface_src_send_event(GstElement * element,GstEvent * event)258 static gboolean gst_surface_src_send_event(GstElement *element, GstEvent *event)
259 {
260     GstSurfaceSrc *surfacesrc = GST_SURFACE_SRC(element);
261     g_return_val_if_fail(surfacesrc != nullptr, FALSE);
262     g_return_val_if_fail(event != nullptr, FALSE);
263     GST_INFO_OBJECT(surfacesrc, "New event %s", GST_EVENT_TYPE_NAME(event));
264 
265     switch (GST_EVENT_TYPE(event)) {
266         case GST_EVENT_FLUSH_START:
267             if (surfacesrc->need_flush == FALSE) {
268                 GST_INFO_OBJECT(surfacesrc, "No need flushing");
269                 surfacesrc->flushing = FALSE;
270                 return TRUE;
271             }
272             surfacesrc->flushing = TRUE;
273             break;
274         case GST_EVENT_FLUSH_STOP:
275             if (surfacesrc->flushing == FALSE) {
276                 GST_INFO_OBJECT(surfacesrc, "No flush start");
277                 return TRUE;
278             }
279             surfacesrc->flushing = FALSE;
280             break;
281         default:
282             break;
283     }
284 
285     return GST_ELEMENT_CLASS(parent_class)->send_event(element, event);
286 }
287 
gst_surface_src_create_pool(GstMemSrc * memsrc)288 static GstBufferPool *gst_surface_src_create_pool(GstMemSrc *memsrc)
289 {
290     (void)memsrc;
291     return gst_consumer_surface_pool_new();
292 }
293 
gst_surface_src_init_pool(GstSurfaceSrc * surfacesrc)294 static gboolean gst_surface_src_init_pool(GstSurfaceSrc *surfacesrc)
295 {
296     GstMemSrcClass *memsrcclass = GST_MEM_SRC_GET_CLASS(surfacesrc);
297     g_return_val_if_fail(memsrcclass != nullptr, FALSE);
298     GstAllocationParams params;
299     GstBufferPool *pool = nullptr;
300     gst_allocation_params_init(&params);
301 
302     if (memsrcclass->create_pool) {
303         GstMemSrc *memsrc = GST_MEM_SRC(surfacesrc);
304         pool = memsrcclass->create_pool(memsrc);
305     }
306 
307     g_return_val_if_fail(pool != nullptr, FALSE);
308     ON_SCOPE_EXIT(0) { gst_object_unref(pool); };
309     GstAllocator *allocator = gst_consumer_surface_allocator_new();
310     g_return_val_if_fail(allocator != nullptr, FALSE);
311     ON_SCOPE_EXIT(1) { gst_object_unref(allocator); };
312     gst_consumer_surface_pool_set_surface(pool, surfacesrc->consumerSurface);
313     gst_consumer_surface_allocator_set_surface(allocator, surfacesrc->consumerSurface);
314     // init pool config
315     GstStructure *config = gst_buffer_pool_get_config(pool);
316     gst_buffer_pool_config_set_allocator(config, allocator, &params);
317     g_return_val_if_fail(gst_buffer_pool_set_config(pool, config) != TRUE, FALSE);
318     surfacesrc->pool = pool;
319     CANCEL_SCOPE_EXIT_GUARD(0);
320     GST_DEBUG_OBJECT(surfacesrc, "create surface pool");
321     return TRUE;
322 }
323 
gst_surface_src_destroy_pool(GstSurfaceSrc * src)324 static void gst_surface_src_destroy_pool(GstSurfaceSrc *src)
325 {
326     gst_object_unref(src->pool);
327     src->pool = nullptr;
328 }
329 
gst_surface_src_destroy_surface(GstSurfaceSrc * src)330 static void gst_surface_src_destroy_surface(GstSurfaceSrc *src)
331 {
332     src->consumerSurface = nullptr;
333     src->producerSurface = nullptr;
334 }
335 
gst_surface_src_init_surface(GstSurfaceSrc * src)336 static void gst_surface_src_init_surface(GstSurfaceSrc *src)
337 {
338     g_return_if_fail(src != nullptr && src->consumerSurface != nullptr);
339     // The internal function do not need judge whether it is empty
340     GstMemSrc *memsrc = GST_MEM_SRC(src);
341     sptr<Surface> surface = src->consumerSurface;
342     guint width = DEFAULT_VIDEO_WIDTH;
343     guint height = DEFAULT_VIDEO_HEIGHT;
344     GST_OBJECT_LOCK(memsrc);
345     if (memsrc->caps != nullptr) {
346         GstVideoInfo info;
347         gst_video_info_init(&info);
348         gst_video_info_from_caps(&info, memsrc->caps);
349         width = static_cast<guint>(info.width);
350         height = static_cast<guint>(info.height);
351     }
352     GST_OBJECT_UNLOCK(memsrc);
353     SurfaceError ret = surface->SetUserData("video_width", std::to_string(width));
354     if (ret != SURFACE_ERROR_OK) {
355         GST_WARNING_OBJECT(src, "Set video width fail");
356     }
357     ret = surface->SetUserData("video_height", std::to_string(height));
358     if (ret != SURFACE_ERROR_OK) {
359         GST_WARNING_OBJECT(src, "Set video height fail");
360     }
361     ret = surface->SetUserData("surface_size", std::to_string(DEFAULT_SURFACE_SIZE));
362     if (ret != SURFACE_ERROR_OK) {
363         GST_WARNING_OBJECT(src, "Set surface size fail");
364     }
365     ret = surface->SetDefaultWidthAndHeight(width, height);
366     if (ret != SURFACE_ERROR_OK) {
367         GST_WARNING_OBJECT(src, "Set surface width and height fail");
368     }
369 }
370 
gst_surface_src_get_pool(GstSurfaceSrc * surfacesrc,GstQuery * query,GstCaps * outcaps)371 static gboolean gst_surface_src_get_pool(GstSurfaceSrc *surfacesrc, GstQuery *query, GstCaps *outcaps)
372 {
373     g_return_val_if_fail(surfacesrc != nullptr && query != nullptr && surfacesrc->consumerSurface != nullptr, FALSE);
374     if (surfacesrc->pool == nullptr) {
375         return FALSE;
376     }
377     GstMemSrc *memsrc = GST_MEM_SRC(surfacesrc);
378     guint min_buf = surfacesrc->consumerSurface->GetQueueSize();
379     guint max_buf = min_buf;
380     memsrc->buffer_num = max_buf;
381     gboolean is_video = gst_query_find_allocation_meta(query, GST_VIDEO_META_API_TYPE, nullptr);
382     if (is_video) {
383         // when video need update size
384         GstVideoInfo info;
385         gst_video_info_init(&info);
386         gst_video_info_from_caps(&info, outcaps);
387         if (info.size != 0) {
388             memsrc->buffer_size = info.size;
389         }
390     }
391     GST_INFO_OBJECT(surfacesrc, "update buffer num %u", memsrc->buffer_num);
392     GstStructure *config = gst_buffer_pool_get_config(surfacesrc->pool);
393     if (is_video) {
394         gst_buffer_pool_config_add_option(config, GST_BUFFER_POOL_OPTION_VIDEO_META);
395     }
396     gst_buffer_pool_config_set_params(config, outcaps, memsrc->buffer_size, min_buf, max_buf);
397     if (gst_buffer_pool_set_config(surfacesrc->pool, config) != TRUE) {
398         GST_WARNING_OBJECT(surfacesrc, "set config failed");
399     }
400 
401     if (gst_query_get_n_allocation_pools(query) > 0) {
402         gst_query_set_nth_allocation_pool(query, 0, surfacesrc->pool, memsrc->buffer_num, min_buf, max_buf);
403     } else {
404         gst_query_add_allocation_pool(query, surfacesrc->pool, memsrc->buffer_num, min_buf, max_buf);
405     }
406 
407     GST_DEBUG_OBJECT(surfacesrc, "set surface pool success");
408     return TRUE;
409 }
410 
gst_surface_src_decide_allocation(GstBaseSrc * basesrc,GstQuery * query)411 static gboolean gst_surface_src_decide_allocation(GstBaseSrc *basesrc, GstQuery *query)
412 {
413     GstSurfaceSrc *surfacesrc = GST_SURFACE_SRC(basesrc);
414     g_return_val_if_fail(basesrc != nullptr && query != nullptr, FALSE);
415     GST_OBJECT_LOCK(surfacesrc);
416     surfacesrc->need_flush = TRUE;
417     GST_OBJECT_UNLOCK(surfacesrc);
418     GstCaps *outcaps = nullptr;
419     GstBufferPool *pool = nullptr;
420     guint size = 0;
421     guint min_buf = DEFAULT_SURFACE_QUEUE_SIZE;
422     guint max_buf = DEFAULT_SURFACE_QUEUE_SIZE;
423 
424     // get caps and save to video info
425     gst_query_parse_allocation(query, &outcaps, nullptr);
426     // get pool and pool info from down stream
427     if (gst_query_get_n_allocation_pools(query) > 0) {
428         gst_query_parse_nth_allocation_pool(query, 0, &pool, &size, &min_buf, &max_buf);
429     }
430     auto caps_struct = gst_caps_get_structure(outcaps, 0);
431     auto mediaType = gst_structure_get_name(caps_struct);
432     gboolean isVideo = g_str_has_prefix(mediaType, "video/");
433     if (isVideo) {
434         gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, nullptr);
435     }
436     GstVideoInfo info;
437     gst_video_info_init(&info);
438     gst_video_info_from_caps(&info, outcaps);
439     size = info.size;
440 
441     // we use our own pool
442     if (pool != nullptr) {
443         gst_query_set_nth_allocation_pool(query, 0, nullptr, 0, 0, 0);
444         gst_object_unref(pool);
445         pool = nullptr;
446     }
447     if (gst_surface_src_get_pool(surfacesrc, query, outcaps)) {
448         return TRUE;
449     }
450     return FALSE;
451 }
452 
gst_surface_mem_src_dump_buffer(GstBaseSrc * self,GstBuffer * buffer)453 static void gst_surface_mem_src_dump_buffer(GstBaseSrc *self, GstBuffer *buffer)
454 {
455     g_return_if_fail(self != nullptr);
456     GstSurfaceSrc *src = GST_SURFACE_SRC(self);
457     g_return_if_fail(src != nullptr);
458     g_return_if_fail(buffer != nullptr);
459 
460     if (src->dump.enable_dump == FALSE) {
461         return;
462     }
463 
464     GST_DEBUG_OBJECT(src, "Dump surface src buffer");
465     std::string input_dump_file = "/data/media/surface-in-" +
466         std::to_string(static_cast<int32_t>(FAKE_POINTER(self))) + ".yuv";
467     if (src->dump.dump_file == nullptr) {
468         src->dump.dump_file = fopen(input_dump_file.c_str(), "wb+");
469     }
470     if (src->dump.dump_file == nullptr) {
471         GST_ERROR_OBJECT(self, "open file failed");
472         return;
473     }
474     GstMapInfo info = GST_MAP_INFO_INIT;
475     g_return_if_fail(gst_buffer_map(buffer, &info, GST_MAP_READ));
476     (void)fwrite(info.data, info.size, 1, src->dump.dump_file);
477     (void)fflush(src->dump.dump_file);
478     gst_buffer_unmap(buffer, &info);
479 }
480 
gst_surface_mem_src_dump_from_sys_param(GstSurfaceSrc * src)481 static void gst_surface_mem_src_dump_from_sys_param(GstSurfaceSrc *src)
482 {
483     std::string dump_enable;
484     src->dump.enable_dump = FALSE;
485     int32_t res = OHOS::system::GetStringParameter("sys.media.dump.surfacesrc.enable", dump_enable, "");
486     if (res != 0 || dump_enable.empty()) {
487         GST_DEBUG_OBJECT(src, "sys.media.dump.surfacesrc.enable");
488         return;
489     }
490     GST_DEBUG_OBJECT(src, "sys.media.dump.surfacesrc.enable=%s", dump_enable.c_str());
491 
492     if (dump_enable == "true") {
493         src->dump.enable_dump = TRUE;
494     }
495 }