Coverage Report

Created: 2026-01-22 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gstreamer/subprojects/gst-plugins-base/gst-libs/gst/video/video-event.c
Line
Count
Source
1
/* GStreamer
2
 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3
 * Library       <2002> Ronald Bultje <rbultje@ronald.bitfreak.net>
4
 * Copyright (C) 2007 David A. Schleef <ds@schleef.org>
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Library General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Library General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Library General Public
17
 * License along with this library; if not, write to the
18
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19
 * Boston, MA 02110-1301, USA.
20
 */
21
#ifdef HAVE_CONFIG_H
22
#include "config.h"
23
#endif
24
25
#include "video-event.h"
26
27
0
#define GST_VIDEO_EVENT_STILL_STATE_NAME "GstEventStillFrame"
28
29
/**
30
 * gst_video_event_new_still_frame:
31
 * @in_still: boolean value for the still-frame state of the event.
32
 *
33
 * Creates a new Still Frame event. If @in_still is %TRUE, then the event
34
 * represents the start of a still frame sequence. If it is %FALSE, then
35
 * the event ends a still frame sequence.
36
 *
37
 * To parse an event created by gst_video_event_new_still_frame() use
38
 * gst_video_event_parse_still_frame().
39
 *
40
 * Returns: The new GstEvent
41
 */
42
GstEvent *
43
gst_video_event_new_still_frame (gboolean in_still)
44
0
{
45
0
  GstEvent *still_event;
46
0
  GstStructure *s;
47
48
0
  s = gst_structure_new (GST_VIDEO_EVENT_STILL_STATE_NAME,
49
0
      "still-state", G_TYPE_BOOLEAN, in_still, NULL);
50
0
  still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
51
52
0
  return still_event;
53
0
}
54
55
/**
56
 * gst_video_event_parse_still_frame:
57
 * @event: A #GstEvent to parse
58
 * @in_still: (out):
59
 *     A boolean to receive the still-frame status from the event, or NULL
60
 *
61
 * Parse a #GstEvent, identify if it is a Still Frame event, and
62
 * return the still-frame state from the event if it is.
63
 * If the event represents the start of a still frame, the in_still
64
 * variable will be set to TRUE, otherwise FALSE. It is OK to pass NULL for the
65
 * in_still variable order to just check whether the event is a valid still-frame
66
 * event.
67
 *
68
 * Create a still frame event using gst_video_event_new_still_frame()
69
 *
70
 * Returns: %TRUE if the event is a valid still-frame event. %FALSE if not
71
 */
72
gboolean
73
gst_video_event_parse_still_frame (GstEvent * event, gboolean * in_still)
74
0
{
75
0
  const GstStructure *s;
76
0
  gboolean ev_still_state;
77
78
0
  g_return_val_if_fail (event != NULL, FALSE);
79
80
0
  if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM)
81
0
    return FALSE;               /* Not a still frame event */
82
83
0
  s = gst_event_get_structure (event);
84
0
  if (s == NULL
85
0
      || !gst_structure_has_name (s, GST_VIDEO_EVENT_STILL_STATE_NAME))
86
0
    return FALSE;               /* Not a still frame event */
87
0
  if (!gst_structure_get_boolean (s, "still-state", &ev_still_state))
88
0
    return FALSE;               /* Not a still frame event */
89
0
  if (in_still)
90
0
    *in_still = ev_still_state;
91
0
  return TRUE;
92
0
}
93
94
0
#define GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME "GstForceKeyUnit"
95
96
/**
97
 * gst_video_event_new_downstream_force_key_unit:
98
 * @timestamp: the timestamp of the buffer that starts a new key unit
99
 * @stream_time: the stream_time of the buffer that starts a new key unit
100
 * @running_time: the running_time of the buffer that starts a new key unit
101
 * @all_headers: %TRUE to produce headers when starting a new key unit
102
 * @count: integer that can be used to number key units
103
 *
104
 * Creates a new downstream force key unit event. A downstream force key unit
105
 * event can be sent down the pipeline to request downstream elements to produce
106
 * a key unit. A downstream force key unit event must also be sent when handling
107
 * an upstream force key unit event to notify downstream that the latter has been
108
 * handled.
109
 *
110
 * To parse an event created by gst_video_event_new_downstream_force_key_unit() use
111
 * gst_video_event_parse_downstream_force_key_unit().
112
 *
113
 * Returns: The new GstEvent
114
 */
