4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include <wireshark.h>
15 #include "wsutil/codecs.h"
16 #include "ws_attributes.h"
18 #include <opencore-amrnb/interf_dec.h>
20 void codec_register_amr(void);
23 codec_amr_init(codec_context_t
*ctx _U_
)
26 state
= Decoder_Interface_init();
32 codec_amr_release(codec_context_t
*state
)
34 Decoder_Interface_exit(state
->priv
);
38 codec_amr_get_channels(codec_context_t
*ctx _U_
)
44 codec_amr_get_frequency(codec_context_t
*ctx _U_
)
49 /* RTP doesn't allow the other SID types */
50 static const uint8_t speech_bits
[16] = {95,103,118,134,148,159,204,244,39, 0, 0, 0, 0, 0, 0, 0};
51 /* The number of speech bits rounded up to bytes */
52 static const uint8_t block_size
[16] = {12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0};
54 static const uint8_t bit_mask8
[] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
56 /* Retrieve no_of_bits (<= 8) from in, starting at bit_offset.
57 * Does not do bounds checking.
60 get_bits8(uint8_t *in
, unsigned bit_offset
, const unsigned no_of_bits
)
63 unsigned octet_offset
= bit_offset
>> 3;
64 unsigned bits_in_first_octet
= 8 - (bit_offset
% 8);
65 if (bits_in_first_octet
>= no_of_bits
) {
66 ret
= in
[octet_offset
] >> (bits_in_first_octet
- no_of_bits
) & bit_mask8
[no_of_bits
];
68 unsigned left_shift
= no_of_bits
- bits_in_first_octet
;
69 ret
= (in
[octet_offset
] << left_shift
) & bit_mask8
[no_of_bits
];
70 ret
|= (in
[octet_offset
+ 1] >> (8 - left_shift
));
76 codec_amr_decode_one(void *state
, const void *input
, size_t inputSizeBytes
,
77 void *output
, size_t *outputSizeBytes
)
82 packet_size
= 2; /* CMR + TOC */
84 /* 160 samples per frame, two byte per frame, 20ms */
85 *outputSizeBytes
= 160 * 2;
87 /* If no room for CMR + TOC, insert silence */
88 if (packet_size
> inputSizeBytes
) {
89 memset(output
, 0, 160 * 2);
90 return *outputSizeBytes
;
93 in
= (uint8_t*)input
+ 1;
94 mode
= (in
[0] >> 3) & 0x0F;
95 packet_size
+= block_size
[mode
];
97 /* If the size is screwed up, insert silence */
98 if (packet_size
> inputSizeBytes
) {
99 memset(output
, 0, 160 * 2);
100 return *outputSizeBytes
;
103 /* XXX: The last parameter is the BFI - we could invert the
104 * Q-bit and pass it in, which might be better?
106 Decoder_Interface_Decode(state
, in
, (short *)output
, 0);
107 return *outputSizeBytes
;
111 codec_amr_decode_many(void *state
, const void *input
, size_t inputSizeBytes
,
112 void *output
, size_t *outputSizeBytes
, unsigned frames
)
115 unsigned packet_size
= 1; /* CMR */
117 *outputSizeBytes
= 160 * 2 * frames
;
119 uint8_t *toc
= (uint8_t *)input
+ 1;
120 uint8_t *speech
= toc
+ frames
;
123 for (unsigned i
= 0; i
< frames
; i
++) {
124 mode
= (toc
[i
] >> 3) & 0x0F;
125 packet_size
+= block_size
[mode
] + 1; /* include the TOC */
127 /* If the size is screwed up, insert silence */
128 if (packet_size
> inputSizeBytes
) {
129 memset(output
, 0, 160 * 2 * (frames
- i
));
130 return *outputSizeBytes
;
133 /* OpenCORE-AMR ignores the F-bit (which is why we're doing
134 * this memcpy) but might as well clear it.
136 in
[0] = toc
[i
] & 0x7F;
137 memcpy(&in
[1], speech
, block_size
[mode
]);
138 /* XXX: The last parameter is the BFI - we could invert the
139 * Q-bit and pass it in, which might be better?
141 Decoder_Interface_Decode(state
, in
, (short *)output
, 0);
142 speech
+= block_size
[mode
];
143 output
= (uint8_t *)output
+ 160 * 2;
146 return *outputSizeBytes
;
150 codec_amr_decode_oa(codec_context_t
*ctx
, const void *input
,
151 size_t inputSizeBytes
, void *output
, size_t *outputSizeBytes
)
155 void *state
= ctx
->priv
;
157 /* First byte is CMR, second is the Payload TOC */
158 if (inputSizeBytes
< 2) {
161 uint8_t *in
= (uint8_t *)input
;
163 f_bit
= (in
[++frames
] >> 7) & 0x01;
164 } while (f_bit
&& inputSizeBytes
> frames
+ 1);
167 /* 160 samples per frame, two byte per frame, 20ms */
168 if (!output
|| !outputSizeBytes
)
169 return 160 * 2 * frames
;
172 return codec_amr_decode_one(state
, input
, inputSizeBytes
, output
, outputSizeBytes
);
174 return codec_amr_decode_many(state
, input
, inputSizeBytes
, output
, outputSizeBytes
, frames
);
179 codec_amr_decode(codec_context_t
*ctx
, const void *input
,
180 size_t inputSizeBytes
, void *output
, size_t *outputSizeBytes
)
184 void *state
= ctx
->priv
;
187 const char* octet_align
= (const char *)wmem_map_lookup(ctx
->fmtp_map
, "octet-align");
188 /* There's a few other lesser used options like "crc", "interleaving",
189 * and "robust-sorting" that can change how it should be decoded.
190 * (All of them imply octet-aligned.) Ideally we'd handle them too.
192 if (g_strcmp0(octet_align
, "1") == 0) {
193 return codec_amr_decode_oa(ctx
, input
, inputSizeBytes
, output
, outputSizeBytes
);
197 unsigned bit_offset
= 4;
198 uint8_t *in
= (uint8_t *)input
;
199 /* Per RFC 4867, if the format parameters don't indicate octet-align,
200 * bandwidth-efficient mode is used. (For Decode As, we'll pass in
201 * the value of the dissector's prefs.)
202 * OpenCORE-AMR's interface only supports octet-aligned mode, so we
203 * have to align the data. (From the source, the decode also supports
204 * IF2, except that there's no way to access that from the interface.)
206 /* First byte is CMR, second is the Payload TOC */
207 if (inputSizeBytes
< 2) {
211 f_bit
= get_bits8(in
, bit_offset
, 1);
214 } while (f_bit
&& inputSizeBytes
> (bit_offset
/ 8));
217 /* 160 samples per frame, two byte per frame, 20ms */
218 if (!output
|| !outputSizeBytes
)
219 return 160 * 2 * frames
;
221 *outputSizeBytes
= 160 * 2 * frames
;
222 /* bit_offset is now where the speech bits begin */
223 unsigned toc_offset
= 5; /* Mode start */
226 for (unsigned i
= 0; i
< frames
; ++i
) {
227 mode
= get_bits8(in
, toc_offset
, 4);
229 /* If the size is screwed up, insert silence */
230 if ((bit_offset
+ speech_bits
[mode
] + 7) / 8 > inputSizeBytes
) {
231 memset(output
, 0, 160 * 2 * (frames
- i
));
232 return *outputSizeBytes
;
235 memset(aligned
, 0, 32);
236 aligned
[0] = mode
<< 3;
237 for (unsigned j
= 0; j
< speech_bits
[mode
] / 8U; ++j
) {
238 aligned
[1 + j
] = get_bits8(in
, bit_offset
, 8);
241 if (speech_bits
[mode
] % 8) {
242 aligned
[1 + block_size
[mode
]] = get_bits8(in
, bit_offset
, speech_bits
[mode
] % 8);
244 /* Padding might be different. */
246 /* XXX: The last parameter is the BFI - we could invert the
247 * Q-bit and pass it in, which might be better?
249 Decoder_Interface_Decode(state
, aligned
, (short *)output
, 0);
250 output
= (uint8_t *)output
+ 160 * 2;
253 return *outputSizeBytes
;
257 codec_register_amr(void)
259 register_codec("AMR", codec_amr_init
, codec_amr_release
,
260 codec_amr_get_channels
, codec_amr_get_frequency
, codec_amr_decode
);
264 * Editor modelines - http://www.wireshark.org/tools/modelines.html
269 * indent-tabs-mode: nil
272 * vi: set shiftwidth=4 tabstop=8 expandtab:
273 * :indentSize=4:tabSize=8:noTabs=true: