1 /* packet-smpte-2110-20.c
4 * Copyright 2023, Sergey V. Lobanov <sergey@lobanov.in>
7 * SMPTE ST 2110-20:2022, Uncompressed Active Video
8 * RFC4175, RTP Payload Format for Uncompressed Video
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * SPDX-License-Identifier: GPL-2.0-or-later
19 #include <epan/packet.h>
20 #include <epan/prefs.h>
21 #include <epan/proto.h>
22 #include <epan/proto_data.h>
24 #include "packet-rtp.h"
26 void proto_reg_handoff_st2110_20(void);
27 void proto_register_st2110_20(void);
29 static dissector_handle_t st2110_20_handle
;
31 /* Initialize the protocol and registered fields */
32 static int proto_st2110_20
;
35 static int hf_st2110_ext_seqno
;
36 static int hf_st2110_seqno
;
37 static int hf_st2110_rtp_time
;
38 static int hf_st2110_srd_index
;
39 static int hf_st2110_srd_length
;
40 static int hf_st2110_field_ident
;
41 static int hf_st2110_row_num
;
42 static int hf_st2110_continuation
;
43 static int hf_st2110_srd_offset
;
44 static int hf_st2110_srd_data
;
45 static int hf_st2110_srd_rows
;
47 /* Initialize the subtree pointers */
48 static int ett_st2110_20
;
49 static int ett_st2110_20_srd_row
;
53 dissect_st2110_20(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, void* data _U_
)
56 proto_tree
*st2110_20_tree
;
60 struct _rtp_packet_info
*rtp_pkt_info
= (struct _rtp_packet_info
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_rtp
, RTP_CONVERSATION_PROTO_DATA
);
62 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ST2110-20");
64 item
= proto_tree_add_item(tree
, proto_st2110_20
, tvb
, 0, -1, ENC_NA
);
65 st2110_20_tree
= proto_item_add_subtree(item
, ett_st2110_20
);
67 /* Extract original RTP sequence number from low bits */
68 uint32_t rtp_seqno
= (rtp_pkt_info
!= NULL
) ? (rtp_pkt_info
->extended_seqno
& 0xFFFF) : 0;
69 /* ST2110-20 extended sequence number field */
70 uint32_t ext_seqno
= tvb_get_uint16(tvb
, offset
, ENC_BIG_ENDIAN
);
71 /* Sequence number (RTP seqno is low bits, ST2110-20 ext seqno is high bits) */
72 uint32_t seqno
= (ext_seqno
<< 16) + rtp_seqno
;
74 /* Extract original RTP timestamp */
75 uint32_t rtp_time
= (rtp_pkt_info
!= NULL
) ? (uint32_t)(rtp_pkt_info
->extended_timestamp
& 0xFFFFFFFF) : 0;
77 proto_tree_add_item(st2110_20_tree
, hf_st2110_ext_seqno
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
78 PROTO_ITEM_SET_GENERATED(
79 proto_tree_add_uint(st2110_20_tree
, hf_st2110_seqno
, tvb
, offset
, 2, seqno
)
81 PROTO_ITEM_SET_GENERATED(
82 proto_tree_add_uint(st2110_20_tree
, hf_st2110_rtp_time
, NULL
, 0, 0, rtp_time
)
84 offset
+= 2; /* st2110-20 ext seqno */
86 /* According to ST2110-20:2022 6.2.1, max three SRD headers might be in a packet */
87 uint16_t srd_lengths
[3] = {0, 0, 0}; /* store for second pass */
88 proto_tree
* srd_header_trees
[3] = {NULL
, NULL
, NULL
}; /* store for second pass */
89 uint8_t srd_rows
= 0; /* rows count */
90 uint16_t first_row
; /* first row number */
91 for (uint8_t srd_idx
= 0; srd_idx
< 3 ; srd_idx
++) {
92 proto_tree
*srd_header_tree
= proto_tree_add_subtree_format(st2110_20_tree
, tvb
, offset
, 6,
93 ett_st2110_20_srd_row
, &item
, "Sample Row Data %u", srd_idx
);
94 srd_header_trees
[srd_idx
] = srd_header_tree
;
95 PROTO_ITEM_SET_GENERATED(
96 proto_tree_add_uint(srd_header_tree
, hf_st2110_srd_index
, NULL
, 0, 0, srd_idx
)
99 srd_lengths
[srd_idx
] = tvb_get_uint16(tvb
, offset
, ENC_BIG_ENDIAN
);
100 proto_tree_add_item(srd_header_tree
, hf_st2110_srd_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
103 first_row
= (srd_idx
== 0) ? (tvb_get_uint16(tvb
, offset
, ENC_BIG_ENDIAN
) & 0x7FFF) : first_row
;
104 proto_tree_add_item(srd_header_tree
, hf_st2110_field_ident
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
105 proto_tree_add_item(srd_header_tree
, hf_st2110_row_num
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
108 uint16_t cont_bit
= tvb_get_uint16(tvb
, offset
, ENC_BIG_ENDIAN
) >> 15;
109 proto_tree_add_item(srd_header_tree
, hf_st2110_continuation
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
110 proto_tree_add_item(srd_header_tree
, hf_st2110_srd_offset
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
115 if (cont_bit
!= 1) /* if continuation is not set, then no more headers*/
119 PROTO_ITEM_SET_GENERATED(
120 proto_tree_add_uint(st2110_20_tree
, hf_st2110_srd_rows
, NULL
, 0, 0, srd_rows
)
123 /* Second pass, get SRD data and add it to the same trees created for SRD headers */
124 for (uint8_t srd_idx
= 0; srd_idx
< srd_rows
; srd_idx
++) {
125 uint16_t srd_length
= srd_lengths
[srd_idx
];
127 proto_tree_add_item(srd_header_trees
[srd_idx
], hf_st2110_srd_data
, tvb
, offset
, srd_length
, ENC_NA
);
128 offset
+= srd_length
;
131 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Seq=%u, Time=%u, FirstRow=%u, Rows=%u", seqno
, rtp_time
, first_row
, srd_rows
);
137 proto_register_st2110_20(void)
139 module_t
*st2110_20_module
;
141 static hf_register_info hf
[] = {
142 { &hf_st2110_ext_seqno
,
143 { "Extended Sequence Number", "st2110_20.ext_seq",
144 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
148 { "Sequence Number", "st2110_20.seq",
149 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
152 { &hf_st2110_rtp_time
,
153 { "RTP Timestamp", "st2110_20.rtp_timestamp",
154 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
157 { &hf_st2110_srd_index
,
158 { "SRD Header Index", "st2110_20.srd_index",
159 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
162 { &hf_st2110_srd_length
,
163 { "SRD Length", "st2110_20.srd_length",
164 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
167 { &hf_st2110_field_ident
,
168 { "Field Identification Bit", "st2110_20.srd_field_ident",
169 FT_UINT16
, BASE_DEC
, NULL
, 0x8000,
172 { &hf_st2110_row_num
,
173 { "SRD Row Number", "st2110_20.srd_row_num",
174 FT_UINT16
, BASE_DEC
, NULL
, 0x7FFF,
177 { &hf_st2110_continuation
,
178 { "SRD Continuation Bit", "st2110_20.srd_cont_bit",
179 FT_UINT16
, BASE_DEC
, NULL
, 0x8000,
182 { &hf_st2110_srd_offset
,
183 { "SRD Offset", "st2110_20.srd_offset",
184 FT_UINT16
, BASE_DEC
, NULL
, 0x7FFF,
187 { &hf_st2110_srd_data
,
188 { "SRD Data", "st2110_20.srd_data",
189 FT_NONE
, BASE_NONE
, NULL
, 0x0,
192 { &hf_st2110_srd_rows
,
193 { "SRD Rows", "st2110_20.srd_rows",
194 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
202 &ett_st2110_20_srd_row
205 proto_st2110_20
= proto_register_protocol("SMPTE ST2110-20 (Uncompressed Active Video)", "ST2110-20", "st2110_20");
207 proto_register_field_array(proto_st2110_20
, hf
, array_length(hf
));
208 proto_register_subtree_array(ett
, array_length(ett
));
210 st2110_20_module
= prefs_register_protocol(proto_st2110_20
, NULL
);
212 prefs_register_obsolete_preference(st2110_20_module
, "dynamic.payload.type");
213 st2110_20_handle
= register_dissector("st2110_20", dissect_st2110_20
, proto_st2110_20
);
217 proto_reg_handoff_st2110_20(void)
219 dissector_add_string("rtp_dyn_payload_type" , "ST2110-20", st2110_20_handle
);
220 dissector_add_uint_range_with_preference("rtp.pt", "", st2110_20_handle
);
221 proto_rtp
= proto_get_id_by_filter_name("rtp");
225 * Editor modelines - https://www.wireshark.org/tools/modelines.html
230 * indent-tabs-mode: nil
233 * vi: set shiftwidth=4 tabstop=8 expandtab:
234 * :indentSize=4:tabSize=8:noTabs=true: