ref: 7bb26e13ca0523e195dc126547bfa8264008ff07
parent: 263e27194898248d5ef9500df57075af35f5a86d
author: Jean-Marc Valin <[email protected]>
date: Tue Feb 1 12:04:27 EST 2011
Adds a generic CELT_SET_BITRATE() ctl() API for CBR and VBR
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -103,7 +103,8 @@
int upsample;
int start, end;
- celt_int32 vbr_rate_norm; /* Target number of 8th bits per frame */
+ celt_int32 bitrate;
+ int vbr;
int constrained_vbr; /* If zero, VBR can do whatever it likes with the rate */
/* Everything beyond this point gets cleared on a reset */
@@ -224,7 +225,8 @@
st->end = st->mode->effEBands;
st->constrained_vbr = 1;
- st->vbr_rate_norm = 0;
+ st->bitrate = 255000*channels;
+ st->vbr = 0;
st->vbr_offset = 0;
st->force_intra = 0;
st->delayedIntra = 1;
@@ -909,6 +911,7 @@
if (LM>=MAX_CONFIG_SIZES)
return CELT_BAD_ARG;
M=1<<LM;
+ N = M*st->mode->shortMdctSize;
prefilter_mem = st->in_mem+CC*(st->overlap);
_overlap_mem = prefilter_mem+CC*COMBFILTER_MAXPERIOD;
@@ -919,9 +922,6 @@
if (enc==NULL)
{
- ec_byte_writeinit_buffer(&buf, compressed, nbCompressedBytes);
- ec_enc_init(&_enc,&buf);
- enc = &_enc;
tell=1;
nbFilledBytes=0;
} else {
@@ -930,10 +930,30 @@
}
nbAvailableBytes = nbCompressedBytes - nbFilledBytes;
- vbr_rate = st->vbr_rate_norm<<LM;
+ if (st->vbr)
+ {
+ vbr_rate = ((2*st->bitrate*frame_size<<BITRES)+st->mode->Fs)/(2*st->mode->Fs);
+ effectiveBytes = vbr_rate>>3;
+ } else {
+ celt_int32 tmp;
+ vbr_rate = 0;
+ tmp = st->bitrate*frame_size;
+ if (tell>1)
+ tmp += tell;
+ nbCompressedBytes = IMAX(2, IMIN(nbCompressedBytes,
+ (tmp+4*st->mode->Fs)/(8*st->mode->Fs)));
+ effectiveBytes = nbCompressedBytes;
+ }
+
+ if (enc==NULL)
+ {
+ ec_byte_writeinit_buffer(&buf, compressed, nbCompressedBytes);
+ ec_enc_init(&_enc,&buf);
+ enc = &_enc;
+ }
+
if (vbr_rate>0)
{
- effectiveBytes = st->vbr_rate_norm>>BITRES<<LM>>3;
/* Computes the max bit-rate allowed in VBR mode to avoid violating the
target rate and buffering.
We must do this up front so that bust-prevention logic triggers
@@ -954,11 +974,10 @@
{
nbCompressedBytes = nbFilledBytes+max_allowed;
nbAvailableBytes = max_allowed;
- ec_byte_shrink(&buf, nbCompressedBytes);
+ ec_byte_shrink(enc->buf, nbCompressedBytes);
}
}
- } else
- effectiveBytes = nbCompressedBytes;
+ }
total_bits = nbCompressedBytes*8;
effEnd = st->end;
@@ -965,7 +984,6 @@
if (effEnd > st->mode->effEBands)
effEnd = st->mode->effEBands;
- N = M*st->mode->shortMdctSize;
ALLOC(in, CC*(N+st->overlap), celt_sig);
/* Find pitch period and gain */
@@ -1021,7 +1039,7 @@
effectiveBytes=nbCompressedBytes=IMIN(nbCompressedBytes, nbFilledBytes+2);
total_bits=nbCompressedBytes*8;
nbAvailableBytes=2;
- ec_byte_shrink(&buf, nbCompressedBytes);
+ ec_byte_shrink(enc->buf, nbCompressedBytes);
}
/* Pretend we've filled all the remaining bits with zeros
(that's what the initialiser did anyway) */
@@ -1357,7 +1375,7 @@
}
nbCompressedBytes = IMIN(nbCompressedBytes,nbAvailableBytes+nbFilledBytes);
/* This moves the raw bits to take into account the new compressed size */
- ec_byte_shrink(&buf, nbCompressedBytes);
+ ec_byte_shrink(enc->buf, nbCompressedBytes);
}
if (C==2)
{
@@ -1688,17 +1706,18 @@
st->constrained_vbr = value;
}
break;
- case CELT_SET_VBR_RATE_REQUEST:
+ case CELT_SET_VBR_REQUEST:
{
celt_int32 value = va_arg(ap, celt_int32);
- int frame_rate;
- int N = st->mode->shortMdctSize;
- if (value<0)
+ st->vbr = value;
+ }
+ break;
+ case CELT_SET_BITRATE_REQUEST:
+ {
+ celt_int32 value = va_arg(ap, celt_int32);
+ if (value<=500)
goto bad_arg;
- if (value>3072000)
- value = 3072000;
- frame_rate = ((st->mode->Fs<<3)+(N>>1))/N;
- st->vbr_rate_norm = value>0?IMAX(1,((value<<(BITRES+3))+(frame_rate>>1))/frame_rate):0;
+ st->bitrate = value;
}
break;
case CELT_SET_CHANNELS_REQUEST:
--- a/libcelt/celt.h
+++ b/libcelt/celt.h
@@ -78,9 +78,11 @@
#define CELT_GET_MODE_REQUEST 1
/** Get the CELTMode used by an encoder or decoder */
#define CELT_GET_MODE(x) CELT_GET_MODE_REQUEST, _celt_check_mode_ptr_ptr(x)
+
#define CELT_SET_COMPLEXITY_REQUEST 2
/** Controls the complexity from 0-10 (int) */
#define CELT_SET_COMPLEXITY(x) CELT_SET_COMPLEXITY_REQUEST, _celt_check_int(x)
+
#define CELT_SET_PREDICTION_REQUEST 4
/** Controls the use of interframe prediction.
0=Independent frames
@@ -88,9 +90,11 @@
2=Long term prediction allowed
*/
#define CELT_SET_PREDICTION(x) CELT_SET_PREDICTION_REQUEST, _celt_check_int(x)
-#define CELT_SET_VBR_RATE_REQUEST 6
+
+#define CELT_SET_BITRATE_REQUEST 6
/** Set the target VBR rate in bits per second(int); 0=CBR (default) */
-#define CELT_SET_VBR_RATE(x) CELT_SET_VBR_RATE_REQUEST, _celt_check_int(x)
+#define CELT_SET_BITRATE(x) CELT_SET_BITRATE_REQUEST, _celt_check_int(x)
+
/** Reset the encoder/decoder memories to zero*/
#define CELT_RESET_STATE_REQUEST 8
#define CELT_RESET_STATE CELT_RESET_STATE_REQUEST
@@ -97,6 +101,9 @@
#define CELT_SET_VBR_CONSTRAINT_REQUEST 10
#define CELT_SET_VBR_CONSTRAINT(x) CELT_SET_VBR_CONSTRAINT_REQUEST, _celt_check_int(x)
+
+#define CELT_SET_VBR_REQUEST 12
+#define CELT_SET_VBR(x) CELT_SET_VBR_REQUEST, _celt_check_int(x)
#define CELT_SET_START_BAND_REQUEST 10000
#define CELT_SET_START_BAND(x) CELT_SET_START_BAND_REQUEST, _celt_check_int(x)
--- a/tools/celtenc.c
+++ b/tools/celtenc.c
@@ -482,21 +482,8 @@
else
bitrate=128.0;
- bytes_per_packet = (bitrate*1000*frame_size/rate+4)/8;
+ bytes_per_packet = MAX_FRAME_BYTES;
- if (bytes_per_packet > MAX_FRAME_BYTES) {
- bytes_per_packet=MAX_FRAME_BYTES;
- fprintf (stderr, "Warning: Requested bitrate (%0.3fkbit/sec) is too high. Setting CELT to %d bytes/frame.\n",bitrate,MAX_FRAME_BYTES);
- }
-
- if (with_cbr)
- {
- bitrate = ((rate/(float)frame_size)*8*bytes_per_packet)/1000.0;
- } else {
- /*In VBR mode the bytes_per_packet argument becomes a hard maximum. 3x the average rate is just a random choice.*/
- bytes_per_packet=IMIN(bytes_per_packet*3,MAX_FRAME_BYTES);
- }
-
mode = celt_mode_create(rate, frame_size, NULL);
if (!mode)
return 1;
@@ -527,10 +514,17 @@
/*Initialize CELT encoder*/
st = celt_encoder_create_custom(mode, chan, NULL);
+ {
+ int tmp = (bitrate*1000);
+ if (celt_encoder_ctl(st, CELT_SET_BITRATE(tmp)) != CELT_OK)
+ {
+ fprintf (stderr, "bitrate request failed\n");
+ return 1;
+ }
+ }
if (!with_cbr)
{
- int tmp = (bitrate*1000);
- if (celt_encoder_ctl(st, CELT_SET_VBR_RATE(tmp)) != CELT_OK)
+ if (celt_encoder_ctl(st, CELT_SET_VBR(1)) != CELT_OK)
{
fprintf (stderr, "VBR request failed\n");
return 1;