c->sample_fmt = AV_SAMPLE_FMT_S16;
c->sample_rate = sri_to_rate(ssc->es_sri);
+#if LIBAVUTIL_VERSION_MAJOR > 57
+ c->ch_layout.nb_channels = ssc->es_channels;
+#else
c->channels = ssc->es_channels;
+#endif
#if 0
c->time_base.num = 1;
const int *
tvh_codec_profile_audio_get_sample_rates(TVHCodecProfile *self);
+#if LIBAVCODEC_VERSION_MAJOR > 59
+const AVChannelLayout *
+tvh_codec_profile_audio_get_channel_layouts(TVHCodecProfile *self);
+#else
const uint64_t *
tvh_codec_profile_audio_get_channel_layouts(TVHCodecProfile *self);
+#endif
/* module level ============================================================= */
self->sample_rates = default_sample_rates;
}
if (!self->channel_layouts) {
+#if LIBAVCODEC_VERSION_MAJOR > 59
+ self->channel_layouts = codec->ch_layouts;
+#else
self->channel_layouts = codec->channel_layouts;
+#endif
}
}
{ FF_PROFILE_UNKNOWN },
};
+#if LIBAVCODEC_VERSION_MAJOR > 59
+// see aac_chan_configs in ffmpeg-6.0/libavcodec/aacenctab.h
+static const AVChannelLayout aac_channel_layouts[] = {
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_SURROUND,
+ AV_CHANNEL_LAYOUT_4POINT0,
+ AV_CHANNEL_LAYOUT_5POINT0_BACK,
+ AV_CHANNEL_LAYOUT_5POINT1_BACK,
+ AV_CHANNEL_LAYOUT_7POINT1,
+};
+#else
// see aac_chan_configs in ffmpeg-3.0.2/libavcodec/aacenctab.h
static const uint64_t aac_channel_layouts[] = {
AV_CH_LAYOUT_MONO,
AV_CH_LAYOUT_7POINT1_WIDE_BACK,
0
};
+#endif
typedef struct {
/* flac ====================================================================== */
+#if LIBAVCODEC_VERSION_MAJOR > 59
+// see flac_channel_layouts ffmpeg-6.0/libavcodec/flac.c
+static const AVChannelLayout flac_channel_layouts[] = {
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_SURROUND,
+ AV_CHANNEL_LAYOUT_QUAD,
+ AV_CHANNEL_LAYOUT_5POINT0,
+ AV_CHANNEL_LAYOUT_5POINT1,
+ AV_CHANNEL_LAYOUT_6POINT1,
+ AV_CHANNEL_LAYOUT_7POINT1
+};
+#else
// see flac_channel_layouts ffmpeg-3.4/libavcodec/flac.c & flacenc.c
static const uint64_t flac_channel_layouts[] = {
AV_CH_LAYOUT_MONO,
AV_CH_LAYOUT_5POINT1_BACK,
0
};
+#endif
typedef struct {
/* libvorbis ================================================================ */
+#if LIBAVCODEC_VERSION_MAJOR > 59
+// see libvorbis_setup() in ffmpeg-6.0/libavcodec/libvorbisenc.c
+static const AVChannelLayout libvorbis_channel_layouts[] = {
+ AV_CHANNEL_LAYOUT_MONO,
+ AV_CHANNEL_LAYOUT_STEREO,
+ AV_CHANNEL_LAYOUT_SURROUND,
+ AV_CHANNEL_LAYOUT_2_2,
+ AV_CHANNEL_LAYOUT_QUAD,
+ AV_CHANNEL_LAYOUT_5POINT0,
+ AV_CHANNEL_LAYOUT_5POINT0_BACK,
+ AV_CHANNEL_LAYOUT_5POINT1,
+ AV_CHANNEL_LAYOUT_5POINT1_BACK,
+ AV_CHANNEL_LAYOUT_6POINT1,
+ AV_CHANNEL_LAYOUT_7POINT1
+};
+#else
// see libvorbis_setup() in ffmpeg-3.0.2/libavcodec/libvorbisenc.c
static const uint64_t libvorbis_channel_layouts[] = {
AV_CH_LAYOUT_MONO,
//AV_CH_LAYOUT_STEREO_DOWNMIX,
0
};
+#endif
static int
}
+#if LIBAVCODEC_VERSION_MAJOR > 59
+// see vorbis_encode_init() in ffmpeg-6.0/libavcodec/vorbis_data.c
+static const AVChannelLayout vorbis_channel_layouts[] = {
+ AV_CHANNEL_LAYOUT_STEREO
+};
+#else
// see vorbis_encode_init() in ffmpeg-3.0.2/libavcodec/vorbisenc.c
static const uint64_t vorbis_channel_layouts[] = {
AV_CH_LAYOUT_STEREO,
0
};
+#endif
static const codec_profile_class_t codec_profile_vorbis_class = {
TVHCodec;
const enum AVSampleFormat *sample_fmts;
const int *sample_rates;
+#if LIBAVCODEC_VERSION_MAJOR > 59
+ const AVChannelLayout *channel_layouts;
+#else
const uint64_t *channel_layouts;
+#endif
} TVHAudioCodec;
char *language3;
int sample_fmt;
int sample_rate;
+#if LIBAVCODEC_VERSION_MAJOR > 59
+ AVChannelLayout channel_layout;
+#else
int64_t channel_layout;
+#endif
} TVHAudioCodecProfile;
return tvh_codec_audio_getattr(codec, sample_rates);
}
+#if LIBAVCODEC_VERSION_MAJOR > 59
+const AVChannelLayout *
+tvh_codec_profile_audio_get_channel_layouts(TVHCodecProfile *self)
+#else
const uint64_t *
tvh_codec_profile_audio_get_channel_layouts(TVHCodecProfile *self)
+#endif
{
TVHCodec *codec = tvh_codec_profile_get_codec(self);
return tvh_codec_audio_getattr(codec, channel_layouts);
tvh_codec_audio_get_list_channel_layouts(TVHAudioCodec *self)
{
htsmsg_t *list = NULL, *map = NULL;
+#if LIBAVCODEC_VERSION_MAJOR > 59
+ const AVChannelLayout *channel_layouts = self->channel_layouts;
+ const AVChannelLayout *l;
+#else
const uint64_t *channel_layouts = self->channel_layouts;
uint64_t l = 0;
- char l_buf[16];
int i;
+#endif
+ char l_buf[16];
if (channel_layouts && (list = htsmsg_create_list())) {
if (!(map = htsmsg_create_map())) {
list = NULL;
}
else {
+#if LIBAVCODEC_VERSION_MAJOR > 59
+ l = channel_layouts;
+ ADD_ENTRY(list, map, s64, l->u.mask, str, AUTO_STR);
+ while (l->nb_channels) {
+ if (!(map = htsmsg_create_map())) {
+ htsmsg_destroy(list);
+ list = NULL;
+ break;
+ }
+ l_buf[0] = '\0';
+ av_channel_layout_describe(l, l_buf, sizeof(l_buf));
+ ADD_ENTRY(list, map, s64, l->u.mask, str, l_buf);
+ l++;
+ }
+#else
ADD_ENTRY(list, map, s64, l, str, AUTO_STR);
for (i = 0; (l = channel_layouts[i]); i++) {
if (l < INT64_MAX) {
ADD_ENTRY(list, map, s64, l, str, l_buf);
}
}
+#endif
}
}
return list;
// and sample_rate (48kHz) for input
int ssc_channels = ssc->es_channels ? ssc->es_channels : 2;
int ssc_sr = ssc->es_sri ? sri_to_rate(ssc->es_sri) : 48000;
+#if LIBAVCODEC_VERSION_MAJOR > 59
+ if ((self->channel_layout.order != AV_CHANNEL_ORDER_UNSPEC &&
+ ssc_channels != self->channel_layout.nb_channels) ||
+ (self->sample_rate && ssc_sr != self->sample_rate)) {
+ return 0;
+ }
+#else
if ((self->channel_layout &&
ssc_channels != av_get_channel_layout_nb_channels(self->channel_layout)) ||
(self->sample_rate && ssc_sr != self->sample_rate)) {
return 0;
}
+#endif
return 1;
}
AV_DICT_SET_INT(opts, "sample_rate", self->sample_rate,
AV_DICT_DONT_OVERWRITE);
}
+#if LIBAVCODEC_VERSION_MAJOR > 59
+ if (self->channel_layout.order != AV_CHANNEL_ORDER_UNSPEC) {
+ AV_DICT_SET_INT(opts, "channel_layout", self->channel_layout.u.mask,
+ AV_DICT_DONT_OVERWRITE);
+ }
+#else
if (self->channel_layout) {
AV_DICT_SET_INT(opts, "channel_layout", self->channel_layout,
AV_DICT_DONT_OVERWRITE);
}
+#endif
return 0;
}
}
+#if LIBAVCODEC_VERSION_MAJOR > 59
+static int
+_audio_context_channel_layout(TVHContext *self, AVDictionary **opts, AVChannelLayout *dst)
+{
+ const AVChannelLayout *channel_layouts =
+ tvh_codec_profile_audio_get_channel_layouts(self->profile);
+ AVChannelLayout ilayout;
+ av_channel_layout_copy(&ilayout, &self->iavctx->ch_layout);
+ AVChannelLayout olayout;
+ av_channel_layout_default(&olayout, 0);
+ AVChannelLayout altlayout;
+ av_channel_layout_default(&altlayout, 0);
+ int tmp = 0, ichannels = 0, i;
+ char obuf[64], abuf[64], ibuf[64];
+
+ if (!tvh_context_get_int_opt(opts, "ch_layout", &tmp) &&
+ !(av_channel_layout_from_mask(&olayout, tmp)) && channel_layouts) {
+ ichannels = ilayout.nb_channels;
+ for (i = 0; (av_channel_layout_from_mask(&olayout, channel_layouts[i].u.mask)); i++) {
+ if (av_channel_layout_compare(&olayout, &ilayout)) {
+ break;
+ }
+ if (olayout.nb_channels <= ichannels) {
+ altlayout = olayout;
+ }
+ }
+ }
+ if (tvhtrace_enabled()) {
+ strcpy(obuf, "none");
+ av_channel_layout_describe(&olayout, obuf, sizeof(obuf));
+ strcpy(abuf, "none");
+ av_channel_layout_describe(&altlayout, abuf, sizeof(abuf));
+ strcpy(ibuf, "none");
+ av_channel_layout_describe(&ilayout, ibuf, sizeof(ibuf));
+ tvh_context_log(self, LOG_TRACE, "audio layout selection: old %s, alt %s, in %s",
+ obuf, abuf, ibuf);
+ }
+ if (olayout.order != AV_CHANNEL_ORDER_UNSPEC)
+ return av_channel_layout_copy(dst, &olayout);
+ if (altlayout.order != AV_CHANNEL_ORDER_UNSPEC)
+ return av_channel_layout_copy(dst, &altlayout);
+ return av_channel_layout_copy(dst, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO);
+}
+#else
static uint64_t
_audio_context_channel_layout(TVHContext *self, AVDictionary **opts)
{
}
return olayout ? olayout : (altlayout ? altlayout : AV_CH_LAYOUT_STEREO);
}
+#endif
static int
self->oavctx->time_base = av_make_q(1, self->oavctx->sample_rate);
self->sri = rate_to_sri(self->oavctx->sample_rate);
// channel_layout
+#if LIBAVCODEC_VERSION_MAJOR > 59
+ _audio_context_channel_layout(self, opts, &self->oavctx->ch_layout);
+ if (self->oavctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
+ tvh_context_log(self, LOG_ERR,
+ "audio encoder has no suitable channel layout");
+ return -1;
+ }
+ self->oavctx->ch_layout.nb_channels = self->oavctx->ch_layout.nb_channels;
+#else
self->oavctx->channel_layout = _audio_context_channel_layout(self, opts);
if (!self->oavctx->channel_layout) {
tvh_context_log(self, LOG_ERR,
}
self->oavctx->channels =
av_get_channel_layout_nb_channels(self->oavctx->channel_layout);
+#endif
return 0;
}
// source args
memset(source_args, 0, sizeof(source_args));
+#if LIBAVCODEC_VERSION_MAJOR > 59
+ av_channel_layout_describe(&self->iavctx->ch_layout, layout, sizeof(layout));
+#else
av_get_channel_layout_string(layout, sizeof(layout), self->iavctx->channels, self->iavctx->channel_layout);
+#endif
if (str_snprintf(source_args, sizeof(source_args),
"time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%s",
self->iavctx->time_base.num,
"abuffer", source_args, // source
filters, // filters
"abuffersink", // sink
+#if LIBAVCODEC_VERSION_MAJOR > 59
+ "channel_layouts", &self->oavctx->ch_layout.u.mask, // sink option: channel_layout
+ sizeof(self->oavctx->ch_layout.u.mask),
+#else
"channel_layouts", &self->oavctx->channel_layout, // sink option: channel_layout
sizeof(self->oavctx->channel_layout),
+#endif
"sample_fmts", &self->oavctx->sample_fmt, // sink option: sample_fmt
sizeof(self->oavctx->sample_fmt),
"sample_rates", &self->oavctx->sample_rate, // sink option: sample_rate
tvh_audio_context_wrap(TVHContext *self, AVPacket *avpkt, th_pkt_t *pkt)
{
pkt->pkt_duration = avpkt->duration;
+#if LIBAVCODEC_VERSION_MAJOR > 59
+ pkt->a.pkt_channels = self->oavctx->ch_layout.nb_channels;
+#else
pkt->a.pkt_channels = self->oavctx->channels;
+#endif
pkt->a.pkt_sri = self->sri;
return 0;
}
tvh_aac_pack_adts_header(TVHContext *self, pktbuf_t *pb)
{
// XXX: this really should happen in the muxer
+#if LIBAVCODEC_VERSION_MAJOR > 59
+ int chan_conf = (self->oavctx->ch_layout.nb_channels == 8) ? 7 : self->oavctx->ch_layout.nb_channels;
+#else
int chan_conf = (self->oavctx->channels == 8) ? 7 : self->oavctx->channels;
+#endif
bitstream_t bs;
// https://wiki.multimedia.cx/index.php?title=ADTS
// there be one in the first place?.
// originally there was a check for avpkt->size < 2, I don't get it.
// max aac frame size = 768 bytes per channel, max writable size 13 bits
+#if LIBAVCODEC_VERSION_MAJOR > 59
+ if (avpkt->size > (768 * self->oavctx->ch_layout.nb_channels)) {
+ tvh_context_log(self, LOG_WARNING,
+ "packet size (%d) > aac max frame size (%d for %d channels)",
+ avpkt->size, (768 * self->oavctx->ch_layout.nb_channels),
+ self->oavctx->ch_layout.nb_channels);
+ }
+#else
if (avpkt->size > (768 * self->oavctx->channels)) {
tvh_context_log(self, LOG_WARNING,
"packet size (%d) > aac max frame size (%d for %d channels)",
avpkt->size, (768 * self->oavctx->channels),
self->oavctx->channels);
}
+#endif
if ((pkt_size = avpkt->size + header_size) > max_size) {
tvh_context_log(self, LOG_ERR, "aac frame data too big");
}