MT#56008 switch to fractional clock rate factor

Instead of just having an integer multiplier, support a fractional
factor. This allows us to have the RTP clock rate run faster than the
audio clock rate, and not just slower by an integer factor.

Change-Id: I7681cf369c43d8424ca2d2ebeffe932595d271ec
pull/1579/head
Richard Fuchs 2 years ago
parent afb42551c4
commit f976f21d49

@ -1899,7 +1899,7 @@ static int codec_add_dtmf_packet(struct codec_ssrc_handler *ch, struct codec_ssr
ch->last_dtmf_event_ts = 0; // last DTMF event duration ch->last_dtmf_event_ts = 0; // last DTMF event duration
} }
unsigned long ts = output_ch->encoder->next_pts / output_ch->encoder->def->clockrate_mult; unsigned long ts = fraction_divl(output_ch->encoder->next_pts, &output_ch->encoder->def->clockrate_fact);
// roll back TS to start of event // roll back TS to start of event
ts -= ch->last_dtmf_event_ts; ts -= ch->last_dtmf_event_ts;
// adjust to output RTP TS // adjust to output RTP TS
@ -1924,8 +1924,8 @@ static int codec_add_dtmf_packet(struct codec_ssrc_handler *ch, struct codec_ssr
ts_delay = duration - ch->dtmf_first_duration; ts_delay = duration - ch->dtmf_first_duration;
// shift forward our output RTP TS // shift forward our output RTP TS
output_ch->encoder->next_pts = (ts + duration) * output_ch->encoder->def->clockrate_mult; output_ch->encoder->next_pts = fraction_multl(ts + duration, &output_ch->encoder->def->clockrate_fact);
output_ch->encoder->packet_pts += (duration - ch->last_dtmf_event_ts) * output_ch->encoder->def->clockrate_mult; output_ch->encoder->packet_pts += fraction_multl(duration - ch->last_dtmf_event_ts, &output_ch->encoder->def->clockrate_fact);
ch->last_dtmf_event_ts = duration; ch->last_dtmf_event_ts = duration;
} }
payload_type = h->dtmf_payload_type; payload_type = h->dtmf_payload_type;
@ -3412,7 +3412,7 @@ static struct ssrc_entry *__ssrc_handler_transcode_new(void *p) {
ch->bitrate = h->dest_pt.bitrate ? : h->dest_pt.codec_def->default_bitrate; ch->bitrate = h->dest_pt.bitrate ? : h->dest_pt.codec_def->default_bitrate;
format_t enc_format = { format_t enc_format = {
.clockrate = h->dest_pt.clock_rate * h->dest_pt.codec_def->clockrate_mult, .clockrate = fraction_mult(h->dest_pt.clock_rate, &h->dest_pt.codec_def->clockrate_fact),
.channels = h->dest_pt.channels, .channels = h->dest_pt.channels,
.format = -1, .format = -1,
}; };
@ -3569,7 +3569,7 @@ static int packet_encoded_rtp(encoder_t *enc, void *u1, void *u2) {
memcpy(send_buf, buf, pkt_len); memcpy(send_buf, buf, pkt_len);
} }
__output_rtp(mp, ch, ch->handler, send_buf, inout.len, ch->first_ts __output_rtp(mp, ch, ch->handler, send_buf, inout.len, ch->first_ts
+ enc->avpkt->pts / enc->def->clockrate_mult, + fraction_divl(enc->avpkt->pts, &enc->def->clockrate_fact),
ch->rtp_mark ? 1 : 0, -1, 0, ch->rtp_mark ? 1 : 0, -1, 0,
payload_type, 0); payload_type, 0);
mp->ssrc_out->parent->seq_diff++; mp->ssrc_out->parent->seq_diff++;

@ -306,7 +306,7 @@ found:
// that has passed // that has passed
if (mp->sync_ts_tv.tv_sec) { if (mp->sync_ts_tv.tv_sec) {
long long ts_diff_us = timeval_diff(&rtpe_now, &mp->sync_ts_tv); long long ts_diff_us = timeval_diff(&rtpe_now, &mp->sync_ts_tv);
mp->sync_ts += ts_diff_us * dst_pt->clock_rate / 1000000 / dst_pt->codec_def->clockrate_mult; mp->sync_ts += fraction_divl(ts_diff_us * dst_pt->clock_rate / 1000000, &dst_pt->codec_def->clockrate_fact);
} }
// if we already have a handler, see if anything needs changing // if we already have a handler, see if anything needs changing

