gstbaseparse.c 100 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/* 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>.
 *
 * 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
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/**
 * SECTION:gstbaseparse
 * @short_description: Base class for stream parsers
 * @see_also: #GstBaseTransform
 *
 * This base class is for parser elements that process data and splits it 
 * into separate audio/video/whatever frames.
 *
 * It provides for:
 * <itemizedlist>
 *   <listitem><para>One sinkpad and one srcpad</para></listitem>
 *   <listitem><para>Handles state changes</para></listitem>
 *   <listitem><para>Does flushing</para></listitem>
 *   <listitem><para>Push mode</para></listitem>
 *   <listitem><para>Pull mode</para></listitem>
 *   <listitem><para>Handles events (NEWSEGMENT/EOS/FLUSH)</para></listitem>
 *   <listitem><para>Handles seeking in both modes</para></listitem>
 *   <listitem><para>
 *        Handles POSITION/DURATION/SEEKING/FORMAT/CONVERT queries
 *   </para></listitem>
 * </itemizedlist>
 *
 * The purpose of this base class is to provide a basic functionality of
 * a parser and share a lot of rather complex code.
 *
 * Description of the parsing mechanism:
 * <orderedlist>
 * <listitem>
 *   <itemizedlist><title>Set-up phase</title>
 *   <listitem><para>
 *     GstBaseParse class calls @set_sink_caps to inform the subclass about
 *     incoming sinkpad caps. Subclass should set the srcpad caps accordingly.
 *   </para></listitem>
 *   <listitem><para>
 *     GstBaseParse calls @start to inform subclass that data processing is
 *     about to start now.
 *   </para></listitem>
 *   <listitem><para>
 *      At least in this point subclass needs to tell the GstBaseParse class
 *      how big data chunks it wants to receive (min_frame_size). It can do 
 *      this with @gst_base_parse_set_min_frame_size.
 *   </para></listitem>
 *   <listitem><para>
 *      GstBaseParse class sets up appropriate data passing mode (pull/push)
 *      and starts to process the data.
 *   </para></listitem>
 *   </itemizedlist>
 * </listitem>
 * <listitem>
 *   <itemizedlist>
 *   <title>Parsing phase</title>
 *     <listitem><para>
 *       GstBaseParse gathers at least min_frame_size bytes of data either 
 *       by pulling it from upstream or collecting buffers into internal
 *       #GstAdapter.
 *     </para></listitem>
 *     <listitem><para>
 *       A buffer of min_frame_size bytes is passed to subclass with
 *       @check_valid_frame. Subclass checks the contents and returns TRUE
 *       if the buffer contains a valid frame. It also needs to set the
 *       @framesize according to the detected frame size. If buffer didn't
 *       contain a valid frame, this call must return FALSE and optionally
 *       set the @skipsize value to inform base class that how many bytes
 *       it needs to skip in order to find a valid frame. The passed buffer
86
87
 *       is read-only.  Note that @check_valid_frame might receive any small
 *       amount of input data when leftover data is being drained (e.g. at EOS).
88
89
90
91
 *     </para></listitem>
 *     <listitem><para>
 *       After valid frame is found, it will be passed again to subclass with
 *       @parse_frame call. Now subclass is responsible for parsing the
92
93
94
 *       frame contents and setting the caps, buffer timestamp and duration
 *       (although the latter can also be done by GstBaseParse if it is
 *       appropriately configured, see below).
95
96
97
 *     </para></listitem>
 *     <listitem><para>
 *       Finally the buffer can be pushed downstream and parsing loop starts
98
99
100
101
 *       over again.  Just prior to actually pushing the buffer in question,
 *       it is passed to @pre_push_buffer which gives subclass yet one
 *       last chance to examine buffer metadata, or to send some custom (tag)
 *       events, or to perform custom (segment) filtering.
102
103
 *     </para></listitem>
 *     <listitem><para>
104
 *       During the parsing process GstBaseParseClass will handle both srcpad and
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
 *       sinkpad events. They will be passed to subclass if @event or
 *       @src_event callbacks have been provided.
 *     </para></listitem>
 *   </itemizedlist>
 * </listitem>
 * <listitem>
 *   <itemizedlist><title>Shutdown phase</title>
 *   <listitem><para>
 *     GstBaseParse class calls @stop to inform the subclass that data
 *     parsing will be stopped.
 *   </para></listitem>
 *   </itemizedlist>
 * </listitem>
 * </orderedlist>
 *
 * 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' @set_sink_caps function).
 *
 * This base class uses GST_FORMAT_DEFAULT as a meaning of frames. So,
 * subclass conversion routine needs to know that conversion from
 * GST_FORMAT_TIME to GST_FORMAT_DEFAULT must return the
 * frame number that can be found from the given byte position.
 *
130
131
 * GstBaseParse uses subclasses conversion methods also for seeking (or otherwise
 * uses its own default one, see also below).
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
 *
 * 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:
 * <itemizedlist>
 *   <listitem><para>Provide pad templates</para></listitem>
 *   <listitem><para>
 *      Fixate the source pad caps when appropriate
 *   </para></listitem>
 *   <listitem><para>
 *      Inform base class how big data chunks should be retrieved. This is
 *      done with @gst_base_parse_set_min_frame_size function.
 *   </para></listitem>
 *   <listitem><para>
 *      Examine data chunks passed to subclass with @check_valid_frame
 *      and tell if they contain a valid frame
 *   </para></listitem>
 *   <listitem><para>
 *      Set the caps and timestamp to frame that is passed to subclass with
 *      @parse_frame function.
 *   </para></listitem>
 *   <listitem><para>Provide conversion functions</para></listitem>
 *   <listitem><para>
 *      Update the duration information with @gst_base_parse_set_duration
 *   </para></listitem>
158
 *   <listitem><para>
159
160
161
162
163
164
165
166
167
168
 *      Optionally passthrough using @gst_base_parse_set_passthrough
 *   </para></listitem>
 *   <listitem><para>
 *      Configure various baseparse parameters using @gst_base_parse_set_seek and
 *      @gst_base_parse_set_frame_props.
 *   </para></listitem>
 *   <listitem><para>
 *      In particular, if subclass is unable to determine a duration, but
 *      parsing (or specs) yields a frames per seconds rate, then this can be
 *      provided to GstBaseParse to enable it to cater for
169
 *      buffer time metadata (which will be taken from upstream as much as possible).
170
171
172
 *      Internally keeping track of frame durations and respective
 *      sizes that have been pushed provides GstBaseParse with an estimated bitrate.
 *      A default @convert (used if not overriden) will then use these
173
174
175
 *      rates to perform obvious conversions.  These rates are also used to update
 *      (estimated) duration at regular frame intervals.
 *   </para></listitem>
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
 * </itemizedlist>
 *
 */

/* 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>

#include "gstbaseparse.h"

195
196
#define MIN_FRAMES_TO_POST_BITRATE 10

197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
GST_DEBUG_CATEGORY_STATIC (gst_base_parse_debug);
#define GST_CAT_DEFAULT gst_base_parse_debug

/* Supported formats */
static GstFormat fmtlist[] = {
  GST_FORMAT_DEFAULT,
  GST_FORMAT_BYTES,
  GST_FORMAT_TIME,
  0
};

#define GST_BASE_PARSE_GET_PRIVATE(obj)  \
    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_PARSE, GstBaseParsePrivate))

struct _GstBaseParsePrivate
{
  GstActivateMode pad_mode;

  gint64 duration;
  GstFormat duration_fmt;
217
  gint64 estimated_duration;
218
219

  guint min_frame_size;
220
  gboolean passthrough;
221
222
  guint fps_num, fps_den;
  guint update_interval;
223
  guint bitrate;
224
225
  guint lead_in, lead_out;
  GstClockTime lead_in_ts, lead_out_ts;
226
  GstBaseParseSeekable seekable;
227
228
229

  gboolean discont;
  gboolean flushing;
230
  gboolean drain;
231
232

  gint64 offset;
233
  gint64 sync_offset;
234
235
236
237
238
239
  GstClockTime next_ts;
  GstClockTime prev_ts;
  GstClockTime frame_duration;

