• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) <2016> Carlos Rafael Giani <dv at pseudoterminal dot org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 /**
21  * SECTION:gstrawbaseparse
22  * @short_description: Base class for raw media data parsers
23  *
24  * This base class is for parsers which read raw media data and output
25  * timestamped buffers with an integer number of frames inside.
26  *
27  * The format of the raw media data is specified in one of two ways: either,
28  * the information from the sink pad's caps is taken, or the information from
29  * the properties is used (this is chosen by the use-sink-caps property).
30  * These two ways are internally referred to as "configurations". The configuration
31  * that receives its information from the sink pad's caps is called the
32  * "sink caps configuration", while the one that depends on the information from
33  * the properties is the "properties configuration". Configurations have a
34  * "readiness". A configuration is "ready" when it contains valid information.
35  * For example, with an audio parser, a configuration is not ready unless it
36  * contains a valid sample rate, sample format, and channel count.
37  *
38  * The properties configuration must always be ready, even right from the start.
39  * Subclasses must ensure this. The underlying reason is that properties have valid
40  * values right from the start, and with the properties configuration, there is
41  * nothing that readies it before actual data is sent (unlike with the sink caps
42  * configuration, where a sink caps event will ready it before data is pushed
43  * downstream).
44  *
45  * It is possible to switch between the configurations during a stream by
46  * setting the use-sink-caps property. Subclasses typically allow for updating the
47  * properties configuration during a stream by setting the various properties
48  * (like sample-rate for a raw audio parser).
49  * In these cases, the parser will produce a new CAPS event and push it downstream
50  * to announce the caps for the new configuration. This also happens if the sink
51  * caps change.
52  *
53  * A common mistake when trying to parse raw data with no input caps (for example,
54  * a file with raw PCM samples when using rawaudioparse) is to forget to set the
55  * use-sink-caps property to FALSE. In this case, the parser will report an error
56  * when it tries to access the current configuration (because then the sink caps
57  * configuration will be the current one and it will not contain valid values
58  * since no sink caps were seen at this point).
59  *
60  * Subclasses must ensure that the properties configuration is the default one.
61  *
62  * The sink caps configuration is mostly useful with push-based sources, because these
63  * will produce caps events and send them downstream. With pull-based sources, it is
64  * possible that this doesn't happen. Since the sink caps configuration requires a caps
65  * event to arrive at the sinkpad, this will cause the parser to fail then.
66  *
67  * The base class identifies the configurations by means of the GstRawAudioParseConfig
68  * enum. It instructs the subclass to switch between configurations this way, and
69  * also requests information about the current configuration, a configuration's
70  * frame size, its readiness, etc. Subclasses are not required to use any particular
71  * structure for the configuration implementations.
72  *
73  * Use the GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK and GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK
74  * macros to protect configuration modifications.
75  *
76  * ## Summary of the subclass requirements
77  *
78  * * Sink caps and properties configurations must both be
79  *   implemented and supported. It must also be ensured that there is a
80  *   "current" configuration.
81  *
82  * * Modifications to the configurations must be protected with the
83  *   GstRawBaseParse lock. This is typically necessary when the
84  *   properties configuration is modified by setting new property values.
85  *   (Note that the lock is held during *all* vfunc calls.)
86  *
87  * * If the properties configuration is updated (typically by
88  *   setting new property values), gst_raw_base_parse_invalidate_src_caps()
89  *   must be called if the properties config is the current one. This is
90  *   necessary to ensure that GstBaseParse pushes a new caps event downstream
91  *   which contains caps from the updated configuration.
92  *
93  * * In case there are bytes in each frame that aren't part of the actual
94  *   payload, the `get_overhead_size()` vfunc must be defined, and the
95  *   `get_config_frame_size()` vfunc must return a frame size that includes
96  *   the number of non-payload bytes (= the overhead). Otherwise, the
97  *   timestamps will incorrectly include the overhead bytes.
98  */
99 
100 #ifdef HAVE_CONFIG_H
101 #  include "config.h"
102 #endif
103 
104 #include <string.h>
105 #include "gstrawbaseparse.h"
106 
107 GST_DEBUG_CATEGORY_STATIC (raw_base_parse_debug);
108 #define GST_CAT_DEFAULT raw_base_parse_debug
109 
110 enum
111 {
112   PROP_0,
113   PROP_USE_SINK_CAPS
114 };
115 
116 #define DEFAULT_USE_SINK_CAPS  FALSE
117 #define INITIAL_PARSER_CONFIG \
118   ((DEFAULT_USE_SINK_CAPS) ? GST_RAW_BASE_PARSE_CONFIG_SINKCAPS : \
119    GST_RAW_BASE_PARSE_CONFIG_PROPERTIES)
120 
121 #define gst_raw_base_parse_parent_class parent_class
122 G_DEFINE_ABSTRACT_TYPE (GstRawBaseParse, gst_raw_base_parse,
123     GST_TYPE_BASE_PARSE);
124 
125 static void gst_raw_base_parse_finalize (GObject * object);
126 static void gst_raw_base_parse_set_property (GObject * object, guint prop_id,
127     GValue const *value, GParamSpec * pspec);
128 static void gst_raw_base_parse_get_property (GObject * object, guint prop_id,
129     GValue * value, GParamSpec * pspec);
130 static gboolean gst_raw_base_parse_start (GstBaseParse * parse);
131 static gboolean gst_raw_base_parse_stop (GstBaseParse * parse);
132 static gboolean gst_raw_base_parse_set_sink_caps (GstBaseParse * parse,
133     GstCaps * caps);
134 static GstFlowReturn gst_raw_base_parse_handle_frame (GstBaseParse * parse,
135     GstBaseParseFrame * frame, gint * skipsize);
136 static gboolean gst_raw_base_parse_convert (GstBaseParse * parse,
137     GstFormat src_format, gint64 src_value, GstFormat dest_format,
138     gint64 * dest_value);
139 
140 static gboolean gst_raw_base_parse_is_using_sink_caps (GstRawBaseParse *
141     raw_base_parse);
142 static gboolean gst_raw_base_parse_is_gstformat_supported (GstRawBaseParse *
143     raw_base_parse, GstFormat format);
144 
145 static void
gst_raw_base_parse_class_init(GstRawBaseParseClass * klass)146 gst_raw_base_parse_class_init (GstRawBaseParseClass * klass)
147 {
148   GObjectClass *object_class;
149   GstBaseParseClass *baseparse_class;
150 
151   GST_DEBUG_CATEGORY_INIT (raw_base_parse_debug, "rawbaseparse", 0,
152       "raw base parse class");
153 
154   object_class = G_OBJECT_CLASS (klass);
155   baseparse_class = GST_BASE_PARSE_CLASS (klass);
156 
157   object_class->finalize = GST_DEBUG_FUNCPTR (gst_raw_base_parse_finalize);
158   object_class->set_property =
159       GST_DEBUG_FUNCPTR (gst_raw_base_parse_set_property);
160   object_class->get_property =
161       GST_DEBUG_FUNCPTR (gst_raw_base_parse_get_property);
162 
163   baseparse_class->start = GST_DEBUG_FUNCPTR (gst_raw_base_parse_start);
164   baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_raw_base_parse_stop);
165   baseparse_class->set_sink_caps =
166       GST_DEBUG_FUNCPTR (gst_raw_base_parse_set_sink_caps);
167   baseparse_class->handle_frame =
168       GST_DEBUG_FUNCPTR (gst_raw_base_parse_handle_frame);
169   baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_raw_base_parse_convert);
170 
171   /**
172    * GstRawBaseParse::use-sink-caps:
173    *
174    * Use sink caps configuration. If set to false, the parser
175    * will use the properties configuration instead. It is possible
176    * to switch between these during playback.
177    */
178   g_object_class_install_property (object_class,
179       PROP_USE_SINK_CAPS,
180       g_param_spec_boolean ("use-sink-caps",
181           "Use sink caps",
182           "Use the sink caps for defining the output format",
183           DEFAULT_USE_SINK_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
184       );
185 
186   gst_type_mark_as_plugin_api (GST_TYPE_RAW_BASE_PARSE, 0);
187 }
188 
189 static void
gst_raw_base_parse_init(GstRawBaseParse * raw_base_parse)190 gst_raw_base_parse_init (GstRawBaseParse * raw_base_parse)
191 {
192   raw_base_parse->src_caps_set = FALSE;
193   g_mutex_init (&(raw_base_parse->config_mutex));
194 }
195 
196 static void
gst_raw_base_parse_finalize(GObject * object)197 gst_raw_base_parse_finalize (GObject * object)
198 {
199   GstRawBaseParse *raw_base_parse = GST_RAW_BASE_PARSE (object);
200 
201   g_mutex_clear (&(raw_base_parse->config_mutex));
202 
203   G_OBJECT_CLASS (parent_class)->finalize (object);
204 }
205 
206 static void
gst_raw_base_parse_set_property(GObject * object,guint prop_id,GValue const * value,GParamSpec * pspec)207 gst_raw_base_parse_set_property (GObject * object, guint prop_id,
208     GValue const *value, GParamSpec * pspec)
209 {
210   GstBaseParse *base_parse = GST_BASE_PARSE (object);
211   GstRawBaseParse *raw_base_parse = GST_RAW_BASE_PARSE (object);
212   GstRawBaseParseClass *klass = GST_RAW_BASE_PARSE_GET_CLASS (object);
213 
214   g_assert (klass->is_config_ready);
215   g_assert (klass->set_current_config);
216 
217   switch (prop_id) {
218     case PROP_USE_SINK_CAPS:
219     {
220       gboolean new_state, cur_state;
221       GstRawBaseParseConfig new_config;
222 
223       GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
224 
225       /* Check to ensure nothing is done if the value stays the same */
226       new_state = g_value_get_boolean (value);
227       cur_state = gst_raw_base_parse_is_using_sink_caps (raw_base_parse);
228       if (new_state == cur_state) {
229         GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
230         break;
231       }
232 
233       GST_DEBUG_OBJECT (raw_base_parse, "switching to %s config",
234           new_state ? "sink caps" : "properties");
235       new_config =
236           new_state ? GST_RAW_BASE_PARSE_CONFIG_SINKCAPS :
237           GST_RAW_BASE_PARSE_CONFIG_PROPERTIES;
238 
239       if (!klass->set_current_config (raw_base_parse, new_config)) {
240         GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
241         GST_ELEMENT_ERROR (raw_base_parse, STREAM, FAILED,
242             ("could not set new current config"), ("use-sink-caps property: %d",
243                 new_state));
244         break;
245       }
246 
247       /* Update the minimum frame size if the config is ready. This ensures that
248        * the next buffer that is passed to handle_frame contains complete frames.
249        * If the current config is the properties config, then it will always be
250        * ready, and its frame size will be valid. Ensure that the baseparse minimum
251        * frame size is set properly then.
252        * If the current config is the sink caps config, then it will initially not
253        * be ready until the sink caps are set, so the minimum frame size cannot be
254        * set right here. However, since the caps always come in *before* the actual
255        * data, the config will be readied in the set_sink_caps function, and be ready
256        * by the time handle_frame is called. There, the minimum frame size is set as
257        * well. */
258       if (klass->is_config_ready (raw_base_parse,
259               GST_RAW_BASE_PARSE_CONFIG_CURRENT)) {
260         gsize frame_size = klass->get_config_frame_size (raw_base_parse,
261             GST_RAW_BASE_PARSE_CONFIG_CURRENT);
262         gst_base_parse_set_min_frame_size (base_parse, frame_size);
263       }
264 
265       /* Since the current config was switched, the source caps change. Ensure the
266        * new caps are pushed downstream by setting src_caps_set to FALSE: This way,
267        * the next handle_frame call will take care of that. */
268       raw_base_parse->src_caps_set = FALSE;
269 
270       GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
271 
272       break;
273     }
274 
275     default:
276       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
277       break;
278   }
279 }
280 
281 static void
gst_raw_base_parse_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)282 gst_raw_base_parse_get_property (GObject * object, guint prop_id,
283     GValue * value, GParamSpec * pspec)
284 {
285   GstRawBaseParse *raw_base_parse = GST_RAW_BASE_PARSE (object);
286 
287   switch (prop_id) {
288     case PROP_USE_SINK_CAPS:
289       GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (object);
290       g_value_set_boolean (value,
291           gst_raw_base_parse_is_using_sink_caps (raw_base_parse));
292       GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (object);
293       break;
294 
295     default:
296       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
297       break;
298   }
299 }
300 
301 static gboolean
gst_raw_base_parse_start(GstBaseParse * parse)302 gst_raw_base_parse_start (GstBaseParse * parse)
303 {
304   GstBaseParse *base_parse = GST_BASE_PARSE (parse);
305   GstRawBaseParse *raw_base_parse = GST_RAW_BASE_PARSE (parse);
306   GstRawBaseParseClass *klass = GST_RAW_BASE_PARSE_GET_CLASS (parse);
307 
308   g_assert (klass->set_current_config);
309 
310   GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (raw_base_parse);
311 
312   /* If the config is ready from the start, set the min frame size
313    * (this will happen with the properties config) */
314   if (klass->is_config_ready (raw_base_parse,
315           GST_RAW_BASE_PARSE_CONFIG_CURRENT)) {
316     gsize frame_size = klass->get_config_frame_size (raw_base_parse,
317         GST_RAW_BASE_PARSE_CONFIG_CURRENT);
318     gst_base_parse_set_min_frame_size (base_parse, frame_size);
319   }
320 
321   GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (raw_base_parse);
322 
323   return TRUE;
324 }
325 
326 static gboolean
gst_raw_base_parse_stop(GstBaseParse * parse)327 gst_raw_base_parse_stop (GstBaseParse * parse)
328 {
329   GstRawBaseParse *raw_base_parse = GST_RAW_BASE_PARSE (parse);
330 
331   GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (raw_base_parse);
332   raw_base_parse->src_caps_set = FALSE;
333   GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (raw_base_parse);
334 
335   return TRUE;
336 }
337 
338 static gboolean
gst_raw_base_parse_set_sink_caps(GstBaseParse * parse,GstCaps * caps)339 gst_raw_base_parse_set_sink_caps (GstBaseParse * parse, GstCaps * caps)
340 {
341   gboolean ret = FALSE;
342   GstRawBaseParse *raw_base_parse = GST_RAW_BASE_PARSE (parse);
343   GstRawBaseParseClass *klass = GST_RAW_BASE_PARSE_GET_CLASS (parse);
344 
345   g_assert (klass->set_config_from_caps);
346   g_assert (klass->get_caps_from_config);
347   g_assert (klass->get_config_frame_size);
348 
349   GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (raw_base_parse);
350 
351   GST_DEBUG_OBJECT (parse, "getting config from new sink caps");
352 
353   /* Convert the new sink caps to sink caps config. This also
354    * readies the config. */
355   ret =
356       klass->set_config_from_caps (raw_base_parse,
357       GST_RAW_BASE_PARSE_CONFIG_SINKCAPS, caps);
358   if (!ret) {
359     GST_ERROR_OBJECT (raw_base_parse, "could not get config from sink caps");
360     goto done;
361   }
362 
363   /* If the sink caps config is currently active, push caps downstream,
364    * set the minimum frame size (to guarantee that input buffers hold
365    * complete frames), and update the src_caps_set flag. If the sink
366    * caps config isn't the currently active config, just exit, since in
367    * that case, the caps will always be pushed downstream in handle_frame. */
368   if (gst_raw_base_parse_is_using_sink_caps (raw_base_parse)) {
369     GstCaps *new_src_caps;
370     gsize frame_size;
371 
372     GST_DEBUG_OBJECT (parse,
373         "sink caps config is the current one; trying to push new caps downstream");
374 
375     /* Convert back to caps. The caps may have changed, for example
376      * audio/x-unaligned-raw may have been replaced with audio/x-raw.
377      * (Also, this keeps the behavior in sync with that of the block
378      * in handle_frame that pushes caps downstream if not done already.) */
379     if (!klass->get_caps_from_config (raw_base_parse,
380             GST_RAW_BASE_PARSE_CONFIG_CURRENT, &new_src_caps)) {
381       GST_ERROR_OBJECT (raw_base_parse,
382           "could not get src caps from current config");
383       goto done;
384     }
385 
386     GST_DEBUG_OBJECT (raw_base_parse,
387         "got new sink caps; updating src caps to %" GST_PTR_FORMAT,
388         (gpointer) new_src_caps);
389 
390     frame_size =
391         klass->get_config_frame_size (raw_base_parse,
392         GST_RAW_BASE_PARSE_CONFIG_CURRENT);
393     gst_base_parse_set_min_frame_size (parse, frame_size);
394 
395     raw_base_parse->src_caps_set = TRUE;
396 
397     GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (raw_base_parse);
398 
399     /* Push caps outside of the lock */
400     gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (raw_base_parse),
401         gst_event_new_caps (new_src_caps)
402         );
403 
404     gst_caps_unref (new_src_caps);
405   } else {
406     GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (raw_base_parse);
407   }
408 
409   ret = TRUE;
410 
411 done:
412   return ret;
413 }
414 
415 static GstBuffer *
gst_raw_base_parse_align_buffer(GstRawBaseParse * raw_base_parse,gsize alignment,GstBuffer * buffer,gsize out_size)416 gst_raw_base_parse_align_buffer (GstRawBaseParse * raw_base_parse,
417     gsize alignment, GstBuffer * buffer, gsize out_size)
418 {
419   GstMapInfo map;
420 
421   gst_buffer_map (buffer, &map, GST_MAP_READ);
422 
423   if (map.size < sizeof (guintptr)) {
424     gst_buffer_unmap (buffer, &map);
425     return NULL;
426   }
427 
428   if (((guintptr) map.data) & (alignment - 1)) {
429     GstBuffer *new_buffer;
430     GstAllocationParams params = { 0, alignment - 1, 0, 0, };
431 
432     new_buffer = gst_buffer_new_allocate (NULL, out_size, &params);
433 
434     /* Copy data "by hand", so ensure alignment is kept: */
435     gst_buffer_fill (new_buffer, 0, map.data, out_size);
436 
437     gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0,
438         out_size);
439     GST_DEBUG_OBJECT (raw_base_parse,
440         "We want output aligned on %" G_GSIZE_FORMAT ", reallocated",
441         alignment);
442 
443     gst_buffer_unmap (buffer, &map);
444 
445     return new_buffer;
446   }
447 
448   gst_buffer_unmap (buffer, &map);
449 
450   return NULL;
451 }
452 
453 static GstFlowReturn
gst_raw_base_parse_handle_frame(GstBaseParse * parse,GstBaseParseFrame * frame,gint * skipsize)454 gst_raw_base_parse_handle_frame (GstBaseParse * parse,
455     GstBaseParseFrame * frame, gint * skipsize)
456 {
457   gsize in_size, out_size;
458   guint frame_size;
459   guint num_out_frames;
460   gsize units_n, units_d;
461   guint64 buffer_duration;
462   GstFlowReturn flow_ret = GST_FLOW_OK;
463   GstEvent *new_caps_event = NULL;
464   gint alignment;
465   GstRawBaseParse *raw_base_parse = GST_RAW_BASE_PARSE (parse);
466   GstRawBaseParseClass *klass = GST_RAW_BASE_PARSE_GET_CLASS (parse);
467 
468   g_assert (klass->is_config_ready);
469   g_assert (klass->get_caps_from_config);
470   g_assert (klass->get_config_frame_size);
471   g_assert (klass->get_units_per_second);
472 
473   /* We never skip any bytes this way. Instead, subclass takes care
474    * of skipping any overhead (necessary, since the way it needs to
475    * be skipped is completely subclass specific). */
476   *skipsize = 0;
477 
478   /* The operations below access the current config. Protect
479    * against race conditions by using the object lock. */
480   GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (raw_base_parse);
481 
482   /* If the source pad caps haven't been set yet, or need to be
483    * set again, do so now, BEFORE any buffers are pushed out */
484   if (G_UNLIKELY (!raw_base_parse->src_caps_set)) {
485     GstCaps *new_src_caps;
486 
487     if (G_UNLIKELY (!klass->is_config_ready (raw_base_parse,
488                 GST_RAW_BASE_PARSE_CONFIG_CURRENT))) {
489       /* The current configuration is not ready. No caps can be
490        * generated out of it.
491        * The most likely reason for this is that the sink caps config
492        * is the current one and no valid sink caps have been pushed
493        * by upstream. Report the problem and exit. */
494 
495       if (gst_raw_base_parse_is_using_sink_caps (raw_base_parse)) {
496         goto config_not_ready;
497       } else {
498         /* This should not be reached if the property config is active */
499         g_assert_not_reached ();
500       }
501     }
502 
503     GST_DEBUG_OBJECT (parse,
504         "setting src caps since this has not been done yet");
505 
506     /* Convert the current config to a caps structure to
507      * inform downstream about the new format */
508     if (!klass->get_caps_from_config (raw_base_parse,
509             GST_RAW_BASE_PARSE_CONFIG_CURRENT, &new_src_caps)) {
510       GST_ERROR_OBJECT (raw_base_parse,
511           "could not get src caps from current config");
512       flow_ret = GST_FLOW_NOT_NEGOTIATED;
513       goto error_locked;
514     }
515 
516     new_caps_event = gst_event_new_caps (new_src_caps);
517     gst_caps_unref (new_src_caps);
518 
519     raw_base_parse->src_caps_set = TRUE;
520   }
521 
522   frame_size =
523       klass->get_config_frame_size (raw_base_parse,
524       GST_RAW_BASE_PARSE_CONFIG_CURRENT);
525   if (frame_size <= 0) {
526     GST_ELEMENT_ERROR (parse, STREAM, FORMAT,
527         ("Non strictly positive frame size"), (NULL));
528     flow_ret = GST_FLOW_ERROR;
529     goto error_locked;
530   }
531 
532   in_size = gst_buffer_get_size (frame->buffer);
533 
534   /* drop incomplete frame at the end of the stream
535    * https://bugzilla.gnome.org/show_bug.cgi?id=773666
536    */
537   if (GST_BASE_PARSE_DRAINING (parse) && in_size < frame_size) {
538     GST_DEBUG_OBJECT (raw_base_parse,
539         "Dropping %" G_GSIZE_FORMAT " bytes at EOS", in_size);
540     frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
541     GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (raw_base_parse);
542 
543     return gst_base_parse_finish_frame (parse, frame, in_size);
544   }
545 
546   /* gst_base_parse_set_min_frame_size() is called when the current
547    * configuration changes and the change affects the frame size. This
548    * means that a buffer must contain at least as many bytes as indicated
549    * by the frame size. If there are fewer inside an error occurred;
550    * either something in the parser went wrong, or the min frame size
551    * wasn't updated properly. */
552   g_assert (in_size >= frame_size);
553 
554   /* Determine how many complete frames would fit in the input buffer.
555    * Then check if this amount exceeds the maximum number of frames
556    * as indicated by the subclass. */
557   num_out_frames = (in_size / frame_size);
558   if (klass->get_max_frames_per_buffer) {
559     guint max_num_out_frames = klass->get_max_frames_per_buffer (raw_base_parse,
560         GST_RAW_BASE_PARSE_CONFIG_CURRENT);
561     num_out_frames = MIN (num_out_frames, max_num_out_frames);
562   }
563 
564   /* Ensure that the size of the buffers that get pushed downstream
565    * is always an integer multiple of the frame size to prevent cases
566    * where downstream gets buffers with incomplete frames. */
567   out_size = num_out_frames * frame_size;
568 
569   /* Set the overhead size to ensure that timestamping excludes these
570    * extra overhead bytes. */
571   frame->overhead =
572       klass->get_overhead_size ? klass->get_overhead_size (raw_base_parse,
573       GST_RAW_BASE_PARSE_CONFIG_CURRENT) : 0;
574 
575   g_assert (out_size >= (guint) (frame->overhead));
576   out_size -= frame->overhead;
577 
578   GST_LOG_OBJECT (raw_base_parse,
579       "%" G_GSIZE_FORMAT " bytes input  %" G_GSIZE_FORMAT
580       " bytes output (%u frame(s))  %d bytes overhead", in_size, out_size,
581       num_out_frames, frame->overhead);
582 
583   /* Calculate buffer duration */
584   klass->get_units_per_second (raw_base_parse, GST_FORMAT_BYTES,
585       GST_RAW_BASE_PARSE_CONFIG_CURRENT, &units_n, &units_d);
586   if (units_n == 0 || units_d == 0)
587     buffer_duration = GST_CLOCK_TIME_NONE;
588   else
589     buffer_duration =
590         gst_util_uint64_scale (out_size, GST_SECOND * units_d, units_n);
591 
592   if (klass->process) {
593     GstBuffer *processed_data = NULL;
594 
595     if (!klass->process (raw_base_parse, GST_RAW_BASE_PARSE_CONFIG_CURRENT,
596             frame->buffer, in_size, out_size, &processed_data))
597       goto process_error;
598 
599     frame->out_buffer = processed_data;
600   } else {
601     frame->out_buffer = NULL;
602   }
603 
604   if (klass->get_alignment
605       && (alignment =
606           klass->get_alignment (raw_base_parse,
607               GST_RAW_BASE_PARSE_CONFIG_CURRENT)) != 1) {
608     GstBuffer *aligned_buffer;
609 
610     aligned_buffer =
611         gst_raw_base_parse_align_buffer (raw_base_parse, alignment,
612         frame->out_buffer ? frame->out_buffer : frame->buffer, out_size);
613 
614     if (aligned_buffer) {
615       if (frame->out_buffer)
616         gst_buffer_unref (frame->out_buffer);
617       frame->out_buffer = aligned_buffer;
618     }
619   }
620 
621   /* Set the duration of the output buffer, or if none exists, of
622    * the input buffer. Do this after the process() call, since in
623    * case out_buffer is set, the subclass has created a new buffer.
624    * Instead of requiring subclasses to set the duration (which
625    * anyway must always be buffer_duration), let's do it here. */
626   if (frame->out_buffer != NULL)
627     GST_BUFFER_DURATION (frame->out_buffer) = buffer_duration;
628   else
629     GST_BUFFER_DURATION (frame->buffer) = buffer_duration;
630 
631   /* Access to the current config is not needed in subsequent
632    * operations, so the lock can be released */
633   GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (raw_base_parse);
634 
635   /* If any new caps have to be pushed downstrean, do so
636    * *before* the frame is finished */
637   if (G_UNLIKELY (new_caps_event != NULL)) {
638     gst_pad_push_event (GST_BASE_PARSE_SRC_PAD (raw_base_parse),
639         new_caps_event);
640     new_caps_event = NULL;
641   }
642 
643   flow_ret =
644       gst_base_parse_finish_frame (parse, frame, out_size + frame->overhead);
645 
646   return flow_ret;
647 
648 config_not_ready:
649   GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (raw_base_parse);
650   GST_ELEMENT_ERROR (parse, STREAM, FORMAT,
651       ("sink caps config is the current config, and it is not ready -"
652           "upstream may not have pushed a caps event yet"), (NULL));
653   flow_ret = GST_FLOW_ERROR;
654   goto error_end;
655 
656 process_error:
657   GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (raw_base_parse);
658   GST_ELEMENT_ERROR (parse, STREAM, DECODE, ("could not process data"), (NULL));
659   flow_ret = GST_FLOW_ERROR;
660   goto error_end;
661 
662 error_locked:
663   GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (raw_base_parse);
664   goto error_end;
665 
666 error_end:
667   frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
668   if (new_caps_event != NULL)
669     gst_event_unref (new_caps_event);
670   return flow_ret;
671 }
672 
673 static gboolean
gst_raw_base_parse_convert(GstBaseParse * parse,GstFormat src_format,gint64 src_value,GstFormat dest_format,gint64 * dest_value)674 gst_raw_base_parse_convert (GstBaseParse * parse, GstFormat src_format,
675     gint64 src_value, GstFormat dest_format, gint64 * dest_value)
676 {
677   GstRawBaseParse *raw_base_parse = GST_RAW_BASE_PARSE (parse);
678   GstRawBaseParseClass *klass = GST_RAW_BASE_PARSE_GET_CLASS (parse);
679   gboolean ret = TRUE;
680   gsize units_n, units_d;
681 
682   g_assert (klass->is_config_ready);
683   g_assert (klass->get_units_per_second);
684 
685   /* The operations below access the current config. Protect
686    * against race conditions by using the object lock. */
687   GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK (raw_base_parse);
688 
689   if (!klass->is_config_ready (raw_base_parse,
690           GST_RAW_BASE_PARSE_CONFIG_CURRENT)) {
691     if (gst_raw_base_parse_is_using_sink_caps (raw_base_parse)) {
692       goto config_not_ready;
693     } else {
694       /* This should not be reached if the property config is active */
695       g_assert_not_reached ();
696     }
697   }
698 
699   if (G_UNLIKELY (src_format == dest_format)) {
700     *dest_value = src_value;
701   } else if ((src_format == GST_FORMAT_TIME || dest_format == GST_FORMAT_TIME)
702       && gst_raw_base_parse_is_gstformat_supported (raw_base_parse, src_format)
703       && gst_raw_base_parse_is_gstformat_supported (raw_base_parse,
704           dest_format)) {
705     /* Perform conversions here if either the src or dest format
706      * are GST_FORMAT_TIME and the other format is supported by
707      * the subclass. This is because we perform TIME<->non-TIME
708      * conversions here. Typically, subclasses only support
709      * BYTES and DEFAULT formats. */
710 
711     if (src_format == GST_FORMAT_TIME) {
712       /* The source format is time, so perform a TIME -> non-TIME conversion */
713       klass->get_units_per_second (raw_base_parse, dest_format,
714           GST_RAW_BASE_PARSE_CONFIG_CURRENT, &units_n, &units_d);
715       *dest_value = (units_n == 0
716           || units_d == 0) ? src_value : gst_util_uint64_scale (src_value,
717           units_n, GST_SECOND * units_d);
718     } else {
719       /* The dest format is time, so perform a non-TIME -> TIME conversion */
720       klass->get_units_per_second (raw_base_parse, src_format,
721           GST_RAW_BASE_PARSE_CONFIG_CURRENT, &units_n, &units_d);
722       *dest_value = (units_n == 0
723           || units_d == 0) ? src_value : gst_util_uint64_scale (src_value,
724           GST_SECOND * units_d, units_n);
725     }
726   } else {
727     /* Fallback for other conversions */
728     ret =
729         gst_base_parse_convert_default (parse, src_format, src_value,
730         dest_format, dest_value);
731   }
732 
733   GST_DEBUG_OBJECT (parse,
734       "converted %s -> %s  %" G_GINT64_FORMAT " -> %" GST_TIME_FORMAT,
735       gst_format_get_name (src_format), gst_format_get_name (dest_format),
736       src_value, GST_TIME_ARGS (*dest_value));
737 
738   GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (raw_base_parse);
739   return ret;
740 
741 config_not_ready:
742   GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK (raw_base_parse);
743   GST_ELEMENT_ERROR (parse, STREAM, FORMAT,
744       ("sink caps config is the current config, and it is not ready - "
745           "upstream may not have pushed a caps event yet"), (NULL));
746   return FALSE;
747 }
748 
749 static gboolean
gst_raw_base_parse_is_using_sink_caps(GstRawBaseParse * raw_base_parse)750 gst_raw_base_parse_is_using_sink_caps (GstRawBaseParse * raw_base_parse)
751 {
752   /* must be called with lock */
753   GstRawBaseParseClass *klass = GST_RAW_BASE_PARSE_GET_CLASS (raw_base_parse);
754   g_assert (klass->get_current_config);
755   return klass->get_current_config (raw_base_parse) ==
756       GST_RAW_BASE_PARSE_CONFIG_SINKCAPS;
757 }
758 
759 static gboolean
gst_raw_base_parse_is_gstformat_supported(GstRawBaseParse * raw_base_parse,GstFormat format)760 gst_raw_base_parse_is_gstformat_supported (GstRawBaseParse * raw_base_parse,
761     GstFormat format)
762 {
763   /* must be called with lock */
764   GstRawBaseParseClass *klass = GST_RAW_BASE_PARSE_GET_CLASS (raw_base_parse);
765   g_assert (klass->is_unit_format_supported);
766   return klass->is_unit_format_supported (raw_base_parse, format);
767 }
768 
769 /**
770  * gst_raw_base_parse_invalidate_src_caps:
771  * @raw_base_parse: a #GstRawBaseParse instance
772  *
773  * Flags the current source caps as invalid. Before the next downstream
774  * buffer push, @get_caps_from_config is called, and the created caps are
775  * pushed downstream in a new caps event, This is used if for example the
776  * properties configuration is modified in the subclass.
777  *
778  * Note that this must be called with the parser lock held. Use the
779  * GST_RAW_BASE_PARSE_CONFIG_MUTEX_LOCK() and GST_RAW_BASE_PARSE_CONFIG_MUTEX_UNLOCK()
780  * macros for this purpose.
781  */
782 void
gst_raw_base_parse_invalidate_src_caps(GstRawBaseParse * raw_base_parse)783 gst_raw_base_parse_invalidate_src_caps (GstRawBaseParse * raw_base_parse)
784 {
785   /* must be called with lock */
786   g_assert (raw_base_parse != NULL);
787   raw_base_parse->src_caps_set = FALSE;
788 }
789