~oah-dev/oah/gst-plugins-bad

« back to all changes in this revision

Viewing changes to ext/resindvd/gstpesfilter.c

  • Committer: Haakon Sporsheim
  • Date: 2009-03-12 13:52:03 UTC
  • Revision ID: haakon.sporsheim@tandberg.com-20090312135203-i5k294hgkushb0mt
Initial import of git repository: git://anongit.freedesktop.org/gstreamer/gst-plugins-bad (tag: RELEASE-0_10_10)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * The contents of this file are subject to the Mozilla Public License
 
3
 * Version 1.1 (the "License"); you may not use this file except in
 
4
 * compliance with the License. You may obtain a copy of the License at
 
5
 * http://www.mozilla.org/MPL/.
 
6
 *
 
7
 * Software distributed under the License is distributed on an "AS IS"
 
8
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 
9
 * License for the specific language governing rights and limitations
 
10
 * under the License.
 
11
 *
 
12
 * The Original Code is Fluendo MPEG Demuxer plugin.
 
13
 *
 
14
 * The Initial Developer of the Original Code is Fluendo, S.L.
 
15
 * Portions created by Fluendo, S.L. are Copyright (C) 2005
 
16
 * Fluendo, S.L. All Rights Reserved.
 
17
 *
 
18
 * Contributor(s): Wim Taymans <wim@fluendo.com>
 
19
 *                 Jan Schmidt <thaytan@noraisin.net>
 
20
 */
 
21
 
 
22
#ifdef HAVE_CONFIG_H
 
23
#include "config.h"
 
24
#endif
 
25
 
 
26
#include "gstmpegdefs.h"
 
27
#include "gstpesfilter.h"
 
28
 
 
29
GST_DEBUG_CATEGORY (gstflupesfilter_debug);
 
30
#define GST_CAT_DEFAULT (gstflupesfilter_debug)
 
31
 
 
32
static GstFlowReturn gst_pes_filter_data_push (GstPESFilter * filter,
 
33
    gboolean first, GstBuffer * buffer);
 
34
 
 
35
#define ADAPTER_OFFSET_FLUSH(_bytes_)  if (filter->adapter_offset) *filter->adapter_offset = *filter->adapter_offset + (_bytes_)
 
36
 
 
37
/* May pass null for adapter to have the filter create one */
 
38
void
 
39
gst_pes_filter_init (GstPESFilter * filter, GstAdapter * adapter,
 
40
    guint64 * adapter_offset)
 
41
{
 
42
  g_return_if_fail (filter != NULL);
 
43
 
 
44
  if (adapter != NULL)
 
45
    g_object_ref (adapter);
 
46
  else
 
47
    adapter = gst_adapter_new ();
 
48
 
 
49
  filter->adapter = adapter;
 
50
  filter->adapter_offset = adapter_offset;
 
51
  filter->state = STATE_HEADER_PARSE;
 
52
  filter->gather_pes = FALSE;
 
53
  filter->allow_unbounded = FALSE;
 
54
}
 
55
 
 
56
void
 
57
gst_pes_filter_uninit (GstPESFilter * filter)
 
58
{
 
59
  g_return_if_fail (filter != NULL);
 
60
 
 
61
  if (filter->adapter)
 
62
    g_object_unref (filter->adapter);
 
63
  filter->adapter = NULL;
 
64
  filter->adapter_offset = NULL;
 
65
}
 
66
 
 
67
void
 
68
gst_pes_filter_set_callbacks (GstPESFilter * filter,
 
69
    GstPESFilterData data_cb, GstPESFilterResync resync_cb, gpointer user_data)
 
70
{
 
71
  g_return_if_fail (filter != NULL);
 
72
 
 
73
  filter->data_cb = data_cb;
 
74
  filter->resync_cb = resync_cb;
 
75
  filter->user_data = user_data;
 
76
}
 
77
 
 
78
/* sync:4 == 00xx ! pts:3 ! 1 ! pts:15 ! 1 | pts:15 ! 1 */
 
79
#define READ_TS(data, target, lost_sync_label)          \
 
80
    if ((*data & 0x01) != 0x01) goto lost_sync_label;   \
 
81
    target  = ((guint64) (*data++ & 0x0E)) << 29;       \
 
82
    target |= ((guint64) (*data++       )) << 22;       \
 
83
    if ((*data & 0x01) != 0x01) goto lost_sync_label;   \
 
84
    target |= ((guint64) (*data++ & 0xFE)) << 14;       \
 
85
    target |= ((guint64) (*data++       )) << 7;        \
 
86
    if ((*data & 0x01) != 0x01) goto lost_sync_label;   \
 
87
    target |= ((guint64) (*data++ & 0xFE)) >> 1;
 
88
 
 
89
static gboolean
 
90
gst_pes_filter_is_sync (guint32 sync)
 
91
{
 
92
  return ((sync & 0xfffffffc) == 0x000001bc) ||
 
93
      ((sync & 0xffffffe0) == 0x000001c0) ||
 
94
      ((sync & 0xfffffff0) == 0x000001f0) ||
 
95
      ((sync & 0xfffffff0) == 0x000001e0);
 
96
}
 
97
 
 
98
static GstFlowReturn
 
99
gst_pes_filter_parse (GstPESFilter * filter)
 