  guint64 framecount;
  guint64 bytecount;
240
  guint64 data_bytecount;
241
  guint64 acc_duration;
242

243
244
245
246
247
248
  gboolean post_min_bitrate;
  gboolean post_avg_bitrate;
  gboolean post_max_bitrate;
  guint min_bitrate;
  guint avg_bitrate;
  guint max_bitrate;
249
  guint posted_avg_bitrate;
250

251
252
253
  GList *pending_events;

  GstBuffer *cache;
254
255
256
257
258
259
260
261
262
263
264
265

  /* index entry storage, either ours or provided */
  GstIndex *index;
  gint index_id;
  gboolean own_index;
  /* seek table entries only maintained if upstream is BYTE seekable */
  gboolean upstream_seekable;
  /* minimum distance between two index entries */
  GstClockTimeDiff idx_interval;
  /* ts and offset of last entry added */
  GstClockTime index_last_ts;
  guint64 index_last_offset;
266
267
268
269
270

  /* 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;
271

272
273
274
275
276
  /* reverse playback */
  GSList *buffers_pending;
  GSList *buffers_queued;
  GstClockTime last_ts;
  gint64 last_offset;
277
278
};

279
280
281
282
283
284
285
286
typedef struct _GstBaseParseSeek
{
  GstSegment segment;
  gboolean accurate;
  gint64 offset;
  GstClockTime start_ts;
} GstBaseParseSeek;

287
288
289
290
291
292
293
294
295
296
297
298
299
300
static GstElementClass *parent_class = NULL;

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)
{
  static GType base_parse_type = 0;

  if (!base_parse_type) {
    static const GTypeInfo base_parse_info = {
      sizeof (GstBaseParseClass),
301
302
      (GBaseInitFunc) NULL,
      (GBaseFinalizeFunc) NULL,
303
304
305
306
307
308
309
310
311
      (GClassInitFunc) gst_base_parse_class_init,
      NULL,
      NULL,
      sizeof (GstBaseParse),
      0,
      (GInstanceInitFunc) gst_base_parse_init,
    };

    base_parse_type = g_type_register_static (GST_TYPE_ELEMENT,
312
        "GstAudioBaseParseBad", &base_parse_info, G_TYPE_FLAG_ABSTRACT);
313
314
315
316
317
318
  }
  return base_parse_type;
}

static void gst_base_parse_finalize (GObject * object);

319
320
321
322
static GstStateChangeReturn gst_base_parse_change_state (GstElement * element,
    GstStateChange transition);
static void gst_base_parse_reset (GstBaseParse * parse);

323
324
325
static void gst_base_parse_set_index (GstElement * element, GstIndex * index);
static GstIndex *gst_base_parse_get_index (GstElement * element);

326
327
328
329
330
331
332
static gboolean gst_base_parse_sink_activate (GstPad * sinkpad);
static gboolean gst_base_parse_sink_activate_push (GstPad * pad,
    gboolean active);
static gboolean gst_base_parse_sink_activate_pull (GstPad * pad,
    gboolean active);
static gboolean gst_base_parse_handle_seek (GstBaseParse * parse,
    GstEvent * event);
333
static void gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event);
334
335
336
337
338
339
340
341
342
343
344
345
346

static gboolean gst_base_parse_src_event (GstPad * pad, GstEvent * event);
static gboolean gst_base_parse_sink_event (GstPad * pad, GstEvent * event);
static gboolean gst_base_parse_query (GstPad * pad, GstQuery * query);
static gboolean gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps);
static const GstQueryType *gst_base_parse_get_querytypes (GstPad * pad);

static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstBuffer * buffer);
static void gst_base_parse_loop (GstPad * pad);

static gboolean gst_base_parse_check_frame (GstBaseParse * parse,
    GstBuffer * buffer, guint * framesize, gint * skipsize);

347
static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse,
348
349
350
351
352
353
354
355
356
357
    GstBuffer * buffer);

static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse,
    GstEvent * event);

