From 9c54e97a88940b03a5c20ed21fc750bbfcd88115 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 1 Dec 2022 08:54:59 -0500 Subject: [PATCH] MT#56008 support encoded-selected clock rates Some codecs (e.g. Opus) can natively encode audio with various clock rates without producing an output that is locked to that clock rate and without requiring resampling the input. Add an appropriate callback function and adapt tests. Change-Id: Id788c4d4c05e20f93cce7e910f9f265b381cbe34 --- daemon/codec.c | 7 +++++- lib/codeclib.c | 49 ++++++++++++++++++++++++++++++++++++++---- lib/codeclib.h | 4 ++++ t/auto-daemon-tests.pl | 32 +++++++++++++-------------- 4 files changed, 71 insertions(+), 21 deletions(-) diff --git a/daemon/codec.c b/daemon/codec.c index b15655bb5..44064a04e 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -3411,6 +3411,11 @@ static struct ssrc_entry *__ssrc_handler_transcode_new(void *p) { ch->sample_buffer = g_string_new(""); ch->bitrate = h->dest_pt.bitrate ? : h->dest_pt.codec_def->default_bitrate; + format_t dec_format = { + .clockrate = h->source_pt.clock_rate, + .channels = h->source_pt.channels, + .format = -1, + }; format_t enc_format = { .clockrate = h->dest_pt.clock_rate, .channels = h->dest_pt.channels, @@ -3421,7 +3426,7 @@ static struct ssrc_entry *__ssrc_handler_transcode_new(void *p) { goto err; if (encoder_config_fmtp(ch->encoder, h->dest_pt.codec_def, ch->bitrate, - ch->ptime, + ch->ptime, &dec_format, &enc_format, &ch->encoder_format, &h->dest_pt.format, &h->dest_pt.format_parameters, &h->dest_pt.codec_opts)) diff --git a/lib/codeclib.c b/lib/codeclib.c index 594b5f9d2..e209a94c1 100644 --- a/lib/codeclib.c +++ b/lib/codeclib.c @@ -37,6 +37,7 @@ static packetizer_f packetizer_amr; static format_init_f opus_init; static set_enc_options_f opus_set_enc_options; +static select_clockrate_f opus_select_enc_clockrate; static format_parse_f ilbc_format_parse; static set_enc_options_f ilbc_set_enc_options; @@ -407,6 +408,7 @@ static codec_def_t __codec_defs[] = { .init = opus_init, .format_cmp = format_cmp_ignore, .set_enc_options = opus_set_enc_options, + .select_enc_clockrate = opus_select_enc_clockrate, .dtx_methods = { [DTX_SILENCE] = &dtx_method_silence, [DTX_CN] = &dtx_method_cn, @@ -1412,11 +1414,12 @@ static const char *avc_encoder_init(encoder_t *enc, const str *extra_opts) { int encoder_config(encoder_t *enc, const codec_def_t *def, int bitrate, int ptime, const format_t *requested_format, format_t *actual_format) { - return encoder_config_fmtp(enc, def, bitrate, ptime, requested_format, actual_format, + return encoder_config_fmtp(enc, def, bitrate, ptime, NULL, requested_format, actual_format, NULL, NULL, NULL); } int encoder_config_fmtp(encoder_t *enc, const codec_def_t *def, int bitrate, int ptime, + const format_t *input_format, const format_t *requested_format_p, format_t *actual_format, struct rtp_codec_format *fmtp, const str *fmtp_string, const str *extra_opts) @@ -1427,13 +1430,21 @@ int encoder_config_fmtp(encoder_t *enc, const codec_def_t *def, int bitrate, int if (!def->codec_type) goto err; - enc->clockrate_fact = def->default_clockrate_fact; + if (def->select_enc_clockrate) + enc->clockrate_fact = def->select_enc_clockrate(requested_format_p, input_format); + else + enc->clockrate_fact = def->default_clockrate_fact; + format_t requested_format = *requested_format_p; requested_format.clockrate = fraction_mult(requested_format.clockrate, &enc->clockrate_fact); // anything to do? - if (G_LIKELY(format_eq(&requested_format, &enc->requested_format))) - goto done; + if (G_LIKELY(format_eq(&requested_format, &enc->requested_format))) { + if (!input_format) + goto done; + if (G_LIKELY(format_eq(input_format, &enc->input_format))) + goto done; + } encoder_close(enc); @@ -1441,6 +1452,10 @@ int encoder_config_fmtp(encoder_t *enc, const codec_def_t *def, int bitrate, int ptime = 20; enc->requested_format = requested_format; + if (input_format) + enc->input_format = *input_format; + else + format_init(&enc->input_format); enc->def = def; enc->ptime = ptime; enc->bitrate = bitrate; @@ -1786,6 +1801,32 @@ static void opus_set_enc_options(encoder_t *enc, const str *codec_opts) { free(s); } +// opus RTP always runs at 48 kHz +static struct fraction opus_select_enc_clockrate(const format_t *req_format, const format_t *f) { + if (req_format->clockrate != 48000) + return (struct fraction) {1,1}; // bail - encoder will fail to initialise + + // check against natively supported rates first + switch (f->clockrate) { + case 48000: + case 24000: + case 16000: + case 12000: + case 8000: + return (struct fraction) {1, 48000 / f->clockrate}; + } + // resample to next best rate + if (f->clockrate > 24000) + return (struct fraction) {1,1}; + if (f->clockrate > 16000) + return (struct fraction) {1,2}; + if (f->clockrate > 12000) + return (struct fraction) {1,3}; + if (f->clockrate > 8000) + return (struct fraction) {1,4}; + return (struct fraction) {1,6}; +} + static int ilbc_format_parse(struct rtp_codec_format *f, const str *fmtp) { if (!str_cmp(fmtp, "mode=20")) f->parsed.ilbc.mode = 20; diff --git a/lib/codeclib.h b/lib/codeclib.h index 8ce87d2df..4249e58f5 100644 --- a/lib/codeclib.h +++ b/lib/codeclib.h @@ -86,6 +86,7 @@ typedef int packetizer_f(AVPacket *, GString *, str *, encoder_t *); typedef void format_init_f(struct rtp_payload_type *); typedef void set_enc_options_f(encoder_t *, const str *); typedef void set_dec_options_f(decoder_t *, const str *); +typedef struct fraction select_clockrate_f(const format_t *requested_format, const format_t *input_format); typedef int format_parse_f(struct rtp_codec_format *, const str *fmtp); typedef void format_answer_f(struct rtp_payload_type *); @@ -174,6 +175,7 @@ struct codec_def_s { format_print_f * const format_print; format_answer_f * const format_answer; packetizer_f * const packetizer; + select_clockrate_f * const select_enc_clockrate; const int bits_per_sample; const enum media_type media_type; const str silence_pattern; @@ -281,6 +283,7 @@ struct decoder_s { struct encoder_s { format_t requested_format, + input_format, actual_format; const codec_def_t *def; @@ -371,6 +374,7 @@ encoder_t *encoder_new(void); int encoder_config(encoder_t *enc, const codec_def_t *def, int bitrate, int ptime, const format_t *requested_format, format_t *actual_format); int encoder_config_fmtp(encoder_t *enc, const codec_def_t *def, int bitrate, int ptime, + const format_t *input_format, const format_t *requested_format, format_t *actual_format, struct rtp_codec_format *fmtp, const str *fmtp_string, const str *codec_opts); void encoder_close(encoder_t *); diff --git a/t/auto-daemon-tests.pl b/t/auto-daemon-tests.pl index 7f92681e4..8f9037ea8 100755 --- a/t/auto-daemon-tests.pl +++ b/t/auto-daemon-tests.pl @@ -1232,9 +1232,9 @@ a=rtcp:PORT SDP snd($sock_a, $port_b, rtp(8, 1000, 3000, 0x1234, $pcma_1)); -Time::HiRes::usleep(20000); # no output, resampling delay +($ssrc) = rcv($sock_b, $port_a, rtpm(96, 1000, 3000, -1, "\x9c\xb5\x45\xde\xb5\x38\xab\x45\x5d\x2d\x35\x87\x19\x3c\x65\xfc\x2a\x06\xd8\xe0\x22\x68\x33\xe8\xaa\x2b\xef\x61\x4e\x2c\x59\xd2\x43\x47\xd4\x2b\xc6\x09\x7b\x1b\xd0\xd2\x84\x60\xa1\xec\x94\x98\x35\x90\x3b\x41\x1b\xc2\xa2\x2c\xbc\xe4\x4e\xc6\x56\x2d\xa1\x86\x7c\xda\x28\xff\x80\x22\x15\xdb\x91\x6c\x72\x40\x28\x3d\xdb\xa5\x00\xb5\xdb\xf4\x2b\x1b\xdd\x5a\x27\xa2\x8c\xcc\xdf\x7e\xdd\x6a\xe0\xe5\x7a\xb2\xcc\x7b\x77\x95\x13\x54\xb5\x60\xdf\xdc\xd7\xcd\x32\x31\xb4\x5f\x31\xd2\x74\x41\xdf\x6f\x52\x2c\x80\x6d\xb6\xde\xdd\xad\x81\xb6\xcb\xad")); snd($sock_a, $port_b, rtp(8, 1001, 3160, 0x1234, $pcma_1)); -rcv($sock_b, $port_a, rtpm(96, 1000, 3000, -1, "\x7c\x87\xfc\xe4\x61\x05\x5f\xd3\x00\xf8\x00\x31\x6d\x5a\x5e\x9d\x87\x3c\x8d\x49\x37\x65\x84\x76\x20\x46\x02\x0e\x26\x89\x32\x8e\x14\xce\x99\xb5\x65\xb6\x42\xba\x76\x83\x50\xa7\xce\x66\x64\x0c\x4f\xfe\x2c\xea\x0a\x64\x9e\xd0\xe1\xd0\x33\x1d\x71\x72\xc3\x59\x87\x5d\x9e\x3e\x37\x12\x29\xc3\x9f\xf7\x86\x78\xe4\x07\x45\x2d\x83\x65")); +rcv($sock_b, $port_a, rtpm(96, 1001, 3960, $ssrc, "\x9c\xaa\xb1\x2b\x6c\x51\xf2\x64\xba\x0f\xdd\xdc\x36\x9b\x81\xaa\x12\xed\xd4\x4b\x09\x7b\x62\xc5\xfd\x79\x95\x6f\x43\xbe\x38\x57\x0a\x24\x08\xa5\x72\x1f\xae\x5a\x15\xdd\x5f\xa7\xe8\x61\x74\x5f\x07\xd1\xbe\x48\x20\x3f\xf9\x53\x7a\xae\x3d\x0a\x36\x8c\x79\x08\x8d\xbc\x37\xe5\x9d\x08\x8c\x4f\x86\x93\x66\xdf\x22\xa8\x7e\x61\xe1\xf5\xad")); @@ -1283,9 +1283,9 @@ a=rtcp:PORT SDP snd($sock_a, $port_b, rtp(8, 1000, 3000, 0x1234, $pcma_1)); -Time::HiRes::usleep(20000); # no output, resampling delay +($ssrc) = rcv($sock_b, $port_a, rtpm(96, 1000, 3000, -1, "\x08\x83\xf8\xa5\xd0\x1c\xfe\x12\x46\x19\xf1\x1c\x8b\xa3\x46\x3f\xe2\x95\xaf\xbc\x1d\x74\x9c\xa4\x2d\x9f\x00\x8b\x94\x31\xda\x52\x5a\x8f\x45\x70\x19\xa2")); snd($sock_a, $port_b, rtp(8, 1001, 3160, 0x1234, $pcma_1)); -rcv($sock_b, $port_a, rtpm(96, 1000, 3000, -1, "\x78\x83\xcb\x0a\x56\x49\x82\x8c\x01\xdb\xcf\x62\x02\x71\x67\x4d\x70\x34\xd8\x3c\x34\xda\x8e\xb1\x16\xfb\x52\xb8\xc2\x23\xa2\x72\xf9\x65\x9e\x3b\x71\x44\xb7\x09\xe3\x3a\xa8\x30\xcf\x28\xb2\xb5\x4e\x67\x07\xab\x02\x98\x3c\x51\xd7\xd7\x52\xe8\x50\x91\xba\x0c\x6f\xd0")); +rcv($sock_b, $port_a, rtpm(96, 1001, 3960, $ssrc, "\x08\xb7\x46\xf0\xe6\xab\xd0\x63\xd8\x86\x62\x55\x90\x2b\xe5\x51\xe3\xac\x70\x2a\x95\x8c\x3e\xe5\x46")); @@ -1335,9 +1335,9 @@ a=rtcp:PORT SDP snd($sock_a, $port_b, rtp(8, 1000, 3000, 0x1234, $pcma_1)); -Time::HiRes::usleep(20000); # no output, resampling delay +($ssrc) = rcv($sock_b, $port_a, rtpm(96, 1000, 3000, -1, "\x9c\x7b\x19\x8d\xf7\x3c\x6e\x75\xaa\x82\x29\x26\x03\x17\xc3\x58\xb0\xc6\x75\xdb\x04\x80\x15\x29\x0c\x75\xf9\x9e\xc2\x64\xd9\xa0\x60\x57\x34\x87\x48\xe3\xe0\x80\xda\xcf\x7e\x5c\x08\x66\xdd\xc0\x8a\xf3\x39\x88\xbd\xef\xe4\xf0\x70\x4a\xfe\xe9\x67\x1a\xae\x9a\xa1\xa9\x8e\xa1\x25\x39\x93\x08\xef\x82\x18\x08\xb4\x24\x2d\xaf\x97\x35\x4b\xa4\x2a\xae\x5a\x4f\xe3\xfb\xd3\xa6\x65\x59\x38\x4e\x70\xf0\x75\x7c\x08\xd1\x1d\x3a\x16\x21\x07\x9b\xd8\xa5\x3d\x22\x81\xe5\xb7\x0e\xaa\x39\x68\xad\xdd\x78\x7a\xed\x5e\x89\x75\xfd\x6f\x69\x3f\x03\xc2\xbd\x26\x6a\xaf")); snd($sock_a, $port_b, rtp(8, 1001, 3160, 0x1234, $pcma_1)); -rcv($sock_b, $port_a, rtpm(96, 1000, 3000, -1, "\xfc\x7b\x19\x8d\xf7\x3c\x6e\x75\xaa\x82\x27\x2e\xe1\x8c\x32\xef\xdb\xc4\xdc\xf3\x94\x18\x84\xa9\xe0\xb3\xc3\xec\xae\x0f\x4a\x2e\x81\x0e\xd6\xbc\x8a\x54\x7e\x66\xd8\xa1\x7a\x06\x8e\x43\x7b\x4e\xf0\xe4\x13\x82\xec\xb7\xc2\xe0\x5a\x1d\x6b\x8d\x8b\xcb\x9d\x3c\x88\xdb\xb1\x8e\x1f\xa0\x15\xb2\xe5\x36\x50\x48\x52\x34\xa3\x6a\xd5\xd3\xbf\xb5\xd1\x16\x09\xc2\x90\x6b\x1d\x8a\xfd\xae\xe5\xbc\x35\xdd\x74\x44\x55\x31\x19\xd9\x09\x53\xe7\xbd\x96\x84\xd6\x8e\x0c\x21\x4b\x02\x58\xff\x4d\x99\x87\xa5\xcd\x29\xd6\x41\x58\x6c\x4a\x0c\xd2\x17\x5c\x0c\x23\x17\x41\x91\xbd\xa4\x00\x5f\x5f\xf0\xcf\x1b\xb7")); +rcv($sock_b, $port_a, rtpm(96, 1001, 3960, $ssrc, "\x9c\x65\xd7\x89\x49\x43\x59\x41\x1c\x37\xf0\x8a\x86\x0f\xbc\x21\x1c\xc5\x36\xa6\xf7\x86\xb3\xe3\x8d\x2d\x1d\x93\x65\x15\x22\xb3\x0b\xd2\xee\x36\xa7\x04\x18\x2c\x72\x16\x7d\x8a\xa7\x02\x2d\xee\xd9\xf7\x14\x40\x78\x60\x54\x33\x1b\x7b\xbb\x09\xcc\x08\xea\x61\x9f\x2e\x92\x86\x6e\x61\x04\x0d\x1f\x24\xb3\x9e\x15\xd8\x9d\x73\xcb\x85\x8f\x9e\x63\x22\xf6\x62\xfe\xed\x50\xff\xc0\x5a\xd8\x9f")); ($sock_a, $sock_b) = new_call([qw(198.51.100.16 6012)], [qw(198.51.100.16 6014)]); @@ -1385,9 +1385,9 @@ a=rtcp:PORT SDP snd($sock_a, $port_b, rtp(8, 1000, 3000, 0x1234, $pcma_1)); -Time::HiRes::usleep(20000); # no output, resampling delay +($ssrc) = rcv($sock_b, $port_a, rtpm(96, 1000, 3000, -1, "\x08\x83\x9c\x5e\xdd\x07\x1e\x3c\xdf\xb6\xd6\x1e\xac\x5f\xb8\x27\x26\xc6\xf3\xa3\xef\xab\x0c\x2b\xce\x35\x08\xe8\x52\x55\xb9\x73\xf2\xeb\xc2")); snd($sock_a, $port_b, rtp(8, 1001, 3160, 0x1234, $pcma_1)); -rcv($sock_b, $port_a, rtpm(96, 1000, 3000, -1, "\x78\x83\x9c\xd1\x69\xef\xe5\xc1\x48\x01\x46\xb2\x49\xbb\xad\x3d\xe5\xd4\x69\x75\x3e\x0f\x10\x9a\xad\xb4\x43\x86\x69\x32\x22\xed\x13\x7a\x9b\x23\x34\x93\xd6\x34\x25\xa4\x09\x9c\x87\x78\x4f\xee\xa6\x07\x04\x6c\x6f\x3b\xfa\x56\x06\x95\xcd\xe8\x1a\x0c\x6f\xd0")); +rcv($sock_b, $port_a, rtpm(96, 1001, 3960, $ssrc, "\x08\xb6\x61\x7f\x42\xc4\x86\x2d\x41\xf4\x0c\x90\xf5\xa4\x82\x27\xee\x44\x85\xe1\x7b\x3a\x8f")); @@ -1436,9 +1436,9 @@ a=rtcp:PORT SDP snd($sock_b, $port_a, rtp(8, 1000, 3000, 0x1234, $pcma_1)); -Time::HiRes::usleep(20000); # no output, resampling delay +($ssrc) = rcv($sock_a, $port_b, rtpm(96, 1000, 3000, -1, "\x9c\xb5\x45\xde\xb5\x38\xab\x45\x5d\x2d\x35\x87\x19\x3c\x65\xfc\x2a\x06\xd8\xe0\x22\x68\x33\xe8\xaa\x2b\xef\x61\x4e\x2c\x59\xd2\x43\x47\xd4\x2b\xc6\x09\x7b\x1b\xd0\xd2\x84\x60\xa1\xec\x94\x98\x35\x90\x3b\x41\x1b\xc2\xa2\x2c\xbc\xe4\x4e\xc6\x56\x2d\xa1\x86\x7c\xda\x28\xff\x80\x22\x15\xdb\x91\x6c\x72\x40\x28\x3d\xdb\xa5\x00\xb5\xdb\xf4\x2b\x1b\xdd\x5a\x27\xa2\x8c\xcc\xdf\x7e\xdd\x6a\xe0\xe5\x7a\xb2\xcc\x7b\x77\x95\x13\x54\xb5\x60\xdf\xdc\xd7\xcd\x32\x31\xb4\x5f\x31\xd2\x74\x41\xdf\x6f\x52\x2c\x80\x6d\xb6\xde\xdd\xad\x81\xb6\xcb\xad")); snd($sock_b, $port_a, rtp(8, 1001, 3160, 0x1234, $pcma_1)); -rcv($sock_a, $port_b, rtpm(96, 1000, 3000, -1, "\x7c\x87\xfc\xe4\x61\x05\x5f\xd3\x00\xf8\x00\x31\x6d\x5a\x5e\x9d\x87\x3c\x8d\x49\x37\x65\x84\x76\x20\x46\x02\x0e\x26\x89\x32\x8e\x14\xce\x99\xb5\x65\xb6\x42\xba\x76\x83\x50\xa7\xce\x66\x64\x0c\x4f\xfe\x2c\xea\x0a\x64\x9e\xd0\xe1\xd0\x33\x1d\x71\x72\xc3\x59\x87\x5d\x9e\x3e\x37\x12\x29\xc3\x9f\xf7\x86\x78\xe4\x07\x45\x2d\x83\x65")); +rcv($sock_a, $port_b, rtpm(96, 1001, 3960, $ssrc, "\x9c\xaa\xb1\x2b\x6c\x51\xf2\x64\xba\x0f\xdd\xdc\x36\x9b\x81\xaa\x12\xed\xd4\x4b\x09\x7b\x62\xc5\xfd\x79\x95\x6f\x43\xbe\x38\x57\x0a\x24\x08\xa5\x72\x1f\xae\x5a\x15\xdd\x5f\xa7\xe8\x61\x74\x5f\x07\xd1\xbe\x48\x20\x3f\xf9\x53\x7a\xae\x3d\x0a\x36\x8c\x79\x08\x8d\xbc\x37\xe5\x9d\x08\x8c\x4f\x86\x93\x66\xdf\x22\xa8\x7e\x61\xe1\xf5\xad")); @@ -1487,9 +1487,9 @@ a=rtcp:PORT SDP snd($sock_b, $port_a, rtp(8, 1000, 3000, 0x1234, $pcma_1)); -Time::HiRes::usleep(20000); # no output, resampling delay +($ssrc) = rcv($sock_a, $port_b, rtpm(96, 1000, 3000, -1, "\x08\x83\xf8\xa5\xd0\x1c\xfe\x12\x46\x19\xf1\x1c\x8b\xa3\x46\x3f\xe2\x95\xaf\xbc\x1d\x74\x9c\xa4\x2d\x9f\x00\x8b\x94\x31\xda\x52\x5a\x8f\x45\x70\x19\xa2")); snd($sock_b, $port_a, rtp(8, 1001, 3160, 0x1234, $pcma_1)); -rcv($sock_a, $port_b, rtpm(96, 1000, 3000, -1, "\x78\x83\xcb\x0a\x56\x49\x82\x8c\x01\xdb\xcf\x62\x02\x71\x67\x4d\x70\x34\xd8\x3c\x34\xda\x8e\xb1\x16\xfb\x52\xb8\xc2\x23\xa2\x72\xf9\x65\x9e\x3b\x71\x44\xb7\x09\xe3\x3a\xa8\x30\xcf\x28\xb2\xb5\x4e\x67\x07\xab\x02\x98\x3c\x51\xd7\xd7\x52\xe8\x50\x91\xba\x0c\x6f\xd0")); +rcv($sock_a, $port_b, rtpm(96, 1001, 3960, $ssrc, "\x08\xb7\x46\xf0\xe6\xab\xd0\x63\xd8\x86\x62\x55\x90\x2b\xe5\x51\xe3\xac\x70\x2a\x95\x8c\x3e\xe5\x46")); @@ -1538,9 +1538,9 @@ a=rtcp:PORT SDP snd($sock_b, $port_a, rtp(8, 1000, 3000, 0x1234, $pcma_1)); -Time::HiRes::usleep(20000); # no output, resampling delay +($ssrc) = rcv($sock_a, $port_b, rtpm(96, 1000, 3000, -1, "\x9c\x7b\x19\x8d\xf7\x3c\x6e\x75\xaa\x82\x29\x26\x03\x17\xc3\x58\xb0\xc6\x75\xdb\x04\x80\x15\x29\x0c\x75\xf9\x9e\xc2\x64\xd9\xa0\x60\x57\x34\x87\x48\xe3\xe0\x80\xda\xcf\x7e\x5c\x08\x66\xdd\xc0\x8a\xf3\x39\x88\xbd\xef\xe4\xf0\x70\x4a\xfe\xe9\x67\x1a\xae\x9a\xa1\xa9\x8e\xa1\x25\x39\x93\x08\xef\x82\x18\x08\xb4\x24\x2d\xaf\x97\x35\x4b\xa4\x2a\xae\x5a\x4f\xe3\xfb\xd3\xa6\x65\x59\x38\x4e\x70\xf0\x75\x7c\x08\xd1\x1d\x3a\x16\x21\x07\x9b\xd8\xa5\x3d\x22\x81\xe5\xb7\x0e\xaa\x39\x68\xad\xdd\x78\x7a\xed\x5e\x89\x75\xfd\x6f\x69\x3f\x03\xc2\xbd\x26\x6a\xaf")); snd($sock_b, $port_a, rtp(8, 1001, 3160, 0x1234, $pcma_1)); -rcv($sock_a, $port_b, rtpm(96, 1000, 3000, -1, "\xfc\x7b\x19\x8d\xf7\x3c\x6e\x75\xaa\x82\x27\x2e\xe1\x8c\x32\xef\xdb\xc4\xdc\xf3\x94\x18\x84\xa9\xe0\xb3\xc3\xec\xae\x0f\x4a\x2e\x81\x0e\xd6\xbc\x8a\x54\x7e\x66\xd8\xa1\x7a\x06\x8e\x43\x7b\x4e\xf0\xe4\x13\x82\xec\xb7\xc2\xe0\x5a\x1d\x6b\x8d\x8b\xcb\x9d\x3c\x88\xdb\xb1\x8e\x1f\xa0\x15\xb2\xe5\x36\x50\x48\x52\x34\xa3\x6a\xd5\xd3\xbf\xb5\xd1\x16\x09\xc2\x90\x6b\x1d\x8a\xfd\xae\xe5\xbc\x35\xdd\x74\x44\x55\x31\x19\xd9\x09\x53\xe7\xbd\x96\x84\xd6\x8e\x0c\x21\x4b\x02\x58\xff\x4d\x99\x87\xa5\xcd\x29\xd6\x41\x58\x6c\x4a\x0c\xd2\x17\x5c\x0c\x23\x17\x41\x91\xbd\xa4\x00\x5f\x5f\xf0\xcf\x1b\xb7")); +rcv($sock_a, $port_b, rtpm(96, 1001, 3960, $ssrc, "\x9c\x65\xd7\x89\x49\x43\x59\x41\x1c\x37\xf0\x8a\x86\x0f\xbc\x21\x1c\xc5\x36\xa6\xf7\x86\xb3\xe3\x8d\x2d\x1d\x93\x65\x15\x22\xb3\x0b\xd2\xee\x36\xa7\x04\x18\x2c\x72\x16\x7d\x8a\xa7\x02\x2d\xee\xd9\xf7\x14\x40\x78\x60\x54\x33\x1b\x7b\xbb\x09\xcc\x08\xea\x61\x9f\x2e\x92\x86\x6e\x61\x04\x0d\x1f\x24\xb3\x9e\x15\xd8\x9d\x73\xcb\x85\x8f\x9e\x63\x22\xf6\x62\xfe\xed\x50\xff\xc0\x5a\xd8\x9f")); @@ -1589,9 +1589,9 @@ a=rtcp:PORT SDP snd($sock_b, $port_a, rtp(8, 1000, 3000, 0x1234, $pcma_1)); -Time::HiRes::usleep(20000); # no output, resampling delay +($ssrc) = rcv($sock_a, $port_b, rtpm(96, 1000, 3000, -1, "\x08\x83\x9c\x5e\xdd\x07\x1e\x3c\xdf\xb6\xd6\x1e\xac\x5f\xb8\x27\x26\xc6\xf3\xa3\xef\xab\x0c\x2b\xce\x35\x08\xe8\x52\x55\xb9\x73\xf2\xeb\xc2")); snd($sock_b, $port_a, rtp(8, 1001, 3160, 0x1234, $pcma_1)); -rcv($sock_a, $port_b, rtpm(96, 1000, 3000, -1, "\x78\x83\x9c\xd1\x69\xef\xe5\xc1\x48\x01\x46\xb2\x49\xbb\xad\x3d\xe5\xd4\x69\x75\x3e\x0f\x10\x9a\xad\xb4\x43\x86\x69\x32\x22\xed\x13\x7a\x9b\x23\x34\x93\xd6\x34\x25\xa4\x09\x9c\x87\x78\x4f\xee\xa6\x07\x04\x6c\x6f\x3b\xfa\x56\x06\x95\xcd\xe8\x1a\x0c\x6f\xd0")); +rcv($sock_a, $port_b, rtpm(96, 1001, 3960, $ssrc, "\x08\xb6\x61\x7f\x42\xc4\x86\x2d\x41\xf4\x0c\x90\xf5\xa4\x82\x27\xee\x44\x85\xe1\x7b\x3a\x8f")); }