mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
fa2916a159
Some mpeg-ts (HLS, DVB, ...) streams out there have completely broken PCR streams on which we can't reliably recover correct timestamps. For those, provide a property that will ignore the program PCR stream (by faking that it's not present (0x1fff)).
247 lines
8.4 KiB
C
247 lines
8.4 KiB
C
/*
|
|
* mpegtsbase.h - GStreamer MPEG transport stream base class
|
|
* Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
|
|
* 2007 Alessandro Decina
|
|
* Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
|
|
* Author: Youness Alaoui <youness.alaoui@collabora.co.uk>, Collabora Ltd.
|
|
* Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
|
|
*
|
|
* Authors:
|
|
* Alessandro Decina <alessandro@nnva.org>
|
|
* Edward Hervey <edward.hervey@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., 51 Franklin St, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
|
|
#ifndef GST_MPEG_TS_BASE_H
|
|
#define GST_MPEG_TS_BASE_H
|
|
|
|
#include <gst/gst.h>
|
|
#include "mpegtspacketizer.h"
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
#define GST_TYPE_MPEGTS_BASE \
|
|
(mpegts_base_get_type())
|
|
#define GST_MPEGTS_BASE(obj) \
|
|
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MPEGTS_BASE,MpegTSBase))
|
|
#define GST_MPEGTS_BASE_CLASS(klass) \
|
|
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MPEGTS_BASE,MpegTSBaseClass))
|
|
#define GST_IS_MPEGTS_BASE(obj) \
|
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MPEGTS_BASE))
|
|
#define GST_IS_MPEGTS_BASE_CLASS(klass) \
|
|
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MPEGTS_BASE))
|
|
#define GST_MPEGTS_BASE_GET_CLASS(obj) \
|
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPEGTS_BASE, MpegTSBaseClass))
|
|
|
|
#define MPEG_TS_BASE_PACKETIZER(b) (((MpegTSBase*)b)->packetizer)
|
|
|
|
typedef struct _MpegTSBase MpegTSBase;
|
|
typedef struct _MpegTSBaseClass MpegTSBaseClass;
|
|
typedef struct _MpegTSBaseStream MpegTSBaseStream;
|
|
typedef struct _MpegTSBaseProgram MpegTSBaseProgram;
|
|
|
|
struct _MpegTSBaseStream
|
|
{
|
|
guint16 pid;
|
|
guint8 stream_type;
|
|
|
|
/* Content of the registration descriptor (if present) */
|
|
guint32 registration_id;
|
|
|
|
GstMpegtsPMTStream *stream;
|
|
GstStream *stream_object;
|
|
gchar *stream_id;
|
|
};
|
|
|
|
struct _MpegTSBaseProgram
|
|
{
|
|
gint program_number;
|
|
guint16 pmt_pid;
|
|
guint16 pcr_pid;
|
|
|
|
/* Content of the registration descriptor (if present) */
|
|
guint32 registration_id;
|
|
|
|
GstMpegtsSection *section;
|
|
const GstMpegtsPMT *pmt;
|
|
|
|
MpegTSBaseStream **streams;
|
|
GList *stream_list;
|
|
gint patcount;
|
|
|
|
GstStreamCollection *collection;
|
|
|
|
/* Pending Tags for the program */
|
|
GstTagList *tags;
|
|
guint event_id;
|
|
|
|
/* TRUE if the program is currently being used */
|
|
gboolean active;
|
|
/* TRUE if this is the first program created */
|
|
gboolean initial_program;
|
|
};
|
|
|
|
typedef enum {
|
|
/* PULL MODE */
|
|
BASE_MODE_SCANNING, /* Looking for PAT/PMT */
|
|
BASE_MODE_SEEKING, /* Seeking */
|
|
BASE_MODE_STREAMING, /* Normal mode (pushing out data) */
|
|
|
|
/* PUSH MODE */
|
|
BASE_MODE_PUSHING
|
|
} MpegTSBaseMode;
|
|
|
|
struct _MpegTSBase {
|
|
GstElement element;
|
|
|
|
GstPad *sinkpad;
|
|
|
|
/* pull-based behaviour */
|
|
MpegTSBaseMode mode;
|
|
|
|
/* Current pull offset (also set by seek handler) */
|
|
guint64 seek_offset;
|
|
|
|
/* Cached packetsize */
|
|
guint16 packetsize;
|
|
|
|
/* the following vars must be protected with the OBJECT_LOCK as they can be
|
|
* accessed from the application thread and the streaming thread */
|
|
GHashTable *programs;
|
|
|
|
GPtrArray *pat;
|
|
MpegTSPacketizer2 *packetizer;
|
|
|
|
/* arrays that say whether a pid is a known psi pid or a pes pid */
|
|
/* Use MPEGTS_BIT_* to set/unset/check the values */
|
|
guint8 *known_psi;
|
|
guint8 *is_pes;
|
|
|
|
gboolean disposed;
|
|
|
|
/* size of the MpegTSBaseProgram structure, can be overridden
|
|
* by subclasses if they have their own MpegTSBaseProgram subclasses. */
|
|
gsize program_size;
|
|
|
|
/* size of the MpegTSBaseStream structure, can be overridden
|
|
* by subclasses if they have their own MpegTSBaseStream subclasses */
|
|
gsize stream_size;
|
|
|
|
/* Whether we saw a PAT yet */
|
|
gboolean seen_pat;
|
|
|
|
/* Upstream segment */
|
|
GstSegment segment;
|
|
|
|
/* Downstream segment, for use by sub-classes */
|
|
GstSegment out_segment;
|
|
|
|
/* Last received seek event seqnum (default GST_SEQNUM_INVALID) */
|
|
guint last_seek_seqnum;
|
|
|
|
/* Whether to parse private section or not */
|
|
gboolean parse_private_sections;
|
|
|
|
/* Whether to push data and/or sections to subclasses */
|
|
gboolean push_data;
|
|
gboolean push_section;
|
|
|
|
/* Whether the parent bin is streams-aware, meaning we can
|
|
* add/remove streams at any point in time */
|
|
gboolean streams_aware;
|
|
|
|
/* Do not use the PCR stream for timestamp calculation. Useful for
|
|
* streams with broken/invalid PCR streams. */
|
|
gboolean ignore_pcr;
|
|
};
|
|
|
|
struct _MpegTSBaseClass {
|
|
GstElementClass parent_class;
|
|
|
|
/* Virtual methods */
|
|
void (*reset) (MpegTSBase *base);
|
|
GstFlowReturn (*push) (MpegTSBase *base, MpegTSPacketizerPacket *packet, GstMpegtsSection * section);
|
|
void (*inspect_packet) (MpegTSBase *base, MpegTSPacketizerPacket *packet);
|
|
/* takes ownership of @event */
|
|
gboolean (*push_event) (MpegTSBase *base, GstEvent * event);
|
|
|
|
/* program_started gets called when program's pmt arrives for first time */
|
|
void (*program_started) (MpegTSBase *base, MpegTSBaseProgram *program);
|
|
/* program_stopped gets called when pat no longer has program's pmt */
|
|
void (*program_stopped) (MpegTSBase *base, MpegTSBaseProgram *program);
|
|
void (*update_program) (MpegTSBase *base, MpegTSBaseProgram *program);
|
|
/* Whether mpegtbase can deactivate/free a program or whether the subclass will do it
|
|
* If the subclass responds TRUE, it should call mpegts_base_deactivate_and_free_program()
|
|
* when it wants to remove it */
|
|
gboolean (*can_remove_program) (MpegTSBase *base, MpegTSBaseProgram *program);
|
|
|
|
/* stream_added is called whenever a new stream has been identified */
|
|
gboolean (*stream_added) (MpegTSBase *base, MpegTSBaseStream *stream, MpegTSBaseProgram *program);
|
|
/* stream_removed is called whenever a stream is no longer referenced */
|
|
void (*stream_removed) (MpegTSBase *base, MpegTSBaseStream *stream);
|
|
|
|
/* find_timestamps is called to find PCR */
|
|
GstFlowReturn (*find_timestamps) (MpegTSBase * base, guint64 initoff, guint64 *offset);
|
|
|
|
/* seek is called to wait for seeking */
|
|
GstFlowReturn (*seek) (MpegTSBase * base, GstEvent * event);
|
|
|
|
/* Drain all currently pending data */
|
|
GstFlowReturn (*drain) (MpegTSBase * base);
|
|
|
|
/* flush all streams
|
|
* The hard inicator is used to flush completely on FLUSH_STOP events
|
|
* or partially in pull mode seeks of tsdemux */
|
|
void (*flush) (MpegTSBase * base, gboolean hard);
|
|
|
|
/* Notifies subclasses input buffer has been handled */
|
|
GstFlowReturn (*input_done) (MpegTSBase *base, GstBuffer *buffer);
|
|
|
|
/* signals */
|
|
void (*pat_info) (GstStructure *pat);
|
|
void (*pmt_info) (GstStructure *pmt);
|
|
void (*nit_info) (GstStructure *nit);
|
|
void (*sdt_info) (GstStructure *sdt);
|
|
void (*eit_info) (GstStructure *eit);
|
|
|
|
/* takes ownership of @query */
|
|
gboolean (*sink_query) (MpegTSBase *base, GstQuery * query);
|
|
};
|
|
|
|
#define MPEGTS_BIT_SET(field, offs) ((field)[(offs) >> 3] |= (1 << ((offs) & 0x7)))
|
|
#define MPEGTS_BIT_UNSET(field, offs) ((field)[(offs) >> 3] &= ~(1 << ((offs) & 0x7)))
|
|
#define MPEGTS_BIT_IS_SET(field, offs) ((field)[(offs) >> 3] & (1 << ((offs) & 0x7)))
|
|
|
|
G_GNUC_INTERNAL GType mpegts_base_get_type(void);
|
|
|
|
G_GNUC_INTERNAL MpegTSBaseProgram *mpegts_base_get_program (MpegTSBase * base, gint program_number);
|
|
G_GNUC_INTERNAL MpegTSBaseProgram *mpegts_base_add_program (MpegTSBase * base, gint program_number, guint16 pmt_pid);
|
|
|
|
G_GNUC_INTERNAL const GstMpegtsDescriptor *mpegts_get_descriptor_from_stream (MpegTSBaseStream * stream, guint8 tag);
|
|
G_GNUC_INTERNAL const GstMpegtsDescriptor *mpegts_get_descriptor_from_program (MpegTSBaseProgram * program, guint8 tag);
|
|
|
|
G_GNUC_INTERNAL gboolean
|
|
mpegts_base_handle_seek_event(MpegTSBase * base, GstPad * pad, GstEvent * event);
|
|
|
|
G_GNUC_INTERNAL gboolean gst_mpegtsbase_plugin_init (GstPlugin * plugin);
|
|
|
|
G_GNUC_INTERNAL void mpegts_base_deactivate_and_free_program (MpegTSBase *base, MpegTSBaseProgram *program);
|
|
|
|
G_END_DECLS
|
|
|
|
#endif /* GST_MPEG_TS_BASE_H */
|