3 * Routines for RFC 2435 JPEG dissection
6 * Erwin Rol <erwin@erwinrol.com>
8 * Francisco Javier Cabello Torres, <fjcabello@vtools.es>
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * SPDX-License-Identifier: GPL-2.0-or-later
18 #include <epan/packet.h>
20 #include <epan/rtp_pt.h>
22 #include "packet-ber.h"
24 void proto_register_jpeg(void);
25 void proto_reg_handoff_jpeg(void);
27 static dissector_handle_t jpeg_handle
;
29 static const range_string jpeg_ts_rvals
[] = {
30 {0, 0, "Progressively scanned"},
31 {1, 1, "Odd field of interlaced signal"},
32 {2, 2, "Even field of interlaced signal"},
33 {3, 3, "Interlaced field to be line doubled"},
34 {3, 0xff, "Unspecified"},
38 static const range_string jpeg_type_rvals
[] = {
39 { 0, 0, "4:2:2 Video"},
40 { 1, 1, "4:2:0 Video"},
41 { 2, 5, "Reserved"}, /* Previously assigned by RFC 2035 */
42 { 6, 63, "Unassigned"},
43 { 64, 64, "4:2:0 Video, Restart Markers present"},
44 { 65, 65, "4:2:0 Video, Restart Markers present"},
45 { 66, 69, "Reserved"}, /* Since [2,5] are reserved */
46 { 70, 127, "Unassigned, Restart Markers present"},
47 {128, 255, "Dynamically assigned"},
51 static int proto_jpeg
;
53 static int hf_rtp_jpeg_main_hdr
;
54 static int hf_rtp_jpeg_main_hdr_height
;
55 static int hf_rtp_jpeg_main_hdr_offs
;
56 static int hf_rtp_jpeg_main_hdr_q
;
57 static int hf_rtp_jpeg_main_hdr_ts
;
58 static int hf_rtp_jpeg_main_hdr_type
;
59 static int hf_rtp_jpeg_main_hdr_width
;
60 static int hf_rtp_jpeg_payload
;
61 static int hf_rtp_jpeg_qtable_hdr
;
62 static int hf_rtp_jpeg_qtable_hdr_data
;
63 static int hf_rtp_jpeg_qtable_hdr_length
;
64 static int hf_rtp_jpeg_qtable_hdr_mbz
;
65 static int hf_rtp_jpeg_qtable_hdr_prec
;
66 static int hf_rtp_jpeg_restart_hdr
;
67 static int hf_rtp_jpeg_restart_hdr_count
;
68 static int hf_rtp_jpeg_restart_hdr_f
;
69 static int hf_rtp_jpeg_restart_hdr_interval
;
70 static int hf_rtp_jpeg_restart_hdr_l
;
72 /* JPEG fields defining a sub tree */
76 dissect_jpeg( tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
78 proto_item
*ti
= NULL
;
79 proto_tree
*jpeg_tree
= NULL
;
80 proto_tree
*main_hdr_tree
= NULL
;
81 proto_tree
*restart_hdr_tree
= NULL
;
82 proto_tree
*qtable_hdr_tree
= NULL
;
83 uint32_t fragment_offset
= 0;
90 unsigned int offset
= 0;
92 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "JPEG");
94 col_set_str(pinfo
->cinfo
, COL_INFO
, "JPEG message");
97 ti
= proto_tree_add_item( tree
, proto_jpeg
, tvb
, offset
, -1, ENC_NA
);
98 jpeg_tree
= proto_item_add_subtree( ti
, ett_jpeg
);
100 ti
= proto_tree_add_item(jpeg_tree
, hf_rtp_jpeg_main_hdr
, tvb
, offset
, 8, ENC_NA
);
101 main_hdr_tree
= proto_item_add_subtree(ti
, ett_jpeg
);
103 proto_tree_add_item(main_hdr_tree
, hf_rtp_jpeg_main_hdr_ts
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
105 proto_tree_add_item(main_hdr_tree
, hf_rtp_jpeg_main_hdr_offs
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
106 fragment_offset
= tvb_get_ntoh24(tvb
, offset
);
108 proto_tree_add_item(main_hdr_tree
, hf_rtp_jpeg_main_hdr_type
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
109 type
= tvb_get_uint8(tvb
, offset
);
111 proto_tree_add_item(main_hdr_tree
, hf_rtp_jpeg_main_hdr_q
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
112 q
= tvb_get_uint8(tvb
, offset
);
114 w
= tvb_get_uint8(tvb
, offset
) * 8;
115 proto_tree_add_uint(main_hdr_tree
, hf_rtp_jpeg_main_hdr_width
, tvb
, offset
, 1, w
);
117 h
= tvb_get_uint8(tvb
, offset
) * 8;
118 proto_tree_add_uint(main_hdr_tree
, hf_rtp_jpeg_main_hdr_height
, tvb
, offset
, 1, h
);
121 if (type
>= 64 && type
<= 127) {
122 ti
= proto_tree_add_item(jpeg_tree
, hf_rtp_jpeg_restart_hdr
, tvb
, offset
, 4, ENC_NA
);
123 restart_hdr_tree
= proto_item_add_subtree(ti
, ett_jpeg
);
124 proto_tree_add_item(restart_hdr_tree
, hf_rtp_jpeg_restart_hdr_interval
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
126 proto_tree_add_item(restart_hdr_tree
, hf_rtp_jpeg_restart_hdr_f
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
127 proto_tree_add_item(restart_hdr_tree
, hf_rtp_jpeg_restart_hdr_l
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
128 proto_tree_add_item(restart_hdr_tree
, hf_rtp_jpeg_restart_hdr_count
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
132 if (q
>= 128 && fragment_offset
== 0) {
133 ti
= proto_tree_add_item(jpeg_tree
, hf_rtp_jpeg_qtable_hdr
, tvb
, offset
, -1, ENC_NA
);
134 qtable_hdr_tree
= proto_item_add_subtree(ti
, ett_jpeg
);
135 proto_tree_add_item(qtable_hdr_tree
, hf_rtp_jpeg_qtable_hdr_mbz
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
137 proto_tree_add_item(qtable_hdr_tree
, hf_rtp_jpeg_qtable_hdr_prec
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
139 proto_tree_add_item(qtable_hdr_tree
, hf_rtp_jpeg_qtable_hdr_length
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
140 len
= tvb_get_ntohs(tvb
, offset
);
143 proto_tree_add_item(qtable_hdr_tree
, hf_rtp_jpeg_qtable_hdr_data
, tvb
, offset
, len
, ENC_NA
);
146 proto_item_set_len(ti
, len
+ 4);
149 /* The rest of the packet is the JPEG data */
150 proto_tree_add_item( jpeg_tree
, hf_rtp_jpeg_payload
, tvb
, offset
, -1, ENC_NA
);
152 return tvb_captured_length(tvb
);
156 proto_register_jpeg(void)
158 static hf_register_info hf
[] = {
159 { &hf_rtp_jpeg_main_hdr
,
160 { "Main Header", "jpeg.main_hdr",
161 FT_NONE
, BASE_NONE
, NULL
, 0,
164 { &hf_rtp_jpeg_main_hdr_ts
,
165 { "Type Specific", "jpeg.main_hdr.ts",
166 FT_UINT8
, BASE_DEC
|BASE_RANGE_STRING
, RVALS(jpeg_ts_rvals
), 0,
169 { &hf_rtp_jpeg_main_hdr_offs
,
170 { "Fragment Offset", "jpeg.main_hdr.offset",
171 FT_UINT24
, BASE_DEC
, NULL
, 0,
174 { &hf_rtp_jpeg_main_hdr_type
,
175 { "Type", "jpeg.main_hdr.type",
176 FT_UINT8
, BASE_DEC
|BASE_RANGE_STRING
, RVALS(jpeg_type_rvals
), 0,
179 { &hf_rtp_jpeg_main_hdr_q
,
180 { "Q", "jpeg.main_hdr.q",
181 FT_UINT8
, BASE_DEC
, NULL
, 0,
184 { &hf_rtp_jpeg_main_hdr_width
,
185 { "Width", "jpeg.main_hdr.width",
186 FT_UINT8
, BASE_DEC
, NULL
, 0,
189 { &hf_rtp_jpeg_main_hdr_height
,
190 { "Height", "jpeg.main_hdr.height",
191 FT_UINT8
, BASE_DEC
, NULL
, 0,
194 { &hf_rtp_jpeg_restart_hdr
,
195 { "Restart Marker Header", "jpeg.restart_hdr",
196 FT_NONE
, BASE_NONE
, NULL
, 0,
199 { &hf_rtp_jpeg_restart_hdr_interval
,
200 { "Restart Interval", "jpeg.restart_hdr.interval",
201 FT_UINT16
, BASE_DEC
, NULL
, 0,
204 { &hf_rtp_jpeg_restart_hdr_f
,
205 { "F", "jpeg.restart_hdr.f",
206 FT_UINT16
, BASE_DEC
, NULL
, 0x8000,
209 { &hf_rtp_jpeg_restart_hdr_l
,
210 { "L", "jpeg.restart_hdr.l",
211 FT_UINT16
, BASE_DEC
, NULL
, 0x4000,
214 { &hf_rtp_jpeg_restart_hdr_count
,
215 { "Restart Count", "jpeg.restart_hdr.count",
216 FT_UINT16
, BASE_DEC
, NULL
, 0x3FFF,
219 { &hf_rtp_jpeg_qtable_hdr
,
220 { "Quantization Table Header", "jpeg.qtable_hdr",
221 FT_NONE
, BASE_NONE
, NULL
, 0,
224 { &hf_rtp_jpeg_qtable_hdr_mbz
,
225 { "MBZ", "jpeg.qtable_hdr.mbz",
226 FT_UINT8
, BASE_DEC
, NULL
, 0,
229 { &hf_rtp_jpeg_qtable_hdr_prec
,
230 { "Precision", "jpeg.qtable_hdr.precision",
231 FT_UINT8
, BASE_DEC
, NULL
, 0,
234 { &hf_rtp_jpeg_qtable_hdr_length
,
235 { "Length", "jpeg.qtable_hdr.length",
236 FT_UINT16
, BASE_DEC
, NULL
, 0,
239 { &hf_rtp_jpeg_qtable_hdr_data
,
240 { "Quantization Table Data", "jpeg.qtable_hdr.data",
241 FT_BYTES
, BASE_NONE
, NULL
, 0,
244 { &hf_rtp_jpeg_payload
,
245 { "Payload", "jpeg.payload",
246 FT_BYTES
, BASE_NONE
, NULL
, 0,
251 static int *ett
[] = {
255 proto_jpeg
= proto_register_protocol("RFC 2435 JPEG","JPEG","jpeg");
256 proto_register_field_array(proto_jpeg
, hf
, array_length(hf
));
257 proto_register_subtree_array(ett
, array_length(ett
));
259 jpeg_handle
= register_dissector("jpeg", dissect_jpeg
, proto_jpeg
);
262 register_ber_oid_dissector_handle("0.9.2342.19200300.100.1.60", jpeg_handle
, proto_jpeg
, "jpegPhoto");
266 proto_reg_handoff_jpeg(void)
268 dissector_add_uint("rtp.pt", PT_JPEG
, jpeg_handle
);
272 * Editor modelines - https://www.wireshark.org/tools/modelines.html
277 * indent-tabs-mode: t
280 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
281 * :indentSize=8:tabSize=8:noTabs=false: