gstbaseparse.c 160 KB
Newer Older
1
2
3
4
/* GStreamer
 * Copyright (C) 2008 Nokia Corporation. All rights reserved.
 *   Contact: Stefan Kost <stefan.kost@nokia.com>
 * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>.
5
6
 * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
 *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
Tim-Philipp Müller's avatar
Tim-Philipp Müller committed
20
21
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
22
23
24
25
 */

/**
 * SECTION:gstbaseparse
26
 * @title: GstBaseParse
27
28
29
 * @short_description: Base class for stream parsers
 * @see_also: #GstBaseTransform
 *
30
 * This base class is for parser elements that process data and splits it
31
32
33
 * into separate audio/video/whatever frames.
 *
 * It provides for:
34
35
36
37
38
39
40
41
 *
 *   * provides one sink pad and one source pad
 *   * handles state changes
 *   * can operate in pull mode or push mode
 *   * handles seeking in both modes
 *   * handles events (SEGMENT/EOS/FLUSH)
 *   * handles queries (POSITION/DURATION/SEEKING/FORMAT/CONVERT)
 *   * handles flushing
42
 *
43
 * The purpose of this base class is to provide the basic functionality of
44
45
 * a parser and share a lot of rather complex code.
 *
46
47
48
49
 * # Description of the parsing mechanism:
 *
 * ## Set-up phase
 *
50
51
 *  * #GstBaseParse calls #GstBaseParseClass.start() to inform subclass
 *    that data processing is about to start now.
52
 *
53
54
55
56
 *  * #GstBaseParse class calls #GstBaseParseClass.set_sink_caps() to
 *    inform the subclass about incoming sinkpad caps. Subclass could
 *    already set the srcpad caps accordingly, but this might be delayed
 *    until calling gst_base_parse_finish_frame() with a non-queued frame.
57
58
 *
 *  * At least at this point subclass needs to tell the #GstBaseParse class
59
60
 *    how big data chunks it wants to receive (minimum frame size ). It can
 *    do this with gst_base_parse_set_min_frame_size().
61
62
63
64
65
66
67
68
69
70
 *
 *  * #GstBaseParse class sets up appropriate data passing mode (pull/push)
 *    and starts to process the data.
 *
 * ## Parsing phase
 *
 *  * #GstBaseParse gathers at least min_frame_size bytes of data either
 *    by pulling it from upstream or collecting buffers in an internal
 *    #GstAdapter.
 *
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
 *  * A buffer of (at least) min_frame_size bytes is passed to subclass
 *    with #GstBaseParseClass.handle_frame(). Subclass checks the contents
 *    and can optionally return #GST_FLOW_OK along with an amount of data
 *    to be skipped to find a valid frame (which will result in a
 *    subsequent DISCONT).  If, otherwise, the buffer does not hold a
 *    complete frame, #GstBaseParseClass.handle_frame() can merely return
 *    and will be called again when additional data is available.  In push
 *    mode this amounts to an additional input buffer (thus minimal
 *    additional latency), in pull mode this amounts to some arbitrary
 *    reasonable buffer size increase.
 *
 *    Of course, gst_base_parse_set_min_frame_size() could also be used if
 *    a very specific known amount of additional data is required.  If,
 *    however, the buffer holds a complete valid frame, it can pass the
 *    size of this frame to gst_base_parse_finish_frame().
 *
 *    If acting as a converter, it can also merely indicate consumed input
 *    data while simultaneously providing custom output data.  Note that
 *    baseclass performs some processing (such as tracking overall consumed
 *    data rate versus duration) for each finished frame, but other state
 *    is only updated upon each call to #GstBaseParseClass.handle_frame()
92
93
94
95
96
97
98
99
100
101
 *    (such as tracking upstream input timestamp).
 *
 *    Subclass is also responsible for setting the buffer metadata
 *    (e.g. buffer timestamp and duration, or keyframe if applicable).
 *    (although the latter can also be done by #GstBaseParse if it is
 *    appropriately configured, see below).  Frame is provided with
 *    timestamp derived from upstream (as much as generally possible),
 *    duration obtained from configuration (see below), and offset
 *    if meaningful (in pull mode).
 *
102
103
104
 *    Note that #GstBaseParseClass.handle_frame() might receive any small
 *    amount of input data when leftover data is being drained (e.g. at
 *    EOS).
105
 *
106
107
108
109
 *  * As part of finish frame processing, just prior to actually pushing
 *    the buffer in question, it is passed to
 *    #GstBaseParseClass.pre_push_frame() which gives subclass yet one last
 *    chance to examine buffer metadata, or to send some custom (tag)
110
111
112
 *    events, or to perform custom (segment) filtering.
 *
 *  * During the parsing process #GstBaseParseClass will handle both srcpad
113
114
115
 *    and sinkpad events. They will be passed to subclass if
 *    #GstBaseParseClass.event() or #GstBaseParseClass.src_event()
 *    implementations have been provided.
116
117
118
 *
 * ## Shutdown phase
 *
119
120
 * * #GstBaseParse class calls #GstBaseParseClass.stop() to inform the
 *   subclass that data parsing will be stopped.
121
 *
122
123
124
125
 * Subclass is responsible for providing pad template caps for source and
 * sink pads. The pads need to be named "sink" and "src". It also needs to
 * set the fixed caps on srcpad, when the format is ensured (e.g.  when
 * base class calls subclass' #GstBaseParseClass.set_sink_caps() function).
126
 *
127
 * This base class uses %GST_FORMAT_DEFAULT as a meaning of frames. So,
128
 * subclass conversion routine needs to know that conversion from
129
 * %GST_FORMAT_TIME to %GST_FORMAT_DEFAULT must return the
130
131
 * frame number that can be found from the given byte position.
 *
132
 * #GstBaseParse uses subclasses conversion methods also for seeking (or
133
 * otherwise uses its own default one, see also below).
134
135
136
137
138
 *
 * Subclass @start and @stop functions will be called to inform the beginning
 * and end of data processing.
 *
 * Things that subclass need to take care of:
139
140
141
142
143
 *
 * * Provide pad templates
 * * Fixate the source pad caps when appropriate
 * * Inform base class how big data chunks should be retrieved. This is
 *   done with gst_base_parse_set_min_frame_size() function.
144
145
146
147
 * * Examine data chunks passed to subclass with
 *   #GstBaseParseClass.handle_frame() and pass proper frame(s) to
 *   gst_base_parse_finish_frame(), and setting src pad caps and timestamps
 *   on frame.
148
149
150
151
152
153
154
155
156
 * * Provide conversion functions
 * * Update the duration information with gst_base_parse_set_duration()
 * * Optionally passthrough using gst_base_parse_set_passthrough()
 * * Configure various baseparse parameters using
 *   gst_base_parse_set_average_bitrate(), gst_base_parse_set_syncable()
 *   and gst_base_parse_set_frame_rate().
 *
 * * In particular, if subclass is unable to determine a duration, but
 *   parsing (or specs) yields a frames per seconds rate, then this can be
157
158
 *   provided to #GstBaseParse to enable it to cater for buffer time
 *   metadata (which will be taken from upstream as much as
159
160
 *   possible). Internally keeping track of frame durations and respective
 *   sizes that have been pushed provides #GstBaseParse with an estimated
161
162
163
164
 *   bitrate. A default #GstBaseParseClass.convert() (used if not
 *   overridden) will then use these rates to perform obvious conversions.
 *   These rates are also used to update (estimated) duration at regular
 *   frame intervals.
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
 *
 */

/* TODO:
 *  - In push mode provide a queue of adapter-"queued" buffers for upstream
 *    buffer metadata
 *  - Queue buffers/events until caps are set
 */

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include <stdlib.h>
#include <string.h>

181
182
#include <gst/base/gstadapter.h>

183
184
#include "gstbaseparse.h"

185
186
187
188
189
/* FIXME: get rid of old GstIndex code */
#include "gstindex.h"
#include "gstindex.c"
#include "gstmemindex.c"

190
191
#define GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC  (1 << 0)

192
#define MIN_FRAMES_TO_POST_BITRATE 10
193
#define TARGET_DIFFERENCE          (20 * GST_SECOND)
194
#define MAX_INDEX_ENTRIES          4096
195
196
197
#define UPDATE_THRESHOLD           2

#define ABSDIFF(a,b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a)))
198

199
200
201
202
GST_DEBUG_CATEGORY_STATIC (gst_base_parse_debug);
#define GST_CAT_DEFAULT gst_base_parse_debug

/* Supported formats */
203
static const GstFormat fmtlist[] = {
204
205
206
  GST_FORMAT_DEFAULT,
  GST_FORMAT_BYTES,
  GST_FORMAT_TIME,
207
  GST_FORMAT_UNDEFINED
208
209
210
211
};

struct _GstBaseParsePrivate
{
Wim Taymans's avatar
Wim Taymans committed
212
  GstPadMode pad_mode;
213

214
215
  GstAdapter *adapter;

216
217
  gint64 duration;
  GstFormat duration_fmt;
218
  gint64 estimated_duration;
219
  gint64 estimated_drift;
220
221

  guint min_frame_size;
222
  gboolean disable_passthrough;
223
  gboolean passthrough;
224
  gboolean pts_interpolate;
225
  gboolean infer_ts;
226
227
  gboolean syncable;
  gboolean has_timing_info;
228
  guint fps_num, fps_den;
229
  gint update_interval;
230
  guint bitrate;
231
232
  guint lead_in, lead_out;
  GstClockTime lead_in_ts, lead_out_ts;
233
  GstClockTime min_latency, max_latency;
234
235
236

  gboolean discont;
  gboolean flushing;
237
  gboolean drain;
238
  gboolean saw_gaps;
239
240

  gint64 offset;
241
  gint64 sync_offset;
242
243
244
245
  GstClockTime next_pts;
  GstClockTime next_dts;
  GstClockTime prev_pts;
  GstClockTime prev_dts;
246
  gboolean prev_dts_from_pts;
247
  GstClockTime frame_duration;
248
249
  gboolean seen_keyframe;
  gboolean is_video;
250
  gint flushed;
251
252
253

  guint64 framecount;
  guint64 bytecount;
254
  guint64 data_bytecount;
255
  guint64 acc_duration;
256
257
  GstClockTime first_frame_pts;
  GstClockTime first_frame_dts;
258
  gint64 first_frame_offset;
259

260
261
262
263
  gboolean post_min_bitrate;
  gboolean post_avg_bitrate;
  gboolean post_max_bitrate;

264
265
266
  guint min_bitrate;
  guint avg_bitrate;
  guint max_bitrate;
267
  guint posted_avg_bitrate;
268

269
  /* frames/buffers that are queued and ready to go on OK */
270
  GQueue queued_frames;
271

272
  GstBuffer *cache;
273
274
275
276
277

  /* index entry storage, either ours or provided */
  GstIndex *index;
  gint index_id;
  gboolean own_index;
278
  GMutex index_lock;
279

280
281
  /* seek table entries only maintained if upstream is BYTE seekable */
  gboolean upstream_seekable;
282
  gboolean upstream_has_duration;
283
  gint64 upstream_size;
284
  GstFormat upstream_format;
285
286
  /* minimum distance between two index entries */
  GstClockTimeDiff idx_interval;
287
  guint64 idx_byte_interval;
288
289
  /* ts and offset of last entry added */
  GstClockTime index_last_ts;
290
  gint64 index_last_offset;
291
  gboolean index_last_valid;
292
293
294
295
296

  /* timestamps currently produced are accurate, e.g. started from 0 onwards */
  gboolean exact_position;
  /* seek events are temporarily kept to match them with newsegments */
  GSList *pending_seeks;
297

298
299
  /* reverse playback */
  GSList *buffers_pending;
300
  GSList *buffers_head;
301
  GSList *buffers_queued;
302
  GSList *buffers_send;
303
304
  GstClockTime last_pts;
  GstClockTime last_dts;
305
  gint64 last_offset;
306

307
308
  /* Pending serialized events */
  GList *pending_events;
309
310
311
312

  /* If baseparse has checked the caps to identify if it is
   * handling video or audio */
  gboolean checked_media;
313

314
  /* offset of last parsed frame/data */
315
  gint64 prev_offset;
316
317
  /* force a new frame, regardless of offset */
  gboolean new_frame;
318
319
320
321
  /* whether we are merely scanning for a frame */
  gboolean scanning;
  /* ... and resulting frame, if any */
  GstBaseParseFrame *scanned_frame;
322
323
324
325
326
327

  /* TRUE if we're still detecting the format, i.e.
   * if ::detect() is still called for future buffers */
  gboolean detecting;
  GList *detect_buffers;
  guint detect_buffers_size;
328

329
330
331
  /* True when no buffers have been received yet */
  gboolean first_buffer;

332
333
  /* if TRUE, a STREAM_START event needs to be pushed */
  gboolean push_stream_start;
334
335
336

  /* When we need to skip more data than we have currently */
  guint skip;
337
338
339

  /* Tag handling (stream tags only, global tags are passed through as-is) */
  GstTagList *upstream_tags;
340
341
  GstTagList *parser_tags;
  GstTagMergeMode parser_tags_merge_mode;
342
  gboolean tags_changed;
343
344
345

  /* Current segment seqnum */
  guint32 segment_seqnum;
346
347
};

348
349
350
351
352
353
354
355
typedef struct _GstBaseParseSeek
{
  GstSegment segment;
  gboolean accurate;
  gint64 offset;
  GstClockTime start_ts;
} GstBaseParseSeek;

356
357
358
359
360
361
362
363
364
#define DEFAULT_DISABLE_PASSTHROUGH        FALSE

enum
{
  PROP_0,
  PROP_DISABLE_PASSTHROUGH,
  PROP_LAST
};

365
366
367
368
369
#define GST_BASE_PARSE_INDEX_LOCK(parse) \
  g_mutex_lock (&parse->priv->index_lock);
#define GST_BASE_PARSE_INDEX_UNLOCK(parse) \
  g_mutex_unlock (&parse->priv->index_lock);

370
static GstElementClass *parent_class = NULL;
371
static gint base_parse_private_offset = 0;
372
373
374
375
376
377
378
379

static void gst_base_parse_class_init (GstBaseParseClass * klass);
static void gst_base_parse_init (GstBaseParse * parse,
    GstBaseParseClass * klass);

GType
gst_base_parse_get_type (void)
{
380
  static volatile gsize base_parse_type = 0;
381

382
  if (g_once_init_enter (&base_parse_type)) {
383
384
    static const GTypeInfo base_parse_info = {
      sizeof (GstBaseParseClass),
385
386
      (GBaseInitFunc) NULL,
      (GBaseFinalizeFunc) NULL,
387
388
389
390
391
392
393
      (GClassInitFunc) gst_base_parse_class_init,
      NULL,
      NULL,
      sizeof (GstBaseParse),
      0,
      (GInstanceInitFunc) gst_base_parse_init,
    };
394
    GType _type;
395

396
397
    _type = g_type_register_static (GST_TYPE_ELEMENT,
        "GstBaseParse", &base_parse_info, G_TYPE_FLAG_ABSTRACT);
398
399
400
401

    base_parse_private_offset =
        g_type_add_instance_private (_type, sizeof (GstBaseParsePrivate));

402
    g_once_init_leave (&base_parse_type, _type);
403
  }
404
  return (GType) base_parse_type;
405
406
}

407
408
409
410
411
412
static inline GstBaseParsePrivate *
gst_base_parse_get_instance_private (GstBaseParse * self)
{
  return (G_STRUCT_MEMBER_P (self, base_parse_private_offset));
}

413
414
static void gst_base_parse_finalize (GObject * object);

415
416
417
418
static GstStateChangeReturn gst_base_parse_change_state (GstElement * element,
    GstStateChange transition);
static void gst_base_parse_reset (GstBaseParse * parse);

419
#if 0
420
421
static void gst_base_parse_set_index (GstElement * element, GstIndex * index);
static GstIndex *gst_base_parse_get_index (GstElement * element);
422
#endif
423

424
425
static gboolean gst_base_parse_sink_activate (GstPad * sinkpad,
    GstObject * parent);
426
427
static gboolean gst_base_parse_sink_activate_mode (GstPad * pad,
    GstObject * parent, GstPadMode mode, gboolean active);
428
429
static gboolean gst_base_parse_handle_seek (GstBaseParse * parse,
    GstEvent * event);
430
431
static void gst_base_parse_set_upstream_tags (GstBaseParse * parse,
    GstTagList * taglist);
432

433
434
435
436
437
static void gst_base_parse_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void gst_base_parse_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);

438
439
static gboolean gst_base_parse_src_event (GstPad * pad, GstObject * parent,
    GstEvent * event);
440
441
static gboolean gst_base_parse_src_query (GstPad * pad, GstObject * parent,
    GstQuery * query);
442

443
444
static gboolean gst_base_parse_sink_event (GstPad * pad, GstObject * parent,
    GstEvent * event);
445
446
static gboolean gst_base_parse_sink_query (GstPad * pad, GstObject * parent,
    GstQuery * query);
447

448
449
static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstObject * parent,
    GstBuffer * buffer);
450
451
static void gst_base_parse_loop (GstPad * pad);

452
static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse,
453
    GstBaseParseFrame * frame);
454

455
static gboolean gst_base_parse_sink_event_default (GstBaseParse * parse,
456
457
    GstEvent * event);

458
static gboolean gst_base_parse_src_event_default (GstBaseParse * parse,
459
460
    GstEvent * event);

461
462
463
464
465
static gboolean gst_base_parse_sink_query_default (GstBaseParse * parse,
    GstQuery * query);
static gboolean gst_base_parse_src_query_default (GstBaseParse * parse,
    GstQuery * query);

466
467
static gint64 gst_base_parse_find_offset (GstBaseParse * parse,
    GstClockTime time, gboolean before, GstClockTime * _ts);
468
469
static GstFlowReturn gst_base_parse_locate_time (GstBaseParse * parse,
    GstClockTime * _time, gint64 * _offset);
470

471
472
473
static GstFlowReturn gst_base_parse_start_fragment (GstBaseParse * parse);
static GstFlowReturn gst_base_parse_finish_fragment (GstBaseParse * parse,
    gboolean prev_head);
474
static GstFlowReturn gst_base_parse_send_buffers (GstBaseParse * parse);
475
476

static inline GstFlowReturn gst_base_parse_check_sync (GstBaseParse * parse);
477

478
479
static gboolean gst_base_parse_is_seekable (GstBaseParse * parse);

480
481
static void gst_base_parse_push_pending_events (GstBaseParse * parse);

482
483
484
485
486
487
488
489
490
491
static void
gst_base_parse_clear_queues (GstBaseParse * parse)
{
  g_slist_foreach (parse->priv->buffers_queued, (GFunc) gst_buffer_unref, NULL);
  g_slist_free (parse->priv->buffers_queued);
  parse->priv->buffers_queued = NULL;
  g_slist_foreach (parse->priv->buffers_pending, (GFunc) gst_buffer_unref,
      NULL);
  g_slist_free (parse->priv->buffers_pending);
  parse->priv->buffers_pending = NULL;
492
493
494
  g_slist_foreach (parse->priv->buffers_head, (GFunc) gst_buffer_unref, NULL);
  g_slist_free (parse->priv->buffers_head);
  parse->priv->buffers_head = NULL;
495
496
497
  g_slist_foreach (parse->priv->buffers_send, (GFunc) gst_buffer_unref, NULL);
  g_slist_free (parse->priv->buffers_send);
  parse->priv->buffers_send = NULL;
498
499
500
501
502

  g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, NULL);
  g_list_free (parse->priv->detect_buffers);
  parse->priv->detect_buffers = NULL;
  parse->priv->detect_buffers_size = 0;
503
504
505
506

  g_queue_foreach (&parse->priv->queued_frames,
      (GFunc) gst_base_parse_frame_free, NULL);
  g_queue_clear (&parse->priv->queued_frames);
507
508
509
510
511

  gst_buffer_replace (&parse->priv->cache, NULL);

  g_list_foreach (parse->priv->pending_events, (GFunc) gst_event_unref, NULL);
  g_list_free (parse->priv->pending_events);
512
  parse->priv->pending_events = NULL;
513
514

  parse->priv->checked_media = FALSE;
515
516
}

517
518
519
520
521
static void
gst_base_parse_finalize (GObject * object)
{
  GstBaseParse *parse = GST_BASE_PARSE (object);

522
  g_object_unref (parse->priv->adapter);
523

524
525
526
527
  if (parse->priv->index) {
    gst_object_unref (parse->priv->index);
    parse->priv->index = NULL;
  }
528
  g_mutex_clear (&parse->priv->index_lock);
529

530
531
  gst_base_parse_clear_queues (parse);

532
533
534
535
536
537
538
  G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
gst_base_parse_class_init (GstBaseParseClass * klass)
{
  GObjectClass *gobject_class;
539
  GstElementClass *gstelement_class;
540
541

  gobject_class = G_OBJECT_CLASS (klass);
542
543
544
545

  if (base_parse_private_offset != 0)
    g_type_class_adjust_private_offset (klass, &base_parse_private_offset);

546
  parent_class = g_type_class_peek_parent (klass);
547

548
  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_parse_finalize);
549
550
551
552
553
554
  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_base_parse_set_property);
  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_base_parse_get_property);

  /**
   * GstBaseParse:disable-passthrough:
   *
555
   * If set to %TRUE, baseparse will unconditionally force parsing of the
556
557
558
   * incoming data. This can be required in the rare cases where the incoming
   * side-data (caps, pts, dts, ...) is not trusted by the user and wants to
   * force validation and parsing of the incoming data.
559
   * If set to %FALSE, decision of whether to parse the data or not is up to
560
561
562
563
564
565
566
   * the implementation (standard behaviour).
   */
  g_object_class_install_property (gobject_class, PROP_DISABLE_PASSTHROUGH,
      g_param_spec_boolean ("disable-passthrough", "Disable passthrough",
          "Force processing (disables passthrough)",
          DEFAULT_DISABLE_PASSTHROUGH,
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
567

568
569
570
  gstelement_class = (GstElementClass *) klass;
  gstelement_class->change_state =
      GST_DEBUG_FUNCPTR (gst_base_parse_change_state);
571
572

#if 0
573
574
  gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_base_parse_set_index);
  gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_base_parse_get_index);
575
#endif
576

577
  /* Default handlers */
578
579
  klass->sink_event = gst_base_parse_sink_event_default;
  klass->src_event = gst_base_parse_src_event_default;
580
581
  klass->sink_query = gst_base_parse_sink_query_default;
  klass->src_query = gst_base_parse_src_query_default;
582
  klass->convert = gst_base_parse_convert_default;
583
584
585

  GST_DEBUG_CATEGORY_INIT (gst_base_parse_debug, "baseparse", 0,
      "baseparse element");
586
587
588
589
590
591
592
593
594
}

static void
gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
{
  GstPadTemplate *pad_template;

  GST_DEBUG_OBJECT (parse, "gst_base_parse_init");

595
  parse->priv = gst_base_parse_get_instance_private (parse);
596
597
598
599
600
601
602

  pad_template =
      gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink");
  g_return_if_fail (pad_template != NULL);
  parse->sinkpad = gst_pad_new_from_template (pad_template, "sink");
  gst_pad_set_event_function (parse->sinkpad,
      GST_DEBUG_FUNCPTR (gst_base_parse_sink_event));
603
604
  gst_pad_set_query_function (parse->sinkpad,
      GST_DEBUG_FUNCPTR (gst_base_parse_sink_query));
605
606
607
608
  gst_pad_set_chain_function (parse->sinkpad,
      GST_DEBUG_FUNCPTR (gst_base_parse_chain));
  gst_pad_set_activate_function (parse->sinkpad,
      GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate));
609
610
  gst_pad_set_activatemode_function (parse->sinkpad,
      GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_mode));
611
  GST_PAD_SET_PROXY_ALLOCATION (parse->sinkpad);
612
613
614
615
616
617
618
619
620
621
622
  gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad);

  GST_DEBUG_OBJECT (parse, "sinkpad created");

  pad_template =
      gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src");
  g_return_if_fail (pad_template != NULL);
  parse->srcpad = gst_pad_new_from_template (pad_template, "src");
  gst_pad_set_event_function (parse->srcpad,
      GST_DEBUG_FUNCPTR (gst_base_parse_src_event));
  gst_pad_set_query_function (parse->srcpad,
623
      GST_DEBUG_FUNCPTR (gst_base_parse_src_query));
624
  gst_pad_use_fixed_caps (parse->srcpad);
625
626
627
  gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
  GST_DEBUG_OBJECT (parse, "src created");

628
629
  g_queue_init (&parse->priv->queued_frames);

630
  parse->priv->adapter = gst_adapter_new ();
631

Wim Taymans's avatar
Wim Taymans committed
632
  parse->priv->pad_mode = GST_PAD_MODE_NONE;
633

634
  g_mutex_init (&parse->priv->index_lock);
635

636
637
638
  /* init state */
  gst_base_parse_reset (parse);
  GST_DEBUG_OBJECT (parse, "init ok");
Wim Taymans's avatar
Wim Taymans committed
639
640

  GST_OBJECT_FLAG_SET (parse, GST_ELEMENT_FLAG_INDEXABLE);
641
642
643
644

  parse->priv->upstream_tags = NULL;
  parse->priv->parser_tags = NULL;
  parse->priv->parser_tags_merge_mode = GST_TAG_MERGE_APPEND;
645
  parse->priv->disable_passthrough = DEFAULT_DISABLE_PASSTHROUGH;
646
647
}