static gboolean gst_base_parse_src_eventfunc (GstBaseParse * parse,
    GstEvent * event);

static void gst_base_parse_drain (GstBaseParse * parse);

358
359
360
static void gst_base_parse_post_bitrates (GstBaseParse * parse,
    gboolean post_min, gboolean post_avg, gboolean post_max);

361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
static gint64 gst_base_parse_find_offset (GstBaseParse * parse,
    GstClockTime time, gboolean before, GstClockTime * _ts);

static GstFlowReturn gst_base_parse_process_fragment (GstBaseParse * parse,
    gboolean push_only);

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;
}

379
380
381
382
static void
gst_base_parse_finalize (GObject * object)
{
  GstBaseParse *parse = GST_BASE_PARSE (object);
383
  GstEvent **p_ev;
384
385
386
387
388

  g_mutex_free (parse->parse_lock);
  g_object_unref (parse->adapter);

  if (parse->pending_segment) {
389
390
    p_ev = &parse->pending_segment;
    gst_event_replace (p_ev, NULL);
391
392
  }
  if (parse->close_segment) {
393
394
    p_ev = &parse->close_segment;
    gst_event_replace (p_ev, NULL);
395
396
397
398
399
400
401
402
403
404
405
406
  }

  if (parse->priv->cache) {
    gst_buffer_unref (parse->priv->cache);
    parse->priv->cache = NULL;
  }

  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;

407
408
409
410
411
  if (parse->priv->index) {
    gst_object_unref (parse->priv->index);
    parse->priv->index = NULL;
  }

412
413
  gst_base_parse_clear_queues (parse);

414
415
416
417
418
419
420
  G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
gst_base_parse_class_init (GstBaseParseClass * klass)
{
  GObjectClass *gobject_class;
421
  GstElementClass *gstelement_class;
422
423
424
425
426
427

  gobject_class = G_OBJECT_CLASS (klass);
  g_type_class_add_private (klass, sizeof (GstBaseParsePrivate));
  parent_class = g_type_class_peek_parent (klass);
  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_parse_finalize);

428
429
430
  gstelement_class = (GstElementClass *) klass;
  gstelement_class->change_state =
      GST_DEBUG_FUNCPTR (gst_base_parse_change_state);
431
432
  gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_base_parse_set_index);
  gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_base_parse_get_index);
433

434
435
436
437
  /* Default handlers */
  klass->check_valid_frame = gst_base_parse_check_frame;
  klass->parse_frame = gst_base_parse_parse_frame;
  klass->src_event = gst_base_parse_src_eventfunc;
438
  klass->convert = gst_base_parse_convert_default;
439
440
441

  GST_DEBUG_CATEGORY_INIT (gst_base_parse_debug, "baseparse", 0,
      "baseparse element");
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
}

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

  GST_DEBUG_OBJECT (parse, "gst_base_parse_init");

  parse->priv = GST_BASE_PARSE_GET_PRIVATE (parse);

  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));
  gst_pad_set_setcaps_function (parse->sinkpad,
      GST_DEBUG_FUNCPTR (gst_base_parse_sink_setcaps));
  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));
  gst_pad_set_activatepush_function (parse->sinkpad,
      GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_push));
  gst_pad_set_activatepull_function (parse->sinkpad,
      GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_pull));
  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_type_function (parse->srcpad,
      GST_DEBUG_FUNCPTR (gst_base_parse_get_querytypes));
  gst_pad_set_query_function (parse->srcpad,
      GST_DEBUG_FUNCPTR (gst_base_parse_query));
483
  gst_pad_use_fixed_caps (parse->srcpad);
484
485
486
487
488
489
490
  gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad);
  GST_DEBUG_OBJECT (parse, "src created");

  parse->parse_lock = g_mutex_new ();
  parse->adapter = gst_adapter_new ();

  parse->priv->pad_mode = GST_ACTIVATE_NONE;
491
492
493
494
495
496
497
498
499
500
501

  /* init state */
  gst_base_parse_reset (parse);
  GST_DEBUG_OBJECT (parse, "init ok");
}

static void
gst_base_parse_reset (GstBaseParse * parse)
{
  GST_OBJECT_LOCK (parse);
  gst_segment_init (&parse->segment, GST_FORMAT_TIME);
502
503
  parse->priv->duration = -1;
  parse->priv->min_frame_size = 1;
504
  parse->priv->discont = TRUE;
505
506
  parse->priv->flushing = FALSE;
  parse->priv->offset = 0;
507
508
509
510
  parse->priv->sync_offset = 0;
  parse->priv->update_interval = 50;
  parse->priv->fps_num = parse->priv->fps_den = 0;
  parse->priv->frame_duration = GST_CLOCK_TIME_NONE;
511
512
  parse->priv->lead_in = parse->priv->lead_out = 0;
  parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0;
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
  parse->priv->seekable = GST_BASE_PARSE_SEEK_DEFAULT;
  parse->priv->bitrate = 0;
  parse->priv->framecount = 0;
  parse->priv->bytecount = 0;
  parse->priv->acc_duration = 0;
  parse->priv->estimated_duration = -1;
  parse->priv->next_ts = 0;
  parse->priv->passthrough = FALSE;
  parse->priv->post_min_bitrate = TRUE;
  parse->priv->post_avg_bitrate = TRUE;
  parse->priv->post_max_bitrate = TRUE;
  parse->priv->min_bitrate = G_MAXUINT;
  parse->priv->max_bitrate = 0;
  parse->priv->avg_bitrate = 0;
  parse->priv->posted_avg_bitrate = 0;

529
530
531
532
  parse->priv->index_last_ts = 0;
  parse->priv->index_last_offset = 0;
  parse->priv->upstream_seekable = FALSE;
  parse->priv->idx_interval = 0;
533
  parse->priv->exact_position = TRUE;
534

535
536
537
  parse->priv->last_ts = GST_CLOCK_TIME_NONE;
  parse->priv->last_offset = 0;

538
539
  if (parse->pending_segment)
    gst_event_unref (parse->pending_segment);
540

541
542
543
544
  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;
545

546
547
548
549
  if (parse->priv->cache) {
    gst_buffer_unref (parse->priv->cache);
    parse->priv->cache = NULL;
  }
550
551
552
553
554

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

555
556
  GST_OBJECT_UNLOCK (parse);
}
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586

/**
 * gst_base_parse_check_frame:
 * @parse: #GstBaseParse.
 * @buffer: GstBuffer.
 * @framesize: This will be set to tell the found frame size in bytes.
 * @skipsize: Output parameter that tells how much data needs to be skipped
 *            in order to find the following frame header.
 *
 * Default callback for check_valid_frame.
 * 
 * Returns: Always TRUE.
 */
static gboolean
gst_base_parse_check_frame (GstBaseParse * parse,
    GstBuffer * buffer, guint * framesize, gint * skipsize)
{
  *framesize = GST_BUFFER_SIZE (buffer);
  *skipsize = 0;
  return TRUE;
}


/**
 * gst_base_parse_parse_frame:
 * @parse: #GstBaseParse.
 * @buffer: #GstBuffer.
 *
 * Default callback for parse_frame.
 */
587
static GstFlowReturn
588
589
gst_base_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer)
{
590
591
592
593
594
595
596
597
  if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
      GST_CLOCK_TIME_IS_VALID (parse->priv->next_ts)) {
    GST_BUFFER_TIMESTAMP (buffer) = parse->priv->next_ts;
  }
  if (!GST_BUFFER_DURATION_IS_VALID (buffer) &&
      GST_CLOCK_TIME_IS_VALID (parse->priv->frame_duration)) {
    GST_BUFFER_DURATION (buffer) = parse->priv->frame_duration;
  }
598
  return GST_FLOW_OK;
599
600
601
}

/**
602
 * gst_base_parse_convert:
603
 * @parse: #GstBaseParse.
604
605
606
607
 * @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.
608
 *
609
610
611
 * Converts using configured "convert" vmethod in #GstBaseParse class.
 *
 * Returns: TRUE if conversion was successful.
612
613
 */
static gboolean
614
615
616
gst_base_parse_convert (GstBaseParse * parse,
    GstFormat src_format,
    gint64 src_value, GstFormat dest_format, gint64 * dest_value)
617
{
618
619
  GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
  gboolean ret;
620

621
622
623
624
  g_return_val_if_fail (dest_value != NULL, FALSE);

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

626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
  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");
    }
650
  }
651
#endif
652

653
654
  return ret;
}
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
680
681
682
683
684

/**
 * gst_base_parse_sink_event:
 * @pad: #GstPad that received the event.
 * @event: #GstEvent to be handled.
 *
 * Handler for sink pad events.
 *
 * Returns: TRUE if the event was handled.
 */
static gboolean
gst_base_parse_sink_event (GstPad * pad, GstEvent * event)
{
  GstBaseParse *parse;
  GstBaseParseClass *bclass;
  gboolean handled = FALSE;
  gboolean ret = TRUE;


  parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
  bclass = GST_BASE_PARSE_GET_CLASS (parse);

  GST_DEBUG_OBJECT (parse, "handling event %d", GST_EVENT_TYPE (event));

  /* Cache all events except EOS, NEWSEGMENT and FLUSH_STOP if we have a
   * pending segment */
  if (parse->pending_segment && GST_EVENT_TYPE (event) != GST_EVENT_EOS
      && GST_EVENT_TYPE (event) != GST_EVENT_NEWSEGMENT
      && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_START
      && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP) {
685
686
687
688
689

    if (GST_EVENT_TYPE (event) == GST_EVENT_TAG)
      /* See if any bitrate tags were posted */
      gst_base_parse_handle_tag (parse, event);

690
691
692
693
694
    parse->priv->pending_events =
        g_list_append (parse->priv->pending_events, event);
    ret = TRUE;
  } else {

695
696
697
698
699
    if (GST_EVENT_TYPE (event) == GST_EVENT_EOS &&
        parse->priv->framecount < MIN_FRAMES_TO_POST_BITRATE)
      /* We've not posted bitrate tags yet - do so now */
      gst_base_parse_post_bitrates (parse, TRUE, TRUE, TRUE);

700
701
702
    if (bclass->event)
      handled = bclass->event (parse, event);

703
704
705
    if (!handled)
      handled = gst_base_parse_sink_eventfunc (parse, event);

706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
    if (!handled)
      ret = gst_pad_event_default (pad, event);
  }

  gst_object_unref (parse);
  GST_DEBUG_OBJECT (parse, "event handled");
  return ret;
}


/**
 * gst_base_parse_sink_eventfunc:
 * @parse: #GstBaseParse.
 * @event: #GstEvent to be handled.
 *
 * Element-level event handler function.
 *
 * Returns: TRUE if the event was handled and not need forwarding.
 */
