diff options
author | Martin Herkt <lachs0r@srsfckn.biz> | 2016-06-25 02:25:44 +0200 |
---|---|---|
committer | Martin Herkt <lachs0r@srsfckn.biz> | 2016-06-25 02:25:44 +0200 |
commit | ad56f2c46ac6deec86870ec10f2a11a644df07d4 (patch) | |
tree | 89f2d90c5586560911e67c872b530c77f151168d /audio/filter/af_lavcac3enc.c | |
parent | 0536841647ef7931bffb4386d8ffbb5b2b568e8a (diff) | |
parent | 393bb2a565dc1e27812e1dd20747814892f80da2 (diff) | |
download | mpv-ad56f2c46ac6deec86870ec10f2a11a644df07d4.tar.bz2 mpv-ad56f2c46ac6deec86870ec10f2a11a644df07d4.tar.xz |
Merge branch 'master' into release/current
Diffstat (limited to 'audio/filter/af_lavcac3enc.c')
-rw-r--r-- | audio/filter/af_lavcac3enc.c | 180 |
1 files changed, 132 insertions, 48 deletions
diff --git a/audio/filter/af_lavcac3enc.c b/audio/filter/af_lavcac3enc.c index 973e688aaa..26c9cbff58 100644 --- a/audio/filter/af_lavcac3enc.c +++ b/audio/filter/af_lavcac3enc.c @@ -31,9 +31,12 @@ #include <libavutil/bswap.h> #include <libavutil/mem.h> +#include "config.h" + #include "common/common.h" #include "af.h" #include "audio/audio_buffer.h" +#include "audio/chmap_sel.h" #include "audio/fmt-conversion.h" @@ -54,13 +57,50 @@ typedef struct af_ac3enc_s { struct mp_audio *pending; // unconsumed input data int in_samples; // samples of input per AC3 frame int out_samples; // upper bound on encoded output per AC3 frame - int in_sampleformat; int cfg_add_iec61937_header; int cfg_bit_rate; int cfg_min_channel_num; + char *cfg_encoder; } af_ac3enc_t; +// fmt carries the input format. Change it to the best next-possible format +// the encoder likely accepts. +static void select_encode_format(AVCodecContext *c, struct mp_audio *fmt) +{ + int formats[AF_FORMAT_COUNT]; + af_get_best_sample_formats(fmt->format, formats); + + for (int n = 0; formats[n]; n++) { + const enum AVSampleFormat *lf = c->codec->sample_fmts; + for (int i = 0; lf && lf[i] != AV_SAMPLE_FMT_NONE; i++) { + int mpfmt = af_from_avformat(lf[i]); + if (mpfmt && mpfmt == formats[n]) { + mp_audio_set_format(fmt, mpfmt); + goto done_fmt; + } + } + } +done_fmt: ; + + int rate = + af_select_best_samplerate(fmt->rate, c->codec->supported_samplerates); + if (rate > 0) + fmt->rate = rate; + + struct mp_chmap_sel sel = {0}; + const uint64_t *lch = c->codec->channel_layouts; + for (int n = 0; lch && lch[n]; n++) { + struct mp_chmap chmap = {0}; + mp_chmap_from_lavc(&chmap, lch[n]); + mp_chmap_sel_add_map(&sel, &chmap); + } + struct mp_chmap res = fmt->channels; + mp_chmap_sel_adjust(&sel, &res); + if (!mp_chmap_is_empty(&res)) + mp_audio_set_channels(fmt, &res); +} + // Initialization and runtime control static int control(struct af_instance *af, int cmd, void *arg) { @@ -76,23 +116,17 @@ static int control(struct af_instance *af, int cmd, void *arg) if (!af_fmt_is_pcm(in->format) || in->nch < s->cfg_min_channel_num) return AF_DETACH; - mp_audio_set_format(in, s->in_sampleformat); + // At least currently, the AC3 encoder doesn't export sample rates. + in->rate = 48000; + select_encode_format(s->lavc_actx, in); - if (in->rate != 48000 && in->rate != 44100 && in->rate != 32000) - in->rate = 48000; af->data->rate = in->rate; - - mp_chmap_reorder_to_lavc(&in->channels); - if (in->nch > AC3_MAX_CHANNELS) - mp_audio_set_num_channels(in, AC3_MAX_CHANNELS); - mp_audio_set_format(af->data, AF_FORMAT_S_AC3); mp_audio_set_num_channels(af->data, 2); if (!mp_audio_config_equals(in, &orig_in)) return AF_FALSE; - s->in_samples = AC3_FRAME_SIZE; if (s->cfg_add_iec61937_header) { s->out_samples = AC3_FRAME_SIZE; } else { @@ -100,14 +134,11 @@ static int control(struct af_instance *af, int cmd, void *arg) } mp_audio_copy_config(s->input, in); - mp_audio_realloc(s->input, s->in_samples); - s->input->samples = 0; talloc_free(s->pending); s->pending = NULL; - MP_DBG(af, "af_lavcac3enc reinit: %d, %d, %d.\n", - in->nch, in->rate, s->in_samples); + MP_DBG(af, "reinit: %d, %d, %d.\n", in->nch, in->rate, s->in_samples); int bit_rate = s->bit_rate ? s->bit_rate : default_bit_rate[in->nch]; @@ -118,6 +149,7 @@ static int control(struct af_instance *af, int cmd, void *arg) avcodec_close(s->lavc_actx); // Put sample parameters + s->lavc_actx->sample_fmt = af_to_avformat(in->format); s->lavc_actx->channels = in->nch; s->lavc_actx->channel_layout = mp_chmap_to_lavc(&in->channels); s->lavc_actx->sample_rate = in->rate; @@ -127,14 +159,24 @@ static int control(struct af_instance *af, int cmd, void *arg) MP_ERR(af, "Couldn't open codec %s, br=%d.\n", "ac3", bit_rate); return AF_ERROR; } + + if (s->lavc_actx->frame_size < 1) { + MP_ERR(af, "encoder didn't specify input frame size\n"); + return AF_ERROR; + } } - if (s->lavc_actx->frame_size != AC3_FRAME_SIZE) { - MP_ERR(af, "lavcac3enc: unexpected ac3 " - "encoder frame size %d\n", s->lavc_actx->frame_size); - return AF_ERROR; - } + s->in_samples = s->lavc_actx->frame_size; + mp_audio_realloc(s->input, s->in_samples); + s->input->samples = 0; return AF_OK; } + case AF_CONTROL_RESET: + if (avcodec_is_open(s->lavc_actx)) + avcodec_flush_buffers(s->lavc_actx); + talloc_free(s->pending); + s->pending = NULL; + s->input->samples = 0; + return AF_OK; } return AF_UNKNOWN; } @@ -199,31 +241,75 @@ static bool fill_buffer(struct af_instance *af) return s->input->samples >= s->in_samples; } -static int filter_out(struct af_instance *af) +// Return <0 on error, 0 on need more input, 1 on success (and *frame set). +// To actually advance the read pointer, set s->input->samples=0 afterwards. +static int read_input_frame(struct af_instance *af, AVFrame *frame) { af_ac3enc_t *s = af->priv; if (!fill_buffer(af)) return 0; // need more input - AVFrame *frame = av_frame_alloc(); - if (!frame) { - MP_FATAL(af, "Could not allocate memory \n"); - return -1; - } - int err = -1; - frame->nb_samples = s->in_samples; frame->format = s->lavc_actx->sample_fmt; frame->channel_layout = s->lavc_actx->channel_layout; +#if LIBAVUTIL_VERSION_MICRO >= 100 + frame->channels = s->lavc_actx->channels; +#endif assert(s->input->num_planes <= AV_NUM_DATA_POINTERS); frame->extended_data = frame->data; for (int n = 0; n < s->input->num_planes; n++) frame->data[n] = s->input->planes[n]; frame->linesize[0] = s->input->samples * s->input->sstride; + return 1; +} + +static int filter_out(struct af_instance *af) +{ + af_ac3enc_t *s = af->priv; + + AVFrame *frame = av_frame_alloc(); + if (!frame) { + MP_FATAL(af, "Could not allocate memory \n"); + return -1; + } + int err = -1; + AVPacket pkt = {0}; av_init_packet(&pkt); +#if HAVE_AVCODEC_NEW_CODEC_API + // Send input as long as it wants. + while (1) { + err = read_input_frame(af, frame); + if (err < 0) + goto done; + if (err == 0) + break; + err = -1; + int lavc_ret = avcodec_send_frame(s->lavc_actx, frame); + // On EAGAIN, we're supposed to read remaining output. + if (lavc_ret == AVERROR(EAGAIN)) + break; + if (lavc_ret < 0) { + MP_FATAL(af, "Encode failed.\n"); + goto done; + } + s->input->samples = 0; + } + int lavc_ret = avcodec_receive_packet(s->lavc_actx, &pkt); + if (lavc_ret == AVERROR(EAGAIN)) { + // Need to buffer more input. + err = 0; + goto done; + } +#else + err = read_input_frame(af, frame); + if (err < 0) + goto done; + if (err == 0) + goto done; + err = -1; int ok; int lavc_ret = avcodec_encode_audio2(s->lavc_actx, &pkt, frame, &ok); av_frame_free(&frame); @@ -232,9 +318,10 @@ static int filter_out(struct af_instance *af) MP_FATAL(af, "Encode failed.\n"); goto done; } +#endif MP_DBG(af, "avcodec_encode_audio got %d, pending %d.\n", - pkt.size, s->pending->samples); + pkt.size, s->pending->samples); struct mp_audio *out = mp_audio_pool_get(af->out_pool, af->data, s->out_samples); @@ -287,9 +374,9 @@ static int af_open(struct af_instance* af){ af->filter_frame = filter_frame; af->filter_out = filter_out; - s->lavc_acodec = avcodec_find_encoder_by_name("ac3"); + s->lavc_acodec = avcodec_find_encoder_by_name(s->cfg_encoder); if (!s->lavc_acodec) { - MP_ERR(af, "Audio LAVC, couldn't find encoder for codec %s.\n", "ac3"); + MP_ERR(af, "Couldn't find encoder %s.\n", s->cfg_encoder); return AF_ERROR; } @@ -298,35 +385,30 @@ static int af_open(struct af_instance* af){ MP_ERR(af, "Audio LAVC, couldn't allocate context!\n"); return AF_ERROR; } - const enum AVSampleFormat *fmts = s->lavc_acodec->sample_fmts; - for (int i = 0; fmts[i] != AV_SAMPLE_FMT_NONE; i++) { - s->in_sampleformat = af_from_avformat(fmts[i]); - if (s->in_sampleformat) { - s->lavc_actx->sample_fmt = fmts[i]; - break; - } - } - if (!s->in_sampleformat) { - MP_ERR(af, "Audio LAVC, encoder doesn't " - "support expected sample formats!\n"); + // For this one, we require the decoder to expert lists of all supported + // parameters. (Not all decoders do that, but the ones we're interested + // in do.) + if (!s->lavc_acodec->sample_fmts || + !s->lavc_acodec->channel_layouts) + { + MP_ERR(af, "Audio encoder doesn't list supported parameters.\n"); return AF_ERROR; } - MP_VERBOSE(af, "[af_lavcac3enc]: in sample format: %s\n", - af_fmt_to_str(s->in_sampleformat)); s->input = talloc_zero(s, struct mp_audio); if (s->cfg_bit_rate) { int i; for (i = 0; i < 19; i++) { - if (ac3_bitrate_tab[i] == s->cfg_bit_rate) + if (ac3_bitrate_tab[i] == s->cfg_bit_rate) { + s->bit_rate = ac3_bitrate_tab[i] * 1000; break; + } } if (i >= 19) { - MP_WARN(af, "af_lavcac3enc unable set unsupported " - "bitrate %d, use default bitrate (check manpage to see " - "supported bitrates).\n", s->cfg_bit_rate); - s->cfg_bit_rate = 0; + MP_WARN(af, "unable set unsupported bitrate %d, use default " + "bitrate (check manpage to see supported bitrates).\n", + s->cfg_bit_rate); } } @@ -344,12 +426,14 @@ const struct af_info af_info_lavcac3enc = { .cfg_add_iec61937_header = 1, .cfg_bit_rate = 640, .cfg_min_channel_num = 3, + .cfg_encoder = "ac3", }, .options = (const struct m_option[]) { OPT_FLAG("tospdif", cfg_add_iec61937_header, 0), OPT_CHOICE_OR_INT("bitrate", cfg_bit_rate, 0, 32, 640, ({"auto", 0}, {"default", 0})), OPT_INTRANGE("minch", cfg_min_channel_num, 0, 2, 6), + OPT_STRING("encoder", cfg_encoder, 0), {0} }, }; |