blob: e3b65075bab8ac2d620e7f253c47f46a918c1ae2 [file] [log] [blame]
Jan Schmidt1218cff2012-06-09 22:36:06 +10001 /*
2 * This library is licensed under 2 different licenses and you
3 * can choose to use it under the terms of either one of them. The
4 * two licenses are the MPL 1.1 and the LGPL.
5 *
6 * MPL:
7 *
8 * The contents of this file are subject to the Mozilla Public License
9 * Version 1.1 (the "License"); you may not use this file except in
10 * compliance with the License. You may obtain a copy of the License at
11 * http://www.mozilla.org/MPL/.
12 *
13 * Software distributed under the License is distributed on an "AS IS"
14 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
15 * License for the specific language governing rights and limitations
16 * under the License.
17 *
18 * LGPL:
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Library General Public
22 * License as published by the Free Software Foundation; either
23 * version 2 of the License, or (at your option) any later version.
24 *
25 * This library is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Library General Public License for more details.
29 *
30 * You should have received a copy of the GNU Library General Public
31 * License along with this library; if not, write to the
Tim-Philipp Müller9e1b75f2012-11-03 20:38:00 +000032 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
33 * Boston, MA 02110-1301, USA.
Jan Schmidt1218cff2012-06-09 22:36:06 +100034 *
35 * The Original Code is Fluendo MPEG Demuxer plugin.
36 *
37 * The Initial Developer of the Original Code is Fluendo, S.L.
38 * Portions created by Fluendo, S.L. are Copyright (C) 2005
39 * Fluendo, S.L. All Rights Reserved.
40 *
41 * Contributor(s): Wim Taymans <wim@fluendo.com>
42 */
Jan Schmidt0951e002008-06-17 01:08:14 +000043
44#ifdef HAVE_CONFIG_H
45#include "config.h"
46#endif
47
48#include "gstmpegdefs.h"
49#include "gstpesfilter.h"
50
Jan Schmidt1218cff2012-06-09 22:36:06 +100051GST_DEBUG_CATEGORY (mpegpspesfilter_debug);
52#define GST_CAT_DEFAULT (mpegpspesfilter_debug)
Jan Schmidt0951e002008-06-17 01:08:14 +000053
54static GstFlowReturn gst_pes_filter_data_push (GstPESFilter * filter,
55 gboolean first, GstBuffer * buffer);
56
57#define ADAPTER_OFFSET_FLUSH(_bytes_) if (filter->adapter_offset) *filter->adapter_offset = *filter->adapter_offset + (_bytes_)
58
59/* May pass null for adapter to have the filter create one */
60void
61gst_pes_filter_init (GstPESFilter * filter, GstAdapter * adapter,
62 guint64 * adapter_offset)
63{
64 g_return_if_fail (filter != NULL);
65
66 if (adapter != NULL)
67 g_object_ref (adapter);
68 else
69 adapter = gst_adapter_new ();
70
71 filter->adapter = adapter;
72 filter->adapter_offset = adapter_offset;
73 filter->state = STATE_HEADER_PARSE;
74 filter->gather_pes = FALSE;
75 filter->allow_unbounded = FALSE;
76}
77
78void
79gst_pes_filter_uninit (GstPESFilter * filter)
80{
81 g_return_if_fail (filter != NULL);
82
83 if (filter->adapter)
84 g_object_unref (filter->adapter);
85 filter->adapter = NULL;
86 filter->adapter_offset = NULL;
87}
88
89void
90gst_pes_filter_set_callbacks (GstPESFilter * filter,
91 GstPESFilterData data_cb, GstPESFilterResync resync_cb, gpointer user_data)
92{
93 g_return_if_fail (filter != NULL);
94
95 filter->data_cb = data_cb;
96 filter->resync_cb = resync_cb;
97 filter->user_data = user_data;
98}
99
Jan Schmidt0951e002008-06-17 01:08:14 +0000100static gboolean
101gst_pes_filter_is_sync (guint32 sync)
102{
103 return ((sync & 0xfffffffc) == 0x000001bc) ||
Jan Schmidt9d315362014-01-16 20:16:47 +1100104 ((sync & 0xfffffffd) == 0x000001bd) ||
Jan Schmidt0951e002008-06-17 01:08:14 +0000105 ((sync & 0xffffffe0) == 0x000001c0) ||
106 ((sync & 0xfffffff0) == 0x000001f0) ||
107 ((sync & 0xfffffff0) == 0x000001e0);
108}
109
110static GstFlowReturn
111gst_pes_filter_parse (GstPESFilter * filter)
112{
113 GstFlowReturn ret;
114 guint32 start_code;
115
Jan Schmidt1218cff2012-06-09 22:36:06 +1000116 gboolean STD_buffer_bound_scale G_GNUC_UNUSED;
Jan Schmidt0951e002008-06-17 01:08:14 +0000117 guint16 STD_buffer_size_bound;
118 const guint8 *data;
119 gint avail, datalen;
120 gboolean have_size = FALSE;
121
Jan Schmidt1218cff2012-06-09 22:36:06 +1000122 avail = gst_adapter_available (filter->adapter);
123
124 if (avail < 6)
Jan Schmidt0951e002008-06-17 01:08:14 +0000125 goto need_more_data;
126
Jan Schmidt1218cff2012-06-09 22:36:06 +1000127 data = gst_adapter_map (filter->adapter, 6);
128
129 /* read start code and length */
130
Jan Schmidt0951e002008-06-17 01:08:14 +0000131 /* get start code */
132 start_code = GST_READ_UINT32_BE (data);
133 if (!gst_pes_filter_is_sync (start_code))
134 goto lost_sync;
135
136 filter->start_code = start_code;
137 filter->id = data[3];
138
139 /* skip start code */
140 data += 4;
141
142 /* start parsing length */
143 filter->length = GST_READ_UINT16_BE (data);
144
Jan Schmidt0951e002008-06-17 01:08:14 +0000145 GST_DEBUG ("id 0x%02x length %d, avail %d start code 0x%02x", filter->id,
146 filter->length, avail, filter->start_code);
147
148 /* A data length of 0 indicates an unbounded packet in transport
149 * streams, but actually a 0 sized packet in program streams or
150 * for anything except video packets */
151
152 /* FIXME: Remove this hack that is checking start_code. Instead, we need
153 * a callback that a start_code has been collected, giving the caller a chance
154 * to set the allow_unbounded flag if they want */
155 if (filter->length == 0 &&
156 ((filter->start_code & 0xFFFFFFF0) == PACKET_VIDEO_START_CODE ||
Jan Schmidt1218cff2012-06-09 22:36:06 +1000157 filter->start_code == ID_EXTENDED_STREAM_ID ||
Jan Schmidt0951e002008-06-17 01:08:14 +0000158 filter->allow_unbounded)) {
159 GST_DEBUG ("id 0x%02x, unbounded length", filter->id);
160 filter->unbounded_packet = TRUE;
161 } else {
162 filter->unbounded_packet = FALSE;
163
164 if (filter->gather_pes && avail < filter->length + 6) {
165 GST_DEBUG ("id 0x%02x, bounded length %d, only have %d",
166 filter->id, filter->length + 6, avail);
167 goto need_more_data;
168 }
169
170 /* if we need more data from now on, we lost sync */
171 avail = MIN (avail, filter->length + 6);
172 }
173
Jan Schmidt1218cff2012-06-09 22:36:06 +1000174 if (avail < 6)
175 goto need_more_data;
176
177 gst_adapter_unmap (filter->adapter);
178
Jan Schmidt0951e002008-06-17 01:08:14 +0000179 /* read more data, either the whole packet if there is a length
180 * or whatever we have available if this in an unbounded packet. */
Jan Schmidt1218cff2012-06-09 22:36:06 +1000181 data = gst_adapter_map (filter->adapter, avail);
Jan Schmidt0951e002008-06-17 01:08:14 +0000182
183 /* This will make us flag LOST_SYNC if we run out of data from here onward */
184 have_size = TRUE;
185
186 /* skip start code and length */
187 data += 6;
188 datalen = avail - 6;
189
190 GST_DEBUG ("datalen %d", datalen);
191
192 switch (filter->start_code) {
193 case ID_PS_PROGRAM_STREAM_MAP:
194 case ID_PRIVATE_STREAM_2:
195 case ID_ECM_STREAM:
196 case ID_EMM_STREAM:
197 case ID_PROGRAM_STREAM_DIRECTORY:
198 case ID_DSMCC_STREAM:
199 case ID_ITU_TREC_H222_TYPE_E_STREAM:
Jan Schmidt1218cff2012-06-09 22:36:06 +1000200 /* Push directly out */
201 goto push_out;
Jan Schmidt0951e002008-06-17 01:08:14 +0000202 case ID_PADDING_STREAM:
203 GST_DEBUG ("skipping padding stream");
204 goto skip;
205 default:
206 break;
207 }
208
Jan Schmidt1218cff2012-06-09 22:36:06 +1000209 if (datalen == 0)
Jan Schmidt0951e002008-06-17 01:08:14 +0000210 goto need_more_data;
Jan Schmidt0951e002008-06-17 01:08:14 +0000211 filter->pts = filter->dts = -1;
212
213 /* stuffing bits, first two bits are '10' for mpeg2 pes so this code is
214 * not triggered. */
215 while (TRUE) {
216 if (*data != 0xff)
217 break;
218
219 data++;
220 datalen--;
221
222 GST_DEBUG ("got stuffing bit");
223
224 if (datalen < 1)
225 goto need_more_data;
226 }
227
228 /* STD buffer size, never for mpeg2 */
229 if ((*data & 0xc0) == 0x40) {
230 GST_DEBUG ("have STD");
231
232 if (datalen < 3)
233 goto need_more_data;
234
Jan Schmidt1218cff2012-06-09 22:36:06 +1000235 STD_buffer_bound_scale = *data & 0x20;
Jan Schmidt0951e002008-06-17 01:08:14 +0000236 STD_buffer_size_bound = ((guint16) (*data++ & 0x1F)) << 8;
237 STD_buffer_size_bound |= *data++;
238
239 datalen -= 2;
240 }
241
242 /* PTS but no DTS, never for mpeg2 */
243 if ((*data & 0xf0) == 0x20) {
244 GST_DEBUG ("PTS without DTS");
245
246 if (datalen < 5)
247 goto need_more_data;
248 READ_TS (data, filter->pts, lost_sync);
249 GST_DEBUG ("PTS found %" G_GUINT64_FORMAT, filter->pts);
250 datalen -= 5;
251 }
252 /* PTS and DTS, never for mpeg2 */
253 else if ((*data & 0xf0) == 0x30) {
254 GST_DEBUG ("PTS and DTS");
255
256 if (datalen < 10)
257 goto need_more_data;
258 READ_TS (data, filter->pts, lost_sync);
259 READ_TS (data, filter->dts, lost_sync);
260 GST_DEBUG ("PTS found %" G_GUINT64_FORMAT, filter->pts);
261 GST_DEBUG ("DTS found %" G_GUINT64_FORMAT, filter->dts);
262 datalen -= 10;
263 } else if ((*data & 0xc0) == 0x80) {
264 /* mpeg2 case */
265 guchar flags;
266 guint8 header_data_length = 0;
267
268 GST_DEBUG ("MPEG2 PES packet");
269
270 if (datalen < 3)
271 goto need_more_data;
272 /* 2: '10'
273 * 2: PES_scrambling_control
274 * 1: PES_priority
275 * 1: data_alignment_indicator
276 * 1: copyright
277 * 1: original_or_copy
278 */
279 flags = *data++;
280
281 GST_DEBUG ("flags: 0x%02x", flags);
282 if ((flags & 0xc0) != 0x80)
283 goto lost_sync;
284
285 /* check PES scrambling control */
286 if ((flags & 0x30) != 0)
Jan Schmidt1218cff2012-06-09 22:36:06 +1000287 GST_DEBUG ("PES scrambling control: %x", (flags >> 4) & 0x3);
Jan Schmidt0951e002008-06-17 01:08:14 +0000288
289 /* 2: PTS_DTS_flags
290 * 1: ESCR_flag
291 * 1: ES_rate_flag
292 * 1: DSM_trick_mode_flag
293 * 1: additional_copy_info_flag
294 * 1: PES_CRC_flag
295 * 1: PES_extension_flag
296 */
297 flags = *data++;
298
299 /* 8: PES_header_data_length */
300 header_data_length = *data++;
301 datalen -= 3;
302
303 GST_DEBUG ("header_data_length: %d, flags 0x%02x",
304 header_data_length, flags);
305
306 if (header_data_length > datalen)
307 goto need_more_data;
308
309 /* only DTS: this is invalid */
310 if ((flags & 0xc0) == 0x40)
311 goto lost_sync;
312
313 /* check for PTS */
314 if ((flags & 0x80)) {
315 if (datalen < 5)
316 goto need_more_data;
317
318 READ_TS (data, filter->pts, lost_sync);
319 GST_DEBUG ("PTS found %" G_GUINT64_FORMAT, filter->pts);
320 header_data_length -= 5;
321 datalen -= 5;
322 }
323 /* check for DTS */
324 if ((flags & 0x40)) {
325 READ_TS (data, filter->dts, lost_sync);
326 if (datalen < 5)
327 goto need_more_data;
328 GST_DEBUG ("DTS found %" G_GUINT64_FORMAT, filter->dts);
329 header_data_length -= 5;
330 datalen -= 5;
331 }
332 /* ESCR_flag */
333 if ((flags & 0x20)) {
334 GST_DEBUG ("%x ESCR found", filter->id);
335 if (datalen < 6)
336 goto need_more_data;
337 data += 6;
338 header_data_length -= 6;
339 datalen -= 6;
340 }
341 /* ES_rate_flag */
342 if ((flags & 0x10)) {
343 guint32 es_rate;
344
345 if (datalen < 3)
346 goto need_more_data;
347
348 es_rate = ((guint32) (*data++ & 0x07)) << 14;
349 es_rate |= ((guint32) (*data++)) << 7;
350 es_rate |= ((guint32) (*data++ & 0xFE)) >> 1;
351 GST_DEBUG ("%x ES Rate found %u", filter->id, es_rate);
352 header_data_length -= 3;
353 datalen -= 3;
354 }
355 /* DSM_trick_mode_flag */
356 if ((flags & 0x08)) {
357 guint8 trick_mode_flags;
358
359 if (datalen < 1)
360 goto need_more_data;
361
362 /* 3: trick_mode_control */
363 trick_mode_flags = *data++;
364 GST_DEBUG ("%x DSM trick mode found, flags 0x%02x", filter->id,
365 trick_mode_flags);
366
367 /* fast_forward */
368 if ((trick_mode_flags & 0xe0) == 0x00) {
369 }
370 /* slow motion */
371 else if ((trick_mode_flags & 0xe0) == 0x20) {
372 }
373 /* freeze frame */
374 else if ((trick_mode_flags & 0xe0) == 0x40) {
375 }
376 /* fast reverse */
377 else if ((trick_mode_flags & 0xe0) == 0x60) {
378 }
379 /* slow reverse */
380 else if ((trick_mode_flags & 0xe0) == 0x80) {
381 }
382 /* reserved */
383 else {
384 }
385
386 header_data_length -= 1;
387 datalen -= 1;
388 }
389 /* additional_copy_info_flag */
390 if ((flags & 0x04)) {
391 GST_DEBUG ("%x additional copy info, flags 0x%02x", filter->id, *data);
392 }
393 /* PES_CRC_flag */
394 if ((flags & 0x02)) {
395 GST_DEBUG ("%x PES_CRC", filter->id);
396 }
397 /* PES_extension_flag */
398 if ((flags & 0x01)) {
Jan Schmidt1218cff2012-06-09 22:36:06 +1000399 flags = *data++;
400 header_data_length -= 1;
401 datalen -= 1;
402 GST_DEBUG ("%x PES_extension, flags 0x%02x", filter->id, flags);
403 /* PES_private_data_flag */
404 if ((flags & 0x80)) {
405 GST_DEBUG ("%x PES_private_data_flag", filter->id);
406 data += 16;
407 header_data_length -= 16;
408 datalen -= 16;
409 }
410 /* pack_header_field_flag */
411 if ((flags & 0x40)) {
412 guint8 pack_field_length = *data;
413 GST_DEBUG ("%x pack_header_field_flag, pack_field_length %d",
414 filter->id, pack_field_length);
415 data += pack_field_length + 1;
416 header_data_length -= pack_field_length + 1;
417 datalen -= pack_field_length + 1;
418 }
419 /* program_packet_sequence_counter_flag */
420 if ((flags & 0x20)) {
421 GST_DEBUG ("%x program_packet_sequence_counter_flag", filter->id);
422 data += 2;
423 header_data_length -= 2;
424 datalen -= 2;
425 }
426 /* P-STD_buffer_flag */
427 if ((flags & 0x10)) {
428 GST_DEBUG ("%x P-STD_buffer_flag", filter->id);
429 data += 2;
430 header_data_length -= 2;
431 datalen -= 2;
432 }
433 /* PES_extension_flag_2 */
434 if ((flags & 0x01)) {
435 guint8 PES_extension_field_length = *data++;
436 GST_DEBUG ("%x PES_extension_flag_2, len %d",
437 filter->id, PES_extension_field_length & 0x7f);
438 if (PES_extension_field_length == 0x81) {
439 GST_DEBUG ("%x substream id 0x%02x", filter->id, *data);
440 }
441 data += PES_extension_field_length & 0x7f;
442 header_data_length -= (PES_extension_field_length & 0x7f) + 1;
443 datalen -= (PES_extension_field_length & 0x7f) + 1;
444 }
Jan Schmidt0951e002008-06-17 01:08:14 +0000445 }
Jan Schmidt0951e002008-06-17 01:08:14 +0000446 /* calculate the amount of real data in this PES packet */
447 data += header_data_length;
448 datalen -= header_data_length;
449 } else if (*data == 0x0f) {
450 /* Not sure what this clause is for */
451 data++;
452 datalen--;
453 } else {
454 /* Data byte wasn't recognised as a flags byte */
455 GST_DEBUG ("Unrecognised flags byte 0x%02x\n", *data);
456 goto lost_sync;
457 }
458
Jan Schmidt1218cff2012-06-09 22:36:06 +1000459push_out:
Jan Schmidt0951e002008-06-17 01:08:14 +0000460 {
461 GstBuffer *out;
Edward Hervey97426a12013-07-29 09:35:08 +0200462#ifndef GST_DISABLE_GST_DEBUG
Jan Schmidt0951e002008-06-17 01:08:14 +0000463 guint16 consumed;
464
465 consumed = avail - 6 - datalen;
Edward Hervey97426a12013-07-29 09:35:08 +0200466#endif
Jan Schmidt0951e002008-06-17 01:08:14 +0000467
468 if (filter->unbounded_packet == FALSE) {
469 filter->length -= avail - 6;
470 GST_DEBUG ("pushing %d, need %d more, consumed %d",
471 datalen, filter->length, consumed);
472 } else {
473 GST_DEBUG ("pushing %d, unbounded packet, consumed %d",
474 datalen, consumed);
475 }
476
477 if (datalen > 0) {
Jan Schmidt1218cff2012-06-09 22:36:06 +1000478 out = gst_buffer_new_allocate (NULL, datalen, NULL);
479 gst_buffer_fill (out, 0, data, datalen);
Jan Schmidt0951e002008-06-17 01:08:14 +0000480 ret = gst_pes_filter_data_push (filter, TRUE, out);
481 filter->first = FALSE;
482 } else {
483 GST_LOG ("first being set to TRUE");
484 filter->first = TRUE;
485 ret = GST_FLOW_OK;
486 }
487
488 if (filter->length > 0 || filter->unbounded_packet)
489 filter->state = STATE_DATA_PUSH;
490 }
491
Jan Schmidt1218cff2012-06-09 22:36:06 +1000492 gst_adapter_unmap (filter->adapter);
Jan Schmidt0951e002008-06-17 01:08:14 +0000493 gst_adapter_flush (filter->adapter, avail);
494 ADAPTER_OFFSET_FLUSH (avail);
495
496 return ret;
497
498need_more_data:
499 {
500 if (filter->unbounded_packet == FALSE) {
501 if (have_size == TRUE) {
Jan Schmidt1218cff2012-06-09 22:36:06 +1000502 GST_DEBUG ("bounded need more data %" G_GSIZE_FORMAT " , lost sync",
Jan Schmidt0951e002008-06-17 01:08:14 +0000503 gst_adapter_available (filter->adapter));
504 ret = GST_FLOW_LOST_SYNC;
505 } else {
Jan Schmidt1218cff2012-06-09 22:36:06 +1000506 GST_DEBUG ("bounded need more data %" G_GSIZE_FORMAT
507 ", breaking for more", gst_adapter_available (filter->adapter));
Jan Schmidt0951e002008-06-17 01:08:14 +0000508 ret = GST_FLOW_NEED_MORE_DATA;
509 }
510 } else {
Jan Schmidt1218cff2012-06-09 22:36:06 +1000511 GST_DEBUG ("unbounded need more data %" G_GSIZE_FORMAT,
Jan Schmidt0951e002008-06-17 01:08:14 +0000512 gst_adapter_available (filter->adapter));
513 ret = GST_FLOW_NEED_MORE_DATA;
514 }
Jan Schmidt1218cff2012-06-09 22:36:06 +1000515 gst_adapter_unmap (filter->adapter);
Jan Schmidt0951e002008-06-17 01:08:14 +0000516 return ret;
517 }
518skip:
519 {
Jan Schmidt1218cff2012-06-09 22:36:06 +1000520 gst_adapter_unmap (filter->adapter);
Jan Schmidt0951e002008-06-17 01:08:14 +0000521
Jan Schmidt1218cff2012-06-09 22:36:06 +1000522 GST_DEBUG ("skipping 0x%02x", filter->id);
Jan Schmidt0951e002008-06-17 01:08:14 +0000523 gst_adapter_flush (filter->adapter, avail);
524 ADAPTER_OFFSET_FLUSH (avail);
525
526 filter->length -= avail - 6;
527 if (filter->length > 0 || filter->unbounded_packet)
528 filter->state = STATE_DATA_SKIP;
529 return GST_FLOW_OK;
530 }
531lost_sync:
532 {
Jan Schmidt1218cff2012-06-09 22:36:06 +1000533 gst_adapter_unmap (filter->adapter);
Jan Schmidt0951e002008-06-17 01:08:14 +0000534 GST_DEBUG ("lost sync");
535 gst_adapter_flush (filter->adapter, 4);
536 ADAPTER_OFFSET_FLUSH (4);
537
538 return GST_FLOW_LOST_SYNC;
539 }
540}
541
542static GstFlowReturn
543gst_pes_filter_data_push (GstPESFilter * filter, gboolean first,
544 GstBuffer * buffer)
545{
546 GstFlowReturn ret;
547
548 GST_LOG ("pushing, first: %d", first);
549
550 if (filter->data_cb) {
551 ret = filter->data_cb (filter, first, buffer, filter->user_data);
552 } else {
553 gst_buffer_unref (buffer);
554 ret = GST_FLOW_OK;
555 }
556 return ret;
557}
558
559GstFlowReturn
560gst_pes_filter_push (GstPESFilter * filter, GstBuffer * buffer)
561{
562 GstFlowReturn ret;
563
564 g_return_val_if_fail (filter != NULL, GST_FLOW_ERROR);
565 g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
566
567 switch (filter->state) {
568 case STATE_HEADER_PARSE:
569 gst_adapter_push (filter->adapter, buffer);
570 ret = gst_pes_filter_parse (filter);
571 break;
572 case STATE_DATA_PUSH:
573 ret = gst_pes_filter_data_push (filter, filter->first, buffer);
574 filter->first = FALSE;
575 break;
576 case STATE_DATA_SKIP:
577 gst_buffer_unref (buffer);
578 ret = GST_FLOW_OK;
579 break;
580 default:
581 goto wrong_state;
582 }
583 return ret;
584
585 /* ERROR */
586wrong_state:
587 {
588 GST_DEBUG ("wrong internal state %d", filter->state);
589 return GST_FLOW_ERROR;
590 }
591}
592
593GstFlowReturn
594gst_pes_filter_process (GstPESFilter * filter)
595{
596 GstFlowReturn ret;
597 gboolean skip = FALSE;
598
599 g_return_val_if_fail (filter != NULL, GST_FLOW_ERROR);
600
601 switch (filter->state) {
602 case STATE_HEADER_PARSE:
603 ret = gst_pes_filter_parse (filter);
604 break;
605 case STATE_DATA_SKIP:
606 skip = TRUE;
607 /* fallthrough */
608 case STATE_DATA_PUSH:
609 if (filter->length > 0 || filter->unbounded_packet) {
610 gint avail;
611
612 avail = gst_adapter_available (filter->adapter);
613 if (filter->unbounded_packet == FALSE)
614 avail = MIN (avail, filter->length);
615
616 if (skip) {
617 gst_adapter_flush (filter->adapter, avail);
618 ADAPTER_OFFSET_FLUSH (avail);
619 ret = GST_FLOW_OK;
620 } else {
621 GstBuffer *out;
Jan Schmidt0951e002008-06-17 01:08:14 +0000622
Jan Schmidt1218cff2012-06-09 22:36:06 +1000623 out = gst_adapter_take_buffer (filter->adapter, avail);
Jan Schmidt0951e002008-06-17 01:08:14 +0000624
625 ret = gst_pes_filter_data_push (filter, filter->first, out);
626 filter->first = FALSE;
627 }
628
629 if (filter->unbounded_packet == FALSE) {
630 filter->length -= avail;
631 if (filter->length == 0)
632 filter->state = STATE_HEADER_PARSE;
633 }
634 } else {
635 filter->state = STATE_HEADER_PARSE;
636 ret = GST_FLOW_OK;
637 }
638 break;
639 default:
640 goto wrong_state;
641 }
642 return ret;
643
644 /* ERROR */
645wrong_state:
646 {
647 GST_DEBUG ("wrong internal state %d", filter->state);
648 return GST_FLOW_ERROR;
649 }
650}
651
652void
653gst_pes_filter_flush (GstPESFilter * filter)
654{
655 g_return_if_fail (filter != NULL);
656
657 if (filter->adapter) {
658 gst_adapter_clear (filter->adapter);
659 if (filter->adapter_offset)
660 *filter->adapter_offset = G_MAXUINT64;
661 }
662 filter->state = STATE_HEADER_PARSE;
663}
664
665GstFlowReturn
666gst_pes_filter_drain (GstPESFilter * filter)
667{
668 g_return_val_if_fail (filter != NULL, GST_FLOW_ERROR);
669
670 gst_pes_filter_flush (filter);
671
672 return GST_FLOW_OK;
673}