3 * Routines for RFC 2250 MPEG2 (ISO/IEC 13818-1) Transport Stream dissection
7 * Copyright 2006, Erwin Rol <erwin@erwinrol.com>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
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.
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.
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.
33 #include <epan/packet.h>
35 #include <epan/rtp_pt.h>
36 #include "packet-frame.h"
38 #include <epan/emem.h>
39 #include <epan/conversation.h>
40 #include <epan/expert.h>
41 #include <epan/reassemble.h>
43 /* The MPEG2 TS packet size */
44 #define MP2T_PACKET_SIZE 188
45 #define MP2T_SYNC_BYTE 0x47
47 static dissector_handle_t pes_handle;
48 static dissector_handle_t docsis_handle;
49 static dissector_handle_t data_handle;
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 static gint ett_mp2t_analysis = -1;
56 static gint ett_dmpt = -1;
58 static int hf_mp2t_header = -1;
59 static int hf_mp2t_sync_byte = -1;
60 static int hf_mp2t_tei = -1;
61 static int hf_mp2t_pusi = -1;
62 static int hf_mp2t_tp = -1;
63 static int hf_mp2t_pid = -1;
64 static int hf_mp2t_tsc = -1;
65 static int hf_mp2t_afc = -1;
66 static int hf_mp2t_cc = -1;
67 static int hf_mp2t_cc_drop = -1;
69 static int hf_mp2t_analysis_flags = -1;
70 static int hf_mp2t_analysis_skips = -1;
71 static int hf_mp2t_analysis_drops = -1;
73 #define MP2T_SYNC_BYTE_MASK 0xFF000000
74 #define MP2T_TEI_MASK 0x00800000
75 #define MP2T_PUSI_MASK 0x00400000
76 #define MP2T_TP_MASK 0x00200000
77 #define MP2T_PID_MASK 0x001FFF00
78 #define MP2T_TSC_MASK 0x000000C0
79 #define MP2T_AFC_MASK 0x00000030
80 #define MP2T_CC_MASK 0x0000000F
82 #define MP2T_SYNC_BYTE_SHIFT 24
83 #define MP2T_TEI_SHIFT 23
84 #define MP2T_PUSI_SHIFT 22
85 #define MP2T_TP_SHIFT 21
86 #define MP2T_PID_SHIFT 8
87 #define MP2T_TSC_SHIFT 6
88 #define MP2T_AFC_SHIFT 4
89 #define MP2T_CC_SHIFT 0
91 static int hf_mp2t_af = -1;
92 static int hf_mp2t_af_length = -1;
93 static int hf_mp2t_af_di = -1;
94 static int hf_mp2t_af_rai = -1;
95 static int hf_mp2t_af_espi = -1;
96 static int hf_mp2t_af_pcr_flag = -1;
97 static int hf_mp2t_af_opcr_flag = -1;
98 static int hf_mp2t_af_sp_flag = -1;
99 static int hf_mp2t_af_tpd_flag = -1;
100 static int hf_mp2t_af_afe_flag = -1;
102 #define MP2T_AF_DI_MASK 0x80
103 #define MP2T_AF_RAI_MASK 0x40
104 #define MP2T_AF_ESPI_MASK 0x20
105 #define MP2T_AF_PCR_MASK 0x10
106 #define MP2T_AF_OPCR_MASK 0x08
107 #define MP2T_AF_SP_MASK 0x04
108 #define MP2T_AF_TPD_MASK 0x02
109 #define MP2T_AF_AFE_MASK 0x01
111 #define MP2T_AF_DI_SHIFT 7
112 #define MP2T_AF_RAI_SHIFT 6
113 #define MP2T_AF_ESPI_SHIFT 5
114 #define MP2T_AF_PCR_SHIFT 4
115 #define MP2T_AF_OPCR_SHIFT 3
116 #define MP2T_AF_SP_SHIFT 2
117 #define MP2T_AF_TPD_SHIFT 1
118 #define MP2T_AF_AFE_SHIFT 0
120 static int hf_mp2t_af_pcr = -1;
121 static int hf_mp2t_af_opcr = -1;
123 static int hf_mp2t_af_sc = -1;
125 static int hf_mp2t_af_tpd_length = -1;
126 static int hf_mp2t_af_tpd = -1;
128 static int hf_mp2t_af_e_length = -1;
129 static int hf_mp2t_af_e_ltw_flag = -1;
130 static int hf_mp2t_af_e_pr_flag = -1;
131 static int hf_mp2t_af_e_ss_flag = -1;
132 static int hf_mp2t_af_e_reserved = -1;
134 #define MP2T_AF_E_LTW_FLAG_MASK 0x80
135 #define MP2T_AF_E_PR_FLAG_MASK 0x40
136 #define MP2T_AF_E_SS_FLAG_MASK 0x20
138 static int hf_mp2t_af_e_reserved_bytes = -1;
139 static int hf_mp2t_af_stuffing_bytes = -1;
141 static int hf_mp2t_af_e_ltwv_flag = -1;
142 static int hf_mp2t_af_e_ltwo = -1;
144 static int hf_mp2t_af_e_pr_reserved = -1;
145 static int hf_mp2t_af_e_pr = -1;
147 static int hf_mp2t_af_e_st = -1;
148 static int hf_mp2t_af_e_dnau_32_30 = -1;
149 static int hf_mp2t_af_e_m_1 = -1;
150 static int hf_mp2t_af_e_dnau_29_15 = -1;
151 static int hf_mp2t_af_e_m_2 = -1;
152 static int hf_mp2t_af_e_dnau_14_0 = -1;
153 static int hf_mp2t_af_e_m_3 = -1;
155 static int hf_mp2t_payload = -1;
156 static int hf_mp2t_malformed_payload = -1;
159 static const value_string mp2t_sync_byte_vals[] = {
160 { MP2T_SYNC_BYTE, "Correct" },
164 static const value_string mp2t_pid_vals[] = {
165 { 0x0000, "Program Association Table" },
166 { 0x0001, "Conditional Access Table" },
167 { 0x0002, "Transport Stream Description Table" },
168 { 0x0003, "Reserved" },
169 { 0x0004, "Reserved" },
170 { 0x0005, "Reserved" },
171 { 0x0006, "Reserved" },
172 { 0x0007, "Reserved" },
173 { 0x0008, "Reserved" },
174 { 0x0009, "Reserved" },
175 { 0x000A, "Reserved" },
176 { 0x000B, "Reserved" },
177 { 0x000C, "Reserved" },
178 { 0x000D, "Reserved" },
179 { 0x000E, "Reserved" },
180 { 0x000F, "Reserved" },
181 { 0x1FFE, "DOCSIS Data-over-cable well-known PID" },
182 { 0x1FFF, "Null packet" },
186 static const value_string mp2t_tsc_vals[] = {
187 { 0, "Not scrambled" },
188 { 1, "User-defined" },
189 { 2, "User-defined" },
190 { 3, "User-defined" },
194 static const value_string mp2t_afc_vals[] = {
196 { 1, "Payload only" },
197 { 2, "Adaptation Field only" },
198 { 3, "Adaptation Field and Payload" },
202 static gint ett_depi_msg_fragment = -1;
203 static gint ett_depi_msg_fragments = -1;
204 static int hf_depi_msg_fragments = -1;
205 static int hf_depi_msg_fragment = -1;
206 static int hf_depi_msg_fragment_overlap = -1;
207 static int hf_depi_msg_fragment_overlap_conflicts = -1;
208 static int hf_depi_msg_fragment_multiple_tails = -1;
209 static int hf_depi_msg_fragment_too_long_fragment = -1;
210 static int hf_depi_msg_fragment_error = -1;
211 static int hf_depi_msg_fragment_count = -1;
212 static int hf_depi_msg_reassembled_in = -1;
213 static int hf_depi_msg_reassembled_length = -1;
215 static const fragment_items depi_msg_frag_items = {
216 /* Fragment subtrees */
217 &ett_depi_msg_fragment,
218 &ett_depi_msg_fragments,
219 /* Fragment fields */
220 &hf_depi_msg_fragments,
221 &hf_depi_msg_fragment,
222 &hf_depi_msg_fragment_overlap,
223 &hf_depi_msg_fragment_overlap_conflicts,
224 &hf_depi_msg_fragment_multiple_tails,
225 &hf_depi_msg_fragment_too_long_fragment,
226 &hf_depi_msg_fragment_error,
227 &hf_depi_msg_fragment_count,
228 /* Reassembled in field */
229 &hf_depi_msg_reassembled_in,
230 /* Reassembled length field */
231 &hf_depi_msg_reassembled_length,
236 /* Structures to handle DOCSIS-DEPI packets, spanned across
237 * multiple MPEG packets
239 static GHashTable *mp2t_depi_fragment_table = NULL;
240 static GHashTable *mp2t_depi_reassembled_table = NULL;
242 /***************** DOCSIS defragmentation support *******************/
243 /* definitions of DOCSIS payload type - from plugins/docsis/packet-docsis.c */
244 #define DOCSIS_FC_TYPE_DATA 0x00
245 #define DOCSIS_FC_TYPE_ATM 0x01
246 #define DOCSIS_FC_TYPE_RESERVED 0x02
247 #define DOCSIS_FC_TYPE_MAC 0x03
250 get_docsis_packet_length(tvbuff_t * tvb, gint offset)
256 /* Extract FC_TYPE and FC_PARM */
257 fc = tvb_get_guint8 (tvb, offset); /* Frame Control Byte */
258 fctype = (fc >> 6) & 0x03; /* Frame Control Type: 2 MSB Bits */
260 if((fctype == DOCSIS_FC_TYPE_ATM) ||
261 (fctype == DOCSIS_FC_TYPE_RESERVED)) {
262 /* add text - this FC type is not supported */
266 /* The only case when this field is used for SID is for
267 * request frames, but they are in upstream direction.
269 len = tvb_get_ntohs(tvb, offset + 2) + 6;
275 mp2t_depi_docsis_fragmentation_handle(tvbuff_t *tvb, guint offset,
276 packet_info *pinfo, proto_tree *tree,
277 guint frag_offset, guint frag_len,
278 gboolean fragment_last)
280 fragment_data *frag_msg = NULL;
281 tvbuff_t *new_tvb = NULL;
282 tvbuff_t *next_tvb = NULL;
284 proto_tree *dmpt_tree;
286 pinfo->fragmented = TRUE;
288 /* check length; send frame for reassembly */
289 frag_msg = fragment_add_check(tvb, offset, pinfo,
290 0, mp2t_depi_fragment_table,
291 mp2t_depi_reassembled_table,
296 new_tvb = process_reassembled_data(tvb, offset, pinfo,
298 frag_msg, &depi_msg_frag_items,
301 if (frag_msg) { /* Reassembled */
302 col_append_str(pinfo->cinfo, COL_INFO, " (Message Reassembled)");
303 } else { /* Not last packet of reassembled Short Message */
304 col_append_fstr(pinfo->cinfo, COL_INFO," (Message fragment %u)", 0);
307 /* put DOCSIS handler here */
308 if (new_tvb) { /* take it all */
311 ti = proto_tree_add_text(tree, tvb, offset, 0, "DOCSIS MAC Frame (reassembled)");
312 dmpt_tree = proto_item_add_subtree(ti, ett_dmpt);
315 call_dissector(docsis_handle, next_tvb, pinfo, dmpt_tree);
317 call_dissector(data_handle, next_tvb, pinfo, dmpt_tree);
322 /* Decoding of DOCSIS MAC frames within MPEG packets. MAC frames may begin anywhere
323 * within an MPEG packet or span multiple MPEG packets.
324 * payload_unit_start_indicator bit in MPEG header, and pointer field are used to
325 * decode fragmented DOCSIS frames within MPEG packet.
326 *-------------------------------------------------------------------------------
327 *MPEG Header | pointer_field | stuff_bytes | Start of MAC Frame #1 |
328 *(PUSI = 1) | (= 0) | (0 or more) |(up to 183 bytes) |
329 *-------------------------------------------------------------------------------
330 *-------------------------------------------------------------------------------
331 *MPEG Header | Continuation of MAC Frame #1 |
332 *(PUSI = 0) | (up to 183 bytes) |
333 *-------------------------------------------------------------------------------
334 *-------------------------------------------------------------------------------
335 *MPEG Header | pointer_field |Tail of MAC Frame| stuff_bytes |Start of MAC Frame|
336 *(PUSI = 1) | (= M) | #1 (M bytes) | (0 or more) |# 2 (N bytes) |
337 *-------------------------------------------------------------------------------
338 * Source - Data-Over-Cable Service Interface Specifications
339 * CM-SP-DRFI-I07-081209
342 mp2t_depi_docsis_process_payload(tvbuff_t *tvb, gint offset, packet_info *pinfo,
343 proto_tree *tree, proto_tree *header_tree)
349 proto_tree *dmpt_tree;
350 static gboolean fragmentation = FALSE;
351 static guint32 mac_frame_len, cumulative_len;
353 pusi_flag = (tvb_get_ntohl(tvb, offset) & 0x00400000);
358 pointer = tvb_get_guint8(tvb, offset);
359 proto_tree_add_text(header_tree, tvb, offset, 1,
360 "Pointer: %u", tvb_get_guint8(tvb, offset));
364 /* get tail of MAC frame */
365 if (pusi_flag && fragmentation) {
366 fragmentation = FALSE;
368 /* check length; send frame for reassembly */
369 mp2t_depi_docsis_fragmentation_handle(tvb, offset, pinfo,
374 cumulative_len += pointer;
376 if (cumulative_len != mac_frame_len) {
377 proto_tree_add_text(tree, tvb, offset, mac_frame_len,
378 "Invalid cumulative length %u",
384 /* Get start of MAC frame or get complete frame */
385 if (pusi_flag && !fragmentation) {
386 guint16 remaining_length;
388 remaining_length = 183 - pointer;
391 while (remaining_length > 0) {
392 while ((tvb_get_guint8(tvb, offset) == 0xFF)) {
394 if (remaining_length == 0)
399 /* Here, we start DOCSIS frame */
400 mac_frame_len = get_docsis_packet_length(tvb, offset);
403 if (!mac_frame_len) {
404 proto_tree_add_text(tree, tvb, offset, mac_frame_len,
405 "Invalid DOCSIS length %u", mac_frame_len);
409 if (mac_frame_len <= remaining_length) {
410 fragmentation = FALSE;
411 /* send for processing */
412 ti = proto_tree_add_text(tree, tvb, offset,
414 "DOCSIS MAC Frame: %u bytes", mac_frame_len);
415 dmpt_tree = proto_item_add_subtree(ti, ett_dmpt);
416 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
418 call_dissector(docsis_handle, next_tvb, pinfo, dmpt_tree);
420 call_dissector(data_handle, next_tvb, pinfo, dmpt_tree);
422 offset += mac_frame_len;
423 remaining_length -= mac_frame_len;
425 fragmentation = TRUE;
427 mp2t_depi_docsis_fragmentation_handle(tvb, offset, pinfo,
428 tree, 0, remaining_length, FALSE);
429 cumulative_len = remaining_length;
435 /* if PUSI flag == 0 - check fragmentation flag */
437 gboolean last_fragment = FALSE;
439 if (fragmentation == FALSE) {
440 /* Error - fragmentation should be TRUE */
441 proto_tree_add_text(tree, tvb, offset, mac_frame_len,
442 "Error - PUSI is 0 in unfragmented DOCSIS packet");
446 /* If packet length is consistent with MAC frame length -
447 * call function to handle all fragments
449 if ((cumulative_len + 184) == mac_frame_len) {
450 last_fragment = TRUE;
451 fragmentation = FALSE;
454 mp2t_depi_docsis_fragmentation_handle(tvb, offset, pinfo,
455 tree, cumulative_len, 184, last_fragment);
456 cumulative_len += 184;
463 /* Data structure used for detecting CC drops
467 * +-> mp2t_analysis_data
469 * +-> pid_table (RB tree) (key: pid)
471 * | +-> pid_analysis_data (per pid)
472 * | +-> pid_analysis_data
473 * | +-> pid_analysis_data
475 * +-> frame_table (RB tree) (key: pinfo->fd->num)
477 * +-> frame_analysis_data (only created if drop detected)
479 * +-> ts_table (RB tree)
481 * +-> ts_analysis_data (per TS subframe)
482 * +-> ts_analysis_data
483 * +-> ts_analysis_data
486 typedef struct mp2t_analysis_data {
488 /* This structure contains a tree containing data for the
489 * individual pid's, this is only used when packets are
490 * processed sequencially.
492 emem_tree_t *pid_table;
494 /* When detecting a CC drop, store that information for the
495 * given frame. This info is needed, when clicking around in
496 * wireshark, as the pid table data only makes sence during
497 * sequencial processing. The flag pinfo->fd->flags.visited is
498 * used to tell the difference.
501 emem_tree_t *frame_table;
503 /* Total counters per conversation / multicast stream */
505 guint32 total_discontinuity;
507 } mp2t_analysis_data_t;
509 /* Analysis TS frame info needed during sequential processing */
510 typedef struct pid_analysis_data {
512 gint8 cc_prev; /* Previous CC number */
513 } pid_analysis_data_t;
515 /* Analysis info stored for a TS frame */
516 typedef struct ts_analysis_data {
518 gint8 cc_prev; /* Previous CC number */
519 guint8 skips; /* Skips between CCs max 14 */
520 } ts_analysis_data_t;
523 typedef struct frame_analysis_data {
525 /* As each frame has several pid's, thus need a pid data
526 * structure per TS frame.
528 emem_tree_t *ts_table;
530 } frame_analysis_data_t;
532 static mp2t_analysis_data_t *
533 init_mp2t_conversation_data(void)
535 mp2t_analysis_data_t *mp2t_data = NULL;
537 mp2t_data = se_alloc0(sizeof(struct mp2t_analysis_data));
539 mp2t_data->pid_table =
540 se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,
542 mp2t_data->frame_table =
543 se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,
546 mp2t_data->total_skips = 0;
547 mp2t_data->total_discontinuity = 0;
552 static mp2t_analysis_data_t *
553 get_mp2t_conversation_data(conversation_t *conv)
555 mp2t_analysis_data_t *mp2t_data = NULL;
557 mp2t_data = conversation_get_proto_data(conv, proto_mp2t);
559 mp2t_data = init_mp2t_conversation_data();
560 conversation_add_proto_data(conv, proto_mp2t, mp2t_data);
566 static frame_analysis_data_t *
567 init_frame_analysis_data(mp2t_analysis_data_t *mp2t_data, packet_info *pinfo)
569 frame_analysis_data_t *frame_analysis_data_p = NULL;
571 frame_analysis_data_p = se_alloc0(sizeof(struct frame_analysis_data));
572 frame_analysis_data_p->ts_table =
573 se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,
574 "mp2t_frame_pid_table");
575 /* Insert into mp2t tree */
576 se_tree_insert32(mp2t_data->frame_table, pinfo->fd->num,
577 (void *)frame_analysis_data_p);
579 return frame_analysis_data_p;
583 static frame_analysis_data_t *
584 get_frame_analysis_data(mp2t_analysis_data_t *mp2t_data, packet_info *pinfo)
586 frame_analysis_data_t *frame_analysis_data_p = NULL;
587 frame_analysis_data_p = se_tree_lookup32(mp2t_data->frame_table, pinfo->fd->num);
588 return frame_analysis_data_p;
591 static pid_analysis_data_t *
592 get_pid_analysis(guint32 pid, conversation_t *conv)
595 pid_analysis_data_t *pid_data = NULL;
596 mp2t_analysis_data_t *mp2t_data = NULL;
597 mp2t_data = get_mp2t_conversation_data(conv);
599 pid_data = se_tree_lookup32(mp2t_data->pid_table, pid);
601 pid_data = se_alloc0(sizeof(struct pid_analysis_data));
602 pid_data->cc_prev = -1;
605 se_tree_insert32(mp2t_data->pid_table, pid, (void *)pid_data);
610 /* Calc the number of skipped CC numbers. Note that this can easy
611 * overflow, and a value above 7 indicate several network packets
615 calc_skips(gint32 curr, gint32 prev)
619 /* Only count the missing TS frames in between prev and curr.
620 * The "prev" frame CC number seen is confirmed received, its
621 * the next frames CC counter which is the first known missing
626 /* Calc missing TS frame 'skips' */
629 /* Handle wrap around */
636 #define KEY(pid, cc) ((pid << 4)|cc)
639 detect_cc_drops(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
640 guint32 pid, gint32 cc_curr, conversation_t *conv)
643 pid_analysis_data_t *pid_data = NULL;
644 ts_analysis_data_t *ts_data = NULL;
645 mp2t_analysis_data_t *mp2t_data = NULL;
646 frame_analysis_data_t *frame_analysis_data_p = NULL;
647 proto_item *flags_item;
649 guint32 detected_drop = 0;
652 mp2t_data = get_mp2t_conversation_data(conv);
654 /* The initial sequencial processing stage */
655 if (!pinfo->fd->flags.visited) {
657 /* This is the sequencial processing stage */
658 pid_data = get_pid_analysis(pid, conv);
660 cc_prev = pid_data->cc_prev;
661 pid_data->cc_prev = cc_curr;
663 /* Null packet always have a CC value equal 0 */
667 /* Its allowed that (cc_prev == cc_curr) if adaptation field */
668 if (cc_prev == cc_curr)
671 /* Have not seen this pid before */
675 /* Detect if CC is not increasing by one all the time */
676 if (cc_curr != ((cc_prev+1) & MP2T_CC_MASK)) {
679 skips = calc_skips(cc_curr, cc_prev);
681 mp2t_data->total_skips += skips;
682 mp2t_data->total_discontinuity++;
683 /* TODO: if (skips > 7) signal_loss++; ??? */
687 /* Save the info about the dropped packet */
688 if (detected_drop && !pinfo->fd->flags.visited) {
690 /* Lookup frame data, contains TS pid data objects */
691 frame_analysis_data_p = get_frame_analysis_data(mp2t_data, pinfo);
692 if (!frame_analysis_data_p)
693 frame_analysis_data_p = init_frame_analysis_data(mp2t_data, pinfo);
695 /* Create and store a new TS frame pid_data object.
696 This indicate that we have a drop
698 ts_data = se_alloc0(sizeof(struct ts_analysis_data));
699 ts_data->cc_prev = cc_prev;
701 ts_data->skips = skips;
702 se_tree_insert32(frame_analysis_data_p->ts_table, KEY(pid, cc_curr),
706 /* See if we stored info about drops */
707 if (pinfo->fd->flags.visited) {
709 /* Lookup frame data, contains TS pid data objects */
710 frame_analysis_data_p = get_frame_analysis_data(mp2t_data, pinfo);
711 if (!frame_analysis_data_p)
712 return 0; /* No stored frame data -> no drops*/
714 ts_data = se_tree_lookup32(frame_analysis_data_p->ts_table,
718 if (ts_data->skips > 0) {
720 cc_prev = ts_data->cc_prev;
721 skips = ts_data->skips;
728 /* Add info to the proto tree about drops */
732 proto_tree_add_none_format(
733 tree, hf_mp2t_cc_drop, tvb, 0, 0,
734 "Detected %d missing TS frames before this"
735 " (last_cc:%d total skips:%d discontinuity:%d)",
737 mp2t_data->total_skips,
738 mp2t_data->total_discontinuity
741 PROTO_ITEM_SET_GENERATED(flags_item);
742 expert_add_info_format(pinfo, flags_item, PI_MALFORMED,
743 PI_ERROR, "Detected TS frame loss");
745 flags_item = proto_tree_add_uint(tree, hf_mp2t_analysis_skips,
747 PROTO_ITEM_SET_GENERATED(flags_item);
749 flags_item = proto_tree_add_uint(tree, hf_mp2t_analysis_drops,
751 PROTO_ITEM_SET_GENERATED(flags_item);
759 dissect_tsp(tvbuff_t *tvb, volatile gint offset, packet_info *pinfo,
760 proto_tree *tree, conversation_t *conv)
764 gint start_offset = offset;
765 volatile gint payload_len;
771 proto_item *ti = NULL;
772 proto_item *hi = NULL;
773 proto_item *item = NULL;
774 proto_tree *mp2t_tree = NULL;
775 proto_tree *mp2t_header_tree = NULL;
776 proto_tree *mp2t_af_tree = NULL;
777 proto_tree *mp2t_analysis_tree = NULL;
779 ti = proto_tree_add_item( tree, proto_mp2t, tvb, offset, MP2T_PACKET_SIZE, ENC_NA );
780 mp2t_tree = proto_item_add_subtree( ti, ett_mp2t );
782 header = tvb_get_ntohl(tvb, offset);
784 pid = (header & MP2T_PID_MASK) >> MP2T_PID_SHIFT;
785 cc = (header & MP2T_CC_MASK) >> MP2T_CC_SHIFT;
786 proto_item_append_text(ti, " PID=0x%x CC=%d", pid, cc);
788 hi = proto_tree_add_item( mp2t_tree, hf_mp2t_header, tvb, offset, 4, ENC_BIG_ENDIAN);
789 mp2t_header_tree = proto_item_add_subtree( hi, ett_mp2t_header );
791 proto_tree_add_item( mp2t_header_tree, hf_mp2t_sync_byte, tvb, offset, 4, ENC_BIG_ENDIAN);
792 proto_tree_add_item( mp2t_header_tree, hf_mp2t_tei, tvb, offset, 4, ENC_BIG_ENDIAN);
793 proto_tree_add_item( mp2t_header_tree, hf_mp2t_pusi, tvb, offset, 4, ENC_BIG_ENDIAN);
794 proto_tree_add_item( mp2t_header_tree, hf_mp2t_tp, tvb, offset, 4, ENC_BIG_ENDIAN);
795 proto_tree_add_item( mp2t_header_tree, hf_mp2t_pid, tvb, offset, 4, ENC_BIG_ENDIAN);
796 proto_tree_add_item( mp2t_header_tree, hf_mp2t_tsc, tvb, offset, 4, ENC_BIG_ENDIAN);
797 proto_tree_add_item( mp2t_header_tree, hf_mp2t_afc, tvb, offset, 4, ENC_BIG_ENDIAN);
798 proto_tree_add_item( mp2t_header_tree, hf_mp2t_cc, tvb, offset, 4, ENC_BIG_ENDIAN);
800 /* If this is a DOCSIS packet - reassemble MPEG frames and call DOCSIS dissector */
801 if (((header & MP2T_PID_MASK) >> MP2T_PID_SHIFT) == 0x1FFE) {
802 mp2t_depi_docsis_process_payload(tvb, offset, pinfo, tree, mp2t_tree);
807 /* Create a subtree for analysis stuff */
808 item = proto_tree_add_text(mp2t_tree, tvb, 0, 0, "MPEG2 PCR Analysis");
809 PROTO_ITEM_SET_GENERATED(item);
810 mp2t_analysis_tree = proto_item_add_subtree(item, ett_mp2t_analysis);
812 skips = detect_cc_drops(tvb, mp2t_analysis_tree, pinfo, pid, cc, conv);
814 proto_item_append_text(ti, " skips=%d", skips);
817 afc = (header & MP2T_AFC_MASK) >> MP2T_AFC_SHIFT;
819 if (afc == 2 || afc == 3)
821 gint af_start_offset = offset;
828 af_length = tvb_get_guint8(tvb, offset);
830 proto_tree_add_item( mp2t_tree, hf_mp2t_af_length, tvb, offset, 1, ENC_BIG_ENDIAN);
832 /* fix issues where afc==3 but af_length==0
833 * Adaptaion field...spec section 2.4.3.5: The value 0 is for inserting a single
834 * stuffing byte in a Transport Stream packet. When the adaptation_field_control
835 * value is '11', the value of the adaptation_field_length shall be in the range 0 to 182.
837 if (af_length > 0 ) {
838 hi = proto_tree_add_item( mp2t_tree, hf_mp2t_af, tvb, offset, af_length, ENC_NA);
839 mp2t_af_tree = proto_item_add_subtree( hi, ett_mp2t_af );
841 af_flags = tvb_get_guint8(tvb, offset);
843 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_di, tvb, offset, 1, ENC_BIG_ENDIAN);
844 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_rai, tvb, offset, 1, ENC_BIG_ENDIAN);
845 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_espi, tvb, offset, 1, ENC_BIG_ENDIAN);
846 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_pcr_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
847 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_opcr_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
848 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_sp_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
849 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
850 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_afe_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
854 if (af_flags & MP2T_AF_PCR_MASK) {
855 guint64 pcr_base = 0;
859 tmp = tvb_get_guint8(tvb, offset);
860 pcr_base = (pcr_base << 8) | tmp;
863 tmp = tvb_get_guint8(tvb, offset);
864 pcr_base = (pcr_base << 8) | tmp;
867 tmp = tvb_get_guint8(tvb, offset);
868 pcr_base = (pcr_base << 8) | tmp;
871 tmp = tvb_get_guint8(tvb, offset);
872 pcr_base = (pcr_base << 8) | tmp;
875 tmp = tvb_get_guint8(tvb, offset);
876 pcr_base = (pcr_base << 1) | ((tmp >> 7) & 0x01);
877 pcr_ext = (tmp & 0x01);
880 tmp = tvb_get_guint8(tvb, offset);
881 pcr_ext = (pcr_ext << 8) | tmp;
884 proto_tree_add_none_format(mp2t_af_tree, hf_mp2t_af_pcr, tvb, offset - 6, 6,
885 "Program Clock Reference: base(%" G_GINT64_MODIFIER "u) * 300 + ext(%u) = %" G_GINT64_MODIFIER "u",
886 pcr_base, pcr_ext, pcr_base * 300 + pcr_ext);
889 if (af_flags & MP2T_AF_OPCR_MASK) {
890 guint64 opcr_base = 0;
891 guint32 opcr_ext = 0;
894 tmp = tvb_get_guint8(tvb, offset);
895 opcr_base = (opcr_base << 8) | tmp;
898 tmp = tvb_get_guint8(tvb, offset);
899 opcr_base = (opcr_base << 8) | tmp;
902 tmp = tvb_get_guint8(tvb, offset);
903 opcr_base = (opcr_base << 8) | tmp;
906 tmp = tvb_get_guint8(tvb, offset);
907 opcr_base = (opcr_base << 8) | tmp;
910 tmp = tvb_get_guint8(tvb, offset);
911 opcr_base = (opcr_base << 1) | ((tmp >> 7) & 0x01);
912 opcr_ext = (tmp & 0x01);
915 tmp = tvb_get_guint8(tvb, offset);
916 opcr_ext = (opcr_ext << 8) | tmp;
919 proto_tree_add_none_format(mp2t_af_tree, hf_mp2t_af_opcr, tvb, offset - 6, 6,
920 "Original Program Clock Reference: base(%" G_GINT64_MODIFIER "u) * 300 + ext(%u) = %" G_GINT64_MODIFIER "u",
921 opcr_base, opcr_ext, opcr_base * 300 + opcr_ext);
926 if (af_flags & MP2T_AF_SP_MASK) {
927 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_sc, tvb, offset, 1, ENC_BIG_ENDIAN);
931 if (af_flags & MP2T_AF_TPD_MASK) {
934 tpd_len = tvb_get_guint8(tvb, offset);
935 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd_length, tvb, offset, 1, ENC_BIG_ENDIAN);
938 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd, tvb, offset, tpd_len, ENC_NA);
942 if (af_flags & MP2T_AF_AFE_MASK) {
945 gint e_start_offset = offset;
946 gint reserved_len = 0;
948 e_len = tvb_get_guint8(tvb, offset);
949 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_length, tvb, offset, 1, ENC_BIG_ENDIAN);
952 e_flags = tvb_get_guint8(tvb, offset);
953 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltw_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
954 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
955 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ss_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
956 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
959 if (e_flags & MP2T_AF_E_LTW_FLAG_MASK) {
960 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltwv_flag, tvb, offset, 2, ENC_BIG_ENDIAN);
961 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltwo, tvb, offset, 2, ENC_BIG_ENDIAN);
965 if (e_flags & MP2T_AF_E_PR_FLAG_MASK) {
966 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr_reserved, tvb, offset, 3, ENC_BIG_ENDIAN);
967 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr, tvb, offset, 3, ENC_BIG_ENDIAN);
971 if (e_flags & MP2T_AF_E_SS_FLAG_MASK) {
972 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_st, tvb, offset, 1, ENC_BIG_ENDIAN);
973 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_32_30, tvb, offset, 1, ENC_BIG_ENDIAN);
974 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_1, tvb, offset, 1, ENC_BIG_ENDIAN);
976 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_29_15, tvb, offset, 2, ENC_BIG_ENDIAN);
977 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_2, tvb, offset, 2, ENC_BIG_ENDIAN);
979 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_14_0, tvb, offset, 2, ENC_BIG_ENDIAN);
980 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_3, tvb, offset, 2, ENC_BIG_ENDIAN);
984 reserved_len = (e_len + 1) - (offset - e_start_offset);
985 if (reserved_len > 0) {
986 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_reserved_bytes, tvb, offset, reserved_len, ENC_NA);
987 offset += reserved_len;
991 stuffing_len = (af_length + 1) - (offset - af_start_offset);
992 if (stuffing_len > 0) {
993 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_stuffing_bytes, tvb, offset, stuffing_len, ENC_NA);
994 offset += stuffing_len;
999 payload_len = MP2T_PACKET_SIZE - (offset - start_offset);
1000 if (payload_len > 0) {
1001 if (afc == 2) { /* AF only */
1002 /* Packet is malformed */
1003 proto_tree_add_item( mp2t_tree, hf_mp2t_malformed_payload, tvb, offset, payload_len, ENC_NA);
1004 offset += payload_len;
1006 /* Check to make sure if we are not at end of payload, if we have less than 3 bytes, the tvb_get_ntoh24 fails. */
1007 if (payload_len >=3 ) {
1008 if (tvb_get_ntoh24(tvb, offset) == 0x000001) {
1009 tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, payload_len, payload_len);
1010 const char *saved_proto = pinfo->current_proto;
1011 void *pd_save = pinfo->private_data;
1014 call_dissector(pes_handle, next_tvb, pinfo, mp2t_tree);
1018 Don't stop processing TS packets if somebody threw
1019 BoundsError, which means that dissecting the payload found
1020 that the packet was cut off by before the end of the
1021 payload. This is very likely as this protocol splits the
1022 media stream up into chunks of MP2T_PACKET_SIZE.
1024 CATCH2(BoundsError, ReportedBoundsError) {
1025 /* Restore the private_data structure in case one of the
1026 * called dissectors modified it (and, due to the exception,
1027 * was unable to restore it).
1029 pinfo->private_data = pd_save;
1030 show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
1031 pinfo->current_proto = saved_proto;
1036 proto_tree_add_item( mp2t_tree, hf_mp2t_payload, tvb, offset, payload_len, ENC_NA);
1039 proto_tree_add_item( mp2t_tree, hf_mp2t_payload, tvb, offset, payload_len, ENC_NA);
1041 offset += payload_len;
1050 dissect_mp2t( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
1053 conversation_t *conv;
1054 conv = find_or_create_conversation(pinfo);
1056 while ( tvb_reported_length_remaining(tvb, offset) >= MP2T_PACKET_SIZE ) {
1057 offset = dissect_tsp(tvb, offset, pinfo, tree, conv);
1062 heur_dissect_mp2t( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
1066 if (tvb_length_remaining(tvb, offset) % MP2T_PACKET_SIZE) {
1069 while (tvb_length_remaining(tvb, offset)) {
1070 if (tvb_get_guint8(tvb, offset) != MP2T_SYNC_BYTE)
1072 offset += MP2T_PACKET_SIZE;
1076 dissect_mp2t(tvb, pinfo, tree);
1083 fragment_table_init(&mp2t_depi_fragment_table);
1084 reassembled_table_init(&mp2t_depi_reassembled_table);
1088 proto_register_mp2t(void)
1090 static hf_register_info hf[] = {
1091 { &hf_mp2t_header, {
1092 "Header", "mp2t.header",
1093 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL
1095 { &hf_mp2t_sync_byte, {
1096 "Sync Byte", "mp2t.sync_byte",
1097 FT_UINT32, BASE_HEX, VALS(mp2t_sync_byte_vals), MP2T_SYNC_BYTE_MASK, NULL, HFILL
1100 "Transport Error Indicator", "mp2t.tei",
1101 FT_UINT32, BASE_DEC, NULL, MP2T_TEI_MASK, NULL, HFILL
1104 "Payload Unit Start Indicator", "mp2t.pusi",
1105 FT_UINT32, BASE_DEC, NULL, MP2T_PUSI_MASK, NULL, HFILL
1108 "Transport Priority", "mp2t.tp",
1109 FT_UINT32, BASE_DEC, NULL, MP2T_TP_MASK, NULL, HFILL
1113 FT_UINT32, BASE_HEX, VALS(mp2t_pid_vals), MP2T_PID_MASK, NULL, HFILL
1116 "Transport Scrambling Control", "mp2t.tsc",
1117 FT_UINT32, BASE_HEX, VALS(mp2t_tsc_vals), MP2T_TSC_MASK, NULL, HFILL
1120 "Adaption Field Control", "mp2t.afc",
1121 FT_UINT32, BASE_HEX, VALS(mp2t_afc_vals) , MP2T_AFC_MASK, NULL, HFILL
1124 "Continuity Counter", "mp2t.cc",
1125 FT_UINT32, BASE_DEC, NULL, MP2T_CC_MASK, NULL, HFILL
1127 { &hf_mp2t_cc_drop, {
1128 "Continuity Counter Drops", "mp2t.cc.drop",
1129 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL
1131 { &hf_mp2t_analysis_flags, {
1132 "MPEG2-TS Analysis Flags", "mp2t.analysis.flags",
1133 FT_NONE, BASE_NONE, NULL, 0x0,
1134 "This frame has some of the MPEG2 analysis flags set", HFILL
1136 { &hf_mp2t_analysis_skips, {
1137 "TS Continuity Counter Skips", "mp2t.analysis.skips",
1138 FT_UINT8, BASE_DEC, NULL, 0x0,
1139 "Missing TS frames accoding to CC counter values", HFILL
1141 { &hf_mp2t_analysis_drops, {
1142 "Some frames dropped", "mp2t.analysis.drops",
1143 FT_UINT8, BASE_DEC, NULL, 0x0,
1144 "Discontinuity: A number of TS frames were dropped", HFILL
1147 "Adaption field", "mp2t.af",
1148 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
1150 { &hf_mp2t_af_length, {
1151 "Adaptation Field Length", "mp2t.af.length",
1152 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL
1155 "Discontinuity Indicator", "mp2t.af.di",
1156 FT_UINT8, BASE_DEC, NULL, MP2T_AF_DI_MASK, NULL, HFILL
1158 { &hf_mp2t_af_rai, {
1159 "Random Access Indicator", "mp2t.af.rai",
1160 FT_UINT8, BASE_DEC, NULL, MP2T_AF_RAI_MASK, NULL, HFILL
1162 { &hf_mp2t_af_espi, {
1163 "Elementary Stream Priority Indicator", "mp2t.af.espi",
1164 FT_UINT8, BASE_DEC, NULL, MP2T_AF_ESPI_MASK, NULL, HFILL
1166 { &hf_mp2t_af_pcr_flag, {
1167 "PCR Flag", "mp2t.af.pcr_flag",
1168 FT_UINT8, BASE_DEC, NULL, MP2T_AF_PCR_MASK, NULL, HFILL
1170 { &hf_mp2t_af_opcr_flag, {
1171 "OPCR Flag", "mp2t.af.opcr_flag",
1172 FT_UINT8, BASE_DEC, NULL, MP2T_AF_OPCR_MASK, NULL, HFILL
1174 { &hf_mp2t_af_sp_flag, {
1175 "Splicing Point Flag", "mp2t.af.sp_flag",
1176 FT_UINT8, BASE_DEC, NULL, MP2T_AF_SP_MASK, NULL, HFILL
1178 { &hf_mp2t_af_tpd_flag, {
1179 "Transport Private Data Flag", "mp2t.af.tpd_flag",
1180 FT_UINT8, BASE_DEC, NULL, MP2T_AF_TPD_MASK, NULL, HFILL
1182 { &hf_mp2t_af_afe_flag, {
1183 "Adaptation Field Extension Flag", "mp2t.af.afe_flag",
1184 FT_UINT8, BASE_DEC, NULL, MP2T_AF_AFE_MASK, NULL, HFILL
1186 { &hf_mp2t_af_pcr, {
1187 "Program Clock Reference", "mp2t.af.pcr",
1188 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
1190 { &hf_mp2t_af_opcr, {
1191 "Original Program Clock Reference", "mp2t.af.opcr",
1192 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
1195 "Splice Countdown", "mp2t.af.sc",
1196 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
1198 { &hf_mp2t_af_tpd_length, {
1199 "Transport Private Data Length", "mp2t.af.tpd_length",
1200 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
1202 { &hf_mp2t_af_tpd, {
1203 "Transport Private Data", "mp2t.af.tpd",
1204 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL
1206 { &hf_mp2t_af_e_length, {
1207 "Adaptation Field Extension Length", "mp2t.af.e_length",
1208 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
1210 { &hf_mp2t_af_e_ltw_flag, {
1211 "LTW Flag", "mp2t.af.e.ltw_flag",
1212 FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_LTW_FLAG_MASK, NULL, HFILL
1214 { &hf_mp2t_af_e_pr_flag, {
1215 "Piecewise Rate Flag", "mp2t.af.e.pr_flag",
1216 FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_PR_FLAG_MASK, NULL, HFILL
1218 { &hf_mp2t_af_e_ss_flag, {
1219 "Seamless Splice Flag", "mp2t.af.e.ss_flag",
1220 FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_SS_FLAG_MASK, NULL, HFILL
1222 { &hf_mp2t_af_e_reserved, {
1223 "Reserved", "mp2t.af.e.reserved",
1224 FT_UINT8, BASE_DEC, NULL, 0x1F, NULL, HFILL
1226 { &hf_mp2t_af_e_reserved_bytes, {
1227 "Reserved", "mp2t.af.e.reserved_bytes",
1228 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1230 { &hf_mp2t_af_stuffing_bytes, {
1231 "Stuffing", "mp2t.af.stuffing_bytes",
1232 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1234 { &hf_mp2t_af_e_ltwv_flag, {
1235 "LTW Valid Flag", "mp2t.af.e.ltwv_flag",
1236 FT_UINT16, BASE_DEC, NULL, 0x8000, NULL, HFILL
1238 { &hf_mp2t_af_e_ltwo, {
1239 "LTW Offset", "mp2t.af.e.ltwo",
1240 FT_UINT16, BASE_DEC, NULL, 0x7FFF, NULL, HFILL
1242 { &hf_mp2t_af_e_pr_reserved, {
1243 "Reserved", "mp2t.af.e.pr_reserved",
1244 FT_UINT24, BASE_DEC, NULL, 0xC00000, NULL, HFILL
1246 { &hf_mp2t_af_e_pr, {
1247 "Piecewise Rate", "mp2t.af.e.pr",
1248 FT_UINT24, BASE_DEC, NULL, 0x3FFFFF, NULL, HFILL
1250 { &hf_mp2t_af_e_st, {
1251 "Splice Type", "mp2t.af.e.st",
1252 FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL
1254 { &hf_mp2t_af_e_dnau_32_30, {
1255 "DTS Next AU[32...30]", "mp2t.af.e.dnau_32_30",
1256 FT_UINT8, BASE_DEC, NULL, 0x0E, NULL, HFILL
1258 { &hf_mp2t_af_e_m_1, {
1259 "Marker Bit", "mp2t.af.e.m_1",
1260 FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL
1262 { &hf_mp2t_af_e_dnau_29_15, {
1263 "DTS Next AU[29...15]", "mp2t.af.e.dnau_29_15",
1264 FT_UINT16, BASE_DEC, NULL, 0xFFFE, NULL, HFILL
1266 { &hf_mp2t_af_e_m_2, {
1267 "Marker Bit", "mp2t.af.e.m_2",
1268 FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL
1270 { &hf_mp2t_af_e_dnau_14_0, {
1271 "DTS Next AU[14...0]", "mp2t.af.e.dnau_14_0",
1272 FT_UINT16, BASE_DEC, NULL, 0xFFFE, NULL, HFILL
1274 { &hf_mp2t_af_e_m_3, {
1275 "Marker Bit", "mp2t.af.e.m_3",
1276 FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL
1278 { &hf_mp2t_payload, {
1279 "Payload", "mp2t.payload",
1280 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1282 { &hf_mp2t_malformed_payload, {
1283 "Malformed Payload", "mp2t.malformed_payload",
1284 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1286 { &hf_depi_msg_fragments, {
1287 "Message fragments", "mp2t.depi_msg.fragments",
1288 FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL
1290 { &hf_depi_msg_fragment, {
1291 "Message fragment", "mp2t.depi_msg.fragment",
1292 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL
1294 { &hf_depi_msg_fragment_overlap, {
1295 "Message fragment overlap", "mp2t.depi_msg.fragment.overlap",
1296 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1298 { &hf_depi_msg_fragment_overlap_conflicts, {
1299 "Message fragment overlapping with conflicting data",
1300 "mp2t.depi_msg.fragment.overlap.conflicts",
1301 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1303 { &hf_depi_msg_fragment_multiple_tails, {
1304 "Message has multiple tail fragments",
1305 "mp2t.depi_msg.fragment.multiple_tails",
1306 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1308 { &hf_depi_msg_fragment_too_long_fragment, {
1309 "Message fragment too long", "mp2t.depi_msg.fragment.too_long_fragment",
1310 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1312 { &hf_depi_msg_fragment_error, {
1313 "Message defragmentation error", "mp2t.depi_msg.fragment.error",
1314 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL
1316 { &hf_depi_msg_fragment_count, {
1317 "Message fragment count", "mp2t.depi_msg.fragment.count",
1318 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL
1320 { &hf_depi_msg_reassembled_in, {
1321 "Reassembled in", "mp2t.depi_msg.reassembled.in",
1322 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL
1324 { &hf_depi_msg_reassembled_length, {
1325 "Reassembled MP2T length", "mp2t.depi_msg.reassembled.length",
1326 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL
1330 static gint *ett[] =
1337 &ett_depi_msg_fragment,
1338 &ett_depi_msg_fragments
1341 proto_mp2t = proto_register_protocol("ISO/IEC 13818-1", "MP2T", "mp2t");
1342 register_dissector("mp2t", dissect_mp2t, proto_mp2t);
1343 proto_register_field_array(proto_mp2t, hf, array_length(hf));
1344 proto_register_subtree_array(ett, array_length(ett));
1345 /* Register init of processing of fragmented DEPI packets */
1346 register_init_routine(mp2t_init);
1352 proto_reg_handoff_mp2t(void)
1354 dissector_handle_t mp2t_handle;
1356 heur_dissector_add("udp", heur_dissect_mp2t, proto_mp2t);
1358 mp2t_handle = create_dissector_handle(dissect_mp2t, proto_mp2t);
1359 dissector_add_uint("rtp.pt", PT_MP2T, mp2t_handle);
1360 dissector_add_handle("udp.port", mp2t_handle); /* for decode-as */
1361 heur_dissector_add("usb.bulk", heur_dissect_mp2t, proto_mp2t);
1363 pes_handle = find_dissector("mpeg-pes");
1364 docsis_handle = find_dissector("docsis");
1365 data_handle = find_dissector("data");