From 02dbbe92be4dfe323246e2470229d58b7ebd4748 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Wed, 15 Mar 2023 18:16:34 +0100 Subject: [PATCH 01/31] audio: separate aureceiver --- CMakeLists.txt | 1 + include/baresip.h | 1 + src/audio.c | 548 +++++++------------------------------- src/aureceiver.c | 654 ++++++++++++++++++++++++++++++++++++++++++++++ src/core.h | 30 +++ 5 files changed, 777 insertions(+), 457 deletions(-) create mode 100644 src/aureceiver.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d9c04c3fa1..2822912bf2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -145,6 +145,7 @@ set(SRCS src/audio.c src/aufilt.c src/auplay.c + src/aureceiver.c src/ausrc.c src/baresip.c src/bundle.c diff --git a/include/baresip.h b/include/baresip.h index 66296d0108..8758a4c771 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -1190,6 +1190,7 @@ void aucodec_unregister(struct aucodec *ac); const struct aucodec *aucodec_find(const struct list *aucodecl, const char *name, uint32_t srate, uint8_t ch); +int aucodec_print(struct re_printf *pf, const struct aucodec *ac); /* diff --git a/src/audio.c b/src/audio.c index 6fe5ae6b13..093cf88211 100644 --- a/src/audio.c +++ b/src/audio.c @@ -117,61 +117,29 @@ struct autx { }; -/** - * Audio receive/decoder - * - \verbatim - - Processing decoder pipeline: - - .--------. .-------. .--------. .--------. - |\ | | | | | | | | - | |<--| auplay |<--| aubuf |<--| aufilt |<--| decode |<--- RTP - |/ | | | | | | | | - '--------' '-------' '--------' '--------' - - \endverbatim - */ struct aurx { const struct auplay *ap; /**< Audio Player module */ struct auplay_st *auplay; /**< Audio Player */ struct auplay_prm auplay_prm; /**< Audio Player parameters */ - const struct aucodec *ac; /**< Current audio decoder */ - struct audec_state *dec; /**< Audio decoder state (optional) */ - struct aubuf *aubuf; /**< Audio buffer before auplay */ - uint32_t ssrc; /**< Incoming synchronization source */ - size_t aubuf_minsz; /**< Minimum aubuf size in [bytes] */ - size_t aubuf_maxsz; /**< Maximum aubuf size in [bytes] */ - size_t num_bytes; /**< Size of one frame in [bytes] */ - volatile bool aubuf_started; /**< Aubuf was started flag */ - struct list filtl; /**< Audio filters in decoding order */ char *module; /**< Audio player module name */ char *device; /**< Audio player device name */ - void *sampv; /**< Sample buffer */ uint32_t ptime; /**< Packet time for receiving */ int pt; /**< Payload type for incoming RTP */ - double level_last; /**< Last audio level value [dBov] */ - bool level_set; /**< True if level_last is set */ enum aufmt play_fmt; /**< Sample format for audio playback*/ - enum aufmt dec_fmt; /**< Sample format for decoder */ - struct timestamp_recv ts_recv;/**< Receive timestamp state */ - struct { - uint64_t aubuf_overrun; - uint64_t aubuf_underrun; - uint64_t n_discard; - } stats; + struct aurpipe *aup; /**< Audio receive pipeline */ + bool first_write; /**< First write to auplay */ +}; - mtx_t *mtx; -}; +struct aurpipe; /** Generic Audio stream */ struct audio { MAGIC_DECL /**< Magic number for debugging */ struct autx tx; /**< Transmit */ - struct aurx rx; /**< Receive */ + struct aurx rx; /**< Audio Receiver */ struct stream *strm; /**< Generic media stream */ struct telev *telev; /**< Telephony events */ struct config_audio cfg; /**< Audio configuration */ @@ -200,29 +168,10 @@ static const char *uri_aulevel = "urn:ietf:params:rtp-hdrext:ssrc-audio-level"; */ uint64_t audio_jb_current_value(const struct audio *au) { - const struct aurx *rx; - if (!au) return 0; - rx = &au->rx; - - if (rx->aubuf) { - uint64_t b_p_ms; /* bytes per ms */ - - b_p_ms = aufmt_sample_size(rx->play_fmt) * - rx->auplay_prm.srate * rx->auplay_prm.ch / 1000; - - if (b_p_ms) { - uint64_t val; - - val = aubuf_cur_size(rx->aubuf) / b_p_ms; - - return val; - } - } - - return 0; + return aup_latency(au->rx.aup); } @@ -239,19 +188,6 @@ static double autx_calc_seconds(const struct autx *autx) } -static double aurx_calc_seconds(const struct aurx *aurx) -{ - uint64_t dur; - - if (!aurx->ac) - return .0; - - dur = timestamp_duration(&aurx->ts_recv); - - return timestamp_calc_seconds(dur, aurx->ac->crate); -} - - static void stop_tx(struct autx *tx, struct audio *a) { if (!tx || !a) @@ -278,13 +214,7 @@ static void stop_rx(struct aurx *rx) /* audio player must be stopped first */ rx->auplay = mem_deref(rx->auplay); - rx->aubuf = mem_deref(rx->aubuf); - if (rx->mtx) - mtx_lock(rx->mtx); - - list_flush(&rx->filtl); - if (rx->mtx) - mtx_unlock(rx->mtx); + aup_stop(rx->aup); } @@ -298,12 +228,9 @@ static void audio_destructor(void *arg) stop_rx(&a->rx); mem_deref(a->tx.enc); - mem_deref(a->rx.dec); mem_deref(a->tx.aubuf); mem_deref(a->tx.mb); mem_deref(a->tx.sampv); - mem_deref(a->rx.sampv); - mem_deref(a->rx.aubuf); mem_deref(a->tx.module); mem_deref(a->tx.device); mem_deref(a->rx.module); @@ -313,9 +240,9 @@ static void audio_destructor(void *arg) mem_deref(a->strm); mem_deref(a->telev); + mem_deref(a->rx.aup); mem_deref(a->tx.mtx); - mem_deref(a->rx.mtx); } @@ -604,9 +531,28 @@ bool audio_txtelev_empty(const struct audio *au) } +static void check_plframe(struct auframe *af1, struct auframe *af2) +{ + if ((af1->srate && af1->srate != af2->srate) || + (af1->ch && af1->ch != af2->ch )) { + warning("aurpipe: srate/ch of frame %u/%u vs " + "player %u/%u. Use module auresamp!\n", + af1->srate, af1->ch, + af2->srate, af2->ch); + } + + if (af1->fmt != af2->fmt) { + warning("aurpipe: invalid sample formats (%s -> %s). " + "%s\n", + aufmt_name(af1->fmt), aufmt_name(af2->fmt), + af1->fmt == AUFMT_S16LE ? + "Use module auconv!" : ""); + } +} + + /* - * Write samples to Audio Player. This version of the write handler is used - * for the configuration jitter_buffer_type JBUF_FIXED. + * Write samples to Audio Player. * * @note This function has REAL-TIME properties * @@ -620,22 +566,21 @@ bool audio_txtelev_empty(const struct audio *au) static void auplay_write_handler(struct auframe *af, void *arg) { struct audio *a = arg; + struct auframe afr; struct aurx *rx = &a->rx; - size_t num_bytes = auframe_size(af); - mtx_lock(rx->mtx); - if (rx->aubuf_started && aubuf_cur_size(rx->aubuf) < num_bytes) { + if (!rx->auplay) + return; - ++rx->stats.aubuf_underrun; + if (!rx->first_write) + afr = *af; -#if 0 - debug("audio: rx aubuf underrun (total %llu)\n", - rx->stats.aubuf_underrun); -#endif - } + aup_read(rx->aup, af); - mtx_unlock(rx->mtx); - aubuf_read_auframe(rx->aubuf, af); + if (!rx->first_write) { + (void)check_plframe(&afr, af); + rx->first_write = true; + } } @@ -724,15 +669,6 @@ static void handle_telev(struct audio *a, struct mbuf *mb) } -static bool audio_is_telev(struct audio *a, int pt) -{ - const struct sdp_format *lc; - - lc = sdp_media_lformat(stream_sdpmedia(a->strm), pt); - return lc && !str_casecmp(lc->name, "telephone-event"); -} - - static int stream_pt_handler(uint8_t pt, struct mbuf *mb, void *arg) { struct audio *a = arg; @@ -761,233 +697,22 @@ static int stream_pt_handler(uint8_t pt, struct mbuf *mb, void *arg) } -static int process_decfilt(struct aurx *rx, struct auframe *af) -{ - int err = 0; - - /* Process exactly one audio-frame in reverse list order */ - mtx_lock(rx->mtx); - for (struct le *le = rx->filtl.tail; le; le = le->prev) { - struct aufilt_dec_st *st = le->data; - - if (st->af && st->af->dech) - err = st->af->dech(st, af); - - if (err) - break; - } - - mtx_unlock(rx->mtx); - return err; -} - - -static int rx_push_aubuf(struct aurx *rx, const struct auframe *af) -{ - int err; - - if (aubuf_cur_size(rx->aubuf) >= rx->aubuf_maxsz) { - - ++rx->stats.aubuf_overrun; - -#if 0 - debug("audio: rx aubuf overrun (total %llu)\n", - rx->stats.aubuf_overrun); -#endif - } - - if (rx->auplay_prm.srate != af->srate || rx->auplay_prm.ch != af->ch) { - warning("audio: srate/ch of frame %u/%u vs player %u/%u. Use " - "module auresamp!\n", - af->srate, af->ch, - rx->auplay_prm.srate, rx->auplay_prm.ch); - } - - if (af->fmt != rx->play_fmt) { - warning("audio: rx: invalid sample formats (%s -> %s). %s\n", - aufmt_name(af->fmt), aufmt_name(rx->play_fmt), - rx->play_fmt == AUFMT_S16LE ? "Use module auconv!" : "" - ); - } - - err = aubuf_write_auframe(rx->aubuf, af); - if (err) - return err; - - mtx_lock(rx->mtx); - if (!rx->aubuf_started && - (aubuf_cur_size(rx->aubuf) >= rx->aubuf_minsz)) - rx->aubuf_started = true; - - mtx_unlock(rx->mtx); - - return 0; -} - - -static int aurx_stream_decode(struct aurx *rx, const struct rtp_header *hdr, - struct mbuf *mb, unsigned lostc, bool drop) -{ - struct auframe af; - size_t sampc = AUDIO_SAMPSZ; - bool marker = hdr->m; - int err = 0; - const struct aucodec *ac = rx->ac; - bool flush = rx->ssrc != hdr->ssrc; - - /* No decoder set */ - if (!ac) - return 0; - - rx->ssrc = hdr->ssrc; - - /* TODO: PLC */ - if (lostc && ac->plch) { - - err = ac->plch(rx->dec, - rx->dec_fmt, rx->sampv, &sampc, - mbuf_buf(mb), mbuf_get_left(mb)); - if (err) { - warning("audio: %s codec decode %u bytes: %m\n", - ac->name, mbuf_get_left(mb), err); - goto out; - } - } - else if (mbuf_get_left(mb)) { - - err = ac->dech(rx->dec, - rx->dec_fmt, rx->sampv, &sampc, - marker, mbuf_buf(mb), mbuf_get_left(mb)); - if (err) { - warning("audio: %s codec decode %u bytes: %m\n", - ac->name, mbuf_get_left(mb), err); - goto out; - } - } - else { - /* no PLC in the codec, might be done in filters below */ - sampc = 0; - } - - auframe_init(&af, rx->dec_fmt, rx->sampv, sampc, ac->srate, ac->ch); - af.timestamp = ((uint64_t) hdr->ts) * AUDIO_TIMEBASE / ac->crate; - - if (drop) { - aubuf_drop_auframe(rx->aubuf, &af); - goto out; - } - - if (flush) - aubuf_flush(rx->aubuf); - - err = process_decfilt(rx, &af); - if (err) - goto out; - - if (!rx->aubuf) - goto out; - - err = rx_push_aubuf(rx, &af); - out: - return err; -} - - -/* RFC 5285 -- A General Mechanism for RTP Header Extensions */ -static const struct rtpext *rtpext_find(const struct rtpext *extv, size_t extc, - uint8_t id) -{ - for (size_t i=0; iid == id) - return rtpext; - } - - return NULL; -} - - -/* Handle incoming stream data from the network */ +/** + * Stream receive handler for audio is called from RX thread if enabled + */ static void stream_recv_handler(const struct rtp_header *hdr, struct rtpext *extv, size_t extc, struct mbuf *mb, unsigned lostc, bool *ignore, void *arg) { struct audio *a = arg; - struct aurx *rx = &a->rx; - bool discard = false; - bool drop = *ignore; - int wrap; - (void) lostc; MAGIC_CHECK(a); - if (!mb) - goto out; - - if (audio_is_telev(a, hdr->pt)) { - *ignore = true; + if (!a->rx.aup) return; - } - - *ignore = false; - /* RFC 5285 -- A General Mechanism for RTP Header Extensions */ - const struct rtpext *ext = rtpext_find(extv, extc, a->extmap_aulevel); - if (ext) { - rx->level_last = -(double)(ext->data[0] & 0x7f); - rx->level_set = true; - } - - /* Save timestamp for incoming RTP packets */ - - if (!rx->ts_recv.is_set) - timestamp_set(&rx->ts_recv, hdr->ts); - - wrap = timestamp_wrap(hdr->ts, rx->ts_recv.last); - - switch (wrap) { - - case -1: - warning("audio: rtp timestamp wraps backwards" - " (delta = %d) -- discard\n", - (int32_t)(rx->ts_recv.last - hdr->ts)); - discard = true; - break; - - case 0: - break; - - case 1: - ++rx->ts_recv.num_wraps; - break; - - default: - break; - } - - rx->ts_recv.last = hdr->ts; - -#if 0 - re_printf("[time=%.3f] wrap=%d discard=%d\n", - aurx_calc_seconds(rx), wrap, discard); -#endif - - if (discard) { - ++rx->stats.n_discard; - return; - } - - out: - /* TODO: what if lostc > 1 ?*/ - /* PLC should generate lostc frames here. Not only one. - * aubuf should replace PLC frames with late arriving real frames. - * It should use timestamp to decide if a frame should be replaced. */ -/* if (lostc)*/ -/* (void)aurx_stream_decode(&a->rx, hdr, mb, lostc, drop);*/ - - (void)aurx_stream_decode(&a->rx, hdr, mb, 0, drop); + aup_receive(a->rx.aup, hdr, extv, extc, mb, lostc, ignore); } @@ -997,19 +722,23 @@ static int add_telev_codec(struct audio *a) struct sdp_format *sf; uint32_t pt = a->cfg.telev_pt; char pts[11]; + bool add = !sdp_media_lformat(m, pt); int err; (void)re_snprintf(pts, sizeof(pts), "%u", pt); /* Use payload-type 101 if available, for CiscoGW interop */ err = sdp_format_add(&sf, m, false, - (!sdp_media_lformat(m, pt)) ? pts : NULL, + add ? pts : NULL, telev_rtpfmt, TELEV_SRATE, 1, NULL, NULL, NULL, false, "0-15"); if (err) return err; - return err; + if (add) + aup_set_telev_pt(a->rx.aup, pt); + + return 0; } @@ -1074,15 +803,18 @@ int audio_alloc(struct audio **ap, struct list *streaml, tx->src_fmt = cfg->audio.src_fmt; rx->play_fmt = cfg->audio.play_fmt; - tx->enc_fmt = cfg->audio.enc_fmt; - rx->dec_fmt = cfg->audio.dec_fmt; err = stream_alloc(&a->strm, streaml, stream_prm, &cfg->avt, sdp_sess, MEDIA_AUDIO, mnat, mnat_sess, menc, menc_sess, offerer, - stream_recv_handler, NULL, stream_pt_handler, a); + stream_recv_handler, NULL, stream_pt_handler, + a); + if (err) + goto out; + + err = aup_alloc(&a->rx.aup, &a->cfg, AUDIO_SAMPSZ); if (err) goto out; @@ -1115,6 +847,7 @@ int audio_alloc(struct audio **ap, struct list *streaml, if (cfg->audio.level && offerer) { a->extmap_aulevel = stream_generate_extmap_id(a->strm); + aup_set_extmap(a->rx.aup, a->extmap_aulevel); err = sdp_media_set_lattr(stream_sdpmedia(a->strm), true, "extmap", @@ -1128,9 +861,7 @@ int audio_alloc(struct audio **ap, struct list *streaml, tx->sampv = mem_zalloc(AUDIO_SAMPSZ * aufmt_sample_size(tx->enc_fmt), NULL); - rx->sampv = mem_zalloc(AUDIO_SAMPSZ * aufmt_sample_size(rx->dec_fmt), - NULL); - if (!tx->mb || !tx->sampv || !rx->sampv) { + if (!tx->mb || !tx->sampv) { err = ENOMEM; goto out; } @@ -1184,7 +915,6 @@ int audio_alloc(struct audio **ap, struct list *streaml, rx->ptime = ptime; err = mutex_alloc(&tx->mtx); - err |= mutex_alloc(&rx->mtx); if (err) goto out; @@ -1291,7 +1021,7 @@ static int autx_print_pipeline(struct re_printf *pf, const struct autx *autx) err |= re_hprintf(pf, " ---> %s", st->af->name); } - err |= re_hprintf(pf, " ---> %s\n", + err |= re_hprintf(pf, " ---> %s", autx->ac ? autx->ac->name : "(encoder)"); return err; @@ -1300,7 +1030,6 @@ static int autx_print_pipeline(struct re_printf *pf, const struct autx *autx) static int aurx_print_pipeline(struct re_printf *pf, const struct aurx *rx) { - struct le *le; int err; if (!rx) @@ -1309,19 +1038,6 @@ static int aurx_print_pipeline(struct re_printf *pf, const struct aurx *rx) err = re_hprintf(pf, "audio rx pipeline: %10s", rx->ap ? rx->ap->name : "(play)"); - err |= re_hprintf(pf, " <--- aubuf"); - mtx_lock(rx->mtx); - for (le = list_head(&rx->filtl); le; le = le->next) { - struct aufilt_dec_st *st = le->data; - - if (st->af->dech) - err |= re_hprintf(pf, " <--- %s", st->af->name); - } - - mtx_unlock(rx->mtx); - err |= re_hprintf(pf, " <--- %s\n", - rx->ac ? rx->ac->name : "(decoder)"); - return err; } @@ -1341,23 +1057,18 @@ static int aufilt_setup(struct audio *a, struct list *aufiltl) struct autx *tx = &a->tx; struct aurx *rx = &a->rx; struct le *le; - bool update_enc = false, update_dec = false; + bool update_enc, update_dec; int err = 0; /* wait until we have both Encoder and Decoder */ - if (!tx->ac || !rx->ac) + if (!tx->ac || !aup_codec(rx->aup)) return 0; - if (list_isempty(&tx->filtl)) - update_enc = true; - - mtx_lock(rx->mtx); - if (list_isempty(&rx->filtl)) - update_dec = true; + update_dec = aup_filt_empty(rx->aup); + update_enc = list_isempty(&tx->filtl); - mtx_unlock(rx->mtx); aufilt_param_set(&encprm, tx->ac, tx->enc_fmt); - aufilt_param_set(&plprm, rx->ac, rx->dec_fmt); + aufilt_param_set(&plprm, aup_codec(rx->aup), a->cfg.play_fmt); if (a->cfg.srate_play && a->cfg.srate_play != plprm.srate) { plprm.srate = a->cfg.srate_play; } @@ -1393,9 +1104,7 @@ static int aufilt_setup(struct audio *a, struct list *aufiltl) } else { decst->af = af; - mtx_lock(rx->mtx); - list_append(&rx->filtl, &decst->le, decst); - mtx_unlock(rx->mtx); + aup_filt_append(rx->aup, decst); } } @@ -1413,12 +1122,9 @@ static int aufilt_setup(struct audio *a, struct list *aufiltl) static int start_player(struct aurx *rx, struct audio *a, struct list *auplayl) { - const struct aucodec *ac = rx->ac; + const struct aucodec *ac = aup_codec(rx->aup); uint32_t srate_dsp; uint32_t channels_dsp; - size_t sz; - size_t min_sz; - size_t max_sz; int err = 0; if (!ac) @@ -1444,36 +1150,6 @@ static int start_player(struct aurx *rx, struct audio *a, prm.ptime = rx->ptime; prm.fmt = rx->play_fmt; - if (!rx->aubuf) { - const uint16_t ptime_min = (uint16_t)a->cfg.buffer.min; - const uint16_t ptime_max = (uint16_t)a->cfg.buffer.max; - sz = aufmt_sample_size(rx->play_fmt); - - if (!ptime_min || !ptime_max) - return EINVAL; - - min_sz = sz*calc_nsamp(prm.srate, prm.ch, ptime_min); - max_sz = sz*calc_nsamp(prm.srate, prm.ch, ptime_max); - - debug("audio: create auplay buffer" - " [%u - %u ms]" - " [%zu - %zu bytes]\n", - ptime_min, ptime_max, min_sz, max_sz); - - err = aubuf_alloc(&rx->aubuf, min_sz, max_sz); - if (err) { - warning("audio: aubuf alloc error (%m)\n", - err); - return err; - } - - aubuf_set_mode(rx->aubuf, a->cfg.adaptive ? - AUBUF_ADAPTIVE : AUBUF_FIXED); - aubuf_set_silence(rx->aubuf, a->cfg.silence); - rx->aubuf_minsz = min_sz; - rx->aubuf_maxsz = max_sz; - } - rx->auplay_prm = prm; err = auplay_alloc(&rx->auplay, auplayl, rx->module, @@ -1493,8 +1169,6 @@ static int start_player(struct aurx *rx, struct audio *a, } out: - if (err) - rx->aubuf = mem_deref(rx->aubuf); return 0; } @@ -1614,9 +1288,7 @@ static void audio_flush_filters(struct audio *a) struct aurx *rx = &a->rx; struct autx *tx = &a->tx; - mtx_lock(rx->mtx); - list_flush(&rx->filtl); - mtx_unlock(rx->mtx); + aup_flush(rx->aup); mtx_lock(a->tx.mtx); list_flush(&tx->filtl); @@ -1663,12 +1335,13 @@ int audio_start(struct audio *a) return err; } - if (a->tx.ac && a->rx.ac) { + if (a->tx.ac && aup_codec(a->rx.aup)) { if (!a->started) { - info("%H%H", + info("%H\n%H%H", autx_print_pipeline, &a->tx, - aurx_print_pipeline, &a->rx); + aurx_print_pipeline, &a->rx, + aup_print_pipeline, a->rx.aup); } a->started = true; @@ -1839,36 +1512,25 @@ int audio_decoder_set(struct audio *a, const struct aucodec *ac, return EINVAL; rx = &a->rx; + rx->pt = pt_rx; - if (ac != rx->ac) { + if (ac != aup_codec(rx->aup)) { struct sdp_media *m; bool reset; m = stream_sdpmedia(audio_strm(a)); - reset = !aucodec_equal(ac, rx->ac); + reset = !aucodec_equal(ac, aup_codec(rx->aup)); reset |= !(sdp_media_dir(m) & SDP_RECVONLY); if (reset) { rx->auplay = mem_deref(rx->auplay); audio_flush_filters(a); - aubuf_flush(rx->aubuf); stream_flush(a->strm); } - - info("audio: Set audio decoder: %s %uHz %dch\n", - ac->name, ac->srate, ac->ch); - - rx->pt = pt_rx; - rx->ac = ac; - rx->dec = mem_deref(rx->dec); } - if (ac->decupdh) { - err = ac->decupdh(&rx->dec, ac, params); - if (err) { - warning("audio: alloc decoder: %m\n", err); - return err; - } - } + err = aup_decoder_set(rx->aup, ac, params); + if (err) + return err; stream_set_srate(a->strm, 0, ac->crate); @@ -1983,6 +1645,7 @@ static bool extmap_handler(const char *name, const char *value, void *arg) } au->extmap_aulevel = extmap.id; + aup_set_extmap(au->rx.aup, au->extmap_aulevel); err = sdp_media_set_lattr(stream_sdpmedia(au->strm), true, "extmap", @@ -2079,11 +1742,11 @@ int audio_level_get(const struct audio *au, double *levelp) if (!au->level_enabled) return ENOTSUP; - if (!au->rx.level_set) + if (!aup_level_set(au->rx.aup)) return ENOENT; if (levelp) - *levelp = au->rx.level_last; + *levelp = aup_level(au->rx.aup); return 0; } @@ -2101,7 +1764,8 @@ int audio_debug(struct re_printf *pf, const struct audio *a) { const struct autx *tx; const struct aurx *rx; - size_t sztx, szrx; + const struct aurpipe *aup; + size_t sztx; int err; if (!a) @@ -2109,9 +1773,9 @@ int audio_debug(struct re_printf *pf, const struct audio *a) tx = &a->tx; rx = &a->rx; + aup = a->rx.aup; sztx = aufmt_sample_size(tx->src_fmt); - szrx = aufmt_sample_size(rx->play_fmt); err = re_hprintf(pf, "\n--- Audio stream ---\n"); @@ -2137,44 +1801,18 @@ int audio_debug(struct re_printf *pf, const struct audio *a) err |= re_hprintf(pf, " time = %.3f sec\n", autx_calc_seconds(tx)); - err |= re_hprintf(pf, - " rx: decode: %H %s\n", - aucodec_print, rx->ac, aufmt_name(rx->dec_fmt)); - err |= re_hprintf(pf, " aubuf: %H" - " (cur %.2fms, max %.2fms, or %llu, ur %llu)\n", - aubuf_debug, rx->aubuf, - calc_ptime(aubuf_cur_size(rx->aubuf)/szrx, - rx->auplay_prm.srate, - rx->auplay_prm.ch), - calc_ptime(rx->aubuf_maxsz/szrx, - rx->auplay_prm.srate, - rx->auplay_prm.ch), - rx->stats.aubuf_overrun, - rx->stats.aubuf_underrun - ); + err |= aup_debug(pf, aup); err |= re_hprintf(pf, " player: %s,%s %s\n", rx->ap ? rx->ap->name : "none", rx->device, aufmt_name(rx->play_fmt)); - err |= re_hprintf(pf, " n_discard:%llu\n", - rx->stats.n_discard); - if (rx->level_set) { - err |= re_hprintf(pf, " level %.3f dBov\n", - rx->level_last); - } - if (rx->ts_recv.is_set) { - err |= re_hprintf(pf, " time = %.3f sec\n", - aurx_calc_seconds(rx)); - } - else { - err |= re_hprintf(pf, " time = (not started)\n"); - } err |= re_hprintf(pf, - " %H" - " %H", + " %H\n" + " %H%H", autx_print_pipeline, tx, - aurx_print_pipeline, rx); + aurx_print_pipeline, rx, + aup_print_pipeline, aup); err |= stream_debug(pf, a->strm); @@ -2346,14 +1984,10 @@ int audio_set_bitrate(struct audio *au, uint32_t bitrate) */ bool audio_rxaubuf_started(const struct audio *au) { - const struct aurx *rx; - - if (!au) + if (!au || !au->rx.aup) return false; - rx = &au->rx; - - return rx->aubuf_started; + return aup_started(au->rx.aup); } @@ -2417,7 +2051,7 @@ const struct aucodec *audio_codec(const struct audio *au, bool tx) if (!au) return NULL; - return tx ? au->tx.ac : au->rx.ac; + return tx ? au->tx.ac : aup_codec(au->rx.aup); } diff --git a/src/aureceiver.c b/src/aureceiver.c new file mode 100644 index 0000000000..c718fa887c --- /dev/null +++ b/src/aureceiver.c @@ -0,0 +1,654 @@ +/** + * @file src/aureceiver.c Audio stream receiver + * + * Copyright (C) 2023 Alfred E. Heggestad, Christian Spielberger + */ +#include +#include +#include +#include +#include +#include "core.h" + + +/** + * Audio receive pipeline + * + \verbatim + + Processing decoder pipeline: + + .--------. .-------. .--------. .--------. + |\ | | | | | | | | + | |<--| auplay |<--| aubuf |<--| aufilt |<--| decode |<--- RTP + |/ | | | | | | | | + '--------' '-------' '--------' '--------' + + \endverbatim + */ +struct aurpipe { + uint32_t srate; /**< Decoder sample rate */ + uint32_t ch; /**< Decoder channel number */ + enum aufmt fmt; /**< Decoder sample format */ + const struct config_audio *cfg; /**< Audio configuration */ + struct audec_state *dec; /**< Audio decoder state (optional) */ + const struct aucodec *ac; /**< Current audio decoder */ + struct aubuf *aubuf; /**< Audio buffer before auplay */ + size_t aubuf_minsz; /**< Minimum aubuf size in [bytes] */ + size_t aubuf_maxsz; /**< Maximum aubuf size in [bytes] */ + bool aubuf_started; /**< Aubuf started flag */ + uint32_t ssrc; /**< Incoming synchronization source */ + struct list filtl; /**< Audio filters in decoding order */ + void *sampv; /**< Sample buffer */ + size_t sampvsz; /**< Sample buffer size */ + + double level_last; /**< Last audio level value [dBov] */ + bool level_set; /**< True if level_last is set */ + struct timestamp_recv ts_recv;/**< Receive timestamp state */ + uint8_t extmap_aulevel; /**< ID Range 1-14 inclusive */ + uint32_t telev_pt; /**< Payload type for telephone-events */ + + struct { + uint64_t aubuf_overrun; + uint64_t aubuf_underrun; + uint64_t n_discard; + } stats; + + mtx_t *mtx; +}; + + +static void destructor(void *arg) +{ + struct aurpipe *rp = arg; + + mem_deref(rp->dec); + mem_deref(rp->aubuf); + mem_deref(rp->sampv); + mem_deref(rp->mtx); + list_flush(&rp->filtl); +} + + +static int aup_process_decfilt(struct aurpipe *rp, struct auframe *af) +{ + int err = 0; + + /* Process exactly one audio-frame in reverse list order */ + for (struct le *le = rp->filtl.tail; le; le = le->prev) { + struct aufilt_dec_st *st = le->data; + + if (st->af && st->af->dech) + err = st->af->dech(st, af); + + if (err) + break; + } + + return err; +} + + +static double aup_calc_seconds(const struct aurpipe *rp) +{ + uint64_t dur; + double seconds; + + if (!rp->ac) + return .0; + + dur = timestamp_duration(&rp->ts_recv); + seconds = timestamp_calc_seconds(dur, rp->ac->crate); + + return seconds; +} + + +static int aup_alloc_aubuf(struct aurpipe *rp, const struct auframe *af) +{ + size_t min_sz; + size_t max_sz; + size_t sz; + const struct config_audio *cfg = rp->cfg; + int err; + + sz = aufmt_sample_size(cfg->play_fmt); + min_sz = sz * calc_nsamp(af->srate, af->ch, cfg->buffer.min); + max_sz = sz * calc_nsamp(af->srate, af->ch, cfg->buffer.max); + + debug("aurpipe: create audio buffer" + " [%u - %u ms]" + " [%zu - %zu bytes]\n", + (unsigned) cfg->buffer.min, (unsigned) cfg->buffer.max, + min_sz, max_sz); + + err = aubuf_alloc(&rp->aubuf, min_sz, max_sz); + if (err) { + warning("aurpipe: aubuf alloc error (%m)\n", + err); + } + + aubuf_set_mode(rp->aubuf, cfg->adaptive ? + AUBUF_ADAPTIVE : AUBUF_FIXED); + aubuf_set_silence(rp->aubuf, cfg->silence); + rp->aubuf_minsz = min_sz; + rp->aubuf_maxsz = max_sz; + return err; +} + + +static int aup_push_aubuf(struct aurpipe *rp, const struct auframe *af) +{ + int err; + + if (!rp->aubuf) { + err = aup_alloc_aubuf(rp, af); + if (err) + return err; + } + + if (aubuf_cur_size(rp->aubuf) >= rp->aubuf_maxsz) { + + ++rp->stats.aubuf_overrun; + +#if 0 + debug("audio: rx aubuf overrun (total %llu)\n", + rp->stats.aubuf_overrun); +#endif + } + + err = aubuf_write_auframe(rp->aubuf, af); + if (err) + return err; + + rp->srate = af->srate; + rp->ch = af->ch; + rp->fmt = af->fmt; + + if (!rp->aubuf_started && + (aubuf_cur_size(rp->aubuf) >= rp->aubuf_minsz)) + rp->aubuf_started = true; + + return 0; +} + + +static int aup_stream_decode(struct aurpipe *rp, const struct rtp_header *hdr, + struct mbuf *mb, unsigned lostc, bool drop) +{ + struct auframe af; + size_t sampc = rp->sampvsz / aufmt_sample_size(rp->fmt); + bool marker = hdr->m; + int err = 0; + const struct aucodec *ac = rp->ac; + bool flush = rp->ssrc != hdr->ssrc; + + /* No decoder set */ + if (!ac) + return 0; + + rp->ssrc = hdr->ssrc; + + /* TODO: PLC */ + if (lostc && ac->plch) { + + err = ac->plch(rp->dec, + rp->fmt, rp->sampv, &sampc, + mbuf_buf(mb), mbuf_get_left(mb)); + if (err) { + warning("audio: %s codec decode %u bytes: %m\n", + ac->name, mbuf_get_left(mb), err); + goto out; + } + } + else if (mbuf_get_left(mb)) { + + err = ac->dech(rp->dec, + rp->fmt, rp->sampv, &sampc, + marker, mbuf_buf(mb), mbuf_get_left(mb)); + if (err) { + warning("audio: %s codec decode %u bytes: %m\n", + ac->name, mbuf_get_left(mb), err); + goto out; + } + } + else { + /* no PLC in the codec, might be done in filters below */ + sampc = 0; + } + + auframe_init(&af, rp->fmt, rp->sampv, sampc, ac->srate, ac->ch); + af.timestamp = ((uint64_t) hdr->ts) * AUDIO_TIMEBASE / ac->crate; + + if (drop) { + aubuf_drop_auframe(rp->aubuf, &af); + goto out; + } + + if (flush) + aubuf_flush(rp->aubuf); + + err = aup_process_decfilt(rp, &af); + if (err) + goto out; + + err = aup_push_aubuf(rp, &af); + out: + return err; +} + + +/* RFC 5285 -- A General Mechanism for RTP Header Extensions */ +static const struct rtpext *rtpext_find(const struct rtpext *extv, size_t extc, + uint8_t id) +{ + for (size_t i=0; iid == id) + return rtpext; + } + + return NULL; +} + + +/* Handle incoming stream data from the network */ +void aup_receive(struct aurpipe *rp, const struct rtp_header *hdr, + struct rtpext *extv, size_t extc, + struct mbuf *mb, unsigned lostc, bool *ignore) +{ + bool discard = false; + bool drop = *ignore; + int wrap; + (void) lostc; + + if (!mb) + goto out; + + mtx_lock(rp->mtx); + if (hdr->pt == rp->telev_pt) { + mtx_unlock(rp->mtx); + *ignore = true; + return; + } + + *ignore = false; + + /* RFC 5285 -- A General Mechanism for RTP Header Extensions */ + const struct rtpext *ext = rtpext_find(extv, extc, rp->extmap_aulevel); + if (ext) { + rp->level_last = -(double)(ext->data[0] & 0x7f); + rp->level_set = true; + } + + /* Save timestamp for incoming RTP packets */ + + if (!rp->ts_recv.is_set) + timestamp_set(&rp->ts_recv, hdr->ts); + + wrap = timestamp_wrap(hdr->ts, rp->ts_recv.last); + + switch (wrap) { + + case -1: + warning("audio: rtp timestamp wraps backwards" + " (delta = %d) -- discard\n", + (int32_t)(rp->ts_recv.last - hdr->ts)); + discard = true; + break; + + case 0: + break; + + case 1: + ++rp->ts_recv.num_wraps; + break; + + default: + break; + } + + rp->ts_recv.last = hdr->ts; + + if (discard) { + ++rp->stats.n_discard; + goto unlock; + } + + out: + /* TODO: what if lostc > 1 ?*/ + /* PLC should generate lostc frames here. Not only one. + * aubuf should replace PLC frames with late arriving real frames. + * It should use timestamp to decide if a frame should be replaced. */ +/* if (lostc)*/ +/* (void)aup_stream_decode(rp, hdr, mb, lostc, drop);*/ + + (void)aup_stream_decode(rp, hdr, mb, 0, drop); + +unlock: + mtx_unlock(rp->mtx); +} + + +void aup_set_extmap(struct aurpipe *rp, uint8_t aulevel) +{ + if (!rp) + return; + + mtx_lock(rp->mtx); + rp->extmap_aulevel = aulevel; + mtx_unlock(rp->mtx); +} + + +void aup_set_telev_pt(struct aurpipe *rp, int pt) +{ + if (!rp) + return; + + mtx_lock(rp->mtx); + rp->telev_pt = pt; + mtx_unlock(rp->mtx); +} + + +uint64_t aup_latency(const struct aurpipe *rp) +{ + uint64_t bpms; + if (!rp || !rp->aubuf) + return 0; + + mtx_lock(rp->mtx); + bpms = rp->srate * rp->ch * aufmt_sample_size(rp->fmt) / 1000; + mtx_unlock(rp->mtx); + if (bpms) { + uint64_t val = aubuf_cur_size(rp->aubuf) / bpms; + + return val; + } + + return 0; +} + + +int aup_alloc(struct aurpipe **aupp, const struct config_audio *cfg, + size_t sampc) +{ + struct aurpipe *rp; + int err; + + if (!aupp) + return EINVAL; + + rp = mem_zalloc(sizeof(*rp), destructor); + if (!rp) + return ENOMEM; + + rp->cfg = cfg; + rp->srate = cfg->srate_play; + rp->ch = cfg->channels_play; + rp->fmt = cfg->play_fmt; + rp->sampvsz = sampc * aufmt_sample_size(rp->fmt); + rp->sampv = mem_zalloc(rp->sampvsz, NULL); + if (!rp->sampv) { + err = ENOMEM; + goto out; + } + + err = mutex_alloc(&rp->mtx); + +out: + if (err) + rp = mem_deref(rp); + else + *aupp = rp; + + return err; +} + + +void aup_flush(struct aurpipe *rp) +{ + if (!rp) + return; + + mtx_lock(rp->mtx); + aubuf_flush(rp->aubuf); + + /* Reset audio filter chain */ + list_flush(&rp->filtl); + mtx_unlock(rp->mtx); +} + + +int aup_decoder_set(struct aurpipe *rp, + const struct aucodec *ac, const char *params) +{ + int err = 0; + + if (!rp || !ac) + return EINVAL; + + info("audio: Set audio decoder: %s %uHz %dch\n", + ac->name, ac->srate, ac->ch); + + mtx_lock(rp->mtx); + if (ac != rp->ac) { + rp->ac = ac; + rp->dec = mem_deref(rp->dec); + } + + if (ac->decupdh) { + err = ac->decupdh(&rp->dec, ac, params); + if (err) { + warning("aurpipe: alloc decoder: %m\n", err); + goto out; + } + } + +out: + mtx_unlock(rp->mtx); + return err; +} + + +int aup_filt_append(struct aurpipe *rp, struct aufilt_dec_st *decst) +{ + if (!rp || !decst) + return EINVAL; + + mtx_lock(rp->mtx); + list_append(&rp->filtl, &decst->le, decst); + mtx_unlock(rp->mtx); + + return 0; +} + + +bool aup_filt_empty(const struct aurpipe *rp) +{ + bool empty; + if (!rp) + return false; + + mtx_lock(rp->mtx); + empty = list_isempty(&rp->filtl); + mtx_unlock(rp->mtx); + + return empty; +} + + +bool aup_level_set(const struct aurpipe *rp) +{ + bool set; + if (!rp) + return false; + + mtx_lock(rp->mtx); + set = rp->level_set; + mtx_unlock(rp->mtx); + + return set; +} + + +double aup_level(const struct aurpipe *rp) +{ + double v; + if (!rp) + return 0.0; + + mtx_lock(rp->mtx); + v = rp->level_last; + mtx_unlock(rp->mtx); + + return v; +} + + +const struct aucodec *aup_codec(const struct aurpipe *rp) +{ + const struct aucodec *ac; + + if (!rp) + return NULL; + + mtx_lock(rp->mtx); + ac = rp->ac; + mtx_unlock(rp->mtx); + return ac; +} + + +void aup_read(struct aurpipe *rp, struct auframe *af) +{ + size_t num_bytes = auframe_size(af); + + mtx_lock(rp->mtx); + if (rp->aubuf_started && aubuf_cur_size(rp->aubuf) < num_bytes) { + + ++rp->stats.aubuf_underrun; + +#if 0 + debug("aurpipe: aubuf underrun (total %llu)\n", + rp->stats.aubuf_underrun); +#endif + } + + mtx_unlock(rp->mtx); + aubuf_read_auframe(rp->aubuf, af); +} + + +void aup_stop(struct aurpipe *rp) +{ + if (!rp) + return; + + mtx_lock(rp->mtx); + rp->ac = NULL; + mtx_unlock(rp->mtx); +} + + +bool aup_started(const struct aurpipe *rp) +{ + bool started; + if (!rp) + return false; + + mtx_lock(rp->mtx); + started = rp->aubuf_started; + mtx_unlock(rp->mtx); + + return started; +} + + +int aup_debug(struct re_printf *pf, const struct aurpipe *rp) +{ + struct mbuf *mb; + uint64_t bpms; + int err; + + if (!rp) + return 0; + + mb = mbuf_alloc(32); + if (!mb) + return ENOMEM; + + mtx_lock(rp->mtx); + bpms = rp->srate * rp->ch * aufmt_sample_size(rp->fmt) / 1000; + err = mbuf_printf(mb, + " rx: decode: %H %s\n", + aucodec_print, rp->ac, + aufmt_name(rp->fmt)); + err |= mbuf_printf(mb, " aubuf: %H" + " (cur %.2fms, max %.2fms, or %llu, ur %llu)\n", + aubuf_debug, rp->aubuf, + aubuf_cur_size(rp->aubuf) / bpms, + rp->aubuf_maxsz / bpms, + rp->stats.aubuf_overrun, + rp->stats.aubuf_underrun); + err |= mbuf_printf(mb, " n_discard:%llu\n", + rp->stats.n_discard); + if (rp->level_set) { + err |= mbuf_printf(mb, " level %.3f dBov\n", + rp->level_last); + } + if (rp->ts_recv.is_set) { + err |= mbuf_printf(mb, " time = %.3f sec\n", + aup_calc_seconds(rp)); + } + else { + err |= mbuf_printf(mb, " time = (not started)\n"); + } + mtx_unlock(rp->mtx); + + if (err) + goto out; + + err = re_hprintf(pf, "%b", mb->buf, mb->pos); +out: + mem_deref(mb); + return err; +} + + +int aup_print_pipeline(struct re_printf *pf, const struct aurpipe *rp) +{ + struct mbuf *mb; + struct le *le; + int err; + + if (!rp) + return 0; + + mb = mbuf_alloc(32); + if (!mb) + return ENOMEM; + + err = mbuf_printf(mb, " <--- aubuf"); + mtx_lock(rp->mtx); + for (le = list_head(&rp->filtl); le; le = le->next) { + struct aufilt_dec_st *st = le->data; + + if (st->af->dech) + err |= mbuf_printf(mb, " <--- %s", st->af->name); + } + + err |= mbuf_printf(mb, " <--- %s\n", + rp->ac ? rp->ac->name : "(decoder)"); + mtx_unlock(rp->mtx); + + if (err) + goto out; + + err = re_hprintf(pf, "%b", mb->buf, mb->pos); +out: + mem_deref(mb); + return err; +} diff --git a/src/core.h b/src/core.h index f03a1a3704..437af324a3 100644 --- a/src/core.h +++ b/src/core.h @@ -112,6 +112,36 @@ void audio_sdp_attr_decode(struct audio *a); int aucodec_print(struct re_printf *pf, const struct aucodec *ac); +/* + * Audio Receiver Pipeline + */ + +struct aurpipe; + +int aup_alloc(struct aurpipe **aupp, const struct config_audio *cfg, + size_t sampc); +int aup_decoder_set(struct aurpipe *rp, + const struct aucodec *ac, const char *params); +int aup_filt_append(struct aurpipe *rp, struct aufilt_dec_st *decst); +void aup_flush(struct aurpipe *rp); +void aup_set_extmap(struct aurpipe *rp, uint8_t aulevel); +void aup_set_telev_pt(struct aurpipe *rp, int pt); +void aup_receive(struct aurpipe *rp, const struct rtp_header *hdr, + struct rtpext *extv, size_t extc, + struct mbuf *mb, unsigned lostc, bool *ignore); +void aup_read(struct aurpipe *rp, struct auframe *af); +void aup_stop(struct aurpipe *rp); + +const struct aucodec *aup_codec(const struct aurpipe *rp); +uint64_t aup_latency(const struct aurpipe *rp); +bool aup_started(const struct aurpipe *rp); +bool aup_filt_empty(const struct aurpipe *rp); +bool aup_level_set(const struct aurpipe *rp); +double aup_level(const struct aurpipe *rp); +int aup_debug(struct re_printf *pf, const struct aurpipe *rp); +int aup_print_pipeline(struct re_printf *pf, const struct aurpipe *rp); + + /* * Call Control */ From c10edda2600ddadb11777aed9db779783b13d3f5 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Thu, 11 May 2023 17:39:49 +0200 Subject: [PATCH 02/31] aureceiver: simplify logging of over/underruns Reducing complexity here helps to avoid concurrency problems with RX thread --- src/aureceiver.c | 48 +++--------------------------------------------- 1 file changed, 3 insertions(+), 45 deletions(-) diff --git a/src/aureceiver.c b/src/aureceiver.c index c718fa887c..2d161b5341 100644 --- a/src/aureceiver.c +++ b/src/aureceiver.c @@ -34,9 +34,6 @@ struct aurpipe { struct audec_state *dec; /**< Audio decoder state (optional) */ const struct aucodec *ac; /**< Current audio decoder */ struct aubuf *aubuf; /**< Audio buffer before auplay */ - size_t aubuf_minsz; /**< Minimum aubuf size in [bytes] */ - size_t aubuf_maxsz; /**< Maximum aubuf size in [bytes] */ - bool aubuf_started; /**< Aubuf started flag */ uint32_t ssrc; /**< Incoming synchronization source */ struct list filtl; /**< Audio filters in decoding order */ void *sampv; /**< Sample buffer */ @@ -49,8 +46,6 @@ struct aurpipe { uint32_t telev_pt; /**< Payload type for telephone-events */ struct { - uint64_t aubuf_overrun; - uint64_t aubuf_underrun; uint64_t n_discard; } stats; @@ -131,8 +126,6 @@ static int aup_alloc_aubuf(struct aurpipe *rp, const struct auframe *af) aubuf_set_mode(rp->aubuf, cfg->adaptive ? AUBUF_ADAPTIVE : AUBUF_FIXED); aubuf_set_silence(rp->aubuf, cfg->silence); - rp->aubuf_minsz = min_sz; - rp->aubuf_maxsz = max_sz; return err; } @@ -147,16 +140,6 @@ static int aup_push_aubuf(struct aurpipe *rp, const struct auframe *af) return err; } - if (aubuf_cur_size(rp->aubuf) >= rp->aubuf_maxsz) { - - ++rp->stats.aubuf_overrun; - -#if 0 - debug("audio: rx aubuf overrun (total %llu)\n", - rp->stats.aubuf_overrun); -#endif - } - err = aubuf_write_auframe(rp->aubuf, af); if (err) return err; @@ -165,10 +148,6 @@ static int aup_push_aubuf(struct aurpipe *rp, const struct auframe *af) rp->ch = af->ch; rp->fmt = af->fmt; - if (!rp->aubuf_started && - (aubuf_cur_size(rp->aubuf) >= rp->aubuf_minsz)) - rp->aubuf_started = true; - return 0; } @@ -524,20 +503,6 @@ const struct aucodec *aup_codec(const struct aurpipe *rp) void aup_read(struct aurpipe *rp, struct auframe *af) { - size_t num_bytes = auframe_size(af); - - mtx_lock(rp->mtx); - if (rp->aubuf_started && aubuf_cur_size(rp->aubuf) < num_bytes) { - - ++rp->stats.aubuf_underrun; - -#if 0 - debug("aurpipe: aubuf underrun (total %llu)\n", - rp->stats.aubuf_underrun); -#endif - } - - mtx_unlock(rp->mtx); aubuf_read_auframe(rp->aubuf, af); } @@ -555,15 +520,10 @@ void aup_stop(struct aurpipe *rp) bool aup_started(const struct aurpipe *rp) { - bool started; if (!rp) return false; - mtx_lock(rp->mtx); - started = rp->aubuf_started; - mtx_unlock(rp->mtx); - - return started; + return aubuf_started(rp->aubuf); } @@ -587,12 +547,10 @@ int aup_debug(struct re_printf *pf, const struct aurpipe *rp) aucodec_print, rp->ac, aufmt_name(rp->fmt)); err |= mbuf_printf(mb, " aubuf: %H" - " (cur %.2fms, max %.2fms, or %llu, ur %llu)\n", + " (cur %.2fms, max %.2fms)\n", aubuf_debug, rp->aubuf, aubuf_cur_size(rp->aubuf) / bpms, - rp->aubuf_maxsz / bpms, - rp->stats.aubuf_overrun, - rp->stats.aubuf_underrun); + aubuf_maxsz(rp->aubuf) / bpms); err |= mbuf_printf(mb, " n_discard:%llu\n", rp->stats.n_discard); if (rp->level_set) { From 9f02efc2d7b570f4122959f167a993e4bd6335b9 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Fri, 26 May 2023 09:21:33 +0200 Subject: [PATCH 03/31] aup: concurrency safe check if aubuf exists --- src/aureceiver.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/aureceiver.c b/src/aureceiver.c index 2d161b5341..fc05f7453a 100644 --- a/src/aureceiver.c +++ b/src/aureceiver.c @@ -34,6 +34,7 @@ struct aurpipe { struct audec_state *dec; /**< Audio decoder state (optional) */ const struct aucodec *ac; /**< Current audio decoder */ struct aubuf *aubuf; /**< Audio buffer before auplay */ + RE_ATOMIC bool ready; /**< Audio buffer is ready flag */ uint32_t ssrc; /**< Incoming synchronization source */ struct list filtl; /**< Audio filters in decoding order */ void *sampv; /**< Sample buffer */ @@ -133,11 +134,14 @@ static int aup_alloc_aubuf(struct aurpipe *rp, const struct auframe *af) static int aup_push_aubuf(struct aurpipe *rp, const struct auframe *af) { int err; + uint64_t bpms; if (!rp->aubuf) { err = aup_alloc_aubuf(rp, af); if (err) return err; + + rp->ready = true; } err = aubuf_write_auframe(rp->aubuf, af); @@ -389,7 +393,7 @@ int aup_alloc(struct aurpipe **aupp, const struct config_audio *cfg, void aup_flush(struct aurpipe *rp) { - if (!rp) + if (!rp || !rp->ready) return; mtx_lock(rp->mtx); @@ -503,6 +507,9 @@ const struct aucodec *aup_codec(const struct aurpipe *rp) void aup_read(struct aurpipe *rp, struct auframe *af) { + if (!rp || !rp->ready) + return; + aubuf_read_auframe(rp->aubuf, af); } @@ -520,7 +527,7 @@ void aup_stop(struct aurpipe *rp) bool aup_started(const struct aurpipe *rp) { - if (!rp) + if (!rp || !rp->ready) return false; return aubuf_started(rp->aubuf); @@ -533,7 +540,7 @@ int aup_debug(struct re_printf *pf, const struct aurpipe *rp) uint64_t bpms; int err; - if (!rp) + if (!rp || !rp->ready) return 0; mb = mbuf_alloc(32); From 5c0e0f30d668d0321248cb99f680bba46aba3b6e Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Fri, 26 May 2023 09:28:29 +0200 Subject: [PATCH 04/31] aup: use atomic instead mtx lock for latency --- src/aureceiver.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/aureceiver.c b/src/aureceiver.c index fc05f7453a..b362bfb243 100644 --- a/src/aureceiver.c +++ b/src/aureceiver.c @@ -48,6 +48,7 @@ struct aurpipe { struct { uint64_t n_discard; + RE_ATOMIC uint64_t latency; /**< Latency in [ms] */ } stats; mtx_t *mtx; @@ -152,6 +153,10 @@ static int aup_push_aubuf(struct aurpipe *rp, const struct auframe *af) rp->ch = af->ch; rp->fmt = af->fmt; + bpms = rp->srate * rp->ch * aufmt_sample_size(rp->fmt) / 1000; + if (bpms) + rp->stats.latency = aubuf_cur_size(rp->aubuf) / bpms; + return 0; } @@ -338,20 +343,10 @@ void aup_set_telev_pt(struct aurpipe *rp, int pt) uint64_t aup_latency(const struct aurpipe *rp) { - uint64_t bpms; - if (!rp || !rp->aubuf) + if (!rp) return 0; - mtx_lock(rp->mtx); - bpms = rp->srate * rp->ch * aufmt_sample_size(rp->fmt) / 1000; - mtx_unlock(rp->mtx); - if (bpms) { - uint64_t val = aubuf_cur_size(rp->aubuf) / bpms; - - return val; - } - - return 0; + return rp->stats.latency; } From 364132453d47eeba9411edeebc7871338131aae5 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Fri, 26 May 2023 10:14:18 +0200 Subject: [PATCH 05/31] audio: fix sanitizer warning in auplay_write_handler --- src/audio.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/audio.c b/src/audio.c index 093cf88211..2817890f1c 100644 --- a/src/audio.c +++ b/src/audio.c @@ -569,9 +569,6 @@ static void auplay_write_handler(struct auframe *af, void *arg) struct auframe afr; struct aurx *rx = &a->rx; - if (!rx->auplay) - return; - if (!rx->first_write) afr = *af; From 1f84cfe488d094effc43578b5172342c8365278a Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Tue, 13 Jun 2023 17:39:05 +0200 Subject: [PATCH 06/31] aucodec: move aucodec_print to internal API --- include/baresip.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/baresip.h b/include/baresip.h index 8758a4c771..66296d0108 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -1190,7 +1190,6 @@ void aucodec_unregister(struct aucodec *ac); const struct aucodec *aucodec_find(const struct list *aucodecl, const char *name, uint32_t srate, uint8_t ch); -int aucodec_print(struct re_printf *pf, const struct aucodec *ac); /* From 68d143b2a0a13f51a2fb1f8a85bc1d27e25c556b Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Fri, 16 Jun 2023 11:29:32 +0200 Subject: [PATCH 07/31] audio/video: disable stream in destructor --- src/audio.c | 1 + src/video.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/audio.c b/src/audio.c index 2817890f1c..6a9cb26c86 100644 --- a/src/audio.c +++ b/src/audio.c @@ -224,6 +224,7 @@ static void audio_destructor(void *arg) debug("audio: destroyed (started=%d)\n", a->started); + stream_enable(a->strm, false); stop_tx(&a->tx, a); stop_rx(&a->rx); diff --git a/src/video.c b/src/video.c index f3a941365e..213db23ca6 100644 --- a/src/video.c +++ b/src/video.c @@ -277,6 +277,8 @@ static void video_destructor(void *arg) struct vtx *vtx = &v->vtx; struct vrx *vrx = &v->vrx; + stream_enable(v->strm, false); + /* transmit */ if (re_atomic_rlx(&vtx->run)) { re_atomic_rlx_set(&vtx->run, false); From 404ca8ca78743e9806779ca5eb627307d38879fa Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Fri, 16 Jun 2023 11:30:17 +0200 Subject: [PATCH 08/31] aup: correctly read/write atomic --- src/aureceiver.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/aureceiver.c b/src/aureceiver.c index b362bfb243..e1672df6fb 100644 --- a/src/aureceiver.c +++ b/src/aureceiver.c @@ -142,7 +142,7 @@ static int aup_push_aubuf(struct aurpipe *rp, const struct auframe *af) if (err) return err; - rp->ready = true; + re_atomic_rlx_set(&rp->ready, true); } err = aubuf_write_auframe(rp->aubuf, af); @@ -155,7 +155,8 @@ static int aup_push_aubuf(struct aurpipe *rp, const struct auframe *af) bpms = rp->srate * rp->ch * aufmt_sample_size(rp->fmt) / 1000; if (bpms) - rp->stats.latency = aubuf_cur_size(rp->aubuf) / bpms; + re_atomic_rlx_set(&rp->stats.latency, + aubuf_cur_size(rp->aubuf) / bpms); return 0; } @@ -346,7 +347,7 @@ uint64_t aup_latency(const struct aurpipe *rp) if (!rp) return 0; - return rp->stats.latency; + return re_atomic_rlx(&rp->stats.latency); } @@ -388,7 +389,7 @@ int aup_alloc(struct aurpipe **aupp, const struct config_audio *cfg, void aup_flush(struct aurpipe *rp) { - if (!rp || !rp->ready) + if (!rp || !re_atomic_rlx(&rp->ready)) return; mtx_lock(rp->mtx); @@ -502,7 +503,7 @@ const struct aucodec *aup_codec(const struct aurpipe *rp) void aup_read(struct aurpipe *rp, struct auframe *af) { - if (!rp || !rp->ready) + if (!rp || !re_atomic_rlx(&rp->ready)) return; aubuf_read_auframe(rp->aubuf, af); @@ -522,7 +523,7 @@ void aup_stop(struct aurpipe *rp) bool aup_started(const struct aurpipe *rp) { - if (!rp || !rp->ready) + if (!rp || !re_atomic_rlx(&rp->ready)) return false; return aubuf_started(rp->aubuf); @@ -535,7 +536,7 @@ int aup_debug(struct re_printf *pf, const struct aurpipe *rp) uint64_t bpms; int err; - if (!rp || !rp->ready) + if (!rp || !re_atomic_rlx(&rp->ready)) return 0; mb = mbuf_alloc(32); From 31fa25250346fbdc6e314b108cc080f9cb42bbb1 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Fri, 16 Jun 2023 12:07:46 +0200 Subject: [PATCH 09/31] aup: check atomic ready flag instead of aubuf pointer --- src/aureceiver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aureceiver.c b/src/aureceiver.c index e1672df6fb..e07d459996 100644 --- a/src/aureceiver.c +++ b/src/aureceiver.c @@ -137,7 +137,7 @@ static int aup_push_aubuf(struct aurpipe *rp, const struct auframe *af) int err; uint64_t bpms; - if (!rp->aubuf) { + if (!re_atomic_rlx(&rp->ready)) { err = aup_alloc_aubuf(rp, af); if (err) return err; From 60752cfe91a368fda41e14f27564065e858a063d Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Fri, 23 Jun 2023 10:56:06 +0200 Subject: [PATCH 10/31] aup: replace atomic by mtx avoids thread sanitizer warnings --- src/aureceiver.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/aureceiver.c b/src/aureceiver.c index e07d459996..140e3afaf6 100644 --- a/src/aureceiver.c +++ b/src/aureceiver.c @@ -34,7 +34,7 @@ struct aurpipe { struct audec_state *dec; /**< Audio decoder state (optional) */ const struct aucodec *ac; /**< Current audio decoder */ struct aubuf *aubuf; /**< Audio buffer before auplay */ - RE_ATOMIC bool ready; /**< Audio buffer is ready flag */ + mtx_t *aubuf_mtx; /**< Mutex for aubuf allocation */ uint32_t ssrc; /**< Incoming synchronization source */ struct list filtl; /**< Audio filters in decoding order */ void *sampv; /**< Sample buffer */ @@ -63,6 +63,7 @@ static void destructor(void *arg) mem_deref(rp->aubuf); mem_deref(rp->sampv); mem_deref(rp->mtx); + mem_deref(rp->aubuf_mtx); list_flush(&rp->filtl); } @@ -137,12 +138,12 @@ static int aup_push_aubuf(struct aurpipe *rp, const struct auframe *af) int err; uint64_t bpms; - if (!re_atomic_rlx(&rp->ready)) { + if (!rp->aubuf) { + mtx_lock(rp->aubuf_mtx); err = aup_alloc_aubuf(rp, af); + mtx_unlock(rp->aubuf_mtx); if (err) return err; - - re_atomic_rlx_set(&rp->ready, true); } err = aubuf_write_auframe(rp->aubuf, af); @@ -375,7 +376,8 @@ int aup_alloc(struct aurpipe **aupp, const struct config_audio *cfg, goto out; } - err = mutex_alloc(&rp->mtx); + err = mutex_alloc(&rp->mtx); + err |= mutex_alloc(&rp->aubuf_mtx); out: if (err) @@ -389,7 +391,7 @@ int aup_alloc(struct aurpipe **aupp, const struct config_audio *cfg, void aup_flush(struct aurpipe *rp) { - if (!rp || !re_atomic_rlx(&rp->ready)) + if (!rp) return; mtx_lock(rp->mtx); @@ -503,10 +505,11 @@ const struct aucodec *aup_codec(const struct aurpipe *rp) void aup_read(struct aurpipe *rp, struct auframe *af) { - if (!rp || !re_atomic_rlx(&rp->ready)) + if (!rp || mtx_trylock(rp->aubuf_mtx) != thrd_success) return; aubuf_read_auframe(rp->aubuf, af); + mtx_unlock(rp->aubuf_mtx); } @@ -523,10 +526,14 @@ void aup_stop(struct aurpipe *rp) bool aup_started(const struct aurpipe *rp) { - if (!rp || !re_atomic_rlx(&rp->ready)) + bool ret; + + if (!rp || mtx_trylock(rp->aubuf_mtx) != thrd_success) return false; - return aubuf_started(rp->aubuf); + ret = aubuf_started(rp->aubuf); + mtx_unlock(rp->aubuf_mtx); + return ret; } @@ -536,12 +543,14 @@ int aup_debug(struct re_printf *pf, const struct aurpipe *rp) uint64_t bpms; int err; - if (!rp || !re_atomic_rlx(&rp->ready)) + if (!rp || mtx_trylock(rp->aubuf_mtx) != thrd_success) return 0; mb = mbuf_alloc(32); - if (!mb) - return ENOMEM; + if (!mb) { + err = ENOMEM; + goto out; + } mtx_lock(rp->mtx); bpms = rp->srate * rp->ch * aufmt_sample_size(rp->fmt) / 1000; @@ -575,6 +584,7 @@ int aup_debug(struct re_printf *pf, const struct aurpipe *rp) err = re_hprintf(pf, "%b", mb->buf, mb->pos); out: mem_deref(mb); + mtx_unlock(rp->aubuf_mtx); return err; } From d1c0aadf3191018dc05ef7f85d493c038ffeafba Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Tue, 1 Aug 2023 13:28:00 +0200 Subject: [PATCH 11/31] aur: rename aurpipe to audio_recv --- src/audio.c | 10 ++++---- src/aureceiver.c | 59 ++++++++++++++++++++++++------------------------ src/core.h | 38 +++++++++++++++---------------- 3 files changed, 54 insertions(+), 53 deletions(-) diff --git a/src/audio.c b/src/audio.c index 6a9cb26c86..f8b0c998c6 100644 --- a/src/audio.c +++ b/src/audio.c @@ -127,12 +127,12 @@ struct aurx { int pt; /**< Payload type for incoming RTP */ enum aufmt play_fmt; /**< Sample format for audio playback*/ - struct aurpipe *aup; /**< Audio receive pipeline */ + struct audio_recv *aup; /**< Audio receive pipeline */ bool first_write; /**< First write to auplay */ }; -struct aurpipe; +struct audio_recv; /** Generic Audio stream */ @@ -536,14 +536,14 @@ static void check_plframe(struct auframe *af1, struct auframe *af2) { if ((af1->srate && af1->srate != af2->srate) || (af1->ch && af1->ch != af2->ch )) { - warning("aurpipe: srate/ch of frame %u/%u vs " + warning("audio_recv: srate/ch of frame %u/%u vs " "player %u/%u. Use module auresamp!\n", af1->srate, af1->ch, af2->srate, af2->ch); } if (af1->fmt != af2->fmt) { - warning("aurpipe: invalid sample formats (%s -> %s). " + warning("audio_recv: invalid sample formats (%s -> %s). " "%s\n", aufmt_name(af1->fmt), aufmt_name(af2->fmt), af1->fmt == AUFMT_S16LE ? @@ -1762,7 +1762,7 @@ int audio_debug(struct re_printf *pf, const struct audio *a) { const struct autx *tx; const struct aurx *rx; - const struct aurpipe *aup; + const struct audio_recv *aup; size_t sztx; int err; diff --git a/src/aureceiver.c b/src/aureceiver.c index 140e3afaf6..3ec67a123d 100644 --- a/src/aureceiver.c +++ b/src/aureceiver.c @@ -26,7 +26,7 @@ \endverbatim */ -struct aurpipe { +struct audio_recv { uint32_t srate; /**< Decoder sample rate */ uint32_t ch; /**< Decoder channel number */ enum aufmt fmt; /**< Decoder sample format */ @@ -57,7 +57,7 @@ struct aurpipe { static void destructor(void *arg) { - struct aurpipe *rp = arg; + struct audio_recv *rp = arg; mem_deref(rp->dec); mem_deref(rp->aubuf); @@ -68,7 +68,7 @@ static void destructor(void *arg) } -static int aup_process_decfilt(struct aurpipe *rp, struct auframe *af) +static int aup_process_decfilt(struct audio_recv *rp, struct auframe *af) { int err = 0; @@ -87,7 +87,7 @@ static int aup_process_decfilt(struct aurpipe *rp, struct auframe *af) } -static double aup_calc_seconds(const struct aurpipe *rp) +static double aup_calc_seconds(const struct audio_recv *rp) { uint64_t dur; double seconds; @@ -102,7 +102,7 @@ static double aup_calc_seconds(const struct aurpipe *rp) } -static int aup_alloc_aubuf(struct aurpipe *rp, const struct auframe *af) +static int aup_alloc_aubuf(struct audio_recv *rp, const struct auframe *af) { size_t min_sz; size_t max_sz; @@ -114,7 +114,7 @@ static int aup_alloc_aubuf(struct aurpipe *rp, const struct auframe *af) min_sz = sz * calc_nsamp(af->srate, af->ch, cfg->buffer.min); max_sz = sz * calc_nsamp(af->srate, af->ch, cfg->buffer.max); - debug("aurpipe: create audio buffer" + debug("audio_recv: create audio buffer" " [%u - %u ms]" " [%zu - %zu bytes]\n", (unsigned) cfg->buffer.min, (unsigned) cfg->buffer.max, @@ -122,7 +122,7 @@ static int aup_alloc_aubuf(struct aurpipe *rp, const struct auframe *af) err = aubuf_alloc(&rp->aubuf, min_sz, max_sz); if (err) { - warning("aurpipe: aubuf alloc error (%m)\n", + warning("audio_recv: aubuf alloc error (%m)\n", err); } @@ -133,7 +133,7 @@ static int aup_alloc_aubuf(struct aurpipe *rp, const struct auframe *af) } -static int aup_push_aubuf(struct aurpipe *rp, const struct auframe *af) +static int aup_push_aubuf(struct audio_recv *rp, const struct auframe *af) { int err; uint64_t bpms; @@ -163,8 +163,9 @@ static int aup_push_aubuf(struct aurpipe *rp, const struct auframe *af) } -static int aup_stream_decode(struct aurpipe *rp, const struct rtp_header *hdr, - struct mbuf *mb, unsigned lostc, bool drop) +static int aup_stream_decode(struct audio_recv *rp, + const struct rtp_header *hdr, + struct mbuf *mb, unsigned lostc, bool drop) { struct auframe af; size_t sampc = rp->sampvsz / aufmt_sample_size(rp->fmt); @@ -244,7 +245,7 @@ static const struct rtpext *rtpext_find(const struct rtpext *extv, size_t extc, /* Handle incoming stream data from the network */ -void aup_receive(struct aurpipe *rp, const struct rtp_header *hdr, +void aup_receive(struct audio_recv *rp, const struct rtp_header *hdr, struct rtpext *extv, size_t extc, struct mbuf *mb, unsigned lostc, bool *ignore) { @@ -321,7 +322,7 @@ void aup_receive(struct aurpipe *rp, const struct rtp_header *hdr, } -void aup_set_extmap(struct aurpipe *rp, uint8_t aulevel) +void aup_set_extmap(struct audio_recv *rp, uint8_t aulevel) { if (!rp) return; @@ -332,7 +333,7 @@ void aup_set_extmap(struct aurpipe *rp, uint8_t aulevel) } -void aup_set_telev_pt(struct aurpipe *rp, int pt) +void aup_set_telev_pt(struct audio_recv *rp, int pt) { if (!rp) return; @@ -343,7 +344,7 @@ void aup_set_telev_pt(struct aurpipe *rp, int pt) } -uint64_t aup_latency(const struct aurpipe *rp) +uint64_t aup_latency(const struct audio_recv *rp) { if (!rp) return 0; @@ -352,10 +353,10 @@ uint64_t aup_latency(const struct aurpipe *rp) } -int aup_alloc(struct aurpipe **aupp, const struct config_audio *cfg, +int aup_alloc(struct audio_recv **aupp, const struct config_audio *cfg, size_t sampc) { - struct aurpipe *rp; + struct audio_recv *rp; int err; if (!aupp) @@ -389,7 +390,7 @@ int aup_alloc(struct aurpipe **aupp, const struct config_audio *cfg, } -void aup_flush(struct aurpipe *rp) +void aup_flush(struct audio_recv *rp) { if (!rp) return; @@ -403,7 +404,7 @@ void aup_flush(struct aurpipe *rp) } -int aup_decoder_set(struct aurpipe *rp, +int aup_decoder_set(struct audio_recv *rp, const struct aucodec *ac, const char *params) { int err = 0; @@ -423,7 +424,7 @@ int aup_decoder_set(struct aurpipe *rp, if (ac->decupdh) { err = ac->decupdh(&rp->dec, ac, params); if (err) { - warning("aurpipe: alloc decoder: %m\n", err); + warning("audio_recv: alloc decoder: %m\n", err); goto out; } } @@ -434,7 +435,7 @@ int aup_decoder_set(struct aurpipe *rp, } -int aup_filt_append(struct aurpipe *rp, struct aufilt_dec_st *decst) +int aup_filt_append(struct audio_recv *rp, struct aufilt_dec_st *decst) { if (!rp || !decst) return EINVAL; @@ -447,7 +448,7 @@ int aup_filt_append(struct aurpipe *rp, struct aufilt_dec_st *decst) } -bool aup_filt_empty(const struct aurpipe *rp) +bool aup_filt_empty(const struct audio_recv *rp) { bool empty; if (!rp) @@ -461,7 +462,7 @@ bool aup_filt_empty(const struct aurpipe *rp) } -bool aup_level_set(const struct aurpipe *rp) +bool aup_level_set(const struct audio_recv *rp) { bool set; if (!rp) @@ -475,7 +476,7 @@ bool aup_level_set(const struct aurpipe *rp) } -double aup_level(const struct aurpipe *rp) +double aup_level(const struct audio_recv *rp) { double v; if (!rp) @@ -489,7 +490,7 @@ double aup_level(const struct aurpipe *rp) } -const struct aucodec *aup_codec(const struct aurpipe *rp) +const struct aucodec *aup_codec(const struct audio_recv *rp) { const struct aucodec *ac; @@ -503,7 +504,7 @@ const struct aucodec *aup_codec(const struct aurpipe *rp) } -void aup_read(struct aurpipe *rp, struct auframe *af) +void aup_read(struct audio_recv *rp, struct auframe *af) { if (!rp || mtx_trylock(rp->aubuf_mtx) != thrd_success) return; @@ -513,7 +514,7 @@ void aup_read(struct aurpipe *rp, struct auframe *af) } -void aup_stop(struct aurpipe *rp) +void aup_stop(struct audio_recv *rp) { if (!rp) return; @@ -524,7 +525,7 @@ void aup_stop(struct aurpipe *rp) } -bool aup_started(const struct aurpipe *rp) +bool aup_started(const struct audio_recv *rp) { bool ret; @@ -537,7 +538,7 @@ bool aup_started(const struct aurpipe *rp) } -int aup_debug(struct re_printf *pf, const struct aurpipe *rp) +int aup_debug(struct re_printf *pf, const struct audio_recv *rp) { struct mbuf *mb; uint64_t bpms; @@ -589,7 +590,7 @@ int aup_debug(struct re_printf *pf, const struct aurpipe *rp) } -int aup_print_pipeline(struct re_printf *pf, const struct aurpipe *rp) +int aup_print_pipeline(struct re_printf *pf, const struct audio_recv *rp) { struct mbuf *mb; struct le *le; diff --git a/src/core.h b/src/core.h index 437af324a3..bd72ce2c61 100644 --- a/src/core.h +++ b/src/core.h @@ -116,30 +116,30 @@ int aucodec_print(struct re_printf *pf, const struct aucodec *ac); * Audio Receiver Pipeline */ -struct aurpipe; +struct audio_recv; -int aup_alloc(struct aurpipe **aupp, const struct config_audio *cfg, +int aup_alloc(struct audio_recv **aupp, const struct config_audio *cfg, size_t sampc); -int aup_decoder_set(struct aurpipe *rp, +int aup_decoder_set(struct audio_recv *rp, const struct aucodec *ac, const char *params); -int aup_filt_append(struct aurpipe *rp, struct aufilt_dec_st *decst); -void aup_flush(struct aurpipe *rp); -void aup_set_extmap(struct aurpipe *rp, uint8_t aulevel); -void aup_set_telev_pt(struct aurpipe *rp, int pt); -void aup_receive(struct aurpipe *rp, const struct rtp_header *hdr, +int aup_filt_append(struct audio_recv *rp, struct aufilt_dec_st *decst); +void aup_flush(struct audio_recv *rp); +void aup_set_extmap(struct audio_recv *rp, uint8_t aulevel); +void aup_set_telev_pt(struct audio_recv *rp, int pt); +void aup_receive(struct audio_recv *rp, const struct rtp_header *hdr, struct rtpext *extv, size_t extc, struct mbuf *mb, unsigned lostc, bool *ignore); -void aup_read(struct aurpipe *rp, struct auframe *af); -void aup_stop(struct aurpipe *rp); - -const struct aucodec *aup_codec(const struct aurpipe *rp); -uint64_t aup_latency(const struct aurpipe *rp); -bool aup_started(const struct aurpipe *rp); -bool aup_filt_empty(const struct aurpipe *rp); -bool aup_level_set(const struct aurpipe *rp); -double aup_level(const struct aurpipe *rp); -int aup_debug(struct re_printf *pf, const struct aurpipe *rp); -int aup_print_pipeline(struct re_printf *pf, const struct aurpipe *rp); +void aup_read(struct audio_recv *rp, struct auframe *af); +void aup_stop(struct audio_recv *rp); + +const struct aucodec *aup_codec(const struct audio_recv *rp); +uint64_t aup_latency(const struct audio_recv *rp); +bool aup_started(const struct audio_recv *rp); +bool aup_filt_empty(const struct audio_recv *rp); +bool aup_level_set(const struct audio_recv *rp); +double aup_level(const struct audio_recv *rp); +int aup_debug(struct re_printf *pf, const struct audio_recv *rp); +int aup_print_pipeline(struct re_printf *pf, const struct audio_recv *rp); /* From 7aaeaada1551d1df9dfa1234532f6b5d6bbc6242 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Wed, 2 Aug 2023 13:55:16 +0200 Subject: [PATCH 12/31] aur: rename audio_recv pointer from rp to ar --- src/aureceiver.c | 326 +++++++++++++++++++++++------------------------ src/core.h | 34 ++--- 2 files changed, 180 insertions(+), 180 deletions(-) diff --git a/src/aureceiver.c b/src/aureceiver.c index 3ec67a123d..1a4f6d4498 100644 --- a/src/aureceiver.c +++ b/src/aureceiver.c @@ -57,23 +57,23 @@ struct audio_recv { static void destructor(void *arg) { - struct audio_recv *rp = arg; - - mem_deref(rp->dec); - mem_deref(rp->aubuf); - mem_deref(rp->sampv); - mem_deref(rp->mtx); - mem_deref(rp->aubuf_mtx); - list_flush(&rp->filtl); + struct audio_recv *ar = arg; + + mem_deref(ar->dec); + mem_deref(ar->aubuf); + mem_deref(ar->sampv); + mem_deref(ar->mtx); + mem_deref(ar->aubuf_mtx); + list_flush(&ar->filtl); } -static int aup_process_decfilt(struct audio_recv *rp, struct auframe *af) +static int aup_process_decfilt(struct audio_recv *ar, struct auframe *af) { int err = 0; /* Process exactly one audio-frame in reverse list order */ - for (struct le *le = rp->filtl.tail; le; le = le->prev) { + for (struct le *le = ar->filtl.tail; le; le = le->prev) { struct aufilt_dec_st *st = le->data; if (st->af && st->af->dech) @@ -87,27 +87,27 @@ static int aup_process_decfilt(struct audio_recv *rp, struct auframe *af) } -static double aup_calc_seconds(const struct audio_recv *rp) +static double aup_calc_seconds(const struct audio_recv *ar) { uint64_t dur; double seconds; - if (!rp->ac) + if (!ar->ac) return .0; - dur = timestamp_duration(&rp->ts_recv); - seconds = timestamp_calc_seconds(dur, rp->ac->crate); + dur = timestamp_duration(&ar->ts_recv); + seconds = timestamp_calc_seconds(dur, ar->ac->crate); return seconds; } -static int aup_alloc_aubuf(struct audio_recv *rp, const struct auframe *af) +static int aup_alloc_aubuf(struct audio_recv *ar, const struct auframe *af) { size_t min_sz; size_t max_sz; size_t sz; - const struct config_audio *cfg = rp->cfg; + const struct config_audio *cfg = ar->cfg; int err; sz = aufmt_sample_size(cfg->play_fmt); @@ -120,71 +120,71 @@ static int aup_alloc_aubuf(struct audio_recv *rp, const struct auframe *af) (unsigned) cfg->buffer.min, (unsigned) cfg->buffer.max, min_sz, max_sz); - err = aubuf_alloc(&rp->aubuf, min_sz, max_sz); + err = aubuf_alloc(&ar->aubuf, min_sz, max_sz); if (err) { warning("audio_recv: aubuf alloc error (%m)\n", err); } - aubuf_set_mode(rp->aubuf, cfg->adaptive ? + aubuf_set_mode(ar->aubuf, cfg->adaptive ? AUBUF_ADAPTIVE : AUBUF_FIXED); - aubuf_set_silence(rp->aubuf, cfg->silence); + aubuf_set_silence(ar->aubuf, cfg->silence); return err; } -static int aup_push_aubuf(struct audio_recv *rp, const struct auframe *af) +static int aup_push_aubuf(struct audio_recv *ar, const struct auframe *af) { int err; uint64_t bpms; - if (!rp->aubuf) { - mtx_lock(rp->aubuf_mtx); - err = aup_alloc_aubuf(rp, af); - mtx_unlock(rp->aubuf_mtx); + if (!ar->aubuf) { + mtx_lock(ar->aubuf_mtx); + err = aup_alloc_aubuf(ar, af); + mtx_unlock(ar->aubuf_mtx); if (err) return err; } - err = aubuf_write_auframe(rp->aubuf, af); + err = aubuf_write_auframe(ar->aubuf, af); if (err) return err; - rp->srate = af->srate; - rp->ch = af->ch; - rp->fmt = af->fmt; + ar->srate = af->srate; + ar->ch = af->ch; + ar->fmt = af->fmt; - bpms = rp->srate * rp->ch * aufmt_sample_size(rp->fmt) / 1000; + bpms = ar->srate * ar->ch * aufmt_sample_size(ar->fmt) / 1000; if (bpms) - re_atomic_rlx_set(&rp->stats.latency, - aubuf_cur_size(rp->aubuf) / bpms); + re_atomic_rlx_set(&ar->stats.latency, + aubuf_cur_size(ar->aubuf) / bpms); return 0; } -static int aup_stream_decode(struct audio_recv *rp, +static int aup_stream_decode(struct audio_recv *ar, const struct rtp_header *hdr, struct mbuf *mb, unsigned lostc, bool drop) { struct auframe af; - size_t sampc = rp->sampvsz / aufmt_sample_size(rp->fmt); + size_t sampc = ar->sampvsz / aufmt_sample_size(ar->fmt); bool marker = hdr->m; int err = 0; - const struct aucodec *ac = rp->ac; - bool flush = rp->ssrc != hdr->ssrc; + const struct aucodec *ac = ar->ac; + bool flush = ar->ssrc != hdr->ssrc; /* No decoder set */ if (!ac) return 0; - rp->ssrc = hdr->ssrc; + ar->ssrc = hdr->ssrc; /* TODO: PLC */ if (lostc && ac->plch) { - err = ac->plch(rp->dec, - rp->fmt, rp->sampv, &sampc, + err = ac->plch(ar->dec, + ar->fmt, ar->sampv, &sampc, mbuf_buf(mb), mbuf_get_left(mb)); if (err) { warning("audio: %s codec decode %u bytes: %m\n", @@ -194,8 +194,8 @@ static int aup_stream_decode(struct audio_recv *rp, } else if (mbuf_get_left(mb)) { - err = ac->dech(rp->dec, - rp->fmt, rp->sampv, &sampc, + err = ac->dech(ar->dec, + ar->fmt, ar->sampv, &sampc, marker, mbuf_buf(mb), mbuf_get_left(mb)); if (err) { warning("audio: %s codec decode %u bytes: %m\n", @@ -208,22 +208,22 @@ static int aup_stream_decode(struct audio_recv *rp, sampc = 0; } - auframe_init(&af, rp->fmt, rp->sampv, sampc, ac->srate, ac->ch); + auframe_init(&af, ar->fmt, ar->sampv, sampc, ac->srate, ac->ch); af.timestamp = ((uint64_t) hdr->ts) * AUDIO_TIMEBASE / ac->crate; if (drop) { - aubuf_drop_auframe(rp->aubuf, &af); + aubuf_drop_auframe(ar->aubuf, &af); goto out; } if (flush) - aubuf_flush(rp->aubuf); + aubuf_flush(ar->aubuf); - err = aup_process_decfilt(rp, &af); + err = aup_process_decfilt(ar, &af); if (err) goto out; - err = aup_push_aubuf(rp, &af); + err = aup_push_aubuf(ar, &af); out: return err; } @@ -245,7 +245,7 @@ static const struct rtpext *rtpext_find(const struct rtpext *extv, size_t extc, /* Handle incoming stream data from the network */ -void aup_receive(struct audio_recv *rp, const struct rtp_header *hdr, +void aup_receive(struct audio_recv *ar, const struct rtp_header *hdr, struct rtpext *extv, size_t extc, struct mbuf *mb, unsigned lostc, bool *ignore) { @@ -257,9 +257,9 @@ void aup_receive(struct audio_recv *rp, const struct rtp_header *hdr, if (!mb) goto out; - mtx_lock(rp->mtx); - if (hdr->pt == rp->telev_pt) { - mtx_unlock(rp->mtx); + mtx_lock(ar->mtx); + if (hdr->pt == ar->telev_pt) { + mtx_unlock(ar->mtx); *ignore = true; return; } @@ -267,25 +267,25 @@ void aup_receive(struct audio_recv *rp, const struct rtp_header *hdr, *ignore = false; /* RFC 5285 -- A General Mechanism for RTP Header Extensions */ - const struct rtpext *ext = rtpext_find(extv, extc, rp->extmap_aulevel); + const struct rtpext *ext = rtpext_find(extv, extc, ar->extmap_aulevel); if (ext) { - rp->level_last = -(double)(ext->data[0] & 0x7f); - rp->level_set = true; + ar->level_last = -(double)(ext->data[0] & 0x7f); + ar->level_set = true; } /* Save timestamp for incoming RTP packets */ - if (!rp->ts_recv.is_set) - timestamp_set(&rp->ts_recv, hdr->ts); + if (!ar->ts_recv.is_set) + timestamp_set(&ar->ts_recv, hdr->ts); - wrap = timestamp_wrap(hdr->ts, rp->ts_recv.last); + wrap = timestamp_wrap(hdr->ts, ar->ts_recv.last); switch (wrap) { case -1: warning("audio: rtp timestamp wraps backwards" " (delta = %d) -- discard\n", - (int32_t)(rp->ts_recv.last - hdr->ts)); + (int32_t)(ar->ts_recv.last - hdr->ts)); discard = true; break; @@ -293,17 +293,17 @@ void aup_receive(struct audio_recv *rp, const struct rtp_header *hdr, break; case 1: - ++rp->ts_recv.num_wraps; + ++ar->ts_recv.num_wraps; break; default: break; } - rp->ts_recv.last = hdr->ts; + ar->ts_recv.last = hdr->ts; if (discard) { - ++rp->stats.n_discard; + ++ar->stats.n_discard; goto unlock; } @@ -313,116 +313,116 @@ void aup_receive(struct audio_recv *rp, const struct rtp_header *hdr, * aubuf should replace PLC frames with late arriving real frames. * It should use timestamp to decide if a frame should be replaced. */ /* if (lostc)*/ -/* (void)aup_stream_decode(rp, hdr, mb, lostc, drop);*/ +/* (void)aup_stream_decode(ar, hdr, mb, lostc, drop);*/ - (void)aup_stream_decode(rp, hdr, mb, 0, drop); + (void)aup_stream_decode(ar, hdr, mb, 0, drop); unlock: - mtx_unlock(rp->mtx); + mtx_unlock(ar->mtx); } -void aup_set_extmap(struct audio_recv *rp, uint8_t aulevel) +void aup_set_extmap(struct audio_recv *ar, uint8_t aulevel) { - if (!rp) + if (!ar) return; - mtx_lock(rp->mtx); - rp->extmap_aulevel = aulevel; - mtx_unlock(rp->mtx); + mtx_lock(ar->mtx); + ar->extmap_aulevel = aulevel; + mtx_unlock(ar->mtx); } -void aup_set_telev_pt(struct audio_recv *rp, int pt) +void aup_set_telev_pt(struct audio_recv *ar, int pt) { - if (!rp) + if (!ar) return; - mtx_lock(rp->mtx); - rp->telev_pt = pt; - mtx_unlock(rp->mtx); + mtx_lock(ar->mtx); + ar->telev_pt = pt; + mtx_unlock(ar->mtx); } -uint64_t aup_latency(const struct audio_recv *rp) +uint64_t aup_latency(const struct audio_recv *ar) { - if (!rp) + if (!ar) return 0; - return re_atomic_rlx(&rp->stats.latency); + return re_atomic_rlx(&ar->stats.latency); } int aup_alloc(struct audio_recv **aupp, const struct config_audio *cfg, size_t sampc) { - struct audio_recv *rp; + struct audio_recv *ar; int err; if (!aupp) return EINVAL; - rp = mem_zalloc(sizeof(*rp), destructor); - if (!rp) + ar = mem_zalloc(sizeof(*ar), destructor); + if (!ar) return ENOMEM; - rp->cfg = cfg; - rp->srate = cfg->srate_play; - rp->ch = cfg->channels_play; - rp->fmt = cfg->play_fmt; - rp->sampvsz = sampc * aufmt_sample_size(rp->fmt); - rp->sampv = mem_zalloc(rp->sampvsz, NULL); - if (!rp->sampv) { + ar->cfg = cfg; + ar->srate = cfg->srate_play; + ar->ch = cfg->channels_play; + ar->fmt = cfg->play_fmt; + ar->sampvsz = sampc * aufmt_sample_size(ar->fmt); + ar->sampv = mem_zalloc(ar->sampvsz, NULL); + if (!ar->sampv) { err = ENOMEM; goto out; } - err = mutex_alloc(&rp->mtx); - err |= mutex_alloc(&rp->aubuf_mtx); + err = mutex_alloc(&ar->mtx); + err |= mutex_alloc(&ar->aubuf_mtx); out: if (err) - rp = mem_deref(rp); + ar = mem_deref(ar); else - *aupp = rp; + *aupp = ar; return err; } -void aup_flush(struct audio_recv *rp) +void aup_flush(struct audio_recv *ar) { - if (!rp) + if (!ar) return; - mtx_lock(rp->mtx); - aubuf_flush(rp->aubuf); + mtx_lock(ar->mtx); + aubuf_flush(ar->aubuf); /* Reset audio filter chain */ - list_flush(&rp->filtl); - mtx_unlock(rp->mtx); + list_flush(&ar->filtl); + mtx_unlock(ar->mtx); } -int aup_decoder_set(struct audio_recv *rp, +int aup_decoder_set(struct audio_recv *ar, const struct aucodec *ac, const char *params) { int err = 0; - if (!rp || !ac) + if (!ar || !ac) return EINVAL; info("audio: Set audio decoder: %s %uHz %dch\n", ac->name, ac->srate, ac->ch); - mtx_lock(rp->mtx); - if (ac != rp->ac) { - rp->ac = ac; - rp->dec = mem_deref(rp->dec); + mtx_lock(ar->mtx); + if (ac != ar->ac) { + ar->ac = ac; + ar->dec = mem_deref(ar->dec); } if (ac->decupdh) { - err = ac->decupdh(&rp->dec, ac, params); + err = ac->decupdh(&ar->dec, ac, params); if (err) { warning("audio_recv: alloc decoder: %m\n", err); goto out; @@ -430,121 +430,121 @@ int aup_decoder_set(struct audio_recv *rp, } out: - mtx_unlock(rp->mtx); + mtx_unlock(ar->mtx); return err; } -int aup_filt_append(struct audio_recv *rp, struct aufilt_dec_st *decst) +int aup_filt_append(struct audio_recv *ar, struct aufilt_dec_st *decst) { - if (!rp || !decst) + if (!ar || !decst) return EINVAL; - mtx_lock(rp->mtx); - list_append(&rp->filtl, &decst->le, decst); - mtx_unlock(rp->mtx); + mtx_lock(ar->mtx); + list_append(&ar->filtl, &decst->le, decst); + mtx_unlock(ar->mtx); return 0; } -bool aup_filt_empty(const struct audio_recv *rp) +bool aup_filt_empty(const struct audio_recv *ar) { bool empty; - if (!rp) + if (!ar) return false; - mtx_lock(rp->mtx); - empty = list_isempty(&rp->filtl); - mtx_unlock(rp->mtx); + mtx_lock(ar->mtx); + empty = list_isempty(&ar->filtl); + mtx_unlock(ar->mtx); return empty; } -bool aup_level_set(const struct audio_recv *rp) +bool aup_level_set(const struct audio_recv *ar) { bool set; - if (!rp) + if (!ar) return false; - mtx_lock(rp->mtx); - set = rp->level_set; - mtx_unlock(rp->mtx); + mtx_lock(ar->mtx); + set = ar->level_set; + mtx_unlock(ar->mtx); return set; } -double aup_level(const struct audio_recv *rp) +double aup_level(const struct audio_recv *ar) { double v; - if (!rp) + if (!ar) return 0.0; - mtx_lock(rp->mtx); - v = rp->level_last; - mtx_unlock(rp->mtx); + mtx_lock(ar->mtx); + v = ar->level_last; + mtx_unlock(ar->mtx); return v; } -const struct aucodec *aup_codec(const struct audio_recv *rp) +const struct aucodec *aup_codec(const struct audio_recv *ar) { const struct aucodec *ac; - if (!rp) + if (!ar) return NULL; - mtx_lock(rp->mtx); - ac = rp->ac; - mtx_unlock(rp->mtx); + mtx_lock(ar->mtx); + ac = ar->ac; + mtx_unlock(ar->mtx); return ac; } -void aup_read(struct audio_recv *rp, struct auframe *af) +void aup_read(struct audio_recv *ar, struct auframe *af) { - if (!rp || mtx_trylock(rp->aubuf_mtx) != thrd_success) + if (!ar || mtx_trylock(ar->aubuf_mtx) != thrd_success) return; - aubuf_read_auframe(rp->aubuf, af); - mtx_unlock(rp->aubuf_mtx); + aubuf_read_auframe(ar->aubuf, af); + mtx_unlock(ar->aubuf_mtx); } -void aup_stop(struct audio_recv *rp) +void aup_stop(struct audio_recv *ar) { - if (!rp) + if (!ar) return; - mtx_lock(rp->mtx); - rp->ac = NULL; - mtx_unlock(rp->mtx); + mtx_lock(ar->mtx); + ar->ac = NULL; + mtx_unlock(ar->mtx); } -bool aup_started(const struct audio_recv *rp) +bool aup_started(const struct audio_recv *ar) { bool ret; - if (!rp || mtx_trylock(rp->aubuf_mtx) != thrd_success) + if (!ar || mtx_trylock(ar->aubuf_mtx) != thrd_success) return false; - ret = aubuf_started(rp->aubuf); - mtx_unlock(rp->aubuf_mtx); + ret = aubuf_started(ar->aubuf); + mtx_unlock(ar->aubuf_mtx); return ret; } -int aup_debug(struct re_printf *pf, const struct audio_recv *rp) +int aup_debug(struct re_printf *pf, const struct audio_recv *ar) { struct mbuf *mb; uint64_t bpms; int err; - if (!rp || mtx_trylock(rp->aubuf_mtx) != thrd_success) + if (!ar || mtx_trylock(ar->aubuf_mtx) != thrd_success) return 0; mb = mbuf_alloc(32); @@ -553,31 +553,31 @@ int aup_debug(struct re_printf *pf, const struct audio_recv *rp) goto out; } - mtx_lock(rp->mtx); - bpms = rp->srate * rp->ch * aufmt_sample_size(rp->fmt) / 1000; + mtx_lock(ar->mtx); + bpms = ar->srate * ar->ch * aufmt_sample_size(ar->fmt) / 1000; err = mbuf_printf(mb, " rx: decode: %H %s\n", - aucodec_print, rp->ac, - aufmt_name(rp->fmt)); + aucodec_print, ar->ac, + aufmt_name(ar->fmt)); err |= mbuf_printf(mb, " aubuf: %H" " (cur %.2fms, max %.2fms)\n", - aubuf_debug, rp->aubuf, - aubuf_cur_size(rp->aubuf) / bpms, - aubuf_maxsz(rp->aubuf) / bpms); + aubuf_debug, ar->aubuf, + aubuf_cur_size(ar->aubuf) / bpms, + aubuf_maxsz(ar->aubuf) / bpms); err |= mbuf_printf(mb, " n_discard:%llu\n", - rp->stats.n_discard); - if (rp->level_set) { + ar->stats.n_discard); + if (ar->level_set) { err |= mbuf_printf(mb, " level %.3f dBov\n", - rp->level_last); + ar->level_last); } - if (rp->ts_recv.is_set) { + if (ar->ts_recv.is_set) { err |= mbuf_printf(mb, " time = %.3f sec\n", - aup_calc_seconds(rp)); + aup_calc_seconds(ar)); } else { err |= mbuf_printf(mb, " time = (not started)\n"); } - mtx_unlock(rp->mtx); + mtx_unlock(ar->mtx); if (err) goto out; @@ -585,18 +585,18 @@ int aup_debug(struct re_printf *pf, const struct audio_recv *rp) err = re_hprintf(pf, "%b", mb->buf, mb->pos); out: mem_deref(mb); - mtx_unlock(rp->aubuf_mtx); + mtx_unlock(ar->aubuf_mtx); return err; } -int aup_print_pipeline(struct re_printf *pf, const struct audio_recv *rp) +int aup_print_pipeline(struct re_printf *pf, const struct audio_recv *ar) { struct mbuf *mb; struct le *le; int err; - if (!rp) + if (!ar) return 0; mb = mbuf_alloc(32); @@ -604,8 +604,8 @@ int aup_print_pipeline(struct re_printf *pf, const struct audio_recv *rp) return ENOMEM; err = mbuf_printf(mb, " <--- aubuf"); - mtx_lock(rp->mtx); - for (le = list_head(&rp->filtl); le; le = le->next) { + mtx_lock(ar->mtx); + for (le = list_head(&ar->filtl); le; le = le->next) { struct aufilt_dec_st *st = le->data; if (st->af->dech) @@ -613,8 +613,8 @@ int aup_print_pipeline(struct re_printf *pf, const struct audio_recv *rp) } err |= mbuf_printf(mb, " <--- %s\n", - rp->ac ? rp->ac->name : "(decoder)"); - mtx_unlock(rp->mtx); + ar->ac ? ar->ac->name : "(decoder)"); + mtx_unlock(ar->mtx); if (err) goto out; diff --git a/src/core.h b/src/core.h index bd72ce2c61..5a3397b4b2 100644 --- a/src/core.h +++ b/src/core.h @@ -120,26 +120,26 @@ struct audio_recv; int aup_alloc(struct audio_recv **aupp, const struct config_audio *cfg, size_t sampc); -int aup_decoder_set(struct audio_recv *rp, +int aup_decoder_set(struct audio_recv *ar, const struct aucodec *ac, const char *params); -int aup_filt_append(struct audio_recv *rp, struct aufilt_dec_st *decst); -void aup_flush(struct audio_recv *rp); -void aup_set_extmap(struct audio_recv *rp, uint8_t aulevel); -void aup_set_telev_pt(struct audio_recv *rp, int pt); -void aup_receive(struct audio_recv *rp, const struct rtp_header *hdr, +int aup_filt_append(struct audio_recv *ar, struct aufilt_dec_st *decst); +void aup_flush(struct audio_recv *ar); +void aup_set_extmap(struct audio_recv *ar, uint8_t aulevel); +void aup_set_telev_pt(struct audio_recv *ar, int pt); +void aup_receive(struct audio_recv *ar, const struct rtp_header *hdr, struct rtpext *extv, size_t extc, struct mbuf *mb, unsigned lostc, bool *ignore); -void aup_read(struct audio_recv *rp, struct auframe *af); -void aup_stop(struct audio_recv *rp); - -const struct aucodec *aup_codec(const struct audio_recv *rp); -uint64_t aup_latency(const struct audio_recv *rp); -bool aup_started(const struct audio_recv *rp); -bool aup_filt_empty(const struct audio_recv *rp); -bool aup_level_set(const struct audio_recv *rp); -double aup_level(const struct audio_recv *rp); -int aup_debug(struct re_printf *pf, const struct audio_recv *rp); -int aup_print_pipeline(struct re_printf *pf, const struct audio_recv *rp); +void aup_read(struct audio_recv *ar, struct auframe *af); +void aup_stop(struct audio_recv *ar); + +const struct aucodec *aup_codec(const struct audio_recv *ar); +uint64_t aup_latency(const struct audio_recv *ar); +bool aup_started(const struct audio_recv *ar); +bool aup_filt_empty(const struct audio_recv *ar); +bool aup_level_set(const struct audio_recv *ar); +double aup_level(const struct audio_recv *ar); +int aup_debug(struct re_printf *pf, const struct audio_recv *ar); +int aup_print_pipeline(struct re_printf *pf, const struct audio_recv *ar); /* From 930f7cc58447d1f7eec2aef5ac90fbc9ef221656 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Wed, 2 Aug 2023 13:57:31 +0200 Subject: [PATCH 13/31] aur: rename functin prefix aup_ to aur_ --- src/audio.c | 50 +++++++++++++++++++++--------------------- src/aureceiver.c | 56 ++++++++++++++++++++++++------------------------ src/core.h | 36 +++++++++++++++---------------- 3 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/audio.c b/src/audio.c index f8b0c998c6..234fa5fe3f 100644 --- a/src/audio.c +++ b/src/audio.c @@ -171,7 +171,7 @@ uint64_t audio_jb_current_value(const struct audio *au) if (!au) return 0; - return aup_latency(au->rx.aup); + return aur_latency(au->rx.aup); } @@ -214,7 +214,7 @@ static void stop_rx(struct aurx *rx) /* audio player must be stopped first */ rx->auplay = mem_deref(rx->auplay); - aup_stop(rx->aup); + aur_stop(rx->aup); } @@ -573,7 +573,7 @@ static void auplay_write_handler(struct auframe *af, void *arg) if (!rx->first_write) afr = *af; - aup_read(rx->aup, af); + aur_read(rx->aup, af); if (!rx->first_write) { (void)check_plframe(&afr, af); @@ -710,7 +710,7 @@ static void stream_recv_handler(const struct rtp_header *hdr, if (!a->rx.aup) return; - aup_receive(a->rx.aup, hdr, extv, extc, mb, lostc, ignore); + aur_receive(a->rx.aup, hdr, extv, extc, mb, lostc, ignore); } @@ -734,7 +734,7 @@ static int add_telev_codec(struct audio *a) return err; if (add) - aup_set_telev_pt(a->rx.aup, pt); + aur_set_telev_pt(a->rx.aup, pt); return 0; } @@ -812,7 +812,7 @@ int audio_alloc(struct audio **ap, struct list *streaml, if (err) goto out; - err = aup_alloc(&a->rx.aup, &a->cfg, AUDIO_SAMPSZ); + err = aur_alloc(&a->rx.aup, &a->cfg, AUDIO_SAMPSZ); if (err) goto out; @@ -845,7 +845,7 @@ int audio_alloc(struct audio **ap, struct list *streaml, if (cfg->audio.level && offerer) { a->extmap_aulevel = stream_generate_extmap_id(a->strm); - aup_set_extmap(a->rx.aup, a->extmap_aulevel); + aur_set_extmap(a->rx.aup, a->extmap_aulevel); err = sdp_media_set_lattr(stream_sdpmedia(a->strm), true, "extmap", @@ -1059,14 +1059,14 @@ static int aufilt_setup(struct audio *a, struct list *aufiltl) int err = 0; /* wait until we have both Encoder and Decoder */ - if (!tx->ac || !aup_codec(rx->aup)) + if (!tx->ac || !aur_codec(rx->aup)) return 0; - update_dec = aup_filt_empty(rx->aup); + update_dec = aur_filt_empty(rx->aup); update_enc = list_isempty(&tx->filtl); aufilt_param_set(&encprm, tx->ac, tx->enc_fmt); - aufilt_param_set(&plprm, aup_codec(rx->aup), a->cfg.play_fmt); + aufilt_param_set(&plprm, aur_codec(rx->aup), a->cfg.play_fmt); if (a->cfg.srate_play && a->cfg.srate_play != plprm.srate) { plprm.srate = a->cfg.srate_play; } @@ -1102,7 +1102,7 @@ static int aufilt_setup(struct audio *a, struct list *aufiltl) } else { decst->af = af; - aup_filt_append(rx->aup, decst); + aur_filt_append(rx->aup, decst); } } @@ -1120,7 +1120,7 @@ static int aufilt_setup(struct audio *a, struct list *aufiltl) static int start_player(struct aurx *rx, struct audio *a, struct list *auplayl) { - const struct aucodec *ac = aup_codec(rx->aup); + const struct aucodec *ac = aur_codec(rx->aup); uint32_t srate_dsp; uint32_t channels_dsp; int err = 0; @@ -1286,7 +1286,7 @@ static void audio_flush_filters(struct audio *a) struct aurx *rx = &a->rx; struct autx *tx = &a->tx; - aup_flush(rx->aup); + aur_flush(rx->aup); mtx_lock(a->tx.mtx); list_flush(&tx->filtl); @@ -1333,13 +1333,13 @@ int audio_start(struct audio *a) return err; } - if (a->tx.ac && aup_codec(a->rx.aup)) { + if (a->tx.ac && aur_codec(a->rx.aup)) { if (!a->started) { info("%H\n%H%H", autx_print_pipeline, &a->tx, aurx_print_pipeline, &a->rx, - aup_print_pipeline, a->rx.aup); + aur_print_pipeline, a->rx.aup); } a->started = true; @@ -1512,12 +1512,12 @@ int audio_decoder_set(struct audio *a, const struct aucodec *ac, rx = &a->rx; rx->pt = pt_rx; - if (ac != aup_codec(rx->aup)) { + if (ac != aur_codec(rx->aup)) { struct sdp_media *m; bool reset; m = stream_sdpmedia(audio_strm(a)); - reset = !aucodec_equal(ac, aup_codec(rx->aup)); + reset = !aucodec_equal(ac, aur_codec(rx->aup)); reset |= !(sdp_media_dir(m) & SDP_RECVONLY); if (reset) { rx->auplay = mem_deref(rx->auplay); @@ -1526,7 +1526,7 @@ int audio_decoder_set(struct audio *a, const struct aucodec *ac, } } - err = aup_decoder_set(rx->aup, ac, params); + err = aur_decoder_set(rx->aup, ac, params); if (err) return err; @@ -1643,7 +1643,7 @@ static bool extmap_handler(const char *name, const char *value, void *arg) } au->extmap_aulevel = extmap.id; - aup_set_extmap(au->rx.aup, au->extmap_aulevel); + aur_set_extmap(au->rx.aup, au->extmap_aulevel); err = sdp_media_set_lattr(stream_sdpmedia(au->strm), true, "extmap", @@ -1740,11 +1740,11 @@ int audio_level_get(const struct audio *au, double *levelp) if (!au->level_enabled) return ENOTSUP; - if (!aup_level_set(au->rx.aup)) + if (!aur_level_set(au->rx.aup)) return ENOENT; if (levelp) - *levelp = aup_level(au->rx.aup); + *levelp = aur_level(au->rx.aup); return 0; } @@ -1799,7 +1799,7 @@ int audio_debug(struct re_printf *pf, const struct audio *a) err |= re_hprintf(pf, " time = %.3f sec\n", autx_calc_seconds(tx)); - err |= aup_debug(pf, aup); + err |= aur_debug(pf, aup); err |= re_hprintf(pf, " player: %s,%s %s\n", rx->ap ? rx->ap->name : "none", rx->device, @@ -1810,7 +1810,7 @@ int audio_debug(struct re_printf *pf, const struct audio *a) " %H%H", autx_print_pipeline, tx, aurx_print_pipeline, rx, - aup_print_pipeline, aup); + aur_print_pipeline, aup); err |= stream_debug(pf, a->strm); @@ -1985,7 +1985,7 @@ bool audio_rxaubuf_started(const struct audio *au) if (!au || !au->rx.aup) return false; - return aup_started(au->rx.aup); + return aur_started(au->rx.aup); } @@ -2049,7 +2049,7 @@ const struct aucodec *audio_codec(const struct audio *au, bool tx) if (!au) return NULL; - return tx ? au->tx.ac : aup_codec(au->rx.aup); + return tx ? au->tx.ac : aur_codec(au->rx.aup); } diff --git a/src/aureceiver.c b/src/aureceiver.c index 1a4f6d4498..73c19fafba 100644 --- a/src/aureceiver.c +++ b/src/aureceiver.c @@ -68,7 +68,7 @@ static void destructor(void *arg) } -static int aup_process_decfilt(struct audio_recv *ar, struct auframe *af) +static int aur_process_decfilt(struct audio_recv *ar, struct auframe *af) { int err = 0; @@ -87,7 +87,7 @@ static int aup_process_decfilt(struct audio_recv *ar, struct auframe *af) } -static double aup_calc_seconds(const struct audio_recv *ar) +static double aur_calc_seconds(const struct audio_recv *ar) { uint64_t dur; double seconds; @@ -102,7 +102,7 @@ static double aup_calc_seconds(const struct audio_recv *ar) } -static int aup_alloc_aubuf(struct audio_recv *ar, const struct auframe *af) +static int aur_alloc_aubuf(struct audio_recv *ar, const struct auframe *af) { size_t min_sz; size_t max_sz; @@ -133,14 +133,14 @@ static int aup_alloc_aubuf(struct audio_recv *ar, const struct auframe *af) } -static int aup_push_aubuf(struct audio_recv *ar, const struct auframe *af) +static int aur_push_aubuf(struct audio_recv *ar, const struct auframe *af) { int err; uint64_t bpms; if (!ar->aubuf) { mtx_lock(ar->aubuf_mtx); - err = aup_alloc_aubuf(ar, af); + err = aur_alloc_aubuf(ar, af); mtx_unlock(ar->aubuf_mtx); if (err) return err; @@ -163,7 +163,7 @@ static int aup_push_aubuf(struct audio_recv *ar, const struct auframe *af) } -static int aup_stream_decode(struct audio_recv *ar, +static int aur_stream_decode(struct audio_recv *ar, const struct rtp_header *hdr, struct mbuf *mb, unsigned lostc, bool drop) { @@ -219,11 +219,11 @@ static int aup_stream_decode(struct audio_recv *ar, if (flush) aubuf_flush(ar->aubuf); - err = aup_process_decfilt(ar, &af); + err = aur_process_decfilt(ar, &af); if (err) goto out; - err = aup_push_aubuf(ar, &af); + err = aur_push_aubuf(ar, &af); out: return err; } @@ -245,7 +245,7 @@ static const struct rtpext *rtpext_find(const struct rtpext *extv, size_t extc, /* Handle incoming stream data from the network */ -void aup_receive(struct audio_recv *ar, const struct rtp_header *hdr, +void aur_receive(struct audio_recv *ar, const struct rtp_header *hdr, struct rtpext *extv, size_t extc, struct mbuf *mb, unsigned lostc, bool *ignore) { @@ -313,16 +313,16 @@ void aup_receive(struct audio_recv *ar, const struct rtp_header *hdr, * aubuf should replace PLC frames with late arriving real frames. * It should use timestamp to decide if a frame should be replaced. */ /* if (lostc)*/ -/* (void)aup_stream_decode(ar, hdr, mb, lostc, drop);*/ +/* (void)aur_stream_decode(ar, hdr, mb, lostc, drop);*/ - (void)aup_stream_decode(ar, hdr, mb, 0, drop); + (void)aur_stream_decode(ar, hdr, mb, 0, drop); unlock: mtx_unlock(ar->mtx); } -void aup_set_extmap(struct audio_recv *ar, uint8_t aulevel) +void aur_set_extmap(struct audio_recv *ar, uint8_t aulevel) { if (!ar) return; @@ -333,7 +333,7 @@ void aup_set_extmap(struct audio_recv *ar, uint8_t aulevel) } -void aup_set_telev_pt(struct audio_recv *ar, int pt) +void aur_set_telev_pt(struct audio_recv *ar, int pt) { if (!ar) return; @@ -344,7 +344,7 @@ void aup_set_telev_pt(struct audio_recv *ar, int pt) } -uint64_t aup_latency(const struct audio_recv *ar) +uint64_t aur_latency(const struct audio_recv *ar) { if (!ar) return 0; @@ -353,7 +353,7 @@ uint64_t aup_latency(const struct audio_recv *ar) } -int aup_alloc(struct audio_recv **aupp, const struct config_audio *cfg, +int aur_alloc(struct audio_recv **aupp, const struct config_audio *cfg, size_t sampc) { struct audio_recv *ar; @@ -390,7 +390,7 @@ int aup_alloc(struct audio_recv **aupp, const struct config_audio *cfg, } -void aup_flush(struct audio_recv *ar) +void aur_flush(struct audio_recv *ar) { if (!ar) return; @@ -404,7 +404,7 @@ void aup_flush(struct audio_recv *ar) } -int aup_decoder_set(struct audio_recv *ar, +int aur_decoder_set(struct audio_recv *ar, const struct aucodec *ac, const char *params) { int err = 0; @@ -435,7 +435,7 @@ int aup_decoder_set(struct audio_recv *ar, } -int aup_filt_append(struct audio_recv *ar, struct aufilt_dec_st *decst) +int aur_filt_append(struct audio_recv *ar, struct aufilt_dec_st *decst) { if (!ar || !decst) return EINVAL; @@ -448,7 +448,7 @@ int aup_filt_append(struct audio_recv *ar, struct aufilt_dec_st *decst) } -bool aup_filt_empty(const struct audio_recv *ar) +bool aur_filt_empty(const struct audio_recv *ar) { bool empty; if (!ar) @@ -462,7 +462,7 @@ bool aup_filt_empty(const struct audio_recv *ar) } -bool aup_level_set(const struct audio_recv *ar) +bool aur_level_set(const struct audio_recv *ar) { bool set; if (!ar) @@ -476,7 +476,7 @@ bool aup_level_set(const struct audio_recv *ar) } -double aup_level(const struct audio_recv *ar) +double aur_level(const struct audio_recv *ar) { double v; if (!ar) @@ -490,7 +490,7 @@ double aup_level(const struct audio_recv *ar) } -const struct aucodec *aup_codec(const struct audio_recv *ar) +const struct aucodec *aur_codec(const struct audio_recv *ar) { const struct aucodec *ac; @@ -504,7 +504,7 @@ const struct aucodec *aup_codec(const struct audio_recv *ar) } -void aup_read(struct audio_recv *ar, struct auframe *af) +void aur_read(struct audio_recv *ar, struct auframe *af) { if (!ar || mtx_trylock(ar->aubuf_mtx) != thrd_success) return; @@ -514,7 +514,7 @@ void aup_read(struct audio_recv *ar, struct auframe *af) } -void aup_stop(struct audio_recv *ar) +void aur_stop(struct audio_recv *ar) { if (!ar) return; @@ -525,7 +525,7 @@ void aup_stop(struct audio_recv *ar) } -bool aup_started(const struct audio_recv *ar) +bool aur_started(const struct audio_recv *ar) { bool ret; @@ -538,7 +538,7 @@ bool aup_started(const struct audio_recv *ar) } -int aup_debug(struct re_printf *pf, const struct audio_recv *ar) +int aur_debug(struct re_printf *pf, const struct audio_recv *ar) { struct mbuf *mb; uint64_t bpms; @@ -572,7 +572,7 @@ int aup_debug(struct re_printf *pf, const struct audio_recv *ar) } if (ar->ts_recv.is_set) { err |= mbuf_printf(mb, " time = %.3f sec\n", - aup_calc_seconds(ar)); + aur_calc_seconds(ar)); } else { err |= mbuf_printf(mb, " time = (not started)\n"); @@ -590,7 +590,7 @@ int aup_debug(struct re_printf *pf, const struct audio_recv *ar) } -int aup_print_pipeline(struct re_printf *pf, const struct audio_recv *ar) +int aur_print_pipeline(struct re_printf *pf, const struct audio_recv *ar) { struct mbuf *mb; struct le *le; diff --git a/src/core.h b/src/core.h index 5a3397b4b2..a6d8ad0557 100644 --- a/src/core.h +++ b/src/core.h @@ -118,28 +118,28 @@ int aucodec_print(struct re_printf *pf, const struct aucodec *ac); struct audio_recv; -int aup_alloc(struct audio_recv **aupp, const struct config_audio *cfg, +int aur_alloc(struct audio_recv **aupp, const struct config_audio *cfg, size_t sampc); -int aup_decoder_set(struct audio_recv *ar, +int aur_decoder_set(struct audio_recv *ar, const struct aucodec *ac, const char *params); -int aup_filt_append(struct audio_recv *ar, struct aufilt_dec_st *decst); -void aup_flush(struct audio_recv *ar); -void aup_set_extmap(struct audio_recv *ar, uint8_t aulevel); -void aup_set_telev_pt(struct audio_recv *ar, int pt); -void aup_receive(struct audio_recv *ar, const struct rtp_header *hdr, +int aur_filt_append(struct audio_recv *ar, struct aufilt_dec_st *decst); +void aur_flush(struct audio_recv *ar); +void aur_set_extmap(struct audio_recv *ar, uint8_t aulevel); +void aur_set_telev_pt(struct audio_recv *ar, int pt); +void aur_receive(struct audio_recv *ar, const struct rtp_header *hdr, struct rtpext *extv, size_t extc, struct mbuf *mb, unsigned lostc, bool *ignore); -void aup_read(struct audio_recv *ar, struct auframe *af); -void aup_stop(struct audio_recv *ar); - -const struct aucodec *aup_codec(const struct audio_recv *ar); -uint64_t aup_latency(const struct audio_recv *ar); -bool aup_started(const struct audio_recv *ar); -bool aup_filt_empty(const struct audio_recv *ar); -bool aup_level_set(const struct audio_recv *ar); -double aup_level(const struct audio_recv *ar); -int aup_debug(struct re_printf *pf, const struct audio_recv *ar); -int aup_print_pipeline(struct re_printf *pf, const struct audio_recv *ar); +void aur_read(struct audio_recv *ar, struct auframe *af); +void aur_stop(struct audio_recv *ar); + +const struct aucodec *aur_codec(const struct audio_recv *ar); +uint64_t aur_latency(const struct audio_recv *ar); +bool aur_started(const struct audio_recv *ar); +bool aur_filt_empty(const struct audio_recv *ar); +bool aur_level_set(const struct audio_recv *ar); +double aur_level(const struct audio_recv *ar); +int aur_debug(struct re_printf *pf, const struct audio_recv *ar); +int aur_print_pipeline(struct re_printf *pf, const struct audio_recv *ar); /* From 19f6508fbb2acddaff74990731ff28adaf128d42 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Thu, 3 Aug 2023 10:08:48 +0200 Subject: [PATCH 14/31] audio,aur: measure SW decoding jitter --- src/audio.c | 2 +- src/aureceiver.c | 35 ++++++++++++++++++++++++++++++++--- src/core.h | 2 +- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/audio.c b/src/audio.c index 234fa5fe3f..db4ffb6079 100644 --- a/src/audio.c +++ b/src/audio.c @@ -812,7 +812,7 @@ int audio_alloc(struct audio **ap, struct list *streaml, if (err) goto out; - err = aur_alloc(&a->rx.aup, &a->cfg, AUDIO_SAMPSZ); + err = aur_alloc(&a->rx.aup, &a->cfg, AUDIO_SAMPSZ, ptime); if (err) goto out; diff --git a/src/aureceiver.c b/src/aureceiver.c index 73c19fafba..107f904c2e 100644 --- a/src/aureceiver.c +++ b/src/aureceiver.c @@ -4,6 +4,7 @@ * Copyright (C) 2023 Alfred E. Heggestad, Christian Spielberger */ #include +#include #include #include #include @@ -26,6 +27,12 @@ \endverbatim */ + +enum { + JITTER_EMA_COEFF = 128, /**< Jitter EMA coefficient */ +}; + + struct audio_recv { uint32_t srate; /**< Decoder sample rate */ uint32_t ch; /**< Decoder channel number */ @@ -39,6 +46,8 @@ struct audio_recv { struct list filtl; /**< Audio filters in decoding order */ void *sampv; /**< Sample buffer */ size_t sampvsz; /**< Sample buffer size */ + uint64_t t; /**< Last auframe push time */ + uint32_t ptime; /**< Packet time for receiving [us] */ double level_last; /**< Last audio level value [dBov] */ bool level_set; /**< True if level_last is set */ @@ -47,8 +56,10 @@ struct audio_recv { uint32_t telev_pt; /**< Payload type for telephone-events */ struct { - uint64_t n_discard; + uint64_t n_discard; /**< Nbr of discarded packets */ RE_ATOMIC uint64_t latency; /**< Latency in [ms] */ + int32_t jitter; /**< Auframe push jitter [us] */ + int32_t dmax; /**< Max deviation [us] */ } stats; mtx_t *mtx; @@ -146,6 +157,19 @@ static int aur_push_aubuf(struct audio_recv *ar, const struct auframe *af) return err; } +#ifndef RELEASE + int32_t d, da; + uint64_t t; + t = tmr_jiffies_usec(); + if (ar->t) { + d = (int32_t) (int64_t) ((t - ar->t) - ar->ptime); + da = abs(d); + ar->stats.dmax = max(ar->stats.dmax, da); + ar->stats.jitter += (da - ar->stats.jitter) / JITTER_EMA_COEFF; + } + + ar->t = t; +#endif err = aubuf_write_auframe(ar->aubuf, af); if (err) return err; @@ -354,7 +378,7 @@ uint64_t aur_latency(const struct audio_recv *ar) int aur_alloc(struct audio_recv **aupp, const struct config_audio *cfg, - size_t sampc) + size_t sampc, uint32_t ptime) { struct audio_recv *ar; int err; @@ -372,6 +396,7 @@ int aur_alloc(struct audio_recv **aupp, const struct config_audio *cfg, ar->fmt = cfg->play_fmt; ar->sampvsz = sampc * aufmt_sample_size(ar->fmt); ar->sampv = mem_zalloc(ar->sampvsz, NULL); + ar->ptime = ptime * 1000; if (!ar->sampv) { err = ENOMEM; goto out; @@ -564,7 +589,11 @@ int aur_debug(struct re_printf *pf, const struct audio_recv *ar) aubuf_debug, ar->aubuf, aubuf_cur_size(ar->aubuf) / bpms, aubuf_maxsz(ar->aubuf) / bpms); - err |= mbuf_printf(mb, " n_discard:%llu\n", +#ifndef RELEASE + err |= mbuf_printf(mb, " SW jitter: %u\n", ar->stats.jitter); + err |= mbuf_printf(mb, " deviation: %d\n", ar->stats.dmax); +#endif + err |= mbuf_printf(mb, " n_discard: %llu\n", ar->stats.n_discard); if (ar->level_set) { err |= mbuf_printf(mb, " level %.3f dBov\n", diff --git a/src/core.h b/src/core.h index a6d8ad0557..657973f20b 100644 --- a/src/core.h +++ b/src/core.h @@ -119,7 +119,7 @@ int aucodec_print(struct re_printf *pf, const struct aucodec *ac); struct audio_recv; int aur_alloc(struct audio_recv **aupp, const struct config_audio *cfg, - size_t sampc); + size_t sampc, uint32_t ptime); int aur_decoder_set(struct audio_recv *ar, const struct aucodec *ac, const char *params); int aur_filt_append(struct audio_recv *ar, struct aufilt_dec_st *decst); From 03439cefcb17ab0dac484f0c965f9b1e0914d70a Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Thu, 3 Aug 2023 10:39:57 +0200 Subject: [PATCH 15/31] aur: print times in ms float numbers --- src/aureceiver.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/aureceiver.c b/src/aureceiver.c index 107f904c2e..18d5b7134f 100644 --- a/src/aureceiver.c +++ b/src/aureceiver.c @@ -566,7 +566,7 @@ bool aur_started(const struct audio_recv *ar) int aur_debug(struct re_printf *pf, const struct audio_recv *ar) { struct mbuf *mb; - uint64_t bpms; + double bpms; int err; if (!ar || mtx_trylock(ar->aubuf_mtx) != thrd_success) @@ -579,7 +579,8 @@ int aur_debug(struct re_printf *pf, const struct audio_recv *ar) } mtx_lock(ar->mtx); - bpms = ar->srate * ar->ch * aufmt_sample_size(ar->fmt) / 1000; + bpms = (double) (uint64_t) (ar->srate * ar->ch * + aufmt_sample_size(ar->fmt) / 1000); err = mbuf_printf(mb, " rx: decode: %H %s\n", aucodec_print, ar->ac, @@ -590,8 +591,10 @@ int aur_debug(struct re_printf *pf, const struct audio_recv *ar) aubuf_cur_size(ar->aubuf) / bpms, aubuf_maxsz(ar->aubuf) / bpms); #ifndef RELEASE - err |= mbuf_printf(mb, " SW jitter: %u\n", ar->stats.jitter); - err |= mbuf_printf(mb, " deviation: %d\n", ar->stats.dmax); + err |= mbuf_printf(mb, " SW jitter: %.2fms\n", + (double) ar->stats.jitter / 1000); + err |= mbuf_printf(mb, " deviation: %.2fms\n", + (double) ar->stats.dmax / 1000); #endif err |= mbuf_printf(mb, " n_discard: %llu\n", ar->stats.n_discard); From 0f89e1ae1851d86f362dbcbaa38016621144e25a Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Thu, 3 Aug 2023 15:41:57 +0200 Subject: [PATCH 16/31] audio: rename pointer aup to aur --- src/audio.c | 62 ++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/audio.c b/src/audio.c index db4ffb6079..8a481eca23 100644 --- a/src/audio.c +++ b/src/audio.c @@ -127,7 +127,7 @@ struct aurx { int pt; /**< Payload type for incoming RTP */ enum aufmt play_fmt; /**< Sample format for audio playback*/ - struct audio_recv *aup; /**< Audio receive pipeline */ + struct audio_recv *aur; /**< Audio receive pipeline */ bool first_write; /**< First write to auplay */ }; @@ -171,7 +171,7 @@ uint64_t audio_jb_current_value(const struct audio *au) if (!au) return 0; - return aur_latency(au->rx.aup); + return aur_latency(au->rx.aur); } @@ -214,7 +214,7 @@ static void stop_rx(struct aurx *rx) /* audio player must be stopped first */ rx->auplay = mem_deref(rx->auplay); - aur_stop(rx->aup); + aur_stop(rx->aur); } @@ -241,7 +241,7 @@ static void audio_destructor(void *arg) mem_deref(a->strm); mem_deref(a->telev); - mem_deref(a->rx.aup); + mem_deref(a->rx.aur); mem_deref(a->tx.mtx); } @@ -573,7 +573,7 @@ static void auplay_write_handler(struct auframe *af, void *arg) if (!rx->first_write) afr = *af; - aur_read(rx->aup, af); + aur_read(rx->aur, af); if (!rx->first_write) { (void)check_plframe(&afr, af); @@ -707,10 +707,10 @@ static void stream_recv_handler(const struct rtp_header *hdr, MAGIC_CHECK(a); - if (!a->rx.aup) + if (!a->rx.aur) return; - aur_receive(a->rx.aup, hdr, extv, extc, mb, lostc, ignore); + aur_receive(a->rx.aur, hdr, extv, extc, mb, lostc, ignore); } @@ -734,7 +734,7 @@ static int add_telev_codec(struct audio *a) return err; if (add) - aur_set_telev_pt(a->rx.aup, pt); + aur_set_telev_pt(a->rx.aur, pt); return 0; } @@ -812,7 +812,7 @@ int audio_alloc(struct audio **ap, struct list *streaml, if (err) goto out; - err = aur_alloc(&a->rx.aup, &a->cfg, AUDIO_SAMPSZ, ptime); + err = aur_alloc(&a->rx.aur, &a->cfg, AUDIO_SAMPSZ, ptime); if (err) goto out; @@ -845,7 +845,7 @@ int audio_alloc(struct audio **ap, struct list *streaml, if (cfg->audio.level && offerer) { a->extmap_aulevel = stream_generate_extmap_id(a->strm); - aur_set_extmap(a->rx.aup, a->extmap_aulevel); + aur_set_extmap(a->rx.aur, a->extmap_aulevel); err = sdp_media_set_lattr(stream_sdpmedia(a->strm), true, "extmap", @@ -1059,14 +1059,14 @@ static int aufilt_setup(struct audio *a, struct list *aufiltl) int err = 0; /* wait until we have both Encoder and Decoder */ - if (!tx->ac || !aur_codec(rx->aup)) + if (!tx->ac || !aur_codec(rx->aur)) return 0; - update_dec = aur_filt_empty(rx->aup); + update_dec = aur_filt_empty(rx->aur); update_enc = list_isempty(&tx->filtl); aufilt_param_set(&encprm, tx->ac, tx->enc_fmt); - aufilt_param_set(&plprm, aur_codec(rx->aup), a->cfg.play_fmt); + aufilt_param_set(&plprm, aur_codec(rx->aur), a->cfg.play_fmt); if (a->cfg.srate_play && a->cfg.srate_play != plprm.srate) { plprm.srate = a->cfg.srate_play; } @@ -1102,7 +1102,7 @@ static int aufilt_setup(struct audio *a, struct list *aufiltl) } else { decst->af = af; - aur_filt_append(rx->aup, decst); + aur_filt_append(rx->aur, decst); } } @@ -1120,7 +1120,7 @@ static int aufilt_setup(struct audio *a, struct list *aufiltl) static int start_player(struct aurx *rx, struct audio *a, struct list *auplayl) { - const struct aucodec *ac = aur_codec(rx->aup); + const struct aucodec *ac = aur_codec(rx->aur); uint32_t srate_dsp; uint32_t channels_dsp; int err = 0; @@ -1286,7 +1286,7 @@ static void audio_flush_filters(struct audio *a) struct aurx *rx = &a->rx; struct autx *tx = &a->tx; - aur_flush(rx->aup); + aur_flush(rx->aur); mtx_lock(a->tx.mtx); list_flush(&tx->filtl); @@ -1333,13 +1333,13 @@ int audio_start(struct audio *a) return err; } - if (a->tx.ac && aur_codec(a->rx.aup)) { + if (a->tx.ac && aur_codec(a->rx.aur)) { if (!a->started) { info("%H\n%H%H", autx_print_pipeline, &a->tx, aurx_print_pipeline, &a->rx, - aur_print_pipeline, a->rx.aup); + aur_print_pipeline, a->rx.aur); } a->started = true; @@ -1512,12 +1512,12 @@ int audio_decoder_set(struct audio *a, const struct aucodec *ac, rx = &a->rx; rx->pt = pt_rx; - if (ac != aur_codec(rx->aup)) { + if (ac != aur_codec(rx->aur)) { struct sdp_media *m; bool reset; m = stream_sdpmedia(audio_strm(a)); - reset = !aucodec_equal(ac, aur_codec(rx->aup)); + reset = !aucodec_equal(ac, aur_codec(rx->aur)); reset |= !(sdp_media_dir(m) & SDP_RECVONLY); if (reset) { rx->auplay = mem_deref(rx->auplay); @@ -1526,7 +1526,7 @@ int audio_decoder_set(struct audio *a, const struct aucodec *ac, } } - err = aur_decoder_set(rx->aup, ac, params); + err = aur_decoder_set(rx->aur, ac, params); if (err) return err; @@ -1643,7 +1643,7 @@ static bool extmap_handler(const char *name, const char *value, void *arg) } au->extmap_aulevel = extmap.id; - aur_set_extmap(au->rx.aup, au->extmap_aulevel); + aur_set_extmap(au->rx.aur, au->extmap_aulevel); err = sdp_media_set_lattr(stream_sdpmedia(au->strm), true, "extmap", @@ -1740,11 +1740,11 @@ int audio_level_get(const struct audio *au, double *levelp) if (!au->level_enabled) return ENOTSUP; - if (!aur_level_set(au->rx.aup)) + if (!aur_level_set(au->rx.aur)) return ENOENT; if (levelp) - *levelp = aur_level(au->rx.aup); + *levelp = aur_level(au->rx.aur); return 0; } @@ -1762,7 +1762,7 @@ int audio_debug(struct re_printf *pf, const struct audio *a) { const struct autx *tx; const struct aurx *rx; - const struct audio_recv *aup; + const struct audio_recv *aur; size_t sztx; int err; @@ -1771,7 +1771,7 @@ int audio_debug(struct re_printf *pf, const struct audio *a) tx = &a->tx; rx = &a->rx; - aup = a->rx.aup; + aur = a->rx.aur; sztx = aufmt_sample_size(tx->src_fmt); @@ -1799,7 +1799,7 @@ int audio_debug(struct re_printf *pf, const struct audio *a) err |= re_hprintf(pf, " time = %.3f sec\n", autx_calc_seconds(tx)); - err |= aur_debug(pf, aup); + err |= aur_debug(pf, aur); err |= re_hprintf(pf, " player: %s,%s %s\n", rx->ap ? rx->ap->name : "none", rx->device, @@ -1810,7 +1810,7 @@ int audio_debug(struct re_printf *pf, const struct audio *a) " %H%H", autx_print_pipeline, tx, aurx_print_pipeline, rx, - aur_print_pipeline, aup); + aur_print_pipeline, aur); err |= stream_debug(pf, a->strm); @@ -1982,10 +1982,10 @@ int audio_set_bitrate(struct audio *au, uint32_t bitrate) */ bool audio_rxaubuf_started(const struct audio *au) { - if (!au || !au->rx.aup) + if (!au || !au->rx.aur) return false; - return aur_started(au->rx.aup); + return aur_started(au->rx.aur); } @@ -2049,7 +2049,7 @@ const struct aucodec *audio_codec(const struct audio *au, bool tx) if (!au) return NULL; - return tx ? au->tx.ac : aur_codec(au->rx.aup); + return tx ? au->tx.ac : aur_codec(au->rx.aur); } From 445d27e84380931948a621eb6b249bb0b6877872 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Mon, 4 Sep 2023 16:32:45 +0200 Subject: [PATCH 17/31] rtprecv: correct error handling --- src/rtprecv.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/rtprecv.c b/src/rtprecv.c index f293f7d51d..82cdac3669 100644 --- a/src/rtprecv.c +++ b/src/rtprecv.c @@ -460,6 +460,8 @@ int rtprecv_alloc(struct rtp_receiver **rxp, rx->pt = -1; err = str_dup(&rx->name, name); err |= mutex_alloc(&rx->mtx); + if (err) + goto out; /* Audio Jitter buffer */ if (stream_type(strm) == MEDIA_AUDIO && @@ -476,17 +478,19 @@ int rtprecv_alloc(struct rtp_receiver **rxp, err = jbuf_alloc(&rx->jbuf, cfg->video.jbuf_del.min, cfg->video.jbuf_del.max); - err |= jbuf_set_type(rx->jbuf, cfg->video.jbtype); + if (err) + goto out; + + err = jbuf_set_type(rx->jbuf, cfg->video.jbtype); + if (err) + goto out; } rx->metric = metric_alloc(); if (!rx->metric) - err |= ENOMEM; + err = ENOMEM; else - err |= metric_init(rx->metric); - - if (err) - goto out; + err = metric_init(rx->metric); out: if (err) From 981a5a70c652d56b9e17319613c96d3fe2151a37 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Wed, 25 Oct 2023 08:19:57 +0200 Subject: [PATCH 18/31] stream,rtprecv: activate RX thread via config --- docs/examples/config | 1 + include/baresip.h | 7 ++ src/config.c | 16 ++- src/core.h | 2 + src/rtprecv.c | 246 ++++++++++++++++++++++++++++++++++++++++++- src/stream.c | 20 ++++ 6 files changed, 287 insertions(+), 5 deletions(-) diff --git a/docs/examples/config b/docs/examples/config index cdd5f827b5..d93950eb59 100644 --- a/docs/examples/config +++ b/docs/examples/config @@ -72,6 +72,7 @@ video_jitter_buffer_delay 5-10 # (min. frames)-(max. packets) rtp_stats no #rtp_timeout 60 #avt_bundle no +#rtp_rxmode main # main,thread # Network #dns_server 1.1.1.1:53 diff --git a/include/baresip.h b/include/baresip.h index 66296d0108..7c0cd34f0e 100644 --- a/include/baresip.h +++ b/include/baresip.h @@ -326,6 +326,12 @@ enum audio_mode { AUDIO_MODE_THREAD, /**< Use dedicated thread */ }; +/** RTP receive mode */ +enum rtp_receive_mode { + RECEIVE_MODE_MAIN = 0, /**< RTP RX is processed in main thread */ + RECEIVE_MODE_THREAD, /**< RTP RX is processed in separate thread */ +}; + /** SIP User-Agent */ struct config_sip { char uuid[64]; /**< Universally Unique Identifier */ @@ -404,6 +410,7 @@ struct config_avt { bool rtp_stats; /**< Enable RTP statistics */ uint32_t rtp_timeout; /**< RTP Timeout in seconds (0=off) */ bool bundle; /**< Media Multiplexing (BUNDLE) */ + enum rtp_receive_mode rxmode; /**< RTP RX processing mode */ }; /** Network Configuration */ diff --git a/src/config.c b/src/config.c index 1a6202d111..5a6eb00f32 100644 --- a/src/config.c +++ b/src/config.c @@ -98,7 +98,8 @@ static struct config core_config = { }, false, 0, - false + false, + RECEIVE_MODE_MAIN, }, /* Network */ @@ -313,6 +314,7 @@ static const char *net_af_str(int af) int config_parse_conf(struct config *cfg, const struct conf *conf) { struct vidsz size = {0, 0}; + struct pl rxmode; struct pl txmode; struct pl jbtype; struct pl tr; @@ -470,6 +472,14 @@ int config_parse_conf(struct config *cfg, const struct conf *conf) (void)conf_get_u32(conf, "rtp_timeout", &cfg->avt.rtp_timeout); (void)conf_get_bool(conf, "avt_bundle", &cfg->avt.bundle); + if (0 == conf_get(conf, "rtp_rxmode", &rxmode)) { + + if (0 == pl_strcasecmp(&rxmode, "thread")) { + cfg->avt.rxmode = RECEIVE_MODE_THREAD; + warning("rtp_rxmode thread is currently " + "experimental\n"); + } + } if (err) { warning("config: configure parse error (%m)\n", err); @@ -571,6 +581,7 @@ int config_print(struct re_printf *pf, const struct config *cfg) "rtp_stats\t\t%s\n" "rtp_timeout\t\t%u # in seconds\n" "avt_bundle\t\t%s\n" + "rtp_rxmode\t\t\t%s\n" "\n" "# Network\n" "net_interface\t\t%s\n" @@ -625,6 +636,8 @@ int config_print(struct re_printf *pf, const struct config *cfg) cfg->avt.rtp_stats ? "yes" : "no", cfg->avt.rtp_timeout, cfg->avt.bundle ? "yes" : "no", + cfg->avt.rxmode == RECEIVE_MODE_THREAD ? "thread" : + "main", cfg->net.ifname, net_af_str(cfg->net.af) @@ -835,6 +848,7 @@ static int core_config_template(struct re_printf *pf, const struct config *cfg) "rtp_stats\t\tno\n" "#rtp_timeout\t\t60\n" "#avt_bundle\t\tno\n" + "#rtp_rxmode\t\tmain\n" "\n# Network\n" "#dns_server\t\t1.1.1.1:53\n" "#dns_server\t\t1.0.0.1:53\n" diff --git a/src/core.h b/src/core.h index 657973f20b..b7fe9a4136 100644 --- a/src/core.h +++ b/src/core.h @@ -511,5 +511,7 @@ void rtprecv_set_enable(struct rtp_receiver *rx, bool enable); int rtprecv_get_ssrc(struct rtp_receiver *rx, uint32_t *ssrc); void rtprecv_enable_mux(struct rtp_receiver *rx, bool enable); int rtprecv_debug(struct re_printf *pf, const struct rtp_receiver *rx); +int rtprecv_start_thread(struct rtp_receiver *rx); void rtprecv_mnat_connected_handler(const struct sa *raddr1, const struct sa *raddr2, void *arg); +bool rtprecv_running(const struct rtp_receiver *rx); diff --git a/src/rtprecv.c b/src/rtprecv.c index 82cdac3669..b0c2589385 100644 --- a/src/rtprecv.c +++ b/src/rtprecv.c @@ -30,6 +30,7 @@ struct rtp_receiver { uint32_t pseq; /**< Sequence number for incoming RTP */ bool pseq_set; /**< True if sequence number is set */ bool rtp_estab; /**< True if RTP stream established */ + RE_ATOMIC bool run; /**< True if RX thread is running */ mtx_t *mtx; /**< Mutex protects above fields */ /* Unprotected data */ @@ -40,10 +41,155 @@ struct rtp_receiver { stream_rtpestab_h *rtpestabh; /**< RTP established handler */ void *arg; /**< Stream argument */ void *sessarg; /**< Session argument */ + thrd_t thr; /**< RX thread */ + struct tmr tmr; /**< Timer for stopping RX thread */ int pt; /**< Previous payload type */ }; +enum work_type { + WORK_RTCP, + WORK_RTPESTAB, + WORK_PTCHANGED, + WORK_MNATCONNH, +}; + + +struct work { + enum work_type type; + struct rtp_receiver *rx; + union { + struct rtcp_msg *rtcp; + struct { + uint8_t pt; + struct mbuf *mb; + } pt; + struct { + struct sa raddr1; + struct sa raddr2; + } mnat; + } u; +}; + + +static void async_work_main(int err, void *arg); +static void work_destructor(void *arg); + + +/* + * functions that run in RX thread (if "rxmode thread" is configured) + */ + + +static void pass_rtcp_work(struct rtp_receiver *rx, struct rtcp_msg *msg) +{ + struct work *w; + + if (!re_atomic_rlx(&rx->run)) { + stream_process_rtcp(rx->strm, msg); + return; + } + + w = mem_zalloc(sizeof(*w), work_destructor); + if (!w) + return; + + w->type = WORK_RTCP; + w->rx = rx; + w->u.rtcp = mem_ref(msg); + re_thread_async_main_id((intptr_t)rx, NULL, async_work_main, w); +} + + +static int pass_pt_work(struct rtp_receiver *rx, uint8_t pt, struct mbuf *mb) +{ + struct work *w; + + if (!re_atomic_rlx(&rx->run)) + return rx->pth(pt, mb, rx->arg); + + w = mem_zalloc(sizeof(*w), work_destructor); + w->type = WORK_PTCHANGED; + w->rx = rx; + w->u.pt.pt = pt; + w->u.pt.mb = mbuf_dup(mb); + + return re_thread_async_main_id((intptr_t)rx, NULL, async_work_main, w); +} + + +static void pass_rtpestab_work(struct rtp_receiver *rx) +{ + struct work *w; + + if (!re_atomic_rlx(&rx->run)) { + rx->rtpestabh(rx->strm, rx->sessarg); + return; + } + + w = mem_zalloc(sizeof(*w), work_destructor); + w->type = WORK_RTPESTAB; + w->rx = rx; + + re_thread_async_main_id((intptr_t)rx, NULL, async_work_main, w); +} + + +static void pass_mnat_work(struct rtp_receiver *rx, const struct sa *raddr1, + const struct sa *raddr2) +{ + struct work *w; + + if (!re_atomic_rlx(&rx->run)) { + stream_mnat_connected(rx->strm, raddr1, raddr2); + return; + } + + w = mem_zalloc(sizeof(*w), work_destructor); + w->type = WORK_MNATCONNH; + w->rx = rx; + sa_cpy(&w->u.mnat.raddr1, raddr1); + sa_cpy(&w->u.mnat.raddr2, raddr2); + + re_thread_async_main_id((intptr_t)rx, NULL, async_work_main, w); +} + + +static void rtprecv_check_stop(void *arg) +{ + struct rtp_receiver *rx = arg; + + if (re_atomic_rlx(&rx->run)) + tmr_start(&rx->tmr, 10, rtprecv_check_stop, rx); + else + re_cancel(); +} + + +static int rtprecv_thread(void *arg) +{ + struct rtp_receiver *rx = arg; + int err; + + re_thread_init(); + tmr_start(&rx->tmr, 10, rtprecv_check_stop, rx); + + err = udp_thread_attach(rtp_sock(rx->rtp)); + if (err) + return err; + + err = udp_thread_attach(rtcp_sock(rx->rtp)); + if (err) + return err; + + err = re_main(NULL); + + tmr_cancel(&rx->tmr); + re_thread_close(); + return err; +} + + static int lostcalc(struct rtp_receiver *rx, uint16_t seq) { const uint16_t delta = seq - rx->pseq; @@ -198,7 +344,7 @@ void rtprecv_decode(const struct sa *src, const struct rtp_header *hdr, debug("stream: incoming rtp for '%s' established, " "receiving from %J\n", rx->name, src); rx->rtp_estab = true; - rx->rtpestabh(rx->strm, rx->sessarg); + pass_rtpestab_work(rx); } } @@ -227,7 +373,7 @@ void rtprecv_decode(const struct sa *src, const struct rtp_header *hdr, if (hdr->pt != rx->pt) { rx->pt = hdr->pt; - err = rx->pth(hdr->pt, mb, rx->arg); + err = pass_pt_work(rx, hdr->pt, mb); if (err && err != ENODATA) return; } @@ -274,7 +420,7 @@ void rtprecv_handle_rtcp(const struct sa *src, struct rtcp_msg *msg, rx->ts_last = tmr_jiffies(); mtx_unlock(rx->mtx); - stream_process_rtcp(rx->strm, msg); + pass_rtcp_work(rx, msg); } @@ -285,10 +431,14 @@ void rtprecv_mnat_connected_handler(const struct sa *raddr1, MAGIC_CHECK(rx); - stream_mnat_connected(rx->strm, raddr1, raddr2); + pass_mnat_work(rx, raddr1, raddr2); } +/* + * functions that run in main thread + */ + void rtprecv_set_socket(struct rtp_receiver *rx, struct rtp_sock *rtp) { mtx_lock(rx->mtx); @@ -427,6 +577,13 @@ static void destructor(void *arg) { struct rtp_receiver *rx = arg; + if (re_atomic_rlx(&rx->run)) { + re_atomic_rlx_set(&rx->run, false); + thrd_join(rx->thr, NULL); + } + + re_thread_async_main_cancel((intptr_t)rx); + mem_deref(rx->metric); mem_deref(rx->name); mem_deref(rx->mtx); @@ -502,6 +659,41 @@ int rtprecv_alloc(struct rtp_receiver **rxp, } +int rtprecv_start_thread(struct rtp_receiver *rx) +{ + int err; + + if (!rx) + return EINVAL; + + if (re_atomic_rlx(&rx->run)) + return 0; + + re_atomic_rlx_set(&rx->run, true); + err = thread_create_name(&rx->thr, + "RX thread", + rtprecv_thread, rx); + if (err) { + re_atomic_rlx_set(&rx->run, false); + } + else { + udp_thread_detach(rtp_sock(rx->rtp)); + udp_thread_detach(rtcp_sock(rx->rtp)); + } + + return err; +} + + +bool rtprecv_running(const struct rtp_receiver *rx) +{ + if (!rx) + return false; + + return re_atomic_rlx(&rx->run); +} + + void rtprecv_set_handlers(struct rtp_receiver *rx, stream_rtpestab_h *rtpestabh, void *arg) { @@ -523,3 +715,49 @@ struct metric *rtprecv_metric(struct rtp_receiver *rx) /* it is allowed to return metric because it is thread safe */ return rx->metric; } + + +static void work_destructor(void *arg) +{ + struct work *w = arg; + + switch (w->type) { + case WORK_RTCP: + mem_deref(w->u.rtcp); + break; + case WORK_PTCHANGED: + mem_deref(w->u.pt.mb); + break; + default: + break; + } +} + + +static void async_work_main(int err, void *arg) +{ + struct work *w = arg; + struct rtp_receiver *rx = w->rx; + (void)err; + + switch (w->type) { + case WORK_RTCP: + stream_process_rtcp(rx->strm, w->u.rtcp); + break; + case WORK_PTCHANGED: + rx->pth(w->u.pt.pt, w->u.pt.mb, rx->arg); + break; + case WORK_RTPESTAB: + rx->rtpestabh(rx->strm, rx->sessarg); + break; + case WORK_MNATCONNH: + stream_mnat_connected(rx->strm, + &w->u.mnat.raddr1, + &w->u.mnat.raddr2); + break; + default: + break; + } + + mem_deref(w); +} diff --git a/src/stream.c b/src/stream.c index d02b6d8a4a..715507ede4 100644 --- a/src/stream.c +++ b/src/stream.c @@ -224,6 +224,13 @@ int stream_enable_tx(struct stream *strm, bool enable) } +static void stream_start_receiver(void *arg) +{ + struct stream *s = arg; + rtprecv_start_thread(s->rx); +} + + /** * Enable RX stream * @@ -251,6 +258,19 @@ int stream_enable_rx(struct stream *strm, bool enable) debug("stream: enable %s RTP receiver\n", media_name(strm->type)); rtprecv_set_enable(strm->rx, true); + if (strm->rtp && strm->cfg.rxmode == RECEIVE_MODE_THREAD && + strm->type == MEDIA_AUDIO && !rtprecv_running(strm->rx)) { + if (stream_bundle(strm)) { + warning("stream: rtp_rxmode thread was disabled " + "because it is not supported in combination " + "with avt_bundle\n"); + } + else { + tmr_start(&strm->rxm.tmr_rec, 1, stream_start_receiver, + strm); + } + } + return 0; } From 1d7b9ad9bd426fb9f997fe42cb524c2252e51fb6 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Wed, 25 Oct 2023 10:35:15 +0200 Subject: [PATCH 19/31] test: run call tests with RX_MODE_THREAD --- test/call.c | 480 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 434 insertions(+), 46 deletions(-) diff --git a/test/call.c b/test/call.c index 78ec1cc509..3fa446fdb2 100644 --- a/test/call.c +++ b/test/call.c @@ -839,11 +839,12 @@ static void event_handler(struct ua *ua, enum ua_event ev, } -int test_call_answer(void) +static int test_call_answer_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; int err = 0; + conf_config()->avt.rxmode = rxmode; fixture_init(f); f->behaviour = BEHAVIOUR_ANSWER; @@ -873,6 +874,21 @@ int test_call_answer(void) } +int test_call_answer(void) +{ + int err; + + err = test_call_answer_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_answer_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + int test_call_reject(void) { struct fixture fix, *f = &fix; @@ -905,11 +921,12 @@ int test_call_reject(void) } -int test_call_answer_hangup_a(void) +static int test_call_answer_hangup_a_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; int err = 0; + conf_config()->avt.rxmode = rxmode; fixture_init(f); f->behaviour = BEHAVIOUR_ANSWER; @@ -939,12 +956,28 @@ int test_call_answer_hangup_a(void) } -int test_call_answer_hangup_b(void) +int test_call_answer_hangup_a(void) +{ + int err; + + err = test_call_answer_hangup_a_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_answer_hangup_a_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_call_answer_hangup_b_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; char uri[256]; int err = 0; + conf_config()->avt.rxmode = rxmode; fixture_init(f); f->behaviour = BEHAVIOUR_ANSWER; @@ -977,13 +1010,29 @@ int test_call_answer_hangup_b(void) } -int test_call_rtp_timeout(void) +int test_call_answer_hangup_b(void) +{ + int err; + + err = test_call_answer_hangup_b_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_answer_hangup_b_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_call_rtp_timeout_base(enum rtp_receive_mode rxmode) { #define RTP_TIMEOUT_MS 1 struct fixture fix, *f = &fix; struct call *call; int err = 0; + conf_config()->avt.rxmode = rxmode; fixture_init(f); f->behaviour = BEHAVIOUR_ANSWER; @@ -1018,6 +1067,21 @@ int test_call_rtp_timeout(void) } +int test_call_rtp_timeout(void) +{ + int err; + + err = test_call_rtp_timeout_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_rtp_timeout_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + /* veriy that line-numbers are in sequence */ static bool linenum_are_sequential(const struct ua *ua) { @@ -1037,13 +1101,14 @@ static bool linenum_are_sequential(const struct ua *ua) } -int test_call_multiple(void) +static int test_call_multiple_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; struct le *le; unsigned i; int err = 0; + conf_config()->avt.rxmode = rxmode; fixture_init(f); f->behaviour = BEHAVIOUR_ANSWER; @@ -1127,7 +1192,22 @@ int test_call_multiple(void) } -int test_call_max(void) +int test_call_multiple(void) +{ + int err; + + err = test_call_multiple_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_multiple_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_call_max_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; unsigned i; @@ -1137,6 +1217,7 @@ int test_call_max(void) /* We start 2 calls from a.ua to b.ua. */ /* This are 2 outgoing calls and 1 incoming. */ conf_config()->call.max_calls = 3; + conf_config()->avt.rxmode = rxmode; fixture_init(f); @@ -1172,12 +1253,29 @@ int test_call_max(void) } -int test_call_dtmf(void) +int test_call_max(void) +{ + int err; + + err = test_call_max_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_max_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_call_dtmf_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; size_t i, n = str_len(dtmf_digits); int err = 0; + conf_config()->avt.rxmode = rxmode; + /* Use a low packet time, so the test completes quickly */ fixture_init_prm(f, ";ptime=1"); @@ -1218,6 +1316,21 @@ int test_call_dtmf(void) } +int test_call_dtmf(void) +{ + int err; + + err = test_call_dtmf_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_dtmf_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + static void mock_vidisp_handler(const struct vidframe *frame, uint64_t timestamp, const char *title, void *arg) @@ -1251,7 +1364,7 @@ static void mock_vidisp_handler(const struct vidframe *frame, } -int test_call_video(void) +static int test_call_video_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; struct vidisp *vidisp = NULL; @@ -1260,6 +1373,7 @@ int test_call_video(void) conf_config()->video.fps = 100; conf_config()->video.enc_fmt = VID_FMT_YUV420P; + conf_config()->avt.rxmode = rxmode; fixture_init(f); cancel_rule_new(UA_EVENT_CUSTOM, f->b.ua, 1, 0, 1); @@ -1307,7 +1421,22 @@ int test_call_video(void) } -int test_call_change_videodir(void) +int test_call_video(void) +{ + int err; + + err = test_call_video_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_video_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_call_change_videodir_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; struct vidisp *vidisp = NULL; @@ -1317,6 +1446,7 @@ int test_call_change_videodir(void) conf_config()->video.fps = 100; conf_config()->video.enc_fmt = VID_FMT_YUV420P; + conf_config()->avt.rxmode = rxmode; fixture_init_prm(f, ";answermode=early"); cr_prog = cancel_rule_new(UA_EVENT_CALL_PROGRESS, f->a.ua, 0, 1, 0); @@ -1435,7 +1565,22 @@ int test_call_change_videodir(void) } -int test_call_100rel_video(void) +int test_call_change_videodir(void) +{ + int err; + + err = test_call_change_videodir_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_change_videodir_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_call_100rel_video_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; struct vidisp *vidisp = NULL; @@ -1444,6 +1589,7 @@ int test_call_100rel_video(void) conf_config()->video.fps = 100; conf_config()->video.enc_fmt = VID_FMT_YUV420P; + conf_config()->avt.rxmode = rxmode; fixture_init_prm(f, ";100rel=yes;answermode=early"); @@ -1523,6 +1669,21 @@ int test_call_100rel_video(void) } +int test_call_100rel_video(void) +{ + int err; + + err = test_call_100rel_video_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_100rel_video_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + static void auframe_handler(struct auframe *af, const char *dev, void *arg) { struct fixture *fix = arg; @@ -1564,13 +1725,15 @@ static void auframe_handler(struct auframe *af, const char *dev, void *arg) } -int test_call_aulevel(void) +static int test_call_aulevel_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; struct cancel_rule *cr; struct auplay *auplay = NULL; int err = 0; + conf_config()->avt.rxmode = rxmode; + /* Use a low packet time, so the test completes quickly */ fixture_init_prm(f, ";ptime=1;audio_player=mock-auplay,a"); mem_deref(f->b.ua); @@ -1616,7 +1779,8 @@ int test_call_aulevel(void) } -static int test_100rel_audio_base(enum audio_mode txmode) +static int test_100rel_audio_base(enum rtp_receive_mode rxmode, + enum audio_mode txmode) { struct fixture fix, *f = &fix; struct cancel_rule *cr; @@ -1630,6 +1794,7 @@ static int test_100rel_audio_base(enum audio_mode txmode) ";regint=0;ptime=1;audio_player=mock-auplay,b" ";answermode=early;100rel=yes"); TEST_ERR(err); + conf_config()->avt.rxmode = rxmode; conf_config()->audio.txmode = txmode; cancel_rule_new(UA_EVENT_CUSTOM, f->b.ua, 1, -1, 0); @@ -1717,11 +1882,14 @@ int test_call_100rel_audio(void) { int err; - err = test_100rel_audio_base(AUDIO_MODE_POLL); - ASSERT_EQ(0, err); - - err = test_100rel_audio_base(AUDIO_MODE_THREAD); - ASSERT_EQ(0, err); + err = test_100rel_audio_base(RECEIVE_MODE_MAIN, AUDIO_MODE_POLL); + TEST_ERR(err); + err = test_100rel_audio_base(RECEIVE_MODE_MAIN, AUDIO_MODE_THREAD); + TEST_ERR(err); + err = test_100rel_audio_base(RECEIVE_MODE_THREAD, AUDIO_MODE_POLL); + TEST_ERR(err); + err = test_100rel_audio_base(RECEIVE_MODE_THREAD, AUDIO_MODE_THREAD); + TEST_ERR(err); conf_config()->audio.txmode = AUDIO_MODE_POLL; @@ -1730,12 +1898,28 @@ int test_call_100rel_audio(void) } -int test_call_progress(void) +int test_call_aulevel(void) +{ + int err; + + err = test_call_aulevel_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_aulevel_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_call_progress_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; struct cancel_rule *cr; int err = 0; + conf_config()->avt.rxmode = rxmode; fixture_init_prm(f, ";answermode=early"); cancel_rule_new(UA_EVENT_CALL_PROGRESS, f->a.ua, 0, 1, 0); @@ -1768,7 +1952,23 @@ int test_call_progress(void) } -static int test_media_base(enum audio_mode txmode) +int test_call_progress(void) +{ + int err; + + err = test_call_progress_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_progress_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_media_base(enum rtp_receive_mode rxmode, + enum audio_mode txmode) { struct fixture fix, *f = &fix; struct cancel_rule *cr; @@ -1776,6 +1976,7 @@ static int test_media_base(enum audio_mode txmode) int err = 0; fixture_init_prm(f, ";ptime=1;audio_player=mock-auplay,a"); + conf_config()->avt.rxmode = rxmode; mem_deref(f->b.ua); err = ua_alloc(&f->b.ua, "B " ";regint=0;ptime=1;audio_player=mock-auplay,b"); @@ -1840,10 +2041,16 @@ int test_call_format_float(void) { int err; - err = test_media_base(AUDIO_MODE_POLL); + err = test_media_base(RECEIVE_MODE_MAIN, AUDIO_MODE_POLL); + ASSERT_EQ(0, err); + + err = test_media_base(RECEIVE_MODE_MAIN, AUDIO_MODE_THREAD); + ASSERT_EQ(0, err); + + err = test_media_base(RECEIVE_MODE_THREAD, AUDIO_MODE_POLL); ASSERT_EQ(0, err); - err = test_media_base(AUDIO_MODE_THREAD); + err = test_media_base(RECEIVE_MODE_THREAD, AUDIO_MODE_THREAD); ASSERT_EQ(0, err); conf_config()->audio.txmode = AUDIO_MODE_POLL; @@ -1853,7 +2060,7 @@ int test_call_format_float(void) } -int test_call_mediaenc(void) +static int test_call_mediaenc_base(enum rtp_receive_mode rxmode) { struct fixture fix = {0}, *f = &fix; struct cancel_rule *cr; @@ -1862,6 +2069,8 @@ int test_call_mediaenc(void) err = module_load(".", "srtp"); TEST_ERR(err); + conf_config()->avt.rxmode = rxmode; + /* Enable a dummy media encryption protocol */ fixture_init_prm(f, ";mediaenc=srtp;ptime=1"); cancel_rule_new(UA_EVENT_CALL_RTPESTAB, f->b.ua, 1, 0, 1); @@ -1914,13 +2123,29 @@ int test_call_mediaenc(void) } -int test_call_medianat(void) +int test_call_mediaenc(void) +{ + int err; + + err = test_call_mediaenc_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_mediaenc_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_call_medianat_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; struct cancel_rule *cr; int err; mock_mnat_register(baresip_mnatl()); + conf_config()->avt.rxmode = rxmode; /* Enable a dummy media NAT-traversal protocol */ fixture_init_prm(f, ";medianat=XNAT;ptime=1"); @@ -1964,7 +2189,22 @@ int test_call_medianat(void) } -int test_call_custom_headers(void) +int test_call_medianat(void) +{ + int err; + + err = test_call_medianat_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_medianat_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_call_custom_headers_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; int err = 0; @@ -1972,6 +2212,7 @@ int test_call_custom_headers(void) struct list custom_hdrs; bool headers_matched = true; + conf_config()->avt.rxmode = rxmode; fixture_init(f); ua_add_xhdr_filter(f->b.ua, "X-CALL_ID"); @@ -2042,11 +2283,27 @@ int test_call_custom_headers(void) } -int test_call_tcp(void) +int test_call_custom_headers(void) +{ + int err; + + err = test_call_custom_headers_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_custom_headers_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_call_tcp_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; int err = 0; + conf_config()->avt.rxmode = rxmode; fixture_init(f); f->behaviour = BEHAVIOUR_ANSWER; @@ -2070,6 +2327,21 @@ int test_call_tcp(void) } +int test_call_tcp(void) +{ + int err; + + err = test_call_tcp_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_tcp_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + int test_call_deny_udp(void) { struct fixture fix, *f = &fix; @@ -2122,11 +2394,12 @@ int test_call_deny_udp(void) * Step 3. Call between B and C * No call for A */ -int test_call_transfer(void) +static int test_call_transfer_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; int err = 0; + conf_config()->avt.rxmode = rxmode; fixture_init(f); /* Create a 3rd useragent needed for transfer */ @@ -2172,11 +2445,27 @@ int test_call_transfer(void) } -int test_call_transfer_fail(void) +int test_call_transfer(void) +{ + int err; + + err = test_call_transfer_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_transfer_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_call_transfer_fail_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; int err = 0; + conf_config()->avt.rxmode = rxmode; fixture_init(f); /* Create a 3rd useragent needed for transfer */ @@ -2227,11 +2516,27 @@ int test_call_transfer_fail(void) } -int test_call_attended_transfer(void) +int test_call_transfer_fail(void) +{ + int err; + + err = test_call_transfer_fail_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_transfer_fail_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_call_attended_transfer_base(enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; int err = 0; + conf_config()->avt.rxmode = rxmode; fixture_init(f); err = ua_alloc(&f->c.ua, "C ;regint=0"); @@ -2278,7 +2583,22 @@ int test_call_attended_transfer(void) } -static int test_call_rtcp_base(bool rtcp_mux) +int test_call_attended_transfer(void) +{ + int err; + + err = test_call_attended_transfer_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_attended_transfer_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_call_rtcp_base(enum rtp_receive_mode rxmode, bool rtcp_mux) { struct fixture fix, *f = &fix; struct cancel_rule *cr; @@ -2287,6 +2607,8 @@ static int test_call_rtcp_base(bool rtcp_mux) err = module_load(".", "ausine"); TEST_ERR(err); + conf_config()->avt.rxmode = rxmode; + /* Use a low packet time, so the test completes quickly */ if (rtcp_mux) { fixture_init_prm(f, ";ptime=1;rtcp_mux=yes"); @@ -2336,11 +2658,21 @@ static int test_call_rtcp_base(bool rtcp_mux) int test_call_rtcp(void) { - int err = 0; + int err; - err |= test_call_rtcp_base(false); - err |= test_call_rtcp_base(true); + err = test_call_rtcp_base(RECEIVE_MODE_MAIN, false); + TEST_ERR(err); + err = test_call_rtcp_base(RECEIVE_MODE_MAIN, true); + TEST_ERR(err); + + err = test_call_rtcp_base(RECEIVE_MODE_THREAD, false); + TEST_ERR(err); + + err = test_call_rtcp_base(RECEIVE_MODE_THREAD, true); + TEST_ERR(err); + +out: return err; } @@ -2352,8 +2684,11 @@ int test_call_aufilt(void) err = module_load(".", "auconv"); TEST_ERR(err); - err = test_media_base(AUDIO_MODE_POLL); - ASSERT_EQ(0, err); + err = test_media_base(RECEIVE_MODE_MAIN, AUDIO_MODE_POLL); + TEST_ERR(err); + + err = test_media_base(RECEIVE_MODE_THREAD, AUDIO_MODE_POLL); + TEST_ERR(err); out: module_unload("auconv"); @@ -2365,7 +2700,7 @@ int test_call_aufilt(void) /* * Simulate a complete WebRTC testcase */ -int test_call_webrtc(void) +static int test_call_webrtc_base(enum rtp_receive_mode rxmode) { struct fixture fix = {0}, *f = &fix; struct cancel_rule *cr; @@ -2373,6 +2708,7 @@ int test_call_webrtc(void) int err; conf_config()->avt.rtcp_mux = true; + conf_config()->avt.rxmode = rxmode; mock_mnat_register(baresip_mnatl()); @@ -2456,7 +2792,23 @@ int test_call_webrtc(void) } -static int test_call_bundle_base(bool use_mnat, bool use_menc) +int test_call_webrtc(void) +{ + int err; + + err = test_call_webrtc_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_webrtc_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_call_bundle_base(bool use_mnat, bool use_menc, + enum rtp_receive_mode rxmode) { struct fixture fix = {0}, *f = &fix; struct cancel_rule *cr; @@ -2471,6 +2823,7 @@ static int test_call_bundle_base(bool use_mnat, bool use_menc) conf_config()->avt.bundle = true; conf_config()->avt.rtcp_mux = true; /* MUST enable RTP/RTCP mux */ conf_config()->video.fps = 100; + conf_config()->avt.rxmode = rxmode; if (use_mnat) { mock_mnat_register(baresip_mnatl()); @@ -2614,13 +2967,26 @@ static int test_call_bundle_base(bool use_mnat, bool use_menc) */ int test_call_bundle(void) { - int err = 0; + int err; - err |= test_call_bundle_base(false, false); - err |= test_call_bundle_base(true, false); - err |= test_call_bundle_base(false, true); - err |= test_call_bundle_base(true, true); + err = test_call_bundle_base(false, false, RECEIVE_MODE_MAIN); + TEST_ERR(err); + err = test_call_bundle_base(true, false, RECEIVE_MODE_MAIN); + TEST_ERR(err); + err = test_call_bundle_base(false, true, RECEIVE_MODE_MAIN); + TEST_ERR(err); + err = test_call_bundle_base(true, true, RECEIVE_MODE_MAIN); + TEST_ERR(err); + err = test_call_bundle_base(false, false, RECEIVE_MODE_THREAD); + TEST_ERR(err); + err = test_call_bundle_base(true, false, RECEIVE_MODE_THREAD); + TEST_ERR(err); + err = test_call_bundle_base(false, true, RECEIVE_MODE_THREAD); + TEST_ERR(err); + err = test_call_bundle_base(true, true, RECEIVE_MODE_THREAD); + TEST_ERR(err); +out: return err; } @@ -2639,7 +3005,7 @@ static bool find_ipv6ll(const char *ifname, const struct sa *sa, void *arg) } -int test_call_ipv6ll(void) +static int test_call_ipv6ll_base(enum rtp_receive_mode rxmode) { struct fixture fix = {0}, *f = &fix; struct cancel_rule *cr; @@ -2658,6 +3024,7 @@ int test_call_ipv6ll(void) err = module_load(".", "ausine"); TEST_ERR(err); + conf_config()->avt.rxmode = rxmode; fixture_init(f); f->behaviour = BEHAVIOUR_ANSWER; @@ -2711,13 +3078,28 @@ int test_call_ipv6ll(void) } -static int test_call_hold_resume_base(bool tcp) +int test_call_ipv6ll(void) +{ + int err; + + err = test_call_ipv6ll_base(RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_ipv6ll_base(RECEIVE_MODE_THREAD); + TEST_ERR(err); + +out: + return err; +} + + +static int test_call_hold_resume_base(bool tcp, enum rtp_receive_mode rxmode) { struct fixture fix, *f = &fix; struct cancel_rule *cr; int err = 0; - + conf_config()->avt.rxmode = rxmode; fixture_init(f); cancel_rule_new(UA_EVENT_CALL_RTPESTAB, f->a.ua, 0, 0, 1); cr->n_audio_estab = 1; @@ -2814,10 +3196,16 @@ int test_call_hold_resume(void) { int err; - err = test_call_hold_resume_base(false); + err = test_call_hold_resume_base(false, RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_hold_resume_base(true, RECEIVE_MODE_MAIN); + TEST_ERR(err); + + err = test_call_hold_resume_base(false, RECEIVE_MODE_THREAD); TEST_ERR(err); - err = test_call_hold_resume_base(true); + err = test_call_hold_resume_base(true, RECEIVE_MODE_THREAD); TEST_ERR(err); out: From b0187db09dc031a7fd54855067bb516490c6068c Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Wed, 25 Oct 2023 11:34:55 +0200 Subject: [PATCH 20/31] test: main - init async workers --- test/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/main.c b/test/main.c index 575dac1482..f78777674d 100644 --- a/test/main.c +++ b/test/main.c @@ -10,6 +10,7 @@ #include #include "test.h" +enum { ASYNC_WORKERS = 4 }; typedef int (test_exec_h)(void); @@ -192,6 +193,7 @@ int main(int argc, char *argv[]) return err; log_enable_info(false); + re_thread_async_init(ASYNC_WORKERS); #ifdef HAVE_GETOPT for (;;) { From e76b25c698c72c2a7f2d120a0f0f48f014330498 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Wed, 25 Oct 2023 11:36:44 +0200 Subject: [PATCH 21/31] rtprecv: detach from RTP/RTCP sockets before re_cancel --- src/rtprecv.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/rtprecv.c b/src/rtprecv.c index b0c2589385..6d9d83c16c 100644 --- a/src/rtprecv.c +++ b/src/rtprecv.c @@ -159,10 +159,14 @@ static void rtprecv_check_stop(void *arg) { struct rtp_receiver *rx = arg; - if (re_atomic_rlx(&rx->run)) + if (re_atomic_rlx(&rx->run)) { tmr_start(&rx->tmr, 10, rtprecv_check_stop, rx); - else + } + else { + udp_thread_detach(rtp_sock(rx->rtp)); + udp_thread_detach(rtcp_sock(rx->rtp)); re_cancel(); + } } From 49cc763a0661227b28cc75285846931b78b2c501 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Wed, 25 Oct 2023 15:50:37 +0200 Subject: [PATCH 22/31] stream,rtprecv: detach from RTP/RTCP also in RECEIVE_MODE_MAIN --- src/audio.c | 2 ++ src/core.h | 2 +- src/rtprecv.c | 15 +++++++++++---- src/stream.c | 4 ++-- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/audio.c b/src/audio.c index 8a481eca23..3ca4b0fcee 100644 --- a/src/audio.c +++ b/src/audio.c @@ -227,6 +227,7 @@ static void audio_destructor(void *arg) stream_enable(a->strm, false); stop_tx(&a->tx, a); stop_rx(&a->rx); + stream_enable(a->strm, false); mem_deref(a->tx.enc); mem_deref(a->tx.aubuf); @@ -1402,6 +1403,7 @@ void audio_stop(struct audio *a) stop_tx(&a->tx, a); stop_rx(&a->rx); + stream_enable(a->strm, false); a->started = false; } diff --git a/src/core.h b/src/core.h index b7fe9a4136..8d5ac25cfc 100644 --- a/src/core.h +++ b/src/core.h @@ -507,7 +507,7 @@ void rtprecv_set_ssrc(struct rtp_receiver *rx, uint32_t ssrc); uint64_t rtprecv_ts_last(struct rtp_receiver *rx); void rtprecv_set_ts_last(struct rtp_receiver *rx, uint64_t ts_last); void rtprecv_flush(struct rtp_receiver *rx); -void rtprecv_set_enable(struct rtp_receiver *rx, bool enable); +void rtprecv_enable(struct rtp_receiver *rx, bool enable); int rtprecv_get_ssrc(struct rtp_receiver *rx, uint32_t *ssrc); void rtprecv_enable_mux(struct rtp_receiver *rx, bool enable); int rtprecv_debug(struct re_printf *pf, const struct rtp_receiver *rx); diff --git a/src/rtprecv.c b/src/rtprecv.c index 6d9d83c16c..5928313ec3 100644 --- a/src/rtprecv.c +++ b/src/rtprecv.c @@ -322,10 +322,10 @@ void rtprecv_decode(const struct sa *src, const struct rtp_header *hdr, bool first = false; int err = 0; - MAGIC_CHECK(rx); if (!rx) return; + MAGIC_CHECK(rx); mtx_lock(rx->mtx); if (!rx->enabled) { mtx_unlock(rx->mtx); @@ -479,6 +479,10 @@ uint64_t rtprecv_ts_last(struct rtp_receiver *rx) return 0; uint64_t ts_last; + + if (!rx) + return 0; + mtx_lock(rx->mtx); ts_last = rx->ts_last; mtx_unlock(rx->mtx); @@ -507,7 +511,7 @@ void rtprecv_flush(struct rtp_receiver *rx) } -void rtprecv_set_enable(struct rtp_receiver *rx, bool enable) +void rtprecv_enable(struct rtp_receiver *rx, bool enable) { if (!rx) return; @@ -584,9 +588,12 @@ static void destructor(void *arg) if (re_atomic_rlx(&rx->run)) { re_atomic_rlx_set(&rx->run, false); thrd_join(rx->thr, NULL); + re_thread_async_main_cancel((intptr_t)rx); + } + else { + udp_thread_detach(rtp_sock(rx->rtp)); + udp_thread_detach(rtcp_sock(rx->rtp)); } - - re_thread_async_main_cancel((intptr_t)rx); mem_deref(rx->metric); mem_deref(rx->name); diff --git a/src/stream.c b/src/stream.c index 715507ede4..a3854d045b 100644 --- a/src/stream.c +++ b/src/stream.c @@ -248,7 +248,7 @@ int stream_enable_rx(struct stream *strm, bool enable) debug("stream: disable %s RTP receiver\n", media_name(strm->type)); - rtprecv_set_enable(strm->rx, false); + rtprecv_enable(strm->rx, false); return 0; } @@ -256,7 +256,7 @@ int stream_enable_rx(struct stream *strm, bool enable) return ENOTSUP; debug("stream: enable %s RTP receiver\n", media_name(strm->type)); - rtprecv_set_enable(strm->rx, true); + rtprecv_enable(strm->rx, true); if (strm->rtp && strm->cfg.rxmode == RECEIVE_MODE_THREAD && strm->type == MEDIA_AUDIO && !rtprecv_running(strm->rx)) { From a5cb0086542ea6d4de2396cd8b111c8393f4bfe2 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Wed, 25 Oct 2023 15:52:40 +0200 Subject: [PATCH 23/31] test: call - add AUDIO_MODE_THREAD for test_call_aufilt --- test/call.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/call.c b/test/call.c index 3fa446fdb2..12494a2207 100644 --- a/test/call.c +++ b/test/call.c @@ -2690,6 +2690,12 @@ int test_call_aufilt(void) err = test_media_base(RECEIVE_MODE_THREAD, AUDIO_MODE_POLL); TEST_ERR(err); + err = test_media_base(RECEIVE_MODE_MAIN, AUDIO_MODE_THREAD); + TEST_ERR(err); + + err = test_media_base(RECEIVE_MODE_THREAD, AUDIO_MODE_THREAD); + TEST_ERR(err); + out: module_unload("auconv"); From 405c1f0c3c36560c48531d699b77ef37932e81cf Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Fri, 27 Oct 2023 13:24:07 +0200 Subject: [PATCH 24/31] test: call - reset to RECEIVE_MODE_MAIN --- test/call.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/test/call.c b/test/call.c index 12494a2207..89af4e425b 100644 --- a/test/call.c +++ b/test/call.c @@ -884,6 +884,8 @@ int test_call_answer(void) err = test_call_answer_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -966,6 +968,8 @@ int test_call_answer_hangup_a(void) err = test_call_answer_hangup_a_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -1020,6 +1024,8 @@ int test_call_answer_hangup_b(void) err = test_call_answer_hangup_b_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -1077,6 +1083,8 @@ int test_call_rtp_timeout(void) err = test_call_rtp_timeout_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -1202,6 +1210,8 @@ int test_call_multiple(void) err = test_call_multiple_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -1263,6 +1273,8 @@ int test_call_max(void) err = test_call_max_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -1326,6 +1338,8 @@ int test_call_dtmf(void) err = test_call_dtmf_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -1431,6 +1445,8 @@ int test_call_video(void) err = test_call_video_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -1575,6 +1591,8 @@ int test_call_change_videodir(void) err = test_call_change_videodir_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -1679,6 +1697,8 @@ int test_call_100rel_video(void) err = test_call_100rel_video_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -1891,6 +1911,7 @@ int test_call_100rel_audio(void) err = test_100rel_audio_base(RECEIVE_MODE_THREAD, AUDIO_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; conf_config()->audio.txmode = AUDIO_MODE_POLL; out: @@ -1908,6 +1929,8 @@ int test_call_aulevel(void) err = test_call_aulevel_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -1962,6 +1985,8 @@ int test_call_progress(void) err = test_call_progress_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -2053,6 +2078,7 @@ int test_call_format_float(void) err = test_media_base(RECEIVE_MODE_THREAD, AUDIO_MODE_THREAD); ASSERT_EQ(0, err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; conf_config()->audio.txmode = AUDIO_MODE_POLL; out: @@ -2133,6 +2159,8 @@ int test_call_mediaenc(void) err = test_call_mediaenc_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -2199,6 +2227,8 @@ int test_call_medianat(void) err = test_call_medianat_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -2293,6 +2323,8 @@ int test_call_custom_headers(void) err = test_call_custom_headers_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -2337,6 +2369,8 @@ int test_call_tcp(void) err = test_call_tcp_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -2455,6 +2489,8 @@ int test_call_transfer(void) err = test_call_transfer_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -2526,6 +2562,8 @@ int test_call_transfer_fail(void) err = test_call_transfer_fail_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -2593,6 +2631,8 @@ int test_call_attended_transfer(void) err = test_call_attended_transfer_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -2672,6 +2712,8 @@ int test_call_rtcp(void) err = test_call_rtcp_base(RECEIVE_MODE_THREAD, true); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -2696,6 +2738,9 @@ int test_call_aufilt(void) err = test_media_base(RECEIVE_MODE_THREAD, AUDIO_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + conf_config()->audio.txmode = AUDIO_MODE_POLL; + out: module_unload("auconv"); @@ -2808,6 +2853,8 @@ int test_call_webrtc(void) err = test_call_webrtc_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -2992,6 +3039,8 @@ int test_call_bundle(void) err = test_call_bundle_base(true, true, RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } @@ -3094,6 +3143,8 @@ int test_call_ipv6ll(void) err = test_call_ipv6ll_base(RECEIVE_MODE_THREAD); TEST_ERR(err); + conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + out: return err; } From 9fa15ebbb3d8928b48627d26ed0d0f13740a28da Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Mon, 30 Oct 2023 09:47:36 +0100 Subject: [PATCH 25/31] rtprecv: use enable flag to prevent data race on stream termination --- src/rtprecv.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/rtprecv.c b/src/rtprecv.c index 5928313ec3..4273f79544 100644 --- a/src/rtprecv.c +++ b/src/rtprecv.c @@ -419,8 +419,12 @@ void rtprecv_handle_rtcp(const struct sa *src, struct rtcp_msg *msg, (void)src; MAGIC_CHECK(rx); - mtx_lock(rx->mtx); + if (!rx->enabled) { + mtx_unlock(rx->mtx); + return; + } + rx->ts_last = tmr_jiffies(); mtx_unlock(rx->mtx); @@ -586,6 +590,7 @@ static void destructor(void *arg) struct rtp_receiver *rx = arg; if (re_atomic_rlx(&rx->run)) { + rtprecv_enable(rx, false); re_atomic_rlx_set(&rx->run, false); thrd_join(rx->thr, NULL); re_thread_async_main_cancel((intptr_t)rx); From c5209c7c32b17e39eeeea2de3f4231e91b60c600 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Mon, 30 Oct 2023 09:52:01 +0100 Subject: [PATCH 26/31] test: call - do not test unsupported combination --- test/call.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/test/call.c b/test/call.c index 89af4e425b..cee8afb6cd 100644 --- a/test/call.c +++ b/test/call.c @@ -2860,8 +2860,7 @@ int test_call_webrtc(void) } -static int test_call_bundle_base(bool use_mnat, bool use_menc, - enum rtp_receive_mode rxmode) +static int test_call_bundle_base(bool use_mnat, bool use_menc) { struct fixture fix = {0}, *f = &fix; struct cancel_rule *cr; @@ -2876,7 +2875,6 @@ static int test_call_bundle_base(bool use_mnat, bool use_menc, conf_config()->avt.bundle = true; conf_config()->avt.rtcp_mux = true; /* MUST enable RTP/RTCP mux */ conf_config()->video.fps = 100; - conf_config()->avt.rxmode = rxmode; if (use_mnat) { mock_mnat_register(baresip_mnatl()); @@ -3020,28 +3018,13 @@ static int test_call_bundle_base(bool use_mnat, bool use_menc, */ int test_call_bundle(void) { - int err; - - err = test_call_bundle_base(false, false, RECEIVE_MODE_MAIN); - TEST_ERR(err); - err = test_call_bundle_base(true, false, RECEIVE_MODE_MAIN); - TEST_ERR(err); - err = test_call_bundle_base(false, true, RECEIVE_MODE_MAIN); - TEST_ERR(err); - err = test_call_bundle_base(true, true, RECEIVE_MODE_MAIN); - TEST_ERR(err); - err = test_call_bundle_base(false, false, RECEIVE_MODE_THREAD); - TEST_ERR(err); - err = test_call_bundle_base(true, false, RECEIVE_MODE_THREAD); - TEST_ERR(err); - err = test_call_bundle_base(false, true, RECEIVE_MODE_THREAD); - TEST_ERR(err); - err = test_call_bundle_base(true, true, RECEIVE_MODE_THREAD); - TEST_ERR(err); + int err = 0; - conf_config()->avt.rxmode = RECEIVE_MODE_MAIN; + err |= test_call_bundle_base(false, false); + err |= test_call_bundle_base(true, false); + err |= test_call_bundle_base(false, true); + err |= test_call_bundle_base(true, true); -out: return err; } From ad79fadc48f7bc4efc8ba558475ba011475ee285 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Tue, 31 Oct 2023 13:55:03 +0100 Subject: [PATCH 27/31] test: call - failure debug for test_media_base() --- test/call.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/call.c b/test/call.c index cee8afb6cd..1d87011cbc 100644 --- a/test/call.c +++ b/test/call.c @@ -2048,6 +2048,9 @@ static int test_media_base(enum rtp_receive_mode rxmode, ASSERT_EQ(0, fix.b.n_closed); out: + if (err) + failure_debug(f, false); + conf_config()->audio.src_fmt = AUFMT_S16LE; conf_config()->audio.play_fmt = AUFMT_S16LE; From e9eaeecc1c7111798560a23da192f805608b4961 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Tue, 31 Oct 2023 13:56:28 +0100 Subject: [PATCH 28/31] [TMP] ci: activate verbose logging for valgrind workflow --- .github/workflows/valgrind.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/valgrind.yml b/.github/workflows/valgrind.yml index 14efa308e8..d30eb54666 100644 --- a/.github/workflows/valgrind.yml +++ b/.github/workflows/valgrind.yml @@ -43,4 +43,4 @@ jobs: run: cmake -B build -DSTATIC=1 -DMODULES="g711;ausine;fakevideo;auconv;dtls_srtp;srtp;aufile" && cmake --build build -j - name: valgrind test - run: valgrind --leak-check=full --show-reachable=yes --error-exitcode=42 ./build/test/selftest + run: valgrind --leak-check=full --show-reachable=yes --error-exitcode=42 ./build/test/selftest -v From 75fe91c74799910ea23e7041184258c3638c8724 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Tue, 31 Oct 2023 17:36:46 +0100 Subject: [PATCH 29/31] rtprecv: detach sockets before attach --- src/rtprecv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rtprecv.c b/src/rtprecv.c index 4273f79544..3b38b522b1 100644 --- a/src/rtprecv.c +++ b/src/rtprecv.c @@ -685,16 +685,16 @@ int rtprecv_start_thread(struct rtp_receiver *rx) if (re_atomic_rlx(&rx->run)) return 0; + udp_thread_detach(rtp_sock(rx->rtp)); + udp_thread_detach(rtcp_sock(rx->rtp)); re_atomic_rlx_set(&rx->run, true); err = thread_create_name(&rx->thr, "RX thread", rtprecv_thread, rx); if (err) { re_atomic_rlx_set(&rx->run, false); - } - else { - udp_thread_detach(rtp_sock(rx->rtp)); - udp_thread_detach(rtcp_sock(rx->rtp)); + udp_thread_attach(rtp_sock(rx->rtp)); + udp_thread_attach(rtcp_sock(rx->rtp)); } return err; From 81433b5fde0bd3c8e937f7fc3af5d3dd49fc64fe Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Thu, 2 Nov 2023 07:17:02 +0100 Subject: [PATCH 30/31] rtprecv: warnings for UDP thread attach --- src/rtprecv.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/rtprecv.c b/src/rtprecv.c index 3b38b522b1..c46f127099 100644 --- a/src/rtprecv.c +++ b/src/rtprecv.c @@ -179,12 +179,18 @@ static int rtprecv_thread(void *arg) tmr_start(&rx->tmr, 10, rtprecv_check_stop, rx); err = udp_thread_attach(rtp_sock(rx->rtp)); - if (err) + if (err) { + warning("rtp_receiver: could not attach to RTP socket (%m)\n", + err); return err; + } err = udp_thread_attach(rtcp_sock(rx->rtp)); - if (err) + if (err) { + warning("rtp_receiver: could not attach to RTCP socket (%m)\n", + err); return err; + } err = re_main(NULL); @@ -239,7 +245,7 @@ static int handle_rtp(struct rtp_receiver *rx, const struct rtp_header *hdr, size_t ext_len = hdr->x.len*sizeof(uint32_t); if (mb->pos < ext_len) { - warning("stream: corrupt rtp packet," + warning("rtp_receiver: corrupt rtp packet," " not enough space for rtpext of %zu bytes\n", ext_len); return 0; @@ -252,8 +258,8 @@ static int handle_rtp(struct rtp_receiver *rx, const struct rtp_header *hdr, err = rtpext_decode(&extv[i], mb); if (err) { - warning("stream: rtpext_decode failed (%m)\n", - err); + warning("rtp_receiver: rtpext_decode failed " + "(%m)\n", err); return 0; } } From 3ff1e645a14ad91dcb6cec60a6e07b8b41b7154c Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Tue, 28 Nov 2023 16:12:13 +0100 Subject: [PATCH 31/31] aurecv: fix cracking audio on start --- src/aureceiver.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/aureceiver.c b/src/aureceiver.c index 18d5b7134f..7e4fb463aa 100644 --- a/src/aureceiver.c +++ b/src/aureceiver.c @@ -534,7 +534,11 @@ void aur_read(struct audio_recv *ar, struct auframe *af) if (!ar || mtx_trylock(ar->aubuf_mtx) != thrd_success) return; - aubuf_read_auframe(ar->aubuf, af); + if (ar->aubuf) + aubuf_read_auframe(ar->aubuf, af); + else + memset(af->sampv, 0, auframe_size(af)); + mtx_unlock(ar->aubuf_mtx); }