100
{
 
101
  GstFlowReturn ret;
 
102
  guint32 start_code;
 
103
 
 
104
  gboolean STD_buffer_bound_scale;
 
105
  guint16 STD_buffer_size_bound;
 
106
  const guint8 *data;
 
107
  gint avail, datalen;
 
108
  gboolean have_size = FALSE;
 
109
 
 
110
  /* read start code and length */
 
111
  if (!(data = gst_adapter_peek (filter->adapter, 6)))
 
112
    goto need_more_data;
 
113
 
 
114
  /* get start code */
 
115
  start_code = GST_READ_UINT32_BE (data);
 
116
  if (!gst_pes_filter_is_sync (start_code))
 
117
    goto lost_sync;
 
118
 
 
119
  filter->start_code = start_code;
 
120
  filter->id = data[3];
 
121
 
 
122
  /* skip start code */
 
123
  data += 4;
 
124
 
 
125
  /* start parsing length */
 
126
  filter->length = GST_READ_UINT16_BE (data);
 
127
 
 
128
  /* see how much is available */
 
129
  avail = gst_adapter_available (filter->adapter);
 
130
 
 
131
  GST_DEBUG ("id 0x%02x length %d, avail %d start code 0x%02x", filter->id,
 
132
      filter->length, avail, filter->start_code);
 
133
 
 
134
  /* A data length of 0 indicates an unbounded packet in transport
 
135
   * streams, but actually a 0 sized packet in program streams or
 
136
   * for anything except video packets */
 
137
 
 
138
  /* FIXME: Remove this hack that is checking start_code. Instead, we need
 
139
   * a callback that a start_code has been collected, giving the caller a chance
 
140
   * to set the allow_unbounded flag if they want */
 
141
  if (filter->length == 0 &&
 
142
      ((filter->start_code & 0xFFFFFFF0) == PACKET_VIDEO_START_CODE ||
 
143
          filter->allow_unbounded)) {
 
144
    GST_DEBUG ("id 0x%02x, unbounded length", filter->id);
 
145
    filter->unbounded_packet = TRUE;
 
146
  } else {
 
147
    filter->unbounded_packet = FALSE;
 
148
 
 
149
    if (filter->gather_pes && avail < filter->length + 6) {
 
150
      GST_DEBUG ("id 0x%02x, bounded length %d, only have %d",
 
151
          filter->id, filter->length + 6, avail);
 
152
      goto need_more_data;
 
153
    }
 
154
 
 
155
    /* if we need more data from now on, we lost sync */
 
156
    avail = MIN (avail, filter->length + 6);
 
157
  }
 
158
 
 
159
  /* read more data, either the whole packet if there is a length
 
160
   * or whatever we have available if this in an unbounded packet. */
 
161
  if (!(data = gst_adapter_peek (filter->adapter, avail)))
 
162
    goto need_more_data;
 
163
 
 
164
  /* This will make us flag LOST_SYNC if we run out of data from here onward */
 
165
  have_size = TRUE;
 
166
 
 
167
  /* skip start code and length */
 
168
  data += 6;
 
169
  datalen = avail - 6;
 
170
 
 
171
  GST_DEBUG ("datalen %d", datalen);
 
172
 
 
173
  switch (filter->start_code) {
 
174
    case ID_PS_PROGRAM_STREAM_MAP:
 
175
    case ID_PRIVATE_STREAM_2:
 
176
    case ID_ECM_STREAM:
 
177
    case ID_EMM_STREAM:
 
178
    case ID_PROGRAM_STREAM_DIRECTORY:
 
179
    case ID_DSMCC_STREAM:
 
180
    case ID_ITU_TREC_H222_TYPE_E_STREAM:
 
181
      goto skip;
 
182
    case ID_PADDING_STREAM:
 
183
      GST_DEBUG ("skipping padding stream");
 
184
      goto skip;
 
185
    default:
 
186
      break;
 
187
  }
 
188
 
 
189
  if (datalen < 1)
 
190
    goto need_more_data;
 
191
 
 
192
  filter->pts = filter->dts = -1;
 
193
 
 
194
  /* stuffing bits, first two bits are '10' for mpeg2 pes so this code is
 
195
   * not triggered. */
 
196
  while (TRUE) {
 
197
    if (*data != 0xff)
 
198
      break;
 
199
 
 
200
    data++;
 
201
    datalen--;
 
202
 
 
203
    GST_DEBUG ("got stuffing bit");
 
204
 
 
205
    if (datalen < 1)
 
206
      goto need_more_data;
 
207
  }
 
208
 
 
209
  /* STD buffer size, never for mpeg2 */
 
210
  if ((*data & 0xc0) == 0x40) {
 
211
    GST_DEBUG ("have STD");
 
212
 
 
213
    if (datalen < 3)
 
214
      goto need_more_data;
 
215
 
 
216
    STD_buffer_bound_scale = *data & 0x20;
 
217
    STD_buffer_size_bound = ((guint16) (*data++ & 0x1F)) << 8;
 
218
    STD_buffer_size_bound |= *data++;
 
219
 
 
220
    datalen -= 2;
 
221
  }
 
222
 
 
223
  /* PTS but no DTS, never for mpeg2 */
 
224
  if ((*data & 0xf0) == 0x20) {
 
225
    GST_DEBUG ("PTS without DTS");
 
226
 
 
227
    if (datalen < 5)
 
228
      goto need_more_data;
 
229
    READ_TS (data, filter->pts, lost_sync);
 
230
    GST_DEBUG ("PTS found %" G_GUINT64_FORMAT, filter->pts);
 
231
    datalen -= 5;
 
232
  }
 
233
  /* PTS and DTS, never for mpeg2 */
 
234
  else if ((*data & 0xf0) == 0x30) {
 
235
    GST_DEBUG ("PTS and DTS");
 
236
 
 
237
    if (datalen < 10)
 
238
      goto need_more_data;
 
239
    READ_TS (data, filter->pts, lost_sync);
 
240
    READ_TS (data, filter->dts, lost_sync);
 
241
    GST_DEBUG ("PTS found %" G_GUINT64_FORMAT, filter->pts);
 
242
    GST_DEBUG ("DTS found %" G_GUINT64_FORMAT, filter->dts);
 
243
    datalen -= 10;
 
244
  } else if ((*data & 0xc0) == 0x80) {
 
245
    /* mpeg2 case */
 
246
    guchar flags;
 
247
    guint8 header_data_length = 0;
 
248
 
 
249
    GST_DEBUG ("MPEG2 PES packet");
 
250
 
 
251
    if (datalen < 3)
 
252
      goto need_more_data;
 
253
    /* 2: '10'
 
254
     * 2: PES_scrambling_control
 
255
     * 1: PES_priority
 
256
     * 1: data_alignment_indicator
 
257
     * 1: copyright
 
258
     * 1: original_or_copy
 
259
     */
 
260
    flags = *data++;
 
261
 
 
262
    GST_DEBUG ("flags: 0x%02x", flags);
 
263
    if ((flags & 0xc0) != 0x80)
 
264
      goto lost_sync;
 
265
 
 
266
    /* check PES scrambling control */
 
267
    if ((flags & 0x30) != 0)
 
268
      goto encrypted;
 
269
 
 
270
    /* 2: PTS_DTS_flags
 
271
     * 1: ESCR_flag
 
272
     * 1: ES_rate_flag
 
273
     * 1: DSM_trick_mode_flag
 
274
     * 1: additional_copy_info_flag
 
275
     * 1: PES_CRC_flag
 
276
     * 1: PES_extension_flag
 
277
     */
 
278
    flags = *data++;
 
279
 
 
280
    /* 8: PES_header_data_length */
 
281
    header_data_length = *data++;
 
282
    datalen -= 3;
 
283
 
 
284
    GST_DEBUG ("header_data_length: %d, flags 0x%02x",
 
285
        header_data_length, flags);
 
286
 
 
287
    if (header_data_length > datalen)
 
288
      goto need_more_data;
 
289
 
 
290
    /* only DTS: this is invalid */
 
291
    if ((flags & 0xc0) == 0x40)
 
292
      goto lost_sync;
 
293
 
 
294
    /* check for PTS */
 
295
    if ((flags & 0x80)) {
 
296
      if (datalen < 5)
 
297
        goto need_more_data;
 
298
 
 
299
      READ_TS (data, filter->pts, lost_sync);
 
300
      GST_DEBUG ("PTS found %" G_GUINT64_FORMAT, filter->pts);
 
301
      header_data_length -= 5;
 
302
      datalen -= 5;
 
303
    }
 
304
    /* check for DTS */
 
305
    if ((flags & 0x40)) {
 
306
      READ_TS (data, filter->dts, lost_sync);
 
307
      if (datalen < 5)
 
308
        goto need_more_data;
 
309
      GST_DEBUG ("DTS found %" G_GUINT64_FORMAT, filter->dts);
 
310
      header_data_length -= 5;
 
311
      datalen -= 5;
 
312
    }
 
313
    /* ESCR_flag */
 
314
    if ((flags & 0x20)) {
 
315
      GST_DEBUG ("%x ESCR found", filter->id);
 
316
      if (datalen < 6)
 
317
        goto need_more_data;
 
318
      data += 6;
 
319
      header_data_length -= 6;
 
320
      datalen -= 6;
 
321
    }
 
322
    /* ES_rate_flag */
 
323
    if ((flags & 0x10)) {
 
324
      guint32 es_rate;
 
325
 
 
326
      if (datalen < 3)
 
327
        goto need_more_data;
 
328
 
 
329
      es_rate = ((guint32) (*data++ & 0x07)) << 14;
 
330
      es_rate |= ((guint32) (*data++)) << 7;
 
331
      es_rate |= ((guint32) (*data++ & 0xFE)) >> 1;
 
332
      GST_DEBUG ("%x ES Rate found %u", filter->id, es_rate);
 
333
      header_data_length -= 3;
 
334
      datalen -= 3;
 
335
    }
 
336
    /* DSM_trick_mode_flag */
 
337
    if ((flags & 0x08)) {
 
338
      guint8 trick_mode_flags;
 
339
 
 
340
      if (datalen < 1)
 
341
        goto need_more_data;
 
342
 
 
343
      /* 3: trick_mode_control */
 
344
      trick_mode_flags = *data++;
 
345
      GST_DEBUG ("%x DSM trick mode found, flags 0x%02x", filter->id,
 
346
          trick_mode_flags);
 
347
 
 
348
      /* fast_forward */
 
349
      if ((trick_mode_flags & 0xe0) == 0x00) {
 
350
      }
 
351
      /* slow motion */
 
352
      else if ((trick_mode_flags & 0xe0) == 0x20) {
 
353
      }
 
354
      /* freeze frame */
 
355
      else if ((trick_mode_flags & 0xe0) == 0x40) {
 
356
      }
 
357
      /* fast reverse */
 
358
      else if ((trick_mode_flags & 0xe0) == 0x60) {
 
359
      }
 
360
      /* slow reverse */
 
361
      else if ((trick_mode_flags & 0xe0) == 0x80) {
 
362
      }
 
363
      /* reserved */
 
364
      else {
 
365
      }
 
366
 
 
367
      header_data_length -= 1;
 
368
      datalen -= 1;
 
369
    }
 
370
    /* additional_copy_info_flag  */
 
371
    if ((flags & 0x04)) {
 
372
      GST_DEBUG ("%x additional copy info, flags 0x%02x", filter->id, *data);
 
373
    }
 
374
    /* PES_CRC_flag  */
 
375
    if ((flags & 0x02)) {
 
376
      GST_DEBUG ("%x PES_CRC", filter->id);
 
377
    }
 
378
    /* PES_extension_flag  */
 
379
    if ((flags & 0x01)) {
 
380
      GST_DEBUG ("%x PES_extension", filter->id);
 
381
    }
 
382
 
 
383
    /* calculate the amount of real data in this PES packet */
 
384
    data += header_data_length;
 
385
    datalen -= header_data_length;
 
386
  } else if (*data == 0x0f) {
 
387
    /* Not sure what this clause is for */
 
388
    data++;
 
389
    datalen--;
 
390
  } else {
 
391
    /* Data byte wasn't recognised as a flags byte */
 
392
    GST_DEBUG ("Unrecognised flags byte 0x%02x\n", *data);
 
393
    goto lost_sync;
 
394
  }
 
395
 
 
396
  {
 
397
    GstBuffer *out;
 
398
    guint16 consumed;
 
399
 
 
400
    consumed = avail - 6 - datalen;
 
401
 
 
402
    if (filter->unbounded_packet == FALSE) {
 
403
      filter->length -= avail - 6;
 
404
      GST_DEBUG ("pushing %d, need %d more, consumed %d",
 
405
          datalen, filter->length, consumed);
 
406
    } else {
 
407
      GST_DEBUG ("pushing %d, unbounded packet, consumed %d",
 
408
          datalen, consumed);
 
409
    }
 
410
 
 
411
    if (datalen > 0) {
 
412
      out = gst_buffer_new ();
 
413
      GST_BUFFER_DATA (out) = g_memdup (data, datalen);
 
414
      GST_BUFFER_SIZE (out) = datalen;
 
415
      GST_BUFFER_MALLOCDATA (out) = GST_BUFFER_DATA (out);
 
416
 
 
417
      ret = gst_pes_filter_data_push (filter, TRUE, out);
 
418
      filter->first = FALSE;
 
419
    } else {
 
420
      GST_LOG ("first being set to TRUE");
 
421
      filter->first = TRUE;
 
422
      ret = GST_FLOW_OK;
 
423
    }
 
424
 
 
425
    if (filter->length > 0 || filter->unbounded_packet)
 
426
      filter->state = STATE_DATA_PUSH;
 
427
  }
 
428
 
 
429
  gst_adapter_flush (filter->adapter, avail);
 
430
  ADAPTER_OFFSET_FLUSH (avail);
 
431
 
 
432
  return ret;
 
433
 
 
434
need_more_data:
 
435
  {
 
436
    if (filter->unbounded_packet == FALSE) {
 
437
      if (have_size == TRUE) {
 
438
        GST_DEBUG ("bounded need more data %d, lost sync",
 
439
            gst_adapter_available (filter->adapter));
 
440
        ret = GST_FLOW_LOST_SYNC;
 
441
      } else {
 
442
        GST_DEBUG ("bounded need more data %d, breaking for more",
 
443
            gst_adapter_available (filter->adapter));
 
444
        ret = GST_FLOW_NEED_MORE_DATA;
 
445
      }
 
446
    } else {
 
447
      GST_DEBUG ("unbounded need more data %d",
 
448
          gst_adapter_available (filter->adapter));
 
449
      ret = GST_FLOW_NEED_MORE_DATA;
 
450
    }
 
451
 
 
452
    return ret;
 
453
  }
 
454
skip:
 
455
  {
 
456
    GST_DEBUG ("skipping 0x%02x", filter->id);
 
457
    gst_adapter_flush (filter->adapter, avail);
 
458
    ADAPTER_OFFSET_FLUSH (avail);
 
459
 
 
460
    filter->length -= avail - 6;
 
461
    if (filter->length > 0 || filter->unbounded_packet)
 
462
      filter->state = STATE_DATA_SKIP;
 
463
    return GST_FLOW_OK;
 
464
  }
 
465
encrypted:
 
466
  {
 
467
    GST_DEBUG ("skipping encrypted 0x%02x", filter->id);
 
468
    gst_adapter_flush (filter->adapter, avail);
 
469
    ADAPTER_OFFSET_FLUSH (avail);
 
470
 
 
471
    filter->length -= avail - 6;
 
472
    if (filter->length > 0 || filter->unbounded_packet)
 
473
      filter->state = STATE_DATA_SKIP;
 
474
    return GST_FLOW_OK;
 
475
  }
 
476
lost_sync:
 
477
  {
 
478
    GST_DEBUG ("lost sync");
 
479
    gst_adapter_flush (filter->adapter, 4);
 
480
    ADAPTER_OFFSET_FLUSH (4);
 
481
 
 
482
    return GST_FLOW_LOST_SYNC;
 
483
  }
 
484
}
 
