3 * Routines for RFC 2250 MPEG2 (ISO/IEC 13818-1) Transport Stream dissection
7 * Copyright 2006, Erwin Rol <erwin@erwinrol.com>
8 * Copyright 2012, Guy Martin <gmsoft@tuxicoman.be>
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #include <epan/packet.h>
36 #include <epan/rtp_pt.h>
37 #include "packet-frame.h"
39 #include <epan/emem.h>
40 #include <epan/conversation.h>
41 #include <epan/expert.h>
42 #include <epan/reassemble.h>
44 /* The MPEG2 TS packet size */
45 #define MP2T_PACKET_SIZE 188
46 #define MP2T_SYNC_BYTE 0x47
48 #define MP2T_PID_DOCSIS 0x1FFE
49 #define MP2T_PID_NULL 0x1FFF
51 static dissector_handle_t docsis_handle;
52 static dissector_handle_t mpeg_pes_handle;
53 static dissector_handle_t mpeg_sect_handle;
54 static dissector_handle_t data_handle;
56 static heur_dissector_list_t heur_subdissector_list;
58 static int proto_mp2t = -1;
59 static gint ett_mp2t = -1;
60 static gint ett_mp2t_header = -1;
61 static gint ett_mp2t_af = -1;
62 static gint ett_mp2t_analysis = -1;
63 static gint ett_stuff = -1;
65 static int hf_mp2t_header = -1;
66 static int hf_mp2t_sync_byte = -1;
67 static int hf_mp2t_tei = -1;
68 static int hf_mp2t_pusi = -1;
69 static int hf_mp2t_tp = -1;
70 static int hf_mp2t_pid = -1;
71 static int hf_mp2t_tsc = -1;
72 static int hf_mp2t_afc = -1;
73 static int hf_mp2t_cc = -1;
74 static int hf_mp2t_cc_drop = -1;
76 static int hf_mp2t_analysis_flags = -1;
77 static int hf_mp2t_analysis_skips = -1;
78 static int hf_mp2t_analysis_drops = -1;
80 #define MP2T_SYNC_BYTE_MASK 0xFF000000
81 #define MP2T_TEI_MASK 0x00800000
82 #define MP2T_PUSI_MASK 0x00400000
83 #define MP2T_TP_MASK 0x00200000
84 #define MP2T_PID_MASK 0x001FFF00
85 #define MP2T_TSC_MASK 0x000000C0
86 #define MP2T_AFC_MASK 0x00000030
87 #define MP2T_CC_MASK 0x0000000F
89 #define MP2T_SYNC_BYTE_SHIFT 24
90 #define MP2T_TEI_SHIFT 23
91 #define MP2T_PUSI_SHIFT 22
92 #define MP2T_TP_SHIFT 21
93 #define MP2T_PID_SHIFT 8
94 #define MP2T_TSC_SHIFT 6
95 #define MP2T_AFC_SHIFT 4
96 #define MP2T_CC_SHIFT 0
98 static int hf_mp2t_af = -1;
99 static int hf_mp2t_af_length = -1;
100 static int hf_mp2t_af_di = -1;
101 static int hf_mp2t_af_rai = -1;
102 static int hf_mp2t_af_espi = -1;
103 static int hf_mp2t_af_pcr_flag = -1;
104 static int hf_mp2t_af_opcr_flag = -1;
105 static int hf_mp2t_af_sp_flag = -1;
106 static int hf_mp2t_af_tpd_flag = -1;
107 static int hf_mp2t_af_afe_flag = -1;
109 #define MP2T_AF_DI_MASK 0x80
110 #define MP2T_AF_RAI_MASK 0x40
111 #define MP2T_AF_ESPI_MASK 0x20
112 #define MP2T_AF_PCR_MASK 0x10
113 #define MP2T_AF_OPCR_MASK 0x08
114 #define MP2T_AF_SP_MASK 0x04
115 #define MP2T_AF_TPD_MASK 0x02
116 #define MP2T_AF_AFE_MASK 0x01
118 #define MP2T_AF_DI_SHIFT 7
119 #define MP2T_AF_RAI_SHIFT 6
120 #define MP2T_AF_ESPI_SHIFT 5
121 #define MP2T_AF_PCR_SHIFT 4
122 #define MP2T_AF_OPCR_SHIFT 3
123 #define MP2T_AF_SP_SHIFT 2
124 #define MP2T_AF_TPD_SHIFT 1
125 #define MP2T_AF_AFE_SHIFT 0
127 static int hf_mp2t_af_pcr = -1;
128 static int hf_mp2t_af_opcr = -1;
130 static int hf_mp2t_af_sc = -1;
132 static int hf_mp2t_af_tpd_length = -1;
133 static int hf_mp2t_af_tpd = -1;
135 static int hf_mp2t_af_e_length = -1;
136 static int hf_mp2t_af_e_ltw_flag = -1;
137 static int hf_mp2t_af_e_pr_flag = -1;
138 static int hf_mp2t_af_e_ss_flag = -1;
139 static int hf_mp2t_af_e_reserved = -1;
141 #define MP2T_AF_E_LTW_FLAG_MASK 0x80
142 #define MP2T_AF_E_PR_FLAG_MASK 0x40
143 #define MP2T_AF_E_SS_FLAG_MASK 0x20
145 static int hf_mp2t_af_e_reserved_bytes = -1;
146 static int hf_mp2t_af_stuffing_bytes = -1;
148 static int hf_mp2t_af_e_ltwv_flag = -1;
149 static int hf_mp2t_af_e_ltwo = -1;
151 static int hf_mp2t_af_e_pr_reserved = -1;
152 static int hf_mp2t_af_e_pr = -1;
154 static int hf_mp2t_af_e_st = -1;
155 static int hf_mp2t_af_e_dnau_32_30 = -1;
156 static int hf_mp2t_af_e_m_1 = -1;
157 static int hf_mp2t_af_e_dnau_29_15 = -1;
158 static int hf_mp2t_af_e_m_2 = -1;
159 static int hf_mp2t_af_e_dnau_14_0 = -1;
160 static int hf_mp2t_af_e_m_3 = -1;
162 static int hf_mp2t_payload = -1;
163 static int hf_mp2t_stuff_bytes = -1;
166 static const value_string mp2t_sync_byte_vals[] = {
167 { MP2T_SYNC_BYTE, "Correct" },
171 static const value_string mp2t_pid_vals[] = {
172 { 0x0000, "Program Association Table" },
173 { 0x0001, "Conditional Access Table" },
174 { 0x0002, "Transport Stream Description Table" },
175 { 0x0003, "Reserved" },
176 { 0x0004, "Reserved" },
177 { 0x0005, "Reserved" },
178 { 0x0006, "Reserved" },
179 { 0x0007, "Reserved" },
180 { 0x0008, "Reserved" },
181 { 0x0009, "Reserved" },
182 { 0x000A, "Reserved" },
183 { 0x000B, "Reserved" },
184 { 0x000C, "Reserved" },
185 { 0x000D, "Reserved" },
186 { 0x000E, "Reserved" },
187 { 0x000F, "Reserved" },
188 { 0x1FFE, "DOCSIS Data-over-cable well-known PID" },
189 { 0x1FFF, "Null packet" },
193 static const value_string mp2t_tsc_vals[] = {
194 { 0, "Not scrambled" },
195 { 1, "User-defined" },
196 { 2, "User-defined" },
197 { 3, "User-defined" },
201 static const value_string mp2t_afc_vals[] = {
203 { 1, "Payload only" },
204 { 2, "Adaptation Field only" },
205 { 3, "Adaptation Field and Payload" },
209 static gint ett_msg_fragment = -1;
210 static gint ett_msg_fragments = -1;
211 static int hf_msg_fragments = -1;
212 static int hf_msg_fragment = -1;
213 static int hf_msg_fragment_overlap = -1;
214 static int hf_msg_fragment_overlap_conflicts = -1;
215 static int hf_msg_fragment_multiple_tails = -1;
216 static int hf_msg_fragment_too_long_fragment = -1;
217 static int hf_msg_fragment_error = -1;
218 static int hf_msg_fragment_count = -1;
219 static int hf_msg_reassembled_in = -1;
220 static int hf_msg_reassembled_length = -1;
222 static const fragment_items mp2t_msg_frag_items = {
223 /* Fragment subtrees */
226 /* Fragment fields */
229 &hf_msg_fragment_overlap,
230 &hf_msg_fragment_overlap_conflicts,
231 &hf_msg_fragment_multiple_tails,
232 &hf_msg_fragment_too_long_fragment,
233 &hf_msg_fragment_error,
234 &hf_msg_fragment_count,
235 /* Reassembled in field */
236 &hf_msg_reassembled_in,
237 /* Reassembled length field */
238 &hf_msg_reassembled_length,
244 /* Data structure used for detecting CC drops
248 * +-> mp2t_analysis_data
250 * +-> pid_table (RB tree) (key: pid)
252 * | +-> pid_analysis_data (per pid)
253 * | +-> pid_analysis_data
254 * | +-> pid_analysis_data
256 * +-> frame_table (RB tree) (key: pinfo->fd->num)
258 * +-> frame_analysis_data (only created if drop detected)
260 * +-> ts_table (RB tree)
262 * +-> ts_analysis_data (per TS subframe)
263 * +-> ts_analysis_data
264 * +-> ts_analysis_data
267 typedef struct mp2t_analysis_data {
269 /* This structure contains a tree containing data for the
270 * individual pid's, this is only used when packets are
271 * processed sequencially.
273 emem_tree_t *pid_table;
275 /* When detecting a CC drop, store that information for the
276 * given frame. This info is needed, when clicking around in
277 * wireshark, as the pid table data only makes sence during
278 * sequencial processing. The flag pinfo->fd->flags.visited is
279 * used to tell the difference.
282 emem_tree_t *frame_table;
284 /* Total counters per conversation / multicast stream */
286 guint32 total_discontinuity;
288 } mp2t_analysis_data_t;
290 enum pid_payload_type {
298 typedef struct subpacket_analysis_data {
299 guint32 frag_cur_pos;
300 guint32 frag_tot_len;
301 gboolean fragmentation;
303 } subpacket_analysis_data_t;
305 typedef struct packet_analysis_data {
307 /* Contain information for each MPEG2-TS packet in the current big packet */
308 emem_tree_t *subpacket_table;
309 } packed_analysis_data_t;
311 /* Analysis TS frame info needed during sequential processing */
312 typedef struct pid_analysis_data {
314 gint8 cc_prev; /* Previous CC number */
315 enum pid_payload_type pload_type;
317 /* Fragments information used for first pass */
318 gboolean fragmentation;
319 guint32 frag_cur_pos;
320 guint32 frag_tot_len;
322 } pid_analysis_data_t;
324 /* Analysis info stored for a TS frame */
325 typedef struct ts_analysis_data {
327 gint8 cc_prev; /* Previous CC number */
328 guint8 skips; /* Skips between CCs max 14 */
329 } ts_analysis_data_t;
332 typedef struct frame_analysis_data {
334 /* As each frame has several pid's, thus need a pid data
335 * structure per TS frame.
337 emem_tree_t *ts_table;
339 } frame_analysis_data_t;
341 static mp2t_analysis_data_t *
342 init_mp2t_conversation_data(void)
344 mp2t_analysis_data_t *mp2t_data = NULL;
346 mp2t_data = se_alloc0(sizeof(struct mp2t_analysis_data));
348 mp2t_data->pid_table =
349 se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,
351 mp2t_data->frame_table =
352 se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,
355 mp2t_data->total_skips = 0;
356 mp2t_data->total_discontinuity = 0;
361 static mp2t_analysis_data_t *
362 get_mp2t_conversation_data(conversation_t *conv)
364 mp2t_analysis_data_t *mp2t_data = NULL;
366 mp2t_data = conversation_get_proto_data(conv, proto_mp2t);
368 mp2t_data = init_mp2t_conversation_data();
369 conversation_add_proto_data(conv, proto_mp2t, mp2t_data);
375 static frame_analysis_data_t *
376 init_frame_analysis_data(mp2t_analysis_data_t *mp2t_data, packet_info *pinfo)
378 frame_analysis_data_t *frame_analysis_data_p = NULL;
380 frame_analysis_data_p = se_alloc0(sizeof(struct frame_analysis_data));
381 frame_analysis_data_p->ts_table =
382 se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,
383 "mp2t_frame_pid_table");
384 /* Insert into mp2t tree */
385 se_tree_insert32(mp2t_data->frame_table, pinfo->fd->num,
386 (void *)frame_analysis_data_p);
388 return frame_analysis_data_p;
392 static frame_analysis_data_t *
393 get_frame_analysis_data(mp2t_analysis_data_t *mp2t_data, packet_info *pinfo)
395 frame_analysis_data_t *frame_analysis_data_p = NULL;
396 frame_analysis_data_p = se_tree_lookup32(mp2t_data->frame_table, pinfo->fd->num);
397 return frame_analysis_data_p;
400 static pid_analysis_data_t *
401 get_pid_analysis(guint32 pid, conversation_t *conv)
404 pid_analysis_data_t *pid_data = NULL;
405 mp2t_analysis_data_t *mp2t_data = NULL;
406 mp2t_data = get_mp2t_conversation_data(conv);
408 pid_data = se_tree_lookup32(mp2t_data->pid_table, pid);
410 pid_data = se_alloc0(sizeof(struct pid_analysis_data));
411 pid_data->cc_prev = -1;
413 pid_data->frag_id = (pid << (32 - 13)) | 0x1;
415 se_tree_insert32(mp2t_data->pid_table, pid, (void *)pid_data);
419 /* Structures to handle packets, spanned across
420 * multiple MPEG packets
422 static GHashTable *mp2t_fragment_table = NULL;
423 static GHashTable *mp2t_reassembled_table = NULL;
426 mp2t_dissect_packet(tvbuff_t *tvb, enum pid_payload_type pload_type,
427 packet_info *pinfo, proto_tree *tree)
429 dissector_handle_t handle = NULL;
432 switch (pload_type) {
433 case pid_pload_docsis:
434 handle = docsis_handle;
437 handle = mpeg_pes_handle;
440 handle = mpeg_sect_handle;
443 /* Should not happen */
449 call_dissector(handle, tvb, pinfo, tree);
451 call_dissector(data_handle, tvb, pinfo, tree);
457 mp2t_get_packet_length(tvbuff_t *tvb, guint offset, packet_info *pinfo,
458 guint32 frag_id, enum pid_payload_type pload_type)
461 fragment_data *frag = NULL;
462 tvbuff_t *len_tvb = NULL, *frag_tvb = NULL, *data_tvb = NULL;
467 remaining_len = tvb_length_remaining(tvb, offset);
468 frag = fragment_get(pinfo, frag_id, mp2t_fragment_table);
472 if (!frag) { /* First frame */
474 if ( (pload_type == pid_pload_docsis && remaining_len < 4) ||
475 (pload_type == pid_pload_sect && remaining_len < 3) ||
476 (pload_type == pid_pload_pes && remaining_len < 5) ) {
477 /* Not enough info to determine the size of the encapulated packet */
478 /* Just add the fragment and we'll check out the length later */
485 /* Create a composite tvb out of the two */
486 frag_tvb = tvb_new_real_data(frag->data, frag->len, frag->len);
487 len_tvb = tvb_new_composite();
488 tvb_composite_append(len_tvb, frag_tvb);
490 data_tvb = tvb_new_subset(tvb, offset, -1, -1);
491 tvb_composite_append(len_tvb, data_tvb);
492 tvb_composite_finalize(len_tvb);
494 offset = frag->offset;
498 /* Get the next packet's size if possible */
500 switch (pload_type) {
501 case pid_pload_docsis:
502 pkt_len = tvb_get_ntohs(len_tvb, offset + 2) + 6;
505 pkt_len = tvb_get_ntohs(len_tvb, offset + 3);
506 if (pkt_len) /* A size of 0 means size not bounded */
510 pkt_len = (tvb_get_ntohs(len_tvb, offset + 1) & 0xFFF) + 3;
513 /* Should not happen */
524 mp2t_fragment_handle(tvbuff_t *tvb, guint offset, packet_info *pinfo,
525 proto_tree *tree, guint32 frag_id,
526 guint frag_offset, guint frag_len,
527 gboolean fragment_last, enum pid_payload_type pload_type)
530 fragment_data *frag_msg = NULL;
531 tvbuff_t *new_tvb = NULL;
532 gboolean save_fragmented;
534 save_fragmented = pinfo->fragmented;
535 pinfo->fragmented = TRUE;
537 /* check length; send frame for reassembly */
538 frag_msg = fragment_add_check(tvb, offset, pinfo,
539 frag_id, mp2t_fragment_table,
540 mp2t_reassembled_table,
545 new_tvb = process_reassembled_data(tvb, offset, pinfo,
547 frag_msg, &mp2t_msg_frag_items,
551 ti = proto_tree_add_text(tree, tvb, 0, 0, "MPEG TS Packet (reassembled)");
552 mp2t_dissect_packet(new_tvb, pload_type, pinfo, tree);
555 pinfo->fragmented = save_fragmented;
560 /* Decoding of DOCSIS MAC frames within MPEG packets. MAC frames may begin anywhere
561 * within an MPEG packet or span multiple MPEG packets.
562 * payload_unit_start_indicator bit in MPEG header, and pointer field are used to
563 * decode fragmented DOCSIS frames within MPEG packet.
564 *-------------------------------------------------------------------------------
565 *MPEG Header | pointer_field | stuff_bytes | Start of MAC Frame #1 |
566 *(PUSI = 1) | (= 0) | (0 or more) |(up to 183 bytes) |
567 *-------------------------------------------------------------------------------
568 *-------------------------------------------------------------------------------
569 *MPEG Header | Continuation of MAC Frame #1 |
570 *(PUSI = 0) | (up to 183 bytes) |
571 *-------------------------------------------------------------------------------
572 *-------------------------------------------------------------------------------
573 *MPEG Header | pointer_field |Tail of MAC Frame| stuff_bytes |Start of MAC Frame|
574 *(PUSI = 1) | (= M) | #1 (M bytes) | (0 or more) |# 2 (N bytes) |
575 *-------------------------------------------------------------------------------
576 * Source - Data-Over-Cable Service Interface Specifications
577 * CM-SP-DRFI-I07-081209
580 mp2t_process_fragmented_payload(tvbuff_t *tvb, gint offset, guint remaining_len, packet_info *pinfo,
581 proto_tree *tree, proto_tree *header_tree, guint32 pusi_flag,
582 pid_analysis_data_t *pid_analysis)
588 proto_tree *stuff_tree;
589 packed_analysis_data_t *pdata = NULL;
590 subpacket_analysis_data_t *spdata = NULL;
591 guint32 frag_cur_pos = 0, frag_tot_len = 0;
592 gboolean fragmentation = FALSE;
595 if (pusi_flag && pid_analysis->pload_type == pid_pload_unknown
596 && remaining_len > 3) {
597 /* We should already have identified if it was a DOCSIS packet
598 * Remaining possibility is PES or SECT */
599 if (tvb_get_ntoh24(tvb, offset) == 0x000001) {
600 /* Looks like a PES packet to me ... */
601 pid_analysis->pload_type = pid_pload_pes;
603 /* Most probably a SECT packet */
604 pid_analysis->pload_type = pid_pload_sect;
609 /* Unable to determine the payload type, do nothing */
610 if (pid_analysis->pload_type == pid_pload_unknown)
613 /* PES packet don't have pointer fields, others do */
614 if (pusi_flag && pid_analysis->pload_type != pid_pload_pes) {
615 pointer = tvb_get_guint8(tvb, offset);
616 proto_tree_add_text(header_tree, tvb, offset, 1,
617 "Pointer: %u", tvb_get_guint8(tvb, offset));
623 if (!pinfo->fd->flags.visited) {
624 /* Get values from our current PID analysis */
625 frag_cur_pos = pid_analysis->frag_cur_pos;
626 frag_tot_len = pid_analysis->frag_tot_len;
627 fragmentation = pid_analysis->fragmentation;
628 frag_id = pid_analysis->frag_id;
629 pdata = p_get_proto_data(pinfo->fd, proto_mp2t);
631 pdata = se_alloc0(sizeof(packed_analysis_data_t));
632 pdata->subpacket_table = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "mp2t_frame_table");
633 p_add_proto_data(pinfo->fd, proto_mp2t, pdata);
636 spdata = se_tree_lookup32(pdata->subpacket_table, offset);
640 spdata = se_alloc0(sizeof(subpacket_analysis_data_t));
641 /* Save the info into pdata from pid_analysis */
642 spdata->frag_cur_pos = frag_cur_pos;
643 spdata->frag_tot_len = frag_tot_len;
644 spdata->fragmentation = fragmentation;
645 spdata->frag_id = frag_id;
646 se_tree_insert32(pdata->subpacket_table, offset, (void *)spdata);
651 /* Get saved values */
652 pdata = p_get_proto_data(pinfo->fd, proto_mp2t);
654 /* Occurs for the first packets in the capture which cannot be reassembled */
658 spdata = se_tree_lookup32(pdata->subpacket_table, offset);
660 /* Occurs for the first sub packets in the capture which cannot be reassembled */
664 frag_cur_pos = spdata->frag_cur_pos;
665 frag_tot_len = spdata->frag_tot_len;
666 fragmentation = spdata->fragmentation;
667 frag_id = spdata->frag_id;
670 if (frag_tot_len == (guint)-1) {
671 frag_tot_len = mp2t_get_packet_length(tvb, offset, pinfo, frag_id, pid_analysis->pload_type);
673 if (frag_tot_len == (guint)-1) {
680 /* The begining of a new packet is present */
683 /* Looks like we already have some stuff in the buffer */
685 mp2t_fragment_handle(tvb, offset, pinfo, tree, frag_id, frag_cur_pos,
686 pointer, TRUE, pid_analysis->pload_type);
691 remaining_len -= pointer;
692 fragmentation = FALSE;
696 if (!remaining_len) {
697 /* Shouldn't happen */
701 while (remaining_len > 0) {
703 /* Skip stuff bytes */
705 while ((tvb_get_guint8(tvb, offset + stuff_len) == 0xFF)) {
707 if (remaining_len - stuff_len <= 0)
712 si = proto_tree_add_text(tree, tvb, offset, stuff_len, "Stuffing");
713 stuff_tree = proto_item_add_subtree(si, ett_stuff);
714 proto_tree_add_item(stuff_tree, hf_mp2t_stuff_bytes, tvb, offset, stuff_len, ENC_NA);
716 remaining_len -= stuff_len;
723 /* Get the next packet's size if possible */
724 frag_tot_len = mp2t_get_packet_length(tvb, offset, pinfo, frag_id, pid_analysis->pload_type);
725 if (frag_tot_len == (guint)-1 || !frag_tot_len) {
726 mp2t_fragment_handle(tvb, offset, pinfo, tree, frag_id, 0, remaining_len, FALSE, pid_analysis->pload_type);
727 fragmentation = TRUE;
728 offset += remaining_len;
729 frag_cur_pos += remaining_len;
733 /* Check for full packets within this TS frame */
735 frag_tot_len <= remaining_len) {
736 next_tvb = tvb_new_subset(tvb, offset, frag_tot_len, frag_tot_len);
737 mp2t_dissect_packet(next_tvb, pid_analysis->pload_type, pinfo, tree);
738 remaining_len -= frag_tot_len;
739 offset += frag_tot_len;
747 if (!remaining_len) {
748 pid_analysis->frag_cur_pos = 0;
749 pid_analysis->frag_tot_len = 0;
756 /* There are remaining bytes. Add them to the fragment list */
758 if (frag_cur_pos + remaining_len >= frag_tot_len) {
759 mp2t_fragment_handle(tvb, offset, pinfo, tree, frag_id, frag_cur_pos, remaining_len, TRUE, pid_analysis->pload_type);
761 fragmentation = FALSE;
765 mp2t_fragment_handle(tvb, offset, pinfo, tree, frag_id, frag_cur_pos, remaining_len, FALSE, pid_analysis->pload_type);
766 fragmentation = TRUE;
767 frag_cur_pos += remaining_len;
772 pid_analysis->fragmentation = fragmentation;
773 pid_analysis->frag_cur_pos = frag_cur_pos;
774 pid_analysis->frag_tot_len = frag_tot_len;
775 pid_analysis->frag_id = frag_id;
782 /* Calc the number of skipped CC numbers. Note that this can easy
783 * overflow, and a value above 7 indicate several network packets
787 calc_skips(gint32 curr, gint32 prev)
791 /* Only count the missing TS frames in between prev and curr.
792 * The "prev" frame CC number seen is confirmed received, its
793 * the next frames CC counter which is the first known missing
798 /* Calc missing TS frame 'skips' */
801 /* Handle wrap around */
808 #define KEY(pid, cc) ((pid << 4)|cc)
811 detect_cc_drops(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
812 guint32 pid, gint32 cc_curr, conversation_t *conv)
815 pid_analysis_data_t *pid_data = NULL;
816 ts_analysis_data_t *ts_data = NULL;
817 mp2t_analysis_data_t *mp2t_data = NULL;
818 frame_analysis_data_t *frame_analysis_data_p = NULL;
819 proto_item *flags_item;
821 guint32 detected_drop = 0;
824 mp2t_data = get_mp2t_conversation_data(conv);
826 /* The initial sequencial processing stage */
827 if (!pinfo->fd->flags.visited) {
829 /* This is the sequencial processing stage */
830 pid_data = get_pid_analysis(pid, conv);
832 cc_prev = pid_data->cc_prev;
833 pid_data->cc_prev = cc_curr;
835 /* Null packet always have a CC value equal 0 */
839 /* Its allowed that (cc_prev == cc_curr) if adaptation field */
840 if (cc_prev == cc_curr)
843 /* Have not seen this pid before */
847 /* Detect if CC is not increasing by one all the time */
848 if (cc_curr != ((cc_prev+1) & MP2T_CC_MASK)) {
851 skips = calc_skips(cc_curr, cc_prev);
853 mp2t_data->total_skips += skips;
854 mp2t_data->total_discontinuity++;
855 /* TODO: if (skips > 7) signal_loss++; ??? */
859 /* Save the info about the dropped packet */
860 if (detected_drop && !pinfo->fd->flags.visited) {
862 /* Lookup frame data, contains TS pid data objects */
863 frame_analysis_data_p = get_frame_analysis_data(mp2t_data, pinfo);
864 if (!frame_analysis_data_p)
865 frame_analysis_data_p = init_frame_analysis_data(mp2t_data, pinfo);
867 /* Create and store a new TS frame pid_data object.
868 This indicate that we have a drop
870 ts_data = se_alloc0(sizeof(struct ts_analysis_data));
871 ts_data->cc_prev = cc_prev;
873 ts_data->skips = skips;
874 se_tree_insert32(frame_analysis_data_p->ts_table, KEY(pid, cc_curr),
878 /* See if we stored info about drops */
879 if (pinfo->fd->flags.visited) {
881 /* Lookup frame data, contains TS pid data objects */
882 frame_analysis_data_p = get_frame_analysis_data(mp2t_data, pinfo);
883 if (!frame_analysis_data_p)
884 return 0; /* No stored frame data -> no drops*/
886 ts_data = se_tree_lookup32(frame_analysis_data_p->ts_table,
890 if (ts_data->skips > 0) {
892 cc_prev = ts_data->cc_prev;
893 skips = ts_data->skips;
900 /* Add info to the proto tree about drops */
904 proto_tree_add_none_format(
905 tree, hf_mp2t_cc_drop, tvb, 0, 0,
906 "Detected %d missing TS frames before this"
907 " (last_cc:%d total skips:%d discontinuity:%d)",
909 mp2t_data->total_skips,
910 mp2t_data->total_discontinuity
913 PROTO_ITEM_SET_GENERATED(flags_item);
914 expert_add_info_format(pinfo, flags_item, PI_MALFORMED,
915 PI_ERROR, "Detected TS frame loss");
917 flags_item = proto_tree_add_uint(tree, hf_mp2t_analysis_skips,
919 PROTO_ITEM_SET_GENERATED(flags_item);
921 flags_item = proto_tree_add_uint(tree, hf_mp2t_analysis_drops,
923 PROTO_ITEM_SET_GENERATED(flags_item);
931 dissect_tsp(tvbuff_t *tvb, volatile gint offset, packet_info *pinfo,
932 proto_tree *tree, conversation_t *conv)
936 gint start_offset = offset;
937 volatile gint payload_len;
938 pid_analysis_data_t *pid_analysis;
946 proto_item *ti = NULL;
947 proto_item *hi = NULL;
948 proto_item *item = NULL;
949 proto_tree *mp2t_tree = NULL;
950 proto_tree *mp2t_header_tree = NULL;
951 proto_tree *mp2t_af_tree = NULL;
952 proto_tree *mp2t_analysis_tree = NULL;
953 proto_item *afci = NULL;
955 ti = proto_tree_add_item( tree, proto_mp2t, tvb, offset, MP2T_PACKET_SIZE, ENC_NA );
956 mp2t_tree = proto_item_add_subtree( ti, ett_mp2t );
958 header = tvb_get_ntohl(tvb, offset);
960 pid = (header & MP2T_PID_MASK) >> MP2T_PID_SHIFT;
961 cc = (header & MP2T_CC_MASK) >> MP2T_CC_SHIFT;
962 pusi_flag = (header & 0x00400000);
963 proto_item_append_text(ti, " PID=0x%x CC=%d", pid, cc);
964 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPEG TS");
966 hi = proto_tree_add_item( mp2t_tree, hf_mp2t_header, tvb, offset, 4, ENC_BIG_ENDIAN);
967 mp2t_header_tree = proto_item_add_subtree( hi, ett_mp2t_header );
969 proto_tree_add_item( mp2t_header_tree, hf_mp2t_sync_byte, tvb, offset, 4, ENC_BIG_ENDIAN);
970 proto_tree_add_item( mp2t_header_tree, hf_mp2t_tei, tvb, offset, 4, ENC_BIG_ENDIAN);
971 proto_tree_add_item( mp2t_header_tree, hf_mp2t_pusi, tvb, offset, 4, ENC_BIG_ENDIAN);
972 proto_tree_add_item( mp2t_header_tree, hf_mp2t_tp, tvb, offset, 4, ENC_BIG_ENDIAN);
973 proto_tree_add_item( mp2t_header_tree, hf_mp2t_pid, tvb, offset, 4, ENC_BIG_ENDIAN);
974 proto_tree_add_item( mp2t_header_tree, hf_mp2t_tsc, tvb, offset, 4, ENC_BIG_ENDIAN);
975 afci = proto_tree_add_item( mp2t_header_tree, hf_mp2t_afc, tvb, offset, 4, ENC_BIG_ENDIAN);
976 proto_tree_add_item( mp2t_header_tree, hf_mp2t_cc, tvb, offset, 4, ENC_BIG_ENDIAN);
980 pointer = tvb_get_guint8(tvb, offset);
982 afc = (header & MP2T_AFC_MASK) >> MP2T_AFC_SHIFT;
984 pid_analysis = get_pid_analysis(pid, conv);
986 /* Find out the payload type based on the payload */
987 if (pid_analysis->pload_type == pid_pload_unknown) {
988 if (pid == MP2T_PID_NULL) {
989 pid_analysis->pload_type = pid_pload_null;
990 } else if (pid == MP2T_PID_DOCSIS) {
991 pid_analysis->pload_type = pid_pload_docsis;
995 if (pid_analysis->pload_type == pid_pload_docsis && afc) {
996 /* DOCSIS packets should not have an adaptation field */
997 proto_item_append_text(afci, " (Invalid for DOCSIS packets, should be 0)");
1001 if (pid_analysis->pload_type == pid_pload_null) {
1002 /* Nothing more to do */
1003 col_set_str(pinfo->cinfo, COL_INFO, "NULL packet");
1004 proto_item_append_text(afci, " (Should be 0 for NULL packets)");
1010 /* Create a subtree for analysis stuff */
1011 item = proto_tree_add_text(mp2t_tree, tvb, offset, 0, "MPEG2 PCR Analysis");
1012 PROTO_ITEM_SET_GENERATED(item);
1013 mp2t_analysis_tree = proto_item_add_subtree(item, ett_mp2t_analysis);
1015 skips = detect_cc_drops(tvb, mp2t_analysis_tree, pinfo, pid, cc, conv);
1017 proto_item_append_text(ti, " skips=%d", skips);
1019 if (afc == 2 || afc == 3)
1021 gint af_start_offset = offset;
1028 af_length = tvb_get_guint8(tvb, offset);
1030 proto_tree_add_item( mp2t_tree, hf_mp2t_af_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1032 /* fix issues where afc==3 but af_length==0
1033 * Adaptaion field...spec section 2.4.3.5: The value 0 is for inserting a single
1034 * stuffing byte in a Transport Stream packet. When the adaptation_field_control
1035 * value is '11', the value of the adaptation_field_length shall be in the range 0 to 182.
1037 if (af_length > 0 ) {
1038 hi = proto_tree_add_item( mp2t_tree, hf_mp2t_af, tvb, offset, af_length, ENC_NA);
1039 mp2t_af_tree = proto_item_add_subtree( hi, ett_mp2t_af );
1041 af_flags = tvb_get_guint8(tvb, offset);
1043 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_di, tvb, offset, 1, ENC_BIG_ENDIAN);
1044 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_rai, tvb, offset, 1, ENC_BIG_ENDIAN);
1045 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_espi, tvb, offset, 1, ENC_BIG_ENDIAN);
1046 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_pcr_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
1047 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_opcr_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
1048 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_sp_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
1049 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
1050 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_afe_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
1054 if (af_flags & MP2T_AF_PCR_MASK) {
1055 guint64 pcr_base = 0;
1056 guint32 pcr_ext = 0;
1059 tmp = tvb_get_guint8(tvb, offset);
1060 pcr_base = (pcr_base << 8) | tmp;
1063 tmp = tvb_get_guint8(tvb, offset);
1064 pcr_base = (pcr_base << 8) | tmp;
1067 tmp = tvb_get_guint8(tvb, offset);
1068 pcr_base = (pcr_base << 8) | tmp;
1071 tmp = tvb_get_guint8(tvb, offset);
1072 pcr_base = (pcr_base << 8) | tmp;
1075 tmp = tvb_get_guint8(tvb, offset);
1076 pcr_base = (pcr_base << 1) | ((tmp >> 7) & 0x01);
1077 pcr_ext = (tmp & 0x01);
1080 tmp = tvb_get_guint8(tvb, offset);
1081 pcr_ext = (pcr_ext << 8) | tmp;
1084 proto_tree_add_none_format(mp2t_af_tree, hf_mp2t_af_pcr, tvb, offset - 6, 6,
1085 "Program Clock Reference: base(%" G_GINT64_MODIFIER "u) * 300 + ext(%u) = %" G_GINT64_MODIFIER "u",
1086 pcr_base, pcr_ext, pcr_base * 300 + pcr_ext);
1089 if (af_flags & MP2T_AF_OPCR_MASK) {
1090 guint64 opcr_base = 0;
1091 guint32 opcr_ext = 0;
1094 tmp = tvb_get_guint8(tvb, offset);
1095 opcr_base = (opcr_base << 8) | tmp;
1098 tmp = tvb_get_guint8(tvb, offset);
1099 opcr_base = (opcr_base << 8) | tmp;
1102 tmp = tvb_get_guint8(tvb, offset);
1103 opcr_base = (opcr_base << 8) | tmp;
1106 tmp = tvb_get_guint8(tvb, offset);
1107 opcr_base = (opcr_base << 8) | tmp;
1110 tmp = tvb_get_guint8(tvb, offset);
1111 opcr_base = (opcr_base << 1) | ((tmp >> 7) & 0x01);
1112 opcr_ext = (tmp & 0x01);
1115 tmp = tvb_get_guint8(tvb, offset);
1116 opcr_ext = (opcr_ext << 8) | tmp;
1119 proto_tree_add_none_format(mp2t_af_tree, hf_mp2t_af_opcr, tvb, offset - 6, 6,
1120 "Original Program Clock Reference: base(%" G_GINT64_MODIFIER "u) * 300 + ext(%u) = %" G_GINT64_MODIFIER "u",
1121 opcr_base, opcr_ext, opcr_base * 300 + opcr_ext);
1126 if (af_flags & MP2T_AF_SP_MASK) {
1127 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_sc, tvb, offset, 1, ENC_BIG_ENDIAN);
1131 if (af_flags & MP2T_AF_TPD_MASK) {
1134 tpd_len = tvb_get_guint8(tvb, offset);
1135 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1138 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd, tvb, offset, tpd_len, ENC_NA);
1142 if (af_flags & MP2T_AF_AFE_MASK) {
1145 gint e_start_offset = offset;
1146 gint reserved_len = 0;
1148 e_len = tvb_get_guint8(tvb, offset);
1149 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1152 e_flags = tvb_get_guint8(tvb, offset);
1153 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltw_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
1154 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
1155 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ss_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
1156 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
1159 if (e_flags & MP2T_AF_E_LTW_FLAG_MASK) {
1160 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltwv_flag, tvb, offset, 2, ENC_BIG_ENDIAN);
1161 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltwo, tvb, offset, 2, ENC_BIG_ENDIAN);
1165 if (e_flags & MP2T_AF_E_PR_FLAG_MASK) {
1166 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr_reserved, tvb, offset, 3, ENC_BIG_ENDIAN);
1167 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr, tvb, offset, 3, ENC_BIG_ENDIAN);
1171 if (e_flags & MP2T_AF_E_SS_FLAG_MASK) {
1172 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_st, tvb, offset, 1, ENC_BIG_ENDIAN);
1173 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_32_30, tvb, offset, 1, ENC_BIG_ENDIAN);
1174 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_1, tvb, offset, 1, ENC_BIG_ENDIAN);
1176 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_29_15, tvb, offset, 2, ENC_BIG_ENDIAN);
1177 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_2, tvb, offset, 2, ENC_BIG_ENDIAN);
1179 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_14_0, tvb, offset, 2, ENC_BIG_ENDIAN);
1180 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_3, tvb, offset, 2, ENC_BIG_ENDIAN);
1184 reserved_len = (e_len + 1) - (offset - e_start_offset);
1185 if (reserved_len > 0) {
1186 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_reserved_bytes, tvb, offset, reserved_len, ENC_NA);
1187 offset += reserved_len;
1191 stuffing_len = (af_length + 1) - (offset - af_start_offset);
1192 if (stuffing_len > 0) {
1193 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_stuffing_bytes, tvb, offset, stuffing_len, ENC_NA);
1194 offset += stuffing_len;
1199 payload_len = MP2T_PACKET_SIZE - (offset - start_offset);
1204 col_set_str(pinfo->cinfo, COL_INFO, "Adaptation field only");
1205 /* The rest of the packet is stuffing bytes */
1206 proto_tree_add_item( mp2t_tree, hf_mp2t_stuff_bytes, tvb, offset, payload_len, ENC_NA);
1207 offset += payload_len;
1210 mp2t_process_fragmented_payload(tvb, offset, payload_len, pinfo, tree, mp2t_tree, pusi_flag, pid_analysis);
1217 dissect_mp2t( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
1220 conversation_t *conv;
1221 conv = find_or_create_conversation(pinfo);
1224 for (; tvb_reported_length_remaining(tvb, offset) >= MP2T_PACKET_SIZE; offset += MP2T_PACKET_SIZE) {
1226 dissect_tsp(tvb, offset, pinfo, tree, conv);
1232 heur_dissect_mp2t( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
1236 if (tvb_length_remaining(tvb, offset) % MP2T_PACKET_SIZE) {
1239 while (tvb_length_remaining(tvb, offset) > 0) {
1240 if (tvb_get_guint8(tvb, offset) != MP2T_SYNC_BYTE)
1242 offset += MP2T_PACKET_SIZE;
1246 dissect_mp2t(tvb, pinfo, tree);
1253 fragment_table_init(&mp2t_fragment_table);
1254 reassembled_table_init(&mp2t_reassembled_table);
1258 proto_register_mp2t(void)
1260 static hf_register_info hf[] = {
1261 { &hf_mp2t_header, {
1262 "Header", "mp2t.header",
1263 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL
1265 { &hf_mp2t_sync_byte, {
1266 "Sync Byte", "mp2t.sync_byte",
1267 FT_UINT32, BASE_HEX, VALS(mp2t_sync_byte_vals), MP2T_SYNC_BYTE_MASK, NULL, HFILL
1270 "Transport Error Indicator", "mp2t.tei",
1271 FT_UINT32, BASE_DEC, NULL, MP2T_TEI_MASK, NULL, HFILL
1274 "Payload Unit Start Indicator", "mp2t.pusi",
1275 FT_UINT32, BASE_DEC, NULL, MP2T_PUSI_MASK, NULL, HFILL
1278 "Transport Priority", "mp2t.tp",
1279 FT_UINT32, BASE_DEC, NULL, MP2T_TP_MASK, NULL, HFILL
1283 FT_UINT32, BASE_HEX, VALS(mp2t_pid_vals), MP2T_PID_MASK, NULL, HFILL
1286 "Transport Scrambling Control", "mp2t.tsc",
1287 FT_UINT32, BASE_HEX, VALS(mp2t_tsc_vals), MP2T_TSC_MASK, NULL, HFILL
1290 "Adaption Field Control", "mp2t.afc",
1291 FT_UINT32, BASE_HEX, VALS(mp2t_afc_vals) , MP2T_AFC_MASK, NULL, HFILL
1294 "Continuity Counter", "mp2t.cc",
1295 FT_UINT32, BASE_DEC, NULL, MP2T_CC_MASK, NULL, HFILL
1297 { &hf_mp2t_cc_drop, {
1298 "Continuity Counter Drops", "mp2t.cc.drop",
1299 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL
1301 { &hf_mp2t_analysis_flags, {
1302 "MPEG2-TS Analysis Flags", "mp2t.analysis.flags",
1303 FT_NONE, BASE_NONE, NULL, 0x0,
1304 "This frame has some of the MPEG2 analysis flags set", HFILL
1306 { &hf_mp2t_analysis_skips, {
1307 "TS Continuity Counter Skips", "mp2t.analysis.skips",
1308 FT_UINT8, BASE_DEC, NULL, 0x0,
1309 "Missing TS frames accoding to CC counter values", HFILL
1311 { &hf_mp2t_analysis_drops, {
1312 "Some frames dropped", "mp2t.analysis.drops",
1313 FT_UINT8, BASE_DEC, NULL, 0x0,
1314 "Discontinuity: A number of TS frames were dropped", HFILL
1317 "Adaption field", "mp2t.af",
1318 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
1320 { &hf_mp2t_af_length, {
1321 "Adaptation Field Length", "mp2t.af.length",
1322 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL
1325 "Discontinuity Indicator", "mp2t.af.di",
1326 FT_UINT8, BASE_DEC, NULL, MP2T_AF_DI_MASK, NULL, HFILL
1328 { &hf_mp2t_af_rai, {
1329 "Random Access Indicator", "mp2t.af.rai",
1330 FT_UINT8, BASE_DEC, NULL, MP2T_AF_RAI_MASK, NULL, HFILL
1332 { &hf_mp2t_af_espi, {
1333 "Elementary Stream Priority Indicator", "mp2t.af.espi",
1334 FT_UINT8, BASE_DEC, NULL, MP2T_AF_ESPI_MASK, NULL, HFILL
1336 { &hf_mp2t_af_pcr_flag, {
1337 "PCR Flag", "mp2t.af.pcr_flag",
1338 FT_UINT8, BASE_DEC, NULL, MP2T_AF_PCR_MASK, NULL, HFILL
1340 { &hf_mp2t_af_opcr_flag, {
1341 "OPCR Flag", "mp2t.af.opcr_flag",
1342 FT_UINT8, BASE_DEC, NULL, MP2T_AF_OPCR_MASK, NULL, HFILL
1344 { &hf_mp2t_af_sp_flag, {
1345 "Splicing Point Flag", "mp2t.af.sp_flag",
1346 FT_UINT8, BASE_DEC, NULL, MP2T_AF_SP_MASK, NULL, HFILL
1348 { &hf_mp2t_af_tpd_flag, {
1349 "Transport Private Data Flag", "mp2t.af.tpd_flag",
1350 FT_UINT8, BASE_DEC, NULL, MP2T_AF_TPD_MASK, NULL, HFILL
1352 { &hf_mp2t_af_afe_flag, {
1353 "Adaptation Field Extension Flag", "mp2t.af.afe_flag",
1354 FT_UINT8, BASE_DEC, NULL, MP2T_AF_AFE_MASK, NULL, HFILL
1356 { &hf_mp2t_af_pcr, {
1357 "Program Clock Reference", "mp2t.af.pcr",
1358 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
1360 { &hf_mp2t_af_opcr, {
1361 "Original Program Clock Reference", "mp2t.af.opcr",
1362 FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
1365 "Splice Countdown", "mp2t.af.sc",
1366 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
1368 { &hf_mp2t_af_tpd_length, {
1369 "Transport Private Data Length", "mp2t.af.tpd_length",
1370 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
1372 { &hf_mp2t_af_tpd, {
1373 "Transport Private Data", "mp2t.af.tpd",
1374 FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL
1376 { &hf_mp2t_af_e_length, {
1377 "Adaptation Field Extension Length", "mp2t.af.e_length",
1378 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
1380 { &hf_mp2t_af_e_ltw_flag, {
1381 "LTW Flag", "mp2t.af.e.ltw_flag",
1382 FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_LTW_FLAG_MASK, NULL, HFILL
1384 { &hf_mp2t_af_e_pr_flag, {
1385 "Piecewise Rate Flag", "mp2t.af.e.pr_flag",
1386 FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_PR_FLAG_MASK, NULL, HFILL
1388 { &hf_mp2t_af_e_ss_flag, {
1389 "Seamless Splice Flag", "mp2t.af.e.ss_flag",
1390 FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_SS_FLAG_MASK, NULL, HFILL
1392 { &hf_mp2t_af_e_reserved, {
1393 "Reserved", "mp2t.af.e.reserved",
1394 FT_UINT8, BASE_DEC, NULL, 0x1F, NULL, HFILL
1396 { &hf_mp2t_af_e_reserved_bytes, {
1397 "Reserved", "mp2t.af.e.reserved_bytes",
1398 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1400 { &hf_mp2t_af_stuffing_bytes, {
1401 "Stuffing", "mp2t.af.stuffing_bytes",
1402 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1404 { &hf_mp2t_af_e_ltwv_flag, {
1405 "LTW Valid Flag", "mp2t.af.e.ltwv_flag",
1406 FT_UINT16, BASE_DEC, NULL, 0x8000, NULL, HFILL
1408 { &hf_mp2t_af_e_ltwo, {
1409 "LTW Offset", "mp2t.af.e.ltwo",
1410 FT_UINT16, BASE_DEC, NULL, 0x7FFF, NULL, HFILL
1412 { &hf_mp2t_af_e_pr_reserved, {
1413 "Reserved", "mp2t.af.e.pr_reserved",
1414 FT_UINT24, BASE_DEC, NULL, 0xC00000, NULL, HFILL
1416 { &hf_mp2t_af_e_pr, {
1417 "Piecewise Rate", "mp2t.af.e.pr",
1418 FT_UINT24, BASE_DEC, NULL, 0x3FFFFF, NULL, HFILL
1420 { &hf_mp2t_af_e_st, {
1421 "Splice Type", "mp2t.af.e.st",
1422 FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL
1424 { &hf_mp2t_af_e_dnau_32_30, {
1425 "DTS Next AU[32...30]", "mp2t.af.e.dnau_32_30",
1426 FT_UINT8, BASE_DEC, NULL, 0x0E, NULL, HFILL
1428 { &hf_mp2t_af_e_m_1, {
1429 "Marker Bit", "mp2t.af.e.m_1",
1430 FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL
1432 { &hf_mp2t_af_e_dnau_29_15, {
1433 "DTS Next AU[29...15]", "mp2t.af.e.dnau_29_15",
1434 FT_UINT16, BASE_DEC, NULL, 0xFFFE, NULL, HFILL
1436 { &hf_mp2t_af_e_m_2, {
1437 "Marker Bit", "mp2t.af.e.m_2",
1438 FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL
1440 { &hf_mp2t_af_e_dnau_14_0, {
1441 "DTS Next AU[14...0]", "mp2t.af.e.dnau_14_0",
1442 FT_UINT16, BASE_DEC, NULL, 0xFFFE, NULL, HFILL
1444 { &hf_mp2t_af_e_m_3, {
1445 "Marker Bit", "mp2t.af.e.m_3",
1446 FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL
1448 { &hf_mp2t_payload, {
1449 "Payload", "mp2t.payload",
1450 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1452 { &hf_mp2t_stuff_bytes, {
1453 "Stuffing", "mp2t.stuff_bytes",
1454 FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL
1456 { &hf_msg_fragments, {
1457 "Message fragments", "mp2t.msg.fragments",
1458 FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL
1460 { &hf_msg_fragment, {
1461 "Message fragment", "mp2t.msg.fragment",
1462 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL
1464 { &hf_msg_fragment_overlap, {
1465 "Message fragment overlap", "mp2t.msg.fragment.overlap",
1466 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1468 { &hf_msg_fragment_overlap_conflicts, {
1469 "Message fragment overlapping with conflicting data",
1470 "mp2t.msg.fragment.overlap.conflicts",
1471 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1473 { &hf_msg_fragment_multiple_tails, {
1474 "Message has multiple tail fragments",
1475 "mp2t.msg.fragment.multiple_tails",
1476 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1478 { &hf_msg_fragment_too_long_fragment, {
1479 "Message fragment too long", "mp2t.msg.fragment.too_long_fragment",
1480 FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL
1482 { &hf_msg_fragment_error, {
1483 "Message defragmentation error", "mp2t.msg.fragment.error",
1484 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL
1486 { &hf_msg_fragment_count, {
1487 "Message fragment count", "mp2t.msg.fragment.count",
1488 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL
1490 { &hf_msg_reassembled_in, {
1491 "Reassembled in", "mp2t.msg.reassembled.in",
1492 FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL
1494 { &hf_msg_reassembled_length, {
1495 "Reassembled MP2T length", "mp2t.msg.reassembled.length",
1496 FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL
1500 static gint *ett[] =
1511 proto_mp2t = proto_register_protocol("ISO/IEC 13818-1", "MP2T", "mp2t");
1512 register_dissector("mp2t", dissect_mp2t, proto_mp2t);
1513 proto_register_field_array(proto_mp2t, hf, array_length(hf));
1514 proto_register_subtree_array(ett, array_length(ett));
1516 register_heur_dissector_list("mp2t.pid", &heur_subdissector_list);
1517 /* Register init of processing of fragmented DEPI packets */
1518 register_init_routine(mp2t_init);
1524 proto_reg_handoff_mp2t(void)
1526 dissector_handle_t mp2t_handle;
1528 heur_dissector_add("udp", heur_dissect_mp2t, proto_mp2t);
1530 mp2t_handle = create_dissector_handle(dissect_mp2t, proto_mp2t);
1531 dissector_add_uint("rtp.pt", PT_MP2T, mp2t_handle);
1532 dissector_add_handle("udp.port", mp2t_handle); /* for decode-as */
1533 heur_dissector_add("usb.bulk", heur_dissect_mp2t, proto_mp2t);
1534 dissector_add_uint("wtap_encap", WTAP_ENCAP_MPEG_2_TS, mp2t_handle);
1536 docsis_handle = find_dissector("docsis");
1537 mpeg_pes_handle = find_dissector("mpeg-pes");
1538 mpeg_sect_handle = find_dissector("mpeg_sect");
1539 data_handle = find_dissector("data");