static gboolean
gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event)
{
  gboolean handled = FALSE;
  GstEvent **eventp;

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_NEWSEGMENT:
    {
      gdouble rate, applied_rate;
      GstFormat format;
736
      gint64 start, stop, pos, next_ts, offset = 0;
737
738
739
740
741
      gboolean update;

      gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
          &format, &start, &stop, &pos);

742
743
744
745
      GST_DEBUG_OBJECT (parse, "newseg rate %g, applied rate %g, "
          "format %d, start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT
          ", pos = %" GST_TIME_FORMAT, rate, applied_rate, format,
          GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (pos));
746
747

      if (format == GST_FORMAT_BYTES) {
748
749
750
        GstClockTime seg_start, seg_stop;
        GstBaseParseSeek *seek = NULL;
        GSList *node;
751
752
753

        /* stop time is allowed to be open-ended, but not start & pos */
        seg_stop = GST_CLOCK_TIME_NONE;
754
        seg_start = 0;
755
        offset = pos;
756

757
758
759
760
761
762
763
764
        GST_OBJECT_LOCK (parse);
        for (node = parse->priv->pending_seeks; node; node = node->next) {
          GstBaseParseSeek *tmp = node->data;

          if (tmp->offset == pos) {
            seek = tmp;
            break;
          }
765
        }
766
767
768
        parse->priv->pending_seeks =
            g_slist_remove (parse->priv->pending_seeks, seek);
        GST_OBJECT_UNLOCK (parse);
769

770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
        if (seek) {
          GST_DEBUG_OBJECT (parse,
              "Matched newsegment to%s seek: %" GST_SEGMENT_FORMAT,
              seek->accurate ? " accurate" : "", &seek->segment);
          seg_start = seek->segment.start;
          seg_stop = seek->segment.stop;
          next_ts = seek->start_ts;
          parse->priv->exact_position = seek->accurate;
          g_free (seek);
        } else {
          /* best attempt convert */
          /* as these are only estimates, stop is kept open-ended to avoid
           * premature cutting */
          gst_base_parse_convert (parse, GST_FORMAT_BYTES, start,
              GST_FORMAT_TIME, (gint64 *) & seg_start);
          parse->priv->exact_position = (start == 0);
          next_ts = seg_start;
        }

        gst_event_unref (event);
        event = gst_event_new_new_segment_full (update, rate, applied_rate,
            GST_FORMAT_TIME, seg_start, seg_stop, seg_start);
        format = GST_FORMAT_TIME;
        start = seg_start;
        stop = seg_stop;
        GST_DEBUG_OBJECT (parse, "Converted incoming segment to TIME. "
            "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT,
            GST_TIME_ARGS (seg_start), GST_TIME_ARGS (seg_stop));
      } else if (format != GST_FORMAT_TIME) {
799
800
801
802
803
        /* Unknown incoming segment format. Output a default open-ended 
         * TIME segment */
        gst_event_unref (event);
        event = gst_event_new_new_segment_full (update, rate, applied_rate,
            GST_FORMAT_TIME, 0, GST_CLOCK_TIME_NONE, 0);
804
805
806
        format = GST_FORMAT_TIME;
        next_ts = start = 0;
        stop = GST_CLOCK_TIME_NONE;
807
808
809
810
      } else {
        /* not considered BYTE seekable if it is talking to us in TIME,
         * whatever else it might claim */
        parse->priv->upstream_seekable = FALSE;
811
        next_ts = start;
812
813
814
      }

      gst_segment_set_newsegment_full (&parse->segment, update, rate,
815
          applied_rate, format, start, stop, start);
816
817
818
819
820
821
822
823

      /* save the segment for later, right before we push a new buffer so that
       * the caps are fixed and the next linked element can receive
       * the segment. */
      eventp = &parse->pending_segment;
      gst_event_replace (eventp, event);
      gst_event_unref (event);
      handled = TRUE;
824
825
826

      /* but finish the current segment */
      GST_DEBUG_OBJECT (parse, "draining current segment");
827
828
829
830
      if (parse->segment.rate > 0.0)
        gst_base_parse_drain (parse);
      else
        gst_base_parse_process_fragment (parse, FALSE);
831
832
      gst_adapter_clear (parse->adapter);
      parse->priv->offset = offset;
833
      parse->priv->sync_offset = offset;
834
      parse->priv->next_ts = next_ts;
835
      parse->priv->last_ts = GST_CLOCK_TIME_NONE;
836
      parse->priv->discont = TRUE;
837
838
839
840
841
      break;
    }

    case GST_EVENT_FLUSH_START:
      parse->priv->flushing = TRUE;
842
      handled = gst_pad_push_event (parse->srcpad, event);
843
844
845
      /* Wait for _chain() to exit by taking the srcpad STREAM_LOCK */
      GST_PAD_STREAM_LOCK (parse->srcpad);
      GST_PAD_STREAM_UNLOCK (parse->srcpad);
846

847
848
849
850
      break;

    case GST_EVENT_FLUSH_STOP:
      gst_adapter_clear (parse->adapter);
851
      gst_base_parse_clear_queues (parse);
852
853
      parse->priv->flushing = FALSE;
      parse->priv->discont = TRUE;
854
      parse->priv->last_ts = GST_CLOCK_TIME_NONE;
855
856
857
      break;

    case GST_EVENT_EOS:
