From 6f38693bb8f8a8906909d1f5c59b5e5e591f4da1 Mon Sep 17 00:00:00 2001 From: Jonathan de Boyne Pollard Date: Thu, 9 Mar 2017 13:46:22 +0000 Subject: [PATCH 1/4] extractaudio: Add support for DLT_RAW pcap format. --- extractaudio/rtpp_loader.c | 7 ++++++- src/rtpp_record_private.h | 11 +++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/extractaudio/rtpp_loader.c b/extractaudio/rtpp_loader.c index 567fb4665..7f44d7c9a 100644 --- a/extractaudio/rtpp_loader.c +++ b/extractaudio/rtpp_loader.c @@ -117,7 +117,7 @@ rtpp_load(const char *path) return NULL; } pcap_hdr = (pcap_hdr_t *)rval->ibuf; - if (pcap_hdr->network != DLT_EN10MB && pcap_hdr->network != DLT_NULL) { + if (pcap_hdr->network != DLT_EN10MB && pcap_hdr->network != DLT_RAW && pcap_hdr->network != DLT_NULL) { warnx("unsupported data-link type in the PCAP: %d", pcap_hdr->network); rval->destroy(rval); return NULL; @@ -248,6 +248,11 @@ load_pcap(struct rtpp_loader *loader, struct channels *channels, memcpy(&pcap, cp, pcap_size); pcaprec_hdr = &(pcap.null.pcaprec_hdr); udpip = &(pcap.null.udpip); + } else if (network == DLT_RAW) { + pcap_size = sizeof(struct pkt_hdr_pcap_raw); + memcpy(&pcap, cp, pcap_size); + pcaprec_hdr = &(pcap.raw.pcaprec_hdr); + udpip = &(pcap.raw.udpip); } else { if (pcp->en10t.ether.type != ETHERTYPE_INET) { rtp_len = sizeof(pcaprec_hdr_t) + pcp->en10t.pcaprec_hdr.incl_len; diff --git a/src/rtpp_record_private.h b/src/rtpp_record_private.h index a1e0b71a3..9f53473fe 100644 --- a/src/rtpp_record_private.h +++ b/src/rtpp_record_private.h @@ -31,6 +31,7 @@ #define DLT_NULL 0 #define DLT_EN10MB 1 +#define DLT_RAW 101 #define PCAP_MAGIC 0xa1b2c3d4 #define PCAP_VER_MAJR 2 #define PCAP_VER_MINR 4 @@ -94,6 +95,14 @@ struct pkt_hdr_pcap_null_v6 { uint32_t family; struct udpip6 udpip6; } __attribute__((__packed__)); +struct pkt_hdr_pcap_raw { + pcaprec_hdr_t pcaprec_hdr; + struct udpip udpip; +} __attribute__((__packed__)); +struct pkt_hdr_pcap_raw_v6 { + pcaprec_hdr_t pcaprec_hdr; + struct udpip6 udpip6; +} __attribute__((__packed__)); struct pkt_hdr_pcap_en10t { pcaprec_hdr_t pcaprec_hdr; struct layer2_hdr ether; @@ -108,6 +117,8 @@ struct pkt_hdr_pcap_en10t_v6 { union pkt_hdr_pcap { struct pkt_hdr_pcap_null null; struct pkt_hdr_pcap_null_v6 null_v6; + struct pkt_hdr_pcap_raw raw; + struct pkt_hdr_pcap_raw_v6 raw_v6; struct pkt_hdr_pcap_en10t en10t; struct pkt_hdr_pcap_en10t_v6 en10t_v6; }; From c1c2c430a4e459cc69d6949ef2dd651395ddc9a3 Mon Sep 17 00:00:00 2001 From: Jonathan de Boyne Pollard Date: Mon, 13 Mar 2017 11:52:42 +0000 Subject: [PATCH 2/4] Follow API changes for bcg729 library. --- extractaudio/g729_compat.c | 2 +- extractaudio/g729_compat.h | 8 ++++---- makeann/makeann.c | 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/extractaudio/g729_compat.c b/extractaudio/g729_compat.c index f36f9d8f7..34d44a76d 100644 --- a/extractaudio/g729_compat.c +++ b/extractaudio/g729_compat.c @@ -13,7 +13,7 @@ g279_compat_decode(G729_DCTX *ctx, uint8_t *ibuf, size_t ibsize) assert(ibsize <= 10); - bcg729Decoder(ctx, ibuf, 0, obuf); + bcg729Decoder(ctx, ibuf, ibsize, 0 /*no erasure*/, 0 /*not SID*/, 0 /*not RFC3389*/, obuf); return (obuf); } diff --git a/extractaudio/g729_compat.h b/extractaudio/g729_compat.h index 33d527b89..ca16bf946 100644 --- a/extractaudio/g729_compat.h +++ b/extractaudio/g729_compat.h @@ -4,10 +4,10 @@ # include # define G729_ECTX bcg729EncoderChannelContextStruct # define G729_DCTX bcg729DecoderChannelContextStruct -# define G729_EINIT initBcg729EncoderChannel +# define G729_EINIT() initBcg729EncoderChannel(0 /*no VAT/DTX detection*/) # define G729_ECLOSE closeBcg729EncoderChannel # define G729_DINIT initBcg729DecoderChannel -# define G729_ENCODE(ctx, ibuf, obuf) bcg729Encoder((ctx), (ibuf), (obuf)) +# define G729_ENCODE(ctx, ibuf, obuf, olen) bcg729Encoder((ctx), (ibuf), (obuf), (olen)) # define G729_DECODE(ctx, ibuf, isize) g279_compat_decode((ctx), (ibuf), (isize)) int16_t *g279_compat_decode(G729_DCTX *, uint8_t *, size_t); @@ -17,10 +17,10 @@ # include # define G729_ECTX G729_CTX # define G729_DCTX G729_CTX -# define G729_EINIT g729_encoder_new +# define G729_EINIT() g729_encoder_new() # define G729_ECLOSE g729_encoder_destroy # define G729_DINIT g729_decoder_new -# define G729_ENCODE(ctx, ibuf, obuf) g729_encode_frame((ctx), (ibuf), (obuf)) +# define G729_ENCODE(ctx, ibuf, obuf, olen) g729_encode_frame((ctx), (ibuf), (obuf), (olen)) # define G729_DECODE(ctx, ibuf, isize) g729_decode_frame((ctx), (ibuf), (isize)) # endif diff --git a/makeann/makeann.c b/makeann/makeann.c index 012596dff..e1daf7df4 100644 --- a/makeann/makeann.c +++ b/makeann/makeann.c @@ -201,9 +201,10 @@ int main(int argc, char **argv) #ifdef ENABLE_G729 case RTP_G729: for (j = 0; j < 2; j++) { - G729_ENCODE(ctx_g729, &(slbuf[j * 80]), &(lawbuf[j * 10])); + uint8_t l; + G729_ENCODE(ctx_g729, &(slbuf[j * 80]), &(lawbuf[j * 10]), &l); + wsize += j; } - wsize = 20; break; #endif From 792bcfeb8733d7f790527d009383c7483d155cd0 Mon Sep 17 00:00:00 2001 From: Jonathan de Boyne Pollard Date: Mon, 13 Mar 2017 12:32:34 +0000 Subject: [PATCH 3/4] Reworked silence interpolation to work around duplicated silence problem. --- extractaudio/decoder.c | 82 ++++++++++++++++++++++++++++++------------ extractaudio/decoder.h | 2 ++ 2 files changed, 61 insertions(+), 23 deletions(-) diff --git a/extractaudio/decoder.c b/extractaudio/decoder.c index 09dd2298b..04ca3d825 100644 --- a/extractaudio/decoder.c +++ b/extractaudio/decoder.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "config.h" @@ -70,6 +71,7 @@ decoder_new(struct session *sp, int dflags) dp->stime = dp->pp->pkt->time; dp->nticks = dp->sticks = dp->pp->parsed.ts; dp->dticks = 0; + dp->silence_at_receiver = dp->silence_from_sender = 0; dp->lpt = RTP_PCMU; dp->dflags = dflags; /* dp->f = fopen(i, "w"); */ @@ -78,13 +80,47 @@ decoder_new(struct session *sp, int dflags) return (void *)dp; } +static +unsigned int +extract_some_pending_silence(struct decoder_stream *dp) +{ + unsigned int t; + + if (dp->silence_at_receiver > 0) { + /* Handle overlapping silences. + ** If the sender has a gap in the timestamps AND packets arrive later + ** than playout time, we do not want to double up the generated silence. + ** So we elide any silence caused by late arrivals that is covered by + ** the period of sender-indicated silence. + */ + if (dp->silence_from_sender > 0) { + warnx("Silence overlap: explicit sender gap of %u ticks, inferred silence of %u ticks at receiver", dp->silence_from_sender, dp->silence_at_receiver); + if (dp->silence_at_receiver >= dp->silence_from_sender) + dp->silence_at_receiver -= dp->silence_from_sender; + else + dp->silence_at_receiver = 0; + } + t = dp->silence_at_receiver; + if (t > 4000) + t = 4000; + dp->silence_at_receiver -= t; + if (t > 0) return t; + } + + t = dp->silence_from_sender; + if (t > 4000) + t = 4000; + dp->silence_from_sender -= t; + return t; +} + int32_t decoder_get(struct decoder_stream *dp) { unsigned int cticks, t; int j; - if (dp->oblen == 0) { + while (dp->oblen <= 0) { if (dp->pp == NULL) return DECODER_EOF; cticks = dp->pp->parsed.ts; @@ -97,30 +133,16 @@ decoder_get(struct decoder_stream *dp) dp->nticks = cticks; dp->sticks = cticks - (dp->pp->pkt->time - dp->stime) * 8000; } + /* Calculate sender-indicated silence between the expected timestamp and the current one. */ if (dp->nticks < cticks) { t = cticks - dp->nticks; - if (t > 4000) - t = 4000; - if ((dp->dflags & D_FLAG_NOSYNC) != 0) { - dp->nticks += t; - dp->dticks += t; - return (DECODER_SKIP); - } - j = generate_silence(dp, dp->obuf, t); - if (j <= 0) - return DECODER_ERROR; dp->nticks += t; - dp->dticks += t; - dp->oblen = j / 2; - dp->obp = dp->obuf; - } else if ((dp->pp->pkt->time - dp->stime - (double)dp->dticks / 8000.0) > 0.2) { - t = (((dp->pp->pkt->time - dp->stime) * 8000) - dp->dticks) / 2; - if (t > 4000) - t = 4000; - if ((dp->dflags & D_FLAG_NOSYNC) != 0) { - dp->dticks += t; + if ((dp->dflags & D_FLAG_NOSYNC) != 0) return (DECODER_SKIP); - } + dp->silence_from_sender += t; + } + t = extract_some_pending_silence(dp); + if (t > 0) { j = generate_silence(dp, dp->obuf, t); if (j <= 0) return DECODER_ERROR; @@ -128,13 +150,27 @@ decoder_get(struct decoder_stream *dp) dp->oblen = j / 2; dp->obp = dp->obuf; } else { + /* Calculate receiver-detected silence from packet arrival time + ** compared to playout time. + ** We do not generate silence immediately, because we want the + ** generated silence to follow the audio, and possibly be + ** subsumed into any sender-indicated silence. + ** We do not infer silence if there is no audio payload, because + ** we want the silence to prefix the next actual audio data. + */ + if (RPLEN(dp->pp) > 0 && (dp->pp->pkt->time - dp->stime - dp->dticks / 8000.0) > 0.2) { + t = (((dp->pp->pkt->time - dp->stime) * 8000) - dp->dticks) / 2; + if ((dp->dflags & D_FLAG_NOSYNC) != 0) { + dp->dticks += t; + return (DECODER_SKIP); + } + dp->silence_at_receiver += t; + } j = decode_frame(dp, dp->obuf, RPLOAD(dp->pp), RPLEN(dp->pp), \ sizeof(dp->obuf)); if (j > 0) dp->lpt = dp->pp->rpkt->pt; dp->pp = MYQ_NEXT(dp->pp); - if (j <= 0) - return decoder_get(dp); dp->oblen = j / 2; dp->obp = dp->obuf; } diff --git a/extractaudio/decoder.h b/extractaudio/decoder.h index 7d8ea7c96..19279452e 100644 --- a/extractaudio/decoder.h +++ b/extractaudio/decoder.h @@ -72,6 +72,8 @@ struct decoder_stream { #endif double stime; double dticks; + unsigned int silence_at_receiver; /* in ticks */ + unsigned int silence_from_sender; /* in ticks */ /* FILE *f; */ int dflags; }; From 9de3ff6144de270b202edb6e3f21c935a3beee68 Mon Sep 17 00:00:00 2001 From: Jonathan de Boyne Pollard Date: Mon, 13 Mar 2017 13:27:59 +0000 Subject: [PATCH 4/4] Follow API changes for bcg729 library. --- extractaudio/g729_compat.c | 2 +- extractaudio/g729_compat.h | 8 ++++---- makeann/makeann.c | 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/extractaudio/g729_compat.c b/extractaudio/g729_compat.c index f36f9d8f7..34d44a76d 100644 --- a/extractaudio/g729_compat.c +++ b/extractaudio/g729_compat.c @@ -13,7 +13,7 @@ g279_compat_decode(G729_DCTX *ctx, uint8_t *ibuf, size_t ibsize) assert(ibsize <= 10); - bcg729Decoder(ctx, ibuf, 0, obuf); + bcg729Decoder(ctx, ibuf, ibsize, 0 /*no erasure*/, 0 /*not SID*/, 0 /*not RFC3389*/, obuf); return (obuf); } diff --git a/extractaudio/g729_compat.h b/extractaudio/g729_compat.h index 33d527b89..ca16bf946 100644 --- a/extractaudio/g729_compat.h +++ b/extractaudio/g729_compat.h @@ -4,10 +4,10 @@ # include # define G729_ECTX bcg729EncoderChannelContextStruct # define G729_DCTX bcg729DecoderChannelContextStruct -# define G729_EINIT initBcg729EncoderChannel +# define G729_EINIT() initBcg729EncoderChannel(0 /*no VAT/DTX detection*/) # define G729_ECLOSE closeBcg729EncoderChannel # define G729_DINIT initBcg729DecoderChannel -# define G729_ENCODE(ctx, ibuf, obuf) bcg729Encoder((ctx), (ibuf), (obuf)) +# define G729_ENCODE(ctx, ibuf, obuf, olen) bcg729Encoder((ctx), (ibuf), (obuf), (olen)) # define G729_DECODE(ctx, ibuf, isize) g279_compat_decode((ctx), (ibuf), (isize)) int16_t *g279_compat_decode(G729_DCTX *, uint8_t *, size_t); @@ -17,10 +17,10 @@ # include # define G729_ECTX G729_CTX # define G729_DCTX G729_CTX -# define G729_EINIT g729_encoder_new +# define G729_EINIT() g729_encoder_new() # define G729_ECLOSE g729_encoder_destroy # define G729_DINIT g729_decoder_new -# define G729_ENCODE(ctx, ibuf, obuf) g729_encode_frame((ctx), (ibuf), (obuf)) +# define G729_ENCODE(ctx, ibuf, obuf, olen) g729_encode_frame((ctx), (ibuf), (obuf), (olen)) # define G729_DECODE(ctx, ibuf, isize) g729_decode_frame((ctx), (ibuf), (isize)) # endif diff --git a/makeann/makeann.c b/makeann/makeann.c index 012596dff..91fbaf20a 100644 --- a/makeann/makeann.c +++ b/makeann/makeann.c @@ -201,9 +201,10 @@ int main(int argc, char **argv) #ifdef ENABLE_G729 case RTP_G729: for (j = 0; j < 2; j++) { - G729_ENCODE(ctx_g729, &(slbuf[j * 80]), &(lawbuf[j * 10])); + uint8_t l; + G729_ENCODE(ctx_g729, &(slbuf[j * 80]), &(lawbuf[j * 10]), &l); + wsize += l; } - wsize = 20; break; #endif