2007-12-13 12:38:17 +00:00
|
|
|
/*
|
|
|
|
* audio filter for runtime AC-3 encoding with libavcodec.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2007 Ulion <ulion A gmail P com>
|
|
|
|
*
|
2015-04-13 07:36:54 +00:00
|
|
|
* This file is part of mpv.
|
2007-12-13 12:38:17 +00:00
|
|
|
*
|
2017-05-09 10:46:40 +00:00
|
|
|
* mpv is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
2007-12-13 12:38:17 +00:00
|
|
|
*
|
2015-04-13 07:36:54 +00:00
|
|
|
* mpv is distributed in the hope that it will be useful,
|
2007-12-13 12:38:17 +00:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2017-05-09 10:46:40 +00:00
|
|
|
* GNU Lesser General Public License for more details.
|
2007-12-13 12:38:17 +00:00
|
|
|
*
|
2017-05-09 10:46:40 +00:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
2007-12-13 12:38:17 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <inttypes.h>
|
2010-05-14 00:54:31 +00:00
|
|
|
#include <assert.h>
|
2007-12-13 12:38:17 +00:00
|
|
|
|
2012-02-01 18:01:16 +00:00
|
|
|
#include <libavcodec/avcodec.h>
|
|
|
|
#include <libavutil/intreadwrite.h>
|
2013-03-09 07:26:10 +00:00
|
|
|
#include <libavutil/common.h>
|
2014-09-23 17:34:14 +00:00
|
|
|
#include <libavutil/bswap.h>
|
2012-08-15 20:23:02 +00:00
|
|
|
#include <libavutil/mem.h>
|
2012-02-01 18:01:16 +00:00
|
|
|
|
2022-06-14 19:36:54 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
#include "audio/aframe.h"
|
2022-06-14 19:36:54 +00:00
|
|
|
#include "audio/chmap_avchannel.h"
|
2016-06-23 09:18:11 +00:00
|
|
|
#include "audio/chmap_sel.h"
|
2013-11-11 11:08:23 +00:00
|
|
|
#include "audio/fmt-conversion.h"
|
2018-01-18 13:44:20 +00:00
|
|
|
#include "audio/format.h"
|
|
|
|
#include "common/av_common.h"
|
|
|
|
#include "common/common.h"
|
|
|
|
#include "filters/f_autoconvert.h"
|
|
|
|
#include "filters/f_utils.h"
|
|
|
|
#include "filters/filter_internal.h"
|
|
|
|
#include "filters/user_filters.h"
|
|
|
|
#include "options/m_option.h"
|
2007-12-13 12:38:17 +00:00
|
|
|
|
2010-05-14 00:54:31 +00:00
|
|
|
|
|
|
|
#define AC3_MAX_CHANNELS 6
|
|
|
|
#define AC3_MAX_CODED_FRAME_SIZE 3840
|
|
|
|
#define AC3_FRAME_SIZE (6 * 256)
|
2022-01-09 17:05:10 +00:00
|
|
|
const static uint16_t ac3_bitrate_tab[19] = {
|
2010-05-14 00:54:31 +00:00
|
|
|
32, 40, 48, 56, 64, 80, 96, 112, 128,
|
|
|
|
160, 192, 224, 256, 320, 384, 448, 512, 576, 640
|
|
|
|
};
|
2007-12-13 12:38:17 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
struct f_opts {
|
2023-02-20 03:32:50 +00:00
|
|
|
bool add_iec61937_header;
|
2018-01-18 13:44:20 +00:00
|
|
|
int bit_rate;
|
|
|
|
int min_channel_num;
|
|
|
|
char *encoder;
|
|
|
|
char **avopts;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct priv {
|
|
|
|
struct f_opts *opts;
|
|
|
|
|
|
|
|
struct mp_pin *in_pin;
|
|
|
|
struct mp_aframe *cur_format;
|
|
|
|
struct mp_aframe *in_frame;
|
|
|
|
struct mp_aframe_pool *out_pool;
|
|
|
|
|
2021-05-01 19:53:56 +00:00
|
|
|
const struct AVCodec *lavc_acodec;
|
2007-12-13 12:38:17 +00:00
|
|
|
struct AVCodecContext *lavc_actx;
|
2022-01-09 17:03:45 +00:00
|
|
|
AVPacket *lavc_pkt;
|
2007-12-13 12:38:17 +00:00
|
|
|
int bit_rate;
|
2013-11-11 11:08:23 +00:00
|
|
|
int out_samples; // upper bound on encoded output per AC3 frame
|
2018-01-18 13:44:20 +00:00
|
|
|
};
|
2016-06-23 09:18:11 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
static bool reinit(struct mp_filter *f)
|
|
|
|
{
|
|
|
|
struct priv *s = f->priv;
|
2016-06-23 09:18:11 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
mp_aframe_reset(s->cur_format);
|
2016-06-23 09:18:11 +00:00
|
|
|
|
2007-12-13 12:38:17 +00:00
|
|
|
static const int default_bit_rate[AC3_MAX_CHANNELS+1] = \
|
|
|
|
{0, 96000, 192000, 256000, 384000, 448000, 448000};
|
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
if (s->opts->add_iec61937_header) {
|
|
|
|
s->out_samples = AC3_FRAME_SIZE;
|
|
|
|
} else {
|
|
|
|
s->out_samples = AC3_MAX_CODED_FRAME_SIZE /
|
|
|
|
mp_aframe_get_sstride(s->in_frame);
|
|
|
|
}
|
2010-10-14 19:28:09 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
int format = mp_aframe_get_format(s->in_frame);
|
|
|
|
int rate = mp_aframe_get_rate(s->in_frame);
|
|
|
|
struct mp_chmap chmap = {0};
|
|
|
|
mp_aframe_get_chmap(s->in_frame, &chmap);
|
2007-12-13 12:38:17 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
int bit_rate = s->bit_rate;
|
|
|
|
if (!bit_rate && chmap.num < AC3_MAX_CHANNELS + 1)
|
|
|
|
bit_rate = default_bit_rate[chmap.num];
|
2007-12-13 12:38:17 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
avcodec_close(s->lavc_actx);
|
2007-12-13 12:38:17 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
// Put sample parameters
|
|
|
|
s->lavc_actx->sample_fmt = af_to_avformat(format);
|
2022-06-14 19:36:54 +00:00
|
|
|
|
|
|
|
#if !HAVE_AV_CHANNEL_LAYOUT
|
2018-01-18 13:44:20 +00:00
|
|
|
s->lavc_actx->channels = chmap.num;
|
|
|
|
s->lavc_actx->channel_layout = mp_chmap_to_lavc(&chmap);
|
2022-06-14 19:36:54 +00:00
|
|
|
#else
|
|
|
|
mp_chmap_to_av_layout(&s->lavc_actx->ch_layout, &chmap);
|
|
|
|
#endif
|
2018-01-18 13:44:20 +00:00
|
|
|
s->lavc_actx->sample_rate = rate;
|
|
|
|
s->lavc_actx->bit_rate = bit_rate;
|
2016-06-23 09:18:11 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
if (avcodec_open2(s->lavc_actx, s->lavc_acodec, NULL) < 0) {
|
|
|
|
MP_ERR(f, "Couldn't open codec %s, br=%d.\n", "ac3", bit_rate);
|
|
|
|
return false;
|
2013-11-11 11:08:11 +00:00
|
|
|
}
|
2013-03-09 07:26:10 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
if (s->lavc_actx->frame_size < 1) {
|
|
|
|
MP_ERR(f, "encoder didn't specify input frame size\n");
|
|
|
|
return false;
|
2007-12-13 12:38:17 +00:00
|
|
|
}
|
2018-01-18 13:44:20 +00:00
|
|
|
|
|
|
|
mp_aframe_config_copy(s->cur_format, s->in_frame);
|
|
|
|
return true;
|
2007-12-13 12:38:17 +00:00
|
|
|
}
|
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
static void reset(struct mp_filter *f)
|
2015-06-15 12:33:48 +00:00
|
|
|
{
|
2018-01-18 13:44:20 +00:00
|
|
|
struct priv *s = f->priv;
|
|
|
|
|
|
|
|
TA_FREEP(&s->in_frame);
|
2015-06-15 12:33:48 +00:00
|
|
|
}
|
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
static void destroy(struct mp_filter *f)
|
2015-01-14 21:16:08 +00:00
|
|
|
{
|
2018-01-18 13:44:20 +00:00
|
|
|
struct priv *s = f->priv;
|
2015-01-14 21:16:08 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
reset(f);
|
2022-01-09 17:03:45 +00:00
|
|
|
av_packet_free(&s->lavc_pkt);
|
2018-01-18 13:44:20 +00:00
|
|
|
avcodec_free_context(&s->lavc_actx);
|
2015-01-14 21:16:08 +00:00
|
|
|
}
|
|
|
|
|
2014-09-23 17:34:14 +00:00
|
|
|
static void swap_16(uint16_t *ptr, size_t size)
|
|
|
|
{
|
|
|
|
for (size_t n = 0; n < size; n++)
|
|
|
|
ptr[n] = av_bswap16(ptr[n]);
|
|
|
|
}
|
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
static void process(struct mp_filter *f)
|
2015-01-14 21:16:08 +00:00
|
|
|
{
|
2018-01-18 13:44:20 +00:00
|
|
|
struct priv *s = f->priv;
|
2012-12-03 19:16:17 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
if (!mp_pin_in_needs_data(f->ppins[1]))
|
|
|
|
return;
|
2016-06-23 10:03:02 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
bool err = true;
|
|
|
|
struct mp_aframe *out = NULL;
|
2022-01-09 17:03:45 +00:00
|
|
|
AVPacket *pkt = s->lavc_pkt;
|
2015-11-04 15:50:16 +00:00
|
|
|
|
2016-06-23 10:03:02 +00:00
|
|
|
// Send input as long as it wants.
|
|
|
|
while (1) {
|
2018-01-18 13:44:20 +00:00
|
|
|
if (avcodec_is_open(s->lavc_actx)) {
|
2022-01-09 17:03:45 +00:00
|
|
|
int lavc_ret = avcodec_receive_packet(s->lavc_actx, pkt);
|
2018-01-18 13:44:20 +00:00
|
|
|
if (lavc_ret >= 0)
|
|
|
|
break;
|
|
|
|
if (lavc_ret < 0 && lavc_ret != AVERROR(EAGAIN)) {
|
|
|
|
MP_FATAL(f, "Encode failed (receive).\n");
|
2021-12-13 12:26:34 +00:00
|
|
|
goto error;
|
2018-01-18 13:44:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
AVFrame *frame = NULL;
|
|
|
|
struct mp_frame input = mp_pin_out_read(s->in_pin);
|
|
|
|
// The following code assumes no sample data buffering in the encoder.
|
2021-12-13 12:26:34 +00:00
|
|
|
switch (input.type) {
|
|
|
|
case MP_FRAME_NONE:
|
|
|
|
goto done; // no data yet
|
|
|
|
case MP_FRAME_EOF:
|
2018-01-18 13:44:20 +00:00
|
|
|
mp_pin_in_write(f->ppins[1], input);
|
2021-12-13 12:26:34 +00:00
|
|
|
goto done;
|
|
|
|
case MP_FRAME_AUDIO:
|
2018-01-18 13:44:20 +00:00
|
|
|
TA_FREEP(&s->in_frame);
|
|
|
|
s->in_frame = input.data;
|
|
|
|
frame = mp_frame_to_av(input, NULL);
|
|
|
|
if (!frame)
|
2021-12-13 12:26:34 +00:00
|
|
|
goto error;
|
2018-01-18 13:44:20 +00:00
|
|
|
if (mp_aframe_get_channels(s->in_frame) < s->opts->min_channel_num) {
|
|
|
|
// Just pass it through.
|
|
|
|
s->in_frame = NULL;
|
|
|
|
mp_pin_in_write(f->ppins[1], input);
|
2021-12-13 12:26:34 +00:00
|
|
|
goto done;
|
2018-01-18 13:44:20 +00:00
|
|
|
}
|
|
|
|
if (!mp_aframe_config_equals(s->in_frame, s->cur_format)) {
|
|
|
|
if (!reinit(f))
|
2021-12-13 12:26:34 +00:00
|
|
|
goto error;
|
2018-01-18 13:44:20 +00:00
|
|
|
}
|
2021-12-13 12:26:34 +00:00
|
|
|
break;
|
|
|
|
default: goto error; // unexpected packet type
|
2018-01-18 13:44:20 +00:00
|
|
|
}
|
2016-06-23 10:03:02 +00:00
|
|
|
int lavc_ret = avcodec_send_frame(s->lavc_actx, frame);
|
2018-01-18 13:44:20 +00:00
|
|
|
av_frame_free(&frame);
|
|
|
|
if (lavc_ret < 0 && lavc_ret != AVERROR(EAGAIN)) {
|
|
|
|
MP_FATAL(f, "Encode failed (send).\n");
|
2021-12-13 12:26:34 +00:00
|
|
|
goto error;
|
2016-06-23 10:03:02 +00:00
|
|
|
}
|
2016-07-31 16:48:21 +00:00
|
|
|
}
|
2013-03-09 07:26:10 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
if (!s->in_frame)
|
2021-12-13 12:26:34 +00:00
|
|
|
goto error;
|
2007-12-13 12:38:17 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
out = mp_aframe_create();
|
|
|
|
mp_aframe_set_format(out, AF_FORMAT_S_AC3);
|
|
|
|
mp_aframe_set_chmap(out, &(struct mp_chmap)MP_CHMAP_INIT_STEREO);
|
|
|
|
mp_aframe_set_rate(out, 48000);
|
2016-08-01 17:59:59 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
if (mp_aframe_pool_allocate(s->out_pool, out, s->out_samples) < 0)
|
2021-12-13 12:26:34 +00:00
|
|
|
goto error;
|
2018-01-18 13:44:20 +00:00
|
|
|
|
|
|
|
int sstride = mp_aframe_get_sstride(out);
|
|
|
|
|
|
|
|
mp_aframe_copy_attributes(out, s->in_frame);
|
2007-12-13 12:38:17 +00:00
|
|
|
|
2022-01-09 17:03:45 +00:00
|
|
|
int frame_size = pkt->size;
|
2015-01-14 21:16:08 +00:00
|
|
|
int header_len = 0;
|
|
|
|
char hdr[8];
|
2007-12-13 12:38:17 +00:00
|
|
|
|
2022-01-09 17:03:45 +00:00
|
|
|
if (s->opts->add_iec61937_header && pkt->size > 5) {
|
|
|
|
int bsmod = pkt->data[5] & 0x7;
|
2015-01-14 21:16:08 +00:00
|
|
|
int len = frame_size;
|
2013-11-11 11:08:23 +00:00
|
|
|
|
2015-01-14 21:16:08 +00:00
|
|
|
frame_size = AC3_FRAME_SIZE * 2 * 2;
|
|
|
|
header_len = 8;
|
2007-12-13 12:38:17 +00:00
|
|
|
|
2015-01-14 21:16:08 +00:00
|
|
|
AV_WL16(hdr, 0xF872); // iec 61937 syncword 1
|
|
|
|
AV_WL16(hdr + 2, 0x4E1F); // iec 61937 syncword 2
|
|
|
|
hdr[5] = bsmod; // bsmod
|
|
|
|
hdr[4] = 0x01; // data-type ac3
|
|
|
|
AV_WL16(hdr + 6, len << 3); // number of bits in payload
|
2007-12-13 12:38:17 +00:00
|
|
|
}
|
2013-11-11 11:08:23 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
if (frame_size > s->out_samples * sstride)
|
2015-01-14 21:16:08 +00:00
|
|
|
abort();
|
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
uint8_t **planes = mp_aframe_get_data_rw(out);
|
|
|
|
if (!planes)
|
2021-12-13 12:26:34 +00:00
|
|
|
goto error;
|
2018-01-18 13:44:20 +00:00
|
|
|
char *buf = planes[0];
|
2015-01-14 21:16:08 +00:00
|
|
|
memcpy(buf, hdr, header_len);
|
2022-01-09 17:03:45 +00:00
|
|
|
memcpy(buf + header_len, pkt->data, pkt->size);
|
|
|
|
memset(buf + header_len + pkt->size, 0,
|
|
|
|
frame_size - (header_len + pkt->size));
|
|
|
|
swap_16((uint16_t *)(buf + header_len), pkt->size / 2);
|
2018-01-18 13:44:20 +00:00
|
|
|
mp_aframe_set_size(out, frame_size / sstride);
|
|
|
|
mp_pin_in_write(f->ppins[1], MAKE_FRAME(MP_FRAME_AUDIO, out));
|
|
|
|
out = NULL;
|
2015-11-04 15:50:16 +00:00
|
|
|
|
|
|
|
done:
|
2021-12-13 12:26:34 +00:00
|
|
|
err = false;
|
|
|
|
// fall through
|
|
|
|
error:
|
2022-01-09 17:03:45 +00:00
|
|
|
av_packet_unref(pkt);
|
2018-01-18 13:44:20 +00:00
|
|
|
talloc_free(out);
|
|
|
|
if (err)
|
|
|
|
mp_filter_internal_mark_failed(f);
|
2007-12-13 12:38:17 +00:00
|
|
|
}
|
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
static const struct mp_filter_info af_lavcac3enc_filter = {
|
|
|
|
.name = "lavcac3enc",
|
|
|
|
.priv_size = sizeof(struct priv),
|
|
|
|
.process = process,
|
|
|
|
.reset = reset,
|
|
|
|
.destroy = destroy,
|
|
|
|
};
|
2007-12-13 12:38:17 +00:00
|
|
|
|
2022-06-14 19:36:54 +00:00
|
|
|
static void add_chmaps_to_autoconv(struct mp_filter *f,
|
|
|
|
struct mp_autoconvert *conv,
|
2022-06-14 19:19:45 +00:00
|
|
|
const struct AVCodec *codec)
|
|
|
|
{
|
2022-06-14 19:36:54 +00:00
|
|
|
#if !HAVE_AV_CHANNEL_LAYOUT
|
2022-06-14 19:19:45 +00:00
|
|
|
const uint64_t *lch = codec->channel_layouts;
|
|
|
|
for (int n = 0; lch && lch[n]; n++) {
|
|
|
|
struct mp_chmap chmap = {0};
|
|
|
|
mp_chmap_from_lavc(&chmap, lch[n]);
|
|
|
|
if (mp_chmap_is_valid(&chmap))
|
|
|
|
mp_autoconvert_add_chmap(conv, &chmap);
|
|
|
|
}
|
2022-06-14 19:36:54 +00:00
|
|
|
#else
|
|
|
|
const AVChannelLayout *lch = codec->ch_layouts;
|
|
|
|
for (int n = 0; lch && lch[n].nb_channels; n++) {
|
|
|
|
struct mp_chmap chmap = {0};
|
|
|
|
|
|
|
|
if (!mp_chmap_from_av_layout(&chmap, &lch[n])) {
|
|
|
|
char layout[128] = {0};
|
|
|
|
MP_VERBOSE(f, "Skipping unsupported channel layout: %s\n",
|
|
|
|
av_channel_layout_describe(&lch[n],
|
|
|
|
layout, 128) < 0 ?
|
|
|
|
"undefined" : layout);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mp_chmap_is_valid(&chmap))
|
|
|
|
mp_autoconvert_add_chmap(conv, &chmap);
|
|
|
|
}
|
|
|
|
#endif
|
2022-06-14 19:19:45 +00:00
|
|
|
}
|
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
static struct mp_filter *af_lavcac3enc_create(struct mp_filter *parent,
|
|
|
|
void *options)
|
|
|
|
{
|
|
|
|
struct mp_filter *f = mp_filter_create(parent, &af_lavcac3enc_filter);
|
|
|
|
if (!f) {
|
|
|
|
talloc_free(options);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
mp_filter_add_pin(f, MP_PIN_IN, "in");
|
|
|
|
mp_filter_add_pin(f, MP_PIN_OUT, "out");
|
2007-12-13 12:38:17 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
struct priv *s = f->priv;
|
|
|
|
s->opts = talloc_steal(s, options);
|
|
|
|
s->cur_format = talloc_steal(s, mp_aframe_create());
|
|
|
|
s->out_pool = mp_aframe_pool_create(s);
|
|
|
|
|
|
|
|
s->lavc_acodec = avcodec_find_encoder_by_name(s->opts->encoder);
|
2007-12-13 12:38:17 +00:00
|
|
|
if (!s->lavc_acodec) {
|
2018-01-18 13:44:20 +00:00
|
|
|
MP_ERR(f, "Couldn't find encoder %s.\n", s->opts->encoder);
|
|
|
|
goto error;
|
2007-12-13 12:38:17 +00:00
|
|
|
}
|
|
|
|
|
2012-01-28 11:41:36 +00:00
|
|
|
s->lavc_actx = avcodec_alloc_context3(s->lavc_acodec);
|
2007-12-13 12:38:17 +00:00
|
|
|
if (!s->lavc_actx) {
|
2018-01-18 13:44:20 +00:00
|
|
|
MP_ERR(f, "Audio LAVC, couldn't allocate context!\n");
|
|
|
|
goto error;
|
2007-12-13 12:38:17 +00:00
|
|
|
}
|
2016-08-09 10:23:04 +00:00
|
|
|
|
2022-01-09 17:03:45 +00:00
|
|
|
s->lavc_pkt = av_packet_alloc();
|
|
|
|
if (!s->lavc_pkt)
|
|
|
|
goto error;
|
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
if (mp_set_avopts(f->log, s->lavc_actx, s->opts->avopts) < 0)
|
|
|
|
goto error;
|
2016-08-09 10:23:04 +00:00
|
|
|
|
2022-01-09 17:05:10 +00:00
|
|
|
// For this one, we require the decoder to export lists of all supported
|
2016-06-23 09:18:11 +00:00
|
|
|
// parameters. (Not all decoders do that, but the ones we're interested
|
|
|
|
// in do.)
|
|
|
|
if (!s->lavc_acodec->sample_fmts ||
|
2022-06-14 19:36:54 +00:00
|
|
|
#if !HAVE_AV_CHANNEL_LAYOUT
|
|
|
|
!s->lavc_acodec->channel_layouts
|
|
|
|
#else
|
|
|
|
!s->lavc_acodec->ch_layouts
|
|
|
|
#endif
|
|
|
|
)
|
2016-06-23 09:18:11 +00:00
|
|
|
{
|
2018-01-18 13:44:20 +00:00
|
|
|
MP_ERR(f, "Audio encoder doesn't list supported parameters.\n");
|
|
|
|
goto error;
|
2013-11-11 11:08:23 +00:00
|
|
|
}
|
2012-12-03 19:16:17 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
if (s->opts->bit_rate) {
|
2013-11-14 23:13:04 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < 19; i++) {
|
2018-01-18 13:44:20 +00:00
|
|
|
if (ac3_bitrate_tab[i] == s->opts->bit_rate) {
|
2016-06-23 08:43:54 +00:00
|
|
|
s->bit_rate = ac3_bitrate_tab[i] * 1000;
|
2013-11-14 23:13:04 +00:00
|
|
|
break;
|
2016-06-23 08:43:54 +00:00
|
|
|
}
|
2013-11-14 23:13:04 +00:00
|
|
|
}
|
|
|
|
if (i >= 19) {
|
2018-01-18 13:44:20 +00:00
|
|
|
MP_WARN(f, "unable set unsupported bitrate %d, using default "
|
2016-06-23 08:45:56 +00:00
|
|
|
"bitrate (check manpage to see supported bitrates).\n",
|
2018-01-18 13:44:20 +00:00
|
|
|
s->opts->bit_rate);
|
2013-11-14 23:13:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
struct mp_autoconvert *conv = mp_autoconvert_create(f);
|
|
|
|
if (!conv)
|
|
|
|
abort();
|
2007-12-13 12:38:17 +00:00
|
|
|
|
2018-01-18 13:44:20 +00:00
|
|
|
const enum AVSampleFormat *lf = s->lavc_acodec->sample_fmts;
|
|
|
|
for (int i = 0; lf && lf[i] != AV_SAMPLE_FMT_NONE; i++) {
|
|
|
|
int mpfmt = af_from_avformat(lf[i]);
|
|
|
|
if (mpfmt)
|
|
|
|
mp_autoconvert_add_afmt(conv, mpfmt);
|
|
|
|
}
|
2013-11-14 23:13:04 +00:00
|
|
|
|
2022-06-14 19:36:54 +00:00
|
|
|
add_chmaps_to_autoconv(f, conv, s->lavc_acodec);
|
2018-01-18 13:44:20 +00:00
|
|
|
|
|
|
|
// At least currently, the AC3 encoder doesn't export sample rates.
|
|
|
|
mp_autoconvert_add_srate(conv, 48000);
|
|
|
|
|
|
|
|
mp_pin_connect(conv->f->pins[0], f->ppins[0]);
|
|
|
|
|
|
|
|
struct mp_filter *fs = mp_fixed_aframe_size_create(f, AC3_FRAME_SIZE, true);
|
|
|
|
if (!fs)
|
|
|
|
abort();
|
|
|
|
|
|
|
|
mp_pin_connect(fs->pins[0], conv->f->pins[1]);
|
|
|
|
s->in_pin = fs->pins[1];
|
|
|
|
|
|
|
|
return f;
|
|
|
|
|
|
|
|
error:
|
2022-01-09 17:03:45 +00:00
|
|
|
av_packet_free(&s->lavc_pkt);
|
2022-01-09 17:05:10 +00:00
|
|
|
avcodec_free_context(&s->lavc_actx);
|
2018-01-18 13:44:20 +00:00
|
|
|
talloc_free(f);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define OPT_BASE_STRUCT struct f_opts
|
|
|
|
|
|
|
|
const struct mp_user_filter_entry af_lavcac3enc = {
|
|
|
|
.desc = {
|
|
|
|
.description = "runtime encode to ac3 using libavcodec",
|
|
|
|
.name = "lavcac3enc",
|
|
|
|
.priv_size = sizeof(OPT_BASE_STRUCT),
|
|
|
|
.priv_defaults = &(const OPT_BASE_STRUCT) {
|
2023-02-20 03:32:50 +00:00
|
|
|
.add_iec61937_header = true,
|
2018-01-18 13:44:20 +00:00
|
|
|
.bit_rate = 640,
|
|
|
|
.min_channel_num = 3,
|
|
|
|
.encoder = "ac3",
|
|
|
|
},
|
|
|
|
.options = (const struct m_option[]) {
|
2023-02-20 03:32:50 +00:00
|
|
|
{"tospdif", OPT_BOOL(add_iec61937_header)},
|
options: change option macros and all option declarations
Change all OPT_* macros such that they don't define the entire m_option
initializer, and instead expand only to a part of it, which sets certain
fields. This requires changing almost every option declaration, because
they all use these macros. A declaration now always starts with
{"name", ...
followed by designated initializers only (possibly wrapped in macros).
The OPT_* macros now initialize the .offset and .type fields only,
sometimes also .priv and others.
I think this change makes the option macros less tricky. The old code
had to stuff everything into macro arguments (and attempted to allow
setting arbitrary fields by letting the user pass designated
initializers in the vararg parts). Some of this was made messy due to
C99 and C11 not allowing 0-sized varargs with ',' removal. It's also
possible that this change is pointless, other than cosmetic preferences.
Not too happy about some things. For example, the OPT_CHOICE()
indentation I applied looks a bit ugly.
Much of this change was done with regex search&replace, but some places
required manual editing. In particular, code in "obscure" areas (which I
didn't include in compilation) might be broken now.
In wayland_common.c the author of some option declarations confused the
flags parameter with the default value (though the default value was
also properly set below). I fixed this with this change.
2020-03-14 20:28:01 +00:00
|
|
|
{"bitrate", OPT_CHOICE(bit_rate,
|
|
|
|
{"auto", 0}, {"default", 0}), M_RANGE(32, 640)},
|
|
|
|
{"minch", OPT_INT(min_channel_num), M_RANGE(2, 6)},
|
|
|
|
{"encoder", OPT_STRING(encoder)},
|
|
|
|
{"o", OPT_KEYVALUELIST(avopts)},
|
2018-01-18 13:44:20 +00:00
|
|
|
{0}
|
|
|
|
},
|
2013-11-14 23:13:04 +00:00
|
|
|
},
|
2018-01-18 13:44:20 +00:00
|
|
|
.create = af_lavcac3enc_create,
|
2007-12-13 12:38:17 +00:00
|
|
|
};
|