diff --git a/daemon/codec.c b/daemon/codec.c index dfeabfc16..a13a9caf5 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -17,6 +17,7 @@ #include "timerthread.h" #include "log_funcs.h" #include "mqtt.h" +#include "fix_frame_channel_layout.h" @@ -2651,7 +2652,7 @@ static void delay_frame_manipulate(struct delay_frame *dframe) { frame_fill_dtmf_samples(frame->format, frame->extended_data[0], dframe->ts, frame->nb_samples, dtmf_code_from_char(dtmf_send->code), dtmf_send->volume, frame->sample_rate, - frame->channels); + GET_CHANNELS(frame)); } break; case BLOCK_DTMF_SILENCE: @@ -2660,7 +2661,7 @@ static void delay_frame_manipulate(struct delay_frame *dframe) { case BLOCK_DTMF_TONE: frame_fill_tone_samples(frame->format, frame->extended_data[0], dframe->ts, frame->nb_samples, ml->tone_freq ? : 400, - ml->tone_vol ? : 10, frame->sample_rate, frame->channels); + ml->tone_vol ? : 10, frame->sample_rate, GET_CHANNELS(frame)); break; case BLOCK_DTMF_ZERO: case BLOCK_DTMF_DTMF: @@ -2672,13 +2673,13 @@ static void delay_frame_manipulate(struct delay_frame *dframe) { dframe->ts, frame->nb_samples, dtmf_code_from_char(ml->dtmf_digit), ml->tone_vol ? : 10, frame->sample_rate, - frame->channels); + GET_CHANNELS(frame)); break; case BLOCK_DTMF_RANDOM: frame_fill_dtmf_samples(frame->format, frame->extended_data[0], dframe->ts, frame->nb_samples, dtmf_send->rand_code - '0', 10, frame->sample_rate, - frame->channels); + GET_CHANNELS(frame)); break; default: break; diff --git a/daemon/media_player.c b/daemon/media_player.c index 1dac2fcda..2cb379db4 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -16,6 +16,7 @@ #include "log_funcs.h" #include "main.h" #include "rtcp.h" +#include "fix_frame_channel_layout.h" @@ -336,7 +337,7 @@ static int __ensure_codec_handler(struct media_player *mp, AVStream *avs) { return -1; } src_pt.encoding = src_pt.codec_def->rtpname_str; - src_pt.channels = avs->CODECPAR->channels; + src_pt.channels = GET_CHANNELS(avs->CODECPAR); src_pt.clock_rate = avs->CODECPAR->sample_rate; codec_init_payload_type(&src_pt, MT_AUDIO); diff --git a/lib/codeclib.c b/lib/codeclib.c index be5bc4c6a..997f30159 100644 --- a/lib/codeclib.c +++ b/lib/codeclib.c @@ -16,6 +16,7 @@ #include "rtplib.h" #include "bitstr.h" #include "dtmflib.h" +#include "fix_frame_channel_layout.h" @@ -599,7 +600,8 @@ static const char *avc_decoder_init(decoder_t *dec, const str *fmtp, const str * dec->u.avc.avcctx = avcodec_alloc_context3(codec); if (!dec->u.avc.avcctx) return "failed to alloc codec context"; - dec->u.avc.avcctx->channels = dec->in_format.channels; + SET_CHANNELS(dec->u.avc.avcctx, dec->in_format.channels); + DEF_CH_LAYOUT(&dec->u.avc.avcctx->CH_LAYOUT, dec->in_format.channels); dec->u.avc.avcctx->sample_rate = dec->in_format.clockrate; if (dec->def->set_dec_options) @@ -1265,8 +1267,8 @@ static const char *avc_encoder_init(encoder_t *enc, const str *fmtp, const str * cdbg("using output sample format %s for codec %s", av_get_sample_fmt_name(enc->actual_format.format), enc->u.avc.codec->name); - enc->u.avc.avcctx->channels = enc->actual_format.channels; - enc->u.avc.avcctx->channel_layout = av_get_default_channel_layout(enc->actual_format.channels); + SET_CHANNELS(enc->u.avc.avcctx, enc->actual_format.channels); + DEF_CH_LAYOUT(&enc->u.avc.avcctx->CH_LAYOUT, enc->actual_format.channels); enc->u.avc.avcctx->sample_rate = enc->actual_format.clockrate; enc->u.avc.avcctx->sample_fmt = enc->actual_format.format; enc->u.avc.avcctx->time_base = (AVRational){1,enc->actual_format.clockrate}; @@ -1330,9 +1332,7 @@ int encoder_config_fmtp(encoder_t *enc, const codec_def_t *def, int bitrate, int enc->frame->nb_samples = enc->samples_per_frame ? : 256; enc->frame->format = enc->actual_format.format; enc->frame->sample_rate = enc->actual_format.clockrate; - enc->frame->channel_layout = av_get_default_channel_layout(enc->actual_format.channels); - //if (!enc->frame->channel_layout) - //enc->frame->channel_layout = av_get_default_channel_layout(enc->u.avc.avcctx->channels); + DEF_CH_LAYOUT(&enc->frame->CH_LAYOUT, enc->actual_format.channels); if (av_frame_get_buffer(enc->frame, 0) < 0) abort(); @@ -2352,7 +2352,7 @@ static int generic_silence_dtx(decoder_t *dec, GQueue *out, int ptime) { frame->nb_samples = num_samples; frame->format = dec->dec_out_format.format; frame->sample_rate = dec->dec_out_format.clockrate; - frame->channel_layout = av_get_default_channel_layout(dec->dec_out_format.channels); + DEF_CH_LAYOUT(&frame->CH_LAYOUT, dec->dec_out_format.channels); if (av_frame_get_buffer(frame, 0) < 0) { av_frame_free(&frame); return -1; @@ -2434,7 +2434,7 @@ static int bcg729_decoder_input(decoder_t *dec, const str *data, GQueue *out) { frame->nb_samples = 80; frame->format = AV_SAMPLE_FMT_S16; frame->sample_rate = dec->in_format.clockrate; // 8000 - frame->channel_layout = av_get_default_channel_layout(dec->in_format.channels); // 1 channel + DEF_CH_LAYOUT(&frame->CH_LAYOUT, dec->in_format.channels); frame->pts = pts; if (av_frame_get_buffer(frame, 0) < 0) abort(); @@ -2564,7 +2564,7 @@ static AVFrame *dtmf_frame_int16_t_mono(unsigned long frame_ts, unsigned long nu frame->nb_samples = num_samples; frame->format = AV_SAMPLE_FMT_S16; frame->sample_rate = sample_rate; - frame->channel_layout = AV_CH_LAYOUT_MONO; + frame->CH_LAYOUT = (CH_LAYOUT_T) MONO_LAYOUT; frame->pts = frame_ts; if (av_frame_get_buffer(frame, 0) < 0) abort(); diff --git a/lib/common.Makefile b/lib/common.Makefile index c6a9d34c7..597764ddd 100644 --- a/lib/common.Makefile +++ b/lib/common.Makefile @@ -34,7 +34,7 @@ $(DAEMONSRCS) $(HASHSRCS): $(patsubst %,../daemon/%,$(DAEMONSRCS)) $(patsubst %, --release="$(RTPENGINE_VERSION)" \ $< $@ -resample.c: fix_frame_channel_layout.h +resample.c media_player.c codec.c codeclib.c mix.c: fix_frame_channel_layout.h ifeq ($(with_transcoding),yes) codec.c: dtmf_rx_fillin.h diff --git a/lib/fix_frame_channel_layout-01.h b/lib/fix_frame_channel_layout-01.h index b0f10769b..c5b11c78a 100644 --- a/lib/fix_frame_channel_layout-01.h +++ b/lib/fix_frame_channel_layout-01.h @@ -2,7 +2,39 @@ #include <libavutil/channel_layout.h> #include "compat.h" +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) +// both `channel_layout` and `channels` are deprecated in favour of `ch_layout` +#define CH_LAYOUT ch_layout +#define CH_LAYOUT_T AVChannelLayout +#define DEF_CH_LAYOUT(d,n) av_channel_layout_default(d,n) +#define CH_LAYOUT_EQ(a,b) (av_channel_layout_compare(&(a),&(b)) == 0) +#define SWR_ALLOC_SET_OPTS(a,b,c,d,e,f,g,h,i) swr_alloc_set_opts2(a,&(b),c,d,&(e),f,g,h,i) +#define SET_CHANNELS(a,b) ((void)0) +#define MONO_LAYOUT AV_CHANNEL_LAYOUT_MONO +#define GET_CHANNELS(x) (x)->ch_layout.nb_channels +#define CH_LAYOUT_EXTRACT_MASK(a,b) (1ULL << av_channel_layout_channel_from_index(&(a),b)) +#define CH_LAYOUT_MASK(a) (a)->u.mask +#define CH_LAYOUT_FROM_MASK(a,b) av_channel_layout_from_mask(a,b) +#define CH_LAYOUT_PRINT(a,b) av_channel_layout_describe(&(a),b,sizeof(b)) +#else +#define CH_LAYOUT channel_layout +#define CH_LAYOUT_T uint64_t +#define DEF_CH_LAYOUT(d,n) *(d) = av_get_default_channel_layout(n) +#define CH_LAYOUT_EQ(a,b) ((a) == (b)) +#define SWR_ALLOC_SET_OPTS(a,b,c,d,e,f,g,h,i) *(a) = swr_alloc_set_opts(NULL,b,c,d,e,f,g,h,i) +#define SET_CHANNELS(a,b) (a)->channels = (b) +#define MONO_LAYOUT AV_CH_LAYOUT_MONO +#define GET_CHANNELS(x) (x)->channels +#define CH_LAYOUT_EXTRACT_MASK(a,b) av_channel_layout_extract_channel(a,b) +#define CH_LAYOUT_MASK(a) (a) +#define CH_LAYOUT_FROM_MASK(a,b) *(a) = (b) +#define CH_LAYOUT_PRINT(a,b) snprintf(b, sizeof(b), "0x" PRIx64, a) +#endif + INLINE void fix_frame_channel_layout(AVFrame *frame) { +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100) + return; +#else if (frame->channel_layout) { #if LIBAVUTIL_VERSION_MAJOR < 56 if (!frame->channels) @@ -15,4 +47,5 @@ INLINE void fix_frame_channel_layout(AVFrame *frame) { #else frame->channel_layout = av_get_default_channel_layout(frame->channels); #endif +#endif } diff --git a/lib/fix_frame_channel_layout-02.h b/lib/fix_frame_channel_layout-02.h index eb597e086..229957188 100644 --- a/lib/fix_frame_channel_layout-02.h +++ b/lib/fix_frame_channel_layout-02.h @@ -2,11 +2,30 @@ #include <libavutil/channel_layout.h> #include "compat.h" +#define CH_LAYOUT channel_layout +#define CH_LAYOUT_T uint64_t +#define DEF_CH_LAYOUT(d,n) *(d) = av_get_default_channel_layout(n) +#define CH_LAYOUT_EQ(a,b) ((a) == (b)) +#define SWR_ALLOC_SET_OPTS(a,b,c,d,e,f,g,h,i) *(a) = swr_alloc_set_opts(NULL,b,c,d,e,f,g,h,i) +#define SET_CHANNELS(a,b) (a)->channels = (b) +#define MONO_LAYOUT AV_CH_LAYOUT_MONO +#define GET_CHANNELS(x) (x)->channels +#define CH_LAYOUT_EXTRACT_MASK(a,b) av_channel_layout_extract_channel(a,b) +#define CH_LAYOUT_MASK(a) (a) +#define CH_LAYOUT_FROM_MASK(a,b) *(a) = (b) +#define CH_LAYOUT_PRINT(a,b) snprintf(b, sizeof(b), "0x" PRIx64, a) + INLINE void fix_frame_channel_layout(AVFrame *frame) { if (frame->channel_layout) { +#if LIBAVUTIL_VERSION_MAJOR < 56 if (!frame->channels) frame->channels = av_frame_get_channels(frame); +#endif return; } +#if LIBAVUTIL_VERSION_MAJOR < 56 + frame->channel_layout = av_get_default_channel_layout(av_frame_get_channels(frame)); +#else frame->channel_layout = av_get_default_channel_layout(frame->channels); +#endif } diff --git a/lib/fix_frame_channel_layout-03.h b/lib/fix_frame_channel_layout-03.h index 5e24334f8..1e7940009 100644 --- a/lib/fix_frame_channel_layout-03.h +++ b/lib/fix_frame_channel_layout-03.h @@ -2,8 +2,24 @@ #include <libavutil/channel_layout.h> #include "compat.h" +#define CH_LAYOUT channel_layout +#define CH_LAYOUT_T uint64_t +#define DEF_CH_LAYOUT(d,n) *(d) = av_get_default_channel_layout(n) +#define CH_LAYOUT_EQ(a,b) ((a) == (b)) +#define SWR_ALLOC_SET_OPTS(a,b,c,d,e,f,g,h,i) *(a) = swr_alloc_set_opts(NULL,b,c,d,e,f,g,h,i) +#define SET_CHANNELS(a,b) (a)->channels = (b) +#define MONO_LAYOUT AV_CH_LAYOUT_MONO +#define GET_CHANNELS(x) (x)->channels +#define CH_LAYOUT_EXTRACT_MASK(a,b) av_channel_layout_extract_channel(a,b) +#define CH_LAYOUT_MASK(a) (a) +#define CH_LAYOUT_FROM_MASK(a,b) *(a) = (b) +#define CH_LAYOUT_PRINT(a,b) snprintf(b, sizeof(b), "0x" PRIx64, a) + INLINE void fix_frame_channel_layout(AVFrame *frame) { - if (frame->channel_layout) + if (frame->channel_layout) { + if (!frame->channels) + frame->channels = av_frame_get_channels(frame); return; - frame->channel_layout = av_get_default_channel_layout(av_frame_get_channels(frame)); + } + frame->channel_layout = av_get_default_channel_layout(frame->channels); } diff --git a/lib/fix_frame_channel_layout-04.h b/lib/fix_frame_channel_layout-04.h index fac1b29cb..3850d46b3 100644 --- a/lib/fix_frame_channel_layout-04.h +++ b/lib/fix_frame_channel_layout-04.h @@ -2,8 +2,21 @@ #include <libavutil/channel_layout.h> #include "compat.h" +#define CH_LAYOUT channel_layout +#define CH_LAYOUT_T uint64_t +#define DEF_CH_LAYOUT(d,n) *(d) = av_get_default_channel_layout(n) +#define CH_LAYOUT_EQ(a,b) ((a) == (b)) +#define SWR_ALLOC_SET_OPTS(a,b,c,d,e,f,g,h,i) *(a) = swr_alloc_set_opts(NULL,b,c,d,e,f,g,h,i) +#define SET_CHANNELS(a,b) (a)->channels = (b) +#define MONO_LAYOUT AV_CH_LAYOUT_MONO +#define GET_CHANNELS(x) (x)->channels +#define CH_LAYOUT_EXTRACT_MASK(a,b) av_channel_layout_extract_channel(a,b) +#define CH_LAYOUT_MASK(a) (a) +#define CH_LAYOUT_FROM_MASK(a,b) *(a) = (b) +#define CH_LAYOUT_PRINT(a,b) snprintf(b, sizeof(b), "0x" PRIx64, a) + INLINE void fix_frame_channel_layout(AVFrame *frame) { if (frame->channel_layout) return; - frame->channel_layout = av_get_default_channel_layout(frame->channels); + frame->channel_layout = av_get_default_channel_layout(av_frame_get_channels(frame)); } diff --git a/lib/fix_frame_channel_layout-05.h b/lib/fix_frame_channel_layout-05.h new file mode 100644 index 000000000..b3f6a91d8 --- /dev/null +++ b/lib/fix_frame_channel_layout-05.h @@ -0,0 +1,22 @@ +#include <libavutil/frame.h> +#include <libavutil/channel_layout.h> +#include "compat.h" + +#define CH_LAYOUT channel_layout +#define CH_LAYOUT_T uint64_t +#define DEF_CH_LAYOUT(d,n) *(d) = av_get_default_channel_layout(n) +#define CH_LAYOUT_EQ(a,b) ((a) == (b)) +#define SWR_ALLOC_SET_OPTS(a,b,c,d,e,f,g,h,i) *(a) = swr_alloc_set_opts(NULL,b,c,d,e,f,g,h,i) +#define SET_CHANNELS(a,b) (a)->channels = (b) +#define MONO_LAYOUT AV_CH_LAYOUT_MONO +#define GET_CHANNELS(x) (x)->channels +#define CH_LAYOUT_EXTRACT_MASK(a,b) av_channel_layout_extract_channel(a,b) +#define CH_LAYOUT_MASK(a) (a) +#define CH_LAYOUT_FROM_MASK(a,b) *(a) = (b) +#define CH_LAYOUT_PRINT(a,b) snprintf(b, sizeof(b), "0x" PRIx64, a) + +INLINE void fix_frame_channel_layout(AVFrame *frame) { + if (frame->channel_layout) + return; + frame->channel_layout = av_get_default_channel_layout(frame->channels); +} diff --git a/lib/resample.c b/lib/resample.c index df1d95f83..e0ba724cf 100644 --- a/lib/resample.c +++ b/lib/resample.c @@ -20,14 +20,15 @@ AVFrame *resample_frame(resample_t *resample, AVFrame *frame, const format_t *to const char *err; int errcode = 0; - uint64_t to_channel_layout = av_get_default_channel_layout(to_format->channels); + CH_LAYOUT_T to_channel_layout; + DEF_CH_LAYOUT(&to_channel_layout, to_format->channels); fix_frame_channel_layout(frame); if (frame->format != to_format->format) goto resample; if (frame->sample_rate != to_format->clockrate) goto resample; - if (frame->channel_layout != to_channel_layout) + if (!CH_LAYOUT_EQ(frame->CH_LAYOUT, to_channel_layout)) goto resample; return av_frame_clone(frame); @@ -35,11 +36,11 @@ AVFrame *resample_frame(resample_t *resample, AVFrame *frame, const format_t *to resample: if (G_UNLIKELY(!resample->swresample)) { - resample->swresample = swr_alloc_set_opts(NULL, + SWR_ALLOC_SET_OPTS(&resample->swresample, to_channel_layout, to_format->format, to_format->clockrate, - frame->channel_layout, + frame->CH_LAYOUT, frame->format, frame->sample_rate, 0, NULL); @@ -69,7 +70,7 @@ resample: goto err; av_frame_copy_props(swr_frame, frame); swr_frame->format = to_format->format; - swr_frame->channel_layout = to_channel_layout; + swr_frame->CH_LAYOUT = to_channel_layout; swr_frame->nb_samples = dst_samples; swr_frame->sample_rate = to_format->clockrate; err = "failed to get resample buffers"; diff --git a/recording-daemon/mix.c b/recording-daemon/mix.c index d53622a87..6091fe5b2 100644 --- a/recording-daemon/mix.c +++ b/recording-daemon/mix.c @@ -13,6 +13,7 @@ #include "output.h" #include "resample.h" #include "main.h" +#include "fix_frame_channel_layout.h" @@ -26,7 +27,7 @@ struct mix_s { uint64_t in_pts[MIX_NUM_INPUTS]; // running counter of next expected adjusted pts struct timeval last_use[MIX_NUM_INPUTS]; // to recycle old mix inputs void *input_ref[MIX_NUM_INPUTS]; // to avoid collisions in case of idx re-use - uint64_t channel_layout[MIX_NUM_INPUTS]; + CH_LAYOUT_T channel_layout[MIX_NUM_INPUTS]; AVFilterContext *amix_ctx; AVFilterContext *sink_ctx; unsigned int next_idx; @@ -145,26 +146,31 @@ int mix_config(mix_t *mix, const format_t *format) { if (!flt) goto err; - uint64_t channel_layout = av_get_default_channel_layout(mix->in_format.channels); - uint64_t ext_layout = av_get_default_channel_layout(mix->in_format.channels * MIX_NUM_INPUTS); + CH_LAYOUT_T channel_layout, ext_layout; + DEF_CH_LAYOUT(&channel_layout, mix->in_format.channels); + DEF_CH_LAYOUT(&ext_layout, mix->in_format.channels * MIX_NUM_INPUTS); for (unsigned int i = 0; i < MIX_NUM_INPUTS; i++) { dbg("init input ctx %i", i); - uint64_t ch_layout = channel_layout; + CH_LAYOUT_T ch_layout = channel_layout; if (mix_method == MM_CHANNELS) { - ch_layout = 0; - for (int ch = 0; ch < mix->in_format.channels; ch++) - ch_layout |= av_channel_layout_extract_channel(ext_layout, + uint64_t mask = 0; + for (int ch = 0; ch < mix->in_format.channels; ch++) { + mask |= CH_LAYOUT_EXTRACT_MASK(ext_layout, i * mix->in_format.channels + ch); + } + CH_LAYOUT_FROM_MASK(&ch_layout, mask); } + char chlayoutbuf[64]; + CH_LAYOUT_PRINT(ch_layout, chlayoutbuf); snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:" - "channel_layout=0x%" PRIx64, + "channel_layout=%s", 1, mix->in_format.clockrate, mix->in_format.clockrate, av_get_sample_fmt_name(mix->in_format.format), - ch_layout); + chlayoutbuf); mix->channel_layout[i] = ch_layout; err = "failed to create abuffer filter context"; @@ -234,8 +240,8 @@ static void mix_silence_fill_idx_upto(mix_t *mix, unsigned int idx, uint64_t upt if (G_UNLIKELY(!mix->silence_frame)) { mix->silence_frame = av_frame_alloc(); mix->silence_frame->format = mix->in_format.format; - mix->silence_frame->channel_layout = - av_get_default_channel_layout(mix->in_format.channels); + DEF_CH_LAYOUT(&mix->silence_frame->CH_LAYOUT, + mix->in_format.channels); mix->silence_frame->nb_samples = silence_samples; mix->silence_frame->sample_rate = mix->in_format.clockrate; if (av_frame_get_buffer(mix->silence_frame, 0) < 0) { @@ -255,7 +261,7 @@ static void mix_silence_fill_idx_upto(mix_t *mix, unsigned int idx, uint64_t upt mix->silence_frame->nb_samples = MIN(silence_samples, upto - mix->in_pts[idx]); mix->in_pts[idx] += mix->silence_frame->nb_samples; - mix->silence_frame->channel_layout = mix->channel_layout[idx]; + mix->silence_frame->CH_LAYOUT = mix->channel_layout[idx]; if (av_buffersrc_write_frame(mix->src_ctxs[idx], mix->silence_frame)) ilog(LOG_WARN, "Failed to write silence frame to buffer"); } @@ -316,7 +322,7 @@ int mix_add(mix_t *mix, AVFrame *frame, unsigned int idx, void *ptr, output_t *o uint64_t next_pts = frame->pts + frame->nb_samples; - frame->channel_layout = mix->channel_layout[idx]; + frame->CH_LAYOUT = mix->channel_layout[idx]; err = "failed to add frame to mixer"; if (av_buffersrc_add_frame(mix->src_ctxs[idx], frame)) goto err;