summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavcodec/opus.h2
-rw-r--r--libavcodec/opus_celt.c4
-rw-r--r--libavcodec/opus_celt.h4
-rw-r--r--libavcodec/opus_pvq.c1
-rw-r--r--libavcodec/opusdec.c17
5 files changed, 25 insertions, 3 deletions
diff --git a/libavcodec/opus.h b/libavcodec/opus.h
index c3cbaec35d..90b87ba5c4 100644
--- a/libavcodec/opus.h
+++ b/libavcodec/opus.h
@@ -150,7 +150,9 @@ typedef struct ChannelMap {
} ChannelMap;
typedef struct OpusContext {
+ AVClass *av_class;
OpusStreamContext *streams;
+ int apply_phase_inv;
/* current output buffers for each streams */
float **out;
diff --git a/libavcodec/opus_celt.c b/libavcodec/opus_celt.c
index 2bbb96bded..72b299a19c 100644
--- a/libavcodec/opus_celt.c
+++ b/libavcodec/opus_celt.c
@@ -997,7 +997,8 @@ void ff_celt_free(CeltFrame **f)
av_freep(f);
}
-int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels)
+int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels,
+ int apply_phase_inv)
{
CeltFrame *frm;
int i, ret;
@@ -1014,6 +1015,7 @@ int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels)
frm->avctx = avctx;
frm->output_channels = output_channels;
+ frm->apply_phase_inv = apply_phase_inv;
for (i = 0; i < FF_ARRAY_ELEMS(frm->imdct); i++)
if ((ret = ff_mdct15_init(&frm->imdct[i], 1, i + 3, -1.0f/32768)) < 0)
diff --git a/libavcodec/opus_celt.h b/libavcodec/opus_celt.h
index 45d50ab27b..9289a1867a 100644
--- a/libavcodec/opus_celt.h
+++ b/libavcodec/opus_celt.h
@@ -98,6 +98,7 @@ struct CeltFrame {
CeltPVQ *pvq;
int channels;
int output_channels;
+ int apply_phase_inv;
enum CeltBlockSize size;
int start_band;
@@ -156,7 +157,8 @@ static av_always_inline void celt_renormalize_vector(float *X, int N, float gain
X[i] *= g;
}
-int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels);
+int ff_celt_init(AVCodecContext *avctx, CeltFrame **f, int output_channels,
+ int apply_phase_inv);
void ff_celt_free(CeltFrame **f);
diff --git a/libavcodec/opus_pvq.c b/libavcodec/opus_pvq.c
index 2f7aa74da4..449215f814 100644
--- a/libavcodec/opus_pvq.c
+++ b/libavcodec/opus_pvq.c
@@ -643,6 +643,7 @@ static av_always_inline uint32_t quant_band_template(CeltPVQ *pvq, CeltFrame *f,
}
} else {
inv = (b > 2 << 3 && f->remaining2 > 2 << 3) ? ff_opus_rc_dec_log(rc, 2) : 0;
+ inv = f->apply_phase_inv ? inv : 0;
}
itheta = 0;
}
diff --git a/libavcodec/opusdec.c b/libavcodec/opusdec.c
index 5a7ba9dbb4..03086dea99 100644
--- a/libavcodec/opusdec.c
+++ b/libavcodec/opusdec.c
@@ -687,7 +687,7 @@ static av_cold int opus_decode_init(AVCodecContext *avctx)
if (ret < 0)
goto fail;
- ret = ff_celt_init(avctx, &s->celt, s->output_channels);
+ ret = ff_celt_init(avctx, &s->celt, s->output_channels, c->apply_phase_inv);
if (ret < 0)
goto fail;
@@ -712,9 +712,24 @@ fail:
return ret;
}
+#define OFFSET(x) offsetof(OpusContext, x)
+#define AD AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM
+static const AVOption opus_options[] = {
+ { "apply_phase_inv", "Apply intensity stereo phase inversion", OFFSET(apply_phase_inv), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, AD },
+ { NULL },
+};
+
+static const AVClass opus_class = {
+ .class_name = "Opus Decoder",
+ .item_name = av_default_item_name,
+ .option = opus_options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
AVCodec ff_opus_decoder = {
.name = "opus",
.long_name = NULL_IF_CONFIG_SMALL("Opus"),
+ .priv_class = &opus_class,
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_OPUS,
.priv_data_size = sizeof(OpusContext),