485
 
 
486
static GstFlowReturn
 
487
gst_pes_filter_data_push (GstPESFilter * filter, gboolean first,
 
488
    GstBuffer * buffer)
 
489
{
 
490
  GstFlowReturn ret;
 
491
 
 
492
  GST_LOG ("pushing, first: %d", first);
 
493
 
 
494
  if (filter->data_cb) {
 
495
    ret = filter->data_cb (filter, first, buffer, filter->user_data);
 
496
  } else {
 
497
    gst_buffer_unref (buffer);
 
498
    ret = GST_FLOW_OK;
 
499
  }
 
500
  return ret;
 
501
}
 
502
 
 
503
GstFlowReturn
 
504
gst_pes_filter_push (GstPESFilter * filter, GstBuffer * buffer)
 
505
{
 
506
  GstFlowReturn ret;
 
507
 
 
508
  g_return_val_if_fail (filter != NULL, GST_FLOW_ERROR);
 
509
  g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
 
510
 
 
511
  switch (filter->state) {
 
512
    case STATE_HEADER_PARSE:
 
513
      gst_adapter_push (filter->adapter, buffer);
 
514
      ret = gst_pes_filter_parse (filter);
 
515
      break;
 
516
    case STATE_DATA_PUSH:
 
517
      ret = gst_pes_filter_data_push (filter, filter->first, buffer);
 
518
      filter->first = FALSE;
 
519
      break;
 
520
    case STATE_DATA_SKIP:
 
521
      gst_buffer_unref (buffer);
 
522
      ret = GST_FLOW_OK;
 
523
      break;
 
524
    default:
 
525
      goto wrong_state;
 
526
  }
 
527
  return ret;
 
528
 
 
529
  /* ERROR */
 
530
wrong_state:
 
531
  {
 
532
    GST_DEBUG ("wrong internal state %d", filter->state);
 
533
    return GST_FLOW_ERROR;
 
534
  }
 
535
}
 
