2 * Routines for VP9 dissection
3 * Copyright 2023, Noan Perrot <noan.perrot@gmail.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * vp9-bitstream-specification-v0.6-20160331-draft - VP9 Bitstream & Decoding Process Specification
14 * draft-ietf-payload-vp9-16 - RTP Payload Format for VP9 Video
18 /* Define the name for the logging domain (try to avoid collisions with existing domains) */
19 #define WS_LOG_DOMAIN "vp9"
21 /* Global header providing a minimum base set of required macros and APIs */
22 #include <wireshark.h>
24 #include <epan/packet.h> /* Required dissection API header */
25 #include <epan/expert.h> /* Include only as needed */
26 #include <epan/prefs.h> /* Include only as needed */
28 #define STRING_SIZE 50
29 #define VP9_1_BIT_MASK 0x80
30 #define VP9_2_BIT_MASK 0x40
31 #define VP9_3_BIT_MASK 0x20
32 #define VP9_4_BIT_MASK 0x10
33 #define VP9_5_BIT_MASK 0x08
34 #define VP9_6_BIT_MASK 0x04
35 #define VP9_7_BIT_MASK 0x02
36 #define VP9_8_BIT_MASK 0x01
37 #define VP9_2_BITS_MASK 0xC0
38 #define VP9_3_BITS_MASK 0xE0
39 #define VP9_7_BITS_MASK 0xFE
40 #define VP9_8_BITS_MASK 0xFF
41 #define VP9_16_BITS_MASK 0xFFFF
42 #define VP9_EXTENDED_PID 0x7FFF
46 static int hf_vp9_pld_i_bit
;
47 static int hf_vp9_pld_p_bit
;
48 static int hf_vp9_pld_l_bit
;
49 static int hf_vp9_pld_f_bit
;
50 static int hf_vp9_pld_b_bit
;
51 static int hf_vp9_pld_e_bit
;
52 static int hf_vp9_pld_v_bit
;
53 static int hf_vp9_pld_z_bit
;
54 static int hf_vp9_pld_u_bit
;
55 static int hf_vp9_pld_m_bit
;
56 static int hf_vp9_pld_d_bit
;
57 static int hf_vp9_pld_n_bit
;
58 static int hf_vp9_pld_y_bit
;
59 static int hf_vp9_pld_g_bit
;
60 static int hf_vp9_pld_pg_bits
;
61 static int hf_vp9_pld_n_s_bits
;
62 static int hf_vp9_pld_n_g_bits
;
63 static int hf_vp9_pld_sid_bits
;
64 static int hf_vp9_pld_pid_bits
;
65 static int hf_vp9_pld_tid_bits
;
66 static int hf_vp9_pld_width_bits
;
67 static int hf_vp9_pld_height_bits
;
68 static int hf_vp9_pld_n_s_numbers
;
69 static int hf_vp9_pld_p_diff_bits
;
70 static int hf_vp9_pld_tl0picidx_bits
;
71 static int hf_vp9_pld_pg_extended_bits
;
72 static int hf_vp9_pld_pid_extended_bits
;
75 static int ett_vp9_descriptor
;
83 dissect_vp9(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree _U_
, void *data _U_
)
85 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "VP9");
87 proto_item
*vp9_item
= proto_tree_add_item(tree
, proto_vp9
, tvb
, 0, -1, ENC_NA
);
88 proto_tree
*vp9_tree
= proto_item_add_subtree(vp9_item
, ett_vp9
);
90 proto_item
*vp9_descriptor_item
;
91 proto_tree
*vp9_descriptor_tree
= proto_tree_add_subtree(vp9_tree
, tvb
, 0, 1, ett_vp9_descriptor
, &vp9_descriptor_item
, "Payload Descriptor");
98 |I|P|L|F|B|E|V|Z| (REQUIRED)
101 uint8_t i
= tvb_get_uint8(tvb
, offset
) & VP9_1_BIT_MASK
;
102 uint8_t p
= tvb_get_uint8(tvb
, offset
) & VP9_2_BIT_MASK
;
103 uint8_t l
= tvb_get_uint8(tvb
, offset
) & VP9_3_BIT_MASK
;
104 uint8_t f
= tvb_get_uint8(tvb
, offset
) & VP9_4_BIT_MASK
;
105 uint8_t v
= tvb_get_uint8(tvb
, offset
) & VP9_7_BIT_MASK
;
106 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_i_bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
107 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_p_bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
108 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_l_bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
109 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_f_bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
110 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_b_bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
111 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_e_bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
112 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_v_bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
113 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_z_bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
119 I: |M| PICTURE ID | (REQUIRED)
121 M: | EXTENDED PID | (RECOMMENDED)
124 uint8_t m
= tvb_get_uint8(tvb
, offset
) & VP9_1_BIT_MASK
;
125 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_m_bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
134 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_pid_extended_bits
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
140 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_pid_bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
157 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_pg_extended_bits
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
163 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_pg_bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
175 L: | TID |U| SID |D| (Conditionally RECOMMENDED)
180 // Layer indices present
181 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_tid_bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
182 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_u_bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
183 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_sid_bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
184 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_d_bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
189 // 1 octet is present for the layer indices
190 proto_item_set_len(vp9_descriptor_item
, 4);
194 // 2 octets are present for the layer indices
195 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_tl0picidx_bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
196 proto_item_set_len(vp9_descriptor_item
, 5);
203 P,F: | P_DIFF |N| (Conditionally REQUIRED) - up to 3 times
208 uint8_t n
= tvb_get_uint8(tvb
, offset
) & (VP9_1_BIT_MASK
>> 7);
211 while (n
&& idx
< max_p_diff
)
213 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_p_diff_bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
214 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_n_bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
215 proto_item_set_len(vp9_descriptor_item
, 6);
217 n
= tvb_get_uint8(tvb
, offset
) & (VP9_1_BIT_MASK
>> 7);
219 if (n
&& idx
== max_p_diff
)
239 proto_item
* n_s_numbers_field
;
240 uint8_t n_s
= (tvb_get_uint8(tvb
, offset
) & (VP9_3_BITS_MASK
)) >> 5;
241 uint8_t y
= tvb_get_uint8(tvb
, offset
) & (VP9_1_BIT_MASK
>> 3);
242 uint8_t g
= tvb_get_uint8(tvb
, offset
) & (VP9_1_BIT_MASK
>> 4);
243 uint8_t number_of_spatial_layers
= n_s
+ 1;
245 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_n_s_bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
246 n_s_numbers_field
= proto_tree_add_uint(vp9_descriptor_tree
, hf_vp9_pld_n_s_numbers
, tvb
, offset
, 1, number_of_spatial_layers
);
247 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_y_bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
248 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_g_bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
249 proto_item_set_generated(n_s_numbers_field
);
255 Y: | WIDTH | (OPTIONAL) .
258 +-+-+-+-+-+-+-+-+ . - N_S + 1 times
259 | HEIGHT | (OPTIONAL) .
264 uint8_t spatial_layer
= 0;
265 while (spatial_layer
< number_of_spatial_layers
)
269 // TODO: Add subtree for spatial layers
270 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_width_bits
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
272 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_height_bits
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
280 G: | N_G | (OPTIONAL)
287 N_G: | TID |U| R |-|-| (OPTIONAL) .
288 +-+-+-+-+-+-+-+-+ -\ . - N_G times
289 | P_DIFF | (OPTIONAL) . - R times .
290 +-+-+-+-+-+-+-+-+ -/ -/
292 proto_tree_add_item(vp9_descriptor_tree
, hf_vp9_pld_n_g_bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
298 return tvb_captured_length(tvb
);
301 void proto_register_vp9(void)
303 static hf_register_info hf
[] = {
305 {"Picture ID present (I)", "vp9.pld.i",
307 NULL
, VP9_1_BIT_MASK
,
310 {"Inter-picture predicted frame (P)", "vp9.pld.p",
312 NULL
, VP9_2_BIT_MASK
,
315 {"Layer indices present (L)", "vp9.pld.l",
317 NULL
, VP9_3_BIT_MASK
,
320 {"Flexible mode (F)", "vp9.pld.f",
322 NULL
, VP9_4_BIT_MASK
,
325 {"Start of a frame (B)", "vp9.pld.b",
327 NULL
, VP9_5_BIT_MASK
,
330 {"End of a frame (E)", "vp9.pld.e",
332 NULL
, VP9_6_BIT_MASK
,
335 {"Scalability structure (SS) data present (V)", "vp9.pld.v",
337 NULL
, VP9_7_BIT_MASK
,
340 {"Not a reference frame for upper spatial layers (Z)", "vp9.pld.z",
342 NULL
, VP9_8_BIT_MASK
,
345 {"Extension flag (M)", "vp9.pld.m",
347 NULL
, VP9_1_BIT_MASK
,
349 {&hf_vp9_pld_pid_bits
,
350 {"Picture ID (PID)", "vp9.pld.pid",
352 NULL
, VP9_7_BITS_MASK
>> 1,
354 {&hf_vp9_pld_pid_extended_bits
,
355 {"Picture ID (PID) Extended", "vp9.pld.pid_ext",
357 NULL
, VP9_EXTENDED_PID
,
359 {&hf_vp9_pld_pg_bits
,
360 {"Picture Group Index (PG)", "vp9.pld.pg",
362 NULL
, VP9_7_BITS_MASK
>> 1,
364 {&hf_vp9_pld_pg_extended_bits
,
365 {"Picture Group Index (PG) Extended", "vp9.pld.pg_ext",
367 NULL
, VP9_EXTENDED_PID
,
369 {&hf_vp9_pld_tid_bits
,
370 {"Temporal layer ID", "vp9.pld.tid",
372 NULL
, VP9_3_BITS_MASK
,
375 {"Switching up point (U)", "vp9.pld.u",
377 NULL
, VP9_1_BIT_MASK
>> 3,
379 {&hf_vp9_pld_sid_bits
,
380 {"Spatial Layer ID", "vp9.pld.sid",
382 NULL
, VP9_3_BITS_MASK
>> 4,
385 {"Inter-layer dependency used (D)", "vp9.pld.d",
387 NULL
, VP9_1_BIT_MASK
>> 7,
389 {&hf_vp9_pld_tl0picidx_bits
,
390 {"Temporal layer zero index", "vp9.pld.tl0picidx",
394 {&hf_vp9_pld_p_diff_bits
,
395 {"Reference index (P_DIFF)", "vp9.pld.p_diff",
397 NULL
, VP9_7_BITS_MASK
,
400 {"Additional reference index (N)", "vp9.pld.n",
402 NULL
, VP9_1_BIT_MASK
>> 7,
404 {&hf_vp9_pld_n_s_bits
,
405 {"Spatial layers minus 1 (N_S)", "vp9.pld.n_s",
407 NULL
, VP9_3_BITS_MASK
,
409 {&hf_vp9_pld_n_s_numbers
,
410 {"Number of spatial layers", "vp9.pld.spatial_layers_number",
415 {"Spatial layer's frame resolution present (Y)", "vp9.pld.y",
417 NULL
, VP9_1_BIT_MASK
>> 3,
420 {"PG description flag (G)", "vp9.pld.g",
422 NULL
, VP9_1_BIT_MASK
>> 4,
424 {&hf_vp9_pld_height_bits
,
425 {"Height", "vp9.pld.height",
429 {&hf_vp9_pld_width_bits
,
430 {"Width", "vp9.pld.width",
434 {&hf_vp9_pld_n_g_bits
,
435 {"Number of pictures (N_G)", "vp9.pld.n_g",
440 proto_vp9
= proto_register_protocol("VP9", "VP9", "vp9");
442 proto_register_field_array(proto_vp9
, hf
, array_length(hf
));
443 proto_register_subtree_array(ett
, array_length(ett
));
446 void proto_reg_handoff_vp9(void)
448 static dissector_handle_t vp9_handle
;
450 vp9_handle
= register_dissector("vp9", dissect_vp9
, proto_vp9
);
452 dissector_add_string("rtp_dyn_payload_type", "vp9", vp9_handle
);
453 dissector_add_uint_range_with_preference("rtp.pt", "", vp9_handle
);
457 * Editor modelines - https://www.wireshark.org/tools/modelines.html
462 * indent-tabs-mode: nil
465 * vi: set shiftwidth=4 tabstop=8 expandtab:
466 * :indentSize=4:tabSize=8:noTabs=true: