Pau Espin Pedrol has submitted this change and it was merged.

Change subject: osmux: Add RTP marker bit support
......................................................................


osmux: Add RTP marker bit support

According to RFC4867 (RTP payload format for AMR):
"The RTP header marker bit (M) SHALL be set to 1 if the first frameblock
carried in the packet contains a speech frame which is the first in a
talkspurt.  For all other packets the marker bit SHALL be set to zero (M=0)."

This information bit provides a way for the receiver to better
synchronize the delay with ther sender.

This is specially useful if AMR DTX features are supported and
enabled on the sender.

Change-Id: I0315658159429603f1d80a168718b026015060e9
---
M include/osmocom/netif/osmux.h
M src/osmux.c
M tests/osmux/osmux_test.c
3 files changed, 83 insertions(+), 7 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/include/osmocom/netif/osmux.h b/include/osmocom/netif/osmux.h
index 1d93aa0..5283059 100644
--- a/include/osmocom/netif/osmux.h
+++ b/include/osmocom/netif/osmux.h
@@ -13,7 +13,8 @@
 
 /* OSmux header:
  *
- *     ft (3 bits):            0=signalling, 1=voice, 2=dummy
+ *     rtp_m (1 bit):          RTP M field (RFC3550, RFC4867)
+ *     ft (2 bits):            0=signalling, 1=voice, 2=dummy
  *     ctr (3 bits):           Number of batched AMR payloads (starting 0)
  *     amr_f (1 bit):          AMR F field (RFC3267)
  *     amr_q (1 bit):          AMR Q field (RFC3267)
@@ -29,7 +30,8 @@
 
 struct osmux_hdr {
 #if OSMO_IS_BIG_ENDIAN
-       uint8_t ft:3,
+       uint8_t rtp_m:1,
+               ft:2,
                ctr:3,
                amr_f:1,
                amr_q:1;
@@ -37,7 +39,8 @@
        uint8_t amr_q:1,
                amr_f:1,
                ctr:3,
-               ft:3;
+               ft:2,
+               rtp_m:1;
 #endif
        uint8_t seq;
 #define OSMUX_CID_MAX          255     /* determined by circuit_id */
diff --git a/src/osmux.c b/src/osmux.c
index 1dcd04f..4d12427 100644
--- a/src/osmux.c
+++ b/src/osmux.c
@@ -105,8 +105,8 @@
 }
 
 static struct msgb *
-osmux_rebuild_rtp(struct osmux_out_handle *h,
-                 struct osmux_hdr *osmuxh, void *payload, int payload_len)
+osmux_rebuild_rtp(struct osmux_out_handle *h, struct osmux_hdr *osmuxh,
+                 void *payload, int payload_len, bool first_pkt)
 {
        struct msgb *out_msg;
        struct rtp_hdr *rtph;
@@ -129,6 +129,8 @@
        rtph->timestamp = htonl(h->rtp_timestamp);
        rtph->sequence = htons(h->rtp_seq);
        rtph->ssrc = htonl(h->rtp_ssrc);
+       /* rtp packet with the marker bit is always warranted to be the first 
one */
+       rtph->marker = first_pkt && osmuxh->rtp_m;
 
        msgb_put(out_msg, sizeof(struct rtp_hdr));
 
@@ -166,7 +168,7 @@
                msg = osmux_rebuild_rtp(h, osmuxh,
                                        osmux_get_payload(osmuxh) +
                                        i * osmo_amr_bytes(osmuxh->amr_ft),
-                                       osmo_amr_bytes(osmuxh->amr_ft));
+                                       osmo_amr_bytes(osmuxh->amr_ft), !i);
                if (msg == NULL)
                        continue;
 
@@ -264,6 +266,7 @@
                osmuxh = (struct osmux_hdr *)state->out_msg->tail;
                osmuxh->ft = OSMUX_FT_VOICE_AMR;
                osmuxh->ctr = 0;
+               osmuxh->rtp_m = osmuxh->rtp_m || state->rtph->marker;
                osmuxh->amr_f = state->amrh->f;
                osmuxh->amr_q= state->amrh->q;
                osmuxh->seq = batch->seq++;
@@ -593,6 +596,13 @@
        if (bytes > batch->remaining_bytes)
                return 1;
 
+       /* Init of talkspurt (RTP M marker bit) needs to be in the first AMR 
slot
+        * of the OSMUX packet, enforce sending previous batch if required:
+        */
+       if (rtph->marker && circuit->nmsgs != 0)
+               return 1;
+
+
        /* Extra validation: check if this message already exists, should not
         * happen but make sure we don't propagate duplicated messages.
         */
diff --git a/tests/osmux/osmux_test.c b/tests/osmux/osmux_test.c
index 2f5a6cd..9941ce3 100644
--- a/tests/osmux/osmux_test.c
+++ b/tests/osmux/osmux_test.c
@@ -55,6 +55,7 @@
 };
 
 static int rtp_pkts;
+static int mark_pkts;
 #if OSMUX_TEST_USE_TIMING
 static struct timeval last;
 #endif
@@ -62,6 +63,7 @@
 static void tx_cb(struct msgb *msg, void *data)
 {
        char buf[4096];
+       struct rtp_hdr *rtph = (struct rtp_hdr *)msg->data;
 #if OSMUX_TEST_USE_TIMING
        struct timeval now, diff;
 
@@ -87,6 +89,8 @@
                exit(EXIT_FAILURE);
        }
 
+       if (rtph->marker)
+               mark_pkts--;
        rtp_pkts--;
        msgb_free(msg);
 }
@@ -122,6 +126,48 @@
 {
        printf("FAIL: test did not run successfully\n");
        exit(EXIT_FAILURE);
+}
+
+static void osmux_test_marker(int ccid) {
+       struct msgb *msg;
+       struct rtp_hdr *rtph = (struct rtp_hdr *)rtp_pkt;
+       struct rtp_hdr *cpy_rtph;
+       uint16_t seq;
+       int i, j;
+
+       for (i = 0; i < 64; i++) {
+
+               seq = ntohs(rtph->sequence);
+               seq++;
+               rtph->sequence = htons(seq);
+
+               for (j=0; j<4; j++) {
+                       msg = msgb_alloc(1500, "test");
+                       if (!msg)
+                               exit(EXIT_FAILURE);
+
+                       memcpy(msg->data, rtp_pkt, sizeof(rtp_pkt));
+                       cpy_rtph = (struct rtp_hdr *) msgb_put(msg, 
sizeof(rtp_pkt));
+
+                       if ((i+j) % 7 == 0) {
+                               cpy_rtph->marker = 1;
+                               mark_pkts++;
+                       }
+
+                       rtp_pkts++;
+                       while (osmux_xfrm_input(&h_input, msg, j + ccid) > 0) {
+                               osmux_xfrm_input_deliver(&h_input);
+                       }
+               }
+       }
+
+       while (rtp_pkts)
+               osmo_select_main(0);
+
+       if (mark_pkts) {
+               fprintf(stdout, "RTP M bit (marker) mismatch! %d\n", mark_pkts);
+               exit(EXIT_FAILURE);
+       }
 }
 
 static void osmux_test_loop(int ccid)
@@ -177,6 +223,11 @@
                        k = 0;
                }
        }
+
+       if (mark_pkts) {
+               fprintf(stdout, "RTP M bit (marker) mismatch! %d\n", mark_pkts);
+               exit(EXIT_FAILURE);
+       }
 }
 
 int main(void)
@@ -192,12 +243,24 @@
        osmo_init_logging(&osmux_test_log_info);
        log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
 
-       osmux_xfrm_input_init(&h_input);
        osmux_xfrm_output_init(&h_output, 0x7000000);
 
        /* If the test takes longer than 10 seconds, abort it */
        alarm(10);
 
+#if !OSMUX_TEST_USE_TIMING
+       /* Check if marker bit features work correctly */
+       osmux_xfrm_input_init(&h_input);
+       for (i = 0; i < 4; i++)
+               osmux_xfrm_input_open_circuit(&h_input, i, 0);
+       osmux_test_marker(0);
+       for (i = 0; i < 4; i++)
+               osmux_xfrm_input_close_circuit(&h_input, i);
+       osmux_xfrm_input_fini(&h_input);
+#endif
+
+       osmux_xfrm_input_init(&h_input);
+
        for (i = 0; i < 2; i++)
                osmux_xfrm_input_open_circuit(&h_input, i, 0);
 

-- 
To view, visit https://gerrit.osmocom.org/2407
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I0315658159429603f1d80a168718b026015060e9
Gerrit-PatchSet: 4
Gerrit-Project: libosmo-netif
Gerrit-Branch: master
Gerrit-Owner: Pau Espin Pedrol <pes...@sysmocom.de>
Gerrit-Reviewer: Harald Welte <lafo...@gnumonks.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Max <msur...@sysmocom.de>
Gerrit-Reviewer: Neels Hofmeyr <nhofm...@sysmocom.de>
Gerrit-Reviewer: Pau Espin Pedrol <pes...@sysmocom.de>
Gerrit-Reviewer: daniel <dwillm...@sysmocom.de>

Reply via email to