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>
38 #include <epan/rtp_pt.h>
39 #include "packet-frame.h"
41 #include <epan/emem.h>
42 #include <epan/conversation.h>
43 #include <epan/expert.h>
45 /* The MPEG2 TS packet size */
46 #define MP2T_PACKET_SIZE 188
47 #define MP2T_SYNC_BYTE 0x47
49 static dissector_handle_t pes_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;
56 static int hf_mp2t_header = -1;
57 static int hf_mp2t_sync_byte = -1;
58 static int hf_mp2t_tei = -1;
59 static int hf_mp2t_pusi = -1;
60 static int hf_mp2t_tp = -1;
61 static int hf_mp2t_pid = -1;
62 static int hf_mp2t_tsc = -1;
63 static int hf_mp2t_afc = -1;
64 static int hf_mp2t_cc = -1;
65 static int hf_mp2t_cc_drop = -1;
67 #define MP2T_SYNC_BYTE_MASK 0xFF000000
68 #define MP2T_TEI_MASK 0x00800000
69 #define MP2T_PUSI_MASK 0x00400000
70 #define MP2T_TP_MASK 0x00200000
71 #define MP2T_PID_MASK 0x001FFF00
72 #define MP2T_TSC_MASK 0x000000C0
73 #define MP2T_AFC_MASK 0x00000030
74 #define MP2T_CC_MASK 0x0000000F
76 #define MP2T_SYNC_BYTE_SHIFT 24
77 #define MP2T_TEI_SHIFT 23
78 #define MP2T_PUSI_SHIFT 22
79 #define MP2T_TP_SHIFT 21
80 #define MP2T_PID_SHIFT 8
81 #define MP2T_TSC_SHIFT 6
82 #define MP2T_AFC_SHIFT 4
83 #define MP2T_CC_SHIFT 0
85 static int hf_mp2t_af = -1;
86 static int hf_mp2t_af_length = -1;
87 static int hf_mp2t_af_di = -1;
88 static int hf_mp2t_af_rai = -1;
89 static int hf_mp2t_af_espi = -1;
90 static int hf_mp2t_af_pcr_flag = -1;
91 static int hf_mp2t_af_opcr_flag = -1;
92 static int hf_mp2t_af_sp_flag = -1;
93 static int hf_mp2t_af_tpd_flag = -1;
94 static int hf_mp2t_af_afe_flag = -1;
96 #define MP2T_AF_DI_MASK 0x80
97 #define MP2T_AF_RAI_MASK 0x40
98 #define MP2T_AF_ESPI_MASK 0x20
99 #define MP2T_AF_PCR_MASK 0x10
100 #define MP2T_AF_OPCR_MASK 0x08
101 #define MP2T_AF_SP_MASK 0x04
102 #define MP2T_AF_TPD_MASK 0x02
103 #define MP2T_AF_AFE_MASK 0x01
105 #define MP2T_AF_DI_SHIFT 7
106 #define MP2T_AF_RAI_SHIFT 6
107 #define MP2T_AF_ESPI_SHIFT 5
108 #define MP2T_AF_PCR_SHIFT 4
109 #define MP2T_AF_OPCR_SHIFT 3
110 #define MP2T_AF_SP_SHIFT 2
111 #define MP2T_AF_TPD_SHIFT 1
112 #define MP2T_AF_AFE_SHIFT 0
114 static int hf_mp2t_af_pcr = -1;
115 static int hf_mp2t_af_opcr = -1;
117 static int hf_mp2t_af_sc = -1;
119 static int hf_mp2t_af_tpd_length = -1;
120 static int hf_mp2t_af_tpd = -1;
122 static int hf_mp2t_af_e_length = -1;
123 static int hf_mp2t_af_e_ltw_flag = -1;
124 static int hf_mp2t_af_e_pr_flag = -1;
125 static int hf_mp2t_af_e_ss_flag = -1;
126 static int hf_mp2t_af_e_reserved = -1;
128 #define MP2T_AF_E_LTW_FLAG_MASK 0x80
129 #define MP2T_AF_E_PR_FLAG_MASK 0x40
130 #define MP2T_AF_E_SS_FLAG_MASK 0x20
132 static int hf_mp2t_af_e_reserved_bytes = -1;
133 static int hf_mp2t_af_stuffing_bytes = -1;
135 static int hf_mp2t_af_e_ltwv_flag = -1;
136 static int hf_mp2t_af_e_ltwo = -1;
138 static int hf_mp2t_af_e_pr_reserved = -1;
139 static int hf_mp2t_af_e_pr = -1;
141 static int hf_mp2t_af_e_st = -1;
142 static int hf_mp2t_af_e_dnau_32_30 = -1;
143 static int hf_mp2t_af_e_m_1 = -1;
144 static int hf_mp2t_af_e_dnau_29_15 = -1;
145 static int hf_mp2t_af_e_m_2 = -1;
146 static int hf_mp2t_af_e_dnau_14_0 = -1;
147 static int hf_mp2t_af_e_m_3 = -1;
149 static int hf_mp2t_payload = -1;
150 static int hf_mp2t_malformed_payload = -1;
152 static const value_string mp2t_sync_byte_vals[] = {
153 { MP2T_SYNC_BYTE, "Correct" },
158 static const value_string mp2t_pid_vals[] = {
159 { 0x0000, "Program Association Table" },
160 { 0x0001, "Conditional Access Table" },
161 { 0x0002, "Transport Stream Description Table" },
162 { 0x0003, "Reserved" },
163 { 0x0004, "Reserved" },
164 { 0x0005, "Reserved" },
165 { 0x0006, "Reserved" },
166 { 0x0007, "Reserved" },
167 { 0x0008, "Reserved" },
168 { 0x0009, "Reserved" },
169 { 0x000A, "Reserved" },
170 { 0x000B, "Reserved" },
171 { 0x000C, "Reserved" },
172 { 0x000D, "Reserved" },
173 { 0x000E, "Reserved" },
174 { 0x000F, "Reserved" },
175 { 0x1FFF, "Null packet" },
179 static const value_string mp2t_tsc_vals[] = {
180 { 0, "Not scrambled" },
181 { 1, "User-defined" },
182 { 2, "User-defined" },
183 { 3, "User-defined" },
187 static const value_string mp2t_afc_vals[] = {
189 { 1, "Payload only" },
190 { 2, "Adaptation Field only" },
191 { 3, "Adaptation Field and Payload" },
195 /* Data structure used for detecting CC drops
199 * +-> mp2t_analysis_data
201 * +-> pid_table (RB tree)
203 * | +-> pid_analysis_data (per pid)
204 * | +-> pid_analysis_data
205 * | +-> pid_analysis_data
207 * +-> frame_table (RB tree)
209 * +-> frame_analysis_data (only created if drop detected)
211 * +-> ts_table (RB tree)
213 * +-> pid_analysis_data (per TS subframe)
214 * +-> pid_analysis_data
215 * +-> pid_analysis_data
218 typedef struct mp2t_analysis_data {
220 /* This structure contains a tree containing data for the
221 * individual pid's, this is only used when packets are
222 * processed sequencially.
224 emem_tree_t *pid_table;
226 /* When detecting a CC drop, store that information for the
227 * given frame. This info is needed, when clicking around in
228 * wireshark, as the pid table data only makes sence during
229 * sequencial processing. The flag pinfo->fd->flags.visited is
230 * used to tell the difference.
233 emem_tree_t *frame_table;
235 guint32 cc_drops; /* Number of detected CC losses per conv */
237 } mp2t_analysis_data_t;
239 typedef struct pid_analysis_data {
241 gint16 cc_prev; /* Previous CC number */
242 } pid_analysis_data_t;
244 typedef struct frame_analysis_data {
246 /* As each frame has several pid's, thus need a pid data
247 * structure per TS frame.
249 emem_tree_t *ts_table;
251 } frame_analysis_data_t;
254 get_the_conversation(packet_info *pinfo)
256 conversation_t *conv = NULL;
258 conv = find_conversation(pinfo->fd->num, &pinfo->src,
259 &pinfo->dst, pinfo->ptype,
260 pinfo->srcport, pinfo->destport, 0);
262 if (conv == NULL) { /* Create a new conversation */
263 conv = conversation_new(pinfo->fd->num, &pinfo->src,
264 &pinfo->dst, pinfo->ptype,
265 pinfo->srcport, pinfo->destport, 0);
270 mp2t_analysis_data_t *
271 init_mp2t_conversation_data()
273 mp2t_analysis_data_t *mp2t_data = NULL;
275 mp2t_data = se_alloc0(sizeof(struct mp2t_analysis_data));
277 mp2t_data->pid_table =
278 se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,
280 mp2t_data->frame_table =
281 se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,
283 mp2t_data->cc_drops = 0;
288 mp2t_analysis_data_t *
289 get_mp2t_conversation_data(conversation_t *conv)
291 mp2t_analysis_data_t *mp2t_data = NULL;
293 mp2t_data = conversation_get_proto_data(conv, proto_mp2t);
295 mp2t_data = init_mp2t_conversation_data();
296 conversation_add_proto_data(conv, proto_mp2t, mp2t_data);
302 frame_analysis_data_t *
303 init_frame_analysis_data(mp2t_analysis_data_t *mp2t_data, packet_info *pinfo)
305 frame_analysis_data_t *frame_data = NULL;
307 frame_data = se_alloc0(sizeof(struct frame_analysis_data));
308 frame_data->ts_table =
309 se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK,
310 "mp2t_frame_pid_table");
311 /* Insert into mp2t tree */
312 se_tree_insert32(mp2t_data->frame_table, pinfo->fd->num,
319 frame_analysis_data_t *
320 get_frame_analysis_data(mp2t_analysis_data_t *mp2t_data, packet_info *pinfo)
322 frame_analysis_data_t *frame_data = NULL;
323 frame_data = se_tree_lookup32(mp2t_data->frame_table, pinfo->fd->num);
327 pid_analysis_data_t *
328 get_pid_analysis(guint32 pid, conversation_t *conv)
331 pid_analysis_data_t *pid_data = NULL;
332 mp2t_analysis_data_t *mp2t_data = NULL;
333 mp2t_data = get_mp2t_conversation_data(conv);
335 pid_data = se_tree_lookup32(mp2t_data->pid_table, pid);
337 pid_data = se_alloc0(sizeof(struct pid_analysis_data));
338 pid_data->cc_prev = -1;
341 se_tree_insert32(mp2t_data->pid_table, pid, (void *)pid_data);
346 #define KEY(pid, cc) ((pid << 4)|cc)
349 detect_cc_drops(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
350 guint32 pid, gint32 cc_curr, conversation_t *conv)
353 pid_analysis_data_t *pid_data = NULL;
354 pid_analysis_data_t *ts_data = NULL;
355 mp2t_analysis_data_t *mp2t_data = NULL;
356 frame_analysis_data_t *frame_data = NULL;
357 proto_item *flags_item;
359 guint32 detected_drop = 0;
361 mp2t_data = get_mp2t_conversation_data(conv);
363 /* The initial sequencial processing stage */
364 if (!pinfo->fd->flags.visited) {
366 /* This is the sequencial processing stage */
367 pid_data = get_pid_analysis(pid, conv);
369 cc_prev = pid_data->cc_prev;
370 pid_data->cc_prev = cc_curr;
372 /* Null packet always have a CC value equal 0 */
376 /* Its allowed that (cc_prev == cc_curr) if adaptation field */
377 if (cc_prev == cc_curr)
380 /* Have not seen this pid before */
384 /* Detect if CC is not increasing by one all the time */
385 if (cc_curr != ((cc_prev+1) & MP2T_CC_MASK)) {
387 mp2t_data->cc_drops++;
391 /* Save the info about the dropped packet */
392 if (detected_drop && !pinfo->fd->flags.visited) {
394 /* Lookup frame data, contains TS pid data objects */
395 frame_data = get_frame_analysis_data(mp2t_data, pinfo);
397 frame_data = init_frame_analysis_data(mp2t_data, pinfo);
399 /* Create and store a new TS frame pid_data object.
400 This indicate that we have a drop
402 ts_data = se_alloc0(sizeof(struct pid_analysis_data));
403 ts_data->cc_prev = cc_prev;
405 se_tree_insert32(frame_data->ts_table, KEY(pid, cc_curr),
409 /* See if we stored info about drops */
410 if (pinfo->fd->flags.visited) {
412 /* Lookup frame data, contains TS pid data objects */
413 frame_data = get_frame_analysis_data(mp2t_data, pinfo);
415 return; /* No stored frame data -> no drops*/
417 ts_data = se_tree_lookup32(frame_data->ts_table,
425 /* Add info to the proto tree about drops */
429 proto_tree_add_none_format(
430 tree, hf_mp2t_cc_drop, tvb, 0, 0,
431 "Detected missing CC frame before this"
432 " (accumulated CC loss count:%d)",
436 PROTO_ITEM_SET_GENERATED(flags_item);
437 expert_add_info_format(pinfo, flags_item, PI_MALFORMED,
438 PI_ERROR, "Detected CC loss");
445 dissect_tsp(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree,
446 conversation_t *conv)
450 gint start_offset = offset;
456 proto_item *ti = NULL;
457 proto_item *hi = NULL;
458 proto_tree *mp2t_tree = NULL;
459 proto_tree *mp2t_header_tree = NULL;
460 proto_tree *mp2t_af_tree = NULL;
462 ti = proto_tree_add_item( tree, proto_mp2t, tvb, offset, MP2T_PACKET_SIZE, FALSE );
463 mp2t_tree = proto_item_add_subtree( ti, ett_mp2t );
465 header = tvb_get_ntohl(tvb, offset);
467 pid = (header & MP2T_PID_MASK) >> MP2T_PID_SHIFT;
468 cc = (header & MP2T_CC_MASK) >> MP2T_CC_SHIFT;
469 proto_item_append_text(ti, " PID=0x%x CC=%d", pid, cc);
471 detect_cc_drops(tvb, tree, pinfo, pid, cc, conv);
473 hi = proto_tree_add_item( mp2t_tree, hf_mp2t_header, tvb, offset, 4, FALSE);
474 mp2t_header_tree = proto_item_add_subtree( hi, ett_mp2t_header );
476 proto_tree_add_item( mp2t_header_tree, hf_mp2t_sync_byte, tvb, offset, 4, FALSE);
477 proto_tree_add_item( mp2t_header_tree, hf_mp2t_tei, tvb, offset, 4, FALSE);
478 proto_tree_add_item( mp2t_header_tree, hf_mp2t_pusi, tvb, offset, 4, FALSE);
479 proto_tree_add_item( mp2t_header_tree, hf_mp2t_tp, tvb, offset, 4, FALSE);
480 proto_tree_add_item( mp2t_header_tree, hf_mp2t_pid, tvb, offset, 4, FALSE);
481 proto_tree_add_item( mp2t_header_tree, hf_mp2t_tsc, tvb, offset, 4, FALSE);
482 proto_tree_add_item( mp2t_header_tree, hf_mp2t_afc, tvb, offset, 4, FALSE);
483 proto_tree_add_item( mp2t_header_tree, hf_mp2t_cc, tvb, offset, 4, FALSE);
486 afc = (header & MP2T_AFC_MASK) >> MP2T_AFC_SHIFT;
488 if (afc == 2 || afc == 3)
490 gint af_start_offset = offset;
497 af_length = tvb_get_guint8(tvb, offset);
499 proto_tree_add_item( mp2t_tree, hf_mp2t_af_length, tvb, offset, 1, FALSE);
501 /* fix issues where afc==3 but af_length==0
502 * Adaptaion field...spec section 2.4.3.5: The value 0 is for inserting a single
503 * stuffing byte in a Transport Stream packet. When the adaptation_field_control
504 * value is '11', the value of the adaptation_field_length shall be in the range 0 to 182.
506 if (af_length > 0 ) {
507 hi = proto_tree_add_item( mp2t_tree, hf_mp2t_af, tvb, offset, af_length, FALSE);
508 mp2t_af_tree = proto_item_add_subtree( hi, ett_mp2t_af );
510 af_flags = tvb_get_guint8(tvb, offset);
512 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_di, tvb, offset, 1, FALSE);
513 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_rai, tvb, offset, 1, FALSE);
514 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_espi, tvb, offset, 1, FALSE);
515 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_pcr_flag, tvb, offset, 1, FALSE);
516 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_opcr_flag, tvb, offset, 1, FALSE);
517 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_sp_flag, tvb, offset, 1, FALSE);
518 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd_flag, tvb, offset, 1, FALSE);
519 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_afe_flag, tvb, offset, 1, FALSE);
523 if (af_flags & MP2T_AF_PCR_MASK) {
524 guint64 pcr_base = 0;
528 tmp = tvb_get_guint8(tvb, offset);
529 pcr_base = (pcr_base << 8) | tmp;
532 tmp = tvb_get_guint8(tvb, offset);
533 pcr_base = (pcr_base << 8) | tmp;
536 tmp = tvb_get_guint8(tvb, offset);
537 pcr_base = (pcr_base << 8) | tmp;
540 tmp = tvb_get_guint8(tvb, offset);
541 pcr_base = (pcr_base << 8) | tmp;
544 tmp = tvb_get_guint8(tvb, offset);
545 pcr_base = (pcr_base << 1) | ((tmp >> 7) & 0x01);
546 pcr_ext = (tmp & 0x01);
549 tmp = tvb_get_guint8(tvb, offset);
550 pcr_ext = (pcr_ext << 8) | tmp;
553 proto_tree_add_none_format(mp2t_af_tree, hf_mp2t_af_pcr, tvb, offset - 6, 6,
554 "Program Clock Reference: base(%" G_GINT64_MODIFIER "u) * 300 + ext(%u) = %" G_GINT64_MODIFIER "u",
555 pcr_base, pcr_ext, pcr_base * 300 + pcr_ext);
558 if (af_flags & MP2T_AF_OPCR_MASK) {
559 guint64 opcr_base = 0;
560 guint32 opcr_ext = 0;
563 tmp = tvb_get_guint8(tvb, offset);
564 opcr_base = (opcr_base << 8) | tmp;
567 tmp = tvb_get_guint8(tvb, offset);
568 opcr_base = (opcr_base << 8) | tmp;
571 tmp = tvb_get_guint8(tvb, offset);
572 opcr_base = (opcr_base << 8) | tmp;
575 tmp = tvb_get_guint8(tvb, offset);
576 opcr_base = (opcr_base << 8) | tmp;
579 tmp = tvb_get_guint8(tvb, offset);
580 opcr_base = (opcr_base << 1) | ((tmp >> 7) & 0x01);
581 opcr_ext = (tmp & 0x01);
584 tmp = tvb_get_guint8(tvb, offset);
585 opcr_ext = (opcr_ext << 8) | tmp;
588 proto_tree_add_none_format(mp2t_af_tree, hf_mp2t_af_opcr, tvb, offset - 6, 6,
589 "Original Program Clock Reference: base(%" G_GINT64_MODIFIER "u) * 300 + ext(%u) = %" G_GINT64_MODIFIER "u",
590 opcr_base, opcr_ext, opcr_base * 300 + opcr_ext);
595 if (af_flags & MP2T_AF_SP_MASK) {
596 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_sc, tvb, offset, 1, FALSE);
600 if (af_flags & MP2T_AF_TPD_MASK) {
603 tpd_len = tvb_get_guint8(tvb, offset);
604 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd_length, tvb, offset, 1, FALSE);
607 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_tpd, tvb, offset, tpd_len, FALSE);
611 if (af_flags & MP2T_AF_AFE_MASK) {
614 gint e_start_offset = offset;
615 gint reserved_len = 0;
617 e_len = tvb_get_guint8(tvb, offset);
618 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_length, tvb, offset, 1, FALSE);
621 e_flags = tvb_get_guint8(tvb, offset);
622 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltw_flag, tvb, offset, 1, FALSE);
623 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr_flag, tvb, offset, 1, FALSE);
624 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ss_flag, tvb, offset, 1, FALSE);
625 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_reserved, tvb, offset, 1, FALSE);
628 if (e_flags & MP2T_AF_E_LTW_FLAG_MASK) {
629 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltwv_flag, tvb, offset, 2, FALSE);
630 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_ltwo, tvb, offset, 2, FALSE);
634 if (e_flags & MP2T_AF_E_PR_FLAG_MASK) {
635 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr_reserved, tvb, offset, 3, FALSE);
636 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_pr, tvb, offset, 3, FALSE);
640 if (e_flags & MP2T_AF_E_SS_FLAG_MASK) {
641 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_st, tvb, offset, 1, FALSE);
642 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_32_30, tvb, offset, 1, FALSE);
643 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_1, tvb, offset, 1, FALSE);
645 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_29_15, tvb, offset, 2, FALSE);
646 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_2, tvb, offset, 2, FALSE);
648 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_dnau_14_0, tvb, offset, 2, FALSE);
649 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_m_3, tvb, offset, 2, FALSE);
653 reserved_len = (e_len + 1) - (offset - e_start_offset);
654 if (reserved_len > 0) {
655 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_e_reserved_bytes, tvb, offset, reserved_len, FALSE);
656 offset += reserved_len;
660 stuffing_len = (af_length + 1) - (offset - af_start_offset);
661 if (stuffing_len > 0) {
662 proto_tree_add_item( mp2t_af_tree, hf_mp2t_af_stuffing_bytes, tvb, offset, stuffing_len, FALSE);
663 offset += stuffing_len;
668 payload_len = MP2T_PACKET_SIZE - (offset - start_offset);
669 if (payload_len > 0) {
670 if (afc == 2) { /* AF only */
671 /* Packet is malformed */
672 proto_tree_add_item( mp2t_tree, hf_mp2t_malformed_payload, tvb, offset, payload_len, FALSE);
673 offset += payload_len;
675 /* Check to make sure if we are not at end of payload, if we have less than 3 bytes, the tvb_get_ntoh24 fails. */
676 if (payload_len >=3 ) {
677 if (tvb_get_ntoh24(tvb, offset) == 0x000001) {
678 tvbuff_t *next_tvb = tvb_new_subset(tvb, offset, payload_len, payload_len);
679 const char *saved_proto = pinfo->current_proto;
682 call_dissector(pes_handle, next_tvb, pinfo, mp2t_tree);
686 Don't stop processing TS packets if somebody threw
687 BoundsError, which means that dissecting the payload found
688 that the packet was cut off by before the end of the
689 payload. This is very likely as this protocol splits the
690 media stream up into chunks of MP2T_PACKET_SIZE.
692 CATCH2(BoundsError, ReportedBoundsError) {
693 show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
694 pinfo->current_proto = saved_proto;
699 proto_tree_add_item( mp2t_tree, hf_mp2t_payload, tvb, offset, payload_len, FALSE);
702 proto_tree_add_item( mp2t_tree, hf_mp2t_payload, tvb, offset, payload_len, FALSE);
704 offset += payload_len;
713 dissect_mp2t( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
716 conversation_t *conv;
717 conv = get_the_conversation(pinfo);
719 while ( tvb_reported_length_remaining(tvb, offset) >= MP2T_PACKET_SIZE ) {
720 offset = dissect_tsp(tvb, offset, pinfo, tree, conv);
725 heur_dissect_mp2t( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
729 if (tvb_length_remaining(tvb, offset) % MP2T_PACKET_SIZE) {
732 while (tvb_length_remaining(tvb, offset)) {
733 if (tvb_get_guint8(tvb, offset) != MP2T_SYNC_BYTE)
735 offset += MP2T_PACKET_SIZE;
739 dissect_mp2t(tvb, pinfo, tree);
744 proto_register_mp2t(void)
746 static hf_register_info hf[] = {
748 "Header", "mp2t.header",
749 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL
751 { &hf_mp2t_sync_byte, {
752 "Sync Byte", "mp2t.sync_byte",
753 FT_UINT32, BASE_HEX, VALS(mp2t_sync_byte_vals), MP2T_SYNC_BYTE_MASK, NULL, HFILL
756 "Transport Error Indicator", "mp2t.tei",
757 FT_UINT32, BASE_DEC, NULL, MP2T_TEI_MASK, NULL, HFILL
760 "Payload Unit Start Indicator", "mp2t.pusi",
761 FT_UINT32, BASE_DEC, NULL, MP2T_PUSI_MASK, NULL, HFILL
764 "Transport Priority", "mp2t.tp",
765 FT_UINT32, BASE_DEC, NULL, MP2T_TP_MASK, NULL, HFILL
769 FT_UINT32, BASE_HEX, VALS(mp2t_pid_vals), MP2T_PID_MASK, NULL, HFILL
772 "Transport Scrambling Control", "mp2t.tsc",
773 FT_UINT32, BASE_HEX, VALS(mp2t_tsc_vals), MP2T_TSC_MASK, NULL, HFILL
776 "Adaption Field Control", "mp2t.afc",
777 FT_UINT32, BASE_HEX, VALS(mp2t_afc_vals) , MP2T_AFC_MASK, NULL, HFILL
780 "Continuity Counter", "mp2t.cc",
781 FT_UINT32, BASE_DEC, NULL, MP2T_CC_MASK, NULL, HFILL
783 { &hf_mp2t_cc_drop, {
784 "Continuity Counter Drops", "mp2t.cc.drop",
785 FT_NONE, BASE_DEC, NULL, 0x0, NULL, HFILL
788 "Adaption field", "mp2t.af",
789 FT_NONE, BASE_HEX, NULL, 0, NULL, HFILL
791 { &hf_mp2t_af_length, {
792 "Adaptation Field Length", "mp2t.af.length",
793 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL
796 "Discontinuity Indicator", "mp2t.af.di",
797 FT_UINT8, BASE_DEC, NULL, MP2T_AF_DI_MASK, NULL, HFILL
800 "Random Access Indicator", "mp2t.af.rai",
801 FT_UINT8, BASE_DEC, NULL, MP2T_AF_RAI_MASK, NULL, HFILL
803 { &hf_mp2t_af_espi, {
804 "Elementary Stream Priority Indicator", "mp2t.af.espi",
805 FT_UINT8, BASE_DEC, NULL, MP2T_AF_ESPI_MASK, NULL, HFILL
807 { &hf_mp2t_af_pcr_flag, {
808 "PCR Flag", "mp2t.af.pcr_flag",
809 FT_UINT8, BASE_DEC, NULL, MP2T_AF_PCR_MASK, NULL, HFILL
811 { &hf_mp2t_af_opcr_flag, {
812 "OPCR Flag", "mp2t.af.opcr_flag",
813 FT_UINT8, BASE_DEC, NULL, MP2T_AF_OPCR_MASK, NULL, HFILL
815 { &hf_mp2t_af_sp_flag, {
816 "Splicing Point Flag", "mp2t.af.sp_flag",
817 FT_UINT8, BASE_DEC, NULL, MP2T_AF_SP_MASK, NULL, HFILL
819 { &hf_mp2t_af_tpd_flag, {
820 "Transport Private Data Flag", "mp2t.af.tpd_flag",
821 FT_UINT8, BASE_DEC, NULL, MP2T_AF_TPD_MASK, NULL, HFILL
823 { &hf_mp2t_af_afe_flag, {
824 "Adaptation Field Extension Flag", "mp2t.af.afe_flag",
825 FT_UINT8, BASE_DEC, NULL, MP2T_AF_AFE_MASK, NULL, HFILL
828 "Program Clock Reference", "mp2t.af.pcr",
829 FT_NONE, BASE_DEC, NULL, 0, NULL, HFILL
831 { &hf_mp2t_af_opcr, {
832 "Original Program Clock Reference", "mp2t.af.opcr",
833 FT_NONE, BASE_DEC, NULL, 0, NULL, HFILL
836 "Splice Countdown", "mp2t.af.sc",
837 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
839 { &hf_mp2t_af_tpd_length, {
840 "Transport Private Data Length", "mp2t.af.tpd_length",
841 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
844 "Transport Private Data", "mp2t.af.tpd",
845 FT_BYTES, BASE_DEC, NULL, 0, NULL, HFILL
847 { &hf_mp2t_af_e_length, {
848 "Adaptation Field Extension Length", "mp2t.af.e_length",
849 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL
851 { &hf_mp2t_af_e_ltw_flag, {
852 "LTW Flag", "mp2t.af.e.ltw_flag",
853 FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_LTW_FLAG_MASK, NULL, HFILL
855 { &hf_mp2t_af_e_pr_flag, {
856 "Piecewise Rate Flag", "mp2t.af.e.pr_flag",
857 FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_PR_FLAG_MASK, NULL, HFILL
859 { &hf_mp2t_af_e_ss_flag, {
860 "Seamless Splice Flag", "mp2t.af.e.ss_flag",
861 FT_UINT8, BASE_DEC, NULL, MP2T_AF_E_SS_FLAG_MASK, NULL, HFILL
863 { &hf_mp2t_af_e_reserved, {
864 "Reserved", "mp2t.af.e.reserved",
865 FT_UINT8, BASE_DEC, NULL, 0x1F, NULL, HFILL
867 { &hf_mp2t_af_e_reserved_bytes, {
868 "Reserved", "mp2t.af.e.reserved_bytes",
869 FT_BYTES, BASE_DEC, NULL, 0x0, NULL, HFILL
871 { &hf_mp2t_af_stuffing_bytes, {
872 "Stuffing", "mp2t.af.stuffing_bytes",
873 FT_BYTES, BASE_DEC, NULL, 0x0, NULL, HFILL
875 { &hf_mp2t_af_e_ltwv_flag, {
876 "LTW Valid Flag", "mp2t.af.e.ltwv_flag",
877 FT_UINT16, BASE_DEC, NULL, 0x8000, NULL, HFILL
879 { &hf_mp2t_af_e_ltwo, {
880 "LTW Offset", "mp2t.af.e.ltwo",
881 FT_UINT16, BASE_DEC, NULL, 0x7FFF, NULL, HFILL
883 { &hf_mp2t_af_e_pr_reserved, {
884 "Reserved", "mp2t.af.e.pr_reserved",
885 FT_UINT24, BASE_DEC, NULL, 0xC00000, NULL, HFILL
887 { &hf_mp2t_af_e_pr, {
888 "Piecewise Rate", "mp2t.af.e.pr",
889 FT_UINT24, BASE_DEC, NULL, 0x3FFFFF, NULL, HFILL
891 { &hf_mp2t_af_e_st, {
892 "Splice Type", "mp2t.af.e.st",
893 FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL
895 { &hf_mp2t_af_e_dnau_32_30, {
896 "DTS Next AU[32...30]", "mp2t.af.e.dnau_32_30",
897 FT_UINT8, BASE_DEC, NULL, 0x0E, NULL, HFILL
899 { &hf_mp2t_af_e_m_1, {
900 "Marker Bit", "mp2t.af.e.m_1",
901 FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL
903 { &hf_mp2t_af_e_dnau_29_15, {
904 "DTS Next AU[29...15]", "mp2t.af.e.dnau_29_15",
905 FT_UINT16, BASE_DEC, NULL, 0xFFFE, NULL, HFILL
907 { &hf_mp2t_af_e_m_2, {
908 "Marker Bit", "mp2t.af.e.m_2",
909 FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL
911 { &hf_mp2t_af_e_dnau_14_0, {
912 "DTS Next AU[14...0]", "mp2t.af.e.dnau_14_0",
913 FT_UINT16, BASE_DEC, NULL, 0xFFFE, NULL, HFILL
915 { &hf_mp2t_af_e_m_3, {
916 "Marker Bit", "mp2t.af.e.m_3",
917 FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL
919 { &hf_mp2t_payload, {
920 "Payload", "mp2t.payload",
921 FT_BYTES, BASE_DEC, NULL, 0x0, NULL, HFILL
923 { &hf_mp2t_malformed_payload, {
924 "Malformed Payload", "mp2t.malformed_payload",
925 FT_BYTES, BASE_DEC, NULL, 0x0, NULL, HFILL
936 proto_mp2t = proto_register_protocol("ISO/IEC 13818-1", "MP2T", "mp2t");
937 proto_register_field_array(proto_mp2t, hf, array_length(hf));
938 proto_register_subtree_array(ett, array_length(ett));
944 proto_reg_handoff_mp2t(void)
946 dissector_handle_t mp2t_handle;
948 heur_dissector_add("udp", heur_dissect_mp2t, proto_mp2t);
950 mp2t_handle = create_dissector_handle(dissect_mp2t, proto_mp2t);
951 dissector_add("rtp.pt", PT_MP2T, mp2t_handle);
952 dissector_add_handle("udp.port", mp2t_handle); /* for decode-as */
954 pes_handle = find_dissector("mpeg-pes");