Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-scte35.c
blobaaf79d9bd647ac7d0f043ee147604059ba55b7a8
1 /* packet-scte35.c
2 * Routines for SCTE-35 dissection
3 * Author: Ben Stewart <bst[at]google.com>
4 * Copyright 2016 Google Inc.
6 * The SCTE-35 protocol is described by the Society of Cable Telecommunications
7 * Engineers at <https://www.scte.org/documents/pdf/Standards/Top%20Ten/ANSI_SCTE%2035%202013.pdf>.
9 * This module implements a dissector for the main table in a SCTE-35 message, a
10 * splice_info_section. This payload is carried in a MPEG Section Table with a
11 * table ID of 0xFC. PIDs carrying this sort of table are also noted in the PMT
12 * with a stream type of 0x86, and a registration descriptor with fourcc 'CUEI'.
14 * The various splice command types are implemented in separate modules, and are
15 * linked to this dissector through the field scte35.splice_command_type. All
16 * field names follow the conventions documented in the SCTE35 specification.
18 * This dissector does not support encrypted SCTE35 messages, other than
19 * indicating through the scte35.encrypted_packet flag.
22 * Wireshark - Network traffic analyzer
23 * By Gerald Combs <gerald@wireshark.org>
24 * Copyright 1998 Gerald Combs
26 * SPDX-License-Identifier: GPL-2.0-or-later
29 #include "config.h"
31 #include <epan/packet.h>
32 #include <epan/tfs.h>
33 #include <wsutil/array.h>
35 #define SCTE35_CMD_SPLICE_NULL (0x00)
36 #define SCTE35_CMD_SPLICE_SCHEDULE (0x04)
37 #define SCTE35_CMD_SPLICE_INSERT (0x05)
38 #define SCTE35_CMD_TIME_SIGNAL (0x06)
39 #define SCTE35_CMD_BANDWIDTH_RESERVATION (0x07)
40 #define SCTE35_CMD_PRIVATE_COMMAND (0xff)
42 #define SCTE35_AVAIL_DESCRIPTOR (0x00)
43 #define SCTE35_DTMF_DESCRIPTOR (0x01)
44 #define SCTE35_SEGMENTATION_DESCRIPTOR (0x02)
46 void proto_register_scte35(void);
47 void proto_register_scte35_private_command(void);
48 void proto_register_scte35_splice_insert(void);
49 void proto_register_scte35_splice_schedule(void);
50 void proto_register_scte35_time_signal(void);
51 void proto_reg_handoff_scte35(void);
52 void proto_reg_handoff_scte35_private_command(void);
53 void proto_reg_handoff_scte35_splice_insert(void);
54 void proto_reg_handoff_scte35_splice_schedule(void);
55 void proto_reg_handoff_scte35_time_signal(void);
57 /* MPEG Section Table ID for a SCTE35 splice_info_section. */
58 static const unsigned char SCTE35_TABLE_ID = 0xFCU;
60 /* Minimum length for a splice_info_section, excluding any splice commands,
61 * splice descriptors, encrypted CRC or alignment stuffing.
63 static const int SCTE35_SI_MIN_LEN = 20;
65 /* Protocol handle */
66 static int proto_scte35;
68 /* Dissector table for scte35.splice_command_type */
69 static dissector_table_t scte35_cmd_dissector_table;
72 /* splice_info_section table */
73 static int ett_scte35_splice_info_section;
75 /* splice_info_section fields */
76 static int hf_table_id;
77 static int hf_section_syntax_indicator;
78 static int hf_private_indicator;
79 static int hf_reserved;
80 static int hf_section_length;
81 static int hf_protocol_version;
82 static int hf_encrypted_packet;
83 static int hf_encryption_algorithm;
84 static int hf_pts_adjustment;
85 static int hf_cw_index;
86 static int hf_tier;
87 static int hf_splice_command_length;
88 static int hf_splice_command_type;
89 static int hf_descriptor_loop_length;
90 static int hf_splice_descriptor_tag;
91 static int hf_splice_descriptor_length;
92 static int hf_splice_descriptor_identifier;
93 static int hf_descriptor_provider_avail_id;
94 static int hf_descriptor_preroll;
95 static int hf_descriptor_dtmf_count;
96 static int hf_descriptor_dtmf_reserved;
97 static int hf_descriptor_dtmf;
98 static int hf_descriptor_event_id;
99 static int hf_descriptor_cancel_indicator;
100 static int hf_descriptor_reserved0;
101 static int hf_descriptor_psf;
102 static int hf_descriptor_segmentation_duration_flag;
103 static int hf_descriptor_delivery_not_restricted_flag;
104 static int hf_descriptor_web_delivery_allowed_flag;
105 static int hf_descriptor_no_regional_blackout_flag;
106 static int hf_descriptor_archive_allow_flag;
107 static int hf_descriptor_device_restrictions;
108 static int hf_descriptor_reserved1;
109 static int hf_descriptor_component_count;
110 static int hf_descriptor_component_tag;
111 static int hf_descriptor_component_reserved;
112 static int hf_descriptor_component_pts_offset;
113 static int hf_descriptor_segmentation_duration;
114 static int hf_descriptor_segmentation_upid_type;
115 static int hf_descriptor_segmentation_upid_length;
116 static int hf_descriptor_segmentation_upid;
117 static int hf_descriptor_segmentation_type_id;
118 static int hf_descriptor_segment_num;
119 static int hf_descriptor_segments_expected;
120 static int hf_e_crc32;
121 static int hf_crc32;
123 /* time_signal protocol and fields */
124 static int proto_scte35_time;
125 static int ett_scte35_time_signal;
126 static int ett_scte35_time_signal_splice_time;
127 static int hf_time_specified;
128 static int hf_time_reserved;
129 static int hf_time_pts;
131 /* private_command protocol and fields */
132 static int proto_private_command;
133 static int ett_private_command;
134 static int hf_identifier;
135 static int hf_private_byte;
137 /* Dissector table for scte35_private_command.identifier */
138 static dissector_table_t private_identifier_table;
140 static dissector_handle_t scte35_handle;
141 static dissector_handle_t scte35_time_handle;
142 static dissector_handle_t scte35_private_command_handle;
143 static dissector_handle_t scte35_si_handle;
144 static dissector_handle_t scte35_ss_handle;
146 /* splice_insert protocol and fields */
147 static int proto_scte35_si;
148 static int ett_scte35_splice_insert;
149 static int hf_splice_insert_event_id;
150 static int hf_splice_cancel_indicator;
151 static int hf_reserved0;
152 static int hf_out_of_network_indicator;
153 static int hf_program_splice_flag;
154 static int hf_duration_flag;
155 static int hf_splice_immediate_flag;
156 static int hf_reserved1;
157 static int hf_splice_time_specified_flag;
158 static int hf_splice_time_reserved;
159 static int hf_splice_time_pts_time;
160 static int hf_component_count;
161 static int hf_component_tag;
162 static int hf_component_splice_time_tsf;
163 static int hf_component_splice_time_reserved;
164 static int hf_component_splice_time_pts_time;
165 static int hf_break_duration_auto_return;
166 static int hf_break_duration_reserved;
167 static int hf_break_duration_duration;
168 static int hf_unique_program_id;
169 static int hf_avail_num;
170 static int hf_avails_expected;
172 /* splice_schedule protocol and fields */
173 static int proto_scte35_splice_schedule;
174 static int ett_scte35_splice_schedule;
175 static int hf_splice_count;
176 static int hf_splice_event_id;
177 static int hf_splice_event_cancel_indicator;
178 static int hf_splice_reserved0;
179 static int hf_splice_out_of_network;
180 static int hf_splice_program_splice_flag;
181 static int hf_splice_duration_flag;
182 static int hf_splice_reserved1;
183 static int hf_splice_utc_splice_time;
184 static int hf_splice_component_count;
185 static int hf_splice_component_tag;
186 static int hf_splice_component_utc_splice_time;
187 static int hf_splice_break_duration_auto_return;
188 static int hf_splice_break_duration_reserved;
189 static int hf_splice_break_duration_duration;
190 static int hf_splice_unique_program_id;
191 static int hf_splice_avail_num;
192 static int hf_splice_avails_expected;
194 static const true_false_string tfs_section_syntax_indicator = {
195 "Reserved", "MPEG short sections in use"};
197 static const true_false_string tfs_private_indicator = {
198 "Reserved", "Mandatory value"};
200 static const true_false_string tfs_encrypted_packet = {
201 "Encrypted data", "Cleartext"};
203 static const true_false_string tfs_descriptor_cancel_indicator = {
204 "Cancel Request", "New or existing event"};
206 static const true_false_string tfs_descriptor_psf = {
207 "All PIDs to be spliced", "Component Splice Mode"};
209 static const true_false_string tfs_descriptor_sdf = {
210 "Segmentation duration present", "No duration present"};
212 static const true_false_string tfs_descriptor_dnr = {
213 "No delivery restrictions", "Restricted delivery"};
215 static const true_false_string tfs_descriptor_web = {
216 "Permitted", "Restricted"};
218 static const true_false_string tfs_descriptor_blackout = {
219 "No regional blackouts", "Regional restrictions"};
221 static const true_false_string tfs_descriptor_archive = {
222 "No recording restrictions", "Recording is restricted"};
224 static const range_string rv_splice_command_type[] = {
225 { SCTE35_CMD_SPLICE_NULL, SCTE35_CMD_SPLICE_NULL, "splice_null" },
226 { 0x01, 0x03, "Reserved" },
227 { SCTE35_CMD_SPLICE_SCHEDULE, SCTE35_CMD_SPLICE_SCHEDULE, "splice_schedule" },
228 { SCTE35_CMD_SPLICE_INSERT, SCTE35_CMD_SPLICE_INSERT, "splice_insert" },
229 { SCTE35_CMD_TIME_SIGNAL, SCTE35_CMD_TIME_SIGNAL, "time_signal" },
230 { SCTE35_CMD_BANDWIDTH_RESERVATION, SCTE35_CMD_BANDWIDTH_RESERVATION, "bandwidth_reservation" },
231 { 0x08, 0xfe, "Reserved" },
232 { SCTE35_CMD_PRIVATE_COMMAND, SCTE35_CMD_PRIVATE_COMMAND, "private_command" },
233 { 0, 0, NULL }
236 static const range_string rv_splice_descriptor_tag[] = {
237 { SCTE35_AVAIL_DESCRIPTOR, SCTE35_AVAIL_DESCRIPTOR, "avail_descriptor" },
238 { SCTE35_DTMF_DESCRIPTOR, SCTE35_DTMF_DESCRIPTOR, "DTMF_descriptor" },
239 { SCTE35_SEGMENTATION_DESCRIPTOR, SCTE35_SEGMENTATION_DESCRIPTOR, "segmentation_descriptor" },
240 { 0x03, 0xff, "Reserved" },
241 { 0, 0, NULL }
244 static const range_string scte35_device_restrictions[] = {
245 { 0x00, 0x00, "Restrict Group 0" },
246 { 0x01, 0x01, "Restrict Group 1" },
247 { 0x02, 0x02, "Restrict Group 2" },
248 { 0x03, 0x03, "No Restrictions" },
249 { 0, 0, NULL }
252 static const range_string scte35_segmentation_upid_type[] = {
253 { 0x00, 0x00, "Not Used" },
254 { 0x01, 0x01, "User Defined (deprecated)" },
255 { 0x02, 0x02, "ISCI" },
256 { 0x03, 0x03, "Ad-ID" },
257 { 0x04, 0x04, "UMID (SMPTE 330M)" },
258 { 0x05, 0x05, "ISAN" },
259 { 0x06, 0x06, "Versioned ISAN" },
260 { 0x07, 0x07, "Tribune TID" },
261 { 0x08, 0x08, "Turner Identifier" },
262 { 0x09, 0x09, "CableLabs ADI Identifier" },
263 { 0x0a, 0x0a, "EIDR" },
264 { 0x0b, 0x0b, "ATSC A57/B Content Identifier" },
265 { 0x0c, 0x0c, "Managed Private UPID" },
266 { 0x0d, 0x0d, "Multiple UPIDs" },
267 { 0x0e, 0xff, "Reserved" },
268 { 0, 0, NULL }
271 static const range_string scte35_segmentation_type_id[] = {
272 { 0x00, 0x00, "Not Indicated" },
273 { 0x01, 0x01, "Content Identification" },
274 { 0x10, 0x10, "Program Start" },
275 { 0x11, 0x11, "Program End" },
276 { 0x12, 0x12, "Program Early Termination" },
277 { 0x13, 0x13, "Program Breakaway" },
278 { 0x14, 0x14, "Program Resumption" },
279 { 0x15, 0x15, "Program Runover Planned" },
280 { 0x16, 0x16, "Program Runover Unplanned" },
281 { 0x17, 0x17, "Program Overlap Start" },
282 { 0x20, 0x20, "Chapter Start" },
283 { 0x21, 0x21, "Chapter End" },
284 { 0x30, 0x30, "Provider Advertisement Start" },
285 { 0x31, 0x31, "Provider Advertisement End" },
286 { 0x32, 0x32, "Distributor Advertisement Start" },
287 { 0x33, 0x33, "Distributor Advertisement End" },
288 { 0x34, 0x34, "Placement Opportunity Start" },
289 { 0x35, 0x35, "Placement Opportunity End" },
290 { 0x40, 0x40, "Unscheduled Event Start" },
291 { 0x41, 0x41, "Unscheduled Event End" },
292 { 0, 0, NULL }
295 static const range_string rv_encryption_algorithm[] = {
296 { 0x00, 0x00, "No encryption"},
297 { 0x01, 0x01, "DES - ECB mode"},
298 { 0x02, 0x02, "DES - CBC mode"},
299 { 0x03, 0x03, "Triple DES EDE3 - ECB mode"},
300 { 0x04, 0x1F, "Reserved"},
301 { 0x20, 0x3F, "User private"},
302 { 0, 0, NULL }
306 /* time_signal dissector */
307 static int
308 dissect_scte35_time_signal(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
309 int tvb_len, min_length = 1, offset = 0;
310 uint8_t time_specified_flag;
311 proto_item *ti;
312 proto_tree *time_tree;
314 /* Check packet length. */
315 tvb_len = (int)tvb_reported_length(tvb);
316 if (tvb_len < min_length)
317 return 0;
319 time_specified_flag = tvb_get_uint8(tvb, offset) & 0x80;
320 if (time_specified_flag)
321 min_length += 4;
322 if (tvb_len < min_length)
323 return 0;
325 /* Set up headers in the packet list */
326 col_add_fstr(pinfo->cinfo, COL_INFO, "Time Signal (%s)",
327 time_specified_flag ? "Future" : "Immediate");
329 /* Create a subtree for the time_signal */
330 ti = proto_tree_add_item(tree, proto_scte35_time, tvb, 0, -1, ENC_NA);
331 time_tree = proto_item_add_subtree(ti, ett_scte35_time_signal);
333 /* Parse out the fields. */
334 proto_tree_add_item(time_tree, hf_time_specified, tvb, offset, 1, ENC_BIG_ENDIAN);
335 proto_tree_add_item(time_tree, hf_time_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
336 if (time_specified_flag) {
337 proto_tree_add_item(time_tree, hf_time_pts, tvb, offset, 5, ENC_BIG_ENDIAN);
338 offset += 4;
340 offset += 1;
342 return offset;
345 void
346 proto_register_scte35_time_signal(void)
348 static int *ett[] = {
349 &ett_scte35_time_signal,
350 &ett_scte35_time_signal_splice_time,
353 static hf_register_info hf[] = {
354 {&hf_time_specified,
355 {"Time Specified", "scte35_time.splice.time_specified", FT_BOOLEAN, 8,
356 NULL, 0x80, NULL, HFILL}},
357 {&hf_time_reserved,
358 {"Reserved", "scte35_time.splice.reserved", FT_UINT8, BASE_HEX,
359 NULL, 0x7E, NULL, HFILL}},
360 {&hf_time_pts,
361 {"PTS Time", "scte35_time.splice.pts", FT_UINT64, BASE_DEC,
362 NULL, UINT64_C(0x01FFFFFFFF), NULL, HFILL}},
365 proto_scte35_time = proto_register_protocol("SCTE-35 Time Signal", "SCTE35 TS", "scte35_time");
366 proto_register_subtree_array(ett, array_length(ett));
367 proto_register_field_array(proto_scte35_time, hf, array_length(hf));
369 /* Create a dissector for time_signal packets. */
370 scte35_time_handle = register_dissector("scte35_time", dissect_scte35_time_signal, proto_scte35_time);
373 void
374 proto_reg_handoff_scte35_time_signal(void)
376 dissector_add_uint("scte35.splice_command_type", SCTE35_CMD_TIME_SIGNAL, scte35_time_handle);
380 /* scte35 private_command dissector */
381 static int
382 dissect_scte35_private_command(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
384 int tvb_len;
385 uint32_t identifier;
386 int offset = 0;
387 proto_item *ti;
388 proto_tree *pc_tree;
390 tvb_len = (int)tvb_reported_length(tvb);
391 if (tvb_len < 4)
392 return 0;
394 /* Display rudimentary header information. */
395 ti = proto_tree_add_item(tree, proto_private_command, tvb, 0, -1, ENC_NA);
396 pc_tree = proto_item_add_subtree(ti, ett_private_command);
398 proto_tree_add_item_ret_uint(pc_tree, hf_identifier, tvb, offset, 4, ENC_BIG_ENDIAN, &identifier);
399 col_add_fstr(pinfo->cinfo, COL_INFO, "Private Command (0x%08x)", identifier);
400 offset += 4;
401 proto_tree_add_item(pc_tree, hf_private_byte, tvb, offset, -1, ENC_NA);
403 /* Let another dissector try to decode this data. */
404 dissector_try_uint(private_identifier_table, identifier, tvb, pinfo, tree);
406 return tvb_len;
409 void
410 proto_register_scte35_private_command(void)
412 static int *ett[] = {
413 &ett_private_command,
416 static hf_register_info hf[] = {
417 {&hf_identifier,
418 {"Identifier", "scte35_private_command.identifier", FT_UINT32,
419 BASE_HEX, NULL, 0, NULL, HFILL}},
420 {&hf_private_byte,
421 {"Private Bytes", "scte35_private_command.private_byte", FT_BYTES, 0,
422 NULL, 0, NULL, HFILL}},
425 proto_private_command = proto_register_protocol("SCTE-35 Private Command", "SCTE35 PC", "scte35_private_command");
427 proto_register_subtree_array(ett, array_length(ett));
428 proto_register_field_array(proto_private_command, hf, array_length(hf));
430 /* Allow other modules to hook private commands and decode them. */
431 private_identifier_table = register_dissector_table(
432 "scte35_private_command.identifier", "SCTE-35 Private Command Identifier",
433 proto_private_command, FT_UINT32, BASE_HEX);
435 /* Create a dissector for private commands. */
436 scte35_private_command_handle = register_dissector("scte35_private_command", dissect_scte35_private_command, proto_private_command);
439 void
440 proto_reg_handoff_scte35_private_command(void)
442 dissector_add_uint("scte35.splice_command_type", SCTE35_CMD_PRIVATE_COMMAND, scte35_private_command_handle);
446 /* scte35 splice_insert dissector */
447 static int
448 dissect_component(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, uint8_t sif, int idx)
450 int offset = 0;
451 uint8_t component_tag, tsf = 0;
452 proto_tree *component_tree;
453 int tvb_len, min_length = sif ? 1 : 2;
455 tvb_len = (int)tvb_reported_length(tvb);
456 if (tvb_len < min_length)
457 return 0;
459 if (!sif) {
460 /* Check whether time is present in the component. */
461 tsf = tvb_get_uint8(tvb, offset + 1) & 0x80;
462 if (tsf) {
463 min_length += 4;
464 if (tvb_len < min_length)
465 return 0;
469 /* Create a subtree for the component. */
470 component_tag = tvb_get_uint8(tvb, offset);
471 proto_tree_add_subtree_format(
472 tree, tvb, offset, min_length, idx, &component_tree,
473 "Component %d (0x%02x)", idx, component_tag);
475 /* Parse out component flags. */
476 proto_tree_add_item(component_tree, hf_component_tag, tvb, offset, 1, ENC_BIG_ENDIAN);
477 offset++;
479 /* For non-immediate splices.. */
480 if (!sif) {
481 proto_tree_add_item(component_tree, hf_component_splice_time_tsf, tvb,
482 offset, 1, ENC_BIG_ENDIAN);
483 proto_tree_add_item(component_tree, hf_component_splice_time_reserved,
484 tvb, offset, 1, ENC_BIG_ENDIAN);
486 /* And the PTS if present. */
487 if (tsf) {
488 proto_tree_add_item(component_tree, hf_component_splice_time_pts_time,
489 tvb, offset, 5, ENC_BIG_ENDIAN);
490 offset += 4;
492 offset++;
495 return offset;
498 static int
499 dissect_scte35_splice_insert(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
501 int tvb_len, min_length = 5, dissected_length;
502 uint8_t cancel_flag, psf, df, sif, tsf, component_count;
503 uint32_t event_id;
504 int component;
505 int offset = 0;
506 proto_item *ti;
507 proto_tree *si_tree, *st_tree;
509 static int * const new_event_fields[] = {
510 &hf_out_of_network_indicator,
511 &hf_program_splice_flag,
512 &hf_duration_flag,
513 &hf_splice_immediate_flag,
514 &hf_reserved1,
515 NULL
518 /* Check with no optional subfields */
519 tvb_len = (int)tvb_reported_length(tvb);
520 if (tvb_len < min_length)
521 return 0;
523 cancel_flag = tvb_get_uint8(tvb, offset + 4) & 0x80;
524 event_id = tvb_get_ntohl(tvb, 0);
526 if (!cancel_flag) {
527 min_length += 5;
528 if (tvb_len < min_length)
529 return 0;
532 /* Set up headers in the packet list */
533 col_add_fstr(pinfo->cinfo, COL_INFO, "Splice %s Event 0x%08x",
534 cancel_flag ? "Cancellation" : "Insertion", event_id);
536 /* Create a root tree element for the splice_insert protocol. */
537 ti = proto_tree_add_item(tree, proto_scte35_si, tvb, 0, -1, ENC_NA);
538 si_tree = proto_item_add_subtree(ti, ett_scte35_splice_insert);
540 /* Parse header fields */
541 proto_tree_add_item(si_tree, hf_splice_insert_event_id, tvb, offset, 4, ENC_BIG_ENDIAN);
542 offset += 4;
544 proto_tree_add_item(si_tree, hf_splice_cancel_indicator, tvb, offset, 1, ENC_BIG_ENDIAN);
545 proto_tree_add_item(si_tree, hf_reserved0, tvb, offset, 1, ENC_BIG_ENDIAN);
546 offset++;
548 /* Check for a new event. */
549 if (!cancel_flag) {
551 /* Parse out the 'new event' fields. */
552 psf = tvb_get_uint8(tvb, offset) & 0x40;
553 df = tvb_get_uint8(tvb, offset) & 0x20;
554 sif = tvb_get_uint8(tvb, offset) & 0x10;
556 proto_tree_add_bitmask_list(si_tree, tvb, offset, 1, new_event_fields, ENC_BIG_ENDIAN);
557 offset++;
559 /* Parse out the program-level splice fields. */
560 if (psf && !sif) {
561 min_length += 1;
562 if (tvb_len < min_length)
563 return offset;
565 tsf = tvb_get_bits8(tvb, offset * 8, 1);
566 proto_tree_add_subtree(si_tree, tvb, offset, tsf ? 5 : 1, 0, &st_tree, "Program Splice Time");
567 proto_tree_add_item(st_tree, hf_splice_time_specified_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
568 proto_tree_add_item(st_tree, hf_splice_time_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
570 /* If a time is specified, display it too. */
571 if (tsf) {
572 min_length += 4;
573 if (tvb_len < min_length)
574 return offset;
576 proto_tree_add_item(st_tree, hf_splice_time_pts_time, tvb, offset, 5, ENC_BIG_ENDIAN);
577 offset += 4;
579 offset++;
582 /* For component-level splices, parse the component table. */
583 if (!psf) {
584 min_length += 1;
585 if (tvb_len < min_length)
586 return offset;
588 component_count = tvb_get_uint8(tvb, offset);
589 proto_tree_add_item(si_tree, hf_component_count, tvb, offset, 1, ENC_BIG_ENDIAN);
590 offset++;
592 min_length += component_count * (sif ? 1 : 2);
593 if (tvb_len < min_length)
594 return offset;
596 /* Dissect each splice component. */
597 for (component = 0; component < component_count; ++component) {
598 dissected_length = dissect_component(
599 tvb_new_subset_remaining(tvb, offset),
600 pinfo, si_tree, sif, component);
602 /* Propagate failures. */
603 if (dissected_length < 1)
604 return offset;
605 offset += dissected_length;
609 /* If present, parse out the duration field. */
610 if (df) {
611 min_length += 5;
612 if (tvb_len < min_length)
613 return offset;
615 proto_tree_add_item(si_tree, hf_break_duration_auto_return, tvb, offset, 1, ENC_BIG_ENDIAN);
616 proto_tree_add_item(si_tree, hf_break_duration_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
617 proto_tree_add_item(si_tree, hf_break_duration_duration, tvb, offset, 5, ENC_BIG_ENDIAN);
618 offset += 5;
621 /* Parse the UPID and avails fields. */
622 proto_tree_add_item(si_tree, hf_unique_program_id, tvb, offset, 2, ENC_BIG_ENDIAN);
623 offset += 2;
625 proto_tree_add_item(si_tree, hf_avail_num, tvb, offset, 1, ENC_BIG_ENDIAN);
626 offset++;
628 proto_tree_add_item(si_tree, hf_avails_expected, tvb, offset, 1, ENC_BIG_ENDIAN);
629 offset++;
632 return offset;
635 void
636 proto_register_scte35_splice_insert(void)
638 static hf_register_info hf[] = {
639 {&hf_splice_insert_event_id,
640 {"Event ID", "scte35_si.event_id", FT_UINT32, BASE_HEX,
641 NULL, 0, NULL, HFILL}},
642 {&hf_splice_cancel_indicator,
643 {"Cancelled", "scte35_si.cancelled", FT_BOOLEAN, 8,
644 NULL, 0x80, NULL, HFILL}},
645 {&hf_reserved0,
646 {"Reserved", "scte35_si.reserved0", FT_UINT8, 1,
647 NULL, 0x7F, NULL, HFILL}},
648 {&hf_out_of_network_indicator,
649 {"Out of Network", "scte35_si.out_of_net", FT_BOOLEAN, 8,
650 NULL, 0x80, NULL, HFILL}},
651 {&hf_program_splice_flag,
652 {"Program Splice Point", "scte35_si.psf", FT_BOOLEAN, 8,
653 NULL, 0x40, NULL, HFILL}},
654 {&hf_duration_flag,
655 {"Duration Present", "scte35_si.duration_flag", FT_BOOLEAN, 8,
656 NULL, 0x20, NULL, HFILL}},
657 {&hf_splice_immediate_flag,
658 {"Splice Immediate", "scte35_si.splice_immediate", FT_BOOLEAN, 8,
659 NULL, 0x10, NULL, HFILL}},
660 {&hf_reserved1,
661 {"Reserved", "scte35_si.reserved1", FT_UINT8, 1,
662 NULL, 0x0f, NULL, HFILL}},
663 {&hf_splice_time_specified_flag,
664 {"Time Specified", "scte35_si.splice_time.time_specified", FT_BOOLEAN,
665 8, NULL, 0x80, NULL, HFILL}},
666 {&hf_splice_time_reserved,
667 {"Reserved", "scte35_si.splice_time.reserved", FT_UINT8, 1,
668 NULL, 0x7E, NULL, HFILL}},
669 {&hf_splice_time_pts_time,
670 {"PTS Time", "scte35_si.splice_time.pts", FT_UINT64, 5,
671 NULL, UINT64_C(0x1FFFFFFFF), NULL, HFILL}},
672 {&hf_component_count,
673 {"Component Count", "scte35_si.component_count", FT_UINT8, BASE_DEC,
674 NULL, 0, NULL, HFILL}},
675 {&hf_component_tag,
676 {"Component Tag", "scte35_si.component.tag", FT_UINT8, BASE_HEX,
677 NULL, 0, NULL, HFILL}},
678 {&hf_component_splice_time_tsf,
679 {"Time Specified", "scte35_si.component.time_specified", FT_BOOLEAN, 8,
680 NULL, 0x80, NULL, HFILL}},
681 {&hf_component_splice_time_reserved,
682 {"Reserved", "scte35_si.component.reserved", FT_UINT8, 1,
683 NULL, 0x7E, NULL, HFILL}},
684 {&hf_component_splice_time_pts_time,
685 {"PTS Time", "scte35_si.component.pts", FT_UINT64, 5,
686 NULL, UINT64_C(0x1FFFFFFFF), NULL, HFILL}},
687 {&hf_break_duration_auto_return,
688 {"Auto Return", "scte35_si.break.auto_return", FT_BOOLEAN, 8,
689 NULL, 0x80, NULL, HFILL}},
690 {&hf_break_duration_reserved,
691 {"Reserved", "scte35_si.break.reserved", FT_UINT8, 1,
692 NULL, 0x7E, NULL, HFILL}},
693 {&hf_break_duration_duration,
694 {"Duration", "scte35_si.break.duration", FT_UINT64, 5,
695 NULL, UINT64_C(0x1FFFFFFFF), NULL, HFILL}},
696 {&hf_unique_program_id,
697 {"Unique Program ID", "scte35_si.upid", FT_UINT16, BASE_HEX,
698 NULL, 0, NULL, HFILL}},
699 {&hf_avail_num,
700 {"Avail Number", "scte35_si.avail", FT_UINT8, BASE_DEC,
701 NULL, 0, NULL, HFILL}},
702 {&hf_avails_expected,
703 {"Avails Expected", "scte35_si.avails_expected", FT_UINT8, BASE_DEC,
704 NULL, 0, NULL, HFILL}},
707 static int *ett[] = {
708 &ett_scte35_splice_insert,
711 proto_scte35_si = proto_register_protocol("SCTE-35 Splice Insert", "SCTE35 SI", "scte35_si");
713 proto_register_subtree_array(ett, array_length(ett));
714 proto_register_field_array(proto_scte35_si, hf, array_length(hf));
716 /* Create a splice_insert dissector. */
717 scte35_si_handle = register_dissector("scte35_si", dissect_scte35_splice_insert, proto_scte35_si);
720 void
721 proto_reg_handoff_scte35_splice_insert(void)
723 dissector_add_uint("scte35.splice_command_type", SCTE35_CMD_SPLICE_INSERT, scte35_si_handle);
727 /* scte35 splice_schedule dissector */
728 static int
729 dissect_scte35_splice_schedule(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
731 int tvb_len, min_length = 1;
732 uint8_t splice_count, cancel_flag, psf, df, component_count;
733 int component, splice;
734 int offset = 0, splice_length;
735 proto_item *ti;
736 proto_tree *ss_tree, *sp_tree, *component_tree;
738 static int * const splice_event_flags[] = {
739 &hf_splice_out_of_network,
740 &hf_splice_program_splice_flag,
741 &hf_splice_duration_flag,
742 &hf_splice_reserved1,
743 NULL
746 /* Check with no optional subfields */
747 tvb_len = (int)tvb_reported_length(tvb);
748 if (tvb_len < min_length)
749 return 0;
751 /* Set up headers in the packet list */
752 splice_count = tvb_get_uint8(tvb, 0);
753 min_length += splice_count * 5;
754 if (tvb_len < min_length)
755 return 0;
757 col_add_fstr(pinfo->cinfo, COL_INFO, "Splice Schedule (%d splices)", splice_count);
759 /* Create the root of the dissection */
760 ti = proto_tree_add_item(tree, proto_scte35_splice_schedule, tvb, 0, -1, ENC_NA);
761 ss_tree = proto_item_add_subtree(ti, ett_scte35_splice_schedule);
763 /* Header fields for splice_schedule() message */
764 proto_tree_add_item(ss_tree, hf_splice_count, tvb, offset, 1, ENC_NA);
765 offset++;
767 /* Process each splice. */
768 for (splice = 0; splice < splice_count; ++splice) {
769 cancel_flag = tvb_get_bits8(tvb, offset * 8 + 32, 1);
770 psf = cancel_flag ? 0 : tvb_get_bits8(tvb, offset * 8 + 41, 1);
771 df = cancel_flag ? 0 : tvb_get_bits8(tvb, offset * 8 + 42, 1);
772 component_count = cancel_flag ? 0 : (psf ? 0 : tvb_get_uint8(tvb, offset + 6));
774 splice_length = 5;
775 if (!cancel_flag)
776 splice_length += 4 + 1;
777 if (!cancel_flag && psf)
778 splice_length += 4;
779 if (!cancel_flag && !psf)
780 splice_length += 1 + 5 * component_count;
781 if (!cancel_flag && df)
782 splice_length += 5;
784 /* Add a subtree for the splice. */
785 proto_tree_add_subtree_format(
786 ss_tree, tvb, offset, splice_length, splice, &sp_tree,
787 "Splice %d", splice);
789 /* Show the splice header. */
790 proto_tree_add_item(ss_tree, hf_splice_event_id, tvb, offset, 4, ENC_BIG_ENDIAN);
791 offset += 4;
793 proto_tree_add_item(ss_tree, hf_splice_event_cancel_indicator, tvb,
794 offset, 1, ENC_BIG_ENDIAN);
795 proto_tree_add_item(ss_tree, hf_splice_reserved0, tvb, offset, 1, ENC_BIG_ENDIAN);
796 offset++;
798 if (!cancel_flag) {
799 min_length += 5;
800 if (tvb_len < min_length)
801 return offset;
803 df = tvb_get_bits8(tvb, offset * 8 + 2, 1);
805 /* Parse out the splice event flags. */
806 proto_tree_add_bitmask_list(ss_tree, tvb, offset, 1, splice_event_flags, ENC_BIG_ENDIAN);
807 offset++;
809 min_length += (psf ? 4 : 1);
810 if (tvb_len < min_length)
811 return offset;
813 if (psf) {
814 proto_tree_add_item(ss_tree, hf_splice_utc_splice_time, tvb,
815 offset, 4, ENC_BIG_ENDIAN);
816 offset += 4;
817 } else {
818 component_count = tvb_get_uint8(tvb, offset);
819 proto_tree_add_item(ss_tree, hf_splice_component_count, tvb, offset, 1, ENC_NA);
820 offset++;
822 min_length += 5 * component_count;
823 if (tvb_len < min_length)
824 return offset;
826 /* Parse out each component stream. */
827 for (component = 0; component < component_count; ++component) {
828 proto_tree_add_subtree_format(sp_tree, tvb, offset, 5, component, &component_tree,
829 "Component %d", component);
830 proto_tree_add_item(component_tree, hf_splice_component_tag, tvb,
831 offset, 1, ENC_NA);
832 offset++;
834 proto_tree_add_item(component_tree, hf_splice_component_utc_splice_time, tvb,
835 offset, 4, ENC_NA);
836 offset += 4;
840 /* Parse out break duration, if present. */
841 if (df) {
842 min_length += 5;
843 if (tvb_len < min_length)
844 return offset;
846 proto_tree_add_item(ss_tree, hf_splice_break_duration_auto_return, tvb,
847 offset, 1, ENC_BIG_ENDIAN);
848 proto_tree_add_item(ss_tree, hf_splice_break_duration_reserved, tvb,
849 offset, 1, ENC_BIG_ENDIAN);
850 proto_tree_add_item(ss_tree, hf_splice_break_duration_duration, tvb,
851 offset, 5, ENC_BIG_ENDIAN);
852 offset += 5;
856 proto_tree_add_item(ss_tree, hf_splice_unique_program_id, tvb, offset, 2, ENC_BIG_ENDIAN);
857 offset += 2;
859 proto_tree_add_item(ss_tree, hf_splice_avail_num, tvb, offset, 1, ENC_BIG_ENDIAN);
860 offset++;
862 proto_tree_add_item(ss_tree, hf_splice_avails_expected, tvb, offset, 1, ENC_BIG_ENDIAN);
863 offset++;
866 return offset;
869 void
870 proto_register_scte35_splice_schedule(void)
872 static hf_register_info hf[] = {
873 {&hf_splice_count,
874 {"Splice Count", "scte35_splice_schedule.splice_count",
875 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
876 {&hf_splice_event_id,
877 {"Event ID", "scte35_splice_schedule.splice.event_id",
878 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL}},
879 {&hf_splice_event_cancel_indicator,
880 {"Event Cancel Indicator", "scte35_splice_schedule.splice.event_cancel_indicator",
881 FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL}},
882 {&hf_splice_reserved0,
883 {"Reserved", "scte35_splice_schedule.splice.reserved0",
884 FT_UINT8, BASE_HEX, NULL, 0x7F, NULL, HFILL}},
885 {&hf_splice_out_of_network,
886 {"Out of Network Indicator", "scte35_splice_schedule.splice.out_of_network_indicator",
887 FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL}},
888 {&hf_splice_program_splice_flag,
889 {"Program Splice Flag", "scte35_splice_schedule.splice.program_splice_flag",
890 FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL}},
891 {&hf_splice_duration_flag,
892 {"Duration Flag", "scte35_splice_schedule.splice.duration_flag",
893 FT_BOOLEAN, 8, NULL, 0x20, NULL, HFILL}},
894 {&hf_splice_reserved1,
895 {"Reserved", "scte35_splice_schedule.splice.reserved1",
896 FT_UINT8, BASE_HEX, NULL, 0x1F, NULL, HFILL}},
897 {&hf_splice_utc_splice_time,
898 {"UTC Splice Time", "scte35_splice_schedule.splice.utc_splice_time",
899 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
900 {&hf_splice_component_count,
901 {"Component Count", "scte35_splice_schedule.splice.component_count",
902 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
903 {&hf_splice_component_tag,
904 {"Component Tag", "scte35_splice_schedule.splice.component.tag",
905 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL}},
906 {&hf_splice_component_utc_splice_time,
907 {"UTC Splice Time", "scte35_splice_schedule.splice.component.utc_splice_time",
908 FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL}},
909 {&hf_splice_break_duration_auto_return,
910 {"Auto Return", "scte35_splice_schedule.splice.break_duration.auto_return",
911 FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL}},
912 {&hf_splice_break_duration_reserved,
913 {"Reserved", "scte35_splice_schedule.splice.break_duration.reserved",
914 FT_UINT8, BASE_HEX, NULL, 0x7E, NULL, HFILL}},
915 {&hf_splice_break_duration_duration,
916 {"Duration", "scte35_splice_schedule.splice.break_duration.duration",
917 FT_UINT64, BASE_DEC, NULL, UINT64_C(0x1FFFFFFFF), NULL, HFILL}},
918 {&hf_splice_unique_program_id,
919 {"Unique Program ID", "scte35_splice_schedule.splice.unique_program_id",
920 FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL}},
921 {&hf_splice_avail_num,
922 {"Avail Number", "scte35_splice_schedule.splice.avail_num",
923 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
924 {&hf_splice_avails_expected,
925 {"Avails Expected", "scte35_splice_schedule.splice.avails_expected",
926 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
929 static int *ett[] = {
930 &ett_scte35_splice_schedule,
933 proto_scte35_splice_schedule = proto_register_protocol("SCTE-35 Splice Schedule", "SCTE35 SS", "scte35_splice_schedule");
935 proto_register_subtree_array(ett, array_length(ett));
936 proto_register_field_array(proto_scte35_splice_schedule, hf, array_length(hf));
938 scte35_ss_handle = register_dissector("scte35_splice_schedule", dissect_scte35_splice_schedule, proto_scte35_splice_schedule);
941 void
942 proto_reg_handoff_scte35_splice_schedule(void)
944 dissector_add_uint("scte35.splice_command_type", SCTE35_CMD_SPLICE_SCHEDULE, scte35_ss_handle);
948 /* core scte35 splice_info_section dissector */
949 static int
950 dissect_scte35_avail_descriptor(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
952 int offset = 0;
953 int tvb_len;
955 /* Check length. */
956 tvb_len = (int)tvb_reported_length(tvb);
957 if (tvb_len < 4)
958 return 0;
960 /* Show the field. */
961 proto_tree_add_item(tree, hf_descriptor_provider_avail_id, tvb, offset, 4, ENC_NA);
962 offset += 4;
964 return offset;
967 static int
968 dissect_scte35_dtmf_descriptor(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
970 int offset = 0;
971 int tvb_len, min_length = 2;
972 uint8_t dtmf_count;
974 /* Check length. */
975 tvb_len = (int)tvb_reported_length(tvb);
976 if (tvb_len < min_length)
977 return 0;
979 dtmf_count = tvb_get_bits8(tvb, (offset+1)* 8, 3);
981 /* Check length with DTMF string too. */
982 min_length += dtmf_count;
983 if (tvb_len < min_length)
984 return 0;
986 /* Describe header. */
987 proto_tree_add_item(tree, hf_descriptor_preroll, tvb, offset, 1, ENC_NA);
988 offset++;
990 proto_tree_add_item(tree, hf_descriptor_dtmf_count, tvb, offset, 1, ENC_NA);
991 proto_tree_add_item(tree, hf_descriptor_dtmf_reserved, tvb, offset, 1, ENC_NA);
992 offset++;
994 /* Show the DTMF string field. */
995 proto_tree_add_item(tree, hf_descriptor_dtmf, tvb,
996 offset, dtmf_count, ENC_NA | ENC_ASCII);
998 offset += dtmf_count;
999 return offset;
1002 static int
1003 dissect_scte35_component(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int idx) {
1004 int offset = 0;
1005 proto_tree *subtree;
1007 /* Create the subtree. */
1008 proto_tree_add_subtree_format(tree, tvb, offset, 6, idx, &subtree, "Component %d", idx);
1010 /* Display the component fields. */
1011 proto_tree_add_item(subtree, hf_descriptor_component_tag, tvb,
1012 offset, 1, ENC_NA);
1013 offset++;
1015 proto_tree_add_item(subtree, hf_descriptor_component_reserved, tvb,
1016 offset, 1, ENC_NA);
1017 proto_tree_add_item(subtree, hf_descriptor_component_pts_offset, tvb,
1018 offset, 5, ENC_BIG_ENDIAN);
1019 offset += 5;
1021 return offset;
1024 static int
1025 dissect_scte35_segmentation_descriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1027 int offset = 0, dissected_length = 0, component;
1028 uint8_t cancel_indicator, psf, sdf, dnr, component_count, upid_length;
1030 /* Parse the common header */
1031 proto_tree_add_item(tree, hf_descriptor_event_id, tvb, offset, 4, ENC_BIG_ENDIAN);
1032 offset += 4;
1034 cancel_indicator = tvb_get_bits8(tvb, offset * 8, 1);
1035 proto_tree_add_item(tree, hf_descriptor_cancel_indicator, tvb,
1036 offset, 1, ENC_NA);
1037 proto_tree_add_item(tree, hf_descriptor_reserved0, tvb,
1038 offset, 1, ENC_NA);
1039 offset++;
1041 /* Parse fields for new segmentation events. */
1042 if (!cancel_indicator) {
1043 psf = tvb_get_bits8(tvb, offset * 8, 1);
1044 sdf = tvb_get_bits8(tvb, offset * 8 + 1, 1);
1045 dnr = tvb_get_bits8(tvb, offset * 8 + 2, 1);
1046 proto_tree_add_item(tree, hf_descriptor_psf, tvb, offset, 1, ENC_NA);
1047 proto_tree_add_item(tree, hf_descriptor_segmentation_duration_flag,
1048 tvb, offset, 1, ENC_NA);
1049 proto_tree_add_item(tree, hf_descriptor_delivery_not_restricted_flag,
1050 tvb, offset, 1, ENC_NA);
1052 /* Parse delivery flags */
1053 if (dnr) {
1054 proto_tree_add_item(tree, hf_descriptor_reserved1, tvb, offset, 1, ENC_NA);
1055 } else {
1056 proto_tree_add_item(tree, hf_descriptor_web_delivery_allowed_flag,
1057 tvb, offset, 1, ENC_NA);
1058 proto_tree_add_item(tree, hf_descriptor_no_regional_blackout_flag,
1059 tvb, offset, 1, ENC_NA);
1060 proto_tree_add_item(tree, hf_descriptor_archive_allow_flag,
1061 tvb, offset, 1, ENC_NA);
1062 proto_tree_add_item(tree, hf_descriptor_device_restrictions,
1063 tvb, offset, 1, ENC_NA);
1065 offset++;
1067 /* Parse component segmentation offsets if not switched as a program. */
1068 if (!psf) {
1069 component_count = tvb_get_uint8(tvb, offset);
1070 proto_tree_add_item(tree, hf_descriptor_component_count, tvb,
1071 offset, 1, ENC_NA);
1072 offset++;
1074 /* Parse each component */
1075 for (component = 0; component < component_count; ++component) {
1076 dissected_length = dissect_scte35_component(
1077 tvb_new_subset_length(tvb, offset, 6),
1078 pinfo, tree, component);
1080 /* Propagate errors. */
1081 if (dissected_length < 1)
1082 return dissected_length;
1083 offset += dissected_length;
1087 /* Parse segmentation duration if present. */
1088 if (sdf) {
1089 proto_tree_add_item(tree, hf_descriptor_segmentation_duration, tvb,
1090 offset, 5, ENC_BIG_ENDIAN);
1091 offset += 5;
1094 /* Parse UPID. */
1095 proto_tree_add_item(tree, hf_descriptor_segmentation_upid_type, tvb,
1096 offset, 1, ENC_NA);
1097 offset++;
1099 upid_length = tvb_get_uint8(tvb, offset);
1100 proto_tree_add_item(tree, hf_descriptor_segmentation_upid_length, tvb,
1101 offset, 1, ENC_NA);
1102 offset++;
1104 /* Only show non-empty UPIDs. */
1105 if (upid_length) {
1106 proto_tree_add_item(tree, hf_descriptor_segmentation_upid, tvb,
1107 offset, upid_length, ENC_NA | ENC_ASCII);
1108 offset += upid_length;
1111 /* Parse Segment counts. */
1112 proto_tree_add_item(tree, hf_descriptor_segmentation_type_id, tvb, offset, 1, ENC_NA);
1113 offset++;
1115 proto_tree_add_item(tree, hf_descriptor_segment_num, tvb, offset, 1, ENC_NA);
1116 offset++;
1118 proto_tree_add_item(tree, hf_descriptor_segments_expected, tvb, offset, 1, ENC_NA);
1119 offset++;
1122 return offset;
1125 static int
1126 dissect_scte35_splice_descriptor(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int idx)
1128 proto_tree *subtree;
1129 tvbuff_t *descriptor_tvb;
1130 int offset = 0, dissected_length = 0;
1131 uint8_t tag, length = 0;
1133 /* Create the subtree header for the descriptor. */
1134 tag = tvb_get_uint8(tvb, offset);
1135 length = tvb_get_uint8(tvb, offset + 1);
1136 proto_tree_add_subtree_format(
1137 tree, tvb, offset, length + 2, idx, &subtree,
1138 "Descriptor %d (0x%02x)", idx, tag);
1140 /* Parse descriptor headers */
1141 proto_tree_add_item(subtree, hf_splice_descriptor_tag, tvb, offset, 1, ENC_NA);
1142 offset++;
1144 proto_tree_add_item(subtree, hf_splice_descriptor_length, tvb, offset, 1, ENC_NA);
1145 offset++;
1147 proto_tree_add_item(subtree, hf_splice_descriptor_identifier, tvb,
1148 offset, 4, ENC_BIG_ENDIAN);
1149 offset += 4;
1151 /* Parse the specific descriptor type. */
1152 descriptor_tvb = tvb_new_subset_length(tvb, offset, length - 4);
1153 switch (tag) {
1154 case SCTE35_AVAIL_DESCRIPTOR:
1155 dissected_length = dissect_scte35_avail_descriptor(descriptor_tvb, pinfo, subtree);
1156 break;
1158 case SCTE35_DTMF_DESCRIPTOR:
1159 dissected_length = dissect_scte35_dtmf_descriptor(descriptor_tvb, pinfo, subtree);
1160 break;
1162 case SCTE35_SEGMENTATION_DESCRIPTOR:
1163 dissected_length = dissect_scte35_segmentation_descriptor(descriptor_tvb, pinfo, subtree);
1164 break;
1166 default:
1167 /* Just trust the descriptor_length field. */
1168 dissected_length = length - 4;
1171 /* Propagate errors. */
1172 if (dissected_length < 1)
1173 return dissected_length;
1175 offset += dissected_length;
1176 return offset;
1179 static int
1180 dissect_scte35_splice_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1182 int tvb_len, min_length = SCTE35_SI_MIN_LEN, dissected_length = 0;
1183 uint8_t table_id, encrypted_packet, command_type;
1184 uint16_t command_length, descriptor_loop_length, i;
1186 proto_item *ti;
1187 proto_tree *splice_info_tree;
1188 int offset = 0, descriptor_offset = 0;
1189 tvbuff_t *command_tvb;
1191 static int * const section_flags[] = {
1192 &hf_section_syntax_indicator,
1193 &hf_private_indicator,
1194 &hf_reserved,
1195 &hf_section_length,
1196 NULL
1199 static int * const encrypt_flags[] = {
1200 &hf_encrypted_packet,
1201 &hf_encryption_algorithm,
1202 &hf_pts_adjustment,
1203 NULL
1206 tvb_len = (int)tvb_reported_length(tvb);
1207 if (tvb_len < min_length)
1208 return 0;
1210 /* Pre-fetch a few fields in the message. */
1211 table_id = tvb_get_uint8(tvb, offset);
1212 encrypted_packet = tvb_get_uint8(tvb, offset + 4) & 0x80;
1213 command_type = tvb_get_uint8(tvb, offset + 13);
1214 command_length = tvb_get_ntohs(tvb, offset + 11) & 0xFFF;
1216 /* Check for excessive length before indexing past the command. */
1217 min_length += command_length;
1218 if (tvb_len < min_length)
1219 return 0;
1221 /* Determine length of descriptors. */
1222 descriptor_loop_length = tvb_get_ntohs(tvb, 14 + command_length);
1223 min_length += descriptor_loop_length;
1224 if (tvb_len < min_length)
1225 return 0;
1227 /* Check for excessive length before parsing the remainder of the packet. */
1228 if (encrypted_packet)
1229 min_length += 4;
1231 if (tvb_len < min_length)
1232 return 0;
1234 /* Set up headers in the packet list */
1235 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SCTE-35");
1236 col_add_fstr(pinfo->cinfo, COL_INFO, "Table 0x%02x", table_id);
1238 /* Create the protocol header. */
1239 ti = proto_tree_add_item(tree, proto_scte35, tvb, 0, -1, ENC_NA);
1240 splice_info_tree = proto_item_add_subtree(ti, ett_scte35_splice_info_section);
1242 /* Explain the root fields. */
1243 proto_tree_add_item(splice_info_tree, hf_table_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1244 offset++;
1246 proto_tree_add_bitmask_list(splice_info_tree, tvb, offset, 2, section_flags, ENC_BIG_ENDIAN);
1247 offset += 2;
1249 proto_tree_add_item(splice_info_tree, hf_protocol_version, tvb, offset, 1, ENC_BIG_ENDIAN);
1250 offset++;
1252 /* 7 bits of flags, 33 bits of PTS */
1253 proto_tree_add_bitmask_list(splice_info_tree, tvb, offset, 5, encrypt_flags, ENC_BIG_ENDIAN);
1254 offset += 5;
1256 proto_tree_add_item(splice_info_tree, hf_cw_index, tvb, offset, 1, ENC_BIG_ENDIAN);
1257 offset++;
1259 /* Two twelve-bit fields */
1260 proto_tree_add_item(splice_info_tree, hf_tier, tvb, offset, 2, ENC_BIG_ENDIAN);
1261 offset++;
1263 proto_tree_add_item(splice_info_tree, hf_splice_command_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1264 offset += 2;
1266 proto_tree_add_item(splice_info_tree, hf_splice_command_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1267 offset++;
1269 /* Extract the splice command payload for later use. */
1270 command_tvb = tvb_new_subset_length(tvb, offset, command_length);
1271 offset += command_length;
1273 /* Process the descriptor loop. */
1274 proto_tree_add_item(splice_info_tree, hf_descriptor_loop_length, tvb, offset, 2, ENC_BIG_ENDIAN);
1275 offset += 2;
1277 /* Explain each descriptor. */
1278 for (i = 0, descriptor_offset = offset;
1279 descriptor_offset < offset + descriptor_loop_length;
1280 ++i) {
1281 dissected_length = dissect_scte35_splice_descriptor( tvb_new_subset_remaining(tvb, descriptor_offset),
1282 pinfo, splice_info_tree, i);
1284 /* Escalate failure. */
1285 if (dissected_length < 1)
1286 return offset;
1287 descriptor_offset += dissected_length;
1289 offset += descriptor_loop_length;
1291 /* Explain the packet footer. */
1292 if (encrypted_packet) {
1293 proto_tree_add_item(splice_info_tree, hf_e_crc32, tvb, offset, 4, ENC_BIG_ENDIAN);
1294 offset += 4;
1296 proto_tree_add_item(splice_info_tree, hf_crc32, tvb, offset, 4, ENC_BIG_ENDIAN);
1297 offset += 4;
1299 /* We've reached the end. Run a child dissector for the splice command. */
1300 dissector_try_uint_with_data(scte35_cmd_dissector_table, command_type, command_tvb, pinfo, tree,
1301 false, NULL);
1303 return offset;
1307 void
1308 proto_register_scte35(void)
1310 static int *ett[] = {
1311 &ett_scte35_splice_info_section,
1314 static hf_register_info hf[] = {
1315 /* MPEG Section Table Headers. Field members taken from mpeg-sect.c. */
1316 {&hf_table_id,
1317 {"Table ID", "scte35.tid", FT_UINT8, BASE_HEX,
1318 NULL, 0, NULL, HFILL}},
1319 {&hf_section_syntax_indicator,
1320 {"Section Syntax Identifier", "scte35.syntax_indicator", FT_BOOLEAN,
1321 16, TFS(&tfs_section_syntax_indicator), 0x8000, NULL, HFILL }},
1322 {&hf_private_indicator,
1323 {"Private Indicator", "scte35.private", FT_BOOLEAN,
1324 16, TFS(&tfs_private_indicator), 0x4000, NULL, HFILL }},
1325 {&hf_reserved,
1326 {"Reserved", "scte35.reserved", FT_UINT16, BASE_HEX,
1327 NULL, 0x3000, NULL, HFILL }},
1328 {&hf_section_length,
1329 {"Section length", "scte35.len", FT_UINT16, BASE_DEC,
1330 NULL, 0x0FFF, NULL, HFILL}},
1332 /* SCTE35-specific headers */
1333 {&hf_protocol_version,
1334 {"Protocol Version", "scte35.protocol_version", FT_UINT8, BASE_DEC,
1335 NULL, 0, NULL, HFILL}},
1336 {&hf_encrypted_packet,
1337 {"Encrypted Packet", "scte35.encrypted_packet", FT_BOOLEAN, 40,
1338 TFS(&tfs_encrypted_packet), UINT64_C(0x8000000000), NULL, HFILL}},
1339 {&hf_encryption_algorithm,
1340 {"Encryption Algorithm", "scte35.encryption_algorithm", FT_UINT40,
1341 BASE_HEX | BASE_RANGE_STRING, RVALS(rv_encryption_algorithm),
1342 UINT64_C(0x7E00000000), NULL, HFILL}},
1343 {&hf_pts_adjustment,
1344 {"PTS Adjustment", "scte35.pts_adjustment", FT_UINT40, BASE_DEC,
1345 NULL, UINT64_C(0x1FFFFFFFF), NULL, HFILL}},
1346 {&hf_cw_index,
1347 {"Control Word Index", "scte35.cw_index", FT_UINT8, BASE_HEX,
1348 NULL, 0, NULL, HFILL}},
1349 {&hf_tier,
1350 {"Authorisation Tier", "scte35.tier", FT_UINT16, BASE_DEC,
1351 NULL, 0xFFF0, NULL, HFILL}},
1352 {&hf_splice_command_length,
1353 {"Command Length", "scte35.splice_command_length", FT_UINT16, BASE_DEC,
1354 NULL, 0x0FFF, NULL, HFILL}},
1355 {&hf_splice_command_type,
1356 {"Command Type", "scte35.splice_command_type", FT_UINT8,
1357 BASE_HEX | BASE_RANGE_STRING, RVALS(rv_splice_command_type),
1358 0, NULL, HFILL}},
1360 /* Splice command payload goes here via the dissector table. */
1362 /* Descriptor loop header. */
1363 {&hf_descriptor_loop_length,
1364 {"Descriptor Loop Length", "scte35.desc_len", FT_UINT16, BASE_DEC,
1365 NULL, 0, NULL, HFILL}},
1367 /* Descriptor loop entries. */
1368 {&hf_splice_descriptor_tag,
1369 {"Tag", "scte35.splice_descriptor.tag", FT_UINT8,
1370 BASE_HEX | BASE_RANGE_STRING, RVALS(rv_splice_descriptor_tag),
1371 0, NULL, HFILL}},
1372 {&hf_splice_descriptor_length,
1373 {"Length", "scte35.splice_descriptor.length", FT_UINT8, BASE_DEC,
1374 NULL, 0, NULL, HFILL}},
1375 {&hf_splice_descriptor_identifier,
1376 {"Descriptor ID", "scte35.splice_descriptor.identifier", FT_UINT32,
1377 BASE_HEX, NULL, 0, NULL, HFILL}},
1379 /* avail_descriptor */
1380 {&hf_descriptor_provider_avail_id,
1381 {"Provider Avail ID", "scte35.splice_descriptor.provider_avail_id",
1382 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL}},
1384 /* dtmf_descriptor */
1385 {&hf_descriptor_preroll,
1386 {"Preroll", "scte35.splice_descriptor.preroll",
1387 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
1388 {&hf_descriptor_dtmf_count,
1389 {"DTMF Count", "scte35.splice_descriptor.dtmf_count",
1390 FT_UINT8, BASE_DEC, NULL, 0xE0, NULL, HFILL}},
1391 {&hf_descriptor_dtmf_reserved,
1392 {"DTMF Reserved", "scte35.splice_descriptor.dtmf_reserved",
1393 FT_UINT8, BASE_HEX, NULL, 0x1F, NULL, HFILL}},
1394 {&hf_descriptor_dtmf,
1395 {"DTMF", "scte35.splice_descriptor.dtmf",
1396 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}},
1398 /* segmentation_descriptor */
1399 {&hf_descriptor_event_id,
1400 {"Segmentation Event ID", "scte35.splice_descriptor.event_id",
1401 FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL}},
1402 {&hf_descriptor_cancel_indicator,
1403 {"Cancel Indicator", "scte35.splice_descriptor.cancel_indicator",
1404 FT_BOOLEAN, 8, TFS(&tfs_descriptor_cancel_indicator), 0x80, NULL, HFILL}},
1405 {&hf_descriptor_reserved0,
1406 {"Reserved", "scte35.splice_descriptor.reserved0",
1407 FT_UINT8, BASE_HEX, NULL, 0x7F, NULL, HFILL}},
1408 {&hf_descriptor_psf,
1409 {"Program Segmentation Flag", "scte35.splice_descriptor.psf",
1410 FT_BOOLEAN, 8, TFS(&tfs_descriptor_psf), 0x80, NULL, HFILL}},
1411 {&hf_descriptor_segmentation_duration_flag,
1412 {"Segmentation Duration Flag", "scte35.splice_descriptor.sdf",
1413 FT_BOOLEAN, 8, TFS(&tfs_descriptor_sdf), 0x40, NULL, HFILL}},
1414 {&hf_descriptor_delivery_not_restricted_flag,
1415 {"Delivery not Restricted", "scte35.splice_descriptor.dnr",
1416 FT_BOOLEAN, 8, TFS(&tfs_descriptor_dnr), 0x20, NULL, HFILL}},
1417 {&hf_descriptor_web_delivery_allowed_flag,
1418 {"Web Delivery Allowed", "scte35.splice_descriptor.web_delivery_allowed",
1419 FT_BOOLEAN, 8, TFS(&tfs_descriptor_web), 0x10, NULL, HFILL}},
1420 {&hf_descriptor_no_regional_blackout_flag,
1421 {"No Regional Blackout", "scte35.splice_descriptor.no_regional_blackout",
1422 FT_BOOLEAN, 8, TFS(&tfs_descriptor_blackout), 0x08, NULL, HFILL}},
1423 {&hf_descriptor_archive_allow_flag,
1424 {"Archive Allowed", "scte35.splice_descriptor.archive_allowed",
1425 FT_BOOLEAN, 8, TFS(&tfs_descriptor_archive), 0x04, NULL, HFILL}},
1426 {&hf_descriptor_device_restrictions,
1427 {"Device Restrictions", "scte35.splice_descriptor.device_restrictions",
1428 FT_UINT8, BASE_HEX | BASE_RANGE_STRING,
1429 RVALS(scte35_device_restrictions), 0x03, NULL, HFILL}},
1430 {&hf_descriptor_reserved1,
1431 {"Reserved", "scte35.splice_descriptor.reserved1",
1432 FT_UINT8, BASE_HEX, NULL, 0x1F, NULL, HFILL}},
1433 {&hf_descriptor_component_count,
1434 {"Component Count", "scte35.splice_descriptor.component_count",
1435 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
1436 {&hf_descriptor_component_tag,
1437 {"Component Tag", "scte35.splice_descriptor.component.tag",
1438 FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL}},
1439 {&hf_descriptor_component_reserved,
1440 {"Reserved", "scte35.splice_descriptor.component.reserved",
1441 FT_UINT8, BASE_HEX, NULL, 0xFE, NULL, HFILL}},
1442 {&hf_descriptor_component_pts_offset,
1443 {"PTS Offset", "scte35.splice_descriptor.component.pts_offset",
1444 FT_UINT40, BASE_DEC, NULL, 0x01FFFFFFFF, NULL, HFILL}},
1445 {&hf_descriptor_segmentation_duration,
1446 {"Segmentation Duration", "scte35.splice_descriptor.segmentation_duration",
1447 FT_UINT64, BASE_DEC, NULL, 0xFFFFFFFFFF, NULL, HFILL}},
1448 {&hf_descriptor_segmentation_upid_type,
1449 {"UPID Type", "scte35.splice_descriptor.upid_type",
1450 FT_UINT8, BASE_HEX | BASE_RANGE_STRING,
1451 RVALS(scte35_segmentation_upid_type), 0, NULL, HFILL}},
1452 {&hf_descriptor_segmentation_upid_length,
1453 {"UPID Length", "scte35.splice_descriptor.upid_length",
1454 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
1455 {&hf_descriptor_segmentation_upid,
1456 {"UPID", "scte35.splice_descriptor.upid",
1457 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}},
1458 {&hf_descriptor_segmentation_type_id,
1459 {"Segmentation Type", "scte35.splice_descriptor.segmentation_type_id",
1460 FT_UINT8, BASE_HEX | BASE_RANGE_STRING,
1461 RVALS(scte35_segmentation_type_id), 0, NULL, HFILL}},
1462 {&hf_descriptor_segment_num,
1463 {"Segment Number", "scte35.splice_descriptor.segment_num",
1464 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
1465 {&hf_descriptor_segments_expected,
1466 {"Segments Expected", "scte35.splice_descriptor.segments_expected",
1467 FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL}},
1469 /* Optional alignment padding, encrypted CRC32 suffix. */
1470 {&hf_e_crc32,
1471 {"Encrypted CRC32", "scte35.ecrc32", FT_UINT32, BASE_HEX,
1472 NULL, 0, NULL, HFILL}},
1474 /* MPEG Section table CRC suffix */
1475 {&hf_crc32,
1476 {"CRC32", "scte35.crc", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL}},
1479 /* Allocate a protocol number. */
1480 proto_scte35 = proto_register_protocol("SCTE-35 Splice Information", "SCTE 35", "scte35");
1481 scte35_handle = register_dissector("scte35", dissect_scte35_splice_info, proto_scte35);
1483 /* Register groups and fields. */
1484 proto_register_subtree_array(ett, array_length(ett));
1485 proto_register_field_array(proto_scte35, hf, array_length(hf));
1487 /* Allow other protocols to discriminate against the splice command type
1488 * to further dissect the payload.
1490 scte35_cmd_dissector_table = register_dissector_table(
1491 "scte35.splice_command_type", "SCTE-35 Command", proto_scte35, FT_UINT8,
1492 BASE_HEX);
1495 void
1496 proto_reg_handoff_scte35(void)
1498 /* Invoke the splice_info_section parser for a section table with ID 0xFC */
1499 dissector_add_uint("mpeg_sect.tid", SCTE35_TABLE_ID, scte35_handle);
1503 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1505 * Local variables:
1506 * c-basic-offset: 4
1507 * tab-width: 8
1508 * indent-tabs-mode: nil
1509 * End:
1511 * vi: set shiftwidth=4 tabstop=8 expandtab:
1512 * :indentSize=4:tabSize=8:noTabs=true: