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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
32 #include <epan/packet.h>
34 #include <epan/rtp_pt.h>
36 #include <epan/wmem/wmem.h>
37 #include <epan/conversation.h>
38 #include <epan/expert.h>
39 #include <epan/reassemble.h>
41 #include <epan/tvbuff-int.h> /* XXX, for tvb_new_proxy() */
43 /* The MPEG2 TS packet size */
44 #define MP2T_PACKET_SIZE 188
45 #define MP2T_SYNC_BYTE 0x47
47 #define MP2T_PID_DOCSIS 0x1FFE
48 #define MP2T_PID_NULL 0x1FFF
50 static dissector_handle_t mp2t_handle
;
52 static dissector_handle_t docsis_handle
;
53 static dissector_handle_t mpeg_pes_handle
;
54 static dissector_handle_t mpeg_sect_handle
;
55 static dissector_handle_t data_handle
;
57 static heur_dissector_list_t heur_subdissector_list
;
59 static int proto_mp2t
= -1;
60 static gint ett_mp2t
= -1;
61 static gint ett_mp2t_header
= -1;
62 static gint ett_mp2t_af
= -1;
63 static gint ett_mp2t_analysis
= -1;
64 static gint ett_stuff
= -1;
66 static int hf_mp2t_header
= -1;
67 static int hf_mp2t_sync_byte
= -1;
68 static int hf_mp2t_tei
= -1;
69 static int hf_mp2t_pusi
= -1;
70 static int hf_mp2t_tp
= -1;
71 static int hf_mp2t_pid
= -1;
72 static int hf_mp2t_tsc
= -1;
73 static int hf_mp2t_afc
= -1;
74 static int hf_mp2t_cc
= -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;
164 static int hf_mp2t_pointer
= -1;
167 static const value_string mp2t_sync_byte_vals
[] = {
168 { MP2T_SYNC_BYTE
, "Correct" },
172 static const value_string mp2t_pid_vals
[] = {
173 { 0x0000, "Program Association Table" },
174 { 0x0001, "Conditional Access Table" },
175 { 0x0002, "Transport Stream Description Table" },
176 { 0x0003, "Reserved" },
177 { 0x0004, "Reserved" },
178 { 0x0005, "Reserved" },
179 { 0x0006, "Reserved" },
180 { 0x0007, "Reserved" },
181 { 0x0008, "Reserved" },
182 { 0x0009, "Reserved" },
183 { 0x000A, "Reserved" },
184 { 0x000B, "Reserved" },
185 { 0x000C, "Reserved" },
186 { 0x000D, "Reserved" },
187 { 0x000E, "Reserved" },
188 { 0x000F, "Reserved" },
189 { 0x1FFE, "DOCSIS Data-over-cable well-known PID" },
190 { 0x1FFF, "Null packet" },
195 /* Values below according ETSI ETR 289 */
196 static const value_string mp2t_tsc_vals
[] = {
197 { 0, "Not scrambled" },
199 { 2, "Packet scrambled with Even Key" },
200 { 3, "Packet scrambled with Odd Key" },
204 static const value_string mp2t_afc_vals
[] = {
206 { 1, "Payload only" },
207 { 2, "Adaptation Field only" },
208 { 3, "Adaptation Field and Payload" },
212 static gint ett_msg_fragment
= -1;
213 static gint ett_msg_fragments
= -1;
214 static int hf_msg_fragments
= -1;
215 static int hf_msg_fragment
= -1;
216 static int hf_msg_fragment_overlap
= -1;
217 static int hf_msg_fragment_overlap_conflicts
= -1;
218 static int hf_msg_fragment_multiple_tails
= -1;
219 static int hf_msg_fragment_too_long_fragment
= -1;
220 static int hf_msg_fragment_error
= -1;
221 static int hf_msg_fragment_count
= -1;
222 static int hf_msg_reassembled_in
= -1;
223 static int hf_msg_reassembled_length
= -1;
225 static expert_field ei_mp2t_pointer
= EI_INIT
;
226 static expert_field ei_mp2t_cc_drop
= EI_INIT
;
228 static const fragment_items mp2t_msg_frag_items
= {
229 /* Fragment subtrees */
232 /* Fragment fields */
235 &hf_msg_fragment_overlap
,
236 &hf_msg_fragment_overlap_conflicts
,
237 &hf_msg_fragment_multiple_tails
,
238 &hf_msg_fragment_too_long_fragment
,
239 &hf_msg_fragment_error
,
240 &hf_msg_fragment_count
,
241 /* Reassembled in field */
242 &hf_msg_reassembled_in
,
243 /* Reassembled length field */
244 &hf_msg_reassembled_length
,
245 /* Reassembled data field */
252 /* Data structure used for detecting CC drops
256 * +-> mp2t_analysis_data
258 * +-> pid_table (RB tree) (key: pid)
260 * | +-> pid_analysis_data (per pid)
261 * | +-> pid_analysis_data
262 * | +-> pid_analysis_data
264 * +-> frame_table (RB tree) (key: pinfo->fd->num)
266 * +-> frame_analysis_data (only created if drop detected)
268 * +-> ts_table (RB tree)
270 * +-> ts_analysis_data (per TS subframe)
271 * +-> ts_analysis_data
272 * +-> ts_analysis_data
275 typedef struct mp2t_analysis_data
{
277 /* This structure contains a tree containing data for the
278 * individual pid's, this is only used when packets are
279 * processed sequencially.
281 wmem_tree_t
*pid_table
;
283 /* When detecting a CC drop, store that information for the
284 * given frame. This info is needed, when clicking around in
285 * wireshark, as the pid table data only makes sense during
286 * sequential processing. The flag pinfo->fd->flags.visited is
287 * used to tell the difference.
290 wmem_tree_t
*frame_table
;
292 /* Total counters per conversation / multicast stream */
294 guint32 total_discontinuity
;
296 } mp2t_analysis_data_t
;
298 enum pid_payload_type
{
306 typedef struct subpacket_analysis_data
{
307 guint32 frag_cur_pos
;
308 guint32 frag_tot_len
;
309 gboolean fragmentation
;
311 } subpacket_analysis_data_t
;
313 typedef struct packet_analysis_data
{
315 /* Contain information for each MPEG2-TS packet in the current big packet */
316 wmem_tree_t
*subpacket_table
;
317 } packet_analysis_data_t
;
319 /* Analysis TS frame info needed during sequential processing */
320 typedef struct pid_analysis_data
{
322 gint8 cc_prev
; /* Previous CC number */
323 enum pid_payload_type pload_type
;
325 /* Fragments information used for first pass */
326 gboolean fragmentation
;
327 guint32 frag_cur_pos
;
328 guint32 frag_tot_len
;
330 } pid_analysis_data_t
;
332 /* Analysis info stored for a TS frame */
333 typedef struct ts_analysis_data
{
335 gint8 cc_prev
; /* Previous CC number */
336 guint8 skips
; /* Skips between CCs max 14 */
337 } ts_analysis_data_t
;
340 typedef struct frame_analysis_data
{
342 /* As each frame has several pid's, thus need a pid data
343 * structure per TS frame.
345 wmem_tree_t
*ts_table
;
347 } frame_analysis_data_t
;
349 static mp2t_analysis_data_t
*
350 init_mp2t_conversation_data(void)
352 mp2t_analysis_data_t
*mp2t_data
= NULL
;
354 mp2t_data
= wmem_new0(wmem_file_scope(), struct mp2t_analysis_data
);
356 mp2t_data
->pid_table
= wmem_tree_new(wmem_file_scope());
358 mp2t_data
->frame_table
= wmem_tree_new(wmem_file_scope());
360 mp2t_data
->total_skips
= 0;
361 mp2t_data
->total_discontinuity
= 0;
366 static mp2t_analysis_data_t
*
367 get_mp2t_conversation_data(conversation_t
*conv
)
369 mp2t_analysis_data_t
*mp2t_data
= NULL
;
371 mp2t_data
= (mp2t_analysis_data_t
*)conversation_get_proto_data(conv
, proto_mp2t
);
373 mp2t_data
= init_mp2t_conversation_data();
374 conversation_add_proto_data(conv
, proto_mp2t
, mp2t_data
);
380 static frame_analysis_data_t
*
381 init_frame_analysis_data(mp2t_analysis_data_t
*mp2t_data
, packet_info
*pinfo
)
383 frame_analysis_data_t
*frame_analysis_data_p
= NULL
;
385 frame_analysis_data_p
= wmem_new0(wmem_file_scope(), struct frame_analysis_data
);
386 frame_analysis_data_p
->ts_table
= wmem_tree_new(wmem_file_scope());
387 /* Insert into mp2t tree */
388 wmem_tree_insert32(mp2t_data
->frame_table
, pinfo
->fd
->num
,
389 (void *)frame_analysis_data_p
);
391 return frame_analysis_data_p
;
395 static frame_analysis_data_t
*
396 get_frame_analysis_data(mp2t_analysis_data_t
*mp2t_data
, packet_info
*pinfo
)
398 frame_analysis_data_t
*frame_analysis_data_p
= NULL
;
399 frame_analysis_data_p
= (frame_analysis_data_t
*)wmem_tree_lookup32(mp2t_data
->frame_table
, pinfo
->fd
->num
);
400 return frame_analysis_data_p
;
403 static pid_analysis_data_t
*
404 get_pid_analysis(guint32 pid
, conversation_t
*conv
)
406 pid_analysis_data_t
*pid_data
= NULL
;
407 mp2t_analysis_data_t
*mp2t_data
= NULL
;
409 mp2t_data
= get_mp2t_conversation_data(conv
);
411 pid_data
= (pid_analysis_data_t
*)wmem_tree_lookup32(mp2t_data
->pid_table
, pid
);
413 pid_data
= wmem_new0(wmem_file_scope(), struct pid_analysis_data
);
414 pid_data
->cc_prev
= -1;
416 pid_data
->frag_id
= (pid
<< (32 - 13)) | 0x1;
418 wmem_tree_insert32(mp2t_data
->pid_table
, pid
, (void *)pid_data
);
423 /* Structure to handle packets, spanned across
424 * multiple MPEG packets
426 static reassembly_table mp2t_reassembly_table
;
429 mp2t_dissect_packet(tvbuff_t
*tvb
, enum pid_payload_type pload_type
,
430 packet_info
*pinfo
, proto_tree
*tree
)
432 dissector_handle_t handle
= NULL
;
434 switch (pload_type
) {
435 case pid_pload_docsis
:
436 handle
= docsis_handle
;
439 handle
= mpeg_pes_handle
;
442 handle
= mpeg_sect_handle
;
445 /* Should not happen */
450 call_dissector(handle
, tvb
, pinfo
, tree
);
452 call_dissector(data_handle
, tvb
, pinfo
, tree
);
456 mp2t_get_packet_length(tvbuff_t
*tvb
, guint offset
, packet_info
*pinfo
,
457 guint32 frag_id
, enum pid_payload_type pload_type
)
459 fragment_head
*frag
= NULL
;
460 tvbuff_t
*len_tvb
= NULL
, *frag_tvb
= NULL
, *data_tvb
= NULL
;
464 remaining_len
= tvb_length_remaining(tvb
, offset
);
465 frag
= fragment_get(&mp2t_reassembly_table
, pinfo
, frag_id
, NULL
);
469 if (!frag
) { /* First frame */
470 if ( (pload_type
== pid_pload_docsis
&& remaining_len
< 4) ||
471 (pload_type
== pid_pload_sect
&& remaining_len
< 3) ||
472 (pload_type
== pid_pload_pes
&& remaining_len
< 5) ) {
473 /* Not enough info to determine the size of the encapulated packet */
474 /* Just add the fragment and we'll check out the length later */
480 /* Create a composite tvb out of the two */
481 frag_tvb
= tvb_new_proxy(frag
->tvb_data
);
482 len_tvb
= tvb_new_composite();
483 tvb_composite_append(len_tvb
, frag_tvb
);
485 data_tvb
= tvb_new_subset_remaining(tvb
, offset
);
486 tvb_composite_append(len_tvb
, data_tvb
);
487 tvb_composite_finalize(len_tvb
);
489 offset
= frag
->offset
;
492 /* Get the next packet's size if possible */
493 switch (pload_type
) {
494 case pid_pload_docsis
:
495 pkt_len
= tvb_get_ntohs(len_tvb
, offset
+ 2) + 6;
498 pkt_len
= tvb_get_ntohs(len_tvb
, offset
+ 4);
499 if (pkt_len
) /* A size of 0 means size not bounded */
503 pkt_len
= (tvb_get_ntohs(len_tvb
, offset
+ 1) & 0xFFF) + 3;
506 /* Should not happen */
517 mp2t_fragment_handle(tvbuff_t
*tvb
, guint offset
, packet_info
*pinfo
,
518 proto_tree
*tree
, guint32 frag_id
,
519 guint frag_offset
, guint frag_len
,
520 gboolean fragment_last
, enum pid_payload_type pload_type
)
522 /* proto_item *ti; */
523 fragment_head
*frag_msg
= NULL
;
524 tvbuff_t
*new_tvb
= NULL
;
525 gboolean save_fragmented
;
527 save_fragmented
= pinfo
->fragmented
;
528 pinfo
->fragmented
= TRUE
;
530 /* check length; send frame for reassembly */
531 frag_msg
= fragment_add_check(&mp2t_reassembly_table
,
532 tvb
, offset
, pinfo
, frag_id
, NULL
,
537 new_tvb
= process_reassembled_data(tvb
, offset
, pinfo
,
539 frag_msg
, &mp2t_msg_frag_items
,
543 /* ti = */ proto_tree_add_text(tree
, tvb
, 0, 0, "MPEG TS Packet (reassembled)");
544 mp2t_dissect_packet(new_tvb
, pload_type
, pinfo
, tree
);
547 pinfo
->fragmented
= save_fragmented
;
551 /* Decoding of DOCSIS MAC frames within MPEG packets. MAC frames may begin anywhere
552 * within an MPEG packet or span multiple MPEG packets.
553 * payload_unit_start_indicator bit in MPEG header, and pointer field are used to
554 * decode fragmented DOCSIS frames within MPEG packet.
555 *-------------------------------------------------------------------------------
556 *MPEG Header | pointer_field | stuff_bytes | Start of MAC Frame #1 |
557 *(PUSI = 1) | (= 0) | (0 or more) |(up to 183 bytes) |
558 *-------------------------------------------------------------------------------
559 *-------------------------------------------------------------------------------
560 *MPEG Header | Continuation of MAC Frame #1 |
561 *(PUSI = 0) | (up to 183 bytes) |
562 *-------------------------------------------------------------------------------
563 *-------------------------------------------------------------------------------
564 *MPEG Header | pointer_field |Tail of MAC Frame| stuff_bytes |Start of MAC Frame|
565 *(PUSI = 1) | (= M) | #1 (M bytes) | (0 or more) |# 2 (N bytes) |
566 *-------------------------------------------------------------------------------
567 * Source - Data-Over-Cable Service Interface Specifications
568 * CM-SP-DRFI-I07-081209
571 mp2t_process_fragmented_payload(tvbuff_t
*tvb
, gint offset
, guint remaining_len
, packet_info
*pinfo
,
572 proto_tree
*tree
, proto_tree
*header_tree
, guint32 pusi_flag
,
573 pid_analysis_data_t
*pid_analysis
)
580 proto_tree
*stuff_tree
;
581 packet_analysis_data_t
*pdata
= NULL
;
582 subpacket_analysis_data_t
*spdata
= NULL
;
583 guint32 frag_cur_pos
= 0, frag_tot_len
= 0;
584 gboolean fragmentation
= FALSE
;
587 if (pusi_flag
&& pid_analysis
->pload_type
== pid_pload_unknown
588 && remaining_len
> 3) {
589 /* We should already have identified if it was a DOCSIS packet
590 * Remaining possibility is PES or SECT */
591 if (tvb_get_ntoh24(tvb
, offset
) == 0x000001) {
592 /* Looks like a PES packet to me ... */
593 pid_analysis
->pload_type
= pid_pload_pes
;
595 /* Most probably a SECT packet */
596 pid_analysis
->pload_type
= pid_pload_sect
;
600 /* Unable to determine the payload type, do nothing */
601 if (pid_analysis
->pload_type
== pid_pload_unknown
)
604 /* PES packet don't have pointer fields, others do */
605 if (pusi_flag
&& pid_analysis
->pload_type
!= pid_pload_pes
) {
606 pointer
= tvb_get_guint8(tvb
, offset
);
607 pi
= proto_tree_add_item(header_tree
, hf_mp2t_pointer
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
610 if (pointer
> remaining_len
) {
612 expert_add_info_format(pinfo
, pi
, &ei_mp2t_pointer
,
613 "Pointer value is too large (> remaining data length %u)",
618 if (!pinfo
->fd
->flags
.visited
) {
619 /* Get values from our current PID analysis */
620 frag_cur_pos
= pid_analysis
->frag_cur_pos
;
621 frag_tot_len
= pid_analysis
->frag_tot_len
;
622 fragmentation
= pid_analysis
->fragmentation
;
623 frag_id
= pid_analysis
->frag_id
;
624 pdata
= (packet_analysis_data_t
*)p_get_proto_data(pinfo
->fd
, proto_mp2t
, 0);
626 pdata
= wmem_new0(wmem_file_scope(), packet_analysis_data_t
);
627 pdata
->subpacket_table
= wmem_tree_new(wmem_file_scope());
628 p_add_proto_data(pinfo
->fd
, proto_mp2t
, 0, pdata
);
631 spdata
= (subpacket_analysis_data_t
*)wmem_tree_lookup32(pdata
->subpacket_table
, offset
);
635 spdata
= wmem_new0(wmem_file_scope(), subpacket_analysis_data_t
);
636 /* Save the info into pdata from pid_analysis */
637 spdata
->frag_cur_pos
= frag_cur_pos
;
638 spdata
->frag_tot_len
= frag_tot_len
;
639 spdata
->fragmentation
= fragmentation
;
640 spdata
->frag_id
= frag_id
;
641 wmem_tree_insert32(pdata
->subpacket_table
, offset
, (void *)spdata
);
644 /* Get saved values */
645 pdata
= (packet_analysis_data_t
*)p_get_proto_data(pinfo
->fd
, proto_mp2t
, 0);
647 /* Occurs for the first packets in the capture which cannot be reassembled */
651 spdata
= (subpacket_analysis_data_t
*)wmem_tree_lookup32(pdata
->subpacket_table
, offset
);
653 /* Occurs for the first sub packets in the capture which cannot be reassembled */
657 frag_cur_pos
= spdata
->frag_cur_pos
;
658 frag_tot_len
= spdata
->frag_tot_len
;
659 fragmentation
= spdata
->fragmentation
;
660 frag_id
= spdata
->frag_id
;
663 if (frag_tot_len
== (guint
)-1) {
664 frag_tot_len
= mp2t_get_packet_length(tvb
, offset
, pinfo
, frag_id
, pid_analysis
->pload_type
);
666 if (frag_tot_len
== (guint
)-1) {
672 /* The beginning of a new packet is present */
674 if (pointer
> remaining_len
) {
676 * Quit, so we don't use the bogus pointer value;
677 * that could cause remaining_len to become
678 * "negative", meaning it becomes a very large
684 /* "pointer" contains the number of bytes until the
685 * start of the new section
686 * if the new section does not start immediately after the
687 * pointer field (i.e. pointer>0), the remaining bytes before the
688 * start of the section are another fragment of the
690 if (pointer
>0 && fragmentation
) {
691 mp2t_fragment_handle(tvb
, offset
, pinfo
, tree
, frag_id
, frag_cur_pos
,
692 pointer
, TRUE
, pid_analysis
->pload_type
);
697 remaining_len
-= pointer
;
698 fragmentation
= FALSE
;
702 if (!remaining_len
) {
703 /* Shouldn't happen */
707 while (remaining_len
> 0) {
708 /* Skip stuff bytes */
710 while ((tvb_get_guint8(tvb
, offset
+ stuff_len
) == 0xFF)) {
712 if (stuff_len
>= remaining_len
) {
719 si
= proto_tree_add_text(tree
, tvb
, offset
, stuff_len
, "Stuffing");
720 stuff_tree
= proto_item_add_subtree(si
, ett_stuff
);
721 proto_tree_add_item(stuff_tree
, hf_mp2t_stuff_bytes
, tvb
, offset
, stuff_len
, ENC_NA
);
723 if (stuff_len
>= remaining_len
) {
726 remaining_len
-= stuff_len
;
729 /* Get the next packet's size if possible */
730 frag_tot_len
= mp2t_get_packet_length(tvb
, offset
, pinfo
, frag_id
, pid_analysis
->pload_type
);
731 if (frag_tot_len
== (guint
)-1 || !frag_tot_len
) {
732 mp2t_fragment_handle(tvb
, offset
, pinfo
, tree
, frag_id
, 0, remaining_len
, FALSE
, pid_analysis
->pload_type
);
733 fragmentation
= TRUE
;
734 /*offset += remaining_len;*/
735 frag_cur_pos
+= remaining_len
;
739 /* Check for full packets within this TS frame */
741 frag_tot_len
<= remaining_len
) {
742 next_tvb
= tvb_new_subset(tvb
, offset
, frag_tot_len
, frag_tot_len
);
743 mp2t_dissect_packet(next_tvb
, pid_analysis
->pload_type
, pinfo
, tree
);
744 remaining_len
-= frag_tot_len
;
745 offset
+= frag_tot_len
;
752 if (remaining_len
== 0) {
753 pid_analysis
->frag_cur_pos
= 0;
754 pid_analysis
->frag_tot_len
= 0;
761 /* There are remaining bytes. Add them to the fragment list */
763 if ((frag_tot_len
&& frag_cur_pos
+ remaining_len
>= frag_tot_len
) || (!frag_tot_len
&& pusi_flag
)) {
764 mp2t_fragment_handle(tvb
, offset
, pinfo
, tree
, frag_id
, frag_cur_pos
, remaining_len
, TRUE
, pid_analysis
->pload_type
);
766 fragmentation
= FALSE
;
770 mp2t_fragment_handle(tvb
, offset
, pinfo
, tree
, frag_id
, frag_cur_pos
, remaining_len
, FALSE
, pid_analysis
->pload_type
);
771 fragmentation
= TRUE
;
772 frag_cur_pos
+= remaining_len
;
776 pid_analysis
->fragmentation
= fragmentation
;
777 pid_analysis
->frag_cur_pos
= frag_cur_pos
;
778 pid_analysis
->frag_tot_len
= frag_tot_len
;
779 pid_analysis
->frag_id
= frag_id
;
784 /* Calc the number of skipped CC numbers. Note that this can easy
785 * overflow, and a value above 7 indicate several network packets
789 calc_skips(gint32 curr
, gint32 prev
)
793 /* Only count the missing TS frames in between prev and curr.
794 * The "prev" frame CC number seen is confirmed received, it's
795 * the next frames CC counter which is the first known missing
800 /* Calc missing TS frame 'skips' */
803 /* Handle wrap around */
810 #define KEY(pid, cc) ((pid << 4)|cc)
813 detect_cc_drops(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
,
814 guint32 pid
, gint32 cc_curr
, conversation_t
*conv
)
817 pid_analysis_data_t
*pid_data
= NULL
;
818 ts_analysis_data_t
*ts_data
= NULL
;
819 mp2t_analysis_data_t
*mp2t_data
= NULL
;
820 frame_analysis_data_t
*frame_analysis_data_p
= NULL
;
821 proto_item
*flags_item
;
823 guint32 detected_drop
= 0;
826 mp2t_data
= get_mp2t_conversation_data(conv
);
828 /* The initial sequencial processing stage */
829 if (!pinfo
->fd
->flags
.visited
) {
830 /* This is the sequencial processing stage */
831 pid_data
= get_pid_analysis(pid
, conv
);
833 cc_prev
= pid_data
->cc_prev
;
834 pid_data
->cc_prev
= cc_curr
;
836 /* Null packet always have a CC value equal 0 */
840 /* Its allowed that (cc_prev == cc_curr) if adaptation field */
841 if (cc_prev
== cc_curr
)
844 /* Have not seen this pid before */
848 /* Detect if CC is not increasing by one all the time */
849 if (cc_curr
!= ((cc_prev
+1) & MP2T_CC_MASK
)) {
852 skips
= calc_skips(cc_curr
, cc_prev
);
854 mp2t_data
->total_skips
+= skips
;
855 mp2t_data
->total_discontinuity
++;
856 /* TODO: if (skips > 7) signal_loss++; ??? */
860 /* Save the info about the dropped packet */
861 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
= wmem_new0(wmem_file_scope(), struct ts_analysis_data
);
871 ts_data
->cc_prev
= cc_prev
;
873 ts_data
->skips
= skips
;
874 wmem_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
= (struct ts_analysis_data
*)wmem_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
;
899 /* Add info to the proto tree about drops */
901 expert_add_info_format(pinfo
, tree
, &ei_mp2t_cc_drop
,
902 "Detected %d missing TS frames before this (last_cc:%d total skips:%d discontinuity:%d)",
904 mp2t_data
->total_skips
,
905 mp2t_data
->total_discontinuity
908 flags_item
= proto_tree_add_uint(tree
, hf_mp2t_analysis_skips
,
910 PROTO_ITEM_SET_GENERATED(flags_item
);
912 flags_item
= proto_tree_add_uint(tree
, hf_mp2t_analysis_drops
,
914 PROTO_ITEM_SET_GENERATED(flags_item
);
920 dissect_mp2t_adaptation_field(tvbuff_t
*tvb
, gint offset
, guint8 af_length
,
921 packet_info
*pinfo _U_
, proto_tree
*tree
)
923 gint af_start_offset
;
925 proto_tree
*mp2t_af_tree
;
930 af_start_offset
= offset
;
932 hi
= proto_tree_add_item( tree
, hf_mp2t_af
, tvb
, offset
, af_length
, ENC_NA
);
933 mp2t_af_tree
= proto_item_add_subtree( hi
, ett_mp2t_af
);
935 af_flags
= tvb_get_guint8(tvb
, offset
);
936 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_di
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
937 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_rai
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
938 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_espi
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
939 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_pcr_flag
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
940 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_opcr_flag
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
941 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_sp_flag
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
942 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_tpd_flag
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
943 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_afe_flag
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
946 if (af_flags
& MP2T_AF_PCR_MASK
) {
947 guint64 pcr_base
= 0;
951 tmp
= tvb_get_guint8(tvb
, offset
);
952 pcr_base
= (pcr_base
<< 8) | tmp
;
955 tmp
= tvb_get_guint8(tvb
, offset
);
956 pcr_base
= (pcr_base
<< 8) | tmp
;
959 tmp
= tvb_get_guint8(tvb
, offset
);
960 pcr_base
= (pcr_base
<< 8) | tmp
;
963 tmp
= tvb_get_guint8(tvb
, offset
);
964 pcr_base
= (pcr_base
<< 8) | tmp
;
967 tmp
= tvb_get_guint8(tvb
, offset
);
968 pcr_base
= (pcr_base
<< 1) | ((tmp
>> 7) & 0x01);
969 pcr_ext
= (tmp
& 0x01);
972 tmp
= tvb_get_guint8(tvb
, offset
);
973 pcr_ext
= (pcr_ext
<< 8) | tmp
;
976 proto_tree_add_none_format(mp2t_af_tree
, hf_mp2t_af_pcr
, tvb
, offset
- 6, 6,
977 "Program Clock Reference: base(%" G_GINT64_MODIFIER
"u) * 300 + ext(%u) = %" G_GINT64_MODIFIER
"u",
978 pcr_base
, pcr_ext
, pcr_base
* 300 + pcr_ext
);
981 if (af_flags
& MP2T_AF_OPCR_MASK
) {
982 guint64 opcr_base
= 0;
983 guint32 opcr_ext
= 0;
986 tmp
= tvb_get_guint8(tvb
, offset
);
987 opcr_base
= (opcr_base
<< 8) | tmp
;
990 tmp
= tvb_get_guint8(tvb
, offset
);
991 opcr_base
= (opcr_base
<< 8) | tmp
;
994 tmp
= tvb_get_guint8(tvb
, offset
);
995 opcr_base
= (opcr_base
<< 8) | tmp
;
998 tmp
= tvb_get_guint8(tvb
, offset
);
999 opcr_base
= (opcr_base
<< 8) | tmp
;
1002 tmp
= tvb_get_guint8(tvb
, offset
);
1003 opcr_base
= (opcr_base
<< 1) | ((tmp
>> 7) & 0x01);
1004 opcr_ext
= (tmp
& 0x01);
1007 tmp
= tvb_get_guint8(tvb
, offset
);
1008 opcr_ext
= (opcr_ext
<< 8) | tmp
;
1011 proto_tree_add_none_format(mp2t_af_tree
, hf_mp2t_af_opcr
, tvb
, offset
- 6, 6,
1012 "Original Program Clock Reference: base(%" G_GINT64_MODIFIER
"u) * 300 + ext(%u) = %" G_GINT64_MODIFIER
"u",
1013 opcr_base
, opcr_ext
, opcr_base
* 300 + opcr_ext
);
1018 if (af_flags
& MP2T_AF_SP_MASK
) {
1019 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_sc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1023 if (af_flags
& MP2T_AF_TPD_MASK
) {
1026 tpd_len
= tvb_get_guint8(tvb
, offset
);
1027 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_tpd_length
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1030 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_tpd
, tvb
, offset
, tpd_len
, ENC_NA
);
1034 if (af_flags
& MP2T_AF_AFE_MASK
) {
1037 gint e_start_offset
= offset
;
1038 gint reserved_len
= 0;
1040 e_len
= tvb_get_guint8(tvb
, offset
);
1041 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_length
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1044 e_flags
= tvb_get_guint8(tvb
, offset
);
1045 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_ltw_flag
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1046 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_pr_flag
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1047 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_ss_flag
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1048 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_reserved
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1051 if (e_flags
& MP2T_AF_E_LTW_FLAG_MASK
) {
1052 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_ltwv_flag
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1053 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_ltwo
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1057 if (e_flags
& MP2T_AF_E_PR_FLAG_MASK
) {
1058 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_pr_reserved
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
1059 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_pr
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
1063 if (e_flags
& MP2T_AF_E_SS_FLAG_MASK
) {
1064 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_st
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1065 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_dnau_32_30
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1066 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_m_1
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1068 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_dnau_29_15
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1069 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_m_2
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1071 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_dnau_14_0
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1072 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_m_3
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1076 reserved_len
= (e_len
+ 1) - (offset
- e_start_offset
);
1077 if (reserved_len
> 0) {
1078 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_e_reserved_bytes
, tvb
, offset
, reserved_len
, ENC_NA
);
1079 offset
+= reserved_len
;
1083 stuffing_len
= af_length
- (offset
- af_start_offset
);
1084 if (stuffing_len
> 0) {
1085 proto_tree_add_item( mp2t_af_tree
, hf_mp2t_af_stuffing_bytes
, tvb
, offset
, stuffing_len
, ENC_NA
);
1086 offset
+= stuffing_len
;
1089 return offset
-af_start_offset
;
1093 dissect_tsp(tvbuff_t
*tvb
, volatile gint offset
, packet_info
*pinfo
,
1094 proto_tree
*tree
, conversation_t
*conv
)
1099 gint start_offset
= offset
;
1100 volatile gint payload_len
;
1101 pid_analysis_data_t
*pid_analysis
;
1110 proto_item
*ti
= NULL
;
1111 proto_item
*hi
= NULL
;
1112 proto_item
*item
= NULL
;
1113 proto_tree
*mp2t_tree
= NULL
;
1114 proto_tree
*mp2t_header_tree
= NULL
;
1115 proto_tree
*mp2t_analysis_tree
= NULL
;
1116 proto_item
*afci
= NULL
;
1118 ti
= proto_tree_add_item( tree
, proto_mp2t
, tvb
, offset
, MP2T_PACKET_SIZE
, ENC_NA
);
1119 mp2t_tree
= proto_item_add_subtree( ti
, ett_mp2t
);
1121 header
= tvb_get_ntohl(tvb
, offset
);
1123 pid
= (header
& MP2T_PID_MASK
) >> MP2T_PID_SHIFT
;
1124 cc
= (header
& MP2T_CC_MASK
) >> MP2T_CC_SHIFT
;
1125 tsc
= (header
& MP2T_TSC_MASK
);
1126 pusi_flag
= (header
& 0x00400000);
1127 proto_item_append_text(ti
, " PID=0x%x CC=%d", pid
, cc
);
1128 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "MPEG TS");
1130 hi
= proto_tree_add_item( mp2t_tree
, hf_mp2t_header
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1131 mp2t_header_tree
= proto_item_add_subtree( hi
, ett_mp2t_header
);
1133 proto_tree_add_item( mp2t_header_tree
, hf_mp2t_sync_byte
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1134 proto_tree_add_item( mp2t_header_tree
, hf_mp2t_tei
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1135 proto_tree_add_item( mp2t_header_tree
, hf_mp2t_pusi
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1136 proto_tree_add_item( mp2t_header_tree
, hf_mp2t_tp
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1137 proto_tree_add_item( mp2t_header_tree
, hf_mp2t_pid
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1138 proto_tree_add_item( mp2t_header_tree
, hf_mp2t_tsc
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1139 afci
= proto_tree_add_item( mp2t_header_tree
, hf_mp2t_afc
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1140 proto_tree_add_item( mp2t_header_tree
, hf_mp2t_cc
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1142 afc
= (header
& MP2T_AFC_MASK
) >> MP2T_AFC_SHIFT
;
1144 pid_analysis
= get_pid_analysis(pid
, conv
);
1146 /* Find out the payload type based on the payload */
1147 if (pid_analysis
->pload_type
== pid_pload_unknown
) {
1148 if (pid
== MP2T_PID_NULL
) {
1149 pid_analysis
->pload_type
= pid_pload_null
;
1150 } else if (pid
== MP2T_PID_DOCSIS
) {
1151 pid_analysis
->pload_type
= pid_pload_docsis
;
1155 if (pid_analysis
->pload_type
== pid_pload_docsis
&& afc
) {
1156 /* DOCSIS packets should not have an adaptation field */
1157 proto_item_append_text(afci
, " (Invalid for DOCSIS packets, should be 0)");
1160 if (pid_analysis
->pload_type
== pid_pload_null
) {
1161 /* Nothing more to do */
1162 col_set_str(pinfo
->cinfo
, COL_INFO
, "NULL packet");
1163 proto_item_append_text(afci
, " (Should be 0 for NULL packets)");
1169 /* Create a subtree for analysis stuff */
1170 item
= proto_tree_add_text(mp2t_tree
, tvb
, offset
, 0, "MPEG2 PCR Analysis");
1171 PROTO_ITEM_SET_GENERATED(item
);
1172 mp2t_analysis_tree
= proto_item_add_subtree(item
, ett_mp2t_analysis
);
1174 skips
= detect_cc_drops(tvb
, mp2t_analysis_tree
, pinfo
, pid
, cc
, conv
);
1176 proto_item_append_text(ti
, " skips=%d", skips
);
1178 if (afc
== 2 || afc
== 3) {
1179 af_length
= tvb_get_guint8(tvb
, offset
);
1180 proto_tree_add_item( mp2t_tree
, hf_mp2t_af_length
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1182 /* fix issues where afc==3 but af_length==0
1183 * Adaptaion field...spec section 2.4.3.5: The value 0 is for inserting a single
1184 * stuffing byte in a Transport Stream packet. When the adaptation_field_control
1185 * value is '11', the value of the adaptation_field_length shall be in the range 0 to 182.
1188 offset
+= dissect_mp2t_adaptation_field(tvb
, offset
, af_length
, pinfo
, mp2t_tree
);
1191 if ((offset
- start_offset
) < MP2T_PACKET_SIZE
)
1192 payload_len
= MP2T_PACKET_SIZE
- (offset
- start_offset
);
1200 col_set_str(pinfo
->cinfo
, COL_INFO
, "Adaptation field only");
1201 /* The rest of the packet is stuffing bytes */
1202 proto_tree_add_item( mp2t_tree
, hf_mp2t_stuff_bytes
, tvb
, offset
, payload_len
, ENC_NA
);
1203 offset
+= payload_len
;
1207 mp2t_process_fragmented_payload(tvb
, offset
, payload_len
, pinfo
, tree
, mp2t_tree
, pusi_flag
, pid_analysis
);
1209 /* Payload is scrambled */
1210 col_set_str(pinfo
->cinfo
, COL_INFO
, "Scrambled TS payload");
1216 dissect_mp2t( tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
1219 conversation_t
*conv
;
1221 conv
= find_or_create_conversation(pinfo
);
1223 for (; tvb_reported_length_remaining(tvb
, offset
) >= MP2T_PACKET_SIZE
; offset
+= MP2T_PACKET_SIZE
) {
1224 dissect_tsp(tvb
, offset
, pinfo
, tree
, conv
);
1230 heur_dissect_mp2t( tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
1235 length
= tvb_length_remaining(tvb
, offset
);
1237 /* Nothing to check for */
1240 if ((length
% MP2T_PACKET_SIZE
) != 0) {
1241 /* Not a multiple of the MPEG-2 transport packet size */
1244 while (tvb_offset_exists(tvb
, offset
)) {
1245 if (tvb_get_guint8(tvb
, offset
) != MP2T_SYNC_BYTE
) {
1246 /* No sync byte at the appropriate offset */
1249 offset
+= MP2T_PACKET_SIZE
;
1253 dissect_mp2t(tvb
, pinfo
, tree
);
1260 reassembly_table_init(&mp2t_reassembly_table
,
1261 &addresses_reassembly_table_functions
);
1265 proto_register_mp2t(void)
1267 static hf_register_info hf
[] = {
1268 { &hf_mp2t_header
, {
1269 "Header", "mp2t.header",
1270 FT_UINT32
, BASE_HEX
, NULL
, 0, NULL
, HFILL
1272 { &hf_mp2t_sync_byte
, {
1273 "Sync Byte", "mp2t.sync_byte",
1274 FT_UINT32
, BASE_HEX
, VALS(mp2t_sync_byte_vals
), MP2T_SYNC_BYTE_MASK
, NULL
, HFILL
1277 "Transport Error Indicator", "mp2t.tei",
1278 FT_UINT32
, BASE_DEC
, NULL
, MP2T_TEI_MASK
, NULL
, HFILL
1281 "Payload Unit Start Indicator", "mp2t.pusi",
1282 FT_UINT32
, BASE_DEC
, NULL
, MP2T_PUSI_MASK
, NULL
, HFILL
1285 "Transport Priority", "mp2t.tp",
1286 FT_UINT32
, BASE_DEC
, NULL
, MP2T_TP_MASK
, NULL
, HFILL
1290 FT_UINT32
, BASE_HEX
, VALS(mp2t_pid_vals
), MP2T_PID_MASK
, NULL
, HFILL
1293 "Transport Scrambling Control", "mp2t.tsc",
1294 FT_UINT32
, BASE_HEX
, VALS(mp2t_tsc_vals
), MP2T_TSC_MASK
, NULL
, HFILL
1297 "Adaptation Field Control", "mp2t.afc",
1298 FT_UINT32
, BASE_HEX
, VALS(mp2t_afc_vals
) , MP2T_AFC_MASK
, NULL
, HFILL
1301 "Continuity Counter", "mp2t.cc",
1302 FT_UINT32
, BASE_DEC
, NULL
, MP2T_CC_MASK
, NULL
, HFILL
1305 { &hf_mp2t_analysis_flags
, {
1306 "MPEG2-TS Analysis Flags", "mp2t.analysis.flags",
1307 FT_NONE
, BASE_NONE
, NULL
, 0x0,
1308 "This frame has some of the MPEG2 analysis flags set", HFILL
1311 { &hf_mp2t_analysis_skips
, {
1312 "TS Continuity Counter Skips", "mp2t.analysis.skips",
1313 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1314 "Missing TS frames according to CC counter values", HFILL
1316 { &hf_mp2t_analysis_drops
, {
1317 "Some frames dropped", "mp2t.analysis.drops",
1318 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
1319 "Discontinuity: A number of TS frames were dropped", HFILL
1322 "Adaptation Field", "mp2t.af",
1323 FT_NONE
, BASE_NONE
, NULL
, 0, NULL
, HFILL
1325 { &hf_mp2t_af_length
, {
1326 "Adaptation Field Length", "mp2t.af.length",
1327 FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
1330 "Discontinuity Indicator", "mp2t.af.di",
1331 FT_UINT8
, BASE_DEC
, NULL
, MP2T_AF_DI_MASK
, NULL
, HFILL
1333 { &hf_mp2t_af_rai
, {
1334 "Random Access Indicator", "mp2t.af.rai",
1335 FT_UINT8
, BASE_DEC
, NULL
, MP2T_AF_RAI_MASK
, NULL
, HFILL
1337 { &hf_mp2t_af_espi
, {
1338 "Elementary Stream Priority Indicator", "mp2t.af.espi",
1339 FT_UINT8
, BASE_DEC
, NULL
, MP2T_AF_ESPI_MASK
, NULL
, HFILL
1341 { &hf_mp2t_af_pcr_flag
, {
1342 "PCR Flag", "mp2t.af.pcr_flag",
1343 FT_UINT8
, BASE_DEC
, NULL
, MP2T_AF_PCR_MASK
, NULL
, HFILL
1345 { &hf_mp2t_af_opcr_flag
, {
1346 "OPCR Flag", "mp2t.af.opcr_flag",
1347 FT_UINT8
, BASE_DEC
, NULL
, MP2T_AF_OPCR_MASK
, NULL
, HFILL
1349 { &hf_mp2t_af_sp_flag
, {
1350 "Splicing Point Flag", "mp2t.af.sp_flag",
1351 FT_UINT8
, BASE_DEC
, NULL
, MP2T_AF_SP_MASK
, NULL
, HFILL
1353 { &hf_mp2t_af_tpd_flag
, {
1354 "Transport Private Data Flag", "mp2t.af.tpd_flag",
1355 FT_UINT8
, BASE_DEC
, NULL
, MP2T_AF_TPD_MASK
, NULL
, HFILL
1357 { &hf_mp2t_af_afe_flag
, {
1358 "Adaptation Field Extension Flag", "mp2t.af.afe_flag",
1359 FT_UINT8
, BASE_DEC
, NULL
, MP2T_AF_AFE_MASK
, NULL
, HFILL
1361 { &hf_mp2t_af_pcr
, {
1362 "Program Clock Reference", "mp2t.af.pcr",
1363 FT_NONE
, BASE_NONE
, NULL
, 0, NULL
, HFILL
1365 { &hf_mp2t_af_opcr
, {
1366 "Original Program Clock Reference", "mp2t.af.opcr",
1367 FT_NONE
, BASE_NONE
, NULL
, 0, NULL
, HFILL
1370 "Splice Countdown", "mp2t.af.sc",
1371 FT_UINT8
, BASE_DEC
, NULL
, 0, NULL
, HFILL
1373 { &hf_mp2t_af_tpd_length
, {
1374 "Transport Private Data Length", "mp2t.af.tpd_length",
1375 FT_UINT8
, BASE_DEC
, NULL
, 0, NULL
, HFILL
1377 { &hf_mp2t_af_tpd
, {
1378 "Transport Private Data", "mp2t.af.tpd",
1379 FT_BYTES
, BASE_NONE
, NULL
, 0, NULL
, HFILL
1381 { &hf_mp2t_af_e_length
, {
1382 "Adaptation Field Extension Length", "mp2t.af.e_length",
1383 FT_UINT8
, BASE_DEC
, NULL
, 0, NULL
, HFILL
1385 { &hf_mp2t_af_e_ltw_flag
, {
1386 "LTW Flag", "mp2t.af.e.ltw_flag",
1387 FT_UINT8
, BASE_DEC
, NULL
, MP2T_AF_E_LTW_FLAG_MASK
, NULL
, HFILL
1389 { &hf_mp2t_af_e_pr_flag
, {
1390 "Piecewise Rate Flag", "mp2t.af.e.pr_flag",
1391 FT_UINT8
, BASE_DEC
, NULL
, MP2T_AF_E_PR_FLAG_MASK
, NULL
, HFILL
1393 { &hf_mp2t_af_e_ss_flag
, {
1394 "Seamless Splice Flag", "mp2t.af.e.ss_flag",
1395 FT_UINT8
, BASE_DEC
, NULL
, MP2T_AF_E_SS_FLAG_MASK
, NULL
, HFILL
1397 { &hf_mp2t_af_e_reserved
, {
1398 "Reserved", "mp2t.af.e.reserved",
1399 FT_UINT8
, BASE_DEC
, NULL
, 0x1F, NULL
, HFILL
1401 { &hf_mp2t_af_e_reserved_bytes
, {
1402 "Reserved", "mp2t.af.e.reserved_bytes",
1403 FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
1405 { &hf_mp2t_af_stuffing_bytes
, {
1406 "Stuffing", "mp2t.af.stuffing_bytes",
1407 FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
1409 { &hf_mp2t_af_e_ltwv_flag
, {
1410 "LTW Valid Flag", "mp2t.af.e.ltwv_flag",
1411 FT_UINT16
, BASE_DEC
, NULL
, 0x8000, NULL
, HFILL
1413 { &hf_mp2t_af_e_ltwo
, {
1414 "LTW Offset", "mp2t.af.e.ltwo",
1415 FT_UINT16
, BASE_DEC
, NULL
, 0x7FFF, NULL
, HFILL
1417 { &hf_mp2t_af_e_pr_reserved
, {
1418 "Reserved", "mp2t.af.e.pr_reserved",
1419 FT_UINT24
, BASE_DEC
, NULL
, 0xC00000, NULL
, HFILL
1421 { &hf_mp2t_af_e_pr
, {
1422 "Piecewise Rate", "mp2t.af.e.pr",
1423 FT_UINT24
, BASE_DEC
, NULL
, 0x3FFFFF, NULL
, HFILL
1425 { &hf_mp2t_af_e_st
, {
1426 "Splice Type", "mp2t.af.e.st",
1427 FT_UINT8
, BASE_DEC
, NULL
, 0xF0, NULL
, HFILL
1429 { &hf_mp2t_af_e_dnau_32_30
, {
1430 "DTS Next AU[32...30]", "mp2t.af.e.dnau_32_30",
1431 FT_UINT8
, BASE_DEC
, NULL
, 0x0E, NULL
, HFILL
1433 { &hf_mp2t_af_e_m_1
, {
1434 "Marker Bit", "mp2t.af.e.m_1",
1435 FT_UINT8
, BASE_DEC
, NULL
, 0x01, NULL
, HFILL
1437 { &hf_mp2t_af_e_dnau_29_15
, {
1438 "DTS Next AU[29...15]", "mp2t.af.e.dnau_29_15",
1439 FT_UINT16
, BASE_DEC
, NULL
, 0xFFFE, NULL
, HFILL
1441 { &hf_mp2t_af_e_m_2
, {
1442 "Marker Bit", "mp2t.af.e.m_2",
1443 FT_UINT16
, BASE_DEC
, NULL
, 0x0001, NULL
, HFILL
1445 { &hf_mp2t_af_e_dnau_14_0
, {
1446 "DTS Next AU[14...0]", "mp2t.af.e.dnau_14_0",
1447 FT_UINT16
, BASE_DEC
, NULL
, 0xFFFE, NULL
, HFILL
1449 { &hf_mp2t_af_e_m_3
, {
1450 "Marker Bit", "mp2t.af.e.m_3",
1451 FT_UINT16
, BASE_DEC
, NULL
, 0x0001, NULL
, HFILL
1454 { &hf_mp2t_payload
, {
1455 "Payload", "mp2t.payload",
1456 FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
1459 { &hf_mp2t_stuff_bytes
, {
1460 "Stuffing", "mp2t.stuff_bytes",
1461 FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
1463 { &hf_mp2t_pointer
, {
1464 "Pointer", "mp2t.pointer",
1465 FT_UINT8
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
1467 { &hf_msg_fragments
, {
1468 "Message fragments", "mp2t.msg.fragments",
1469 FT_NONE
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
1471 { &hf_msg_fragment
, {
1472 "Message fragment", "mp2t.msg.fragment",
1473 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
1475 { &hf_msg_fragment_overlap
, {
1476 "Message fragment overlap", "mp2t.msg.fragment.overlap",
1477 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
1479 { &hf_msg_fragment_overlap_conflicts
, {
1480 "Message fragment overlapping with conflicting data",
1481 "mp2t.msg.fragment.overlap.conflicts",
1482 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
1484 { &hf_msg_fragment_multiple_tails
, {
1485 "Message has multiple tail fragments",
1486 "mp2t.msg.fragment.multiple_tails",
1487 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
1489 { &hf_msg_fragment_too_long_fragment
, {
1490 "Message fragment too long", "mp2t.msg.fragment.too_long_fragment",
1491 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
1493 { &hf_msg_fragment_error
, {
1494 "Message defragmentation error", "mp2t.msg.fragment.error",
1495 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
1497 { &hf_msg_fragment_count
, {
1498 "Message fragment count", "mp2t.msg.fragment.count",
1499 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
1501 { &hf_msg_reassembled_in
, {
1502 "Reassembled in", "mp2t.msg.reassembled.in",
1503 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
1505 { &hf_msg_reassembled_length
, {
1506 "Reassembled MP2T length", "mp2t.msg.reassembled.length",
1507 FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
1511 static gint
*ett
[] =
1522 static ei_register_info ei
[] = {
1523 { &ei_mp2t_pointer
, { "mp2t.pointer", PI_MALFORMED
, PI_ERROR
, "Pointer value is too large", EXPFILL
}},
1524 { &ei_mp2t_cc_drop
, { "mp2t.cc.drop", PI_MALFORMED
, PI_ERROR
, "Detected missing TS frames", EXPFILL
}},
1527 expert_module_t
* expert_mp2t
;
1529 proto_mp2t
= proto_register_protocol("ISO/IEC 13818-1", "MP2T", "mp2t");
1531 mp2t_handle
= register_dissector("mp2t", dissect_mp2t
, proto_mp2t
);
1533 proto_register_field_array(proto_mp2t
, hf
, array_length(hf
));
1534 proto_register_subtree_array(ett
, array_length(ett
));
1535 expert_mp2t
= expert_register_protocol(proto_mp2t
);
1536 expert_register_field_array(expert_mp2t
, ei
, array_length(ei
));
1538 register_heur_dissector_list("mp2t.pid", &heur_subdissector_list
);
1539 /* Register init of processing of fragmented DEPI packets */
1540 register_init_routine(mp2t_init
);
1546 proto_reg_handoff_mp2t(void)
1548 heur_dissector_add("udp", heur_dissect_mp2t
, proto_mp2t
);
1550 dissector_add_uint("rtp.pt", PT_MP2T
, mp2t_handle
);
1551 dissector_add_handle("udp.port", mp2t_handle
); /* for decode-as */
1552 heur_dissector_add("usb.bulk", heur_dissect_mp2t
, proto_mp2t
);
1553 dissector_add_uint("wtap_encap", WTAP_ENCAP_MPEG_2_TS
, mp2t_handle
);
1555 docsis_handle
= find_dissector("docsis");
1556 mpeg_pes_handle
= find_dissector("mpeg-pes");
1557 mpeg_sect_handle
= find_dissector("mpeg_sect");
1558 data_handle
= find_dissector("data");
1562 * Editor modelines - http://www.wireshark.org/tools/modelines.html
1567 * indent-tabs-mode: nil
1570 * vi: set shiftwidth=4 tabstop=8 expandtab:
1571 * :indentSize=4:tabSize=8:noTabs=true: