• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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_video_capture_src.h"
17 #include <gst/gst.h>
18 #include "gst_video_capture_pool.h"
19 #include "media_errors.h"
20 #include "display_type.h"
21 #include "buffer_type_meta.h"
22 
23 using namespace OHOS::Media;
24 #define gst_video_capture_src_parent_class parent_class
25 #define GST_TYPE_VIDEO_CAPTURE_SRC_STREAM_TYPE (gst_video_capture_src_stream_type_get_type())
gst_video_capture_src_stream_type_get_type(void)26 static GType gst_video_capture_src_stream_type_get_type(void)
27 {
28     static GType surface_video_src_stream_type = 0;
29     static const GEnumValue stream_types[] = {
30         {VIDEO_STREAM_TYPE_UNKNOWN, "UNKNOWN", "UNKNOWN"},
31         {VIDEO_STREAM_TYPE_ES_AVC, "ES_AVC", "ES_AVC"},
32         {VIDEO_STREAM_TYPE_YUV_420, "YUV_420", "YUV_420"},
33         {VIDEO_STREAM_TYPE_RGBA, "RGBA8888", "RGBA8888"},
34         {0, nullptr, nullptr}
35     };
36     if (!surface_video_src_stream_type) {
37         surface_video_src_stream_type = g_enum_register_static("VideoStreamType", stream_types);
38     }
39     return surface_video_src_stream_type;
40 }
41 
42 static GstStaticPadTemplate gst_video_src_template =
43 GST_STATIC_PAD_TEMPLATE("src",
44     GST_PAD_SRC,
45     GST_PAD_ALWAYS,
46     GST_STATIC_CAPS_ANY);
47 
48 namespace {
49     constexpr VideoStreamType DEFAULT_STREAM_TYPE = VIDEO_STREAM_TYPE_UNKNOWN;
50     constexpr guint DEFAULT_FRAME_RATE = 25;
51 }
52 
53 GST_DEBUG_CATEGORY_STATIC (gst_video_capture_src_debug);
54 #define GST_CAT_DEFAULT gst_video_capture_src_debug
55 
56 enum {
57     PROP_0,
58     PROP_STREAM_TYPE,
59     PROP_SURFACE_WIDTH,
60     PROP_SURFACE_HEIGHT,
61     PROP_FRAME_RATE,
62 };
63 
64 G_DEFINE_TYPE(GstVideoCaptureSrc, gst_video_capture_src, GST_TYPE_SURFACE_SRC);
65 
66 static void gst_video_capture_src_finalize(GObject *object);
67 static void gst_video_capture_src_set_stream_type(GstVideoCaptureSrc *src, gint stream_type);
68 static void gst_video_capture_src_set_caps(GstVideoCaptureSrc *src, int32_t pixelFormat);
69 static void gst_video_capture_src_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
70 static void gst_video_capture_src_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
71 static GstStateChangeReturn gst_video_capture_src_change_state(GstElement *element, GstStateChange transition);
72 static GstFlowReturn gst_video_capture_deal_with_pts(GstVideoCaptureSrc *src, GstBuffer *buf);
73 static GstFlowReturn gst_video_capture_src_fill(GstBaseSrc *src, guint64 offset, guint size, GstBuffer *buf);
74 static GstBufferPool *gst_video_capture_create_pool(GstMemSrc *memsrc);
75 static void gst_video_capture_src_start(GstVideoCaptureSrc *src);
76 static void gst_video_capture_src_pause(GstVideoCaptureSrc *src);
77 static void gst_video_capture_src_resume(GstVideoCaptureSrc *src);
78 static void gst_video_capture_src_stop(GstVideoCaptureSrc *src);
79 static void gst_video_capture_src_prestop(GstVideoCaptureSrc *src);
80 
gst_video_capture_src_class_init(GstVideoCaptureSrcClass * klass)81 static void gst_video_capture_src_class_init(GstVideoCaptureSrcClass *klass)
82 {
83     g_return_if_fail(klass != nullptr);
84     GObjectClass *gobject_class = reinterpret_cast<GObjectClass*>(klass);
85     GstElementClass *gstelement_class = reinterpret_cast<GstElementClass*>(klass);
86     GstBaseSrcClass *gstbasesrc_class = reinterpret_cast<GstBaseSrcClass*>(klass);
87     GstMemSrcClass *gstmemsrc_class = reinterpret_cast<GstMemSrcClass *>(klass);
88     GST_DEBUG_CATEGORY_INIT(gst_video_capture_src_debug, "videocapturesrc", 0, "video capture src base class");
89 
90     gobject_class->finalize = gst_video_capture_src_finalize;
91     gobject_class->set_property = gst_video_capture_src_set_property;
92     gobject_class->get_property = gst_video_capture_src_get_property;
93 
94     g_object_class_install_property(gobject_class, PROP_STREAM_TYPE,
95         g_param_spec_enum("stream-type", "Stream type",
96             "Stream type", GST_TYPE_VIDEO_CAPTURE_SRC_STREAM_TYPE, DEFAULT_STREAM_TYPE,
97             (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
98 
99     g_object_class_install_property(gobject_class, PROP_FRAME_RATE,
100         g_param_spec_uint("frame-rate", "Frame rate",
101             "recorder frame rate", 0, G_MAXUINT32, DEFAULT_FRAME_RATE,
102             (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
103 
104     g_object_class_install_property(gobject_class, PROP_SURFACE_WIDTH,
105         g_param_spec_uint("surface-width", "Surface width",
106             "Surface width", 0, G_MAXUINT32, 0,
107             (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
108 
109     g_object_class_install_property(gobject_class, PROP_SURFACE_HEIGHT,
110         g_param_spec_uint("surface-height", "Surface height",
111             "Surface width", 0, G_MAXUINT32, 0,
112             (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
113 
114     gstelement_class->change_state = gst_video_capture_src_change_state;
115     gstbasesrc_class->fill = gst_video_capture_src_fill;
116     gstmemsrc_class->create_pool = gst_video_capture_create_pool;
117 
118     gst_element_class_set_static_metadata(gstelement_class,
119         "video capture source", "Source/Video",
120         "Retrieve video frame from surface buffer queue", "OpenHarmony");
121 
122     gst_element_class_add_static_pad_template(gstelement_class, &gst_video_src_template);
123 }
124 
gst_video_capture_src_init(GstVideoCaptureSrc * videocapturesrc)125 static void gst_video_capture_src_init(GstVideoCaptureSrc *videocapturesrc)
126 {
127     g_return_if_fail(videocapturesrc != nullptr);
128 
129     // private param
130     videocapturesrc->video_frame_rate = DEFAULT_FRAME_RATE;
131     videocapturesrc->src_caps = nullptr;
132     videocapturesrc->is_first_buffer = true;
133     videocapturesrc->video_width = 0;
134 
135     videocapturesrc->video_height = 0;
136     videocapturesrc->min_buffer_size = 0;
137     videocapturesrc->cur_state = RECORDER_INITIALIZED;
138     videocapturesrc->min_interval = 0;
139 
140     videocapturesrc->last_timestamp = 0;
141     videocapturesrc->paused_time = -1;
142     videocapturesrc->resume_time = 0;
143     videocapturesrc->paused_count = 0;
144     videocapturesrc->persist_time = 0;
145     videocapturesrc->total_pause_time = 0;
146 }
147 
gst_video_capture_src_finalize(GObject * object)148 static void gst_video_capture_src_finalize(GObject *object)
149 {
150     GST_DEBUG_OBJECT(object, "finalize");
151     g_return_if_fail(object != nullptr);
152     GstVideoCaptureSrc *src = GST_VIDEO_CAPTURE_SRC(object);
153     g_return_if_fail(src != nullptr);
154 
155     if (src->src_caps != nullptr) {
156         gst_caps_unref(src->src_caps);
157         src->src_caps = nullptr;
158     }
159 
160     G_OBJECT_CLASS(parent_class)->finalize(object);
161 }
162 
gst_video_capture_src_set_stream_type(GstVideoCaptureSrc * src,gint stream_type)163 static void gst_video_capture_src_set_stream_type(GstVideoCaptureSrc *src, gint stream_type)
164 {
165     switch (stream_type) {
166         case VideoStreamType::VIDEO_STREAM_TYPE_ES_AVC:
167             src->stream_type = VIDEO_STREAM_TYPE_ES_AVC;
168             break;
169         case VideoStreamType::VIDEO_STREAM_TYPE_YUV_420:
170             src->stream_type = VIDEO_STREAM_TYPE_YUV_420;
171             break;
172         case VideoStreamType::VIDEO_STREAM_TYPE_RGBA:
173             src->stream_type = VIDEO_STREAM_TYPE_RGBA;
174             break;
175         default:
176             return;
177     }
178 }
179 
gst_video_capture_src_set_caps(GstVideoCaptureSrc * src,int32_t pixelFormat)180 static void gst_video_capture_src_set_caps(GstVideoCaptureSrc *src, int32_t pixelFormat)
181 {
182     g_return_if_fail(src != nullptr);
183 
184     if (src->src_caps != nullptr) {
185         gst_caps_unref(src->src_caps);
186     }
187 
188     std::string format = "";
189 
190     switch (pixelFormat) {
191         case PIXEL_FMT_YCRCB_420_SP:
192             GST_INFO("input pixel foramt is nv21");
193             format = "NV21";
194             src->min_buffer_size = (src->video_width * src->video_height * 3) / 2; // Storage format size*3/2
195             break;
196         case PIXEL_FMT_YCBCR_420_P:
197             GST_INFO("input pixel foramt is I420");
198             format = "I420";
199             src->min_buffer_size = (src->video_width * src->video_height * 3) / 2; // Storage format size*3/2
200             break;
201         case PIXEL_FMT_YCBCR_420_SP:
202             GST_INFO("input pixel foramt is nv12");
203             format = "NV12";
204             src->min_buffer_size = (src->video_width * src->video_height * 3) / 2; // Storage format size*3/2
205             break;
206         case PIXEL_FMT_RGBA_8888:
207             GST_INFO("input pixel foramt is rgba");
208             format = "RGBA";
209             src->min_buffer_size = src->video_width * src->video_height * 4; // Storage format size*4
210             break;
211         default:
212             break;
213     }
214 
215     if (src->stream_type == VIDEO_STREAM_TYPE_ES_AVC) {
216         src->src_caps = gst_caps_new_simple("video/x-h264",
217             "framerate", GST_TYPE_FRACTION, src->video_frame_rate, 1,
218             "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
219             "alignment", G_TYPE_STRING, "nal",
220             "stream-format", G_TYPE_STRING, "byte-stream",
221             nullptr);
222         src->min_buffer_size = 0;
223     } else {
224         src->src_caps = gst_caps_new_simple("video/x-raw",
225             "format", G_TYPE_STRING, format.c_str(),
226             "framerate", GST_TYPE_FRACTION, src->video_frame_rate, 1,
227             "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
228             "width", G_TYPE_INT, src->video_width,
229             "height", G_TYPE_INT, src->video_height,
230             nullptr);
231     }
232     gst_base_src_set_caps(GST_BASE_SRC(src), src->src_caps);
233 }
234 
gst_video_capture_src_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)235 static void gst_video_capture_src_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
236 {
237     g_return_if_fail(object != nullptr);
238     g_return_if_fail(value != nullptr);
239     GstVideoCaptureSrc *src = GST_VIDEO_CAPTURE_SRC(object);
240     (void)pspec;
241     switch (prop_id) {
242         case PROP_STREAM_TYPE:
243             gst_video_capture_src_set_stream_type(src, g_value_get_enum(value));
244             break;
245         case PROP_SURFACE_WIDTH:
246             src->video_width = g_value_get_uint(value);
247             break;
248         case PROP_SURFACE_HEIGHT:
249             src->video_height = g_value_get_uint(value);
250             break;
251         case PROP_FRAME_RATE:
252             src->video_frame_rate = g_value_get_uint(value);
253             src->min_interval = 1000000000 / src->video_frame_rate; // 1s = 1000000000ns
254             break;
255         default:
256             break;
257     }
258 }
259 
gst_video_capture_src_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)260 static void gst_video_capture_src_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
261 {
262     g_return_if_fail(object != nullptr);
263     g_return_if_fail(value != nullptr);
264     GstVideoCaptureSrc *src = GST_VIDEO_CAPTURE_SRC(object);
265     (void)pspec;
266     switch (prop_id) {
267         case PROP_STREAM_TYPE:
268             g_value_set_enum(value, src->stream_type);
269             break;
270         case PROP_SURFACE_WIDTH:
271             src->video_width = g_value_get_uint(value);
272             break;
273         case PROP_SURFACE_HEIGHT:
274             src->video_height = g_value_get_uint(value);
275             break;
276         case PROP_FRAME_RATE:
277             g_value_set_uint(value, src->video_frame_rate);
278             break;
279         default:
280             break;
281     }
282 }
283 
gst_video_capture_src_change_state(GstElement * element,GstStateChange transition)284 static GstStateChangeReturn gst_video_capture_src_change_state(GstElement *element, GstStateChange transition)
285 {
286     GstVideoCaptureSrc *capturesrc = GST_VIDEO_CAPTURE_SRC(element);
287     g_return_val_if_fail(capturesrc != nullptr, GST_STATE_CHANGE_FAILURE);
288 
289     switch (transition) {
290         case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
291             if (capturesrc->cur_state == RECORDER_INITIALIZED) {
292                 gst_video_capture_src_start(capturesrc);
293             } else {
294                 gst_video_capture_src_resume(capturesrc);
295             }
296             break;
297         case GST_STATE_CHANGE_PAUSED_TO_READY:
298             gst_video_capture_src_prestop(capturesrc);
299             break;
300         default:
301             break;
302     }
303     GstStateChangeReturn ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
304 
305     switch (transition) {
306         case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
307             gst_video_capture_src_pause(capturesrc);
308             break;
309         case GST_STATE_CHANGE_PAUSED_TO_READY:
310             gst_video_capture_src_stop(capturesrc);
311             break;
312         default:
313             break;
314     }
315 
316     return ret;
317 }
318 
gst_video_capture_create_pool(GstMemSrc * memsrc)319 static GstBufferPool *gst_video_capture_create_pool(GstMemSrc *memsrc)
320 {
321     g_return_val_if_fail(memsrc != nullptr, nullptr);
322     GstBufferPool *bufferpool = gst_video_capture_pool_new();
323     if (bufferpool != nullptr) {
324         GstVideoCaptureSrc *capturesrc = GST_VIDEO_CAPTURE_SRC(memsrc);
325         g_object_set(bufferpool, "suspend", TRUE, nullptr);
326         if (capturesrc->stream_type == VIDEO_STREAM_TYPE_ES_AVC) {
327             g_object_set(bufferpool, "cached-data", TRUE, nullptr);
328         }
329     }
330     return bufferpool;
331 }
332 
gst_video_capture_deal_with_pts(GstVideoCaptureSrc * src,GstBuffer * buf)333 static GstFlowReturn gst_video_capture_deal_with_pts(GstVideoCaptureSrc *src, GstBuffer *buf)
334 {
335     g_return_val_if_fail(buf != nullptr, GST_FLOW_ERROR);
336 
337     guint64 timestamp = GST_BUFFER_PTS(buf);
338     g_return_val_if_fail(timestamp <= G_MAXINT64, GST_FLOW_ERROR);
339     GST_DEBUG_OBJECT(src, "video capture buffer size is: %" G_GSIZE_FORMAT ", pts: %" G_GUINT64_FORMAT,
340         gst_buffer_get_size(buf), timestamp);
341     g_return_val_if_fail(src->last_timestamp >= 0 && timestamp >= static_cast<guint64>(src->last_timestamp),
342         GST_FLOW_ERROR);
343     GST_INFO_OBJECT(src, "videoCapturer timestamp has increased: %" G_GUINT64_FORMAT,
344         timestamp - src->last_timestamp);
345 
346     if (src->cur_state == RECORDER_RESUME && src->paused_time == -1) {
347         src->paused_time = src->last_timestamp;
348         GST_INFO_OBJECT(src, "video pause timestamp %" G_GINT64_FORMAT "", src->paused_time);
349     }
350 
351     if (src->cur_state == RECORDER_PAUSED) {
352         src->paused_time = static_cast<gint64>(timestamp);
353         GST_INFO_OBJECT(src, "video pause timestamp %" G_GINT64_FORMAT "", src->paused_time);
354     }
355 
356     if (src->cur_state == RECORDER_RESUME) {
357         GstBufferTypeMeta *meta = gst_buffer_get_buffer_type_meta(buf);
358         g_return_val_if_fail(meta != nullptr, GST_FLOW_ERROR);
359         if (meta->invalidpts) {
360             timestamp = src->last_timestamp + 1000000; // Increase 1000000 ns to avoid audio and video synchronization.
361             src->paused_time = timestamp;
362             GST_DEBUG_OBJECT(src, "Data received during pause, timestamp %" G_GINT64_FORMAT "", timestamp);
363         } else {
364             src->cur_state = RECORDER_RUNNING;
365             src->resume_time = static_cast<gint64>(timestamp);
366             src->persist_time = fabs(src->resume_time - src->paused_time) - src->min_interval;
367             GST_INFO_OBJECT(src, "video resume timestamp %" G_GINT64_FORMAT "", src->resume_time);
368             src->paused_time = -1; // reset pause time
369             src->total_pause_time += src->persist_time;
370             GST_INFO_OBJECT(src, "video has %d times pause, total PauseTime: %" G_GINT64_FORMAT "",
371                 src->paused_count, src->total_pause_time);
372         }
373     }
374 
375     src->last_timestamp = static_cast<gint64>(timestamp); // updata last_timestamp
376     g_return_val_if_fail(src->total_pause_time >= 0 && timestamp >= static_cast<guint64>(src->last_timestamp),
377         GST_FLOW_ERROR);
378     GST_BUFFER_PTS(buf) = timestamp - src->total_pause_time; // running state timestamp to encoder is up with pause
379     return GST_FLOW_OK;
380 }
381 
gst_video_capture_src_fill(GstBaseSrc * src,guint64 offset,guint size,GstBuffer * buf)382 static GstFlowReturn gst_video_capture_src_fill(GstBaseSrc *src, guint64 offset, guint size, GstBuffer *buf)
383 {
384     g_return_val_if_fail(src != nullptr, GST_FLOW_ERROR);
385     GstVideoCaptureSrc *capturesrc = GST_VIDEO_CAPTURE_SRC(src);
386     (void)offset;
387     (void)size;
388     GstBufferTypeMeta *meta = gst_buffer_get_buffer_type_meta(buf);
389     g_return_val_if_fail(meta != nullptr, GST_FLOW_ERROR);
390     if (meta->bufferFlag & BUFFER_FLAG_EOS) {
391         return GST_FLOW_EOS;
392     }
393 
394     // set caps, called at first frame
395     if (capturesrc->is_first_buffer) {
396         gst_video_capture_src_set_caps(capturesrc, meta->pixelFormat);
397         capturesrc->is_first_buffer = false;
398     }
399 
400     if ((capturesrc->stream_type != VIDEO_STREAM_TYPE_ES_AVC) &&
401         ((meta->width != capturesrc->video_width) || (meta->height != capturesrc->video_height))) {
402         GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, ("Data width or height error on input stream."),
403             ("Data width or height error on input stream. Input data width=%d, height=%d. Set width=%d, height=%d.",
404             meta->width, meta->height, capturesrc->video_width, capturesrc->video_height));
405         return GST_FLOW_ERROR;
406     }
407 
408     if (gst_buffer_get_size(buf) < capturesrc->min_buffer_size) {
409         GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, ("Wrong data length on input streams."),
410             ("The minimum data length of video data input is %d, and the current input data length is "
411             "%" G_GSIZE_FORMAT ".", capturesrc->min_buffer_size, gst_buffer_get_size(buf)));
412         return GST_FLOW_ERROR;
413     }
414 
415     if (capturesrc->stream_type == VIDEO_STREAM_TYPE_ES_AVC) {
416         gst_buffer_resize(buf, 0, meta->length); // es stream gstbuffer size is not equle to surface buffer size
417     }
418 
419     // do with pts
420     if (gst_video_capture_deal_with_pts(capturesrc, buf) != GST_FLOW_OK) {
421         GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, ("Data timestamp error on input stream."),
422             ("Data timestamp error on input stream, pts: %" G_GUINT64_FORMAT, GST_BUFFER_PTS(buf)));
423     }
424 
425     return GST_FLOW_OK;
426 }
427 
gst_video_capture_src_start(GstVideoCaptureSrc * src)428 static void gst_video_capture_src_start(GstVideoCaptureSrc *src)
429 {
430     g_return_if_fail(src != nullptr);
431     GstSurfaceSrc *surfacesrc = GST_SURFACE_SRC(src);
432     g_return_if_fail(surfacesrc->pool != nullptr);
433 
434     if (src->stream_type == VIDEO_STREAM_TYPE_ES_AVC) {
435         g_object_set(surfacesrc->pool, "cached-data", FALSE, nullptr);
436     }
437     g_object_set(surfacesrc->pool, "suspend", FALSE, nullptr);
438     g_object_set(surfacesrc->pool, "src", static_cast<gpointer>(src), nullptr);
439     g_object_set(surfacesrc->pool, "input-detection", TRUE, nullptr);
440 
441     src->cur_state = RECORDER_RUNNING;
442 }
443 
gst_video_capture_src_pause(GstVideoCaptureSrc * src)444 static void gst_video_capture_src_pause(GstVideoCaptureSrc *src)
445 {
446     g_return_if_fail(src != nullptr);
447     GstSurfaceSrc *surfacesrc = GST_SURFACE_SRC(src);
448     g_return_if_fail(surfacesrc->pool != nullptr);
449 
450     if (src->stream_type == VIDEO_STREAM_TYPE_ES_AVC) {
451         g_object_set(surfacesrc->pool, "cached-data", TRUE, nullptr);
452     }
453     g_object_set(surfacesrc->pool, "suspend", TRUE, nullptr);
454     g_object_set(surfacesrc->pool, "pause-data", TRUE, nullptr);
455     g_object_set(surfacesrc->pool, "input-detection", FALSE, nullptr);
456 
457     src->cur_state = RECORDER_PAUSED;
458     src->paused_count++;
459 
460     GstBufferPool *bufferpool = GST_BUFFER_POOL(surfacesrc->pool);
461 
462     if (src->stream_type != VIDEO_STREAM_TYPE_ES_AVC) {
463         gst_buffer_pool_set_flushing(bufferpool, TRUE);
464         gst_buffer_pool_set_flushing(bufferpool, FALSE);
465     }
466     GST_DEBUG_OBJECT(src, "video capture src pause");
467 }
468 
gst_video_capture_src_resume(GstVideoCaptureSrc * src)469 static void gst_video_capture_src_resume(GstVideoCaptureSrc *src)
470 {
471     g_return_if_fail(src != nullptr);
472     GstSurfaceSrc *surfacesrc = GST_SURFACE_SRC(src);
473     g_return_if_fail(surfacesrc->pool != nullptr);
474 
475     src->cur_state = RECORDER_RESUME;
476 
477     if (src->stream_type == VIDEO_STREAM_TYPE_ES_AVC) {
478         g_object_set(surfacesrc->pool, "cached-data", FALSE, nullptr);
479     }
480     g_object_set(surfacesrc->pool, "suspend", FALSE, nullptr);
481     g_object_set(surfacesrc->pool, "pause-data", FALSE, nullptr);
482     g_object_set(surfacesrc->pool, "input-detection", TRUE, nullptr);
483     GST_DEBUG_OBJECT(src, "video capture src resume");
484 }
485 
gst_video_capture_src_prestop(GstVideoCaptureSrc * src)486 static void gst_video_capture_src_prestop(GstVideoCaptureSrc *src)
487 {
488     g_return_if_fail(src != nullptr);
489     GstSurfaceSrc *surfacesrc = GST_SURFACE_SRC(src);
490     g_return_if_fail(surfacesrc->pool != nullptr);
491 
492     // Prevent the data acquisition thread from getting stuck: acquire_buffer.
493     g_object_set(surfacesrc->pool, "pause-data", FALSE, nullptr);
494     g_object_set(surfacesrc->pool, "src", nullptr, nullptr);
495 }
496 
gst_video_capture_src_stop(GstVideoCaptureSrc * src)497 static void gst_video_capture_src_stop(GstVideoCaptureSrc *src)
498 {
499     g_return_if_fail(src != nullptr);
500 
501     src->cur_state = RECORDER_STOP;
502 }
503