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