858
859
860
861
      if (parse->segment.rate > 0.0)
        gst_base_parse_drain (parse);
      else
        gst_base_parse_process_fragment (parse, FALSE);
862
863
864
865
866
867
868
869
870
871
872

      /* If we STILL have zero frames processed, fire an error */
      if (parse->priv->framecount == 0) {
        GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE,
            ("No valid frames found before end of stream"), (NULL));
      }
      /* newsegment before eos */
      if (parse->pending_segment) {
        gst_pad_push_event (parse->srcpad, parse->pending_segment);
        parse->pending_segment = NULL;
      }
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
      break;

    default:
      break;
  }

  return handled;
}


/**
 * gst_base_parse_src_event:
 * @pad: #GstPad that received the event.
 * @event: #GstEvent that was received.
 *
 * Handler for source pad events.
 *
 * Returns: TRUE if the event was handled.
 */
static gboolean
gst_base_parse_src_event (GstPad * pad, GstEvent * event)
{
  GstBaseParse *parse;
  GstBaseParseClass *bclass;
  gboolean handled = FALSE;
  gboolean ret = TRUE;

  parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
  bclass = GST_BASE_PARSE_GET_CLASS (parse);

  GST_DEBUG_OBJECT (parse, "event %d, %s", GST_EVENT_TYPE (event),
      GST_EVENT_TYPE_NAME (event));

  if (bclass->src_event)
    handled = bclass->src_event (parse, event);

  if (!handled)
    ret = gst_pad_event_default (pad, event);
911
912
  else
    gst_event_unref (event);
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938

  gst_object_unref (parse);
  return ret;
}


/**
 * gst_base_parse_src_eventfunc:
 * @parse: #GstBaseParse.
 * @event: #GstEvent that was received.
 *
 * Default srcpad event handler.
 *
 * Returns: TRUE if the event was handled and can be dropped.
 */
static gboolean
gst_base_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event)
{
  gboolean handled = FALSE;
  GstBaseParseClass *bclass;

  bclass = GST_BASE_PARSE_GET_CLASS (parse);

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_SEEK:
    {
939
      if (parse->priv->seekable > GST_BASE_PARSE_SEEK_NONE) {
940
941
942
943
944
945
946
947
948
949
950
        handled = gst_base_parse_handle_seek (parse, event);
      }
      break;
    }
    default:
      break;
  }
  return handled;
}


951
/**
952
 * gst_base_parse_convert_default:
953
954
955
956
957
958
 * @parse: #GstBaseParse.
 * @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.
 *
959
 * Default implementation of "convert" vmethod in #GstBaseParse class.
960
961
962
963
 *
 * Returns: TRUE if conversion was successful.
 */
gboolean
964
gst_base_parse_convert_default (GstBaseParse * parse,
965
966
967
968
    GstFormat src_format,
    gint64 src_value, GstFormat dest_format, gint64 * dest_value)
{
  gboolean ret = FALSE;
969
  guint64 bytes, duration;
970

971
  if (G_UNLIKELY (src_format == dest_format)) {
972
973
974
975
    *dest_value = src_value;
    return TRUE;
  }

976
977
978
979
980
  if (G_UNLIKELY (src_value == -1)) {
    *dest_value = -1;
    return TRUE;
  }

981
982
983
984
985
  if (G_UNLIKELY (src_value == 0)) {
    *dest_value = 0;
    return TRUE;
  }

986
987
988
989
  /* need at least some frames */
  if (!parse->priv->framecount)
    return FALSE;

990
991
  duration = parse->priv->acc_duration / GST_MSECOND;
  bytes = parse->priv->bytecount;
992
993

  if (G_UNLIKELY (!duration || !bytes))
994
995
996
997
998
999
    return FALSE;

  if (src_format == GST_FORMAT_BYTES) {
    if (dest_format == GST_FORMAT_TIME) {
      /* BYTES -> TIME conversion */
      GST_DEBUG_OBJECT (parse, "converting bytes -> time");
1000
      *dest_value = gst_util_uint64_scale (src_value, duration, bytes);