648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
static void
gst_base_parse_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstBaseParse *parse = GST_BASE_PARSE (object);

  switch (prop_id) {
    case PROP_DISABLE_PASSTHROUGH:
      parse->priv->disable_passthrough = g_value_get_boolean (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_base_parse_get_property (GObject * object, guint prop_id, GValue * value,
    GParamSpec * pspec)
{
  GstBaseParse *parse = GST_BASE_PARSE (object);

  switch (prop_id) {
    case PROP_DISABLE_PASSTHROUGH:
      g_value_set_boolean (value, parse->priv->disable_passthrough);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

680
681
682
683
684
685
686
687
688
/**
 * gst_base_parse_frame_copy:
 * @frame: a #GstBaseParseFrame
 *
 * Copies a #GstBaseParseFrame.
 *
 * Returns: A copy of @frame
 */

689
GstBaseParseFrame *
690
gst_base_parse_frame_copy (GstBaseParseFrame * frame)
691
{
692
693
694
695
  GstBaseParseFrame *copy;

  copy = g_slice_dup (GstBaseParseFrame, frame);
  copy->buffer = gst_buffer_ref (frame->buffer);
696
697
  copy->_private_flags &= ~GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC;

698
699
  GST_TRACE ("copied frame %p -> %p", frame, copy);

700
  return copy;
701
702
}

703
704
705
706
707
708
/**
 * gst_base_parse_frame_free:
 * @frame: A #GstBaseParseFrame
 *
 * Frees the provided @frame.
 */
709
void
710
gst_base_parse_frame_free (GstBaseParseFrame * frame)
711
{
712
713
  GST_TRACE ("freeing frame %p", frame);

714
715
716
717
  if (frame->buffer) {
    gst_buffer_unref (frame->buffer);
    frame->buffer = NULL;
  }
718

719
  if (!(frame->_private_flags & GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC)) {
720
    g_slice_free (GstBaseParseFrame, frame);
721
722
723
  } else {
    memset (frame, 0, sizeof (*frame));
  }
724
725
}

726
727
728
G_DEFINE_BOXED_TYPE (GstBaseParseFrame, gst_base_parse_frame,
    (GBoxedCopyFunc) gst_base_parse_frame_copy,
    (GBoxedFreeFunc) gst_base_parse_frame_free);
729

730
731
/**
 * gst_base_parse_frame_init:
732
 * @frame: #GstBaseParseFrame.
733
734
 *
 * Sets a #GstBaseParseFrame to initial state.  Currently this means
735
736
737
738
 * all public fields are zero-ed and a private flag is set to make
 * sure gst_base_parse_frame_free() only frees the contents but not
 * the actual frame. Use this function to initialise a #GstBaseParseFrame
 * allocated on the stack.
739
740
 */
void
741
gst_base_parse_frame_init (GstBaseParseFrame * frame)
742
743
{
  memset (frame, 0, sizeof (GstBaseParseFrame));
744
  frame->_private_flags = GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC;
745
  GST_TRACE ("inited frame %p", frame);
746
747
}

748
749
750
751
752
753
754
755
756
757
758
759
760
/**
 * gst_base_parse_frame_new:
 * @buffer: (transfer none): a #GstBuffer
 * @flags: the flags
 * @overhead: number of bytes in this frame which should be counted as
 *     metadata overhead, ie. not used to calculate the average bitrate.
 *     Set to -1 to mark the entire frame as metadata. If in doubt, set to 0.
 *
 * Allocates a new #GstBaseParseFrame. This function is mainly for bindings,
 * elements written in C should usually allocate the frame on the stack and
 * then use gst_base_parse_frame_init() to initialise it.
 *
 * Returns: a newly-allocated #GstBaseParseFrame. Free with
761
 *     gst_base_parse_frame_free() when no longer needed.
762
763
764
765
 */
GstBaseParseFrame *
gst_base_parse_frame_new (GstBuffer * buffer, GstBaseParseFrameFlags flags,
    gint overhead)
766
{
767
  GstBaseParseFrame *frame;
768

769
770
  frame = g_slice_new0 (GstBaseParseFrame);
  frame->buffer = gst_buffer_ref (buffer);
771

772
  GST_TRACE ("created frame %p", frame);
773
  return frame;
774
775
}

776
static inline void
777
gst_base_parse_update_flags (GstBaseParse * parse)
778
{
779
780
781
782
783
784
  parse->flags = 0;

  /* set flags one by one for clarity */
  if (G_UNLIKELY (parse->priv->drain))
    parse->flags |= GST_BASE_PARSE_FLAG_DRAINING;

785
  /* losing sync is pretty much a discont (and vice versa), no ? */
786
787
  if (G_UNLIKELY (parse->priv->discont))
    parse->flags |= GST_BASE_PARSE_FLAG_LOST_SYNC;
788
789
}

790
791
792
793
794
795
static inline void
gst_base_parse_update_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
{
  if (G_UNLIKELY (parse->priv->discont)) {
    GST_DEBUG_OBJECT (parse, "marking DISCONT");
    GST_BUFFER_FLAG_SET (frame->buffer, GST_BUFFER_FLAG_DISCONT);
796
797
  } else {
    GST_BUFFER_FLAG_UNSET (frame->buffer, GST_BUFFER_FLAG_DISCONT);
798
799
800
801
802
803
804
805
806
807
  }

  if (parse->priv->prev_offset != parse->priv->offset || parse->priv->new_frame) {
    GST_LOG_OBJECT (parse, "marking as new frame");
    frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NEW_FRAME;
  }

  frame->offset = parse->priv->prev_offset = parse->priv->offset;
}

808
809
810
811
812
static void
gst_base_parse_reset (GstBaseParse * parse)
{
  GST_OBJECT_LOCK (parse);
  gst_segment_init (&parse->segment, GST_FORMAT_TIME);
813
814
  parse->priv->duration = -1;
  parse->priv->min_frame_size = 1;
815
  parse->priv->discont = TRUE;
816
  parse->priv->flushing = FALSE;
817
  parse->priv->saw_gaps = FALSE;
818
  parse->priv->offset = 0;
819
  parse->priv->sync_offset = 0;
820
  parse->priv->update_interval = -1;
821
822
  parse->priv->fps_num = parse->priv->fps_den = 0;
  parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
823
824
  parse->priv->lead_in = parse->priv->lead_out = 0;
  parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0;
825
826
827
828
  parse->priv->bitrate = 0;
  parse->priv->framecount = 0;
  parse->priv->bytecount = 0;
  parse->priv->acc_duration = 0;
829
830
  parse->priv->first_frame_pts = GST_CLOCK_TIME_NONE;
  parse->priv->first_frame_dts = GST_CLOCK_TIME_NONE;
831
  parse->priv->first_frame_offset = -1;
832
  parse->priv->estimated_duration = -1;
833
  parse->priv->estimated_drift = 0;
834
  parse->priv->next_pts = GST_CLOCK_TIME_NONE;
835
  parse->priv->next_dts = 0;
836
837
  parse->priv->syncable = TRUE;
  parse->priv->passthrough = FALSE;
838
  parse->priv->pts_interpolate = TRUE;
839
  parse->priv->infer_ts = TRUE;
840
  parse->priv->has_timing_info = FALSE;
841
842
843
844
845
  parse->priv->min_bitrate = G_MAXUINT;
  parse->priv->max_bitrate = 0;
  parse->priv->avg_bitrate = 0;
  parse->priv->posted_avg_bitrate = 0;

846
847
  parse->priv->index_last_ts = GST_CLOCK_TIME_NONE;
  parse->priv->index_last_offset = -1;
848
  parse->priv->index_last_valid = TRUE;
849
  parse->priv->upstream_seekable = FALSE;
850
  parse->priv->upstream_size = 0;
851
  parse->priv->upstream_has_duration = FALSE;
852
  parse->priv->upstream_format = GST_FORMAT_UNDEFINED;
853
  parse->priv->idx_interval = 0;
854
  parse->priv->idx_byte_interval = 0;
855
  parse->priv->exact_position = TRUE;
856
  parse->priv->seen_keyframe = FALSE;
857
  parse->priv->checked_media = FALSE;
858

859
860
  parse->priv->last_dts = GST_CLOCK_TIME_NONE;
  parse->priv->last_pts = GST_CLOCK_TIME_NONE;
861
862
  parse->priv->last_offset = 0;

863
864
  parse->priv->skip = 0;

865
866
867
868
  g_list_foreach (parse->priv->pending_events, (GFunc) gst_mini_object_unref,
      NULL);
  g_list_free (parse->priv->pending_events);
  parse->priv->pending_events = NULL;
869

870
871
872
873
  if (parse->priv->cache) {
    gst_buffer_unref (parse->priv->cache);
    parse->priv->cache = NULL;
  }
874
875
876
877

  g_slist_foreach (parse->priv->pending_seeks, (GFunc) g_free, NULL);
  g_slist_free (parse->priv->pending_seeks);
  parse->priv->pending_seeks = NULL;
878

879
880
881
  if (parse->priv->adapter)
    gst_adapter_clear (parse->priv->adapter);

882
883
  gst_base_parse_set_upstream_tags (parse, NULL);

884
885
886
887
888
889
  if (parse->priv->parser_tags) {
    gst_tag_list_unref (parse->priv->parser_tags);
    parse->priv->parser_tags = NULL;
  }
  parse->priv->parser_tags_merge_mode = GST_TAG_MERGE_APPEND;

890
  parse->priv->new_frame = TRUE;
891

892
893
  parse->priv->first_buffer = TRUE;

894
895
896
897
  g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, NULL);
  g_list_free (parse->priv->detect_buffers);
  parse->priv->detect_buffers = NULL;
  parse->priv->detect_buffers_size = 0;
898
899

  parse->priv->segment_seqnum = GST_SEQNUM_INVALID;
900
901
  GST_OBJECT_UNLOCK (parse);
}
902

903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
static gboolean
gst_base_parse_check_bitrate_tag (GstBaseParse * parse, const gchar * tag)
{
  gboolean got_tag = FALSE;
  guint n = 0;

  if (parse->priv->upstream_tags != NULL)
    got_tag = gst_tag_list_get_uint (parse->priv->upstream_tags, tag, &n);

  if (!got_tag && parse->priv->parser_tags != NULL)
    got_tag = gst_tag_list_get_uint (parse->priv->parser_tags, tag, &n);

  return got_tag;
}

/* check if upstream or subclass tags contain bitrates already */
static void
gst_base_parse_check_bitrate_tags (GstBaseParse * parse)
{
  parse->priv->post_min_bitrate =
      !gst_base_parse_check_bitrate_tag (parse, GST_TAG_MINIMUM_BITRATE);
  parse->priv->post_avg_bitrate =
      !gst_base_parse_check_bitrate_tag (parse, GST_TAG_BITRATE);
  parse->priv->post_max_bitrate =
      !gst_base_parse_check_bitrate_tag (parse, GST_TAG_MAXIMUM_BITRATE);
}

930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
/* Queues new tag event with the current combined state of the stream tags
 * (i.e. upstream tags merged with subclass tags and current baseparse tags) */
static void
gst_base_parse_queue_tag_event_update (GstBaseParse * parse)
{
  GstTagList *merged_tags;

  GST_LOG_OBJECT (parse, "upstream : %" GST_PTR_FORMAT,
      parse->priv->upstream_tags);
  GST_LOG_OBJECT (parse, "parser   : %" GST_PTR_FORMAT,
      parse->priv->parser_tags);
  GST_LOG_OBJECT (parse, "mode     : %d", parse->priv->parser_tags_merge_mode);

  merged_tags =
      gst_tag_list_merge (parse->priv->upstream_tags, parse->priv->parser_tags,
      parse->priv->parser_tags_merge_mode);

  GST_DEBUG_OBJECT (parse, "merged   : %" GST_PTR_FORMAT, merged_tags);

  if (merged_tags == NULL)
    return;

  if (gst_tag_list_is_empty (merged_tags)) {
    gst_tag_list_unref (merged_tags);
    return;
  }

957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
  if (parse->priv->framecount >= MIN_FRAMES_TO_POST_BITRATE) {
    /* only add bitrate tags to non-empty taglists for now, and only if neither
     * upstream tags nor the subclass sets the bitrate tag in question already */
    if (parse->priv->min_bitrate != G_MAXUINT && parse->priv->post_min_bitrate) {
      GST_LOG_OBJECT (parse, "adding min bitrate %u", parse->priv->min_bitrate);
      gst_tag_list_add (merged_tags, GST_TAG_MERGE_KEEP,
          GST_TAG_MINIMUM_BITRATE, parse->priv->min_bitrate, NULL);
    }
    if (parse->priv->max_bitrate != 0 && parse->priv->post_max_bitrate) {
      GST_LOG_OBJECT (parse, "adding max bitrate %u", parse->priv->max_bitrate);
      gst_tag_list_add (merged_tags, GST_TAG_MERGE_KEEP,
          GST_TAG_MAXIMUM_BITRATE, parse->priv->max_bitrate, NULL);
    }
    if (parse->priv->avg_bitrate != 0 && parse->priv->post_avg_bitrate) {
      parse->priv->posted_avg_bitrate = parse->priv->avg_bitrate;
      GST_LOG_OBJECT (parse, "adding avg bitrate %u", parse->priv->avg_bitrate);
      gst_tag_list_add (merged_tags, GST_TAG_MERGE_KEEP,
          GST_TAG_BITRATE, parse->priv->avg_bitrate, NULL);
    }
976
977
978
979
980
981
982
  }

  parse->priv->pending_events =
      g_list_prepend (parse->priv->pending_events,
      gst_event_new_tag (merged_tags));
}

983
/* gst_base_parse_parse_frame:
984
985
986
987
988
 * @parse: #GstBaseParse.
 * @buffer: #GstBuffer.
 *
 * Default callback for parse_frame.
 */
989
static GstFlowReturn
990
gst_base_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
991
{
992
993
  GstBuffer *buffer = frame->buffer;

994
  if (!GST_BUFFER_PTS_IS_VALID (buffer) &&
995
996
997
      GST_CLOCK_TIME_IS_VALID (parse->priv->next_pts)) {
    GST_BUFFER_PTS (buffer) = parse->priv->next_pts;
  }
998
  if (!GST_BUFFER_DTS_IS_VALID (buffer) &&
999
1000
1001
      GST_CLOCK_TIME_IS_VALID (parse->priv->next_dts)) {
    GST_BUFFER_DTS (buffer) = parse->priv->next_dts;
  }
1002
  if (!GST_BUFFER_DURATION_IS_VALID (buffer) &&
1003
1004
      GST_CLOCK_TIME_IS_VALID (parse->priv->frame_duration)) {
    GST_BUFFER_DURATION (buffer) = parse->priv->frame_duration;
1005
  }
1006
  return GST_FLOW_OK;
1007
1008
}

1009
/* gst_base_parse_convert:
1010
 * @parse: #GstBaseParse.
1011
1012
1013
1014
 * @src_format: #GstFormat describing the source format.
 * @src_value: Source value to be converted.
 * @dest_format: #GstFormat defining the converted format.
 * @dest_value: Pointer where the conversion result will be put.
1015
 *
1016
1017
 * Converts using configured "convert" vmethod in #GstBaseParse class.
 *
1018
 * Returns: %TRUE if conversion was successful.
1019
1020
 */
static gboolean
1021
1022
1023
gst_base_parse_convert (GstBaseParse * parse,
    GstFormat src_format,
    gint64 src_value, GstFormat dest_format, gint64 * dest_value)
1024
{
1025
1026
  GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
  gboolean ret;
1027

1028
1029
1030
1031
  g_return_val_if_fail (dest_value != NULL, FALSE);

  if (!klass->convert)
    return FALSE;
1032

1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
  ret = klass->convert (parse, src_format, src_value, dest_format, dest_value);

#ifndef GST_DISABLE_GST_DEBUG
  {
    if (ret) {
      if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
        GST_LOG_OBJECT (parse,
            "TIME -> BYTES: %" GST_TIME_FORMAT " -> %" G_GINT64_FORMAT,
            GST_TIME_ARGS (src_value), *dest_value);
      } else if (dest_format == GST_FORMAT_TIME &&
          src_format == GST_FORMAT_BYTES) {
        GST_LOG_OBJECT (parse,
            "BYTES -> TIME: %" G_GINT64_FORMAT " -> %" GST_TIME_FORMAT,
            src_value, GST_TIME_ARGS (*dest_value));
      } else {
        GST_LOG_OBJECT (parse,
            "%s -> %s: %" G_GINT64_FORMAT " -> %" G_GINT64_FORMAT,
            GST_STR_NULL (gst_format_get_name (src_format)),
            GST_STR_NULL (gst_format_get_name (dest_format)),
            src_value, *dest_value);
      }
    } else {
      GST_DEBUG_OBJECT (parse, "conversion failed");
    }
1057
  }
1058
#endif
1059

1060
1061
  return ret;
}
1062

1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
static gboolean
update_upstream_provided (GQuark field_id, const GValue * value,
    gpointer user_data)
{
  GstCaps *default_caps = user_data;
  gint i;
  gint caps_size;

  caps_size = gst_caps_get_size (default_caps);
  for (i = 0; i < caps_size; i++) {
    GstStructure *structure = gst_caps_get_structure (default_caps, i);
    if (gst_structure_id_has_field (structure, field_id))
      gst_structure_id_set_value (structure, field_id, value);
  }

  return TRUE;
}

static GstCaps *
gst_base_parse_negotiate_default_caps (GstBaseParse * parse)
{
  GstCaps *caps, *templcaps;
  GstCaps *sinkcaps = NULL;
  GstCaps *default_caps = NULL;
  GstStructure *structure;

  templcaps = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SRC_PAD (parse));
  caps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), templcaps);
  if (caps)
    gst_caps_unref (templcaps);
  else
    caps = templcaps;
  templcaps = NULL;

  if (!caps || gst_caps_is_empty (caps) || gst_caps_is_any (caps)) {
    goto caps_error;
  }

  GST_LOG_OBJECT (parse, "peer caps  %" GST_PTR_FORMAT, caps);

  /* before fixating, try to use whatever upstream provided */
  default_caps = gst_caps_copy (caps);
  sinkcaps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse));

  GST_LOG_OBJECT (parse, "current caps %" GST_PTR_FORMAT " for sinkpad",
      sinkcaps);

  if (sinkcaps) {
    structure = gst_caps_get_structure (sinkcaps, 0);
    gst_structure_foreach (structure, update_upstream_provided, default_caps);
  }

  default_caps = gst_caps_fixate (default_caps);

  if (!default_caps) {
    GST_WARNING_OBJECT (parse, "Failed to create default caps !");
    goto caps_error;
  }

  GST_INFO_OBJECT (parse,
      "Chose default caps %" GST_PTR_FORMAT " for initial gap", default_caps);

1125
1126
  if (sinkcaps)
    gst_caps_unref (sinkcaps);
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
  gst_caps_unref (caps);

  return default_caps;

caps_error:
  {
    if (caps)
      gst_caps_unref (caps);
    if (sinkcaps)
      gst_caps_unref (sinkcaps);
    return NULL;
  }
}

1141
/* gst_base_parse_sink_event:
1142
1143
1144
1145
1146
 * @pad: #GstPad that received the event.
 * @event: #GstEvent to be handled.
 *
 * Handler for sink pad events.
 *
1147
 * Returns: %TRUE if the event was handled.
1148
1149
 */
static gboolean
1150
gst_base_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
1151
{
1152
1153
  GstBaseParse *parse = GST_BASE_PARSE (parent);
  GstBaseParseClass *bclass = GST_BASE_PARSE_GET_CLASS (parse);
1154
  gboolean ret;