115
GstEvent *
116
gst_video_event_new_downstream_force_key_unit (GstClockTime timestamp,
117
    GstClockTime stream_time, GstClockTime running_time, gboolean all_headers,
118
    guint count)
119
0
{
120
0
  GstEvent *force_key_unit_event;
121
0
  GstStructure *s;
122
123
0
  s = gst_structure_new (GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME,
124
0
      "timestamp", G_TYPE_UINT64, timestamp,
125
0
      "stream-time", G_TYPE_UINT64, stream_time,
126
0
      "running-time", G_TYPE_UINT64, running_time,
127
0
      "all-headers", G_TYPE_BOOLEAN, all_headers,
128
0
      "count", G_TYPE_UINT, count, NULL);
129
0
  force_key_unit_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
130
131
0
  return force_key_unit_event;
132
0
}
133
134
/**
135
 * gst_video_event_new_upstream_force_key_unit:
136
 * @running_time: the running_time at which a new key unit should be produced
137
 * @all_headers: %TRUE to produce headers when starting a new key unit
138
 * @count: integer that can be used to number key units
139
 *
140
 * Creates a new upstream force key unit event. An upstream force key unit event
141
 * can be sent to request upstream elements to produce a key unit.
142
 *
143
 * @running_time can be set to request a new key unit at a specific
144
 * running_time. If set to GST_CLOCK_TIME_NONE, upstream elements will produce a
145
 * new key unit as soon as possible.
146
 *
147
 * To parse an event created by gst_video_event_new_downstream_force_key_unit() use
148
 * gst_video_event_parse_downstream_force_key_unit().
149
 *
150
 * Returns: The new GstEvent
151
 */
152
GstEvent *
153
gst_video_event_new_upstream_force_key_unit (GstClockTime running_time,
154
    gboolean all_headers, guint count)
155
0
{
156
0
  GstEvent *force_key_unit_event;
157
0
  GstStructure *s;
158
159
0
  s = gst_structure_new (GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME,
160
0
      "running-time", GST_TYPE_CLOCK_TIME, running_time,
161
0
      "all-headers", G_TYPE_BOOLEAN, all_headers,
162
0
      "count", G_TYPE_UINT, count, NULL);
163
0
  force_key_unit_event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s);
164
165
0
  return force_key_unit_event;
166
0
}
167
168
/**
169
 * gst_video_event_is_force_key_unit:
170
 * @event: A #GstEvent to check
171
 *
172
 * Checks if an event is a force key unit event. Returns true for both upstream
173
 * and downstream force key unit events.
174
 *
175
 * Returns: %TRUE if the event is a valid force key unit event
176
 */
177
gboolean
178
gst_video_event_is_force_key_unit (GstEvent * event)
179
0
{
180
0
  const GstStructure *s;
181
182
0
  g_return_val_if_fail (event != NULL, FALSE);
183
184
0
  if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM &&
185
0
      GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_UPSTREAM)
186
0
    return FALSE;               /* Not a force key unit event */
187
188
0
  s = gst_event_get_structure (event);
189
0
  if (s == NULL
190
0
      || !gst_structure_has_name (s, GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME))
191
0
    return FALSE;
192
193
0
  return TRUE;
194
0
}
195
196
/**
197
 * gst_video_event_parse_downstream_force_key_unit:
198
 * @event: A #GstEvent to parse
199
 * @timestamp: (out): A pointer to the timestamp in the event
200
 * @stream_time: (out): A pointer to the stream-time in the event
201
 * @running_time: (out): A pointer to the running-time in the event
202
 * @all_headers: (out): A pointer to the all_headers flag in the event
203
 * @count: (out): A pointer to the count field of the event
204
 *
205
 * Get timestamp, stream-time, running-time, all-headers and count in the force
206
 * key unit event. See gst_video_event_new_downstream_force_key_unit() for a
207
 * full description of the downstream force key unit event.
208
 *
209
 * @running_time will be adjusted for any pad offsets of pads it was passing through.
210
 *
211
 * Returns: %TRUE if the event is a valid downstream force key unit event.
212
 */
213
gboolean
214
gst_video_event_parse_downstream_force_key_unit (GstEvent * event,
215
    GstClockTime * timestamp, GstClockTime * stream_time,
216
    GstClockTime * running_time, gboolean * all_headers, guint * count)
217
0
{
218
0
  const GstStructure *s;
219
0
  GstClockTime ev_timestamp, ev_stream_time, ev_running_time;
220
0
  gboolean ev_all_headers;
221
0
  guint ev_count;
222
223
0
  g_return_val_if_fail (event != NULL, FALSE);
224
225
0
  if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM)
226
0
    return FALSE;               /* Not a force key unit event */
227
228
0
  s = gst_event_get_structure (event);
229
0
  if (s == NULL
230
0
      || !gst_structure_has_name (s, GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME))
231
0
    return FALSE;
232
233
0
  if (!gst_structure_get_clock_time (s, "timestamp", &ev_timestamp))
234
0
    ev_timestamp = GST_CLOCK_TIME_NONE;
235
0
  if (!gst_structure_get_clock_time (s, "stream-time", &ev_stream_time))
236
0
    ev_stream_time = GST_CLOCK_TIME_NONE;
237
0
  if (!gst_structure_get_clock_time (s, "running-time", &ev_running_time))
238
0
    ev_running_time = GST_CLOCK_TIME_NONE;
239
0
  if (!gst_structure_get_boolean (s, "all-headers", &ev_all_headers))
240
0
    ev_all_headers = FALSE;
241
0
  if (!gst_structure_get_uint (s, "count", &ev_count))
242
0
    ev_count = 0;
243
244
0
  if (timestamp)
245
0
    *timestamp = ev_timestamp;
246
247
0
  if (stream_time)
248
0
    *stream_time = ev_stream_time;
249
250
0
  if (running_time) {
251
0
    gint64 offset = gst_event_get_running_time_offset (event);
252
253
0
    *running_time = ev_running_time;
254
    /* Catch underflows */
255
0
    if (*running_time > -offset)
256
0
      *running_time += offset;
257
0
    else
258
0
      *running_time = 0;
259
0
  }
260
261
0
  if (all_headers)
262
0
    *all_headers = ev_all_headers;
263
264
0
  if (count)
265
0
    *count = ev_count;
266
267
0
  return TRUE;
268
0
}
269
270
/**
271
 * gst_video_event_parse_upstream_force_key_unit:
272
 * @event: A #GstEvent to parse
273
 * @running_time: (out): A pointer to the running_time in the event
274
 * @all_headers: (out): A pointer to the all_headers flag in the event
275
 * @count: (out): A pointer to the count field in the event
276
 *
277
 * Get running-time, all-headers and count in the force key unit event. See
278
 * gst_video_event_new_upstream_force_key_unit() for a full description of the
279
 * upstream force key unit event.
280
 *
281
 * Create an upstream force key unit event using  gst_video_event_new_upstream_force_key_unit()
282
 *
283
 * @running_time will be adjusted for any pad offsets of pads it was passing through.
284
 *
285
 * Returns: %TRUE if the event is a valid upstream force-key-unit event. %FALSE if not
286
 */
287
gboolean
288
gst_video_event_parse_upstream_force_key_unit (GstEvent * event,
289
    GstClockTime * running_time, gboolean * all_headers, guint * count)
290
0
{
291
0
  const GstStructure *s;
292
0
  GstClockTime ev_running_time;
293
0
  gboolean ev_all_headers;
294
0
  guint ev_count;
295
296
0
  g_return_val_if_fail (event != NULL, FALSE);
297
298
0
  if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_UPSTREAM)
299
0
    return FALSE;               /* Not a force key unit event */
300
301
0
  s = gst_event_get_structure (event);
302
0
  if (s == NULL
303
0
      || !gst_structure_has_name (s, GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME))
304
0
    return FALSE;
305
306
0
  if (!gst_structure_get_clock_time (s, "running-time", &ev_running_time))
307
0
    ev_running_time = GST_CLOCK_TIME_NONE;
308
0
  if (!gst_structure_get_boolean (s, "all-headers", &ev_all_headers))
309
0
    ev_all_headers = FALSE;
310
0
  if (!gst_structure_get_uint (s, "count", &ev_count))
311
0
    ev_count = 0;
312
313
314
0
  if (running_time) {
315
0
    gint64 offset = gst_event_get_running_time_offset (event);
316
317
0
    *running_time = ev_running_time;
318
    /* Catch underflows */
319
0
    if (*running_time > -offset)
320
0
      *running_time += offset;
321
0
    else
322
0
      *running_time = 0;
323
0
  }
324
325
0
  if (all_headers)
326
0
    *all_headers = ev_all_headers;
327
328
0
  if (count)
329
0
    *count = ev_count;
330
331
0
  return TRUE;
332
0
}