From 147b8b8e5107ebb92f23fbc0e38bec028bd89c22 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 22 Nov 2016 12:10:45 -0500 Subject: [PATCH] TT#5566 force usage of libopus for opus decoding support multichannel audio output add avcodec log callback Change-Id: Id649ba2c51b2914420b149aad791cf5c12445008 --- recording-daemon/decoder.c | 57 +++++++++++++++++++++++++++++--------- recording-daemon/decoder.h | 1 - recording-daemon/log.h | 1 + recording-daemon/main.c | 6 ++++ 4 files changed, 51 insertions(+), 14 deletions(-) diff --git a/recording-daemon/decoder.c b/recording-daemon/decoder.c index 38fba2db5..89b083fa4 100644 --- a/recording-daemon/decoder.c +++ b/recording-daemon/decoder.c @@ -19,7 +19,11 @@ struct decoder_s { struct output_s { char *filename; + + // format params int clockrate; + int channels; + AVCodecContext *avcctx; AVFormatContext *fmtctx; AVStream *avst; @@ -28,17 +32,21 @@ struct output_s { struct decoder_def_s { - const char *name; + const char *rtpname; int clockrate_mult; int avcodec_id; + const char *avcodec_name; }; -#define DECODER_DEF_MULT(ref, id, mult) { \ - .name = #ref, \ +#define DECODER_DEF_MULT_NAME(ref, id, mult, name) { \ + .rtpname = #ref, \ .avcodec_id = AV_CODEC_ID_ ## id, \ .clockrate_mult = mult, \ + .avcodec_name = #name, \ } +#define DECODER_DEF_MULT(ref, id, mult) DECODER_DEF_MULT_NAME(ref, id, mult, NULL) +#define DECODER_DEF_NAME(ref, id, name) DECODER_DEF_MULT_NAME(ref, id, 1, name) #define DECODER_DEF(ref, id) DECODER_DEF_MULT(ref, id, 1) static const struct decoder_def_s decoders[] = { @@ -51,19 +59,20 @@ static const struct decoder_def_s decoders[] = { DECODER_DEF(speex, SPEEX), DECODER_DEF(GSM, GSM), DECODER_DEF(iLBC, ILBC), - DECODER_DEF(opus, OPUS), + DECODER_DEF_NAME(opus, OPUS, libopus), }; typedef struct decoder_def_s decoder_def_t; static void output_shutdown(output_t *output); +static int output_config(output_t *output, unsigned int clockrate, unsigned int channels); static const decoder_def_t *decoder_find(const str *name) { for (int i = 0; i < G_N_ELEMENTS(decoders); i++) { - if (!str_cmp(name, decoders[i].name)) + if (!str_cmp(name, decoders[i].rtpname)) return &decoders[i]; } return NULL; @@ -81,6 +90,14 @@ decoder_t *decoder_new(const char *payload_str) { str_init_len(&name, (char *) payload_str, slash - payload_str); int clockrate = atoi(slash + 1); + int channels = 1; + slash = strchr(slash + 1, '/'); + if (slash) { + channels = atoi(slash + 1); + if (!channels) + channels = 1; + } + const decoder_def_t *def = decoder_find(&name); if (!def) { ilog(LOG_WARN, "No decoder for payload %s", payload_str); @@ -91,11 +108,16 @@ decoder_t *decoder_new(const char *payload_str) { decoder_t *ret = g_slice_alloc0(sizeof(*ret)); // XXX error reporting - AVCodec *codec = avcodec_find_decoder(def->avcodec_id); + AVCodec *codec = NULL; + if (def->avcodec_name) + codec = avcodec_find_decoder_by_name(def->avcodec_name); + if (!codec) + codec = avcodec_find_decoder(def->avcodec_id); + ret->avcctx = avcodec_alloc_context3(codec); if (!ret->avcctx) goto err; - ret->avcctx->channels = 1; + ret->avcctx->channels = channels; ret->avcctx->sample_rate = clockrate; int i = avcodec_open2(ret->avcctx, codec, NULL); if (i) @@ -155,7 +177,7 @@ int decoder_input(decoder_t *dec, const str *data, unsigned long ts, output_t *o } else { // shift pts according to rtp ts shift - dec->pts += (ts - dec->rtp_ts) * output->avst->time_base.num * 8000 / output->avst->time_base.den; + dec->pts += (ts - dec->rtp_ts) /* * output->avst->time_base.num * 8000 / output->avst->time_base.den */ ; // XXX handle lost packets here if timestamps don't line up? } dec->rtp_ts = ts; @@ -184,7 +206,7 @@ int decoder_input(decoder_t *dec, const str *data, unsigned long ts, output_t *o dec->frame->pts = dec->frame->pkt_pts; - output_config(output, dec->avcctx->sample_rate); + output_config(output, dec->avcctx->sample_rate, dec->avcctx->channels); output_add(output, dec->frame); return 0; @@ -195,18 +217,27 @@ output_t *output_new(const char *filename) { output_t *ret = g_slice_alloc0(sizeof(*ret)); ret->filename = strdup(filename); ret->clockrate = -1; + ret->channels = -1; return ret; } -int output_config(output_t *output, unsigned int clockrate) { +static int output_config(output_t *output, unsigned int clockrate, unsigned int channels) { // anything to do? - if (output->clockrate == clockrate) - return 0; + if (G_UNLIKELY(output->clockrate != clockrate)) + goto format_mismatch; + if (G_UNLIKELY(output->channels != channels)) + goto format_mismatch; + + // all good + return 0; +format_mismatch: // XXX support reset/config change + // copy params output->clockrate = clockrate; + output->channels = channels; // XXX error reporting output->fmtctx = avformat_alloc_context(); @@ -229,7 +260,7 @@ int output_config(output_t *output, unsigned int clockrate) { output->avcctx = output->avst->codec; #endif - output->avcctx->channels = 1; + output->avcctx->channels = output->channels; output->avcctx->sample_rate = output->clockrate; output->avcctx->sample_fmt = AV_SAMPLE_FMT_S16; output->avcctx->time_base = (AVRational){output->clockrate,1}; diff --git a/recording-daemon/decoder.h b/recording-daemon/decoder.h index 3627006ec..5c3d516a6 100644 --- a/recording-daemon/decoder.h +++ b/recording-daemon/decoder.h @@ -10,7 +10,6 @@ int decoder_input(decoder_t *, const str *, unsigned long ts, output_t *); void decoder_close(decoder_t *); output_t *output_new(const char *filename); -int output_config(output_t *, unsigned int clock_rate); void output_close(output_t *); diff --git a/recording-daemon/log.h b/recording-daemon/log.h index 6b446623d..71c93f2c2 100644 --- a/recording-daemon/log.h +++ b/recording-daemon/log.h @@ -10,6 +10,7 @@ #define die(fmt, ...) do { ilog(LOG_CRIT, "Fatal error: " fmt, ##__VA_ARGS__); exit(-1); } while (0) #define die_errno(msg) die("%s: %s", msg, strerror(errno)) #define ilog(fclt, fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__) +#define vilog(fclt, fmt, ap) vfprintf(stderr, fmt, ap) #define dbg(fmt, ...) ilog(LOG_DEBUG, fmt, ##__VA_ARGS__) #endif diff --git a/recording-daemon/main.c b/recording-daemon/main.c index cbad04ee3..8b9fdfa99 100644 --- a/recording-daemon/main.c +++ b/recording-daemon/main.c @@ -33,6 +33,11 @@ static void signals(void) { } +static void avlog_ilog(void *ptr, int loglevel, const char *fmt, va_list ap) { + vilog(loglevel, fmt, ap); +} + + static void setup(void) { av_register_all(); avcodec_register_all(); @@ -41,6 +46,7 @@ static void setup(void) { metafile_setup(); epoll_setup(); inotify_setup(); + av_log_set_callback(avlog_ilog); }