blob: f31e7aefbc4b982ab2ef659301ea74aeac961acb [file] [log] [blame]
Jacob Erlbeck239a8532014-03-13 14:25:51 +01001/*
Jacob Erlbeck239a8532014-03-13 14:25:51 +01002 * (C) 2014 by On-Waves
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20#include <stdlib.h>
21#include <string.h>
22#include <errno.h>
23
Jacob Erlbeck42a833e2014-04-14 10:31:47 +020024
Jacob Erlbeck239a8532014-03-13 14:25:51 +010025#include "g711common.h"
Jacob Erlbeck239a8532014-03-13 14:25:51 +010026
27#include <openbsc/debug.h>
28#include <openbsc/mgcp.h>
29#include <openbsc/mgcp_internal.h>
Holger Hans Peter Freytherdd1f8152014-07-22 13:05:31 +020030#include <openbsc/mgcp_transcode.h>
Jacob Erlbeck239a8532014-03-13 14:25:51 +010031
32#include <osmocom/core/talloc.h>
Holger Hans Peter Freyther7c7358e2015-03-22 13:56:30 +010033#include <osmocom/netif/rtp.h>
Jacob Erlbeck239a8532014-03-13 14:25:51 +010034
Jacob Erlbeck136a3192014-03-13 14:33:37 +010035int mgcp_transcoding_get_frame_size(void *state_, int nsamples, int dst)
36{
37 struct mgcp_process_rtp_state *state = state_;
38 if (dst)
39 return (nsamples >= 0 ?
40 nsamples / state->dst_samples_per_frame :
41 1) * state->dst_frame_size;
42 else
43 return (nsamples >= 0 ?
44 nsamples / state->src_samples_per_frame :
45 1) * state->src_frame_size;
46}
47
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +020048static enum audio_format get_audio_format(const struct mgcp_rtp_codec *codec)
Jacob Erlbeck239a8532014-03-13 14:25:51 +010049{
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +020050 if (codec->subtype_name) {
Holger Hans Peter Freytherc57b5502015-04-24 15:07:20 -040051 if (!strcasecmp("GSM", codec->subtype_name))
Jacob Erlbeck239a8532014-03-13 14:25:51 +010052 return AF_GSM;
Holger Hans Peter Freytherc57b5502015-04-24 15:07:20 -040053 if (!strcasecmp("PCMA", codec->subtype_name))
Jacob Erlbeck239a8532014-03-13 14:25:51 +010054 return AF_PCMA;
Holger Hans Peter Freytherceef9362015-08-19 14:43:35 +020055 if (!strcasecmp("PCMU", codec->subtype_name))
56 return AF_PCMU;
Jacob Erlbeck239a8532014-03-13 14:25:51 +010057#ifdef HAVE_BCG729
Holger Hans Peter Freytherc57b5502015-04-24 15:07:20 -040058 if (!strcasecmp("G729", codec->subtype_name))
Jacob Erlbeck239a8532014-03-13 14:25:51 +010059 return AF_G729;
60#endif
Holger Hans Peter Freytherc57b5502015-04-24 15:07:20 -040061 if (!strcasecmp("L16", codec->subtype_name))
Jacob Erlbeck239a8532014-03-13 14:25:51 +010062 return AF_L16;
63 }
64
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +020065 switch (codec->payload_type) {
Holger Hans Peter Freytherceef9362015-08-19 14:43:35 +020066 case 0 /* PCMU */:
67 return AF_PCMU;
Jacob Erlbeck239a8532014-03-13 14:25:51 +010068 case 3 /* GSM */:
69 return AF_GSM;
70 case 8 /* PCMA */:
71 return AF_PCMA;
72#ifdef HAVE_BCG729
73 case 18 /* G.729 */:
74 return AF_G729;
75#endif
76 case 11 /* L16 */:
77 return AF_L16;
78 default:
79 return AF_INVALID;
80 }
81}
82
83static void l16_encode(short *sample, unsigned char *buf, size_t n)
84{
85 for (; n > 0; --n, ++sample, buf += 2) {
86 buf[0] = sample[0] >> 8;
87 buf[1] = sample[0] & 0xff;
88 }
89}
90
91static void l16_decode(unsigned char *buf, short *sample, size_t n)
92{
93 for (; n > 0; --n, ++sample, buf += 2)
94 sample[0] = ((short)buf[0] << 8) | buf[1];
95}
96
97static void alaw_encode(short *sample, unsigned char *buf, size_t n)
98{
99 for (; n > 0; --n)
100 *(buf++) = s16_to_alaw(*(sample++));
101}
102
103static void alaw_decode(unsigned char *buf, short *sample, size_t n)
104{
105 for (; n > 0; --n)
106 *(sample++) = alaw_to_s16(*(buf++));
107}
108
Holger Hans Peter Freytherceef9362015-08-19 14:43:35 +0200109static void ulaw_encode(short *sample, unsigned char *buf, size_t n)
110{
111 for (; n > 0; --n)
112 *(buf++) = s16_to_ulaw(*(sample++));
113}
114
115static void ulaw_decode(unsigned char *buf, short *sample, size_t n)
116{
117 for (; n > 0; --n)
118 *(sample++) = ulaw_to_s16(*(buf++));
119}
120
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100121static int processing_state_destructor(struct mgcp_process_rtp_state *state)
122{
123 switch (state->src_fmt) {
124 case AF_GSM:
Holger Hans Peter Freytherc5c239f2014-07-07 20:38:27 +0200125 if (state->src.gsm_handle)
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100126 gsm_destroy(state->src.gsm_handle);
127 break;
128#ifdef HAVE_BCG729
129 case AF_G729:
130 if (state->src.g729_dec)
131 closeBcg729DecoderChannel(state->src.g729_dec);
132 break;
133#endif
134 default:
135 break;
136 }
137 switch (state->dst_fmt) {
138 case AF_GSM:
139 if (state->dst.gsm_handle)
140 gsm_destroy(state->dst.gsm_handle);
141 break;
142#ifdef HAVE_BCG729
143 case AF_G729:
144 if (state->dst.g729_enc)
145 closeBcg729EncoderChannel(state->dst.g729_enc);
146 break;
147#endif
148 default:
149 break;
150 }
151 return 0;
152}
153
154int mgcp_transcoding_setup(struct mgcp_endpoint *endp,
155 struct mgcp_rtp_end *dst_end,
156 struct mgcp_rtp_end *src_end)
157{
158 struct mgcp_process_rtp_state *state;
159 enum audio_format src_fmt, dst_fmt;
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +0200160 const struct mgcp_rtp_codec *dst_codec = &dst_end->codec;
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100161
162 /* cleanup first */
163 if (dst_end->rtp_process_data) {
164 talloc_free(dst_end->rtp_process_data);
165 dst_end->rtp_process_data = NULL;
166 }
167
168 if (!src_end)
169 return 0;
170
Jacob Erlbeck5a2484b2015-04-28 09:28:18 +0200171 const struct mgcp_rtp_codec *src_codec = &src_end->codec;
172
Holger Hans Peter Freythercb43a9a2015-04-24 16:03:55 -0400173 if (endp->tcfg->no_audio_transcoding) {
174 LOGP(DMGCP, LOGL_NOTICE,
175 "Transcoding disabled on endpoint 0x%x\n",
176 ENDPOINT_NUMBER(endp));
177 return 0;
178 }
179
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +0200180 src_fmt = get_audio_format(src_codec);
181 dst_fmt = get_audio_format(dst_codec);
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100182
183 LOGP(DMGCP, LOGL_ERROR,
184 "Checking transcoding: %s (%d) -> %s (%d)\n",
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +0200185 src_codec->subtype_name, src_codec->payload_type,
186 dst_codec->subtype_name, dst_codec->payload_type);
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100187
188 if (src_fmt == AF_INVALID || dst_fmt == AF_INVALID) {
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +0200189 if (!src_codec->subtype_name || !dst_codec->subtype_name)
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100190 /* Not enough info, do nothing */
191 return 0;
192
Holger Hans Peter Freytherc57b5502015-04-24 15:07:20 -0400193 if (strcasecmp(src_codec->subtype_name, dst_codec->subtype_name) == 0)
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100194 /* Nothing to do */
195 return 0;
196
197 LOGP(DMGCP, LOGL_ERROR,
198 "Cannot transcode: %s codec not supported (%s -> %s).\n",
199 src_fmt != AF_INVALID ? "destination" : "source",
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +0200200 src_codec->audio_name, dst_codec->audio_name);
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100201 return -EINVAL;
202 }
203
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +0200204 if (src_codec->rate && dst_codec->rate && src_codec->rate != dst_codec->rate) {
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100205 LOGP(DMGCP, LOGL_ERROR,
206 "Cannot transcode: rate conversion (%d -> %d) not supported.\n",
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +0200207 src_codec->rate, dst_codec->rate);
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100208 return -EINVAL;
209 }
210
211 state = talloc_zero(endp->tcfg->cfg, struct mgcp_process_rtp_state);
212 talloc_set_destructor(state, processing_state_destructor);
213 dst_end->rtp_process_data = state;
214
215 state->src_fmt = src_fmt;
216
217 switch (state->src_fmt) {
218 case AF_L16:
219 case AF_S16:
220 state->src_frame_size = 80 * sizeof(short);
221 state->src_samples_per_frame = 80;
222 break;
223 case AF_GSM:
224 state->src_frame_size = sizeof(gsm_frame);
225 state->src_samples_per_frame = 160;
226 state->src.gsm_handle = gsm_create();
227 if (!state->src.gsm_handle) {
228 LOGP(DMGCP, LOGL_ERROR,
229 "Failed to initialize GSM decoder.\n");
230 return -EINVAL;
231 }
232 break;
233#ifdef HAVE_BCG729
234 case AF_G729:
235 state->src_frame_size = 10;
236 state->src_samples_per_frame = 80;
237 state->src.g729_dec = initBcg729DecoderChannel();
238 if (!state->src.g729_dec) {
239 LOGP(DMGCP, LOGL_ERROR,
240 "Failed to initialize G.729 decoder.\n");
241 return -EINVAL;
242 }
243 break;
244#endif
Holger Hans Peter Freytherceef9362015-08-19 14:43:35 +0200245 case AF_PCMU:
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100246 case AF_PCMA:
247 state->src_frame_size = 80;
248 state->src_samples_per_frame = 80;
249 break;
250 default:
251 break;
252 }
253
254 state->dst_fmt = dst_fmt;
255
256 switch (state->dst_fmt) {
257 case AF_L16:
258 case AF_S16:
259 state->dst_frame_size = 80*sizeof(short);
260 state->dst_samples_per_frame = 80;
261 break;
262 case AF_GSM:
263 state->dst_frame_size = sizeof(gsm_frame);
264 state->dst_samples_per_frame = 160;
265 state->dst.gsm_handle = gsm_create();
266 if (!state->dst.gsm_handle) {
267 LOGP(DMGCP, LOGL_ERROR,
268 "Failed to initialize GSM encoder.\n");
269 return -EINVAL;
270 }
271 break;
272#ifdef HAVE_BCG729
273 case AF_G729:
274 state->dst_frame_size = 10;
275 state->dst_samples_per_frame = 80;
276 state->dst.g729_enc = initBcg729EncoderChannel();
277 if (!state->dst.g729_enc) {
278 LOGP(DMGCP, LOGL_ERROR,
279 "Failed to initialize G.729 decoder.\n");
280 return -EINVAL;
281 }
282 break;
283#endif
Holger Hans Peter Freytherceef9362015-08-19 14:43:35 +0200284 case AF_PCMU:
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100285 case AF_PCMA:
286 state->dst_frame_size = 80;
287 state->dst_samples_per_frame = 80;
288 break;
289 default:
290 break;
291 }
292
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200293 if (dst_end->force_output_ptime)
294 state->dst_packet_duration = mgcp_rtp_packet_duration(endp, dst_end);
295
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100296 LOGP(DMGCP, LOGL_INFO,
297 "Initialized RTP processing on: 0x%x "
298 "conv: %d (%d, %d, %s) -> %d (%d, %d, %s)\n",
299 ENDPOINT_NUMBER(endp),
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +0200300 src_fmt, src_codec->payload_type, src_codec->rate, src_end->fmtp_extra,
301 dst_fmt, dst_codec->payload_type, dst_codec->rate, dst_end->fmtp_extra);
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100302
303 return 0;
304}
305
306void mgcp_transcoding_net_downlink_format(struct mgcp_endpoint *endp,
307 int *payload_type,
308 const char**audio_name,
309 const char**fmtp_extra)
310{
311 struct mgcp_process_rtp_state *state = endp->net_end.rtp_process_data;
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +0200312 struct mgcp_rtp_codec *net_codec = &endp->net_end.codec;
313 struct mgcp_rtp_codec *bts_codec = &endp->bts_end.codec;
314
315 if (!state || net_codec->payload_type < 0) {
316 *payload_type = bts_codec->payload_type;
317 *audio_name = bts_codec->audio_name;
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100318 *fmtp_extra = endp->bts_end.fmtp_extra;
319 return;
320 }
321
Holger Hans Peter Freythercac24382014-09-01 10:35:55 +0200322 *payload_type = net_codec->payload_type;
323 *audio_name = net_codec->audio_name;
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100324 *fmtp_extra = endp->net_end.fmtp_extra;
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100325}
326
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200327static int decode_audio(struct mgcp_process_rtp_state *state,
328 uint8_t **src, size_t *nbytes)
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100329{
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200330 while (*nbytes >= state->src_frame_size) {
331 if (state->sample_cnt + state->src_samples_per_frame > ARRAY_SIZE(state->samples)) {
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100332 LOGP(DMGCP, LOGL_ERROR,
Holger Hans Peter Freytherf4afcf02016-03-16 11:15:19 +0100333 "Sample buffer too small: %zu > %zu.\n",
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200334 state->sample_cnt + state->src_samples_per_frame,
335 ARRAY_SIZE(state->samples));
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100336 return -ENOSPC;
337 }
338 switch (state->src_fmt) {
339 case AF_GSM:
340 if (gsm_decode(state->src.gsm_handle,
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200341 (gsm_byte *)*src, state->samples + state->sample_cnt) < 0) {
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100342 LOGP(DMGCP, LOGL_ERROR,
343 "Failed to decode GSM.\n");
344 return -EINVAL;
345 }
346 break;
347#ifdef HAVE_BCG729
348 case AF_G729:
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200349 bcg729Decoder(state->src.g729_dec, *src, 0, state->samples + state->sample_cnt);
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100350 break;
351#endif
Holger Hans Peter Freytherceef9362015-08-19 14:43:35 +0200352 case AF_PCMU:
353 ulaw_decode(*src, state->samples + state->sample_cnt,
354 state->src_samples_per_frame);
355 break;
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100356 case AF_PCMA:
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200357 alaw_decode(*src, state->samples + state->sample_cnt,
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100358 state->src_samples_per_frame);
359 break;
360 case AF_S16:
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200361 memmove(state->samples + state->sample_cnt, *src,
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100362 state->src_frame_size);
363 break;
364 case AF_L16:
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200365 l16_decode(*src, state->samples + state->sample_cnt,
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100366 state->src_samples_per_frame);
367 break;
368 default:
369 break;
370 }
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200371 *src += state->src_frame_size;
372 *nbytes -= state->src_frame_size;
373 state->sample_cnt += state->src_samples_per_frame;
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100374 }
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200375 return 0;
376}
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100377
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200378static int encode_audio(struct mgcp_process_rtp_state *state,
379 uint8_t *dst, size_t buf_size, size_t max_samples)
380{
381 int nbytes = 0;
382 size_t nsamples = 0;
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100383 /* Encode samples into dst */
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200384 while (nsamples + state->dst_samples_per_frame <= max_samples) {
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100385 if (nbytes + state->dst_frame_size > buf_size) {
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200386 if (nbytes > 0)
387 break;
388
389 /* Not even one frame fits into the buffer */
390 LOGP(DMGCP, LOGL_INFO,
Holger Hans Peter Freytherf4afcf02016-03-16 11:15:19 +0100391 "Encoding (RTP) buffer too small: %zu > %zu.\n",
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100392 nbytes + state->dst_frame_size, buf_size);
393 return -ENOSPC;
394 }
395 switch (state->dst_fmt) {
396 case AF_GSM:
397 gsm_encode(state->dst.gsm_handle,
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200398 state->samples + state->sample_offs, dst);
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100399 break;
400#ifdef HAVE_BCG729
401 case AF_G729:
402 bcg729Encoder(state->dst.g729_enc,
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200403 state->samples + state->sample_offs, dst);
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100404 break;
405#endif
Holger Hans Peter Freytherceef9362015-08-19 14:43:35 +0200406 case AF_PCMU:
407 ulaw_encode(state->samples + state->sample_offs, dst,
408 state->src_samples_per_frame);
409 break;
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100410 case AF_PCMA:
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200411 alaw_encode(state->samples + state->sample_offs, dst,
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100412 state->src_samples_per_frame);
413 break;
414 case AF_S16:
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200415 memmove(dst, state->samples + state->sample_offs,
416 state->dst_frame_size);
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100417 break;
418 case AF_L16:
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200419 l16_encode(state->samples + state->sample_offs, dst,
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100420 state->src_samples_per_frame);
421 break;
422 default:
423 break;
424 }
425 dst += state->dst_frame_size;
426 nbytes += state->dst_frame_size;
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200427 state->sample_offs += state->dst_samples_per_frame;
428 nsamples += state->dst_samples_per_frame;
429 }
430 state->sample_cnt -= nsamples;
431 return nbytes;
432}
433
Holger Hans Peter Freyther46801212014-09-01 22:20:57 +0200434static struct mgcp_rtp_end *source_for_dest(struct mgcp_endpoint *endp,
435 struct mgcp_rtp_end *dst_end)
436{
437 if (&endp->bts_end == dst_end)
438 return &endp->net_end;
439 else if (&endp->net_end == dst_end)
440 return &endp->bts_end;
441 OSMO_ASSERT(0);
442}
443
444/*
445 * With some modems we get offered multiple codecs
446 * and we have selected one of them. It might not
447 * be the right one and we need to detect this with
448 * the first audio packets. One difficulty is that
449 * we patch the rtp payload type in place, so we
450 * need to discuss this.
451 */
452struct mgcp_process_rtp_state *check_transcode_state(
453 struct mgcp_endpoint *endp,
454 struct mgcp_rtp_end *dst_end,
455 struct rtp_hdr *rtp_hdr)
456{
457 struct mgcp_rtp_end *src_end;
458
459 /* Only deal with messages from net to bts */
460 if (&endp->bts_end != dst_end)
461 goto done;
462
463 src_end = source_for_dest(endp, dst_end);
464
465 /* Already patched */
466 if (rtp_hdr->payload_type == dst_end->codec.payload_type)
467 goto done;
468 /* The payload we expect */
469 if (rtp_hdr->payload_type == src_end->codec.payload_type)
470 goto done;
471 /* The matching alternate payload type? Then switch */
472 if (rtp_hdr->payload_type == src_end->alt_codec.payload_type) {
473 struct mgcp_config *cfg = endp->cfg;
474 struct mgcp_rtp_codec tmp_codec = src_end->alt_codec;
475 src_end->alt_codec = src_end->codec;
476 src_end->codec = tmp_codec;
477 cfg->setup_rtp_processing_cb(endp, &endp->net_end, &endp->bts_end);
478 cfg->setup_rtp_processing_cb(endp, &endp->bts_end, &endp->net_end);
479 }
480
481done:
482 return dst_end->rtp_process_data;
483}
484
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200485int mgcp_transcoding_process_rtp(struct mgcp_endpoint *endp,
486 struct mgcp_rtp_end *dst_end,
487 char *data, int *len, int buf_size)
488{
Holger Hans Peter Freyther46801212014-09-01 22:20:57 +0200489 struct mgcp_process_rtp_state *state;
Holger Hans Peter Freyther3713f782014-09-01 11:02:05 +0200490 const size_t rtp_hdr_size = sizeof(struct rtp_hdr);
491 struct rtp_hdr *rtp_hdr = (struct rtp_hdr *) data;
492 char *payload_data = (char *) &rtp_hdr->data[0];
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200493 int payload_len = *len - rtp_hdr_size;
494 uint8_t *src = (uint8_t *)payload_data;
495 uint8_t *dst = (uint8_t *)payload_data;
496 size_t nbytes = payload_len;
497 size_t nsamples;
498 size_t max_samples;
499 uint32_t ts_no;
500 int rc;
501
Holger Hans Peter Freyther46801212014-09-01 22:20:57 +0200502 state = check_transcode_state(endp, dst_end, rtp_hdr);
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200503 if (!state)
504 return 0;
505
506 if (state->src_fmt == state->dst_fmt) {
507 if (!state->dst_packet_duration)
508 return 0;
509
510 /* TODO: repackage without transcoding */
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100511 }
512
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200513 /* If the remaining samples do not fit into a fixed ptime,
514 * a) discard them, if the next packet is much later
515 * b) add silence and * send it, if the current packet is not
516 * yet too late
517 * c) append the sample data, if the timestamp matches exactly
518 */
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100519
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200520 /* TODO: check payload type (-> G.711 comfort noise) */
521
522 if (payload_len > 0) {
Holger Hans Peter Freyther3713f782014-09-01 11:02:05 +0200523 ts_no = ntohl(rtp_hdr->timestamp);
Holger Hans Peter Freytherc8b29082014-07-02 22:02:15 +0200524 if (!state->is_running) {
Holger Hans Peter Freyther3713f782014-09-01 11:02:05 +0200525 state->next_seq = ntohs(rtp_hdr->sequence);
Holger Hans Peter Freytherc8b29082014-07-02 22:02:15 +0200526 state->next_time = ts_no;
527 state->is_running = 1;
528 }
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200529
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200530
531 if (state->sample_cnt > 0) {
532 int32_t delta = ts_no - state->next_time;
533 /* TODO: check sequence? reordering? packet loss? */
534
Holger Hans Peter Freythere52ca9a2014-07-02 21:56:26 +0200535 if (delta > state->sample_cnt) {
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200536 /* There is a time gap between the last packet
537 * and the current one. Just discard the
538 * partial data that is left in the buffer.
539 * TODO: This can be improved by adding silence
540 * instead if the delta is small enough.
541 */
Holger Hans Peter Freythere52ca9a2014-07-02 21:56:26 +0200542 LOGP(DMGCP, LOGL_NOTICE,
Holger Hans Peter Freytherf4afcf02016-03-16 11:15:19 +0100543 "0x%x dropping sample buffer due delta=%d sample_cnt=%zu\n",
Holger Hans Peter Freythere52ca9a2014-07-02 21:56:26 +0200544 ENDPOINT_NUMBER(endp), delta, state->sample_cnt);
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200545 state->sample_cnt = 0;
Holger Hans Peter Freytherb9362782014-07-04 20:55:20 +0200546 state->next_time = ts_no;
Holger Hans Peter Freythere52ca9a2014-07-02 21:56:26 +0200547 } else if (delta < 0) {
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200548 LOGP(DMGCP, LOGL_NOTICE,
549 "RTP time jumps backwards, delta = %d, "
550 "discarding buffered samples\n",
551 delta);
552 state->sample_cnt = 0;
553 state->sample_offs = 0;
554 return -EAGAIN;
555 }
556
557 /* Make sure the samples start without offset */
558 if (state->sample_offs && state->sample_cnt)
559 memmove(&state->samples[0],
560 &state->samples[state->sample_offs],
561 state->sample_cnt *
562 sizeof(state->samples[0]));
563 }
564
565 state->sample_offs = 0;
566
567 /* Append decoded audio to samples */
568 decode_audio(state, &src, &nbytes);
569
570 if (nbytes > 0)
571 LOGP(DMGCP, LOGL_NOTICE,
Holger Hans Peter Freytherf4afcf02016-03-16 11:15:19 +0100572 "Skipped audio frame in RTP packet: %zu octets\n",
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200573 nbytes);
574 } else
575 ts_no = state->next_time;
576
577 if (state->sample_cnt < state->dst_packet_duration)
578 return -EAGAIN;
579
580 max_samples =
581 state->dst_packet_duration ?
582 state->dst_packet_duration : state->sample_cnt;
583
584 nsamples = state->sample_cnt;
585
586 rc = encode_audio(state, dst, buf_size, max_samples);
Holger Hans Peter Freytherbd4109b2014-06-27 19:27:38 +0200587 /*
588 * There were no samples to encode?
589 * TODO: how does this work for comfort noise?
590 */
591 if (rc == 0)
592 return -ENOMSG;
593 /* Any other error during the encoding */
594 if (rc < 0)
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200595 return rc;
596
597 nsamples -= state->sample_cnt;
598
599 *len = rtp_hdr_size + rc;
Holger Hans Peter Freyther3713f782014-09-01 11:02:05 +0200600 rtp_hdr->sequence = htons(state->next_seq);
601 rtp_hdr->timestamp = htonl(ts_no);
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200602
603 state->next_seq += 1;
604 state->next_time = ts_no + nsamples;
605
Holger Hans Peter Freyther77ceaaf2014-06-28 15:05:42 +0200606 /*
607 * XXX: At this point we should always have consumed
608 * samples. So doing OSMO_ASSERT(nsamples > 0) and returning
609 * rtp_hdr_size should be fine.
610 */
Jacob Erlbeck42a833e2014-04-14 10:31:47 +0200611 return nsamples ? rtp_hdr_size : 0;
Jacob Erlbeck239a8532014-03-13 14:25:51 +0100612}