diff --git a/lib/codeclib.c b/lib/codeclib.c index 6e839d973..e286be23d 100644 --- a/lib/codeclib.c +++ b/lib/codeclib.c @@ -411,7 +411,6 @@ decoder_t *decoder_new_fmt(const codec_def_t *def, int clockrate, int channels, ret->out_format = ret->in_format; if (resample_fmt) ret->out_format = *resample_fmt; - // sample format to be determined later when decoded frames arrive err = def->codec_type->decoder_init(ret); if (err) @@ -966,7 +965,8 @@ int encoder_config(encoder_t *enc, const codec_def_t *def, int bitrate, int ptim done: - *actual_format = enc->actual_format; + if (actual_format) + *actual_format = enc->actual_format; return 0; err: diff --git a/recording-daemon/decoder.c b/recording-daemon/decoder.c index d8af63704..e3676f439 100644 --- a/recording-daemon/decoder.c +++ b/recording-daemon/decoder.c @@ -22,7 +22,7 @@ int resample_audio; -decoder_t *decoder_new(const char *payload_str) { +decoder_t *decoder_new(const char *payload_str, output_t *outp) { str name; char *slash = strchr(payload_str, '/'); if (!slash) { @@ -51,15 +51,22 @@ decoder_t *decoder_new(const char *payload_str) { clockrate *= def->clockrate_mult; - if (!resample_audio) - return decoder_new_fmt(def, clockrate, channels, NULL); - + // we can now config our output, which determines the sample format we convert to format_t out_format = { - .clockrate = resample_audio, + .clockrate = clockrate, .channels = channels, - .format = 0 + .format = -1, }; + if (resample_audio) + out_format.clockrate = resample_audio; + // mono/stereo mixing goes here: out_format.channels = ... + if (outp) { + output_config(outp, &out_format, &out_format); + // save the returned sample format so we don't output_config() twice + outp->encoder->requested_format.format = out_format.format; + } + return decoder_new_fmt(def, clockrate, channels, &out_format); } @@ -74,10 +81,6 @@ static int decoder_got_frame(decoder_t *dec, AVFrame *frame, void *op, void *mp) (unsigned int) frame->extended_data[0][2], (unsigned int) frame->extended_data[0][3]); - // determine and save sample type - if (G_UNLIKELY(dec->in_format.format == -1)) - dec->in_format.format = dec->out_format.format = frame->format; - // handle mix output pthread_mutex_lock(&metafile->mix_lock); if (metafile->mix_out) { @@ -87,6 +90,7 @@ static int decoder_got_frame(decoder_t *dec, AVFrame *frame, void *op, void *mp) if (output_config(metafile->mix_out, &dec->out_format, &actual_format)) goto no_mix_out; mix_config(metafile->mix, &actual_format); + // XXX might be a second resampling to same format AVFrame *dec_frame = resample_frame(&dec->mix_resampler, frame, &actual_format); if (!dec_frame) { pthread_mutex_unlock(&metafile->mix_lock); @@ -99,16 +103,10 @@ no_mix_out: pthread_mutex_unlock(&metafile->mix_lock); if (output) { - // XXX might be a second resampling to same format - format_t actual_format; - if (output_config(output, &dec->out_format, &actual_format)) + if (output_config(output, &dec->out_format, NULL)) goto err; -// AVFrame *dec_frame = resample_frame(&dec->output_resample, frame, &actual_format); -// if (!dec_frame) -// goto err; if (output_add(output, frame)) ilog(LOG_ERR, "Failed to add decoded packet to individual output"); -// av_frame_free(&dec_frame); } av_frame_free(&frame); diff --git a/recording-daemon/decoder.h b/recording-daemon/decoder.h index 07a82a4c8..7f2ba6da4 100644 --- a/recording-daemon/decoder.h +++ b/recording-daemon/decoder.h @@ -8,7 +8,7 @@ extern int resample_audio; -decoder_t *decoder_new(const char *payload_str); +decoder_t *decoder_new(const char *payload_str, output_t *); int decoder_input(decoder_t *, const str *, unsigned long ts, output_t *, metafile_t *); diff --git a/recording-daemon/output.c b/recording-daemon/output.c index 681a95bfd..89a9ef7d0 100644 --- a/recording-daemon/output.c +++ b/recording-daemon/output.c @@ -57,14 +57,15 @@ output_t *output_new(const char *path, const char *filename) { int output_config(output_t *output, const format_t *requested_format, format_t *actual_format) { const char *err; -// // anything to do? -// if (G_LIKELY(format_eq(requested_format, &output->requested_format))) -// goto done; + // anything to do? + if (G_LIKELY(format_eq(requested_format, &output->encoder->requested_format))) { + if (actual_format) + *actual_format = output->encoder->actual_format; + goto done; + } output_shutdown(output); -// output->requested_format = *requested_format; - err = "failed to alloc format context"; output->fmtctx = avformat_alloc_context(); if (!output->fmtctx) @@ -77,43 +78,10 @@ int output_config(output_t *output, const format_t *requested_format, format_t * if (encoder_config(output->encoder, output_codec, mp3_bitrate, 0, requested_format, actual_format)) goto err; -// err = "output codec not found"; -// AVCodec *codec = avcodec_find_encoder(output_codec_id); -// if (!codec) -// goto err; err = "failed to alloc output stream"; output->avst = avformat_new_stream(output->fmtctx, output->encoder->u.avc.codec); if (!output->avst) goto err; -//#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 0, 0) -// err = "failed to alloc codec context"; -// output->avcctx = avcodec_alloc_context3(codec); -// if (!output->avcctx) -// goto err; -//#else -// output->avcctx = output->avst->codec; -//#endif - - // copy all format params -// output->actual_format = output->requested_format; - - // determine sample format to use -// output->actual_format.format = -1; -// for (const enum AVSampleFormat *sfmt = codec->sample_fmts; sfmt && *sfmt != -1; sfmt++) { -// dbg("supported sample format for output codec %s: %s", codec->name, av_get_sample_fmt_name(*sfmt)); -// if (*sfmt == requested_format->format) -// output->actual_format.format = *sfmt; -// } -// if (output->actual_format.format == -1 && codec->sample_fmts) -// output->actual_format.format = codec->sample_fmts[0]; -// dbg("using output sample format %s for codec %s", av_get_sample_fmt_name(output->actual_format.format), codec->name); -// -// output->avcctx->channels = output->actual_format.channels; -// output->avcctx->channel_layout = av_get_default_channel_layout(output->actual_format.channels); -// output->avcctx->sample_rate = output->actual_format.clockrate; -// output->avcctx->sample_fmt = output->actual_format.format; -// output->avcctx->time_base = (AVRational){1,output->actual_format.clockrate}; -// output->avcctx->bit_rate = mp3_bitrate; output->avst->time_base = output->encoder->u.avc.avcctx->time_base; #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 26, 0) // exact version? present in 57.56 @@ -133,10 +101,6 @@ int output_config(output_t *output, const format_t *requested_format, format_t * goto err; got_fn: -// err = "failed to open output context"; -// int i = avcodec_open2(output->avcctx, codec, NULL); -// if (i) -// goto err; err = "failed to open avio"; int i; i = avio_open(&output->fmtctx->pb, full_fn, AVIO_FLAG_WRITE); @@ -147,22 +111,7 @@ got_fn: if (i) goto err; -// av_init_packet(&output->avpkt); - - // output frame and fifo -// output->frame = av_frame_alloc(); -// output->frame->nb_samples = output->encoder->avcctx->frame_size ? : 256; -// output->frame->format = output->encoder->avcctx->sample_fmt; -// output->frame->sample_rate = output->encoder->avcctx->sample_rate; -// output->frame->channel_layout = output->encoder->avcctx->channel_layout; -// if (!output->frame->channel_layout) -// output->frame->channel_layout = av_get_default_channel_layout(output->encoder->avcctx->channels); -// if (av_frame_get_buffer(output->frame, 0) < 0) -// abort(); - -// output->fifo = av_audio_fifo_alloc(output->encoder->avcctx->sample_fmt, output->encoder->avcctx->channels, -// output->frame->nb_samples); - +done: db_config_stream(output); return 0; @@ -183,25 +132,12 @@ static void output_shutdown(output_t *output) { av_write_trailer(output->fmtctx); avio_closep(&output->fmtctx->pb); } -// avcodec_close(output->avcctx); -//#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 0, 0) -// avcodec_free_context(&output->avcctx); -//#endif avformat_free_context(output->fmtctx); -// av_audio_fifo_free(output->fifo); -// av_frame_free(&output->frame); encoder_close(output->encoder); -// output->avcctx = NULL; output->fmtctx = NULL; output->avst = NULL; -// output->fifo = NULL; - -// output->fifo_pts = 0; - -// format_init(&output->requested_format); -// format_init(&output->actual_format); } diff --git a/recording-daemon/packet.c b/recording-daemon/packet.c index 91b1e0d12..ec27f8ec9 100644 --- a/recording-daemon/packet.c +++ b/recording-daemon/packet.c @@ -87,7 +87,12 @@ static void packet_decode(ssrc_t *ssrc, packet_t *packet) { dbg("payload type for %u is %s", payload_type, payload_str); - ssrc->decoders[payload_type] = decoder_new(payload_str); + output_t *outp = NULL; + if (ssrc->output) + outp = ssrc->output; + else if (mf->mix_out) + outp = mf->mix_out; + ssrc->decoders[payload_type] = decoder_new(payload_str, outp); if (!ssrc->decoders[payload_type]) { ilog(LOG_WARN, "Cannot decode RTP payload type %u (%s)", payload_type, payload_str);