be6a9f41ba4de15ff4c6f5743243a2be86a25b59
[obnox/wireshark/wip.git] / epan / dissectors / packet-mp2t.c
1 /* packet-mp2t.c
2  *
3  * Routines for RFC 2250 MPEG2 (ISO/IEC 13818-1) Transport Stream dissection
4  *
5  * $Id$
6  *
7  * Copyright 2006, Erwin Rol <erwin@erwinrol.com>
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program 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
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <glib.h>
33 #include <epan/packet.h>
34
35 #include <stdio.h>
36 #include <string.h>
37
38 #include <epan/rtp_pt.h>
39 #include "packet-frame.h"
40
41 #include <epan/emem.h>
42 #include <epan/conversation.h>
43 #include <epan/expert.h>
44
45 /* The MPEG2 TS packet size */
46 #define MP2T_PACKET_SIZE 188
47 #define MP2T_SYNC_BYTE 0x47
48
49 static dissector_handle_t pes_handle;
50
51 static int proto_mp2t = -1;
52 static gint ett_mp2t = -1;
53 static gint ett_mp2t_header = -1;
54 static gint ett_mp2t_af = -1;
55
56 static int hf_mp2t_header = -1;
57 static int hf_mp2t_sync_byte = -1;
58 static int hf_mp2t_tei = -1;
59 static int hf_mp2t_pusi = -1;
60 static int hf_mp2t_tp = -1;
61 static int hf_mp2t_pid = -1;
62 static int hf_mp2t_tsc = -1;
63 static int hf_mp2t_afc = -1;
64 static int hf_mp2t_cc = -1;
65 static int hf_mp2t_cc_drop = -1;
66
67 #define MP2T_SYNC_BYTE_MASK     0xFF000000
68 #define MP2T_TEI_MASK           0x00800000
69 #define MP2T_PUSI_MASK          0x00400000
70 #define MP2T_TP_MASK            0x00200000
71 #define MP2T_PID_MASK           0x001FFF00
72 #define MP2T_TSC_MASK           0x000000C0
73 #define MP2T_AFC_MASK           0x00000030
74 #define MP2T_CC_MASK            0x0000000F
75
76 #define MP2T_SYNC_BYTE_SHIFT    24
77 #define MP2T_TEI_SHIFT          23
78 #define MP2T_PUSI_SHIFT         22
79 #define MP2T_TP_SHIFT           21
80 #define MP2T_PID_SHIFT          8
81 #define MP2T_TSC_SHIFT          6
82 #define MP2T_AFC_SHIFT          4
83 #define MP2T_CC_SHIFT           0
84
85 static int hf_mp2t_af = -1;
86 static int hf_mp2t_af_length = -1;
87 static int hf_mp2t_af_di = -1;
88 static int hf_mp2t_af_rai = -1;
89 static int hf_mp2t_af_espi = -1;
90 static int hf_mp2t_af_pcr_flag = -1;
91 static int hf_mp2t_af_opcr_flag = -1;
92 static int hf_mp2t_af_sp_flag = -1;
93 static int hf_mp2t_af_tpd_flag = -1;
94 static int hf_mp2t_af_afe_flag = -1;
95
96 #define MP2T_AF_DI_MASK         0x80
97 #define MP2T_AF_RAI_MASK        0x40
98 #define MP2T_AF_ESPI_MASK       0x20
99 #define MP2T_AF_PCR_MASK        0x10
100 #define MP2T_AF_OPCR_MASK       0x08
101 #define MP2T_AF_SP_MASK         0x04
102 #define MP2T_AF_TPD_MASK        0x02
103 #define MP2T_AF_AFE_MASK        0x01
104
105 #define MP2T_AF_DI_SHIFT        7
106 #define MP2T_AF_RAI_SHIFT       6
107 #define MP2T_AF_ESPI_SHIFT      5
108 #define MP2T_AF_PCR_SHIFT       4
109 #define MP2T_AF_OPCR_SHIFT      3
110 #define MP2T_AF_SP_SHIFT        2
111 #define MP2T_AF_TPD_SHIFT       1
112 #define MP2T_AF_AFE_SHIFT       0
113
114 static int hf_mp2t_af_pcr = -1;
115 static int hf_mp2t_af_opcr = -1;
116
117 static int hf_mp2t_af_sc = -1;
118
119 static int hf_mp2t_af_tpd_length = -1;
120 static int hf_mp2t_af_tpd = -1;
121
122 static int hf_mp2t_af_e_length = -1;
123 static int hf_mp2t_af_e_ltw_flag = -1;
124 static int hf_mp2t_af_e_pr_flag = -1;
125 static int hf_mp2t_af_e_ss_flag = -1;
126 static int hf_mp2t_af_e_reserved = -1;
127
128 #define MP2T_AF_E_LTW_FLAG_MASK 0x80 
129 #define MP2T_AF_E_PR_FLAG_MASK  0x40
130 #define MP2T_AF_E_SS_FLAG_MASK  0x20
131
132 static int hf_mp2t_af_e_reserved_bytes = -1;
133 static int hf_mp2t_af_stuffing_bytes = -1;
134
135 static int hf_mp2t_af_e_ltwv_flag = -1;
136 static int hf_mp2t_af_e_ltwo = -1;
137
138 static int hf_mp2t_af_e_pr_reserved = -1;
139 static int hf_mp2t_af_e_pr = -1;
140
141 static int hf_mp2t_af_e_st = -1;
142 static int hf_mp2t_af_e_dnau_32_30 = -1;
143 static int hf_mp2t_af_e_m_1 = -1;
144 static int hf_mp2t_af_e_dnau_29_15 = -1;
145 static int hf_mp2t_af_e_m_2 = -1;
146 static int hf_mp2t_af_e_dnau_14_0 = -1;
147 static int hf_mp2t_af_e_m_3 = -1;
148
149 static int hf_mp2t_payload = -1;
150 static int hf_mp2t_malformed_payload = -1;
151
152 static const value_string mp2t_sync_byte_vals[] = {
153         { MP2T_SYNC_BYTE, "Correct" },
154         { 0, NULL }
155 };
156
157
158 static const value_string mp2t_pid_vals[] = {
159         { 0x0000, "Program Association Table" },
160         { 0x0001, "Conditional Access Table" },
161         { 0x0002, "Transport Stream Description Table" },
162         { 0x0003, "Reserved" },
163         { 0x0004, "Reserved" },
164         { 0x0005, "Reserved" },
165         { 0x0006, "Reserved" },
166         { 0x0007, "Reserved" },
167         { 0x0008, "Reserved" },
168         { 0x0009, "Reserved" },
169         { 0x000A, "Reserved" },
170         { 0x000B, "Reserved" },
171         { 0x000C, "Reserved" },
172         { 0x000D, "Reserved" },
173         { 0x000E, "Reserved" },
174         { 0x000F, "Reserved" },
175         { 0x1FFF, "Null packet" },
176         { 0, NULL }
177 };
178
179 static const value_string mp2t_tsc_vals[] = {
180         { 0, "Not scrambled" },
181         { 1, "User-defined" },
182         { 2, "User-defined" },
183         { 3, "User-defined" },
184         { 0, NULL }
185 };
186
187 static const value_string mp2t_afc_vals[] = {
188         { 0, "Reserved" },
189         { 1, "Payload only" },
190         { 2, "Adaptation Field only" },
191         { 3, "Adaptation Field and Payload" },
192         { 0, NULL }
193 };
194
195 /* Data structure used for detecting CC drops
196  *
197  *  conversation
198  *    |
199  *    +-> mp2t_analysis_data
200  *          |
201  *          +-> pid_table (RB tree)
202  *          |     |
203  *          |     +-> pid_analysis_data (per pid)
204  *          |     +-> pid_analysis_data
205  *          |     +-> pid_analysis_data
206  *          |
207  *          +-> frame_table (RB tree)
208  *                |
209  *                +-> frame_analysis_data (only created if drop detected)
210  *                      |
211  *                      +-> ts_table (RB tree)
212  *                            |
213  *                            +-> pid_analysis_data (per TS subframe)
214  *                            +-> pid_analysis_data
215  *                            +-> pid_analysis_data
216  */
217
218 typedef struct mp2t_analysis_data {
219
220         /* This structure contains a tree containing data for the
221          * individual pid's, this is only used when packets are
222          * processed sequencially.
223          */
224         emem_tree_t     *pid_table;
225
226         /* When detecting a CC drop, store that information for the
227          * given frame.  This info is needed, when clicking around in
228          * wireshark, as the pid table data only makes sence during
229          * sequencial processing. The flag pinfo->fd->flags.visited is
230          * used to tell the difference.
231          *
232          */
233         emem_tree_t     *frame_table;
234
235         guint32 cc_drops;       /* Number of detected CC losses per conv */
236
237 } mp2t_analysis_data_t;
238
239 typedef struct pid_analysis_data {
240         guint16 pid;
241         gint16  cc_prev;        /* Previous CC number */
242 } pid_analysis_data_t;
243
244 typedef struct frame_analysis_data {
245
246         /* As each frame has several pid's, thus need a pid data
247          * structure per TS frame.
248          */
249         emem_tree_t     *ts_table;
250
251 } frame_analysis_data_t;
252
253 static conversation_t *
254 get_the_conversation(packet_info *pinfo)
255 {
256         conversation_t *conv = NULL;
257
258         conv = find_conversation(pinfo->fd->num, &pinfo->src,
259                                  &pinfo->dst, pinfo->ptype,
260                                  pinfo->srcport, pinfo->destport, 0);
261
262         if (conv == NULL) { /* Create a new conversation */
263                 conv = conversation_new(pinfo->fd->num, &pinfo->src,
264                                         &pinfo->dst, pinfo->ptype,
265                                         pinfo->srcport, pinfo->destport, 0);
266         }
267         return conv;
268 }
269
270 static mp2t_analysis_data_t *
271 init_mp2t_conversation_data()
272 {
273         mp2t_analysis_data_t *mp2t_data = NULL;
274
275         mp2t_data = se_alloc0(sizeof(struct mp2t_analysis_data));
276
277         mp2t_data->pid_table =
278                 se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,
279                                               "mp2t_pid_table");
280         mp2t_data->frame_table =
281                 se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,
282                                               "mp2t_frame_table");
283         mp2t_data->cc_drops = 0;
284
285         return mp2t_data;
286 }
287
288 static mp2t_analysis_data_t *
289 get_mp2t_conversation_data(conversation_t *conv)
290 {
291         mp2t_analysis_data_t *mp2t_data = NULL;
292
293         mp2t_data = conversation_get_proto_data(conv, proto_mp2t);
294         if (!mp2t_data) {
295                 mp2t_data = init_mp2t_conversation_data();
296                 conversation_add_proto_data(conv, proto_mp2t, mp2t_data);
297         }
298
299         return mp2t_data;
300 }
301
302 static frame_analysis_data_t *
303 init_frame_analysis_data(mp2t_analysis_data_t *mp2t_data, packet_info *pinfo)
304 {
305         frame_analysis_data_t *frame_data = NULL;
306
307         frame_data = se_alloc0(sizeof(struct frame_analysis_data));
308         frame_data->ts_table =
309           se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,
310                                         "mp2t_frame_pid_table");
311         /* Insert into mp2t tree */
312         se_tree_insert32(mp2t_data->frame_table, pinfo->fd->num,
313                          (void *)frame_data);
314
315         return frame_data;
316 }
317
318
319 static frame_analysis_data_t *
320 get_frame_analysis_data(mp2t_analysis_data_t *mp2t_data, packet_info *pinfo)
321 {
322         frame_analysis_data_t *frame_data = NULL;
323         frame_data = se_tree_lookup32(mp2t_data->frame_table, pinfo->fd->num);
324         return frame_data;
325 }
326
327 static pid_analysis_data_t *
328 get_pid_analysis(guint32 pid, conversation_t *conv)
329 {
330
331         pid_analysis_data_t  *pid_data  = NULL;
332         mp2t_analysis_data_t *mp2t_data = NULL;
333         mp2t_data = get_mp2t_conversation_data(conv);
334
335         pid_data = se_tree_lookup32(mp2t_data->pid_table, pid);
336         if (!pid_data) {
337                 pid_data          = se_alloc0(sizeof(struct pid_analysis_data));
338                 pid_data->cc_prev = -1;
339                 pid_data->pid     = pid;
340
341                 se_tree_insert32(mp2t_data->pid_table, pid, (void *)pid_data);
342         }
343         return pid_data;
344 }
345
346 #define KEY(pid, cc) ((pid << 4)|cc)
347
348 static void
349 detect_cc_drops(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
350                 guint32 pid, gint32 cc_curr, conversation_t *conv)
351 {
352         gint32 cc_prev = -1;
353         pid_analysis_data_t   *pid_data   = NULL;
354         pid_analysis_data_t   *ts_data    = NULL;
355         mp2t_analysis_data_t  *mp2t_data  = NULL;
356         frame_analysis_data_t *frame_data = NULL;
357         proto_item            *flags_item;
358
359         guint32 detected_drop = 0;
360
361         mp2t_data = get_mp2t_conversation_data(conv);
362
363         /* The initial sequencial processing stage */
364         if (!pinfo->fd->flags.visited) {
365
366                 /* This is the sequencial processing stage */
367                 pid_data = get_pid_analysis(pid, conv);
368
369                 cc_prev = pid_data->cc_prev;
370                 pid_data->cc_prev = cc_curr;
371
372                 /* Null packet always have a CC value equal 0 */
373                 if (pid == 0x1fff)
374                         return;
375
376                 /* Its allowed that (cc_prev == cc_curr) if adaptation field */
377                 if (cc_prev == cc_curr)
378                         return;
379
380                 /* Have not seen this pid before */
381                 if (cc_prev == -1)
382                         return;
383
384                 /* Detect if CC is not increasing by one all the time */
385                 if (cc_curr != ((cc_prev+1) & MP2T_CC_MASK)) {
386                         detected_drop = 1;
387                         mp2t_data->cc_drops++;
388                 }
389         }
390
391         /* Save the info about the dropped packet */
392         if (detected_drop && !pinfo->fd->flags.visited) {
393
394                 /* Lookup frame data, contains TS pid data objects */
395                 frame_data = get_frame_analysis_data(mp2t_data, pinfo);
396                 if (!frame_data)
397                         frame_data = init_frame_analysis_data(mp2t_data, pinfo);
398
399                 /* Create and store a new TS frame pid_data object.
400                    This indicate that we have a drop
401                  */
402                 ts_data = se_alloc0(sizeof(struct pid_analysis_data));
403                 ts_data->cc_prev = cc_prev;
404                 ts_data->pid = pid;
405                 se_tree_insert32(frame_data->ts_table, KEY(pid, cc_curr),
406                                  (void *)ts_data);
407         }
408
409         /* See if we stored info about drops */
410         if (pinfo->fd->flags.visited) {
411
412                 /* Lookup frame data, contains TS pid data objects */
413                 frame_data = get_frame_analysis_data(mp2t_data, pinfo);
414                 if (!frame_data)
415                         return; /* No stored frame data -> no drops*/
416                 else {
417                         ts_data = se_tree_lookup32(frame_data->ts_table,
418                                                    KEY(pid, cc_curr));
419                         if (ts_data)
420                                 detected_drop = 1;
421                 }
422
423         }
424
425         /* Add info to the proto tree about drops */
426         if (detected_drop) {
427
428                 flags_item =
429                         proto_tree_add_none_format(
430                                 tree, hf_mp2t_cc_drop, tvb, 0, 0,
431                                 "Detected missing CC frame before this"
432                                 " (accumulated CC loss count:%d)",
433                                 mp2t_data->cc_drops
434                                 );
435
436                 PROTO_ITEM_SET_GENERATED(flags_item);
437                 expert_add_info_format(pinfo, flags_item, PI_MALFORMED,
438                                        PI_ERROR, "Detected CC loss");
439
440         }
441 }
442
443
444 static gint
445 dissect_tsp(tvbuff_t *tvb, volatile gint offset, packet_info *pinfo,
446             proto_tree *tree, conversation_t *conv)
447 {
448         guint32 header;
449         guint afc;
450         gint start_offset = offset;
451         volatile gint payload_len;
452
453         guint32 pid;
454         guint32 cc;
455
456         proto_item *ti = NULL;
457         proto_item *hi = NULL;
458         proto_tree *mp2t_tree = NULL;
459         proto_tree *mp2t_header_tree = NULL;
460         proto_tree *mp2t_af_tree = NULL;
461
462         ti = proto_tree_add_item( tree, proto_mp2t, tvb, offset, MP2T_PACKET_SIZE, FALSE );
463         mp2t_tree = proto_item_add_subtree( ti, ett_mp2t );
464         
465         header = tvb_get_ntohl(tvb, offset);
466
467         pid = (header & MP2T_PID_MASK) >> MP2T_PID_SHIFT;
468         cc  = (header & MP2T_CC_MASK)  >> MP2T_CC_SHIFT;
469         proto_item_append_text(ti, " PID=0x%x CC=%d", pid, cc);
470
471         detect_cc_drops(tvb, tree, pinfo, pid, cc, conv);
472
473         hi = proto_tree_add_item( mp2t_tree, hf_mp2t_header, tvb, offset, 4, FALSE);
474         mp2t_header_tree = proto_item_add_subtree( hi, ett_mp2t_header );
475
476         proto_tree_add_item( mp2t_header_tree, hf_mp2t_sync_byte, tvb, offset, 4, FALSE);
477         proto_tree_add_item( mp2t_header_tree, hf_mp2t_tei, tvb, offset, 4, FALSE);
478         proto_tree_add_item( mp2t_header_tree, hf_mp2t_pusi, tvb, offset, 4, FALSE);
479         proto_tree_add_item( mp2t_header_tree, hf_mp2t_tp, tvb, offset, 4, FALSE);
480         proto_tree_add_item( mp2t_header_tree, hf_mp2t_pid, tvb, offset, 4, FALSE);
481         proto_tree_add_item( mp2t_header_tree, hf_mp2t_tsc, tvb, offset, 4, FALSE);
482         proto_tree_add_item( mp2t_header_tree, hf_mp2t_afc, tvb, offset, 4, FALSE);
483         proto_tree_add_item( mp2t_header_tree, hf_mp2t_cc, tvb, offset, 4, FALSE);
484         offset += 4;
485
486         afc = (header & MP2T_AFC_MASK) >> MP2T_AFC_SHIFT;
487
488         if (afc == 2 || afc == 3) 
489         {
490                 gint af_start_offset = offset;
491         
492                 guint8 af_length;
493                 guint8 af_flags;
494                 gint stuffing_len;
495
496
497                 af_length = tvb_get_guint8(tvb, offset);
498
499                 proto_tree_add_item( mp2t_tree, hf_mp2t_af_length, tvb, offset, 1, FALSE);
500                 offset += 1;
501                 /* fix issues where afc==3 but af_length==0 
502                  *  Adaptaion field...spec section 2.4.3.5: The value 0 is for inserting a single 
503                  *  stuffing byte in a Transport Stream packet. When the adaptation_field_control 
504                  *  value is '11', the value of the adaptation_field_length shall be in the range 0 to 182.
505                  */
506                 if (af_length > 0 ) {
507                         hi = proto_tree_add_item( mp2t_tree, hf_mp2t_af, tvb, offset, af_length, FALSE);
508                         mp2t_af_tree = proto_item_add_subtree( hi, ett_mp2t_af );
509         
510                         af_flags = tvb_get_guint8(tvb, offset);
511         
512                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_di, tvb, offset, 1, FALSE);
513                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_rai, tvb, offset, 1, FALSE);
514                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_espi, tvb, offset, 1, FALSE);
515                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_pcr_flag, tvb, offset, 1, FALSE);
516                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_opcr_flag, tvb, offset, 1, FALSE);
517                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_sp_flag, tvb, offset, 1, FALSE);
518                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd_flag, tvb, offset, 1, FALSE);
519                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_afe_flag, tvb, offset, 1, FALSE);
520         
521                         offset += 1;
522         
523                         if (af_flags &  MP2T_AF_PCR_MASK) {
524                                 guint64 pcr_base = 0;
525                                 guint32 pcr_ext = 0;
526                                 guint8 tmp;
527
528                                 tmp = tvb_get_guint8(tvb, offset);
529                                 pcr_base = (pcr_base << 8) | tmp;
530                                 offset += 1;
531                         
532                                 tmp = tvb_get_guint8(tvb, offset);
533                                 pcr_base = (pcr_base << 8) | tmp;
534                                 offset += 1;
535                                 
536                                 tmp = tvb_get_guint8(tvb, offset);
537                                 pcr_base = (pcr_base << 8) | tmp;
538                                 offset += 1;
539         
540                                 tmp = tvb_get_guint8(tvb, offset);
541                                 pcr_base = (pcr_base << 8) | tmp;
542                                 offset += 1;
543
544                                 tmp = tvb_get_guint8(tvb, offset);
545                                 pcr_base = (pcr_base << 1) | ((tmp >> 7) & 0x01);
546                                 pcr_ext = (tmp & 0x01);
547                                 offset += 1;
548
549                                 tmp = tvb_get_guint8(tvb, offset);
550                                 pcr_ext = (pcr_ext << 8) | tmp;
551                                 offset += 1;
552
553                                 proto_tree_add_none_format(mp2t_af_tree, hf_mp2t_af_pcr, tvb, offset - 6, 6, 
554                                                 "Program Clock Reference: base(%" G_GINT64_MODIFIER "u) * 300 + ext(%u) = %" G_GINT64_MODIFIER "u", 
555                                                 pcr_base, pcr_ext, pcr_base * 300 + pcr_ext);
556                         }
557
558                         if (af_flags &  MP2T_AF_OPCR_MASK) {
559                                 guint64 opcr_base = 0;
560                                 guint32 opcr_ext = 0;
561                                 guint8 tmp = 0;
562
563                                 tmp = tvb_get_guint8(tvb, offset);
564                                 opcr_base = (opcr_base << 8) | tmp;
565                                 offset += 1;
566                         
567                                 tmp = tvb_get_guint8(tvb, offset);
568                                 opcr_base = (opcr_base << 8) | tmp;
569                                 offset += 1;
570                         
571                                 tmp = tvb_get_guint8(tvb, offset);
572                                 opcr_base = (opcr_base << 8) | tmp;
573                                 offset += 1;
574         
575                                 tmp = tvb_get_guint8(tvb, offset);
576                                 opcr_base = (opcr_base << 8) | tmp;
577                                 offset += 1;
578
579                                 tmp = tvb_get_guint8(tvb, offset);
580                                 opcr_base = (opcr_base << 1) | ((tmp >> 7) & 0x01);
581                                 opcr_ext = (tmp & 0x01);
582                                 offset += 1;
583
584                                 tmp = tvb_get_guint8(tvb, offset);
585                                 opcr_ext = (opcr_ext << 8) | tmp;
586                                 offset += 1;
587
588                                 proto_tree_add_none_format(mp2t_af_tree, hf_mp2t_af_opcr, tvb, offset - 6, 6, 
589                                                 "Original Program Clock Reference: base(%" G_GINT64_MODIFIER "u) * 300 + ext(%u) = %" G_GINT64_MODIFIER "u", 
590                                                 opcr_base, opcr_ext, opcr_base * 300 + opcr_ext);
591         
592                                 offset += 6;
593                         }
594         
595                         if (af_flags &  MP2T_AF_SP_MASK) {
596                                 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_sc, tvb, offset, 1, FALSE);
597                                 offset += 1;
598                         }
599
600                         if (af_flags &  MP2T_AF_TPD_MASK) {
601                                 guint8 tpd_len;
602                         
603                                 tpd_len = tvb_get_guint8(tvb, offset);
604                                 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd_length, tvb, offset, 1, FALSE);
605                                 offset += 1;
606
607                                 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd, tvb, offset, tpd_len, FALSE);
608                                 offset += tpd_len;
609                         }
610
611                         if (af_flags &  MP2T_AF_AFE_MASK) {
612                                 guint8 e_len;
613                                 guint8 e_flags;
614                                 gint e_start_offset = offset;
615                                 gint reserved_len = 0;
616
617                                 e_len = tvb_get_guint8(tvb, offset);
618                                 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_length, tvb, offset, 1, FALSE);
619                                 offset += 1;
620
621                                 e_flags = tvb_get_guint8(tvb, offset);
622                                 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltw_flag, tvb, offset, 1, FALSE);
623                                 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr_flag, tvb, offset, 1, FALSE);
624                                 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ss_flag, tvb, offset, 1, FALSE);
625                                 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_reserved, tvb, offset, 1, FALSE);                       
626                                 offset += 1;
627                         
628                                 if (e_flags & MP2T_AF_E_LTW_FLAG_MASK) {
629                                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltwv_flag, tvb, offset, 2, FALSE);
630                                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltwo, tvb, offset, 2, FALSE);
631                                         offset += 2;
632                                 }
633
634                                 if (e_flags & MP2T_AF_E_PR_FLAG_MASK) {
635                                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr_reserved, tvb, offset, 3, FALSE);
636                                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr, tvb, offset, 3, FALSE);
637                                         offset += 3;
638                                 }
639
640                                 if (e_flags & MP2T_AF_E_SS_FLAG_MASK) {
641                                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_st, tvb, offset, 1, FALSE);
642                                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_32_30, tvb, offset, 1, FALSE);
643                                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_1, tvb, offset, 1, FALSE);
644                                         offset += 1;
645                                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_29_15, tvb, offset, 2, FALSE);
646                                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_2, tvb, offset, 2, FALSE);
647                                         offset += 2;
648                                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_14_0, tvb, offset, 2, FALSE);
649                                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_3, tvb, offset, 2, FALSE);
650                                         offset += 2;
651                                 }
652
653                                 reserved_len = (e_len + 1) - (offset - e_start_offset);
654                                 if (reserved_len > 0) {
655                                         proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_reserved_bytes, tvb, offset, reserved_len, FALSE);
656                                         offset += reserved_len;
657                                 }
658                         }
659
660                         stuffing_len = (af_length + 1) - (offset - af_start_offset);
661                         if (stuffing_len > 0) {
662                                 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_stuffing_bytes, tvb, offset, stuffing_len, FALSE);
663                                 offset += stuffing_len;
664                         }
665                 }
666         }
667
668         payload_len = MP2T_PACKET_SIZE - (offset - start_offset);
669         if (payload_len > 0) {
670                 if (afc == 2) { /* AF only */
671                         /* Packet is malformed */
672                         proto_tree_add_item( mp2t_tree, hf_mp2t_malformed_payload, tvb, offset, payload_len, FALSE);
673                         offset += payload_len;
674                 } else {
675                         /* Check to make sure if we are not at end of payload, if we have less than 3 bytes, the tvb_get_ntoh24 fails. */
676                         if (payload_len >=3 ) {
677                                 if (tvb_get_ntoh24(tvb, offset) == 0x000001) {
678                                         tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, payload_len, payload_len);
679                                         const char *saved_proto = pinfo->current_proto;
680
681                                         TRY {
682                                                 call_dissector(pes_handle, next_tvb, pinfo, mp2t_tree);
683                                         }
684
685                                         /*
686                                          Don't stop processing TS packets if somebody threw
687                                          BoundsError, which means that dissecting the payload found
688                                          that the packet was cut off by before the end of the
689                                          payload.  This is very likely as this protocol splits the
690                                          media stream up into chunks of MP2T_PACKET_SIZE.
691                                         */
692                                         CATCH2(BoundsError, ReportedBoundsError) {
693                                                 show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
694                                                 pinfo->current_proto = saved_proto;
695                                         }
696
697                                         ENDTRY;
698                                 } else {
699                                         proto_tree_add_item( mp2t_tree, hf_mp2t_payload, tvb, offset, payload_len, FALSE);
700                                 }
701                         } else {
702                                 proto_tree_add_item( mp2t_tree, hf_mp2t_payload, tvb, offset, payload_len, FALSE);
703                         }
704                         offset += payload_len;
705                 }
706         }
707
708         return offset;
709 }
710
711
712 static void
713 dissect_mp2t( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
714 {
715         guint offset = 0;
716         conversation_t *conv;
717         conv = get_the_conversation(pinfo);
718
719         while ( tvb_reported_length_remaining(tvb, offset) >= MP2T_PACKET_SIZE ) {
720                 offset = dissect_tsp(tvb, offset, pinfo, tree, conv);
721         }
722 }
723
724 static gboolean
725 heur_dissect_mp2t( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
726 {
727         guint offset = 0;
728
729         if (tvb_length_remaining(tvb, offset) % MP2T_PACKET_SIZE) {
730                 return FALSE;
731         } else {
732                 while (tvb_length_remaining(tvb, offset)) {
733                         if (tvb_get_guint8(tvb, offset) != MP2T_SYNC_BYTE)
734                                 return FALSE;
735                         offset += MP2T_PACKET_SIZE;
736                 }
737         }
738
739         dissect_mp2t(tvb, pinfo, tree);
740         return TRUE;
741 }
742
743 void
744 proto_register_mp2t(void)
745 {
746         static hf_register_info hf[] = { 
747                 { &hf_mp2t_header, {
748                         "Header", "mp2t.header",
749                         FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL
750                 } } ,
751                 { &hf_mp2t_sync_byte, {
752                         "Sync Byte", "mp2t.sync_byte",
753                         FT_UINT32, BASE_HEX, VALS(mp2t_sync_byte_vals), MP2T_SYNC_BYTE_MASK, NULL, HFILL
754                 } } ,
755                 { &hf_mp2t_tei, { 
756                         "Transport Error Indicator", "mp2t.tei",
757                         FT_UINT32, BASE_DEC, NULL, MP2T_TEI_MASK, NULL, HFILL
758                 } } ,
759                 { &hf_mp2t_pusi, {
760                         "Payload Unit Start Indicator", "mp2t.pusi",
761                         FT_UINT32, BASE_DEC, NULL, MP2T_PUSI_MASK, NULL, HFILL
762                 } } ,
763                 { &hf_mp2t_tp, {
764                         "Transport Priority", "mp2t.tp",
765                         FT_UINT32, BASE_DEC, NULL, MP2T_TP_MASK, NULL, HFILL
766                 } } ,
767                 { &hf_mp2t_pid, {
768                         "PID", "mp2t.pid",
769                         FT_UINT32, BASE_HEX, VALS(mp2t_pid_vals), MP2T_PID_MASK, NULL, HFILL
770                 } } ,
771                 { &hf_mp2t_tsc, {
772                         "Transport Scrambling Control", "mp2t.tsc",
773                         FT_UINT32, BASE_HEX, VALS(mp2t_tsc_vals), MP2T_TSC_MASK, NULL, HFILL
774                 } } ,
775                 { &hf_mp2t_afc, {
776                         "Adaption Field Control", "mp2t.afc",
777                         FT_UINT32, BASE_HEX, VALS(mp2t_afc_vals) , MP2T_AFC_MASK, NULL, HFILL
778                 } } ,
779                 { &hf_mp2t_cc, {
780                         "Continuity Counter", "mp2t.cc",
781                         FT_UINT32, BASE_DEC, NULL, MP2T_CC_MASK, NULL, HFILL
782                 } } ,
783                 { &hf_mp2t_cc_drop, {
784                         "Continuity Counter Drops", "mp2t.cc.drop",
785                         FT_NONE, BASE_DEC, NULL, 0x0, NULL, HFILL
786                 } } ,
787                 { &hf_mp2t_af, {
788                         "Adaption field", "mp2t.af",
789                         FT_NONE, BASE_HEX, NULL, 0, NULL, HFILL
790                 } } ,
791                 { &hf_mp2t_af_length, {
792                         "Adaptation Field Length", "mp2t.af.length",
793                         FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL
794                 } } ,
795                 { &hf_mp2t_af_di, {
796                         "Discontinuity Indicator", "mp2t.af.di",
797                         FT_UINT8, BASE_DEC, NULL, MP2T_AF_DI_MASK, NULL, HFILL
798                 } } ,
799                 { &hf_mp2t_af_rai, {
800                         "Random Access Indicator", "mp2t.af.rai",
801                         FT_UINT8, BASE_DEC, NULL, MP2T_AF_RAI_MASK, NULL, HFILL
802                 } } ,
803                 { &hf_mp2t_af_espi, {
804                         "Elementary Stream Priority Indicator", "mp2t.af.espi",
805                         FT_UINT8, BASE_DEC, NULL, MP2T_AF_ESPI_MASK, NULL, HFILL
806                 } } ,
807                 { &hf_mp2t_af_pcr_flag, {
808                         "PCR Flag", "mp2t.af.pcr_flag",
809                         FT_UINT8, BASE_DEC, NULL, MP2T_AF_PCR_MASK, NULL, HFILL
810                 } } ,
811                 { &hf_mp2t_af_opcr_flag, {
812                         "OPCR Flag", "mp2t.af.opcr_flag",
813                         FT_UINT8, BASE_DEC, NULL, MP2T_AF_OPCR_MASK, NULL, HFILL
814                 } } ,
815                 { &hf_mp2t_af_sp_flag, {
816                         "Splicing Point Flag", "mp2t.af.sp_flag",
817                         FT_UINT8, BASE_DEC, NULL, MP2T_AF_SP_MASK, NULL, HFILL
818                 } } ,
819                 { &hf_mp2t_af_tpd_flag, {
820                         "Transport Private Data Flag", "mp2t.af.tpd_flag",
821                         FT_UINT8, BASE_DEC, NULL, MP2T_AF_TPD_MASK, NULL, HFILL
822                 } } ,
823                 { &hf_mp2t_af_afe_flag, {
824                         "Adaptation Field Extension Flag", "mp2t.af.afe_flag",
825                         FT_UINT8, BASE_DEC, NULL, MP2T_AF_AFE_MASK, NULL, HFILL
826                 } } ,
827                 { &hf_mp2t_af_pcr, {
828                         "Program Clock Reference", "mp2t.af.pcr",
829                         FT_NONE, BASE_DEC, NULL, 0, NULL, HFILL
830                 } } ,
831                 { &hf_mp2t_af_opcr, {
832                         "Original Program Clock Reference", "mp2t.af.opcr",
833                         FT_NONE, BASE_DEC, NULL, 0, NULL, HFILL
834                 } } ,
835                 { &hf_mp2t_af_sc, {
836                         "Splice Countdown", "mp2t.af.sc",
837                         FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
838                 } } ,
839                 { &hf_mp2t_af_tpd_length, {
840                         "Transport Private Data Length", "mp2t.af.tpd_length",
841                         FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
842                 } } ,
843                 { &hf_mp2t_af_tpd, {
844                         "Transport Private Data", "mp2t.af.tpd",
845                         FT_BYTES, BASE_DEC, NULL, 0, NULL, HFILL
846                 } } ,
847                 { &hf_mp2t_af_e_length, {
848                         "Adaptation Field Extension Length", "mp2t.af.e_length",
849                         FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
850                 } } ,
851                 { &hf_mp2t_af_e_ltw_flag, {
852                         "LTW Flag", "mp2t.af.e.ltw_flag",
853                         FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_LTW_FLAG_MASK, NULL, HFILL
854                 } } ,
855                 { &hf_mp2t_af_e_pr_flag, {
856                         "Piecewise Rate Flag", "mp2t.af.e.pr_flag",
857                         FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_PR_FLAG_MASK, NULL, HFILL
858                 } } ,
859                 { &hf_mp2t_af_e_ss_flag, {
860                         "Seamless Splice Flag", "mp2t.af.e.ss_flag",
861                         FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_SS_FLAG_MASK, NULL, HFILL
862                 } } ,
863                 { &hf_mp2t_af_e_reserved, {
864                         "Reserved", "mp2t.af.e.reserved",
865                         FT_UINT8, BASE_DEC, NULL, 0x1F, NULL, HFILL
866                 } } ,
867                 { &hf_mp2t_af_e_reserved_bytes, {
868                         "Reserved", "mp2t.af.e.reserved_bytes",
869                         FT_BYTES, BASE_DEC, NULL, 0x0, NULL, HFILL
870                 } } ,
871                 { &hf_mp2t_af_stuffing_bytes, {
872                         "Stuffing", "mp2t.af.stuffing_bytes",
873                         FT_BYTES, BASE_DEC, NULL, 0x0, NULL, HFILL
874                 } } ,
875                 { &hf_mp2t_af_e_ltwv_flag, {
876                         "LTW Valid Flag", "mp2t.af.e.ltwv_flag",
877                         FT_UINT16, BASE_DEC, NULL, 0x8000, NULL, HFILL
878                 } } ,
879                 { &hf_mp2t_af_e_ltwo, {
880                         "LTW Offset", "mp2t.af.e.ltwo",
881                         FT_UINT16, BASE_DEC, NULL, 0x7FFF, NULL, HFILL
882                 } } ,
883                 { &hf_mp2t_af_e_pr_reserved, {
884                         "Reserved", "mp2t.af.e.pr_reserved",
885                         FT_UINT24, BASE_DEC, NULL, 0xC00000, NULL, HFILL
886                 } } ,
887                 { &hf_mp2t_af_e_pr, {
888                         "Piecewise Rate", "mp2t.af.e.pr",
889                         FT_UINT24, BASE_DEC, NULL, 0x3FFFFF, NULL, HFILL
890                 } } ,
891                 { &hf_mp2t_af_e_st, {
892                         "Splice Type", "mp2t.af.e.st",
893                         FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL
894                 } } ,
895                 { &hf_mp2t_af_e_dnau_32_30, {
896                         "DTS Next AU[32...30]", "mp2t.af.e.dnau_32_30",
897                         FT_UINT8, BASE_DEC, NULL, 0x0E, NULL, HFILL
898                 } } ,
899                 { &hf_mp2t_af_e_m_1, {
900                         "Marker Bit", "mp2t.af.e.m_1",
901                         FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL
902                 } } ,
903                 { &hf_mp2t_af_e_dnau_29_15, {
904                         "DTS Next AU[29...15]", "mp2t.af.e.dnau_29_15",
905                         FT_UINT16, BASE_DEC, NULL, 0xFFFE, NULL, HFILL
906                 } } ,
907                 { &hf_mp2t_af_e_m_2, {
908                         "Marker Bit", "mp2t.af.e.m_2",
909                         FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL
910                 } } ,
911                 { &hf_mp2t_af_e_dnau_14_0, {
912                         "DTS Next AU[14...0]", "mp2t.af.e.dnau_14_0",
913                         FT_UINT16, BASE_DEC, NULL, 0xFFFE, NULL, HFILL
914                 } } ,
915                 { &hf_mp2t_af_e_m_3, {
916                         "Marker Bit", "mp2t.af.e.m_3",
917                         FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL
918                 } } ,
919                 { &hf_mp2t_payload, {
920                         "Payload", "mp2t.payload",
921                         FT_BYTES, BASE_DEC, NULL, 0x0, NULL, HFILL
922                 } } ,
923                 { &hf_mp2t_malformed_payload, {
924                         "Malformed Payload", "mp2t.malformed_payload",
925                         FT_BYTES, BASE_DEC, NULL, 0x0, NULL, HFILL
926                 } }
927         };
928
929         static gint *ett[] =
930         {
931                 &ett_mp2t,
932                 &ett_mp2t_header,
933                 &ett_mp2t_af
934         };
935
936         proto_mp2t = proto_register_protocol("ISO/IEC 13818-1", "MP2T", "mp2t");
937         proto_register_field_array(proto_mp2t, hf, array_length(hf));
938         proto_register_subtree_array(ett, array_length(ett));
939 }
940
941
942
943 void
944 proto_reg_handoff_mp2t(void)
945 {
946         dissector_handle_t mp2t_handle;
947
948         heur_dissector_add("udp", heur_dissect_mp2t, proto_mp2t);
949
950         mp2t_handle = create_dissector_handle(dissect_mp2t, proto_mp2t);
951         dissector_add("rtp.pt", PT_MP2T, mp2t_handle);
952         dissector_add_handle("udp.port", mp2t_handle);  /* for decode-as */
953
954         pes_handle = find_dissector("mpeg-pes");
955 }
956