ref: b90e63b5bab727bc33dce854b6a4d7e325fef3ab
parent: 36a21ed53636ed4471aa62a8d06dcf175d6ff395
author: Jean-Marc Valin <[email protected]>
date: Mon Sep 16 09:08:52 EDT 2013
Moves frame size selection back out of opus_encode_native() Should fix delayed decision on surround, but not well tested.
--- a/src/analysis.c
+++ b/src/analysis.c
@@ -618,17 +618,17 @@
RESTORE_STACK;
}
-int run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const opus_val16 *pcm,
- const void *analysis_pcm, int frame_size, int variable_duration, int c1, int c2, int C, opus_int32 Fs, int bitrate_bps,
- int delay_compensation, int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info)
+int run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *analysis_pcm,
+ int analysis_frame_size, int frame_size, int c1, int c2, int C, opus_int32 Fs,
+ int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info)
{
int offset;
int pcm_len;
/* Avoid overflow/wrap-around of the analysis buffer */
- frame_size = IMIN((DETECT_SIZE-5)*Fs/100, frame_size);
+ analysis_frame_size = IMIN((DETECT_SIZE-5)*Fs/100, analysis_frame_size);
- pcm_len = frame_size - analysis->analysis_offset;
+ pcm_len = analysis_frame_size - analysis->analysis_offset;
offset = analysis->analysis_offset;
do {
tonality_analysis(analysis, NULL, celt_mode, analysis_pcm, IMIN(480, pcm_len), offset, c1, c2, C, lsb_depth, downmix);
@@ -635,21 +635,8 @@
offset += 480;
pcm_len -= 480;
} while (pcm_len>0);
- analysis->analysis_offset = frame_size;
+ analysis->analysis_offset = analysis_frame_size;
- if (variable_duration == OPUS_FRAMESIZE_VARIABLE && frame_size >= Fs/200)
- {
- int LM = 3;
- LM = optimize_framesize(pcm, frame_size, C, Fs, bitrate_bps,
- analysis->prev_tonality, analysis->subframe_mem, delay_compensation, downmix);
- while ((Fs/400<<LM)>frame_size)
- LM--;
- frame_size = (Fs/400<<LM);
- } else {
- frame_size = frame_size_select(frame_size, variable_duration, Fs);
- }
- if (frame_size<0)
- return -1;
analysis->analysis_offset -= frame_size;
/* Only perform analysis up to 20-ms frames. Longer ones will be split if
--- a/src/analysis.h
+++ b/src/analysis.h
@@ -83,8 +83,8 @@
void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len);
-int run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const opus_val16 *pcm,
- const void *analysis_pcm, int frame_size, int variable_duration, int c1, int c2, int C, opus_int32 Fs, int bitrate_bps,
- int delay_compensation, int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info);
+int run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *analysis_pcm,
+ int analysis_frame_size, int frame_size, int c1, int c2, int C, opus_int32 Fs,
+ int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info);
#endif
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -849,6 +849,26 @@
return new_size;
}
+opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size,
+ int variable_duration, int C, opus_int32 Fs, int bitrate_bps,
+ int delay_compensation, downmix_func downmix, opus_val32 *subframe_mem)
+{
+ if (variable_duration == OPUS_FRAMESIZE_VARIABLE && frame_size >= Fs/200)
+ {
+ int LM = 3;
+ LM = optimize_framesize(analysis_pcm, frame_size, C, Fs, bitrate_bps,
+ 0, subframe_mem, delay_compensation, downmix);
+ while ((Fs/400<<LM)>frame_size)
+ LM--;
+ frame_size = (Fs/400<<LM);
+ } else {
+ frame_size = frame_size_select(frame_size, variable_duration, Fs);
+ }
+ if (frame_size<0)
+ return -1;
+ return frame_size;
+}
+
opus_val16 compute_stereo_width(const opus_val16 *pcm, int frame_size, opus_int32 Fs, StereoWidthState *mem)
{
opus_val16 corr;
@@ -928,7 +948,7 @@
opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
- const void *analysis_pcm, int c1, int c2, int analysis_channels, downmix_func downmix)
+ const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2, int analysis_channels, downmix_func downmix)
{
void *silk_enc;
CELTEncoder *celt_enc;
@@ -987,10 +1007,11 @@
analysis_info.valid = 0;
celt_encoder_ctl(celt_enc, CELT_GET_MODE(&celt_mode));
#ifndef DISABLE_FLOAT_API
- if (st->silk_mode.complexity >= 7 && st->Fs==48000)
+ if (analysis_pcm != NULL && st->silk_mode.complexity >= 7 && st->Fs==48000)
{
- frame_size = run_analysis(&st->analysis, celt_mode, pcm, analysis_pcm,
- frame_size, st->variable_duration, c1, c2, analysis_channels, st->Fs, st->bitrate_bps, delay_compensation, lsb_depth, downmix, &analysis_info);
+ frame_size = run_analysis(&st->analysis, celt_mode, analysis_pcm, analysis_size, frame_size,
+ c1, c2, analysis_channels, st->Fs,
+ lsb_depth, downmix, &analysis_info);
} else
#endif
{
@@ -1373,7 +1394,7 @@
st->user_forced_mode = MODE_CELT_ONLY;
tmp_len = opus_encode_native(st, pcm+i*(st->channels*st->Fs/50), st->Fs/50,
tmp_data+i*bytes_per_frame, bytes_per_frame, lsb_depth,
- analysis_pcm, c1, c2, analysis_channels, downmix);
+ NULL, 0, c1, c2, analysis_channels, downmix);
if (tmp_len<0)
{
RESTORE_STACK;
@@ -1915,49 +1936,88 @@
#ifdef FIXED_POINT
#ifndef DISABLE_FLOAT_API
-opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int frame_size,
+opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size,
unsigned char *data, opus_int32 max_data_bytes)
{
int i, ret;
+ int frame_size;
+ int delay_compensation;
VARDECL(opus_int16, in);
ALLOC_STACK;
+ if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+ delay_compensation = 0;
+ else
+ delay_compensation = st->delay_compensation;
+ frame_size = compute_frame_size(pcm, analysis_frame_size,
+ st->variable_duration, st->channels, st->Fs, st->bitrate_bps,
+ delay_compensation, downmix_float, st->analysis.subframe_mem);
+
ALLOC(in, frame_size*st->channels, opus_int16);
for (i=0;i<frame_size*st->channels;i++)
in[i] = FLOAT2INT16(pcm[i]);
- ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, pcm, 0, -2, st->channels, downmix_float);
+ ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, pcm, analysis_frame_size, 0, -2, st->channels, downmix_float);
RESTORE_STACK;
return ret;
}
#endif
-opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size,
+opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size,
unsigned char *data, opus_int32 out_data_bytes)
{
- return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 16, pcm, 0, -2, st->channels, downmix_int);
+ int frame_size;
+ int delay_compensation;
+ if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+ delay_compensation = 0;
+ else
+ delay_compensation = st->delay_compensation;
+ frame_size = compute_frame_size(pcm, analysis_frame_size,
+ st->variable_duration, st->channels, st->Fs, st->bitrate_bps,
+ delay_compensation, downmix_float, st->analysis.subframe_mem);
+ return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 16, pcm, analysis_frame_size, 0, -2, st->channels, downmix_int);
}
#else
-opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int frame_size,
+opus_int32 opus_encode(OpusEncoder *st, const opus_int16 *pcm, int analysis_frame_size,
unsigned char *data, opus_int32 max_data_bytes)
{
int i, ret;
+ int frame_size;
+ int delay_compensation;
VARDECL(float, in);
ALLOC_STACK;
- ALLOC(in, frame_size*st->channels, float);
+ if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+ delay_compensation = 0;
+ else
+ delay_compensation = st->delay_compensation;
+ frame_size = compute_frame_size(pcm, analysis_frame_size,
+ st->variable_duration, st->channels, st->Fs, st->bitrate_bps,
+ delay_compensation, downmix_float, st->analysis.subframe_mem);
- for (i=0;i<frame_size*st->channels;i++)
+ ALLOC(in, analysis_frame_size*st->channels, float);
+
+ for (i=0;i<analysis_frame_size*st->channels;i++)
in[i] = (1.0f/32768)*pcm[i];
- ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, pcm, 0, -2, st->channels, downmix_int);
+ ret = opus_encode_native(st, in, frame_size, data, max_data_bytes, 16, pcm, analysis_frame_size, 0, -2, st->channels, downmix_int);
RESTORE_STACK;
return ret;
}
-opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int frame_size,
+opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm, int analysis_frame_size,
unsigned char *data, opus_int32 out_data_bytes)
{
- return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 24, pcm, 0, -2, st->channels, downmix_float);
+ int frame_size;
+ int delay_compensation;
+ if (st->application == OPUS_APPLICATION_RESTRICTED_LOWDELAY)
+ delay_compensation = 0;
+ else
+ delay_compensation = st->delay_compensation;
+ frame_size = compute_frame_size(pcm, analysis_frame_size,
+ st->variable_duration, st->channels, st->Fs, st->bitrate_bps,
+ delay_compensation, downmix_float, st->analysis.subframe_mem);
+ return opus_encode_native(st, pcm, frame_size, data, out_data_bytes, 24,
+ pcm, analysis_frame_size, 0, -2, st->channels, downmix_float);
}
#endif
--- a/src/opus_multistream_encoder.c
+++ b/src/opus_multistream_encoder.c
@@ -72,6 +72,7 @@
struct OpusMSEncoder {
ChannelLayout layout;
int lfe_stream;
+ int application;
int variable_duration;
int surround;
opus_int32 bitrate_bps;
@@ -416,6 +417,7 @@
if (!surround)
st->lfe_stream = -1;
st->bitrate_bps = OPUS_AUTO;
+ st->application = application;
st->variable_duration = OPUS_FRAMESIZE_ARG;
for (i=0;i<st->layout.nb_channels;i++)
st->layout.mapping[i] = mapping[i];
@@ -666,7 +668,7 @@
OpusMSEncoder *st,
opus_copy_channel_in_func copy_channel_in,
const void *pcm,
- int frame_size,
+ int analysis_frame_size,
unsigned char *data,
opus_int32 max_data_bytes,
int lsb_depth,
@@ -689,6 +691,7 @@
opus_val16 bandLogE[42];
opus_val32 *mem = NULL;
opus_val32 *preemph_mem=NULL;
+ int frame_size;
ALLOC_STACK;
if (st->surround)
@@ -702,6 +705,18 @@
opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_COMPLEXITY(&complexity));
opus_encoder_ctl((OpusEncoder*)ptr, CELT_GET_MODE(&celt_mode));
+ {
+ opus_int32 delay_compensation;
+ int channels;
+
+ channels = st->layout.nb_streams + st->layout.nb_coupled_streams;
+ opus_encoder_ctl((OpusEncoder*)ptr, OPUS_GET_LOOKAHEAD(&delay_compensation));
+ delay_compensation -= Fs/400;
+ frame_size = compute_frame_size(pcm, analysis_frame_size,
+ st->variable_duration, channels, Fs, st->bitrate_bps,
+ delay_compensation, downmix, st->subframe_mem);
+ }
+
if (400*frame_size < Fs)
{
RESTORE_STACK;
@@ -822,7 +837,8 @@
/* Reserve three bytes for the last stream and four for the others */
curr_max -= IMAX(0,4*(st->layout.nb_streams-s-1)-1);
curr_max = IMIN(curr_max,MS_FRAME_TMP);
- len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth, pcm, c1, c2, st->layout.nb_channels, downmix);
+ len = opus_encode_native(enc, buf, frame_size, tmp_data, curr_max, lsb_depth,
+ pcm, analysis_frame_size, c1, c2, st->layout.nb_channels, downmix);
if (len<0)
{
RESTORE_STACK;
--- a/src/opus_private.h
+++ b/src/opus_private.h
@@ -94,9 +94,13 @@
opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs);
+opus_int32 compute_frame_size(const void *analysis_pcm, int frame_size,
+ int variable_duration, int C, opus_int32 Fs, int bitrate_bps,
+ int delay_compensation, downmix_func downmix, opus_val32 *subframe_mem);
+
opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
- const void *analysis_pcm, int c1, int c2, int analysis_channels, downmix_func downmix);
+ const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2, int analysis_channels, downmix_func downmix);
int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len,
opus_val16 *pcm, int frame_size, int decode_fec, int self_delimited,