536
 
 
537
GstFlowReturn
 
538
gst_pes_filter_process (GstPESFilter * filter)
 
539
{
 
540
  GstFlowReturn ret;
 
541
  gboolean skip = FALSE;
 
542
 
 
543
  g_return_val_if_fail (filter != NULL, GST_FLOW_ERROR);
 
544
 
 
545
  switch (filter->state) {
 
546
    case STATE_HEADER_PARSE:
 
547
      ret = gst_pes_filter_parse (filter);
 
548
      break;
 
549
    case STATE_DATA_SKIP:
 
550
      skip = TRUE;
 
551
      /* fallthrough */
 
552
    case STATE_DATA_PUSH:
 
553
      if (filter->length > 0 || filter->unbounded_packet) {
 
554
        gint avail;
 
555
 
 
556
        avail = gst_adapter_available (filter->adapter);
 
557
        if (filter->unbounded_packet == FALSE)
 
558
          avail = MIN (avail, filter->length);
 
559
 
 
560
        if (skip) {
 
561
          gst_adapter_flush (filter->adapter, avail);
 
562
          ADAPTER_OFFSET_FLUSH (avail);
 
563
          ret = GST_FLOW_OK;
 
564
        } else {
 
565
          GstBuffer *out;
 
566
          guint8 *data;
 
567
 
 
568
          data = gst_adapter_take (filter->adapter, avail);
 
569
 
 
570
          out = gst_buffer_new ();
 
571
          GST_BUFFER_DATA (out) = data;
 
572
          GST_BUFFER_SIZE (out) = avail;
 
573
          GST_BUFFER_MALLOCDATA (out) = data;
 
574
 
 
575
          ret = gst_pes_filter_data_push (filter, filter->first, out);
 
576
          filter->first = FALSE;
 
577
        }
 
578
 
 
579
        if (filter->unbounded_packet == FALSE) {
 
580
          filter->length -= avail;
 
581
          if (filter->length == 0)
 
582
            filter->state = STATE_HEADER_PARSE;
 
583
        }
 
584
      } else {
 
585
        filter->state = STATE_HEADER_PARSE;
 
586
        ret = GST_FLOW_OK;
 
587
      }
 
588
      break;
 
589
    default:
 
590
      goto wrong_state;
 
591
  }
 
592
  return ret;
 
593
 
 
594
  /* ERROR */
 
595
wrong_state:
 
596
  {
 
597
    GST_DEBUG ("wrong internal state %d", filter->state);
 
598
    return GST_FLOW_ERROR;
 
599
  }
 
600
}
 
601
 
 
602
void
 
603
gst_pes_filter_flush (GstPESFilter * filter)
 
604
{
 
605
  g_return_if_fail (filter != NULL);
 
606
 
 
607
  if (filter->adapter) {
 
608
    gst_adapter_clear (filter->adapter);
 
609
    if (filter->adapter_offset)
 
610
      *filter->adapter_offset = G_MAXUINT64;
 
611
  }
 
612
  filter->state = STATE_HEADER_PARSE;
 
613
}
 
614
 
 
615
GstFlowReturn
 
616
gst_pes_filter_drain (GstPESFilter * filter)
 
617
{
 
618
  g_return_val_if_fail (filter != NULL, GST_FLOW_ERROR);
 
619
 
 
620
  gst_pes_filter_flush (filter);
 
621
 
 
622
  return GST_FLOW_OK;
 
623
}