1 /*
2  * mpegtspacketizer.h -
3  * Copyright (C) 2007 Alessandro Decina
4  *
5  * Authors:
6  *   Alessandro Decina <alessandro@nnva.org>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 #ifndef GST_MPEGTS_PACKETIZER_H
25 #define GST_MPEGTS_PACKETIZER_H
26 
27 #include <gst/gst.h>
28 #include <gst/base/gstadapter.h>
29 #include <glib.h>
30 
31 #include <gst/mpegts/mpegts.h>
32 #include "gstmpegdefs.h"
33 
34 #define MPEGTS_NORMAL_PACKETSIZE  188
35 #define MPEGTS_M2TS_PACKETSIZE    192
36 #define MPEGTS_DVB_ASI_PACKETSIZE 204
37 #define MPEGTS_ATSC_PACKETSIZE    208
38 
39 #define MPEGTS_MIN_PACKETSIZE MPEGTS_NORMAL_PACKETSIZE
40 #define MPEGTS_MAX_PACKETSIZE MPEGTS_ATSC_PACKETSIZE
41 
42 #define MPEGTS_AFC_DISCONTINUITY_FLAG           0x80
43 #define MPEGTS_AFC_RANDOM_ACCES_FLAGS           0x40
44 #define MPEGTS_AFC_ELEMENTARY_STREAM_PRIORITY   0x20
45 #define MPEGTS_AFC_PCR_FLAG                     0x10
46 #define MPEGTS_AFC_OPCR_FLAG                    0x08
47 #define MPEGTS_AFC_SPLICING_POINT_FLAG          0x04
48 #define MPEGTS_AFC_TRANSPORT_PRIVATE_DATA_FLAG  0x02
49 #define MPEGTS_AFC_EXTENSION_FLAG               0x01
50 
51 #define MAX_WINDOW 512
52 
53 G_BEGIN_DECLS
54 
55 #define GST_TYPE_MPEGTS_PACKETIZER \
56   (mpegts_packetizer_get_type())
57 #define GST_MPEGTS_PACKETIZER(obj) \
58   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MPEGTS_PACKETIZER,MpegTSPacketizer2))
59 #define GST_MPEGTS_PACKETIZER_CLASS(klass) \
60   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MPEGTS_PACKETIZER,MpegTSPacketizer2Class))
61 #define GST_IS_MPEGTS_PACKETIZER(obj) \
62   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MPEGTS_PACKETIZER))
63 #define GST_IS_MPEGTS_PACKETIZER_CLASS(klass) \
64   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MPEGTS_PACKETIZER))
65 
66 typedef struct _MpegTSPacketizer2 MpegTSPacketizer2;
67 typedef struct _MpegTSPacketizer2Class MpegTSPacketizer2Class;
68 
69 typedef struct
70 {
71   guint16 pid;
72   guint   continuity_counter;
73 
74   /* Section data (always newly allocated) */
75   guint8 *section_data;
76   /* Current offset in section_data */
77   guint16 section_offset;
78 
79   /* Values for pending section */
80   /* table_id of the pending section_data */
81   guint8  table_id;
82   guint   section_length;
83   guint8  version_number;
84   guint16 subtable_extension;
85   guint8  section_number;
86   guint8  last_section_number;
87 
88   GSList *subtables;
89 
90   /* Upstream offset of the data contained in the section */
91   guint64 offset;
92 } MpegTSPacketizerStream;
93 
94 /* Maximum number of MpegTSPcr
95  * 256 should be sufficient for most multiplexes */
96 #define MAX_PCR_OBS_CHANNELS 256
97 
98 /* PCR/offset structure */
99 typedef struct _PCROffset
100 {
101   /* PCR value (units: 1/27MHz) */
102   guint64 pcr;
103 
104   /* The offset (units: bytes) */
105   guint64 offset;
106 } PCROffset;
107 
108 /* Flags used on groups */
109 enum
110 {
111   /* Closed groups: There is a contiguous next group */
112   PCR_GROUP_FLAG_CLOSED = 1 << 0,
113   /* estimated: the pcr_offset has been estimated and is not
114    * guaranteed to be 100% accurate */
115   PCR_GROUP_FLAG_ESTIMATED = 1 << 1,
116   /* reset: there is a pcr reset between the end of this
117    * group and the next one.
118    * This flag is exclusive with CLOSED. */
119   PCR_GROUP_FLAG_RESET = 1 << 2,
120   /* reset: there is a pcr wrapover between the end of this
121    * group and the next one.
122    * This flag is exclusive with CLOSED. */
123   PCR_GROUP_FLAG_WRAPOVER = 1 << 3
124 };
125 
126 
127 
128 /* PCROffsetGroup: A group of PCR observations.
129  * All values in a group have got the same reference pcr and
130  * byte offset (first_pcr/first_offset).
131  */
132 #define DEFAULT_ALLOCATED_OFFSET 16
133 typedef struct _PCROffsetGroup
134 {
135   /* Flags (see PCR_GROUP_FLAG_* above) */
136   guint flags;
137 
138   /* First raw PCR of this group. Units: 1/27MHz.
139    * All values[].pcr are differences against first_pcr */
140   guint64 first_pcr;
141   /* Offset of this group in bytes.
142    * All values[].offset are differences against first_offset */
143   guint64 first_offset;
144 
145   /* Dynamically allocated table of PCROffset */
146   PCROffset *values;
147   /* number of PCROffset allocated in values */
148   guint nb_allocated;
149   /* number of *actual* PCROffset contained in values */
150   guint last_value;
151 
152   /* Offset since the very first PCR value observed in the whole
153    * stream. Units: 1/27MHz.
154    * This will take into account gaps/wraparounds/resets/... and is
155    * used to determine running times.
156    * The value is only guaranteed to be 100% accurate if the group
157    * does not have the ESTIMATED flag.
158    * If the value is estimated, the pcr_offset shall be recalculated
159    * (based on previous groups) whenever it is accessed.
160    */
161   guint64 pcr_offset;
162 
163   /* FIXME : Cache group bitrate ? */
164 } PCROffsetGroup;
165 
166 /* Number of PCRs needed before bitrate estimation can start */
167 /* Note: the reason we use 10 is because PCR should normally be
168  * received at least every 100ms so this gives us close to
169  * a 1s moving window to calculate bitrate */
170 #define PCR_BITRATE_NEEDED 10
171 
172 /* PCROffsetCurrent: The PCR/Offset window iterator
173  * This is used to estimate/observe incoming PCR/offset values
174  * Points to a group (which it is filling) */
175 typedef struct _PCROffsetCurrent
176 {
177   /* The PCROffsetGroup we are filling.
178    * If NULL, a group needs to be identified */
179   PCROffsetGroup *group;
180 
181   /* Table of pending values we are iterating over */
182   PCROffset pending[PCR_BITRATE_NEEDED];
183 
184   /* base offset/pcr from the group */
185   guint64 first_pcr;
186   guint64 first_offset;
187 
188   /* The previous reference PCROffset
189    * This corresponds to the last entry of the group we are filling
190    * and is used to calculate prev_bitrate */
191   PCROffset prev;
192 
193   /* The last PCROffset in pending[] */
194   PCROffset last_value;
195 
196   /* Location of first pending PCR/offset observation in pending */
197   guint first;
198   /* Location of last pending PCR/offset observation in pending */
199   guint last;
200   /* Location of next write in pending */
201   guint write;
202 
203   /* bitrate is always in bytes per second */
204 
205   /* cur_bitrate is the bitrate of the pending values: d(last-first) */
206   guint64 cur_bitrate;
207 
208   /* prev_bitrate is the bitrate between reference PCROffset
209    * and the first pending value. Used to detect changes
210    * in bitrate */
211   guint64 prev_bitrate;
212 } PCROffsetCurrent;
213 
214 typedef struct _MpegTSPCR
215 {
216   guint16 pid;
217 
218   /* Following variables are only active/used when
219    * calculate_skew is TRUE */
220   GstClockTime base_time;
221   GstClockTime base_pcrtime;
222   GstClockTime prev_out_time;
223   GstClockTime prev_in_time;
224   GstClockTime last_pcrtime;
225   gint64 window[MAX_WINDOW];
226   guint window_pos;
227   guint window_size;
228   gboolean window_filling;
229   gint64 window_min;
230   gint64 skew;
231   gint64 prev_send_diff;
232 
233   /* Offset to apply to PCR to handle wraparounds */
234   guint64 pcroffset;
235 
236   /* Used for bitrate calculation */
237   /* List of PCR/offset observations */
238   GList *groups;
239 
240   /* Current PCR/offset observations (used to update pcroffsets) */
241   PCROffsetCurrent *current;
242 } MpegTSPCR;
243 
244 struct _MpegTSPacketizer2 {
245   GObject     parent;
246 
247   GMutex group_lock;
248 
249   GstAdapter *adapter;
250   /* streams hashed by pid */
251   /* FIXME : be more memory efficient (see how it's done in mpegtsbase) */
252   MpegTSPacketizerStream **streams;
253   gboolean    disposed;
254   guint16     packet_size;
255 
256   /* current offset of the tip of the adapter */
257   guint64  offset;
258   gboolean empty;
259 
260   /* clock skew calculation */
261   gboolean       calculate_skew;
262 
263   /* offset/bitrate calculator */
264   gboolean       calculate_offset;
265 
266   /* Shortcuts for adapter usage */
267   guint8 *map_data;
268   gsize map_offset;
269   gsize map_size;
270   gboolean need_sync;
271 
272   /* Reference offset */
273   guint64 refoffset;
274 
275   /* Number of seen pcr/offset observations (FIXME : kill later) */
276   guint nb_seen_offsets;
277 
278   /* Last inputted timestamp */
279   GstClockTime last_in_time;
280 
281   /* offset to observations table */
282   guint8 pcrtablelut[0x2000];
283   MpegTSPCR *observations[MAX_PCR_OBS_CHANNELS];
284   guint8 lastobsid;
285   GstClockTime pcr_discont_threshold;
286 };
287 
288 struct _MpegTSPacketizer2Class {
289   GObjectClass object_class;
290 };
291 
292 #define FLAGS_SCRAMBLED(f) (f & 0xc0)
293 #define FLAGS_HAS_AFC(f) (f & 0x20)
294 #define FLAGS_HAS_PAYLOAD(f) (f & 0x10)
295 #define FLAGS_CONTINUITY_COUNTER(f) (f & 0x0f)
296 
297 typedef struct
298 {
299   gint16  pid;
300   guint8  payload_unit_start_indicator;
301   guint8  scram_afc_cc;
302   guint8 *payload;
303 
304   guint8 *data_start;
305   guint8 *data_end;
306   guint8 *data;
307 
308   guint8  afc_flags;
309   guint64 pcr;
310   guint64 offset;
311 } MpegTSPacketizerPacket;
312 
313 typedef struct
314 {
315   guint8 table_id;
316   /* the spec says sub_table_extension is the fourth and fifth byte of a
317    * section when the section_syntax_indicator is set to a value of "1". If
318    * section_syntax_indicator is 0, sub_table_extension will be set to 0 */
319   guint16  subtable_extension;
320   guint8   version_number;
321   guint8   last_section_number;
322   /* table of bits, whether the section was seen or not.
323    * Use MPEGTS_BIT_* macros to check */
324   /* Size is 32, because there's a maximum of 256 (32*8) section_number */
325   guint8   seen_section[32];
326 } MpegTSPacketizerStreamSubtable;
327 
328 #define MPEGTS_BIT_SET(field, offs)    ((field)[(offs) >> 3] |=  (1 << ((offs) & 0x7)))
329 #define MPEGTS_BIT_UNSET(field, offs)  ((field)[(offs) >> 3] &= ~(1 << ((offs) & 0x7)))
330 #define MPEGTS_BIT_IS_SET(field, offs) ((field)[(offs) >> 3] &   (1 << ((offs) & 0x7)))
331 
332 typedef enum {
333   PACKET_BAD       = FALSE,
334   PACKET_OK        = TRUE,
335   PACKET_NEED_MORE
336 } MpegTSPacketizerPacketReturn;
337 
338 G_GNUC_INTERNAL GType mpegts_packetizer_get_type(void);
339 
340 G_GNUC_INTERNAL MpegTSPacketizer2 *mpegts_packetizer_new (void);
341 G_GNUC_INTERNAL void mpegts_packetizer_clear (MpegTSPacketizer2 *packetizer);
342 G_GNUC_INTERNAL void mpegts_packetizer_flush (MpegTSPacketizer2 *packetizer, gboolean hard);
343 G_GNUC_INTERNAL void mpegts_packetizer_push (MpegTSPacketizer2 *packetizer, GstBuffer *buffer);
344 G_GNUC_INTERNAL gboolean mpegts_packetizer_has_packets (MpegTSPacketizer2 *packetizer);
345 G_GNUC_INTERNAL MpegTSPacketizerPacketReturn mpegts_packetizer_next_packet (MpegTSPacketizer2 *packetizer,
346   MpegTSPacketizerPacket *packet);
347 G_GNUC_INTERNAL MpegTSPacketizerPacketReturn
348 mpegts_packetizer_process_next_packet(MpegTSPacketizer2 * packetizer);
349 G_GNUC_INTERNAL void mpegts_packetizer_clear_packet (MpegTSPacketizer2 *packetizer,
350 				     MpegTSPacketizerPacket *packet);
351 G_GNUC_INTERNAL void mpegts_packetizer_remove_stream(MpegTSPacketizer2 *packetizer,
352   gint16 pid);
353 
354 G_GNUC_INTERNAL GstMpegtsSection *mpegts_packetizer_push_section (MpegTSPacketizer2 *packetzer,
355 								  MpegTSPacketizerPacket *packet, GList **remaining);
356 
357 /* Only valid if calculate_offset is TRUE */
358 G_GNUC_INTERNAL GstClockTime
359 mpegts_packetizer_offset_to_ts (MpegTSPacketizer2 * packetizer,
360 				guint64 offset, guint16 pcr_pid);
361 G_GNUC_INTERNAL guint64
362 mpegts_packetizer_ts_to_offset (MpegTSPacketizer2 * packetizer,
363 				GstClockTime ts, guint16 pcr_pid);
364 G_GNUC_INTERNAL GstClockTime
365 mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer,
366 			     GstClockTime pts, guint16 pcr_pid);
367 G_GNUC_INTERNAL GstClockTime
368 mpegts_packetizer_get_current_time (MpegTSPacketizer2 * packetizer,
369 				    guint16 pcr_pid);
370 G_GNUC_INTERNAL void
371 mpegts_packetizer_set_current_pcr_offset (MpegTSPacketizer2 * packetizer,
372 			  GstClockTime offset, guint16 pcr_pid);
373 G_GNUC_INTERNAL void
374 mpegts_packetizer_set_reference_offset (MpegTSPacketizer2 * packetizer,
375 					guint64 refoffset);
376 G_GNUC_INTERNAL void
377 mpegts_packetizer_set_pcr_discont_threshold (MpegTSPacketizer2 * packetizer,
378 					GstClockTime threshold);
379 G_END_DECLS
380 
381 #endif /* GST_MPEGTS_PACKETIZER_H */
382