avcodec/libopus: support disabling phase inversion.

Signed-off-by: Menno <mrdegier@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
Menno 2018-02-05 10:54:53 +01:00 committed by Michael Niedermayer
parent 26d879c1ce
commit 204c7caf0d
3 changed files with 52 additions and 0 deletions

View File

@ -981,6 +981,11 @@ Other values include 0 for mono and stereo, 1 for surround sound with masking
and LFE bandwidth optimizations, and 255 for independent streams with an and LFE bandwidth optimizations, and 255 for independent streams with an
unspecified channel layout. unspecified channel layout.
@item apply_phase_inv (N.A.) (requires libopus >= 1.2)
If set to 0, disables the use of phase inversion for intensity stereo,
improving the quality of mono downmixes, but slightly reducing normal stereo
quality. The default is 1 (phase inversion enabled).
@end table @end table
@anchor{libshine} @anchor{libshine}

View File

@ -25,6 +25,7 @@
#include "libavutil/internal.h" #include "libavutil/internal.h"
#include "libavutil/intreadwrite.h" #include "libavutil/intreadwrite.h"
#include "libavutil/ffmath.h" #include "libavutil/ffmath.h"
#include "libavutil/opt.h"
#include "avcodec.h" #include "avcodec.h"
#include "internal.h" #include "internal.h"
@ -33,11 +34,15 @@
#include "libopus.h" #include "libopus.h"
struct libopus_context { struct libopus_context {
AVClass *class;
OpusMSDecoder *dec; OpusMSDecoder *dec;
int pre_skip; int pre_skip;
#ifndef OPUS_SET_GAIN #ifndef OPUS_SET_GAIN
union { int i; double d; } gain; union { int i; double d; } gain;
#endif #endif
#ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST
int apply_phase_inv;
#endif
}; };
#define OPUS_HEAD_SIZE 19 #define OPUS_HEAD_SIZE 19
@ -136,6 +141,15 @@ static av_cold int libopus_decode_init(AVCodecContext *avc)
} }
#endif #endif
#ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST
ret = opus_multistream_decoder_ctl(opus->dec,
OPUS_SET_PHASE_INVERSION_DISABLED(!opus->apply_phase_inv));
if (ret != OPUS_OK)
av_log(avc, AV_LOG_WARNING,
"Unable to set phase inversion: %s\n",
opus_strerror(ret));
#endif
/* Decoder delay (in samples) at 48kHz */ /* Decoder delay (in samples) at 48kHz */
avc->delay = avc->internal->skip_samples = opus->pre_skip; avc->delay = avc->internal->skip_samples = opus->pre_skip;
@ -209,6 +223,24 @@ static void libopus_flush(AVCodecContext *avc)
avc->internal->skip_samples = opus->pre_skip; avc->internal->skip_samples = opus->pre_skip;
} }
#define OFFSET(x) offsetof(struct libopus_context, x)
#define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM
static const AVOption libopusdec_options[] = {
#ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST
{ "apply_phase_inv", "Apply intensity stereo phase inversion", OFFSET(apply_phase_inv), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS },
#endif
{ NULL },
};
static const AVClass libopusdec_class = {
.class_name = "libopusdec",
.item_name = av_default_item_name,
.option = libopusdec_options,
.version = LIBAVUTIL_VERSION_INT,
};
AVCodec ff_libopus_decoder = { AVCodec ff_libopus_decoder = {
.name = "libopus", .name = "libopus",
.long_name = NULL_IF_CONFIG_SMALL("libopus Opus"), .long_name = NULL_IF_CONFIG_SMALL("libopus Opus"),
@ -223,5 +255,6 @@ AVCodec ff_libopus_decoder = {
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT, .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLT,
AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16,
AV_SAMPLE_FMT_NONE }, AV_SAMPLE_FMT_NONE },
.priv_class = &libopusdec_class,
.wrapper_name = "libopus", .wrapper_name = "libopus",
}; };

View File

@ -39,6 +39,9 @@ typedef struct LibopusEncOpts {
int packet_size; int packet_size;
int max_bandwidth; int max_bandwidth;
int mapping_family; int mapping_family;
#ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST
int apply_phase_inv;
#endif
} LibopusEncOpts; } LibopusEncOpts;
typedef struct LibopusEncContext { typedef struct LibopusEncContext {
@ -154,6 +157,14 @@ static int libopus_configure_encoder(AVCodecContext *avctx, OpusMSEncoder *enc,
"Unable to set maximum bandwidth: %s\n", opus_strerror(ret)); "Unable to set maximum bandwidth: %s\n", opus_strerror(ret));
} }
#ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST
ret = opus_multistream_encoder_ctl(enc,
OPUS_SET_PHASE_INVERSION_DISABLED(!opts->apply_phase_inv));
if (ret != OPUS_OK)
av_log(avctx, AV_LOG_WARNING,
"Unable to set phase inversion: %s\n",
opus_strerror(ret));
#endif
return OPUS_OK; return OPUS_OK;
} }
@ -530,6 +541,9 @@ static const AVOption libopus_options[] = {
{ "on", "Use variable bit rate", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "vbr" }, { "on", "Use variable bit rate", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "vbr" },
{ "constrained", "Use constrained VBR", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, FLAGS, "vbr" }, { "constrained", "Use constrained VBR", 0, AV_OPT_TYPE_CONST, { .i64 = 2 }, 0, 0, FLAGS, "vbr" },
{ "mapping_family", "Channel Mapping Family", OFFSET(mapping_family), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, FLAGS, "mapping_family" }, { "mapping_family", "Channel Mapping Family", OFFSET(mapping_family), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 255, FLAGS, "mapping_family" },
#ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST
{ "apply_phase_inv", "Apply intensity stereo phase inversion", OFFSET(apply_phase_inv), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS },
#endif
{ NULL }, { NULL },
}; };