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