• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * mpegtsbase.h - GStreamer MPEG transport stream base class
3  * Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
4  *               2007 Alessandro Decina
5  * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
6  *  Author: Youness Alaoui <youness.alaoui@collabora.co.uk>, Collabora Ltd.
7  *  Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
8  *
9  * Authors:
10  *   Alessandro Decina <alessandro@nnva.org>
11  *   Edward Hervey <edward.hervey@collabora.co.uk>
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Library General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Library General Public License for more details.
22  *
23  * You should have received a copy of the GNU Library General Public
24  * License along with this library; if not, write to the
25  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
26  * Boston, MA 02110-1301, USA.
27  */
28 
29 
30 #ifndef GST_MPEG_TS_BASE_H
31 #define GST_MPEG_TS_BASE_H
32 
33 #include <gst/gst.h>
34 #include "mpegtspacketizer.h"
35 
36 G_BEGIN_DECLS
37 
38 #define DRM_MAX_TS_DRM_PSSH_LEN   2048
39 #define DRM_MAX_TS_DRM_UUID_LEN   16
40 #define DRM_MAX_TS_DRM_INFO_NUM   64
41 
42 #define GST_TYPE_MPEGTS_BASE \
43   (mpegts_base_get_type())
44 #define GST_MPEGTS_BASE(obj) \
45   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MPEGTS_BASE,MpegTSBase))
46 #define GST_MPEGTS_BASE_CLASS(klass) \
47   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MPEGTS_BASE,MpegTSBaseClass))
48 #define GST_IS_MPEGTS_BASE(obj) \
49   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MPEGTS_BASE))
50 #define GST_IS_MPEGTS_BASE_CLASS(klass) \
51   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MPEGTS_BASE))
52 #define GST_MPEGTS_BASE_GET_CLASS(obj) \
53   (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPEGTS_BASE, MpegTSBaseClass))
54 
55 #define MPEG_TS_BASE_PACKETIZER(b) (((MpegTSBase*)b)->packetizer)
56 
57 typedef struct _MpegTSBase MpegTSBase;
58 typedef struct _MpegTSBaseClass MpegTSBaseClass;
59 typedef struct _MpegTSBaseStream MpegTSBaseStream;
60 typedef struct _MpegTSBaseProgram MpegTSBaseProgram;
61 typedef struct _DrmInfo DrmInfo;
62 
63 struct _MpegTSBaseStream
64 {
65   guint16             pid;
66   guint8              stream_type;
67 
68   /* Content of the registration descriptor (if present) */
69   guint32             registration_id;
70 
71   GstMpegtsPMTStream *stream;
72   GstStream          *stream_object;
73   gboolean            in_collection;
74   gchar              *stream_id;
75 };
76 
77 struct _MpegTSBaseProgram
78 {
79   gint                program_number;
80   guint16             pmt_pid;
81   guint16             pcr_pid;
82 
83   /* Content of the registration descriptor (if present) */
84   guint32             registration_id;
85 
86   GstMpegtsSection   *section;
87   const GstMpegtsPMT *pmt;
88 
89   MpegTSBaseStream  **streams;
90   GList              *stream_list;
91   gint                patcount;
92 
93   GstStreamCollection *collection;
94 
95   /* Pending Tags for the program */
96   GstTagList *tags;
97   guint event_id;
98 
99   /* TRUE if the program is currently being used */
100   gboolean active;
101   /* TRUE if this is the first program created */
102   gboolean initial_program;
103 
104   /* TRUE if the program shouldn't be freed */
105   gboolean recycle;
106 };
107 
108 typedef enum {
109   /* PULL MODE */
110   BASE_MODE_SCANNING,		/* Looking for PAT/PMT */
111   BASE_MODE_SEEKING,		/* Seeking */
112   BASE_MODE_STREAMING,		/* Normal mode (pushing out data) */
113 
114   /* PUSH MODE */
115   BASE_MODE_PUSHING
116 } MpegTSBaseMode;
117 
118 struct _DrmInfo {
119   guint8 uuid[DRM_MAX_TS_DRM_UUID_LEN];
120   guint8 pssh[DRM_MAX_TS_DRM_PSSH_LEN];
121   guint pssh_len;
122 };
123 
124 struct _MpegTSBase {
125   GstElement element;
126 
127   GstPad *sinkpad;
128 
129   /* pull-based behaviour */
130   MpegTSBaseMode mode;
131 
132   /* Current pull offset (also set by seek handler) */
133   guint64	seek_offset;
134 
135   /* Cached packetsize */
136   guint16	packetsize;
137 
138   /* the following vars must be protected with the OBJECT_LOCK as they can be
139    * accessed from the application thread and the streaming thread */
140   GPtrArray *programs;
141 
142   GPtrArray  *pat;
143   MpegTSPacketizer2 *packetizer;
144 
145   /* arrays that say whether a pid is a known psi pid or a pes pid */
146   /* Use MPEGTS_BIT_* to set/unset/check the values */
147   guint8 *known_psi;
148   guint8 *is_pes;
149 
150   gboolean disposed;
151 
152   /* size of the MpegTSBaseProgram structure, can be overridden
153    * by subclasses if they have their own MpegTSBaseProgram subclasses. */
154   gsize program_size;
155 
156   /* size of the MpegTSBaseStream structure, can be overridden
157    * by subclasses if they have their own MpegTSBaseStream subclasses */
158   gsize stream_size;
159 
160   /* Whether we saw a PAT yet */
161   gboolean seen_pat;
162 
163   /* Upstream segment */
164   GstSegment segment;
165 
166   /* Downstream segment, for use by sub-classes */
167   GstSegment out_segment;
168 
169   /* Last received seek event seqnum (default GST_SEQNUM_INVALID) */
170   guint last_seek_seqnum;
171 
172   /* Whether to parse private section or not */
173   gboolean parse_private_sections;
174 
175   /* Whether to push data and/or sections to subclasses */
176   gboolean push_data;
177   gboolean push_section;
178   gboolean push_unknown;
179 
180   /* Whether the parent bin is streams-aware, meaning we can
181    * add/remove streams at any point in time */
182   gboolean streams_aware;
183 
184   /* Do not use the PCR stream for timestamp calculation. Useful for
185    * streams with broken/invalid PCR streams. */
186   gboolean ignore_pcr;
187 
188   /* Used for delayed seek events */
189   GstEvent *seek_event;
190 
191   guint8 drm_algo_tag;
192 
193   gboolean is_drm;
194 
195   DrmInfo *drm_info;
196 
197   guint drm_info_num;
198 
199   guint drm_info_total_num;
200 };
201 
202 struct _MpegTSBaseClass {
203   GstElementClass parent_class;
204 
205   /* Virtual methods */
206   void (*reset) (MpegTSBase *base);
207   GstFlowReturn (*push) (MpegTSBase *base, MpegTSPacketizerPacket *packet, GstMpegtsSection * section);
208   void (*inspect_packet) (MpegTSBase *base, MpegTSPacketizerPacket *packet);
209   /* takes ownership of @event */
210   gboolean (*push_event) (MpegTSBase *base, GstEvent * event);
211   void (*handle_psi) (MpegTSBase *base, GstMpegtsSection * section);
212 
213   /* program_started gets called when program's pmt arrives for first time */
214   void (*program_started) (MpegTSBase *base, MpegTSBaseProgram *program);
215   /* program_stopped gets called when pat no longer has program's pmt */
216   void (*program_stopped) (MpegTSBase *base, MpegTSBaseProgram *program);
217   void (*update_program) (MpegTSBase *base, MpegTSBaseProgram *program);
218   /* Whether mpegtbase can deactivate/free a program or whether the subclass will do it
219    * If the subclass responds TRUE, it should call mpegts_base_deactivate_and_free_program()
220    * when it wants to remove it */
221   gboolean (*can_remove_program) (MpegTSBase *base, MpegTSBaseProgram *program);
222 
223   /* stream_added is called whenever a new stream has been identified */
224   gboolean (*stream_added) (MpegTSBase *base, MpegTSBaseStream *stream, MpegTSBaseProgram *program);
225   /* stream_removed is called whenever a stream is no longer referenced */
226   void (*stream_removed) (MpegTSBase *base, MpegTSBaseStream *stream);
227 
228   /* find_timestamps is called to find PCR */
229   GstFlowReturn (*find_timestamps) (MpegTSBase * base, guint64 initoff, guint64 *offset);
230 
231   /* seek is called to wait for seeking */
232   GstFlowReturn (*seek) (MpegTSBase * base, GstEvent * event);
233 
234   /* Drain all currently pending data */
235   GstFlowReturn (*drain) (MpegTSBase * base);
236 
237   /* flush all streams
238    * The hard inicator is used to flush completely on FLUSH_STOP events
239    * or partially in pull mode seeks of tsdemux */
240   void (*flush) (MpegTSBase * base, gboolean hard);
241 
242   /* Notifies subclasses input buffer has been handled */
243   GstFlowReturn (*input_done) (MpegTSBase *base);
244 
245   /* signals */
246   void (*pat_info) (GstStructure *pat);
247   void (*pmt_info) (GstStructure *pmt);
248   void (*nit_info) (GstStructure *nit);
249   void (*sdt_info) (GstStructure *sdt);
250   void (*eit_info) (GstStructure *eit);
251 
252   /* takes ownership of @query */
253   gboolean (*sink_query) (MpegTSBase *base, GstQuery * query);
254 };
255 
256 #define MPEGTS_BIT_SET(field, offs)    ((field)[(offs) >> 3] |=  (1 << ((offs) & 0x7)))
257 #define MPEGTS_BIT_UNSET(field, offs)  ((field)[(offs) >> 3] &= ~(1 << ((offs) & 0x7)))
258 #define MPEGTS_BIT_IS_SET(field, offs) ((field)[(offs) >> 3] &   (1 << ((offs) & 0x7)))
259 
260 G_GNUC_INTERNAL GType mpegts_base_get_type(void);
261 
262 G_GNUC_INTERNAL MpegTSBaseProgram *mpegts_base_get_program (MpegTSBase * base, gint program_number);
263 G_GNUC_INTERNAL MpegTSBaseProgram *mpegts_base_add_program (MpegTSBase * base, gint program_number, guint16 pmt_pid);
264 
265 G_GNUC_INTERNAL const GstMpegtsDescriptor *mpegts_get_descriptor_from_stream (MpegTSBaseStream * stream, guint8 tag);
266 G_GNUC_INTERNAL const GstMpegtsDescriptor *mpegts_get_descriptor_from_stream_with_extension (MpegTSBaseStream * stream,
267     guint8 tag, guint8 tag_extension);
268 G_GNUC_INTERNAL const GstMpegtsDescriptor *mpegts_get_descriptor_from_program (MpegTSBaseProgram * program, guint8 tag);
269 
270 G_GNUC_INTERNAL gboolean
271 mpegts_base_handle_seek_event(MpegTSBase * base, GstPad * pad, GstEvent * event);
272 
273 G_GNUC_INTERNAL gboolean gst_mpegtsbase_plugin_init (GstPlugin * plugin);
274 
275 G_GNUC_INTERNAL void mpegts_base_deactivate_and_free_program (MpegTSBase *base, MpegTSBaseProgram *program);
276 
277 G_END_DECLS
278 
279 #endif /* GST_MPEG_TS_BASE_H */
280