diff --git a/daemon/codec.c b/daemon/codec.c index 8f9e1013a..de691c63e 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -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 } - 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 ts -= ch->last_dtmf_event_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; // shift forward our output RTP TS - output_ch->encoder->next_pts = (ts + duration) * output_ch->encoder->def->clockrate_mult; - output_ch->encoder->packet_pts += (duration - ch->last_dtmf_event_ts) * 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 += fraction_multl(duration - ch->last_dtmf_event_ts, &output_ch->encoder->def->clockrate_fact); ch->last_dtmf_event_ts = duration; } 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; 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, .format = -1, }; @@ -3569,7 +3569,7 @@ static int packet_encoded_rtp(encoder_t *enc, void *u1, void *u2) { memcpy(send_buf, buf, pkt_len); } __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, payload_type, 0); mp->ssrc_out->parent->seq_diff++; diff --git a/daemon/media_player.c b/daemon/media_player.c index c1d0bb162..0ef94daed 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -306,7 +306,7 @@ found: // that has passed if (mp->sync_ts_tv.tv_sec) { 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 diff --git a/lib/codeclib.c b/lib/codeclib.c index 99323c62f..39e761b20 100644 --- a/lib/codeclib.c +++ b/lib/codeclib.c @@ -212,7 +212,6 @@ static codec_def_t __codec_defs[] = { { .rtpname = "PCMA", .avcodec_id = AV_CODEC_ID_PCM_ALAW, - .clockrate_mult = 1, .default_clockrate = 8000, .default_channels = 1, .default_ptime = 20, @@ -229,7 +228,6 @@ static codec_def_t __codec_defs[] = { { .rtpname = "PCMU", .avcodec_id = AV_CODEC_ID_PCM_MULAW, - .clockrate_mult = 1, .default_clockrate = 8000, .default_channels = 1, .default_ptime = 20, @@ -246,7 +244,6 @@ static codec_def_t __codec_defs[] = { { .rtpname = "G723", .avcodec_id = AV_CODEC_ID_G723_1, - .clockrate_mult = 1, .default_clockrate = 8000, .default_channels = 1, .default_ptime = 30, @@ -262,7 +259,7 @@ static codec_def_t __codec_defs[] = { { .rtpname = "G722", .avcodec_id = AV_CODEC_ID_ADPCM_G722, - .clockrate_mult = 2, + .clockrate_fact = {2,1}, .default_clockrate = 8000, .default_channels = 1, .default_ptime = 20, @@ -279,7 +276,6 @@ static codec_def_t __codec_defs[] = { { .rtpname = "QCELP", .avcodec_id = AV_CODEC_ID_QCELP, - .clockrate_mult = 1, .default_ptime = 20, .packetizer = packetizer_passthrough, .media_type = MT_AUDIO, @@ -293,7 +289,6 @@ static codec_def_t __codec_defs[] = { { .rtpname = "G729", .avcodec_id = AV_CODEC_ID_G729, - .clockrate_mult = 1, .default_clockrate = 8000, .default_channels = 1, .default_ptime = 20, @@ -308,7 +303,6 @@ static codec_def_t __codec_defs[] = { { .rtpname = "G729a", .avcodec_id = AV_CODEC_ID_G729, - .clockrate_mult = 1, .default_clockrate = 8000, .default_channels = 1, .default_ptime = 20, @@ -324,7 +318,6 @@ static codec_def_t __codec_defs[] = { { .rtpname = "G729", .avcodec_id = -1, - .clockrate_mult = 1, .default_clockrate = 8000, .default_channels = 1, .default_ptime = 20, @@ -341,7 +334,6 @@ static codec_def_t __codec_defs[] = { { .rtpname = "G729a", .avcodec_id = -1, - .clockrate_mult = 1, .default_clockrate = 8000, .default_channels = 1, .default_ptime = 20, @@ -423,7 +415,7 @@ static codec_def_t __codec_defs[] = { { .rtpname = "EVS", .avcodec_id = -1, - .clockrate_mult = 3, + .clockrate_fact = {3,1}, .default_clockrate = 16000, .default_channels = 1, .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) goto err; - clockrate *= def->clockrate_mult; + clockrate = fraction_mult(clockrate, &def->clockrate_fact); 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)) 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, (unsigned long long) dec->rtp_ts, (unsigned long) ts); @@ -1144,8 +1136,10 @@ void codeclib_init(int print) { } // init undefined member vars - if (!def->clockrate_mult) - def->clockrate_mult = 1; + if (!def->clockrate_fact.mult) + def->clockrate_fact.mult = 1; + if (!def->clockrate_fact.div) + def->clockrate_fact.div = 1; if (!def->default_ptime) def->default_ptime = -1; 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->def = def; - enc->ptime = ptime / def->clockrate_mult; + enc->ptime = fraction_div(ptime, &def->clockrate_fact); enc->bitrate = bitrate; 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, pkt->size - 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; } @@ -1694,7 +1688,8 @@ static int packetizer_samplestream(AVPacket *pkt, GString *buf, str *input_outpu g_string_erase(buf, 0, input_output->len); // adjust output 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; } @@ -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); if (dec->in_format.clockrate != 48000) 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) ilog(LOG_WARN, "EVS: %i-channel EVS is not supported", 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); if (enc->requested_format.clockrate != 48000) 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) ilog(LOG_WARN, "EVS: %i-channel EVS is not supported", enc->requested_format.channels); diff --git a/lib/codeclib.h b/lib/codeclib.h index a3c364f80..217530a6c 100644 --- a/lib/codeclib.h +++ b/lib/codeclib.h @@ -70,6 +70,7 @@ struct rtp_payload_type; union codec_options_u; struct encoder_callback_s; struct dtx_method_s; +struct fraction; typedef struct codec_type_s codec_type_t; typedef struct decoder_s decoder_t; @@ -140,9 +141,26 @@ enum dtx_method { 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 { const char * const rtpname; - int clockrate_mult; + struct fraction clockrate_fact; const int avcodec_id; const char * const avcodec_name_enc; const char * const avcodec_name_dec; diff --git a/recording-daemon/decoder.c b/recording-daemon/decoder.c index 694b6b608..7a8e35c6e 100644 --- a/recording-daemon/decoder.c +++ b/recording-daemon/decoder.c @@ -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 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 format_t out_format = {