Bug Summary

File:builds/wireshark/wireshark/epan/dissectors/packet-smpte-291-vanc.c
Warning:line 2088, column 13
Value stored to 'offset' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name packet-smpte-291-vanc.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-22/lib/clang/22 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/epan -D CARES_NO_DEPRECATED -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-22/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu17 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /builds/wireshark/wireshark/sbout/2026-09-19-100317-3660-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-smpte-291-vanc.c
1/* packet-smpte-291-vanc.c
2 * SMPTE ST 291 ancillary-data parsing and built-in VANC application dissectors.
3 *
4 * Built-in application payloads implemented in this source file:
5 * SMPTE ST 12-2, SMPTE ST 2010, SMPTE ST 2016-3, SMPTE ST 2031,
6 * SMPTE ST 334-2, and Free TV Australia OP-47 / SMPTE RDD 8.
7 *
8 * Copyright (c) 2026, Devin Heitmueller <dheitmueller@ltnglobal.com>
9 *
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
13 *
14 * SPDX-License-Identifier: GPL-2.0-or-later
15 */
16
17#include "config.h"
18
19#include <string.h>
20
21#include <epan/expert.h>
22#include <epan/packet.h>
23#include <epan/reassemble.h>
24#include <epan/tfs.h>
25#include <wsutil/array.h>
26#include <wsutil/bitswap.h>
27
28#include "packet-smpte-291-vanc.h"
29
30/* Protocol, field, subtree, expert, and dissector declarations */
31
32/* SMPTE ST 291 common declarations */
33static int proto_st291;
34static int hf_st291_did;
35static int hf_st291_sdid;
36static int hf_st291_dbn;
37static dissector_table_t st291_did_sdid_table;
38
39typedef struct {
40 tvbuff_t *full_tvb;
41 tvbuff_t *byte_tvb;
42} st291_vanc_udw_t;
43
44/* SMPTE ST 12-2 declarations */
45static int proto_st12_2;
46static int hf_st12_2_timecode;
47static int hf_st12_2_frame_units;
48static int hf_st12_2_frame_tens;
49static int hf_st12_2_second_units;
50static int hf_st12_2_second_tens;
51static int hf_st12_2_minute_units;
52static int hf_st12_2_minute_tens;
53static int hf_st12_2_hour_units;
54static int hf_st12_2_hour_tens;
55static int hf_st12_2_binary_group_1;
56static int hf_st12_2_binary_group_2;
57static int hf_st12_2_binary_group_3;
58static int hf_st12_2_binary_group_4;
59static int hf_st12_2_binary_group_5;
60static int hf_st12_2_binary_group_6;
61static int hf_st12_2_binary_group_7;
62static int hf_st12_2_binary_group_8;
63static int hf_st12_2_flag_bit_10;
64static int hf_st12_2_flag_bit_11;
65static int hf_st12_2_flag_bit_27;
66static int hf_st12_2_flag_bit_43;
67static int hf_st12_2_flag_bit_58;
68static int hf_st12_2_flag_bit_59;
69static int hf_st12_2_payload_type;
70static int hf_st12_2_vitc;
71static int hf_st12_2_vitc_line_sel;
72static int hf_st12_2_vitc_line_dup;
73static int hf_st12_2_vitc_validity;
74static int hf_st12_2_vitc_process;
75static int ett_st12_2;
76static int ett_st12_2_timecode;
77static int ett_st12_2_vitc;
78static expert_field ei_st12_2_bad_length = EI_INIT{0, 0};
79static dissector_handle_t st12_2_handle;
80
81/* SMPTE ST 2010 declarations */
82static int proto_st2010;
83static int hf_st2010_payload_descriptor;
84static int hf_st2010_reserved;
85static int hf_st2010_version;
86static int hf_st2010_continued_pkt;
87static int hf_st2010_following_pkt;
88static int hf_st2010_duplicate_msg;
89static int hf_st2010_payload;
90static int hf_st2010_fragments;
91static int hf_st2010_fragment;
92static int hf_st2010_fragment_overlap;
93static int hf_st2010_fragment_overlap_conflict;
94static int hf_st2010_fragment_multiple_tails;
95static int hf_st2010_fragment_too_long_fragment;
96static int hf_st2010_fragment_error;
97static int hf_st2010_fragment_count;
98static int hf_st2010_reassembled_in;
99static int hf_st2010_reassembled_length;
100static int hf_st2010_reassembled_data;
101static int ett_st2010;
102static int ett_st2010_fragment;
103static int ett_st2010_fragments;
104static expert_field ei_st2010_bad_version = EI_INIT{0, 0};
105static expert_field ei_st2010_reserved_bits = EI_INIT{0, 0};
106static expert_field ei_st2010_orphan_fragment = EI_INIT{0, 0};
107static expert_field ei_st2010_overlapping_message = EI_INIT{0, 0};
108static expert_field ei_st2010_empty_payload = EI_INIT{0, 0};
109static dissector_handle_t st2010_handle;
110static dissector_table_t st2010_payload_table;
111static reassembly_table st2010_reassembly_table;
112
113/* SMPTE ST 2016-3 declarations */
114static int proto_st2016_3;
115static int hf_st2016_3_afd_byte;
116static int hf_st2016_3_afd_code;
117static int hf_st2016_3_afd_ar;
118static int hf_st2016_3_afd_reserved;
119static int hf_st2016_3_reserved_1;
120static int hf_st2016_3_reserved_2;
121static int hf_st2016_3_bar_flags;
122static int hf_st2016_3_bar_top;
123static int hf_st2016_3_bar_bottom;
124static int hf_st2016_3_bar_left;
125static int hf_st2016_3_bar_right;
126static int hf_st2016_3_bar_reserved;
127static int hf_st2016_3_bar_value_1;
128static int hf_st2016_3_bar_value_1_marker;
129static int hf_st2016_3_bar_value_1_data;
130static int hf_st2016_3_bar_value_2;
131static int hf_st2016_3_bar_value_2_marker;
132static int hf_st2016_3_bar_value_2_data;
133static int hf_st2016_3_bar_value_1_meaning;
134static int hf_st2016_3_bar_value_2_meaning;
135static int ett_st2016_3;
136static int ett_st2016_3_afd;
137static int ett_st2016_3_bar_flags;
138static int ett_st2016_3_bar_value_1;
139static int ett_st2016_3_bar_value_2;
140static expert_field ei_st2016_3_bad_length;
141static expert_field ei_st2016_3_afd_reserved;
142static expert_field ei_st2016_3_reserved_udw;
143static expert_field ei_st2016_3_bar_reserved;
144static expert_field ei_st2016_3_bar_flags_invalid;
145static expert_field ei_st2016_3_bar_marker;
146static dissector_handle_t st2016_3_handle;
147
148/* SMPTE ST 334-2 declarations */
149static int proto_st334_2;
150static int hf_st334_2_cdp_identifier;
151static int hf_st334_2_cdp_length;
152static int hf_st334_2_frame_rate;
153static int hf_st334_2_header_reserved;
154static int hf_st334_2_time_code_present;
155static int hf_st334_2_ccdata_present;
156static int hf_st334_2_svcinfo_present;
157static int hf_st334_2_svc_info_start;
158static int hf_st334_2_svc_info_change;
159static int hf_st334_2_svc_info_complete;
160static int hf_st334_2_caption_service_active;
161static int hf_st334_2_header_reserved_bit;
162static int hf_st334_2_header_sequence_counter;
163static int hf_st334_2_section_id;
164static int hf_st334_2_timecode;
165static int hf_st334_2_tc_field_flag;
166static int hf_st334_2_drop_frame_flag;
167static int hf_st334_2_cc_count;
168static int hf_st334_2_cc_marker_bits;
169static int hf_st334_2_cc_valid;
170static int hf_st334_2_cc_type;
171static int hf_st334_2_cc_data_1;
172static int hf_st334_2_cc_data_2;
173static int hf_st334_2_dtvcc_data;
174static int hf_st334_2_svc_reserved;
175static int hf_st334_2_svc_info_start_section;
176static int hf_st334_2_svc_info_change_section;
177static int hf_st334_2_svc_info_complete_section;
178static int hf_st334_2_svc_count;
179static int hf_st334_2_csn_reserved;
180static int hf_st334_2_csn_size;
181static int hf_st334_2_csn_reserved_2;
182static int hf_st334_2_caption_service_number;
183static int hf_st334_2_service_data;
184static int hf_st334_2_service_language;
185static int hf_st334_2_service_digital_cc;
186static int hf_st334_2_service_digital_reserved;
187static int hf_st334_2_service_line21_reserved;
188static int hf_st334_2_service_line21_field;
189static int hf_st334_2_service_descriptor_number;
190static int hf_st334_2_service_easy_reader;
191static int hf_st334_2_service_wide_aspect_ratio;
192static int hf_st334_2_service_reserved_14;
193static int hf_st334_2_future_length;
194static int hf_st334_2_future_data;
195static int hf_st334_2_footer_sequence_counter;
196static int hf_st334_2_packet_checksum;
197static int hf_st334_2_checksum_calculated;
198static int ett_st334_2;
199static int ett_st334_2_header;
200static int ett_st334_2_timecode;
201static int ett_st334_2_ccdata;
202static int ett_st334_2_cc_construct;
203static int ett_st334_2_svcinfo;
204static int ett_st334_2_service;
205static int ett_st334_2_service_data;
206static int ett_st334_2_future;
207static int ett_st334_2_footer;
208static expert_field ei_st334_2_bad_identifier;
209static expert_field ei_st334_2_bad_length;
210static expert_field ei_st334_2_bad_reserved;
211static expert_field ei_st334_2_bad_section_order;
212static expert_field ei_st334_2_duplicate_section;
213static expert_field ei_st334_2_missing_section;
214static expert_field ei_st334_2_cc_count;
215static expert_field ei_st334_2_bad_marker;
216static expert_field ei_st334_2_sequence_mismatch;
217static expert_field ei_st334_2_bad_checksum;
218static expert_field ei_st334_2_truncated;
219static dissector_handle_t st334_2_handle;
220
221/* SMPTE ST 2031 declarations */
222static int proto_st2031;
223static int hf_st2031_data_identifier;
224static int hf_st2031_data_unit_id;
225static int hf_st2031_data_unit_length;
226static int hf_st2031_field_parity;
227static int hf_st2031_line_offset;
228static int hf_st2031_framing_code;
229static int hf_st2031_magazine_hamming;
230static int hf_st2031_magazine;
231static int hf_st2031_packet_number_hamming;
232static int hf_st2031_packet_number;
233static int hf_st2031_page_units_hamming;
234static int hf_st2031_page_units;
235static int hf_st2031_page_tens_hamming;
236static int hf_st2031_page_tens;
237static int hf_st2031_data_string;
238static int hf_st2031_textdata_array;
239static int hf_st2031_erase_page;
240static int hf_st2031_newsflash;
241static int hf_st2031_subtitle;
242static int hf_st2031_suppress_header;
243static int hf_st2031_update_indicator;
244static int hf_st2031_interrupted_sequence;
245static int hf_st2031_inhibit_display;
246static int hf_st2031_magazine_serial;
247static int hf_st2031_character_set;
248static int hf_st2031_tt_control;
249static int ett_st2031;
250static dissector_handle_t st2031_handle;
251
252/* OP-47 / SMPTE RDD 8 declarations */
253static int proto_op47;
254static int hf_op47_sdp_identifier;
255static int hf_op47_sdp_length;
256static int hf_op47_sdp_format_code;
257static int hf_op47_sdp_adaption_header;
258static int hf_op47_sdp_pkt_desc_b;
259static int hf_op47_clock_runin;
260static int hf_op47_framing_code;
261static int hf_op47_magazine_hamming;
262static int hf_op47_magazine;
263static int hf_op47_packet_number_hamming;
264static int hf_op47_packet_number;
265static int hf_op47_page_units_hamming;
266static int hf_op47_page_units;
267static int hf_op47_page_tens_hamming;
268static int hf_op47_page_tens;
269static int hf_op47_data_string;
270static int hf_op47_textdata_array;
271static int hf_op47_erase_page;
272static int hf_op47_newsflash;
273static int hf_op47_subtitle;
274static int hf_op47_suppress_header;
275static int hf_op47_update_indicator;
276static int hf_op47_interrupted_sequence;
277static int hf_op47_inhibit_display;
278static int hf_op47_magazine_serial;
279static int hf_op47_character_set;
280static int hf_op47_tt_control;
281static int ett_op47;
282static int ett_op47_wst;
283static dissector_handle_t op47_handle;
284
285/* ST 291 Type 2 DID/SDID keys used by the built-in VANC dissectors. */
286#define ST12_2_DID_SDID_KEY0x6060 0x6060
287#define ST2010_DID_SDID_KEY0x4107 0x4107
288#define ST2016_3_DID_SDID_KEY0x4105 0x4105
289#define ST334_2_DID_SDID_KEY0x6101 0x6101
290#define ST334_2_CDP_IDENTIFIER0x9669 0x9669
291#define ST2031_DID_SDID_KEY0x4108 0x4108
292#define OP47_DID_SDID_KEY0x4302 0x4302
293
294#define ST2010_PAYLOAD_SCTE1040 0
295/*
296 * SMPTE ST 291-1 ancillary-data core and DID/SDID dispatch
297 */
298
299
300/*
301 * Registered SMPTE ST 291 DID/SDID assignments.
302 *
303 * SMPTE ST 291-1:2011, Sec. 4 assigns DID values through the SMPTE
304 * Registration Authority; Sec. 5.1 defines Type 1 versus Type 2 packets.
305 *
306 * Source: SMPTE Registration Authority, "Data Identification Word
307 * Assignments for Registered DIDs", downloaded from:
308 * https://www.smpte-ra.org/smpte-ancillary-data-smpte-st-291
309 *
310 * The register contained 81 assignments when reviewed on 2026-09-05.
311 * Keep this table synchronized with the SMPTE RA register rather than with
312 * transport-specific dissectors such as ST 2110-40 or ST 2038.
313 */
314typedef struct {
315 uint8_t did;
316 uint8_t sdid;
317 const char *description;
318} st291_did_sdid_entry_t;
319
320typedef struct {
321 uint8_t did;
322 const char *description;
323} st291_did_entry_t;
324
325/* Type 2 identities: SMPTE ST 291-1:2011, Sec. 5.1 uses DID + SDID. */
326static const st291_did_sdid_entry_t st291_did_sdid_assignments[] = {
327 { 0x08, 0x08, "SMPTE ST 353: MPEG recoding data, VANC space" },
328 { 0x08, 0x0c, "SMPTE ST 353: MPEG recoding data, HANC space" },
329 { 0x40, 0x01, "SMPTE ST 305: SDTI transport in active frame space" },
330 { 0x40, 0x02, "SMPTE ST 348: HD-SDTI transport in active frame space" },
331 { 0x40, 0x04, "SMPTE ST 427: Link Encryption Message 1" },
332 { 0x40, 0x05, "SMPTE ST 427: Link Encryption Message 2" },
333 { 0x40, 0x06, "SMPTE ST 427: Link Encryption Metadata" },
334 { 0x41, 0x01, "SMPTE ST 352: Payload Identification, HANC space" },
335 { 0x41, 0x05, "SMPTE ST 2016-3: AFD and Bar Data" },
336 { 0x41, 0x06, "SMPTE ST 2016-4: Pan-Scan Data" },
337 { 0x41, 0x07, "SMPTE ST 2010: ANSI/SCTE 104 messages" },
338 { 0x41, 0x08, "SMPTE ST 2031: DVB/SCTE VBI data" },
339 { 0x41, 0x09, "SMPTE ST 2056: MPEG TS packets in VANC" },
340 { 0x41, 0x0a, "SMPTE ST 2068: Stereoscopic 3D Frame Compatible Packing and Signaling" },
341 { 0x41, 0x0b, "SMPTE ST 2064-2: Lip Sync data as specified by ST 2064-1" },
342 { 0x41, 0x0c, "SMPTE ST 2108-1: Extended HDR/WCG for SDI" },
343 { 0x41, 0x0d, "SMPTE ST 2108-2: Vertical Ancillary Data Mapping of KLV Formatted HDR/WCG Metadata" },
344 { 0x43, 0x01, "ITU-R BT.1685: Structure of inter-station control data conveyed by ancillary data packets" },
345 { 0x43, 0x02, "SMPTE RDD 8: Subtitling Distribution packet (SDP)" },
346 { 0x43, 0x03, "SMPTE RDD 8: Transport of ANC packet in an ANC Multipacket" },
347 { 0x43, 0x04, "ARIB TR-B29: Metadata to monitor errors of audio and video signals on a broadcasting chain" },
348 { 0x43, 0x05, "SMPTE RDD 18: Acquisition Metadata Sets for Video Camera Parameters" },
349 { 0x44, 0x04, "SMPTE RP 214: KLV Metadata transport in VANC space" },
350 { 0x44, 0x14, "SMPTE RP 214: KLV Metadata transport in HANC space" },
351 { 0x44, 0x44, "SMPTE RP 223: Packing UMID and Program Identification Label Data into ST 291 ancillary data packets" },
352 { 0x45, 0x01, "SMPTE ST 2020-1: Compressed Audio Metadata" },
353 { 0x45, 0x02, "SMPTE ST 2020-1: Compressed Audio Metadata" },
354 { 0x45, 0x03, "SMPTE ST 2020-1: Compressed Audio Metadata" },
355 { 0x45, 0x04, "SMPTE ST 2020-1: Compressed Audio Metadata" },
356 { 0x45, 0x05, "SMPTE ST 2020-1: Compressed Audio Metadata" },
357 { 0x45, 0x06, "SMPTE ST 2020-1: Compressed Audio Metadata" },
358 { 0x45, 0x07, "SMPTE ST 2020-1: Compressed Audio Metadata" },
359 { 0x45, 0x08, "SMPTE ST 2020-1: Compressed Audio Metadata" },
360 { 0x45, 0x09, "SMPTE ST 2020-1: Compressed Audio Metadata" },
361 { 0x46, 0x01, "SMPTE ST 2051: Two Frame Marker in HANC" },
362 { 0x50, 0x01, "SMPTE RDD 8: WSS data" },
363 { 0x51, 0x01, "SMPTE RP 215: Film Codes in VANC space" },
364 { 0x60, 0x60, "SMPTE ST 12-2: Ancillary Time Code" },
365 { 0x60, 0x61, "SMPTE ST 12-3: Time Code for High Frame Rate Signals" },
366 { 0x60, 0x62, "SMPTE ST 2103: Generic Time Label" },
367 { 0x61, 0x01, "SMPTE ST 334-1: EIA 708B Data mapping into VANC space" },
368 { 0x61, 0x02, "SMPTE ST 334-1: EIA 608 Data mapping into VANC space" },
369 { 0x62, 0x01, "SMPTE RP 207: Program Description in VANC space" },
370 { 0x62, 0x02, "SMPTE ST 334-1: Data broadcast (DTV) in VANC space" },
371 { 0x62, 0x03, "SMPTE RP 208: VBI Data in VANC space" },
372 { 0x64, 0x64, "SMPTE RP 196 (withdrawn): Time Code in HANC space" },
373 { 0x64, 0x7f, "SMPTE RP 196 (withdrawn): VITC in HANC space" },
374};
375
376/* Type 1 identities: SMPTE ST 291-1:2011, Sec. 5.1 uses DID + DBN. */
377static const st291_did_entry_t st291_did_assignments[] = {
378 { 0x00, "SMPTE ST 291: Undefined data deleted (deprecated)" },
379 { 0x80, "SMPTE ST 291: Packet marked for deletion" },
380 { 0x84, "SMPTE ST 291: End packet deleted (deprecated)" },
381 { 0x88, "SMPTE ST 291: Start packet deleted (deprecated)" },
382 { 0xa0, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 8 Control packet" },
383 { 0xa1, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 7 Control packet" },
384 { 0xa2, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 6 Control packet" },
385 { 0xa3, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 5 Control packet" },
386 { 0xa4, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 8" },
387 { 0xa5, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 7" },
388 { 0xa6, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 6" },
389 { 0xa7, "SMPTE ST 299-2: Audio data in HANC space (3G), Group 5" },
390 { 0xe0, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
391 { 0xe1, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
392 { 0xe2, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
393 { 0xe3, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
394 { 0xe4, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
395 { 0xe5, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
396 { 0xe6, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
397 { 0xe7, "SMPTE ST 299-1: Audio data in HANC space (HDTV)" },
398 { 0xec, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
399 { 0xed, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
400 { 0xee, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
401 { 0xef, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
402 { 0xf0, "SMPTE ST 315: Camera position (HANC or VANC space)" },
403 { 0xf4, "SMPTE RP 165: Error Detection and Handling (HANC space)" },
404 { 0xf8, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
405 { 0xf9, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
406 { 0xfa, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
407 { 0xfb, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
408 { 0xfc, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
409 { 0xfd, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
410 { 0xfe, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
411 { 0xff, "SMPTE ST 272: Audio data in HANC space (SDTV)" },
412};
413
414static const char *
415st291_lookup_did(uint8_t did)
416{
417 unsigned i;
418
419 for (i = 0; i < array_length(st291_did_assignments)(sizeof (st291_did_assignments) / sizeof (st291_did_assignments
)[0])
; i++) {
420 if (st291_did_assignments[i].did == did)
421 return st291_did_assignments[i].description;
422 }
423 return NULL((void*)0);
424}
425
426static const char *
427st291_lookup_did_sdid(uint8_t did, uint8_t sdid)
428{
429 unsigned i;
430
431 for (i = 0; i < array_length(st291_did_sdid_assignments)(sizeof (st291_did_sdid_assignments) / sizeof (st291_did_sdid_assignments
)[0])
; i++) {
432 if (st291_did_sdid_assignments[i].did == did &&
433 st291_did_sdid_assignments[i].sdid == sdid)
434 return st291_did_sdid_assignments[i].description;
435 }
436 return NULL((void*)0);
437}
438
439static bool_Bool
440st291_id_word_parity_ok(uint16_t word)
441{
442 unsigned ones = 0;
443 unsigned bit;
444 uint8_t data = word & 0x00ff;
445 unsigned b8 = (word >> 8) & 1U;
446 unsigned b9 = (word >> 9) & 1U;
447
448 for (bit = 0; bit < 8; bit++)
449 ones += (data >> bit) & 1U;
450
451 return (((ones + b8) & 1U) == 0) && (b9 == (b8 ^ 1U));
452}
453
454bool_Bool
455st291_vanc_packet_from_words(tvbuff_t *parent_tvb, packet_info *pinfo,
456 const uint16_t *words, unsigned word_count,
457 st291_vanc_packet_t *packet)
458{
459 uint16_t *normalized_words;
460 uint8_t *packed_data;
461 unsigned expected_words;
462 unsigned packed_length;
463 unsigned i;
464
465 DISSECTOR_ASSERT(parent_tvb != NULL)((void) ((parent_tvb != ((void*)0)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-smpte-291-vanc.c"
, 465, "parent_tvb != ((void*)0)"))))
;
466 DISSECTOR_ASSERT(pinfo != NULL)((void) ((pinfo != ((void*)0)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-smpte-291-vanc.c"
, 466, "pinfo != ((void*)0)"))))
;
467 DISSECTOR_ASSERT(words != NULL || word_count == 0)((void) ((words != ((void*)0) || word_count == 0) ? (void)0 :
(proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-smpte-291-vanc.c", 467, "words != ((void*)0) || word_count == 0"
))))
;
468 DISSECTOR_ASSERT(packet != NULL)((void) ((packet != ((void*)0)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-smpte-291-vanc.c"
, 468, "packet != ((void*)0)"))))
;
469
470 memset(packet, 0, sizeof(*packet));
471 if (word_count < 4)
472 return false0;
473
474 expected_words = 4U + (words[2] & 0x00ff);
475 if (word_count < expected_words)
476 return false0;
477
478 normalized_words = wmem_alloc_array(pinfo->pool, uint16_t, expected_words)((uint16_t*)wmem_alloc((pinfo->pool), (((((expected_words)
) <= 0) || ((size_t)sizeof(uint16_t) > (9223372036854775807L
/ (size_t)((expected_words))))) ? 0 : (sizeof(uint16_t) * ((
expected_words))))))
;
479 for (i = 0; i < expected_words; i++)
480 normalized_words[i] = words[i] & 0x03ff;
481
482 packet->parent_tvb = parent_tvb;
483 packet->words = normalized_words;
484 packet->word_count = expected_words;
485 packet->did = normalized_words[0] & 0x00ff;
486 packet->sdid_or_dbn = normalized_words[1] & 0x00ff;
487 packet->data_count = normalized_words[2] & 0x00ff;
488 packet->checksum = normalized_words[3 + packet->data_count];
489 packet->did_parity_ok = st291_id_word_parity_ok(normalized_words[0]);
490 packet->second_word_parity_ok = st291_id_word_parity_ok(normalized_words[1]);
491 packet->data_count_parity_ok = st291_id_word_parity_ok(normalized_words[2]);
492
493 packet->checksum_calculated = 0;
494 for (i = 0; i < 3U + packet->data_count; i++) {
495 packet->checksum_calculated =
496 (packet->checksum_calculated + (normalized_words[i] & 0x01ff)) &
497 0x01ff;
498 }
499 if ((packet->checksum_calculated & 0x0100) == 0)
500 packet->checksum_calculated |= 0x0200;
501 packet->checksum_ok = packet->checksum == packet->checksum_calculated;
502
503 /* Word-oriented transports do not necessarily have a contiguous source
504 * range (for example, one component of an interleaved SDI raster). Build
505 * a canonical packed representation so the shared renderer can still
506 * display the logical 10-bit UDW sequence. */
507 if (packet->data_count != 0) {
508 packed_length = (packet->data_count * 10 + 7) / 8;
509 packed_data = wmem_alloc0(pinfo->pool, packed_length);
510 for (i = 0; i < packet->data_count; i++) {
511 uint16_t word = normalized_words[3 + i];
512 unsigned bit;
513
514 for (bit = 0; bit < 10; bit++) {
515 if ((word & (1U << (9 - bit))) != 0) {
516 unsigned packed_bit = i * 10 + bit;
517 packed_data[packed_bit / 8] |= 1U << (7 - packed_bit % 8);
518 }
519 }
520 }
521 packet->packed_udw_tvb = tvb_new_child_real_data(parent_tvb,
522 packed_data,
523 packed_length,
524 packed_length);
525 }
526 return true1;
527}
528
529bool_Bool
530st291_vanc_packet_from_packed(tvbuff_t *tvb, packet_info *pinfo,
531 unsigned bit_offset, unsigned available_bits,
532 st291_vanc_packet_t *packet)
533{
534 uint16_t header_words[3];
535 uint16_t *words;
536 unsigned required_bits;
537 unsigned udw_bit_offset;
538 unsigned word_count;
539 unsigned byte_offset;
540 unsigned byte_length;
541 unsigned i;
542
543 DISSECTOR_ASSERT(tvb != NULL)((void) ((tvb != ((void*)0)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-smpte-291-vanc.c"
, 543, "tvb != ((void*)0)"))))
;
544 DISSECTOR_ASSERT(pinfo != NULL)((void) ((pinfo != ((void*)0)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-smpte-291-vanc.c"
, 544, "pinfo != ((void*)0)"))))
;
545 DISSECTOR_ASSERT(packet != NULL)((void) ((packet != ((void*)0)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-smpte-291-vanc.c"
, 545, "packet != ((void*)0)"))))
;
546
547 memset(packet, 0, sizeof(*packet));
548 if (available_bits < 30)
549 return false0;
550
551 for (i = 0; i < array_length(header_words)(sizeof (header_words) / sizeof (header_words)[0]); i++)
552 header_words[i] = tvb_get_bits16(tvb, bit_offset + i * 10, 10,
553 ENC_BIG_ENDIAN0x00000000);
554
555 word_count = 4U + (header_words[2] & 0x00ff);
556 required_bits = word_count * 10;
557 if (required_bits > available_bits) {
558 /* Preserve the decoded header so the transport can distinguish a
559 * truncated ST 291 header from a complete header whose declared
560 * packet extends beyond the transport boundary. */
561 packet->did = header_words[0] & 0x00ff;
562 packet->sdid_or_dbn = header_words[1] & 0x00ff;
563 packet->data_count = header_words[2] & 0x00ff;
564 packet->word_count = word_count;
565 return false0;
566 }
567
568 words = wmem_alloc_array(pinfo->pool, uint16_t, word_count)((uint16_t*)wmem_alloc((pinfo->pool), (((((word_count)) <=
0) || ((size_t)sizeof(uint16_t) > (9223372036854775807L /
(size_t)((word_count))))) ? 0 : (sizeof(uint16_t) * ((word_count
))))))
;
569 for (i = 0; i < word_count; i++)
570 words[i] = tvb_get_bits16(tvb, bit_offset + i * 10, 10,
571 ENC_BIG_ENDIAN0x00000000);
572
573 if (!st291_vanc_packet_from_words(tvb, pinfo, words, word_count, packet))
574 return false0;
575
576 if (packet->data_count != 0) {
577 udw_bit_offset = bit_offset + 30;
578 byte_offset = (unsigned)(udw_bit_offset / 8);
579 packet->packed_udw_bit_offset = (unsigned)(udw_bit_offset % 8);
580 byte_length = (packet->packed_udw_bit_offset +
581 packet->data_count * 10 + 7) / 8;
582 packet->packed_udw_tvb = tvb_new_subset_length(tvb, byte_offset,
583 byte_length);
584 }
585
586 return true1;
587}
588
589/* Keep the canonical full-width and compatibility byte TVBs here so every
590 * ST 291 transport presents the same subdissector interface. */
591static void
592st291_vanc_create_udw_tvbs(tvbuff_t *parent_tvb, packet_info *pinfo,
593 const uint16_t *udw_words, unsigned udw_count,
594 st291_vanc_udw_t *udw)
595{
596 uint8_t *full_data;
597 uint8_t *payload_data;
598 unsigned i;
599
600 DISSECTOR_ASSERT(udw != NULL)((void) ((udw != ((void*)0)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-smpte-291-vanc.c"
, 600, "udw != ((void*)0)"))))
;
601 DISSECTOR_ASSERT(udw_words != NULL || udw_count == 0)((void) ((udw_words != ((void*)0) || udw_count == 0) ? (void)
0 : (proto_report_dissector_bug("%s:%u: failed assertion \"%s\""
, "epan/dissectors/packet-smpte-291-vanc.c", 601, "udw_words != ((void*)0) || udw_count == 0"
))))
;
602
603 full_data = wmem_alloc(pinfo->pool, MAX(2U, udw_count * 2U)(((2U) > (udw_count * 2U)) ? (2U) : (udw_count * 2U)));
604 payload_data = wmem_alloc(pinfo->pool, MAX(1U, udw_count)(((1U) > (udw_count)) ? (1U) : (udw_count)));
605
606 for (i = 0; i < udw_count; i++) {
607 uint16_t word = udw_words[i] & 0x03ff;
608
609 full_data[i * 2] = (uint8_t)(word >> 8);
610 full_data[i * 2 + 1] = (uint8_t)word;
611 payload_data[i] = (uint8_t)word;
612 }
613
614 udw->full_tvb = tvb_new_child_real_data(parent_tvb, full_data,
615 udw_count * 2, udw_count * 2);
616 udw->byte_tvb = tvb_new_child_real_data(parent_tvb, payload_data,
617 udw_count, udw_count);
618}
619
620bool_Bool
621st291_vanc_dissect_packet(const st291_vanc_packet_t *packet,
622 packet_info *pinfo, proto_tree *tree,
623 proto_item *payload_item _U___attribute__((unused)),
624 const st291_vanc_dissector_data_t *data)
625{
626 st291_vanc_udw_t udw;
627 st291_vanc_dissector_data_t subdissector_data;
628 uint8_t dispatch_sdid;
629
630 DISSECTOR_ASSERT(packet != NULL)((void) ((packet != ((void*)0)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-smpte-291-vanc.c"
, 630, "packet != ((void*)0)"))))
;
631 DISSECTOR_ASSERT(data != NULL)((void) ((data != ((void*)0)) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion \"%s\"", "epan/dissectors/packet-smpte-291-vanc.c"
, 631, "data != ((void*)0)"))))
;
632
633 st291_vanc_create_udw_tvbs(packet->parent_tvb, pinfo, packet->words + 3,
634 packet->data_count, &udw);
635 if (packet->data_count != 0)
636 add_new_data_source(pinfo, udw.byte_tvb, "ST 291 UDW Array");
637
638 subdissector_data = *data;
639 subdissector_data.full_udw_tvb = udw.full_tvb;
640 dispatch_sdid = (packet->did & 0x80U) != 0 ? 0x00 : packet->sdid_or_dbn;
641 return dissector_try_uint_with_data(
642 st291_did_sdid_table,
643 ((uint32_t)packet->did << 8) | dispatch_sdid,
644 udw.byte_tvb, pinfo, tree, true1, &subdissector_data);
645}
646
647/* SMPTE ST 291-1:2011, Secs. 5.1-5.2 -- DID/SDID/DBN on-wire identity fields. */
648proto_item *
649st291_tree_add_did(proto_tree *tree, tvbuff_t *tvb,
650 int offset, int length, uint8_t did)
651{
652 return proto_tree_add_uint(tree, hf_st291_did, tvb, offset, length, did);
653}
654
655proto_item *
656st291_tree_add_sdid(proto_tree *tree, tvbuff_t *tvb,
657 int offset, int length, uint8_t did _U___attribute__((unused)), uint8_t sdid)
658{
659 return proto_tree_add_uint(tree, hf_st291_sdid, tvb, offset, length, sdid);
660}
661
662/* SMPTE ST 291-1:2011, Sec. 5.1: bit b7 of the DID distinguishes the
663 * Type 1 (DBN) and Type 2 (SDID) identity forms used for the lookup. */
664void
665st291_append_packet_description(proto_item *item, uint8_t did, uint8_t sdid_or_dbn)
666{
667 const char *description;
668
669 if ((did & 0x80U) != 0)
670 description = st291_lookup_did(did);
671 else
672 description = st291_lookup_did_sdid(did, sdid_or_dbn);
673
674 if (description != NULL((void*)0))
675 proto_item_append_text(item, ": %s", description);
676}
677
678proto_item *
679st291_tree_add_dbn(proto_tree *tree, tvbuff_t *tvb,
680 int offset, int length, uint8_t dbn)
681{
682 return proto_tree_add_uint(tree, hf_st291_dbn, tvb, offset, length, dbn);
683}
684
685/* SMPTE ST 291-1:2011, Secs. 5.1-5.2 define DID, SDID and DBN.
686 * The st291.did_sdid table below is Wireshark-only dispatch metadata. */
687void
688proto_register_st291(void)
689{
690 static hf_register_info hf[] = {
691 { &hf_st291_did,
692 { "Data ID", "st291.did", FT_UINT8, BASE_HEX, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
693 { &hf_st291_sdid,
694 { "Secondary Data ID", "st291.sdid", FT_UINT8, BASE_HEX, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
695 { &hf_st291_dbn,
696 { "Data Block Number", "st291.dbn", FT_UINT8, BASE_HEX, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
697 };
698
699 proto_st291 = proto_register_protocol(
700 "SMPTE ST 291 Ancillary Data", "ST 291", "st291");
701
702 proto_register_field_array(proto_st291, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
703
704 /*
705 * Public extension point for ST 291 application payload dissectors.
706 * Native and Lua dissectors can register DID/SDID keys here for
707 * additional VANC payload formats.
708 */
709 st291_did_sdid_table = register_dissector_table(
710 "st291.did_sdid", "SMPTE ST 291 DID/SDID",
711 proto_st291, FT_UINT16, BASE_HEX);
712}
713
714/*
715 * SMPTE ST 12-2 time code in ancillary data
716 */
717
718
719/* SMPTE ST 12-2:2014, Sec. 6.2.1, Table 2 -- DBB1 payload type. */
720static const value_string st12_2_payload_type_vals[] = {
721 { 0x00, "Linear time code (ATC_LTC)" },
722 { 0x01, "Vertical interval time code #1 (ATC_VITC1)" },
723 { 0x02, "Vertical interval time code #2 (ATC_VITC2)" },
724 { 0x03, "User defined" },
725 { 0x04, "User defined" },
726 { 0x05, "User defined" },
727 { 0x06, "Film data block (transferred from reader)" },
728 { 0x07, "Production data block (transferred from reader)" },
729 { 0x7D, "Video tape data block (locally generated)" },
730 { 0x7E, "Film data block (locally generated)" },
731 { 0x7F, "Production data block (locally generated)" },
732 { 0, NULL((void*)0) }
733};
734
735/* SMPTE ST 12-2:2014, Sec. 6.2.2, Tables 3 and 5 -- DBB2 validity/process bits. */
736static const value_string st12_2_vitc_validity_vals[] = {
737 { 0, "No time code error received or locally generated time code address" },
738 { 1, "Transmitted time code interpolated from previous time code (received a time code error)" },
739 { 0, NULL((void*)0) }
740};
741
742static const value_string st12_2_vitc_process_vals[] = {
743 { 0, "Binary groups in time code data stream are processed to compensate for latency" },
744 { 1, "Binary groups in time code data stream are only retransmitted (no delay compensation)" },
745 { 0, NULL((void*)0) }
746};
747
748
749/*
750 * SMPTE ST 12-2:2014, Sec. 6.3, Table 6 maps the 64 information bits
751 * defined by SMPTE ST 12-1 into UDW 1 through UDW 16. The time address
752 * is BCD; the intervening nibbles are the eight binary groups. The six
753 * remaining positions are ST 12-1 flag bits whose meaning depends on the
754 * television system/frame rate (ST 12-1:2014, Sec. 8.3 and Tables 1-3).
755 */
756static int
757dissect_st12_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
758{
759 const st291_vanc_dissector_data_t *st291_data =
760 (const st291_vanc_dissector_data_t *)data;
761 proto_tree *top_tree =
762 st291_data && st291_data->top_tree ? st291_data->top_tree : tree;
763 proto_item *ti;
764 proto_tree *st12_tree;
765 proto_tree *time_tree;
766 proto_tree *vitc_tree;
767 uint8_t dbb1 = 0;
768 uint8_t dbb2 = 0;
769 uint8_t frame_units;
770 uint8_t frame_tens;
771 uint8_t second_units;
772 uint8_t second_tens;
773 uint8_t minute_units;
774 uint8_t minute_tens;
775 uint8_t hour_units;
776 uint8_t hour_tens;
777 uint8_t frames;
778 uint8_t seconds;
779 uint8_t minutes;
780 uint8_t hours;
781 bool_Bool drop_frame;
782 char time_str[16];
783 unsigned x;
784
785 ti = proto_tree_add_item(top_tree, proto_st12_2, tvb, 0,
786 tvb_captured_length(tvb), ENC_NA0x00000000);
787 st12_tree = proto_item_add_subtree(ti, ett_st12_2);
788
789 if (tvb_captured_length(tvb) < 16) {
790 expert_add_info_format(pinfo, ti, &ei_st12_2_bad_length,
791 "ST 12-2 requires at least 16 UDW bytes; packet contains %u",
792 tvb_captured_length(tvb));
793 return tvb_captured_length(tvb);
794 }
795
796 /*
797 * SMPTE ST 12-2:2014, Sec. 6.3, Table 6 maps the 64 information
798 * bits defined by SMPTE ST 12-1 into UDW 1 through UDW 16.
799 *
800 * The time-address digits are BCD:
801 * UDW 1/3 -- frame units/tens
802 * UDW 5/7 -- second units/tens
803 * UDW 9/11 -- minute units/tens
804 * UDW 13/15 -- hour units/tens
805 *
806 * ST 12-2 Sec. 6.1.2 defines b4 as the least-significant bit of
807 * each four-bit information group.
808 */
809 frame_units = (tvb_get_uint8(tvb, 0) >> 4) & 0x0f;
810 frame_tens = (tvb_get_uint8(tvb, 2) >> 4) & 0x03;
811 second_units = (tvb_get_uint8(tvb, 4) >> 4) & 0x0f;
812 second_tens = (tvb_get_uint8(tvb, 6) >> 4) & 0x07;
813 minute_units = (tvb_get_uint8(tvb, 8) >> 4) & 0x0f;
814 minute_tens = (tvb_get_uint8(tvb, 10) >> 4) & 0x07;
815 hour_units = (tvb_get_uint8(tvb, 12) >> 4) & 0x0f;
816 hour_tens = (tvb_get_uint8(tvb, 14) >> 4) & 0x03;
817
818 frames = frame_tens * 10 + frame_units;
819 seconds = second_tens * 10 + second_units;
820 minutes = minute_tens * 10 + minute_units;
821 hours = hour_tens * 10 + hour_units;
822
823 /*
824 * SMPTE ST 12-2:2014, Sec. 6.3, Table 6 maps ST 12-1 bit 10 to
825 * UDW 3 b6. SMPTE ST 12-1:2014, Table 3 identifies bit 10 as
826 * the drop-frame flag for the applicable 30-frame systems.
827 */
828 drop_frame = (tvb_get_uint8(tvb, 2) & 0x40) != 0;
829
830 snprintf(time_str, sizeof(time_str), "%02u:%02u:%02u%c%02u",
831 hours, minutes, seconds, drop_frame ? ';' : ':', frames);
832
833 /*
834 * This row is a human-readable representation of the 64 information
835 * bits below. It spans the actual UDW bytes rather than being marked
836 * generated, so selecting it highlights the complete ATC data block.
837 */
838 ti = proto_tree_add_string(st12_tree, hf_st12_2_timecode, tvb, 0, 16, time_str);
839 time_tree = proto_item_add_subtree(ti, ett_st12_2_timecode);
840
841 /*
842 * The BCD digit fields below are the actual on-wire nibbles from
843 * ST 12-2:2014, Sec. 6.3, Table 6. Their hf masks select the
844 * corresponding b4-b7 positions in each UDW byte.
845 */
846 /*
847 * SMPTE ST 12-2:2014, Sec. 6.3, Table 6. Present the fields in
848 * UDW order so the protocol tree follows the packet layout directly.
849 */
850 /* UDW 1: units of frames */
851 proto_tree_add_item(time_tree, hf_st12_2_frame_units, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
852
853 /* UDW 2: binary group 1 */
854 proto_tree_add_item(time_tree, hf_st12_2_binary_group_1, tvb, 1, 1, ENC_BIG_ENDIAN0x00000000);
855
856 /* UDW 3: tens of frames, ST 12-1 flag bits 10 and 11 */
857 proto_tree_add_item(time_tree, hf_st12_2_frame_tens, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
858 proto_tree_add_item(time_tree, hf_st12_2_flag_bit_10, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
859 proto_tree_add_item(time_tree, hf_st12_2_flag_bit_11, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
860
861 /* UDW 4: binary group 2 */
862 proto_tree_add_item(time_tree, hf_st12_2_binary_group_2, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
863
864 /* UDW 5: units of seconds */
865 proto_tree_add_item(time_tree, hf_st12_2_second_units, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
866
867 /* UDW 6: binary group 3 */
868 proto_tree_add_item(time_tree, hf_st12_2_binary_group_3, tvb, 5, 1, ENC_BIG_ENDIAN0x00000000);
869
870 /* UDW 7: tens of seconds, ST 12-1 flag bit 27 */
871 proto_tree_add_item(time_tree, hf_st12_2_second_tens, tvb, 6, 1, ENC_BIG_ENDIAN0x00000000);
872 proto_tree_add_item(time_tree, hf_st12_2_flag_bit_27, tvb, 6, 1, ENC_BIG_ENDIAN0x00000000);
873
874 /* UDW 8: binary group 4 */
875 proto_tree_add_item(time_tree, hf_st12_2_binary_group_4, tvb, 7, 1, ENC_BIG_ENDIAN0x00000000);
876
877 /* UDW 9: units of minutes */
878 proto_tree_add_item(time_tree, hf_st12_2_minute_units, tvb, 8, 1, ENC_BIG_ENDIAN0x00000000);
879
880 /* UDW 10: binary group 5 */
881 proto_tree_add_item(time_tree, hf_st12_2_binary_group_5, tvb, 9, 1, ENC_BIG_ENDIAN0x00000000);
882
883 /* UDW 11: tens of minutes, ST 12-1 flag bit 43 */
884 proto_tree_add_item(time_tree, hf_st12_2_minute_tens, tvb, 10, 1, ENC_BIG_ENDIAN0x00000000);
885 proto_tree_add_item(time_tree, hf_st12_2_flag_bit_43, tvb, 10, 1, ENC_BIG_ENDIAN0x00000000);
886
887 /* UDW 12: binary group 6 */
888 proto_tree_add_item(time_tree, hf_st12_2_binary_group_6, tvb, 11, 1, ENC_BIG_ENDIAN0x00000000);
889
890 /* UDW 13: units of hours */
891 proto_tree_add_item(time_tree, hf_st12_2_hour_units, tvb, 12, 1, ENC_BIG_ENDIAN0x00000000);
892
893 /* UDW 14: binary group 7 */
894 proto_tree_add_item(time_tree, hf_st12_2_binary_group_7, tvb, 13, 1, ENC_BIG_ENDIAN0x00000000);
895
896 /* UDW 15: tens of hours, ST 12-1 flag bits 58 and 59 */
897 proto_tree_add_item(time_tree, hf_st12_2_hour_tens, tvb, 14, 1, ENC_BIG_ENDIAN0x00000000);
898 proto_tree_add_item(time_tree, hf_st12_2_flag_bit_58, tvb, 14, 1, ENC_BIG_ENDIAN0x00000000);
899 proto_tree_add_item(time_tree, hf_st12_2_flag_bit_59, tvb, 14, 1, ENC_BIG_ENDIAN0x00000000);
900
901 /* UDW 16: binary group 8 */
902 proto_tree_add_item(time_tree, hf_st12_2_binary_group_8, tvb, 15, 1, ENC_BIG_ENDIAN0x00000000);
903
904 /*
905 * SMPTE ST 12-2:2014, Secs. 6.2.1-6.2.2, Tables 2-3.
906 * DBB1 is assembled from b4 of UDW 1-8; DBB2 from b4 of UDW 9-16.
907 * These bytes are logical fields spread across multiple UDWs, so they
908 * are shown as generated aggregate values.
909 */
910 for (x = 0; x < 8; x++) {
911 dbb1 |= tvb_get_bits8(tvb, (x) * 8 + 4, 1) << x;
912 dbb2 |= tvb_get_bits8(tvb, (8 + x) * 8 + 4, 1) << x;
913 }
914
915 ti = proto_tree_add_uint(st12_tree, hf_st12_2_payload_type, tvb, 0, 0, dbb1);
916 proto_item_set_generated(ti);
917
918 ti = proto_tree_add_uint(st12_tree, hf_st12_2_vitc, tvb, 0, 0, dbb2);
919 proto_item_set_generated(ti);
920
921 if (dbb1 == 0x01 || dbb1 == 0x02) {
922 vitc_tree = proto_item_add_subtree(ti, ett_st12_2_vitc);
923
924 ti = proto_tree_add_uint(vitc_tree, hf_st12_2_vitc_line_sel, tvb, 0, 0, dbb2);
925 proto_item_set_generated(ti);
926 ti = proto_tree_add_uint(vitc_tree, hf_st12_2_vitc_line_dup, tvb, 0, 0, dbb2);
927 proto_item_set_generated(ti);
928 ti = proto_tree_add_uint(vitc_tree, hf_st12_2_vitc_validity, tvb, 0, 0, dbb2);
929 proto_item_set_generated(ti);
930 ti = proto_tree_add_uint(vitc_tree, hf_st12_2_vitc_process, tvb, 0, 0, dbb2);
931 proto_item_set_generated(ti);
932 }
933
934 proto_item_append_text(proto_tree_get_parent(st12_tree), ": %s", time_str);
935
936 return tvb_captured_length(tvb);
937}
938
939void
940proto_register_st12_2(void)
941{
942 static hf_register_info hf[] = {
943 { &hf_st12_2_timecode,
944 { "Time Code", "st12_2.timecode", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
945
946 /* SMPTE ST 12-2:2014, Sec. 6.3, Table 6. */
947 { &hf_st12_2_frame_units,
948 { "Frame Units", "st12_2.time.frames.units", FT_UINT8, BASE_DEC, NULL((void*)0), 0xF0, NULL((void*)0),
949 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
950 { &hf_st12_2_frame_tens,
951 { "Frame Tens", "st12_2.time.frames.tens", FT_UINT8, BASE_DEC, NULL((void*)0), 0x30, NULL((void*)0),
952 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
953 { &hf_st12_2_second_units,
954 { "Second Units", "st12_2.time.seconds.units", FT_UINT8, BASE_DEC, NULL((void*)0), 0xF0, NULL((void*)0),
955 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
956 { &hf_st12_2_second_tens,
957 { "Second Tens", "st12_2.time.seconds.tens", FT_UINT8, BASE_DEC, NULL((void*)0), 0x70, NULL((void*)0),
958 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
959 { &hf_st12_2_minute_units,
960 { "Minute Units", "st12_2.time.minutes.units", FT_UINT8, BASE_DEC, NULL((void*)0), 0xF0, NULL((void*)0),
961 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
962 { &hf_st12_2_minute_tens,
963 { "Minute Tens", "st12_2.time.minutes.tens", FT_UINT8, BASE_DEC, NULL((void*)0), 0x70, NULL((void*)0),
964 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
965 { &hf_st12_2_hour_units,
966 { "Hour Units", "st12_2.time.hours.units", FT_UINT8, BASE_DEC, NULL((void*)0), 0xF0, NULL((void*)0),
967 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
968 { &hf_st12_2_hour_tens,
969 { "Hour Tens", "st12_2.time.hours.tens", FT_UINT8, BASE_DEC, NULL((void*)0), 0x30, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
970
971 /*
972 * SMPTE ST 12-2:2014, Sec. 6.3, Table 6;
973 * SMPTE ST 12-1:2014, Table 3.
974 */
975 { &hf_st12_2_flag_bit_10,
976 { "ST 12-1 Flag Bit 10 (Drop Frame in 30-frame systems)", "st12_2.flag.bit10",
977 FT_BOOLEAN, 8, NULL((void*)0), 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
978 { &hf_st12_2_flag_bit_11,
979 { "ST 12-1 Flag Bit 11 (Color Frame in 30/25-frame systems)", "st12_2.flag.bit11",
980 FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
981 { &hf_st12_2_flag_bit_27,
982 { "ST 12-1 Flag Bit 27", "st12_2.flag.bit27", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
983 { &hf_st12_2_flag_bit_43,
984 { "ST 12-1 Flag Bit 43", "st12_2.flag.bit43", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
985 { &hf_st12_2_flag_bit_58,
986 { "ST 12-1 Flag Bit 58", "st12_2.flag.bit58", FT_BOOLEAN, 8, NULL((void*)0), 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
987 { &hf_st12_2_flag_bit_59,
988 { "ST 12-1 Flag Bit 59", "st12_2.flag.bit59", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
989
990 /* SMPTE ST 12-2:2014, Sec. 6.3, Table 6; ST 12-1 Secs. 8.4-8.5. */
991 { &hf_st12_2_binary_group_1,
992 { "Binary Group 1", "st12_2.binary_group.1", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
993 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
994 { &hf_st12_2_binary_group_2,
995 { "Binary Group 2", "st12_2.binary_group.2", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
996 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
997 { &hf_st12_2_binary_group_3,
998 { "Binary Group 3", "st12_2.binary_group.3", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
999 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1000 { &hf_st12_2_binary_group_4,
1001 { "Binary Group 4", "st12_2.binary_group.4", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
1002 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1003 { &hf_st12_2_binary_group_5,
1004 { "Binary Group 5", "st12_2.binary_group.5", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
1005 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1006 { &hf_st12_2_binary_group_6,
1007 { "Binary Group 6", "st12_2.binary_group.6", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
1008 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1009 { &hf_st12_2_binary_group_7,
1010 { "Binary Group 7", "st12_2.binary_group.7", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
1011 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1012 { &hf_st12_2_binary_group_8,
1013 { "Binary Group 8", "st12_2.binary_group.8", FT_UINT8, BASE_HEX, NULL((void*)0), 0xF0, NULL((void*)0),
1014 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1015
1016 /* SMPTE ST 12-2:2014, Sec. 6.2.1, Table 2. */
1017 { &hf_st12_2_payload_type,
1018 { "Payload Type", "st12_2.payload_type", FT_UINT8, BASE_HEX,
1019 VALS(st12_2_payload_type_vals)((0 ? (const struct _value_string*)0 : ((st12_2_payload_type_vals
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1020
1021 /* SMPTE ST 12-2:2014, Sec. 6.2.2, Tables 3-5. */
1022 { &hf_st12_2_vitc,
1023 { "VITC Data", "st12_2.vitc", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1024 { &hf_st12_2_vitc_line_sel,
1025 { "Line Select", "st12_2.vitc.line_sel", FT_UINT8, BASE_DEC, NULL((void*)0), 0x1F, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1026 { &hf_st12_2_vitc_line_dup,
1027 { "Duplication", "st12_2.vitc.line_dup", FT_UINT8, BASE_DEC, NULL((void*)0), 0x20, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1028 { &hf_st12_2_vitc_validity,
1029 { "TC Validity", "st12_2.vitc.validity", FT_UINT8, BASE_DEC,
1030 VALS(st12_2_vitc_validity_vals)((0 ? (const struct _value_string*)0 : ((st12_2_vitc_validity_vals
))))
, 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1031 { &hf_st12_2_vitc_process,
1032 { "Process Bit", "st12_2.vitc.process", FT_UINT8, BASE_DEC,
1033 VALS(st12_2_vitc_process_vals)((0 ? (const struct _value_string*)0 : ((st12_2_vitc_process_vals
))))
, 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1034 };
1035 static int *ett[] = {
1036 &ett_st12_2,
1037 &ett_st12_2_timecode,
1038 &ett_st12_2_vitc,
1039 };
1040 static ei_register_info ei[] = {
1041 { &ei_st12_2_bad_length,
1042 { "st12_2.length.bad", PI_MALFORMED0x07000000, PI_WARN0x00600000,
1043 "ST 12-2 payload contains fewer than 16 UDW bytes", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1044 };
1045 expert_module_t *expert_st12_2;
1046
1047 proto_st12_2 = proto_register_protocol(
1048 "SMPTE ST 12-2 Ancillary Time Code", "ST 12-2", "st12_2");
1049 proto_register_field_array(proto_st12_2, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
1050 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
1051
1052 expert_st12_2 = expert_register_protocol(proto_st12_2);
1053 expert_register_field_array(expert_st12_2, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
1054
1055 st12_2_handle = register_dissector("st12_2", dissect_st12_2, proto_st12_2);
1056}
1057
1058void
1059proto_reg_handoff_st12_2(void)
1060{
1061 dissector_add_uint("st291.did_sdid", ST12_2_DID_SDID_KEY0x6060, st12_2_handle);
1062}
1063
1064/*
1065 * SMPTE ST 2010 SCTE-104 mapping
1066 */
1067
1068static const fragment_items st2010_frag_items = {
1069 &ett_st2010_fragment,
1070 &ett_st2010_fragments,
1071 &hf_st2010_fragments,
1072 &hf_st2010_fragment,
1073 &hf_st2010_fragment_overlap,
1074 &hf_st2010_fragment_overlap_conflict,
1075 &hf_st2010_fragment_multiple_tails,
1076 &hf_st2010_fragment_too_long_fragment,
1077 &hf_st2010_fragment_error,
1078 &hf_st2010_fragment_count,
1079 &hf_st2010_reassembled_in,
1080 &hf_st2010_reassembled_length,
1081 &hf_st2010_reassembled_data,
1082 "ST 2010 message fragments"
1083};
1084
1085static void
1086call_st2010_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1087{
1088 if (!dissector_try_uint(st2010_payload_table, ST2010_PAYLOAD_SCTE1040,
1089 tvb, pinfo, tree)) {
1090 call_data_dissector(tvb, pinfo, tree);
1091 }
1092}
1093
1094/* SMPTE 2010-2008, Sec. 5.2, Tables 1-3; Sec. 5.4 for multi-packet reassembly. */
1095static int
1096dissect_st2010(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1097{
1098 const st291_vanc_dissector_data_t *st291_data =
1099 (const st291_vanc_dissector_data_t *)data;
1100 proto_tree *payload_tree =
1101 st291_data && st291_data->top_tree ? st291_data->top_tree : tree;
1102 const unsigned len = tvb_captured_length(tvb);
1103 uint8_t desc;
1104 unsigned version;
1105 bool_Bool continued_pkt;
1106 bool_Bool following_pkt;
1107 bool_Bool duplicate_msg;
1108 proto_item *ti;
1109 proto_tree *st2010_tree;
1110 fragment_head *fd_head;
1111 tvbuff_t *reassembled_tvb;
1112 bool_Bool save_fragmented;
1113
1114 if (len < 1)
1115 return 0;
1116
1117 desc = tvb_get_uint8(tvb, 0);
1118 version = (desc & 0x18) >> 3;
1119 continued_pkt = (desc & 0x04) != 0;
1120 following_pkt = (desc & 0x02) != 0;
1121 duplicate_msg = (desc & 0x01) != 0;
1122
1123 col_set_str(pinfo->cinfo, COL_PROTOCOL, "ST2010");
1124
1125 ti = proto_tree_add_item(tree, proto_st2010, tvb, 0, -1, ENC_NA0x00000000);
1126 st2010_tree = proto_item_add_subtree(ti, ett_st2010);
1127
1128 proto_tree_add_item(st2010_tree, hf_st2010_payload_descriptor, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
1129 proto_tree_add_item(st2010_tree, hf_st2010_reserved, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
1130 proto_tree_add_item(st2010_tree, hf_st2010_version, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
1131 proto_tree_add_item(st2010_tree, hf_st2010_continued_pkt, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
1132 proto_tree_add_item(st2010_tree, hf_st2010_following_pkt, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
1133 proto_tree_add_item(st2010_tree, hf_st2010_duplicate_msg, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
1134
1135 if ((desc & 0xE0) != 0)
1136 expert_add_info(pinfo, ti, &ei_st2010_reserved_bits);
1137 if (version != 1)
1138 expert_add_info(pinfo, ti, &ei_st2010_bad_version);
1139
1140 proto_item_append_text(ti, ": version %u%s%s%s",
1141 version,
1142 continued_pkt ? ", continued" : "",
1143 following_pkt ? ", following" : "",
1144 duplicate_msg ? ", duplicate" : "");
1145
1146 if (len <= 1) {
1147 expert_add_info(pinfo, ti, &ei_st2010_empty_payload);
1148 return len;
1149 }
1150
1151 proto_tree_add_item(st2010_tree, hf_st2010_payload, tvb, 1, -1, ENC_NA0x00000000);
1152
1153 /* Single-packet SCTE-104 message. */
1154 if (!continued_pkt && !following_pkt) {
1155 tvbuff_t *msg_tvb = tvb_new_subset_remaining(tvb, 1);
1156 call_st2010_payload(msg_tvb, pinfo, payload_tree);
1157 return len;
1158 }
1159
1160 /*
1161 * Fragmented ST 2010 message. ST 2010 supplies no fragment number or
1162 * message identifier, so fragments are appended in capture order. The
1163 * reassembly key is the enclosing flow (addresses + ports) plus ID 0.
1164 * ST 2010 permits only one complete SCTE-104 message per video frame,
1165 * so overlapping in-progress messages on one flow are malformed.
1166 */
1167 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
1168 fragment_head *active = fragment_get(&st2010_reassembly_table, pinfo, 0, NULL((void*)0));
1169
1170 if (!following_pkt) {
1171 if (active != NULL((void*)0)) {
1172 expert_add_info(pinfo, ti, &ei_st2010_overlapping_message);
1173 return len;
1174 }
1175 } else if (active == NULL((void*)0)) {
1176 expert_add_info(pinfo, ti, &ei_st2010_orphan_fragment);
1177 return len;
1178 }
1179 }
1180
1181 save_fragmented = pinfo->fragmented;
1182 pinfo->fragmented = true1;
1183 fd_head = fragment_add_seq_next(&st2010_reassembly_table,
1184 tvb, 1, pinfo, 0, NULL((void*)0),
1185 len - 1, continued_pkt);
1186
1187 reassembled_tvb = process_reassembled_data(tvb, 1, pinfo,
1188 "Reassembled SCTE-104 Message",
1189 fd_head, &st2010_frag_items,
1190 NULL((void*)0), st2010_tree);
1191 pinfo->fragmented = save_fragmented;
1192
1193 if (reassembled_tvb != NULL((void*)0))
1194 call_st2010_payload(reassembled_tvb, pinfo, payload_tree);
1195
1196 return len;
1197}
1198
1199void
1200proto_register_st2010(void)
1201{
1202 static hf_register_info hf[] = {
1203 { &hf_st2010_payload_descriptor,
1204 { "Payload Descriptor", "st2010.payload_descriptor", FT_UINT8, BASE_HEX, NULL((void*)0), 0x00,
1205 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1206 { &hf_st2010_reserved,
1207 { "Reserved", "st2010.reserved", FT_UINT8, BASE_HEX, NULL((void*)0), 0xE0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1208 { &hf_st2010_version,
1209 { "Mapping Version", "st2010.version", FT_UINT8, BASE_DEC, NULL((void*)0), 0x18, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1210 { &hf_st2010_continued_pkt,
1211 { "Continued Packet", "st2010.continued_pkt", FT_BOOLEAN, 8, NULL((void*)0), 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1212 { &hf_st2010_following_pkt,
1213 { "Following Packet", "st2010.following_pkt", FT_BOOLEAN, 8, NULL((void*)0), 0x02, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1214 { &hf_st2010_duplicate_msg,
1215 { "Duplicate Message", "st2010.duplicate_msg", FT_BOOLEAN, 8, NULL((void*)0), 0x01, NULL((void*)0),
1216 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1217 { &hf_st2010_payload,
1218 { "SCTE-104 Message Bytes", "st2010.payload", FT_BYTES, BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0),
1219 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1220
1221 { &hf_st2010_fragments,
1222
1223 { "Reassembled ST 2010 fragments", "st2010.fragments", FT_NONE, BASE_NONE, NULL((void*)0),
1224
1225 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1226 { &hf_st2010_fragment,
1227 { "ST 2010 fragment", "st2010.fragment", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0),
1228 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1229 { &hf_st2010_fragment_overlap,
1230 { "ST 2010 fragment overlap", "st2010.fragment.overlap", FT_BOOLEAN, BASE_NONE,
1231 NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1232 { &hf_st2010_fragment_overlap_conflict,
1233 { "ST 2010 fragment overlap conflict", "st2010.fragment.overlap.conflict",
1234 FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1235 { &hf_st2010_fragment_multiple_tails,
1236 { "ST 2010 multiple tail fragments", "st2010.fragment.multiple_tails", FT_BOOLEAN,
1237 BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1238 { &hf_st2010_fragment_too_long_fragment,
1239 { "ST 2010 fragment too long", "st2010.fragment.too_long_fragment", FT_BOOLEAN,
1240 BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1241 { &hf_st2010_fragment_error,
1242 { "ST 2010 reassembly error in frame", "st2010.fragment.error", FT_FRAMENUM,
1243 BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1244 { &hf_st2010_fragment_count,
1245 { "ST 2010 fragment count", "st2010.fragment.count", FT_UINT32, BASE_DEC, NULL((void*)0),
1246 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1247 { &hf_st2010_reassembled_in,
1248 { "Reassembled in", "st2010.reassembled.in", FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x00,
1249 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1250 { &hf_st2010_reassembled_length,
1251 { "Reassembled length", "st2010.reassembled.length", FT_UINT32, BASE_DEC, NULL((void*)0),
1252 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1253 { &hf_st2010_reassembled_data,
1254 { "Reassembled SCTE-104 data", "st2010.reassembled.data", FT_BYTES, BASE_NONE, NULL((void*)0),
1255 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1256 };
1257
1258 static int *ett[] = {
1259 &ett_st2010,
1260 &ett_st2010_fragment,
1261 &ett_st2010_fragments,
1262 };
1263
1264 static ei_register_info ei[] = {
1265 { &ei_st2010_bad_version,
1266 { "st2010.version.invalid", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
1267 "ST 2010 mapping version is not Version 1", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1268 { &ei_st2010_reserved_bits,
1269 { "st2010.reserved.nonzero", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
1270 "Reserved Payload Descriptor bits are non-zero", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1271 { &ei_st2010_orphan_fragment,
1272 { "st2010.fragment.orphan", PI_REASSEMBLE0x06000000, PI_WARN0x00600000,
1273 "Following ST 2010 fragment seen without a preceding first fragment", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1274 { &ei_st2010_overlapping_message,
1275 { "st2010.fragment.overlap_message", PI_REASSEMBLE0x06000000, PI_WARN0x00600000,
1276 "New ST 2010 message started while another message is still being reassembled",
1277 EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1278 { &ei_st2010_empty_payload,
1279 { "st2010.payload.empty", PI_MALFORMED0x07000000, PI_WARN0x00600000,
1280 "ST 2010 packet contains a Payload Descriptor but no SCTE-104 bytes", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1281 };
1282
1283 expert_module_t *expert;
1284
1285 proto_st2010 = proto_register_protocol("SMPTE ST 2010", "ST 2010", "st2010");
1286 proto_register_field_array(proto_st2010, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
1287 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
1288
1289 expert = expert_register_protocol(proto_st2010);
1290 expert_register_field_array(expert, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
1291
1292 reassembly_table_register(&st2010_reassembly_table,
1293 &addresses_ports_reassembly_table_functions);
1294
1295 /*
1296 * Public payload table. Key 0 is the complete SCTE-104 message. A Lua
1297 * dissector can register here after all compiled dissectors initialize.
1298 */
1299 st2010_payload_table = register_dissector_table(
1300 "st2010.payload_type", "ST 2010 Payload Type", proto_st2010, FT_UINT8, BASE_DEC);
1301
1302 st2010_handle = register_dissector("st2010", dissect_st2010, proto_st2010);
1303}
1304
1305void
1306proto_reg_handoff_st2010(void)
1307{
1308 dissector_add_uint("st291.did_sdid", ST2010_DID_SDID_KEY0x4107, st2010_handle);
1309}
1310
1311/*
1312 * SMPTE ST 2016-3 active format description and bar data
1313 */
1314
1315static const struct true_false_string st2016_3_tfs_afd_ar = {
1316 "16:9 coded frame",
1317 "4:3 coded frame"
1318};
1319
1320/* SMPTE ST 2016-1:2009, Sec. 5, Table 1 -- AFD code meaning depends on coded-frame AR. */
1321static const char *
1322st2016_3_afd_description(uint8_t afd, bool_Bool ar_16_9)
1323{
1324 static const char *const afd_4_3[16] = {
1325 "Undefined",
1326 "Reserved",
1327 "Letterbox 16:9 image, at top of coded frame",
1328 "Letterbox 14:9 image, at top of coded frame",
1329 "Letterbox image with aspect ratio greater than 16:9, vertically centered",
1330 "Reserved",
1331 "Reserved",
1332 "Reserved",
1333 "Full frame 4:3 image, same as coded frame",
1334 "Full frame 4:3 image, same as coded frame",
1335 "Letterbox 16:9 image, vertically centered, all image areas protected",
1336 "Letterbox 14:9 image, vertically centered",
1337 "Reserved",
1338 "Full frame 4:3 image, with alternative 14:9 center",
1339 "Letterbox 16:9 image, with alternative 14:9 center",
1340 "Letterbox 16:9 image, with alternative 4:3 center"
1341 };
1342 static const char *const afd_16_9[16] = {
1343 "Undefined",
1344 "Reserved",
1345 "Full frame 16:9 image, same as coded frame",
1346 "Pillarbox 14:9 image, horizontally centered",
1347 "Letterbox image with aspect ratio greater than 16:9, vertically centered",
1348 "Reserved",
1349 "Reserved",
1350 "Reserved",
1351 "Full frame 16:9 image, same as coded frame",
1352 "Pillarbox 4:3 image, horizontally centered",
1353 "Full frame 16:9 image, all image areas protected",
1354 "Pillarbox 14:9 image, horizontally centered",
1355 "Reserved",
1356 "Pillarbox 4:3 image, with alternative 14:9 center",
1357 "Full frame 16:9 image, with alternative 14:9 center",
1358 "Full frame 16:9 image, with alternative 4:3 center"
1359 };
1360
1361 return ar_16_9 ? afd_16_9[afd & 0x0f] : afd_4_3[afd & 0x0f];
1362}
1363
1364/* SMPTE ST 2016-1:2009, Secs. 6, 9.2.1-9.2.2, Tables 3, 5 and 6. */
1365static const char *
1366st2016_3_bar_value_meaning(unsigned value_index, bool_Bool top, bool_Bool bottom, bool_Bool left, bool_Bool right)
1367{
1368 if (value_index == 1) {
1369 if (top)
1370 return "Line number: end of top bar";
1371 if (bottom)
1372 return "Line number: start of bottom bar";
1373 if (left)
1374 return "Pixel number: end of left bar";
1375 if (right)
1376 return "Pixel number: start of right bar";
1377 } else {
1378 if (top && bottom)
1379 return "Line number: start of bottom bar";
1380 if (left && right)
1381 return "Pixel number: start of right bar";
1382 }
1383
1384 return "No valid Bar Data value";
1385}
1386
1387static int
1388dissect_st2016_3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1389{
1390 const st291_vanc_dissector_data_t *st291_data =
1391 (const st291_vanc_dissector_data_t *)data;
1392 proto_tree *top_tree =
1393 st291_data && st291_data->top_tree ? st291_data->top_tree : tree;
1394 proto_item *ti;
1395 proto_item *root_ti;
1396 proto_tree *st2016_tree;
1397 proto_tree *afd_tree;
1398 proto_tree *flags_tree;
1399 proto_tree *value_tree;
1400 unsigned len = tvb_captured_length(tvb);
1401 uint8_t afd_byte;
1402 uint8_t afd;
1403 bool_Bool ar_16_9;
1404 uint8_t flags;
1405 bool_Bool top;
1406 bool_Bool bottom;
1407 bool_Bool left;
1408 bool_Bool right;
1409 uint16_t value1;
1410 uint16_t value2;
1411 const char *meaning1;
1412 const char *meaning2;
1413
1414 root_ti = proto_tree_add_item(top_tree, proto_st2016_3, tvb, 0, len, ENC_NA0x00000000);
1415 st2016_tree = proto_item_add_subtree(root_ti, ett_st2016_3);
1416
1417 if (len != 8) {
1418 expert_add_info_format(pinfo, root_ti, &ei_st2016_3_bad_length,
1419 "ST 2016-3 requires 8 UDW bytes; packet contains %u",
1420 len);
1421 return len;
1422 }
1423
1424 /* SMPTE ST 2016-3:2009, Sec. 4.1, Table 1 maps UDW1 to the
1425 * ST 2016-1 AFD byte; ST 2016-1:2009, Sec. 9.1, Table 4 defines
1426 * reserved bits, active_format and coded_frame_aspect_ratio. */
1427 afd_byte = tvb_get_uint8(tvb, 0);
1428 afd = (afd_byte >> 3) & 0x0f;
1429 ar_16_9 = (afd_byte & 0x04) != 0;
1430
1431 ti = proto_tree_add_item(st2016_tree, hf_st2016_3_afd_byte, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
1432 afd_tree = proto_item_add_subtree(ti, ett_st2016_3_afd);
1433 proto_tree_add_item(afd_tree, hf_st2016_3_afd_reserved, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
1434 proto_tree_add_uint_format_value(afd_tree, hf_st2016_3_afd_code, tvb, 0, 1, afd,
1435 "%u (%s)", afd,
1436 st2016_3_afd_description(afd, ar_16_9));
1437 proto_tree_add_item(afd_tree, hf_st2016_3_afd_ar, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
1438
1439 if ((afd_byte & 0x83) != 0)
1440 expert_add_info(pinfo, ti, &ei_st2016_3_afd_reserved);
1441
1442 /* SMPTE ST 2016-3:2009, Sec. 4.1, Table 1 -- UDW2 and UDW3 are reserved. */
1443 ti = proto_tree_add_item(st2016_tree, hf_st2016_3_reserved_1, tvb, 1, 1, ENC_BIG_ENDIAN0x00000000);
1444 if (tvb_get_uint8(tvb, 1) != 0)
1445 expert_add_info(pinfo, ti, &ei_st2016_3_reserved_udw);
1446
1447 ti = proto_tree_add_item(st2016_tree, hf_st2016_3_reserved_2, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
1448 if (tvb_get_uint8(tvb, 2) != 0)
1449 expert_add_info(pinfo, ti, &ei_st2016_3_reserved_udw);
1450
1451 /* SMPTE ST 2016-3:2009, Sec. 4.1, Table 1 maps UDW4 to Bar Data flags;
1452 * SMPTE ST 2016-1:2009, Sec. 9.2.1, Table 5 defines top/bottom/left/right. */
1453 flags = tvb_get_uint8(tvb, 3);
1454 top = (flags & 0x80) != 0;
1455 bottom = (flags & 0x40) != 0;
1456 left = (flags & 0x20) != 0;
1457 right = (flags & 0x10) != 0;
1458
1459 ti = proto_tree_add_item(st2016_tree, hf_st2016_3_bar_flags, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1460 flags_tree = proto_item_add_subtree(ti, ett_st2016_3_bar_flags);
1461 proto_tree_add_item(flags_tree, hf_st2016_3_bar_top, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1462 proto_tree_add_item(flags_tree, hf_st2016_3_bar_bottom, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1463 proto_tree_add_item(flags_tree, hf_st2016_3_bar_left, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1464 proto_tree_add_item(flags_tree, hf_st2016_3_bar_right, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1465 proto_tree_add_item(flags_tree, hf_st2016_3_bar_reserved, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1466
1467 if ((flags & 0x0f) != 0)
1468 expert_add_info(pinfo, ti, &ei_st2016_3_bar_reserved);
1469
1470 if ((top != bottom) || (left != right) || ((top || bottom) && (left || right)))
1471 expert_add_info(pinfo, ti, &ei_st2016_3_bar_flags_invalid);
1472
1473 /* SMPTE ST 2016-3:2009, Sec. 4.1, Table 1 maps UDW5-UDW8 to
1474 * Bar Data Value 1/2; ST 2016-1:2009, Sec. 9.2.2, Table 6 defines
1475 * marker bits and the 14-bit line/pixel values. */
1476 value1 = tvb_get_ntohs(tvb, 4);
1477 value2 = tvb_get_ntohs(tvb, 6);
1478 meaning1 = st2016_3_bar_value_meaning(1, top, bottom, left, right);
1479 meaning2 = st2016_3_bar_value_meaning(2, top, bottom, left, right);
1480
1481 ti = proto_tree_add_item(st2016_tree, hf_st2016_3_bar_value_1, tvb, 4, 2, ENC_BIG_ENDIAN0x00000000);
1482 value_tree = proto_item_add_subtree(ti, ett_st2016_3_bar_value_1);
1483 proto_tree_add_item(value_tree, hf_st2016_3_bar_value_1_marker, tvb, 4, 2, ENC_BIG_ENDIAN0x00000000);
1484 proto_tree_add_item(value_tree, hf_st2016_3_bar_value_1_data, tvb, 4, 2, ENC_BIG_ENDIAN0x00000000);
1485 ti = proto_tree_add_string(value_tree, hf_st2016_3_bar_value_1_meaning, tvb, 4, 0,
1486 meaning1);
1487 proto_item_set_generated(ti);
1488
1489 ti = proto_tree_add_item(st2016_tree, hf_st2016_3_bar_value_2, tvb, 6, 2, ENC_BIG_ENDIAN0x00000000);
1490 value_tree = proto_item_add_subtree(ti, ett_st2016_3_bar_value_2);
1491 proto_tree_add_item(value_tree, hf_st2016_3_bar_value_2_marker, tvb, 6, 2, ENC_BIG_ENDIAN0x00000000);
1492 proto_tree_add_item(value_tree, hf_st2016_3_bar_value_2_data, tvb, 6, 2, ENC_BIG_ENDIAN0x00000000);
1493 ti = proto_tree_add_string(value_tree, hf_st2016_3_bar_value_2_meaning, tvb, 6, 0,
1494 meaning2);
1495 proto_item_set_generated(ti);
1496
1497 if (top || bottom || left || right) {
1498 if ((value1 & 0xc000) != 0xc000)
1499 expert_add_info(pinfo, ti, &ei_st2016_3_bar_marker);
1500 if ((top && bottom) || (left && right)) {
1501 if ((value2 & 0xc000) != 0xc000)
1502 expert_add_info(pinfo, ti, &ei_st2016_3_bar_marker);
1503 }
1504 }
1505
1506 proto_item_append_text(root_ti, ": AFD: %s in %s mode",
1507 st2016_3_afd_description(afd, ar_16_9),
1508 ar_16_9 ? "16:9" : "4:3");
1509
1510 return len;
1511}
1512
1513void
1514proto_register_st2016_3(void)
1515{
1516 static hf_register_info hf[] = {
1517 { &hf_st2016_3_afd_byte,
1518 { "AFD Information", "st2016_3.afd", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1519 { &hf_st2016_3_afd_code,
1520 { "AFD Code", "st2016_3.afd.code", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1521 { &hf_st2016_3_afd_ar,
1522 { "Coded Frame Aspect Ratio", "st2016_3.afd.ar", FT_BOOLEAN, 8,
1523 TFS(&st2016_3_tfs_afd_ar)((0 ? (const struct true_false_string*)0 : ((&st2016_3_tfs_afd_ar
))))
, 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1524 { &hf_st2016_3_afd_reserved,
1525 { "Reserved", "st2016_3.afd.reserved", FT_UINT8, BASE_HEX, NULL((void*)0), 0x83, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1526 { &hf_st2016_3_reserved_1,
1527 { "Reserved UDW 2", "st2016_3.reserved1", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1528 { &hf_st2016_3_reserved_2,
1529 { "Reserved UDW 3", "st2016_3.reserved2", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1530 { &hf_st2016_3_bar_flags,
1531 { "Bar Data Flags", "st2016_3.bar.flags", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1532 { &hf_st2016_3_bar_top,
1533 { "Top Bar Present", "st2016_3.bar.top", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1534 { &hf_st2016_3_bar_bottom,
1535 { "Bottom Bar Present", "st2016_3.bar.bottom", FT_BOOLEAN, 8, NULL((void*)0), 0x40, NULL((void*)0),
1536 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1537 { &hf_st2016_3_bar_left,
1538 { "Left Bar Present", "st2016_3.bar.left", FT_BOOLEAN, 8, NULL((void*)0), 0x20, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1539 { &hf_st2016_3_bar_right,
1540 { "Right Bar Present", "st2016_3.bar.right", FT_BOOLEAN, 8, NULL((void*)0), 0x10, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1541 { &hf_st2016_3_bar_reserved,
1542 { "Reserved", "st2016_3.bar.reserved", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0f, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1543 { &hf_st2016_3_bar_value_1,
1544 { "Bar Data Value 1", "st2016_3.bar.value1", FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0),
1545 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1546 { &hf_st2016_3_bar_value_1_marker,
1547 { "Marker Bits", "st2016_3.bar.value1.marker", FT_UINT16, BASE_HEX, NULL((void*)0), 0xc000,
1548 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1549 { &hf_st2016_3_bar_value_1_data,
1550 { "Line/Pixel Number", "st2016_3.bar.value1.data", FT_UINT16, BASE_DEC, NULL((void*)0),
1551 0x3fff, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1552 { &hf_st2016_3_bar_value_2,
1553 { "Bar Data Value 2", "st2016_3.bar.value2", FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0),
1554 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1555 { &hf_st2016_3_bar_value_2_marker,
1556 { "Marker Bits", "st2016_3.bar.value2.marker", FT_UINT16, BASE_HEX, NULL((void*)0), 0xc000,
1557 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1558 { &hf_st2016_3_bar_value_2_data,
1559 { "Line/Pixel Number", "st2016_3.bar.value2.data", FT_UINT16, BASE_DEC, NULL((void*)0),
1560 0x3fff, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1561 { &hf_st2016_3_bar_value_1_meaning,
1562 { "Meaning", "st2016_3.bar.value1.meaning", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0),
1563 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1564 { &hf_st2016_3_bar_value_2_meaning,
1565 { "Meaning", "st2016_3.bar.value2.meaning", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0),
1566 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
1567 };
1568
1569 static int *ett[] = {
1570 &ett_st2016_3,
1571 &ett_st2016_3_afd,
1572 &ett_st2016_3_bar_flags,
1573 &ett_st2016_3_bar_value_1,
1574 &ett_st2016_3_bar_value_2,
1575 };
1576
1577 static ei_register_info ei[] = {
1578 { &ei_st2016_3_bad_length,
1579 { "st2016_3.length.bad", PI_MALFORMED0x07000000, PI_WARN0x00600000,
1580 "ST 2016-3 payload length is not 8 bytes", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1581 { &ei_st2016_3_afd_reserved,
1582 { "st2016_3.afd.reserved.bad", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
1583 "Reserved AFD bits are not zero", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1584 { &ei_st2016_3_reserved_udw,
1585 { "st2016_3.reserved_udw.bad", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
1586 "Reserved ST 2016-3 UDW is not zero", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1587 { &ei_st2016_3_bar_reserved,
1588 { "st2016_3.bar.reserved.bad", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
1589 "Reserved Bar Data flag bits are not zero", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1590 { &ei_st2016_3_bar_flags_invalid,
1591 { "st2016_3.bar.flags.invalid", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
1592 "Bar Data flags must specify Top+Bottom, Left+Right, or no bars", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1593 { &ei_st2016_3_bar_marker,
1594 { "st2016_3.bar.marker.bad", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
1595 "Bar Data value marker bits are not binary '11'", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
1596 };
1597
1598 expert_module_t *expert_st2016_3;
1599
1600 proto_st2016_3 = proto_register_protocol(
1601 "SMPTE ST 2016-3 AFD and Bar Data", "ST 2016-3", "st2016_3");
1602
1603 proto_register_field_array(proto_st2016_3, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
1604 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
1605
1606 expert_st2016_3 = expert_register_protocol(proto_st2016_3);
1607 expert_register_field_array(expert_st2016_3, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
1608
1609 st2016_3_handle =
1610 register_dissector("st2016_3", dissect_st2016_3, proto_st2016_3);
1611}
1612
1613void
1614proto_reg_handoff_st2016_3(void)
1615{
1616 dissector_add_uint("st291.did_sdid", ST2016_3_DID_SDID_KEY0x4105, st2016_3_handle);
1617}
1618
1619/*
1620 * SMPTE ST 334-2 Caption Distribution Packet
1621 */
1622
1623
1624/* SMPTE ST 334-2:2015, Sec. 5.2, Table 3 -- cdp_frame_rate values. */
1625static const value_string st334_2_frame_rate_vals[] = {
1626 { 0x0, "Forbidden" },
1627 { 0x1, "24000/1001 (~23.976 fps)" },
1628 { 0x2, "24 fps" },
1629 { 0x3, "25 fps" },
1630 { 0x4, "30000/1001 (~29.97 fps)" },
1631 { 0x5, "30 fps" },
1632 { 0x6, "50 fps" },
1633 { 0x7, "60000/1001 (~59.94 fps)" },
1634 { 0x8, "60 fps" },
1635 { 0, NULL((void*)0) }
1636};
1637
1638/* SMPTE ST 334-2:2015, Sec. 5.1, Table 1; Secs. 5.3-5.7 -- CDP section IDs. */
1639static const value_string st334_2_section_id_vals[] = {
1640 { 0x71, "Time Code Section" },
1641 { 0x72, "CC Data Section" },
1642 { 0x73, "CC Service Information Section" },
1643 { 0x74, "CDP Footer" },
1644 { 0, NULL((void*)0) }
1645};
1646
1647/* SMPTE ST 334-2:2015, Sec. 5.4, Table 5; cc_type semantics are inherited from CEA-708. */
1648static const value_string st334_2_cc_type_vals[] = {
1649 { 0x0, "NTSC line 21 field 1 closed captions (CEA-608)" },
1650 { 0x1, "NTSC line 21 field 2 closed captions (CEA-608)" },
1651 { 0x2, "DTVCC channel packet data" },
1652 { 0x3, "DTVCC channel packet start" },
1653 { 0, NULL((void*)0) }
1654};
1655
1656static const struct true_false_string st334_2_tfs_present = {
1657 "Present", "Not present"
1658};
1659
1660static const struct true_false_string st334_2_tfs_valid = {
1661 "Valid", "Invalid"
1662};
1663
1664/* SMPTE ST 334-2:2015, Sec. 5.4, Table 5 -- required cc_count for each cdp_frame_rate. */
1665static unsigned
1666st334_2_expected_cc_count(uint8_t frame_rate)
1667{
1668 switch (frame_rate) {
1669 case 0x1:
1670 case 0x2:
1671 return 25;
1672 case 0x3:
1673 return 24;
1674 case 0x4:
1675 case 0x5:
1676 return 20;
1677 case 0x6:
1678 return 12;
1679 case 0x7:
1680 case 0x8:
1681 return 10;
1682 default:
1683 return 0;
1684 }
1685}
1686
1687/* SMPTE ST 334-2:2015, Sec. 5.6, Table 7 -- CDP checksum makes the modulo-256 packet sum zero. */
1688static uint8_t
1689st334_2_cdp_checksum(tvbuff_t *tvb, unsigned length)
1690{
1691 unsigned i;
1692 uint8_t sum = 0;
1693
1694 for (i = 0; i < length; i++)
1695 sum = (uint8_t)(sum + tvb_get_uint8(tvb, i));
1696
1697 return sum;
1698}
1699
1700/* SMPTE ST 334-2:2015, Sec. 5.1, Table 1 -- required CDP section ordering. */
1701static unsigned
1702st334_2_section_rank(uint8_t id)
1703{
1704 switch (id) {
1705 case 0x71: return 1;
1706 case 0x72: return 2;
1707 case 0x73: return 3;
1708 case 0x74: return 5;
1709 default:
1710 if (id >= 0x75 && id <= 0xef)
1711 return 4;
1712 return 0;
1713 }
1714}
1715
1716/* SMPTE ST 334-2:2015, Sec. 5, Tables 1-8 -- complete CDP syntax. */
1717static int
1718dissect_st334_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1719{
1720 const st291_vanc_dissector_data_t *st291_data =
1721 (const st291_vanc_dissector_data_t *)data;
1722 proto_tree *top_tree = st291_data && st291_data->top_tree ?
1723 st291_data->top_tree : tree;
1724 proto_item *ti;
1725 proto_item *root_ti;
1726 proto_tree *cdp_tree;
1727 proto_tree *header_tree;
1728 unsigned captured_len = tvb_captured_length(tvb);
1729 unsigned parse_len;
1730 unsigned offset;
1731 unsigned previous_rank = 0;
1732 uint16_t identifier;
1733 uint8_t declared_len;
1734 uint8_t frame_rate;
1735 uint8_t flags;
1736 uint16_t header_sequence;
1737 bool_Bool time_present;
1738 bool_Bool cc_present;
1739 bool_Bool svc_present;
1740 bool_Bool seen_time = false0;
1741 bool_Bool seen_cc = false0;
1742 bool_Bool seen_svc = false0;
1743 bool_Bool seen_footer = false0;
1744
1745 ti = proto_tree_add_item(top_tree, proto_st334_2, tvb, 0, -1, ENC_NA0x00000000);
1746 cdp_tree = proto_item_add_subtree(ti, ett_st334_2);
1747
1748 if (captured_len < 7) {
1749 expert_add_info_format(pinfo, ti, &ei_st334_2_bad_length,
1750 "ST 334-2 requires at least 7 UDW bytes; packet contains %u",
1751 captured_len);
1752 return captured_len;
1753 }
1754
1755 identifier = tvb_get_ntohs(tvb, 0);
1756 declared_len = tvb_get_uint8(tvb, 2);
1757 frame_rate = (tvb_get_uint8(tvb, 3) >> 4) & 0x0f;
1758 flags = tvb_get_uint8(tvb, 4);
1759 header_sequence = tvb_get_ntohs(tvb, 5);
1760
1761 if (declared_len < 7 || declared_len > captured_len)
1762 parse_len = captured_len;
1763 else
1764 parse_len = declared_len;
1765
1766 root_ti = ti;
1767 proto_item_set_len(ti, parse_len);
1768 proto_item_append_text(ti, ", sequence %u", header_sequence);
1769
1770 /* SMPTE ST 334-2:2015, Sec. 5.2, Tables 2-3 -- cdp_header(). */
1771 header_tree = proto_tree_add_subtree(cdp_tree, tvb, 0, 7,
1772 ett_st334_2_header, NULL((void*)0), "CDP Header");
1773
1774 ti = proto_tree_add_item(header_tree, hf_st334_2_cdp_identifier, tvb, 0, 2, ENC_BIG_ENDIAN0x00000000);
1775 if (identifier != ST334_2_CDP_IDENTIFIER0x9669)
1776 expert_add_info_format(pinfo, ti, &ei_st334_2_bad_identifier,
1777 "CDP identifier is 0x%04x; expected 0x%04x",
1778 identifier, ST334_2_CDP_IDENTIFIER0x9669);
1779
1780 ti = proto_tree_add_item(header_tree, hf_st334_2_cdp_length, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
1781 if (declared_len != captured_len)
1782 expert_add_info_format(pinfo, ti, &ei_st334_2_bad_length,
1783 "CDP length is %u bytes, but ST 291 UDW payload contains %u bytes",
1784 declared_len, captured_len);
1785
1786 proto_tree_add_item(header_tree, hf_st334_2_frame_rate, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1787 ti = proto_tree_add_item(header_tree, hf_st334_2_header_reserved, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
1788 if ((tvb_get_uint8(tvb, 3) & 0x0f) != 0x0f)
1789 expert_add_info(pinfo, ti, &ei_st334_2_bad_reserved);
1790
1791 proto_tree_add_item(header_tree, hf_st334_2_time_code_present, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1792 proto_tree_add_item(header_tree, hf_st334_2_ccdata_present, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1793 proto_tree_add_item(header_tree, hf_st334_2_svcinfo_present, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1794 proto_tree_add_item(header_tree, hf_st334_2_svc_info_start, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1795 proto_tree_add_item(header_tree, hf_st334_2_svc_info_change, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1796 proto_tree_add_item(header_tree, hf_st334_2_svc_info_complete, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1797 proto_tree_add_item(header_tree, hf_st334_2_caption_service_active, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1798 ti = proto_tree_add_item(header_tree, hf_st334_2_header_reserved_bit, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
1799 if ((flags & 0x01) == 0)
1800 expert_add_info(pinfo, ti, &ei_st334_2_bad_reserved);
1801
1802 proto_tree_add_item(header_tree, hf_st334_2_header_sequence_counter, tvb, 5, 2, ENC_BIG_ENDIAN0x00000000);
1803
1804 time_present = (flags & 0x80) != 0;
1805 cc_present = (flags & 0x40) != 0;
1806 svc_present = (flags & 0x20) != 0;
1807
1808 offset = 7;
1809 while (offset < parse_len) {
1810 uint8_t id;
1811 unsigned rank;
1812 unsigned section_len = 0;
1813
1814 if (!tvb_bytes_exist(tvb, offset, 1))
1815 break;
1816
1817 id = tvb_get_uint8(tvb, offset);
1818 rank = st334_2_section_rank(id);
1819
1820 if (rank != 0 && rank < previous_rank) {
1821 ti = proto_tree_add_item(cdp_tree, hf_st334_2_section_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1822 expert_add_info(pinfo, ti, &ei_st334_2_bad_section_order);
1823 }
1824 if (rank != 0 && rank > previous_rank)
1825 previous_rank = rank;
1826
1827 /* SMPTE ST 334-2:2015, Sec. 5.3, Table 4 -- time_code_section(). */
1828 if (id == 0x71) {
1829 proto_tree *section_tree;
1830 uint8_t b1, b2, b3, b4;
1831 unsigned hours, minutes, seconds, frames;
1832 char time_str[48];
1833
1834 if (!tvb_bytes_exist(tvb, offset, 5) || offset + 5 > parse_len) {
1835 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
1836 "Truncated CDP time code section");
1837 break;
1838 }
1839 section_len = 5;
1840 section_tree = proto_tree_add_subtree(cdp_tree, tvb, offset, section_len,
1841 ett_st334_2_timecode, NULL((void*)0), "Time Code Section");
1842 ti = proto_tree_add_item(section_tree, hf_st334_2_section_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1843 if (seen_time)
1844 expert_add_info(pinfo, ti, &ei_st334_2_duplicate_section);
1845 seen_time = true1;
1846
1847 b1 = tvb_get_uint8(tvb, offset + 1);
1848 b2 = tvb_get_uint8(tvb, offset + 2);
1849 b3 = tvb_get_uint8(tvb, offset + 3);
1850 b4 = tvb_get_uint8(tvb, offset + 4);
1851
1852 hours = ((b1 >> 4) & 0x03) * 10 + (b1 & 0x0f);
1853 minutes = ((b2 >> 4) & 0x07) * 10 + (b2 & 0x0f);
1854 seconds = ((b3 >> 4) & 0x07) * 10 + (b3 & 0x0f);
1855 frames = ((b4 >> 4) & 0x03) * 10 + (b4 & 0x0f);
1856 snprintf(time_str, sizeof(time_str), "%02u:%02u:%02u:%02u",
1857 hours, minutes, seconds, frames);
1858 ti = proto_tree_add_string(section_tree, hf_st334_2_timecode, tvb, offset + 1, 4, time_str);
1859 proto_item_set_generated(ti);
1860 proto_tree_add_item(section_tree, hf_st334_2_tc_field_flag, tvb, offset + 3, 1, ENC_BIG_ENDIAN0x00000000);
1861 proto_tree_add_item(section_tree, hf_st334_2_drop_frame_flag, tvb, offset + 4, 1, ENC_BIG_ENDIAN0x00000000);
1862 } else if (id == 0x72) {
1863 /* SMPTE ST 334-2:2015, Sec. 5.4, Table 5 -- ccdata_section(). */
1864 proto_tree *section_tree;
1865 unsigned count;
1866 unsigned expected;
1867 unsigned i;
1868 unsigned dtvcc_len = 0;
1869 uint8_t *dtvcc_data;
1870
1871 if (!tvb_bytes_exist(tvb, offset, 2) || offset + 2 > parse_len) {
1872 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
1873 "Truncated CDP CC data section header");
1874 break;
1875 }
1876 count = tvb_get_uint8(tvb, offset + 1) & 0x1f;
1877 section_len = 2 + 3 * count;
1878 if (!tvb_bytes_exist(tvb, offset, section_len) || offset + section_len > parse_len) {
1879 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
1880 "CC data section requires %u bytes but packet ends early",
1881 section_len);
1882 break;
1883 }
1884
1885 section_tree = proto_tree_add_subtree(cdp_tree, tvb, offset, section_len,
1886 ett_st334_2_ccdata, NULL((void*)0), "CC Data Section");
1887 ti = proto_tree_add_item(section_tree, hf_st334_2_section_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1888 if (seen_cc)
1889 expert_add_info(pinfo, ti, &ei_st334_2_duplicate_section);
1890 seen_cc = true1;
1891
1892 ti = proto_tree_add_item(section_tree, hf_st334_2_cc_count, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
1893 if ((tvb_get_uint8(tvb, offset + 1) & 0xe0) != 0xe0)
1894 expert_add_info(pinfo, ti, &ei_st334_2_bad_marker);
1895
1896 expected = st334_2_expected_cc_count(frame_rate);
1897 if (expected != 0 && count != expected)
1898 expert_add_info_format(pinfo, ti, &ei_st334_2_cc_count,
1899 "cc_count is %u; frame-rate code 0x%x requires %u",
1900 count, frame_rate, expected);
1901
1902 dtvcc_data = wmem_alloc(pinfo->pool, MAX(1U, count * 2)(((1U) > (count * 2)) ? (1U) : (count * 2)));
1903 for (i = 0; i < count; i++) {
1904 unsigned c_off = offset + 2 + i * 3;
1905 uint8_t type_byte = tvb_get_uint8(tvb, c_off);
1906 uint8_t cc_type = type_byte & 0x03;
1907 proto_tree *construct_tree;
1908
1909 construct_tree = proto_tree_add_subtree_format(
1910 section_tree, tvb, c_off, 3, ett_st334_2_cc_construct, NULL((void*)0),
1911 "CC Construct %u: %s", i + 1,
1912 val_to_str_const(cc_type, st334_2_cc_type_vals, "Unknown"));
1913 ti = proto_tree_add_item(construct_tree, hf_st334_2_cc_marker_bits, tvb, c_off, 1, ENC_BIG_ENDIAN0x00000000);
1914 if ((type_byte & 0xf8) != 0xf8)
1915 expert_add_info(pinfo, ti, &ei_st334_2_bad_marker);
1916 proto_tree_add_item(construct_tree, hf_st334_2_cc_valid, tvb, c_off, 1, ENC_BIG_ENDIAN0x00000000);
1917 proto_tree_add_item(construct_tree, hf_st334_2_cc_type, tvb, c_off, 1, ENC_BIG_ENDIAN0x00000000);
1918 proto_tree_add_item(construct_tree, hf_st334_2_cc_data_1, tvb, c_off + 1, 1, ENC_BIG_ENDIAN0x00000000);
1919 proto_tree_add_item(construct_tree, hf_st334_2_cc_data_2, tvb, c_off + 2, 1, ENC_BIG_ENDIAN0x00000000);
1920
1921 if ((type_byte & 0x04) != 0 && (cc_type == 2 || cc_type == 3)) {
1922 dtvcc_data[dtvcc_len++] = tvb_get_uint8(tvb, c_off + 1);
1923 dtvcc_data[dtvcc_len++] = tvb_get_uint8(tvb, c_off + 2);
1924 }
1925 }
1926 if (dtvcc_len != 0) {
1927 tvbuff_t *dtvcc_tvb;
1928
1929 dtvcc_tvb = tvb_new_child_real_data(tvb, dtvcc_data,
1930 dtvcc_len, dtvcc_len);
1931 /* ST 334-2:2015, Sec. 5.4, Table 5: concatenate valid cc_type 2/3 constructs for CEA-708 decoding. */
1932 add_new_data_source(pinfo, dtvcc_tvb, "CEA-708 DTVCC Data");
1933 ti = proto_tree_add_item(section_tree, hf_st334_2_dtvcc_data,
1934 dtvcc_tvb, 0, dtvcc_len, ENC_NA0x00000000);
1935 proto_item_set_generated(ti);
1936 }
1937 } else if (id == 0x73) {
1938 /* SMPTE ST 334-2:2015, Sec. 5.5, Table 6 -- ccsvcinfo_section(). */
1939 proto_tree *section_tree;
1940 uint8_t svc_flags;
1941 unsigned count;
1942 unsigned i;
1943
1944 if (!tvb_bytes_exist(tvb, offset, 2) || offset + 2 > parse_len) {
1945 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
1946 "Truncated CDP service information section header");
1947 break;
1948 }
1949 svc_flags = tvb_get_uint8(tvb, offset + 1);
1950 count = svc_flags & 0x0f;
1951 section_len = 2 + 7 * count;
1952 if (!tvb_bytes_exist(tvb, offset, section_len) || offset + section_len > parse_len) {
1953 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
1954 "Service information section requires %u bytes but packet ends early",
1955 section_len);
1956 break;
1957 }
1958
1959 section_tree = proto_tree_add_subtree(cdp_tree, tvb, offset, section_len,
1960 ett_st334_2_svcinfo, NULL((void*)0),
1961 "CC Service Information Section");
1962 ti = proto_tree_add_item(section_tree, hf_st334_2_section_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1963 if (seen_svc)
1964 expert_add_info(pinfo, ti, &ei_st334_2_duplicate_section);
1965 seen_svc = true1;
1966
1967 ti = proto_tree_add_item(section_tree, hf_st334_2_svc_reserved, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
1968 if ((svc_flags & 0x80) == 0)
1969 expert_add_info(pinfo, ti, &ei_st334_2_bad_reserved);
1970 proto_tree_add_item(section_tree, hf_st334_2_svc_info_start_section, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
1971 proto_tree_add_item(section_tree, hf_st334_2_svc_info_change_section, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
1972 proto_tree_add_item(section_tree, hf_st334_2_svc_info_complete_section, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
1973 proto_tree_add_item(section_tree, hf_st334_2_svc_count, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
1974
1975 if (((flags >> 2) & 0x07) != ((svc_flags >> 4) & 0x07)) {
1976 expert_add_info_format(pinfo, ti, &ei_st334_2_bad_reserved,
1977 "Service-info start/change/complete flags do not match CDP header");
1978 }
1979
1980 for (i = 0; i < count; i++) {
1981 unsigned s_off = offset + 2 + i * 7;
1982 uint8_t first = tvb_get_uint8(tvb, s_off);
1983 unsigned service_number;
1984 uint8_t type_byte;
1985 bool_Bool digital_cc;
1986 proto_tree *service_tree;
1987 proto_tree *data_tree;
1988
1989 service_tree = proto_tree_add_subtree_format(
1990 section_tree, tvb, s_off, 7, ett_st334_2_service, NULL((void*)0),
1991 "Caption Service %u", i + 1);
1992 ti = proto_tree_add_item(service_tree, hf_st334_2_csn_reserved, tvb, s_off, 1, ENC_BIG_ENDIAN0x00000000);
1993 if ((first & 0x80) == 0)
1994 expert_add_info(pinfo, ti, &ei_st334_2_bad_reserved);
1995 proto_tree_add_item(service_tree, hf_st334_2_csn_size, tvb, s_off, 1, ENC_BIG_ENDIAN0x00000000);
1996 if ((first & 0x40) != 0) {
1997 ti = proto_tree_add_item(service_tree, hf_st334_2_csn_reserved_2, tvb, s_off, 1, ENC_BIG_ENDIAN0x00000000);
1998 if ((first & 0x20) == 0)
1999 expert_add_info(pinfo, ti, &ei_st334_2_bad_reserved);
2000 service_number = first & 0x1f;
2001 } else {
2002 service_number = first & 0x3f;
2003 }
2004 ti = proto_tree_add_uint(service_tree, hf_st334_2_caption_service_number,
2005 tvb, s_off, 1, service_number);
2006
2007 /*
2008 * SMPTE ST 334-2:2015, Sec. 5.5, Table 6 defines
2009 * svc_data_byte_1 through svc_data_byte_6 as one service
2010 * entry encoded according to the caption service descriptor
2011 * loop in ATSC A/65:2013, Sec. 6.9.2, Table 6.26.
2012 */
2013 type_byte = tvb_get_uint8(tvb, s_off + 4);
2014 digital_cc = (type_byte & 0x80) != 0;
2015
2016 data_tree = proto_tree_add_subtree(
2017 service_tree, tvb, s_off + 1, 6,
2018 ett_st334_2_service_data, NULL((void*)0), "Service Data");
2019
2020 proto_tree_add_item(data_tree, hf_st334_2_service_language,
2021 tvb, s_off + 1, 3, ENC_ASCII0x00000000);
2022 proto_tree_add_item(data_tree, hf_st334_2_service_digital_cc,
2023 tvb, s_off + 4, 1, ENC_BIG_ENDIAN0x00000000);
2024
2025 if (digital_cc) {
2026 proto_tree_add_item(data_tree, hf_st334_2_service_digital_reserved,
2027 tvb, s_off + 4, 1, ENC_BIG_ENDIAN0x00000000);
2028 proto_tree_add_item(data_tree, hf_st334_2_service_descriptor_number,
2029 tvb, s_off + 4, 1, ENC_BIG_ENDIAN0x00000000);
2030 } else {
2031 proto_tree_add_item(data_tree, hf_st334_2_service_line21_reserved,
2032 tvb, s_off + 4, 1, ENC_BIG_ENDIAN0x00000000);
2033 proto_tree_add_item(data_tree, hf_st334_2_service_line21_field,
2034 tvb, s_off + 4, 1, ENC_BIG_ENDIAN0x00000000);
2035 }
2036
2037 proto_tree_add_item(data_tree, hf_st334_2_service_easy_reader,
2038 tvb, s_off + 5, 1, ENC_BIG_ENDIAN0x00000000);
2039 proto_tree_add_item(data_tree, hf_st334_2_service_wide_aspect_ratio,
2040 tvb, s_off + 5, 1, ENC_BIG_ENDIAN0x00000000);
2041 ti = proto_tree_add_item(data_tree, hf_st334_2_service_reserved_14,
2042 tvb, s_off + 5, 2, ENC_BIG_ENDIAN0x00000000);
2043 if ((tvb_get_ntohs(tvb, s_off + 5) & 0x3fff) != 0x3fff)
2044 expert_add_info(pinfo, ti, &ei_st334_2_bad_reserved);
2045 }
2046 } else if (id == 0x74) {
2047 /* SMPTE ST 334-2:2015, Sec. 5.6, Table 7 -- cdp_footer(). */
2048 proto_tree *section_tree;
2049 uint16_t footer_sequence;
2050 uint8_t sum;
2051 proto_item *checksum_item;
2052
2053 section_len = 4;
2054 if (!tvb_bytes_exist(tvb, offset, section_len) || offset + section_len > parse_len) {
2055 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
2056 "Truncated CDP footer");
2057 break;
2058 }
2059
2060 section_tree = proto_tree_add_subtree(cdp_tree, tvb, offset, section_len,
2061 ett_st334_2_footer, NULL((void*)0), "CDP Footer");
2062 ti = proto_tree_add_item(section_tree, hf_st334_2_section_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
2063 if (seen_footer)
2064 expert_add_info(pinfo, ti, &ei_st334_2_duplicate_section);
2065 seen_footer = true1;
2066
2067 footer_sequence = tvb_get_ntohs(tvb, offset + 1);
2068 ti = proto_tree_add_item(section_tree, hf_st334_2_footer_sequence_counter,
2069 tvb, offset + 1, 2, ENC_BIG_ENDIAN0x00000000);
2070 if (footer_sequence != header_sequence)
2071 expert_add_info_format(pinfo, ti, &ei_st334_2_sequence_mismatch,
2072 "Footer sequence %u does not match header sequence %u",
2073 footer_sequence, header_sequence);
2074
2075 checksum_item = proto_tree_add_item(section_tree, hf_st334_2_packet_checksum,
2076 tvb, offset + 3, 1, ENC_BIG_ENDIAN0x00000000);
2077 if (parse_len == declared_len && offset + 4 == parse_len) {
2078 sum = st334_2_cdp_checksum(tvb, parse_len);
2079 ti = proto_tree_add_uint(section_tree, hf_st334_2_checksum_calculated,
2080 tvb, 0, 0,
2081 (uint8_t)(tvb_get_uint8(tvb, offset + 3) - sum));
2082 proto_item_set_generated(ti);
2083 if (sum != 0)
2084 expert_add_info_format(pinfo, checksum_item, &ei_st334_2_bad_checksum,
2085 "CDP checksum does not make packet sum modulo 256 equal zero (sum 0x%02x)",
2086 sum);
2087 }
2088 offset += section_len;
Value stored to 'offset' is never read
2089 break;
2090 } else if (id >= 0x75 && id <= 0xef) {
2091 /* SMPTE ST 334-2:2015, Sec. 5.7, Table 8 -- future_section(). */
2092 proto_tree *section_tree;
2093 unsigned future_len;
2094
2095 if (!tvb_bytes_exist(tvb, offset, 2) || offset + 2 > parse_len) {
2096 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
2097 "Truncated future CDP section header");
2098 break;
2099 }
2100 future_len = tvb_get_uint8(tvb, offset + 1);
2101 section_len = 2 + future_len;
2102 if (!tvb_bytes_exist(tvb, offset, section_len) || offset + section_len > parse_len) {
2103 expert_add_info_format(pinfo, root_ti, &ei_st334_2_truncated,
2104 "Future CDP section requires %u bytes but packet ends early",
2105 section_len);
2106 break;
2107 }
2108 section_tree = proto_tree_add_subtree_format(
2109 cdp_tree, tvb, offset, section_len, ett_st334_2_future, NULL((void*)0),
2110 "Unknown/Future CDP Section 0x%02x", id);
2111 proto_tree_add_item(section_tree, hf_st334_2_section_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
2112 proto_tree_add_item(section_tree, hf_st334_2_future_length, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
2113 if (future_len != 0)
2114 proto_tree_add_item(section_tree, hf_st334_2_future_data, tvb, offset + 2,
2115 future_len, ENC_NA0x00000000);
2116 } else {
2117 ti = proto_tree_add_item(cdp_tree, hf_st334_2_section_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
2118 expert_add_info_format(pinfo, ti, &ei_st334_2_bad_section_order,
2119 "Unknown CDP section identifier 0x%02x cannot be safely skipped",
2120 id);
2121 break;
2122 }
2123
2124 offset += section_len;
2125 }
2126
2127 if (time_present != seen_time)
2128 expert_add_info_format(pinfo, root_ti, &ei_st334_2_missing_section,
2129 "CDP header time_code_present=%u but time-code section %s",
2130 time_present, seen_time ? "is present" : "is absent");
2131 if (cc_present != seen_cc)
2132 expert_add_info_format(pinfo, root_ti, &ei_st334_2_missing_section,
2133 "CDP header ccdata_present=%u but CC-data section %s",
2134 cc_present, seen_cc ? "is present" : "is absent");
2135 if (svc_present != seen_svc)
2136 expert_add_info_format(pinfo, root_ti, &ei_st334_2_missing_section,
2137 "CDP header svcinfo_present=%u but service-info section %s",
2138 svc_present, seen_svc ? "is present" : "is absent");
2139 if (!seen_footer)
2140 expert_add_info_format(pinfo, root_ti, &ei_st334_2_missing_section,
2141 "Required CDP footer is absent");
2142
2143 return captured_len;
2144}
2145
2146void
2147proto_register_st334_2(void)
2148{
2149 static hf_register_info hf[] = {
2150 { &hf_st334_2_cdp_identifier,
2151 { "CDP Identifier", "st334_2.cdp.identifier", FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0),
2152 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2153 { &hf_st334_2_cdp_length,
2154 { "CDP Length", "st334_2.cdp.length", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2155 { &hf_st334_2_frame_rate,
2156 { "CDP Frame Rate", "st334_2.cdp.frame_rate", FT_UINT8, BASE_HEX,
2157 VALS(st334_2_frame_rate_vals)((0 ? (const struct _value_string*)0 : ((st334_2_frame_rate_vals
))))
, 0xf0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2158 { &hf_st334_2_header_reserved,
2159 { "Reserved", "st334_2.cdp.header.reserved", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0f, NULL((void*)0),
2160 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2161 { &hf_st334_2_time_code_present,
2162 { "Time Code", "st334_2.cdp.time_code_present", FT_BOOLEAN, 8,
2163 TFS(&st334_2_tfs_present)((0 ? (const struct true_false_string*)0 : ((&st334_2_tfs_present
))))
, 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2164 { &hf_st334_2_ccdata_present,
2165 { "CC Data", "st334_2.cdp.ccdata_present", FT_BOOLEAN, 8, TFS(&st334_2_tfs_present)((0 ? (const struct true_false_string*)0 : ((&st334_2_tfs_present
))))
,
2166 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2167 { &hf_st334_2_svcinfo_present,
2168 { "Service Information", "st334_2.cdp.svcinfo_present", FT_BOOLEAN, 8,
2169 TFS(&st334_2_tfs_present)((0 ? (const struct true_false_string*)0 : ((&st334_2_tfs_present
))))
, 0x20, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2170 { &hf_st334_2_svc_info_start,
2171 { "Service Info Start", "st334_2.cdp.svc_info_start", FT_BOOLEAN, 8, NULL((void*)0), 0x10,
2172 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2173 { &hf_st334_2_svc_info_change,
2174 { "Service Info Change", "st334_2.cdp.svc_info_change", FT_BOOLEAN, 8, NULL((void*)0), 0x08,
2175 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2176 { &hf_st334_2_svc_info_complete,
2177 { "Service Info Complete", "st334_2.cdp.svc_info_complete", FT_BOOLEAN, 8, NULL((void*)0),
2178 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2179 { &hf_st334_2_caption_service_active,
2180 { "Caption Service Active", "st334_2.cdp.caption_service_active", FT_BOOLEAN, 8,
2181 NULL((void*)0), 0x02, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2182 { &hf_st334_2_header_reserved_bit,
2183 { "Reserved", "st334_2.cdp.header.reserved_bit", FT_BOOLEAN, 8, NULL((void*)0), 0x01, NULL((void*)0),
2184 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2185 { &hf_st334_2_header_sequence_counter,
2186 { "Header Sequence Counter", "st334_2.cdp.header_sequence", FT_UINT16, BASE_DEC,
2187 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2188 { &hf_st334_2_section_id,
2189 { "Section ID", "st334_2.section.id", FT_UINT8, BASE_HEX,
2190 VALS(st334_2_section_id_vals)((0 ? (const struct _value_string*)0 : ((st334_2_section_id_vals
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2191 { &hf_st334_2_timecode,
2192 { "Time Code", "st334_2.timecode", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2193 { &hf_st334_2_tc_field_flag,
2194 { "Field Flag", "st334_2.timecode.field_flag", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0),
2195 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2196 { &hf_st334_2_drop_frame_flag,
2197 { "Drop Frame", "st334_2.timecode.drop_frame", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0),
2198 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2199 { &hf_st334_2_cc_count,
2200 { "CC Count", "st334_2.ccdata.count", FT_UINT8, BASE_DEC, NULL((void*)0), 0x1f, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2201 { &hf_st334_2_cc_marker_bits,
2202 { "Marker Bits", "st334_2.ccdata.marker", FT_UINT8, BASE_HEX, NULL((void*)0), 0xf8, NULL((void*)0),
2203 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2204 { &hf_st334_2_cc_valid,
2205 { "CC Valid", "st334_2.ccdata.valid", FT_BOOLEAN, 8, TFS(&st334_2_tfs_valid)((0 ? (const struct true_false_string*)0 : ((&st334_2_tfs_valid
))))
, 0x04,
2206 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2207 { &hf_st334_2_cc_type,
2208 { "CC Type", "st334_2.ccdata.type", FT_UINT8, BASE_DEC, VALS(st334_2_cc_type_vals)((0 ? (const struct _value_string*)0 : ((st334_2_cc_type_vals
))))
,
2209 0x03, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2210 { &hf_st334_2_cc_data_1,
2211 { "CC Data 1", "st334_2.ccdata.data1", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2212 { &hf_st334_2_cc_data_2,
2213 { "CC Data 2", "st334_2.ccdata.data2", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2214 { &hf_st334_2_dtvcc_data,
2215 { "DTVCC Data", "st334_2.ccdata.dtvcc", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2216 { &hf_st334_2_svc_reserved,
2217 { "Reserved", "st334_2.svcinfo.reserved", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2218 { &hf_st334_2_svc_info_start_section,
2219 { "Service Info Start", "st334_2.svcinfo.start", FT_BOOLEAN, 8, NULL((void*)0), 0x40, NULL((void*)0),
2220 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2221 { &hf_st334_2_svc_info_change_section,
2222 { "Service Info Change", "st334_2.svcinfo.change", FT_BOOLEAN, 8, NULL((void*)0), 0x20, NULL((void*)0),
2223 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2224 { &hf_st334_2_svc_info_complete_section,
2225 { "Service Info Complete", "st334_2.svcinfo.complete", FT_BOOLEAN, 8, NULL((void*)0), 0x10,
2226 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2227 { &hf_st334_2_svc_count,
2228 { "Service Count", "st334_2.svcinfo.count", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0f, NULL((void*)0),
2229 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2230 { &hf_st334_2_csn_reserved,
2231 { "Reserved", "st334_2.svcinfo.service.reserved", FT_BOOLEAN, 8, NULL((void*)0), 0x80, NULL((void*)0),
2232 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2233 { &hf_st334_2_csn_size,
2234 { "Caption Service Number Size", "st334_2.svcinfo.service.csn_size", FT_BOOLEAN, 8,
2235 NULL((void*)0), 0x40, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2236 { &hf_st334_2_csn_reserved_2,
2237 { "Reserved", "st334_2.svcinfo.service.reserved_2", FT_BOOLEAN, 8, NULL((void*)0), 0x20, NULL((void*)0),
2238 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2239 { &hf_st334_2_caption_service_number,
2240 { "Caption Service Number", "st334_2.svcinfo.service.number", FT_UINT8, BASE_DEC,
2241 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2242
2243 /*
2244 * SMPTE ST 334-2:2015, Sec. 5.5, Table 6;
2245 * ATSC A/65:2013, Sec. 6.9.2, Table 6.26.
2246 */
2247 { &hf_st334_2_service_data,
2248 { "Service Data", "st334_2.svcinfo.service.data", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
2249 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2250 { &hf_st334_2_service_language,
2251 { "Language", "st334_2.svcinfo.service.language", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
2252 "ISO 639.2/B language code", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2253 { &hf_st334_2_service_digital_cc,
2254 { "Digital CC", "st334_2.svcinfo.service.digital_cc", FT_BOOLEAN, 8,
2255 TFS(&tfs_yes_no)((0 ? (const struct true_false_string*)0 : ((&tfs_yes_no)
)))
, 0x80, "1 = CEA-708 digital captions; 0 = CEA-608/line 21", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2256 { &hf_st334_2_service_digital_reserved,
2257 { "Reserved", "st334_2.svcinfo.service.digital_reserved", FT_BOOLEAN, 8, NULL((void*)0), 0x40,
2258 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2259 { &hf_st334_2_service_line21_reserved,
2260 { "Reserved", "st334_2.svcinfo.service.line21_reserved", FT_UINT8, BASE_HEX, NULL((void*)0),
2261 0x7e, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2262 { &hf_st334_2_service_line21_field,
2263 { "Line 21 Field", "st334_2.svcinfo.service.line21_field", FT_BOOLEAN, 8, NULL((void*)0),
2264 0x01, "0 = field 1; 1 = field 2", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2265 { &hf_st334_2_service_descriptor_number,
2266 { "Caption Service Number", "st334_2.svcinfo.service.descriptor_number", FT_UINT8,
2267 BASE_DEC, NULL((void*)0), 0x3f, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2268 { &hf_st334_2_service_easy_reader,
2269 { "Easy Reader", "st334_2.svcinfo.service.easy_reader", FT_BOOLEAN, 8,
2270 TFS(&tfs_yes_no)((0 ? (const struct true_false_string*)0 : ((&tfs_yes_no)
)))
, 0x80, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2271 { &hf_st334_2_service_wide_aspect_ratio,
2272 { "Wide Aspect Ratio", "st334_2.svcinfo.service.wide_aspect_ratio", FT_BOOLEAN, 8,
2273 TFS(&tfs_yes_no)((0 ? (const struct true_false_string*)0 : ((&tfs_yes_no)
)))
, 0x40, "1 = 16:9; 0 = 4:3", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2274 { &hf_st334_2_service_reserved_14,
2275 { "Reserved", "st334_2.svcinfo.service.reserved_14", FT_UINT16, BASE_HEX, NULL((void*)0),
2276 0x3fff, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2277 { &hf_st334_2_future_length,
2278 { "Length", "st334_2.future.length", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2279 { &hf_st334_2_future_data,
2280 { "Data", "st334_2.future.data", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2281 { &hf_st334_2_footer_sequence_counter,
2282 { "Footer Sequence Counter", "st334_2.cdp.footer_sequence", FT_UINT16, BASE_DEC,
2283 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2284 { &hf_st334_2_packet_checksum,
2285 { "Packet Checksum", "st334_2.cdp.checksum", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0),
2286 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2287 { &hf_st334_2_checksum_calculated,
2288 { "Calculated Checksum", "st334_2.cdp.checksum_calculated", FT_UINT8, BASE_HEX,
2289 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2290 };
2291 static int *ett[] = {
2292 &ett_st334_2,
2293 &ett_st334_2_header,
2294 &ett_st334_2_timecode,
2295 &ett_st334_2_ccdata,
2296 &ett_st334_2_cc_construct,
2297 &ett_st334_2_svcinfo,
2298 &ett_st334_2_service,
2299 &ett_st334_2_service_data,
2300 &ett_st334_2_future,
2301 &ett_st334_2_footer,
2302 };
2303 static ei_register_info ei[] = {
2304 { &ei_st334_2_bad_identifier, { "st334_2.bad_identifier", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Invalid CDP identifier", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2305 { &ei_st334_2_bad_length, { "st334_2.bad_length", PI_MALFORMED0x07000000, PI_WARN0x00600000, "CDP length mismatch", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2306 { &ei_st334_2_bad_reserved, { "st334_2.bad_reserved", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Invalid reserved bits or duplicated flags", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2307 { &ei_st334_2_bad_section_order, { "st334_2.bad_section_order", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Invalid or unknown CDP section ordering", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2308 { &ei_st334_2_duplicate_section, { "st334_2.duplicate_section", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Duplicate CDP section", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2309 { &ei_st334_2_missing_section, { "st334_2.missing_section", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "CDP section presence mismatch", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2310 { &ei_st334_2_cc_count, { "st334_2.bad_cc_count", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "CC count does not match frame rate", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2311 { &ei_st334_2_bad_marker, { "st334_2.bad_marker", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Invalid CEA-708 marker bits", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2312 { &ei_st334_2_sequence_mismatch, { "st334_2.sequence_mismatch", PI_SEQUENCE0x02000000, PI_WARN0x00600000, "CDP header/footer sequence mismatch", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2313 { &ei_st334_2_bad_checksum, { "st334_2.bad_checksum", PI_CHECKSUM0x01000000, PI_WARN0x00600000, "Invalid CDP checksum", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2314 { &ei_st334_2_truncated, { "st334_2.truncated", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "Truncated CDP section", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
} },
2315 };
2316 expert_module_t *expert_st334_2;
2317
2318 proto_st334_2 = proto_register_protocol(
2319 "SMPTE ST 334-2 Caption Distribution Packet", "ST 334-2", "st334_2");
2320 proto_register_field_array(proto_st334_2, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
2321 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
2322
2323 expert_st334_2 = expert_register_protocol(proto_st334_2);
2324 expert_register_field_array(expert_st334_2, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
2325
2326 st334_2_handle = register_dissector("st334_2", dissect_st334_2, proto_st334_2);
2327}
2328
2329void
2330proto_reg_handoff_st334_2(void)
2331{
2332 dissector_add_uint("st291.did_sdid", ST334_2_DID_SDID_KEY0x6101, st334_2_handle);
2333}
2334
2335/*
2336 * Common System B World System Teletext decoding used by ST 2031 and
2337 * RDD 8 / OP-47. The protocols retain separate display-filter fields; this
2338 * structure supplies the appropriate field IDs to the common parser.
2339 */
2340typedef struct {
2341 int *magazine_hamming;
2342 int *magazine;
2343 int *packet_number_hamming;
2344 int *packet_number;
2345 int *page_units_hamming;
2346 int *page_units;
2347 int *page_tens_hamming;
2348 int *page_tens;
2349 int *data_string;
2350 int *textdata_array;
2351 int *erase_page;
2352 int *newsflash;
2353 int *subtitle;
2354 int *suppress_header;
2355 int *update_indicator;
2356 int *interrupted_sequence;
2357 int *inhibit_display;
2358 int *magazine_serial;
2359 int *character_set;
2360 int *tt_control;
2361} st291_wst_fields_t;
2362
2363/* Rec. ITU-R BT.653-3, System B national-option character subsets. */
2364static const value_string st291_wst_national_subset_vals[] = {
2365 { 0x00, "English" },
2366 { 0x01, "German" },
2367 { 0x04, "Swedish/Finnish/Hungarian" },
2368 { 0x05, "Italian" },
2369 { 0x10, "French" },
2370 { 0x11, "Portuguese/Spanish" },
2371 { 0x14, "Czech/Slovak" },
2372 { 0, NULL((void*)0) }
2373};
2374
2375static void
2376st291_process_wst_packet(tvbuff_t *tvb, proto_tree *tree, const st291_wst_fields_t *fields)
2377{
2378 uint8_t text_data[40];
2379 char data_string[41];
2380 unsigned magazine, packet_number;
2381 unsigned data_start_offset = 0, number_of_data_bytes = 0;
2382 proto_item *ti;
2383 unsigned i;
2384
2385 if (tvb_captured_length(tvb) < 42)
2386 return;
2387
2388 proto_tree_add_item(tree, *fields->magazine_hamming, tvb, 0, 2, ENC_BIG_ENDIAN0x00000000);
2389 magazine = tvb_get_bits8(tvb, 1, 1)
2390 + 2 * tvb_get_bits8(tvb, 3, 1)
2391 + 4 * tvb_get_bits8(tvb, 5, 1);
2392 if (magazine == 0)
2393 magazine = 8;
2394 ti = proto_tree_add_uint(tree, *fields->magazine, tvb, 0, 0, magazine);
2395 proto_item_set_generated(ti);
2396
2397 proto_tree_add_item(tree, *fields->packet_number_hamming, tvb, 0, 2, ENC_BIG_ENDIAN0x00000000);
2398 packet_number = tvb_get_bits8(tvb, 7, 1)
2399 + 2 * tvb_get_bits8(tvb, 9, 1)
2400 + 4 * tvb_get_bits8(tvb, 11, 1)
2401 + 8 * tvb_get_bits8(tvb, 13, 1)
2402 + 16 * tvb_get_bits8(tvb, 15, 1);
2403 ti = proto_tree_add_uint(tree, *fields->packet_number, tvb, 0, 0, packet_number);
2404 proto_item_set_generated(ti);
2405
2406 if (packet_number == 0) {
2407 unsigned page_units, page_tens, tt_page;
2408
2409 data_start_offset = 10;
2410 number_of_data_bytes = 32;
2411
2412 page_units = tvb_get_bits8(tvb, 2 * 8 + 1, 1)
2413 + 2 * tvb_get_bits8(tvb, 2 * 8 + 3, 1)
2414 + 4 * tvb_get_bits8(tvb, 2 * 8 + 5, 1)
2415 + 8 * tvb_get_bits8(tvb, 2 * 8 + 7, 1);
2416 page_tens = tvb_get_bits8(tvb, 3 * 8 + 1, 1)
2417 + 2 * tvb_get_bits8(tvb, 3 * 8 + 3, 1)
2418 + 4 * tvb_get_bits8(tvb, 3 * 8 + 5, 1)
2419 + 8 * tvb_get_bits8(tvb, 3 * 8 + 7, 1);
2420
2421 proto_tree_add_item(tree, *fields->page_units_hamming, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
2422 proto_tree_add_item(tree, *fields->page_tens_hamming, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
2423 ti = proto_tree_add_uint(tree, *fields->page_units, tvb, 0, 0, page_units);
2424 proto_item_set_generated(ti);
2425 ti = proto_tree_add_uint(tree, *fields->page_tens, tvb, 0, 0, page_tens);
2426 proto_item_set_generated(ti);
2427
2428 tt_page = (magazine << 8) | (page_tens << 4) | page_units;
2429 proto_tree_add_none_format(tree, *fields->tt_control, tvb, 0, 0,
2430 "Control bits for TT Page 0x%x:", tt_page);
2431
2432 proto_tree_add_item(tree, *fields->erase_page, tvb, 5, 1, ENC_BIG_ENDIAN0x00000000);
2433 proto_tree_add_item(tree, *fields->newsflash, tvb, 7, 1, ENC_BIG_ENDIAN0x00000000);
2434 proto_tree_add_item(tree, *fields->subtitle, tvb, 7, 1, ENC_BIG_ENDIAN0x00000000);
2435 proto_tree_add_item(tree, *fields->suppress_header, tvb, 8, 1, ENC_BIG_ENDIAN0x00000000);
2436 proto_tree_add_item(tree, *fields->update_indicator, tvb, 8, 1, ENC_BIG_ENDIAN0x00000000);
2437 proto_tree_add_item(tree, *fields->interrupted_sequence, tvb, 8, 1, ENC_BIG_ENDIAN0x00000000);
2438 proto_tree_add_item(tree, *fields->inhibit_display, tvb, 8, 1, ENC_BIG_ENDIAN0x00000000);
2439 proto_tree_add_item(tree, *fields->magazine_serial, tvb, 9, 1, ENC_BIG_ENDIAN0x00000000);
2440 proto_tree_add_item(tree, *fields->character_set, tvb, 9, 1, ENC_BIG_ENDIAN0x00000000);
2441 } else if (packet_number >= 1 && packet_number <= 25) {
2442 data_start_offset = 2;
2443 number_of_data_bytes = 40;
2444 }
2445
2446 if (number_of_data_bytes == 0)
2447 return;
2448
2449 for (i = 0; i < number_of_data_bytes; i++) {
2450 uint8_t c = tvb_get_bits8(tvb, (data_start_offset + i) * 8, 7);
2451 text_data[i] = c;
2452 data_string[i] = (char)c;
2453 }
2454 data_string[number_of_data_bytes] = '\0';
2455
2456 ti = proto_tree_add_string(tree, *fields->data_string, tvb, 0, 0, data_string);
2457 proto_item_set_generated(ti);
2458 ti = proto_tree_add_bytes(tree, *fields->textdata_array, tvb, 0, 0, text_data);
2459 proto_item_set_generated(ti);
2460}
2461
2462/*
2463 * SMPTE ST 2031 DVB/SCTE VBI data in VANC
2464 */
2465
2466static const struct true_false_string st2031_tfs_field_parity = {
2467 "First field of a frame", "Second field of a frame"
2468};
2469
2470
2471static const st291_wst_fields_t st2031_wst_fields = {
2472 &hf_st2031_magazine_hamming,
2473 &hf_st2031_magazine,
2474 &hf_st2031_packet_number_hamming,
2475 &hf_st2031_packet_number,
2476 &hf_st2031_page_units_hamming,
2477 &hf_st2031_page_units,
2478 &hf_st2031_page_tens_hamming,
2479 &hf_st2031_page_tens,
2480 &hf_st2031_data_string,
2481 &hf_st2031_textdata_array,
2482 &hf_st2031_erase_page,
2483 &hf_st2031_newsflash,
2484 &hf_st2031_subtitle,
2485 &hf_st2031_suppress_header,
2486 &hf_st2031_update_indicator,
2487 &hf_st2031_interrupted_sequence,
2488 &hf_st2031_inhibit_display,
2489 &hf_st2031_magazine_serial,
2490 &hf_st2031_character_set,
2491 &hf_st2031_tt_control,
2492};
2493
2494/* Rec. ITU-R BT.653-3, System B national-option character subsets used by Teletext data units. */
2495/* SMPTE ST 2031:2015, Sec. 6, Table 2; values originate in ETSI EN 301 775, Sec. 4.4. */
2496static const range_string st2031_data_identifier_vals[] = {
2497 { 0x10, 0x1F, "EBU Teletext/VPS/WSS/CC/VBI sample data" },
2498 { 0x80, 0x98, "User defined" },
2499 { 0x99, 0x9B, "EBU Teletext/VPS/WSS/CC/VBI sample data" },
2500 { 0x9C, 0xFF, "User defined" },
2501 { 0x00, 0xFF, "Reserved for future use" },
2502 { 0, 0, NULL((void*)0) }
2503};
2504
2505/* SMPTE ST 2031:2015, Sec. 6, Table 2; data_unit_id values originate in ETSI EN 301 775, Sec. 4.5. */
2506static const range_string st2031_data_unit_id_vals[] = {
2507 { 0x00, 0x01, "DVB reserved" },
2508 { 0x02, 0x02, "EBU Teletext non-subtitle data" },
2509 { 0x03, 0x03, "EBU Teletext subtitle data" },
2510 { 0x04, 0x7F, "DVB reserved" },
2511 { 0x80, 0xBF, "User defined" },
2512 { 0xC0, 0xC0, "Inverted Teletext" },
2513 { 0xC1, 0xC2, "DVB reserved" },
2514 { 0xC3, 0xC3, "VPS" },
2515 { 0xC4, 0xC4, "WSS" },
2516 { 0xC5, 0xC5, "CEA-608 Closed Captioning" },
2517 { 0xC6, 0xC6, "monochrome 4:2:2 samples" },
2518 { 0xC7, 0xCF, "User defined" },
2519 { 0xD0, 0xD0, "AMOL48" },
2520 { 0xD1, 0xD1, "AMOL96" },
2521 { 0xDA, 0xE5, "SCTE reserved" },
2522 { 0xE6, 0xFE, "SCTE user defined" },
2523 { 0xFF, 0xFF, "MPEG stuffing" },
2524 { 0x00, 0xFF, "Reserved or user defined" },
2525 { 0, 0, NULL((void*)0) }
2526};
2527
2528/* ETSI EN 301 775, Sec. 4.5.2 carries a 42-byte Teletext data block;
2529 * packet addressing, page/control bits and character data follow Rec. ITU-R BT.653-3 System B. */
2530/* SMPTE ST 2031:2015, Secs. 5-6, Tables 1-2; ETSI EN 301 775 Sec. 4.5 for Teletext fields. */
2531static int
2532dissect_st2031(tvbuff_t *tvb, packet_info *pinfo _U___attribute__((unused)), proto_tree *tree, void *data)
2533{
2534 const st291_vanc_dissector_data_t *st291_data = (const st291_vanc_dissector_data_t *)data;
2535 proto_tree *top_tree = st291_data && st291_data->top_tree ? st291_data->top_tree : tree;
2536 proto_item *ti;
2537 proto_tree *st2031_tree;
2538 uint8_t unit_id;
2539 tvbuff_t *wst_tvb;
2540
2541 if (tvb_captured_length(tvb) < 2)
2542 return 0;
2543
2544 ti = proto_tree_add_item(top_tree, proto_st2031, tvb, 0, -1, ENC_NA0x00000000);
2545 st2031_tree = proto_item_add_subtree(ti, ett_st2031);
2546
2547 /* SMPTE ST 2031:2015, Sec. 6, Table 2 -- data_identifier,
2548 * data_unit_id and data_unit_length. */
2549 proto_tree_add_item(st2031_tree, hf_st2031_data_identifier, tvb, 0, 1, ENC_BIG_ENDIAN0x00000000);
2550 proto_tree_add_item(st2031_tree, hf_st2031_data_unit_id, tvb, 1, 1, ENC_BIG_ENDIAN0x00000000);
2551 unit_id = tvb_get_uint8(tvb, 1);
2552
2553 if ((unit_id == 0x02 || unit_id == 0x03) && tvb_captured_length(tvb) >= 47) {
2554 proto_tree_add_item(st2031_tree, hf_st2031_data_unit_length, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
2555 /* ETSI EN 301 775, Secs. 4.5.1-4.5.2, Tables 4-5 --
2556 * field_parity, line_offset, framing_code and Teletext data block. */
2557 proto_tree_add_item(st2031_tree, hf_st2031_field_parity, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
2558 proto_tree_add_item(st2031_tree, hf_st2031_line_offset, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
2559 proto_tree_add_item(st2031_tree, hf_st2031_framing_code, tvb, 4, 1, ENC_BIG_ENDIAN0x00000000);
2560 wst_tvb = tvb_new_subset_length(tvb, 5, 42);
2561 st291_process_wst_packet(wst_tvb, st2031_tree, &st2031_wst_fields);
2562 }
2563
2564 return tvb_captured_length(tvb);
2565}
2566
2567void
2568proto_register_st2031(void)
2569{
2570 static hf_register_info hf[] = {
2571 { &hf_st2031_data_identifier,
2572 { "Data Identifier", "st2031.data_identifier", FT_UINT8,
2573 BASE_HEX | BASE_RANGE_STRING0x00000100, RVALS(st2031_data_identifier_vals)((0 ? (const struct _range_string*)0 : ((st2031_data_identifier_vals
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2574 { &hf_st2031_data_unit_id,
2575 { "Data Unit ID", "st2031.data_unit_id", FT_UINT8, BASE_HEX | BASE_RANGE_STRING0x00000100,
2576 RVALS(st2031_data_unit_id_vals)((0 ? (const struct _range_string*)0 : ((st2031_data_unit_id_vals
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2577 { &hf_st2031_data_unit_length,
2578 { "Data Unit Length", "st2031.data_unit_length", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,
2579 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2580 { &hf_st2031_field_parity,
2581 { "Field Parity", "st2031.field_parity", FT_BOOLEAN, 8,
2582 TFS(&st2031_tfs_field_parity)((0 ? (const struct true_false_string*)0 : ((&st2031_tfs_field_parity
))))
, 0x20, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2583 { &hf_st2031_line_offset,
2584 { "Line Offset", "st2031.line_offset", FT_UINT8, BASE_DEC, NULL((void*)0), 0x1F, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2585 { &hf_st2031_framing_code,
2586 { "Framing Code", "st2031.framing_code", FT_UINT8, BASE_HEX, NULL((void*)0), 0xFF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2587 { &hf_st2031_magazine_hamming,
2588 { "Magazine (Hamming 8/4)", "st2031.teletext.magazine_hamming", FT_UINT16, BASE_DEC,
2589 NULL((void*)0), 0xFC00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2590 { &hf_st2031_magazine,
2591 { "Magazine", "st2031.teletext.magazine", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2592 { &hf_st2031_packet_number_hamming,
2593 { "Packet Number (Hamming 8/4)", "st2031.teletext.packet_number_hamming", FT_UINT16,
2594 BASE_DEC, NULL((void*)0), 0x03FF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2595 { &hf_st2031_packet_number,
2596 { "Packet Number", "st2031.teletext.packet_number", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,
2597 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2598 { &hf_st2031_page_units_hamming,
2599 { "Page Units (Hamming 8/4)", "st2031.teletext.page_units_hamming", FT_UINT8,
2600 BASE_HEX, NULL((void*)0), 0xFF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2601 { &hf_st2031_page_units,
2602 { "Page Units", "st2031.teletext.page_units", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0),
2603 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2604 { &hf_st2031_page_tens_hamming,
2605 { "Page Tens (Hamming 8/4)", "st2031.teletext.page_tens_hamming", FT_UINT8,
2606 BASE_HEX, NULL((void*)0), 0xFF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2607 { &hf_st2031_page_tens,
2608 { "Page Tens", "st2031.teletext.page_tens", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0),
2609 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2610 { &hf_st2031_data_string,
2611 { "Data String", "st2031.teletext.data_string", FT_STRING, BASE_NONE, NULL((void*)0), 0x0,
2612 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2613 { &hf_st2031_textdata_array,
2614 { "Text Data", "st2031.teletext.text_data", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0),
2615 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2616 { &hf_st2031_erase_page,
2617 { "Erase Page", "st2031.teletext.erase_page", FT_BOOLEAN, 8, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2618 { &hf_st2031_newsflash,
2619 { "Newsflash", "st2031.teletext.newsflash", FT_BOOLEAN, 8, NULL((void*)0), 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2620 { &hf_st2031_subtitle,
2621 { "Subtitle", "st2031.teletext.subtitle", FT_BOOLEAN, 8, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2622 { &hf_st2031_suppress_header,
2623 { "Suppress Header", "st2031.teletext.suppress_header", FT_BOOLEAN, 8, NULL((void*)0), 0x40,
2624 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2625 { &hf_st2031_update_indicator,
2626 { "Update Indicator", "st2031.teletext.update_indicator", FT_BOOLEAN, 8, NULL((void*)0), 0x10,
2627 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2628 { &hf_st2031_interrupted_sequence,
2629 { "Interrupted Sequence", "st2031.teletext.interrupted_sequence", FT_BOOLEAN, 8,
2630 NULL((void*)0), 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2631 { &hf_st2031_inhibit_display,
2632 { "Inhibit Display", "st2031.teletext.inhibit_display", FT_BOOLEAN, 8, NULL((void*)0), 0x01,
2633 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2634 { &hf_st2031_magazine_serial,
2635 { "Magazine Serial", "st2031.teletext.magazine_serial", FT_BOOLEAN, 8, NULL((void*)0), 0x40,
2636 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2637 { &hf_st2031_character_set,
2638 { "Character Subset", "st2031.teletext.character_set", FT_UINT8, BASE_DEC,
2639 VALS(st291_wst_national_subset_vals)((0 ? (const struct _value_string*)0 : ((st291_wst_national_subset_vals
))))
, 0x15, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2640 { &hf_st2031_tt_control,
2641 { "Teletext Control", "st2031.teletext.control", FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
2642 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2643 };
2644 static int *ett[] = { &ett_st2031 };
2645
2646 proto_st2031 = proto_register_protocol(
2647 "SMPTE ST 2031 VBI Data", "ST 2031", "st2031");
2648 proto_register_field_array(proto_st2031, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
2649 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
2650
2651 st2031_handle = register_dissector("st2031", dissect_st2031, proto_st2031);
2652}
2653
2654void
2655proto_reg_handoff_st2031(void)
2656{
2657 dissector_add_uint("st291.did_sdid", ST2031_DID_SDID_KEY0x4108, st2031_handle);
2658}
2659
2660/*
2661 * Free TV Australia OP-47 / SMPTE RDD 8 teletext
2662 */
2663
2664static const st291_wst_fields_t op47_wst_fields = {
2665 &hf_op47_magazine_hamming,
2666 &hf_op47_magazine,
2667 &hf_op47_packet_number_hamming,
2668 &hf_op47_packet_number,
2669 &hf_op47_page_units_hamming,
2670 &hf_op47_page_units,
2671 &hf_op47_page_tens_hamming,
2672 &hf_op47_page_tens,
2673 &hf_op47_data_string,
2674 &hf_op47_textdata_array,
2675 &hf_op47_erase_page,
2676 &hf_op47_newsflash,
2677 &hf_op47_subtitle,
2678 &hf_op47_suppress_header,
2679 &hf_op47_update_indicator,
2680 &hf_op47_interrupted_sequence,
2681 &hf_op47_inhibit_display,
2682 &hf_op47_magazine_serial,
2683 &hf_op47_character_set,
2684 &hf_op47_tt_control,
2685};
2686
2687/* Rec. ITU-R BT.653-3, System B national-option character subsets used by OP-47 WST data. */
2688/* OP-47 Issue 6, Sec. 5.5.2 carries a System B WST packet; magazine,
2689 * packet number, page address, control bits and text follow Rec. ITU-R BT.653-3. */
2690/* Free TV Australia OP-47 Issue 6, Secs. 5.1, 5.4 and 5.5, Fig. 2. */
2691static int
2692dissect_op47(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2693{
2694 const st291_vanc_dissector_data_t *st291_data = (const st291_vanc_dissector_data_t *)data;
2695 proto_tree *top_tree = st291_data && st291_data->top_tree ? st291_data->top_tree : tree;
2696 proto_item *ti;
2697 proto_tree *op47_tree;
2698 unsigned len = tvb_captured_length(tvb);
2699 uint8_t format_code;
2700 unsigned offset_a = 4, offset_b = 9, i;
2701
2702 if (len < 4)
2703 return 0;
2704
2705 ti = proto_tree_add_item(top_tree, proto_op47, tvb, 0, -1, ENC_NA0x00000000);
2706 op47_tree = proto_item_add_subtree(ti, ett_op47);
2707
2708 /* OP-47 Issue 6, Sec. 5.1 and Fig. 2 -- SDP identifier, length and format code. */
2709 proto_tree_add_item(op47_tree, hf_op47_sdp_identifier, tvb, 0, 2, ENC_BIG_ENDIAN0x00000000);
2710 proto_tree_add_item(op47_tree, hf_op47_sdp_length, tvb, 2, 1, ENC_BIG_ENDIAN0x00000000);
2711 proto_tree_add_item(op47_tree, hf_op47_sdp_format_code, tvb, 3, 1, ENC_BIG_ENDIAN0x00000000);
2712 format_code = tvb_get_uint8(tvb, 3);
2713 if (format_code != 0x02 || len < 9)
2714 return len;
2715
2716 /* OP-47 Issue 6, Sec. 5.4 -- Packet Descriptor Structure A / adaptation header. */
2717 ti = proto_tree_add_item(op47_tree, hf_op47_sdp_adaption_header, tvb, 4, 5, ENC_NA0x00000000);
2718 proto_item_set_generated(ti);
2719
2720 for (i = 0; i < 5; i++) {
2721 uint8_t pkt_desc_a;
2722 uint8_t *flipped;
2723 tvbuff_t *wst_tvb;
2724 proto_tree *wst_tree;
2725
2726 if (offset_a >= len)
2727 break;
2728 pkt_desc_a = tvb_get_uint8(tvb, offset_a);
2729 if (pkt_desc_a == 0)
2730 break;
2731 if (offset_b + 45 > len)
2732 break;
2733
2734 /* OP-47 Issue 6, Sec. 5.5 -- Packet Descriptor Structure B;
2735 * Secs. 5.5.1-5.5.2 define clock run-in, framing code and WST data. */
2736 ti = proto_tree_add_item(op47_tree, hf_op47_sdp_pkt_desc_b, tvb, offset_b, 45, ENC_NA0x00000000);
2737 proto_item_set_generated(ti);
2738 wst_tree = proto_item_add_subtree(ti, ett_op47_wst);
2739
2740 ti = proto_tree_add_item(wst_tree, hf_op47_clock_runin, tvb, offset_b, 2, ENC_BIG_ENDIAN0x00000000);
2741 proto_item_set_generated(ti);
2742 ti = proto_tree_add_item(wst_tree, hf_op47_framing_code, tvb, offset_b + 2, 1, ENC_BIG_ENDIAN0x00000000);
2743 proto_item_set_generated(ti);
2744
2745 flipped = wmem_alloc(pinfo->pool, 42);
2746 tvb_memcpy(tvb, flipped, offset_b + 3, 42);
2747 bitswap_buf_inplace(flipped, 42);
2748
2749 wst_tvb = tvb_new_child_real_data(tvb, flipped, 42, 42);
2750 add_new_data_source(pinfo, wst_tvb, "OP-47 WST data (bit reversed)");
2751 st291_process_wst_packet(wst_tvb, wst_tree, &op47_wst_fields);
2752
2753 offset_a++;
2754 offset_b += 45;
2755 }
2756
2757 return len;
2758}
2759
2760void
2761proto_register_op47(void)
2762{
2763 static hf_register_info hf[] = {
2764 { &hf_op47_sdp_identifier,
2765 { "Identifier", "op47.sdp.identifier", FT_UINT16, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2766 { &hf_op47_sdp_length,
2767 { "Length", "op47.sdp.length", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2768 { &hf_op47_sdp_format_code,
2769 { "Format Code", "op47.sdp.format_code", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2770 { &hf_op47_sdp_adaption_header,
2771 { "Adaption Header", "op47.sdp.adaption_header", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
2772 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2773 { &hf_op47_sdp_pkt_desc_b,
2774 { "Packet Descriptor B", "op47.sdp.packet_descriptor_b", FT_BYTES, BASE_NONE, NULL((void*)0),
2775 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2776 { &hf_op47_clock_runin,
2777 { "Clock Run-In", "op47.wst.clock_runin", FT_UINT16, BASE_HEX, NULL((void*)0), 0xFFFF, NULL((void*)0),
2778 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2779 { &hf_op47_framing_code,
2780 { "Framing Code", "op47.wst.framing_code", FT_UINT8, BASE_HEX, NULL((void*)0), 0xFF, NULL((void*)0),
2781 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2782 { &hf_op47_magazine_hamming,
2783 { "Magazine (Hamming 8/4)", "op47.wst.magazine_hamming", FT_UINT16, BASE_DEC, NULL((void*)0),
2784 0xFC00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2785 { &hf_op47_magazine,
2786 { "Magazine", "op47.wst.magazine", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2787 { &hf_op47_packet_number_hamming,
2788 { "Packet Number (Hamming 8/4)", "op47.wst.packet_number_hamming", FT_UINT16,
2789 BASE_DEC, NULL((void*)0), 0x03FF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2790 { &hf_op47_packet_number,
2791 { "Packet Number", "op47.wst.packet_number", FT_UINT8, BASE_DEC, NULL((void*)0), 0x0, NULL((void*)0),
2792 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2793 { &hf_op47_page_units_hamming,
2794 { "Page Units (Hamming 8/4)", "op47.wst.page_units_hamming", FT_UINT8, BASE_HEX,
2795 NULL((void*)0), 0xFF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2796 { &hf_op47_page_units,
2797 { "Page Units", "op47.wst.page_units", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2798 { &hf_op47_page_tens_hamming,
2799 { "Page Tens (Hamming 8/4)", "op47.wst.page_tens_hamming", FT_UINT8, BASE_HEX, NULL((void*)0),
2800 0xFF, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2801 { &hf_op47_page_tens,
2802 { "Page Tens", "op47.wst.page_tens", FT_UINT8, BASE_HEX, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2803 { &hf_op47_data_string,
2804 { "Data String", "op47.wst.data_string", FT_STRING, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0),
2805 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2806 { &hf_op47_textdata_array,
2807 { "Text Data", "op47.wst.text_data", FT_BYTES, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2808 { &hf_op47_erase_page,
2809 { "Erase Page", "op47.wst.erase_page", FT_BOOLEAN, 8, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2810 { &hf_op47_newsflash,
2811 { "Newsflash", "op47.wst.newsflash", FT_BOOLEAN, 8, NULL((void*)0), 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2812 { &hf_op47_subtitle,
2813 { "Subtitle", "op47.wst.subtitle", FT_BOOLEAN, 8, NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2814 { &hf_op47_suppress_header,
2815 { "Suppress Header", "op47.wst.suppress_header", FT_BOOLEAN, 8, NULL((void*)0), 0x40, NULL((void*)0),
2816 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2817 { &hf_op47_update_indicator,
2818 { "Update Indicator", "op47.wst.update_indicator", FT_BOOLEAN, 8, NULL((void*)0), 0x10, NULL((void*)0),
2819 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2820 { &hf_op47_interrupted_sequence,
2821 { "Interrupted Sequence", "op47.wst.interrupted_sequence", FT_BOOLEAN, 8, NULL((void*)0),
2822 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2823 { &hf_op47_inhibit_display,
2824 { "Inhibit Display", "op47.wst.inhibit_display", FT_BOOLEAN, 8, NULL((void*)0), 0x01, NULL((void*)0),
2825 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2826 { &hf_op47_magazine_serial,
2827 { "Magazine Serial", "op47.wst.magazine_serial", FT_BOOLEAN, 8, NULL((void*)0), 0x40, NULL((void*)0),
2828 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2829 { &hf_op47_character_set,
2830 { "Character Subset", "op47.wst.character_set", FT_UINT8, BASE_DEC,
2831 VALS(st291_wst_national_subset_vals)((0 ? (const struct _value_string*)0 : ((st291_wst_national_subset_vals
))))
, 0x15, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2832 { &hf_op47_tt_control,
2833 { "Teletext Control", "op47.wst.control", FT_NONE, BASE_NONE, NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } },
2834 };
2835 static int *ett[] = {
2836 &ett_op47,
2837 &ett_op47_wst,
2838 };
2839
2840 proto_op47 = proto_register_protocol(
2841 "RDD 8 / OP-47 Subtitle Distribution Packet", "OP-47", "op47");
2842 proto_register_field_array(proto_op47, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
2843 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
2844
2845 op47_handle = register_dissector("op47", dissect_op47, proto_op47);
2846}
2847
2848void
2849proto_reg_handoff_op47(void)
2850{
2851 dissector_add_uint("st291.did_sdid", OP47_DID_SDID_KEY0x4302, op47_handle);
2852}
2853
2854/*
2855 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2856 *
2857 * Local variables:
2858 * c-basic-offset: 4
2859 * tab-width: 8
2860 * indent-tabs-mode: nil
2861 * End:
2862 *
2863 * vi: set shiftwidth=4 tabstop=8 expandtab:
2864 * :indentSize=4:tabSize=8:noTabs=true:
2865 */