@ -212,7 +212,6 @@ static codec_def_t __codec_defs[] = {
{ {
.rtpname = "PCMA", .rtpname = "PCMA",
.avcodec_id = AV_CODEC_ID_PCM_ALAW, .avcodec_id = AV_CODEC_ID_PCM_ALAW,
.clockrate_mult = 1,
.default_clockrate = 8000, .default_clockrate = 8000,
.default_channels = 1, .default_channels = 1,
.default_ptime = 20, .default_ptime = 20,
@ -229,7 +228,6 @@ static codec_def_t __codec_defs[] = {
{ {
.rtpname = "PCMU", .rtpname = "PCMU",
.avcodec_id = AV_CODEC_ID_PCM_MULAW, .avcodec_id = AV_CODEC_ID_PCM_MULAW,
.clockrate_mult = 1,
.default_clockrate = 8000, .default_clockrate = 8000,
.default_channels = 1, .default_channels = 1,
.default_ptime = 20, .default_ptime = 20,
@ -246,7 +244,6 @@ static codec_def_t __codec_defs[] = {
{ {
.rtpname = "G723", .rtpname = "G723",
.avcodec_id = AV_CODEC_ID_G723_1, .avcodec_id = AV_CODEC_ID_G723_1,
.clockrate_mult = 1,
.default_clockrate = 8000, .default_clockrate = 8000,
.default_channels = 1, .default_channels = 1,
.default_ptime = 30, .default_ptime = 30,
@ -262,7 +259,7 @@ static codec_def_t __codec_defs[] = {
{ {
.rtpname = "G722", .rtpname = "G722",
.avcodec_id = AV_CODEC_ID_ADPCM_G722, .avcodec_id = AV_CODEC_ID_ADPCM_G722,
.clockrate_mult = 2, .clockrate_fact = {2,1},
.default_clockrate = 8000, .default_clockrate = 8000,
.default_channels = 1, .default_channels = 1,
.default_ptime = 20, .default_ptime = 20,
@ -279,7 +276,6 @@ static codec_def_t __codec_defs[] = {
{ {
.rtpname = "QCELP", .rtpname = "QCELP",
.avcodec_id = AV_CODEC_ID_QCELP, .avcodec_id = AV_CODEC_ID_QCELP,
.clockrate_mult = 1,
.default_ptime = 20, .default_ptime = 20,
.packetizer = packetizer_passthrough, .packetizer = packetizer_passthrough,
.media_type = MT_AUDIO, .media_type = MT_AUDIO,
@ -293,7 +289,6 @@ static codec_def_t __codec_defs[] = {
{ {
.rtpname = "G729", .rtpname = "G729",
.avcodec_id = AV_CODEC_ID_G729, .avcodec_id = AV_CODEC_ID_G729,
.clockrate_mult = 1,
.default_clockrate = 8000, .default_clockrate = 8000,
.default_channels = 1, .default_channels = 1,
.default_ptime = 20, .default_ptime = 20,
@ -308,7 +303,6 @@ static codec_def_t __codec_defs[] = {
{ {
.rtpname = "G729a", .rtpname = "G729a",
.avcodec_id = AV_CODEC_ID_G729, .avcodec_id = AV_CODEC_ID_G729,
.clockrate_mult = 1,
.default_clockrate = 8000, .default_clockrate = 8000,
.default_channels = 1, .default_channels = 1,
.default_ptime = 20, .default_ptime = 20,
@ -324,7 +318,6 @@ static codec_def_t __codec_defs[] = {
{ {
.rtpname = "G729", .rtpname = "G729",
.avcodec_id = -1, .avcodec_id = -1,
.clockrate_mult = 1,
.default_clockrate = 8000, .default_clockrate = 8000,
.default_channels = 1, .default_channels = 1,
.default_ptime = 20, .default_ptime = 20,
@ -341,7 +334,6 @@ static codec_def_t __codec_defs[] = {
{ {
.rtpname = "G729a", .rtpname = "G729a",
.avcodec_id = -1, .avcodec_id = -1,
.clockrate_mult = 1,
.default_clockrate = 8000, .default_clockrate = 8000,
.default_channels = 1, .default_channels = 1,
.default_ptime = 20, .default_ptime = 20,
@ -423,7 +415,7 @@ static codec_def_t __codec_defs[] = {
{ {
.rtpname = "EVS", .rtpname = "EVS",
.avcodec_id = -1, .avcodec_id = -1,
.clockrate_mult = 3, .clockrate_fact = {3,1},
.default_clockrate = 16000, .default_clockrate = 16000,
.default_channels = 1, .default_channels = 1,
.default_ptime = 20, .default_ptime = 20,
@ -757,7 +749,7 @@ decoder_t *decoder_new_fmtp(const codec_def_t *def, int clockrate, int channels,
if (!def->codec_type) if (!def->codec_type)
goto err; goto err;
clockrate *= def->clockrate_mult; clockrate = fraction_mult(clockrate, &def->clockrate_fact);
ret = g_slice_alloc0(sizeof(*ret)); ret = g_slice_alloc0(sizeof(*ret));
@ -984,7 +976,7 @@ static int __decoder_input_data(decoder_t *dec, const str *data, unsigned long t
if (!data && (!dec->dtx.do_dtx || !ptime)) if (!data && (!dec->dtx.do_dtx || !ptime))
return 0; return 0;
ts *= dec->def->clockrate_mult; ts = fraction_mult(ts, &dec->def->clockrate_fact);
cdbg("%p dec pts %llu rtp_ts %llu incoming ts %lu", dec, (unsigned long long) dec->pts, cdbg("%p dec pts %llu rtp_ts %llu incoming ts %lu", dec, (unsigned long long) dec->pts,
(unsigned long long) dec->rtp_ts, (unsigned long) ts); (unsigned long long) dec->rtp_ts, (unsigned long) ts);
@ -1144,8 +1136,10 @@ void codeclib_init(int print) {
} }
// init undefined member vars // init undefined member vars
if (!def->clockrate_mult) if (!def->clockrate_fact.mult)
def->clockrate_mult = 1; def->clockrate_fact.mult = 1;
if (!def->clockrate_fact.div)
def->clockrate_fact.div = 1;
if (!def->default_ptime) if (!def->default_ptime)
def->default_ptime = -1; def->default_ptime = -1;
if (!def->default_clockrate) if (!def->default_clockrate)
@ -1444,7 +1438,7 @@ int encoder_config_fmtp(encoder_t *enc, const codec_def_t *def, int bitrate, int
enc->requested_format = *requested_format; enc->requested_format = *requested_format;
enc->def = def; enc->def = def;
enc->ptime = ptime / def->clockrate_mult; enc->ptime = fraction_div(ptime, &def->clockrate_fact);
enc->bitrate = bitrate; enc->bitrate = bitrate;
err = "failed to parse \"fmtp\""; err = "failed to parse \"fmtp\"";
@ -1679,7 +1673,7 @@ static int packetizer_samplestream(AVPacket *pkt, GString *buf, str *input_outpu
g_string_append_len(buf, (char *) pkt->data + input_output->len, g_string_append_len(buf, (char *) pkt->data + input_output->len,
pkt->size - input_output->len); pkt->size - input_output->len);
enc->packet_pts = pkt->pts + input_output->len enc->packet_pts = pkt->pts + input_output->len
* (enc->def->bits_per_sample * enc->def->clockrate_mult / 8); * (fraction_mult(enc->def->bits_per_sample, &enc->def->clockrate_fact) / 8);
} }
return buf->len >= input_output->len ? 1 : 0; return buf->len >= input_output->len ? 1 : 0;
} }
@ -1694,7 +1688,8 @@ static int packetizer_samplestream(AVPacket *pkt, GString *buf, str *input_outpu
g_string_erase(buf, 0, input_output->len); g_string_erase(buf, 0, input_output->len);
// adjust output pts // adjust output pts
enc->avpkt->pts = enc->packet_pts; enc->avpkt->pts = enc->packet_pts;
enc->packet_pts += input_output->len * (enc->def->bits_per_sample * enc->def->clockrate_mult / 8); enc->packet_pts += input_output->len
* fraction_mult(enc->def->bits_per_sample, &enc->def->clockrate_fact) / 8;
return buf->len >= input_output->len ? 1 : 0; return buf->len >= input_output->len ? 1 : 0;
} }
@ -3199,7 +3194,7 @@ static const char *evs_decoder_init(decoder_t *dec, const str *extra_opts) {
dec->u.evs = g_slice_alloc0(evs_decoder_size); dec->u.evs = g_slice_alloc0(evs_decoder_size);
if (dec->in_format.clockrate != 48000) if (dec->in_format.clockrate != 48000)
ilog(LOG_WARN, "EVS: invalid decoder clock rate (%i) requested", ilog(LOG_WARN, "EVS: invalid decoder clock rate (%i) requested",
dec->in_format.clockrate / dec->def->clockrate_mult); fraction_div(dec->in_format.clockrate, &dec->def->clockrate_fact));
if (dec->in_format.channels != 1) if (dec->in_format.channels != 1)
ilog(LOG_WARN, "EVS: %i-channel EVS is not supported", ilog(LOG_WARN, "EVS: %i-channel EVS is not supported",
dec->in_format.channels); dec->in_format.channels);
@ -3445,7 +3440,7 @@ static const char *evs_encoder_init(encoder_t *enc, const str *extra_opts) {
enc->u.evs.ind_list = g_slice_alloc(evs_encoder_ind_list_size); enc->u.evs.ind_list = g_slice_alloc(evs_encoder_ind_list_size);
if (enc->requested_format.clockrate != 48000) if (enc->requested_format.clockrate != 48000)
ilog(LOG_WARN, "EVS: invalid encoder clock rate (%i) requested", ilog(LOG_WARN, "EVS: invalid encoder clock rate (%i) requested",
enc->requested_format.clockrate / enc->def->clockrate_mult); fraction_div(enc->requested_format.clockrate, &enc->def->clockrate_fact));
if (enc->requested_format.channels != 1) if (enc->requested_format.channels != 1)
ilog(LOG_WARN, "EVS: %i-channel EVS is not supported", ilog(LOG_WARN, "EVS: %i-channel EVS is not supported",
enc->requested_format.channels); enc->requested_format.channels);

@ -70,6 +70,7 @@ struct rtp_payload_type;
union codec_options_u; union codec_options_u;
struct encoder_callback_s; struct encoder_callback_s;
struct dtx_method_s; struct dtx_method_s;
struct fraction;
typedef struct codec_type_s codec_type_t; typedef struct codec_type_s codec_type_t;
typedef struct decoder_s decoder_t; typedef struct decoder_s decoder_t;
@ -140,9 +141,26 @@ enum dtx_method {
NUM_DTX_METHODS NUM_DTX_METHODS
}; };
struct fraction {
int mult;
int div;
};
INLINE int fraction_mult(int a, const struct fraction *f) {
return a * f->mult / f->div;
}
INLINE int fraction_div(int a, const struct fraction *f) {
return a * f->div / f->mult;
}
INLINE long fraction_multl(long a, const struct fraction *f) {
return a * f->mult / f->div;
}
INLINE long fraction_divl(long a, const struct fraction *f) {
return a * f->div / f->mult;
}
struct codec_def_s { struct codec_def_s {
const char * const rtpname; const char * const rtpname;
int clockrate_mult; struct fraction clockrate_fact;
const int avcodec_id; const int avcodec_id;
const char * const avcodec_name_enc; const char * const avcodec_name_enc;
const char * const avcodec_name_dec; const char * const avcodec_name_dec;

@ -62,7 +62,7 @@ decode_t *decoder_new(const char *payload_str, const char *format, int ptime, ou
// decoder_new_fmt already handles the clockrate_mult scaling // decoder_new_fmt already handles the clockrate_mult scaling
int rtp_clockrate = clockrate; int rtp_clockrate = clockrate;
clockrate *= def->clockrate_mult; clockrate = fraction_mult(clockrate, &def->clockrate_fact);
// we can now config our output, which determines the sample format we convert to // we can now config our output, which determines the sample format we convert to
format_t out_format = { format_t out_format = {

Loading…
Cancel
Save