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 #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 *
gst_video_event_new_still_frame(gboolean in_still)43 gst_video_event_new_still_frame (gboolean in_still)
44 {
45 GstEvent *still_event;
46 GstStructure *s;
47
48 s = gst_structure_new (GST_VIDEO_EVENT_STILL_STATE_NAME,
49 "still-state", G_TYPE_BOOLEAN, in_still, NULL);
50 still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
51
52 return still_event;
53 }
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
gst_video_event_parse_still_frame(GstEvent * event,gboolean * in_still)73 gst_video_event_parse_still_frame (GstEvent * event, gboolean * in_still)
74 {
75 const GstStructure *s;
76 gboolean ev_still_state;
77
78 g_return_val_if_fail (event != NULL, FALSE);
79
80 if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM)
81 return FALSE; /* Not a still frame event */
82
83 s = gst_event_get_structure (event);
84 if (s == NULL
85 || !gst_structure_has_name (s, GST_VIDEO_EVENT_STILL_STATE_NAME))
86 return FALSE; /* Not a still frame event */
87 if (!gst_structure_get_boolean (s, "still-state", &ev_still_state))
88 return FALSE; /* Not a still frame event */
89 if (in_still)
90 *in_still = ev_still_state;
91 return TRUE;
92 }
93
94 #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 *
gst_video_event_new_downstream_force_key_unit(GstClockTime timestamp,GstClockTime stream_time,GstClockTime running_time,gboolean all_headers,guint count)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 {
120 GstEvent *force_key_unit_event;
121 GstStructure *s;
122
123 s = gst_structure_new (GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME,
124 "timestamp", G_TYPE_UINT64, timestamp,
125 "stream-time", G_TYPE_UINT64, stream_time,
126 "running-time", G_TYPE_UINT64, running_time,
127 "all-headers", G_TYPE_BOOLEAN, all_headers,
128 "count", G_TYPE_UINT, count, NULL);
129 force_key_unit_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s);
130
131 return force_key_unit_event;
132 }
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 *
gst_video_event_new_upstream_force_key_unit(GstClockTime running_time,gboolean all_headers,guint count)153 gst_video_event_new_upstream_force_key_unit (GstClockTime running_time,
154 gboolean all_headers, guint count)
155 {
156 GstEvent *force_key_unit_event;
157 GstStructure *s;
158
159 s = gst_structure_new (GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME,
160 "running-time", GST_TYPE_CLOCK_TIME, running_time,
161 "all-headers", G_TYPE_BOOLEAN, all_headers,
162 "count", G_TYPE_UINT, count, NULL);
163 force_key_unit_event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, s);
164
165 return force_key_unit_event;
166 }
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
gst_video_event_is_force_key_unit(GstEvent * event)178 gst_video_event_is_force_key_unit (GstEvent * event)
179 {
180 const GstStructure *s;
181
182 g_return_val_if_fail (event != NULL, FALSE);
183
184 if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM &&
185 GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_UPSTREAM)
186 return FALSE; /* Not a force key unit event */
187
188 s = gst_event_get_structure (event);
189 if (s == NULL
190 || !gst_structure_has_name (s, GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME))
191 return FALSE;
192
193 return TRUE;
194 }
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
gst_video_event_parse_downstream_force_key_unit(GstEvent * event,GstClockTime * timestamp,GstClockTime * stream_time,GstClockTime * running_time,gboolean * all_headers,guint * count)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 {
218 const GstStructure *s;
219 GstClockTime ev_timestamp, ev_stream_time, ev_running_time;
220 gboolean ev_all_headers;
221 guint ev_count;
222
223 g_return_val_if_fail (event != NULL, FALSE);
224
225 if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM)
226 return FALSE; /* Not a force key unit event */
227
228 s = gst_event_get_structure (event);
229 if (s == NULL
230 || !gst_structure_has_name (s, GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME))
231 return FALSE;
232
233 if (!gst_structure_get_clock_time (s, "timestamp", &ev_timestamp))
234 ev_timestamp = GST_CLOCK_TIME_NONE;
235 if (!gst_structure_get_clock_time (s, "stream-time", &ev_stream_time))
236 ev_stream_time = GST_CLOCK_TIME_NONE;
237 if (!gst_structure_get_clock_time (s, "running-time", &ev_running_time))
238 ev_running_time = GST_CLOCK_TIME_NONE;
239 if (!gst_structure_get_boolean (s, "all-headers", &ev_all_headers))
240 ev_all_headers = FALSE;
241 if (!gst_structure_get_uint (s, "count", &ev_count))
242 ev_count = 0;
243
244 if (timestamp)
245 *timestamp = ev_timestamp;
246
247 if (stream_time)
248 *stream_time = ev_stream_time;
249
250 if (running_time) {
251 gint64 offset = gst_event_get_running_time_offset (event);
252
253 *running_time = ev_running_time;
254 /* Catch underflows */
255 if (*running_time > -offset)
256 *running_time += offset;
257 else
258 *running_time = 0;
259 }
260
261 if (all_headers)
262 *all_headers = ev_all_headers;
263
264 if (count)
265 *count = ev_count;
266
267 return TRUE;
268 }
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
gst_video_event_parse_upstream_force_key_unit(GstEvent * event,GstClockTime * running_time,gboolean * all_headers,guint * count)288 gst_video_event_parse_upstream_force_key_unit (GstEvent * event,
289 GstClockTime * running_time, gboolean * all_headers, guint * count)
290 {
291 const GstStructure *s;
292 GstClockTime ev_running_time;
293 gboolean ev_all_headers;
294 guint ev_count;
295
296 g_return_val_if_fail (event != NULL, FALSE);
297
298 if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_UPSTREAM)
299 return FALSE; /* Not a force key unit event */
300
301 s = gst_event_get_structure (event);
302 if (s == NULL
303 || !gst_structure_has_name (s, GST_VIDEO_EVENT_FORCE_KEY_UNIT_NAME))
304 return FALSE;
305
306 if (!gst_structure_get_clock_time (s, "running-time", &ev_running_time))
307 ev_running_time = GST_CLOCK_TIME_NONE;
308 if (!gst_structure_get_boolean (s, "all-headers", &ev_all_headers))
309 ev_all_headers = FALSE;
310 if (!gst_structure_get_uint (s, "count", &ev_count))
311 ev_count = 0;
312
313
314 if (running_time) {
315 gint64 offset = gst_event_get_running_time_offset (event);
316
317 *running_time = ev_running_time;
318 /* Catch underflows */
319 if (*running_time > -offset)
320 *running_time += offset;
321 else
322 *running_time = 0;
323 }
324
325 if (all_headers)
326 *all_headers = ev_all_headers;
327
328 if (count)
329 *count = ev_count;
330
331 return TRUE;
332 }
333