1 /* MPEG audio packet decoder.
2 * Written by Shaun Jackman <sjackman@gmail.com>.
3 * Copyright 2007 Shaun Jackman
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
8 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include <epan/packet.h>
14 #include <epan/asn1.h>
16 #include <wsutil/mpeg-audio.h>
17 #include <wsutil/array.h>
19 #include "packet-per.h"
21 #include "packet-mpeg-audio-hf.c"
22 #include "packet-mpeg-audio-ett.c"
23 #include "packet-mpeg-audio-fn.c"
25 void proto_register_mpeg_audio(void);
26 void proto_reg_handoff_mpeg_audio(void);
28 dissector_handle_t mpeg_audio_handle
;
30 static int proto_mpeg_audio
;
31 static dissector_handle_t id3v2_handle
;
33 static int hf_mpeg_audio_header
;
34 static int hf_mpeg_audio_data
;
35 static int hf_mpeg_audio_padbytes
;
38 static int ett_mpeg_audio
;
41 test_mpeg_audio(tvbuff_t
*tvb
, int offset
)
46 if (!tvb_bytes_exist(tvb
, offset
, 4))
48 if (tvb_strneql(tvb
, offset
, "TAG", 3) == 0)
50 if (tvb_strneql(tvb
, offset
, "ID3", 3) == 0)
53 hdr
= tvb_get_uint32(tvb
, offset
, ENC_BIG_ENDIAN
);
54 MPA_UNMARSHAL(&mpa
, hdr
);
55 return MPA_VALID(&mpa
);
59 mpeg_resync(tvbuff_t
*tvb
, int offset
)
64 /* This only looks to resync on another frame; it doesn't
65 * look for an ID3 tag.
67 offset
= tvb_find_uint8(tvb
, offset
, -1, '\xff');
68 while (offset
!= -1 && tvb_bytes_exist(tvb
, offset
, 4)) {
69 hdr
= tvb_get_uint32(tvb
, offset
, ENC_BIG_ENDIAN
);
70 MPA_UNMARSHAL(&mpa
, hdr
);
71 if (MPA_VALID(&mpa
)) {
74 offset
= tvb_find_uint8(tvb
, offset
+ 1, -1, '\xff');
76 return tvb_reported_length(tvb
);
80 dissect_mpeg_audio_frame(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
87 static const char *version_names
[] = { "1", "2", "2.5" };
89 if (!tvb_bytes_exist(tvb
, 0, 4))
92 h
= tvb_get_ntohl(tvb
, 0);
93 MPA_UNMARSHAL(&mpa
, h
);
94 if (!MPA_SYNC_VALID(&mpa
) || !MPA_VERSION_VALID(&mpa
) || !MPA_LAYER_VALID(&mpa
)) {
98 col_add_fstr(pinfo
->cinfo
, COL_PROTOCOL
,
99 "MPEG-%s", version_names
[mpa_version(&mpa
)]);
100 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
101 "Audio Layer %d", mpa_layer(&mpa
) + 1);
102 if (MPA_BITRATE_VALID(&mpa
) && MPA_FREQUENCY_VALID(&mpa
)) {
103 data_size
= (int)(MPA_DATA_BYTES(&mpa
) - sizeof mpa
);
104 col_append_fstr(pinfo
->cinfo
, COL_INFO
,
106 mpa_bitrate(&mpa
) / 1000,
107 mpa_frequency(&mpa
) / (float)1000);
110 asn1_ctx_init(&asn1_ctx
, ASN1_ENC_PER
, true, pinfo
);
111 offset
= dissect_mpeg_audio_Audio(tvb
, offset
, &asn1_ctx
,
112 tree
, hf_mpeg_audio_header
);
114 unsigned int padding
;
116 proto_tree_add_item(tree
, hf_mpeg_audio_data
, tvb
,
117 offset
/ 8, data_size
, ENC_NA
);
118 offset
+= data_size
* 8;
119 padding
= mpa_padding(&mpa
);
121 proto_tree_add_item(tree
, hf_mpeg_audio_padbytes
, tvb
,
122 offset
/ 8, padding
, ENC_NA
);
123 offset
+= padding
* 8;
130 dissect_id3v1(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
134 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ID3v1");
135 col_clear(pinfo
->cinfo
, COL_INFO
);
136 asn1_ctx_init(&asn1_ctx
, ASN1_ENC_PER
, true, pinfo
);
137 return dissect_mpeg_audio_ID3v1(tvb
, 0, &asn1_ctx
,
142 dissect_mpeg_audio(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
145 proto_tree
*mpeg_audio_tree
;
147 int magic
, offset
= 0;
151 ti
= proto_tree_add_item(tree
, proto_mpeg_audio
, tvb
, offset
, -1, ENC_NA
);
152 mpeg_audio_tree
= proto_item_add_subtree(ti
, ett_mpeg_audio
);
153 while (tvb_reported_length_remaining(tvb
, offset
) >= 4) {
154 next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
155 magic
= tvb_get_ntoh24(next_tvb
, 0);
157 case 0x544147: /* TAG */
158 offset
+= dissect_id3v1(next_tvb
, pinfo
, mpeg_audio_tree
);
160 case 0x494433: /* ID3 */
161 offset
+= call_dissector(id3v2_handle
, tvb
, pinfo
, mpeg_audio_tree
);
164 frame_len
= dissect_mpeg_audio_frame(next_tvb
, pinfo
, mpeg_audio_tree
);
165 if (frame_len
== 0) {
166 frame_len
= mpeg_resync(next_tvb
, 0);
171 return tvb_reported_length(tvb
);
175 dissect_mpeg_audio_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
177 if (!test_mpeg_audio(tvb
, 0)) {
180 dissect_mpeg_audio(tvb
, pinfo
, tree
, data
);
185 proto_register_mpeg_audio(void)
187 static hf_register_info hf
[] = {
188 #include "packet-mpeg-audio-hfarr.c"
189 { &hf_mpeg_audio_header
,
190 { "Frame Header", "mpeg-audio.header",
191 FT_NONE
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
192 { &hf_mpeg_audio_data
,
193 { "Data", "mpeg-audio.data",
194 FT_BYTES
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
195 { &hf_mpeg_audio_padbytes
,
196 { "Padding", "mpeg-audio.padbytes",
197 FT_BYTES
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
200 { "ID3v1", "mpeg-audio.id3v1",
201 FT_NONE
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
204 static int *ett
[] = {
206 #include "packet-mpeg-audio-ettarr.c"
209 proto_mpeg_audio
= proto_register_protocol("Moving Picture Experts Group Audio", "MPEG Audio", "mpeg-audio");
210 proto_register_field_array(proto_mpeg_audio
, hf
, array_length(hf
));
211 proto_register_subtree_array(ett
, array_length(ett
));
213 mpeg_audio_handle
= register_dissector("mpeg-audio", dissect_mpeg_audio
, proto_mpeg_audio
);
217 proto_reg_handoff_mpeg_audio(void)
219 dissector_add_string("media_type", "audio/mpeg", mpeg_audio_handle
);
220 /* "audio/mp3" used by Chrome before 2020 */
221 /* https://chromium.googlesource.com/chromium/src/+/842f46a95f49e24534ad35c7a71e5c425d426550 */
222 dissector_add_string("media_type", "audio/mp3", mpeg_audio_handle
);
224 heur_dissector_add("mpeg", dissect_mpeg_audio_heur
, "MPEG Audio", "mpeg_audio", proto_mpeg_audio
, HEURISTIC_ENABLE
);
226 id3v2_handle
= find_dissector("id3v2");