projects
/
vg.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
simplify gitignore
[vg.git]
/
dep
/
stb
/
stb_vorbis.h
diff --git
a/dep/stb/stb_vorbis.h
b/dep/stb/stb_vorbis.h
index 2f62db244e2d0af405db20470a3054da0f3eca79..3279c969d8ebda7a1d7ce3db2e19653367a0ee61 100644
(file)
--- a/
dep/stb/stb_vorbis.h
+++ b/
dep/stb/stb_vorbis.h
@@
-1,4
+1,4
@@
-// Ogg Vorbis audio decoder - v1.
19
- public domain
+// Ogg Vorbis audio decoder - v1.
22
- public domain
// http://nothings.org/stb_vorbis/
//
// Original version written by Sean Barrett in 2007.
// http://nothings.org/stb_vorbis/
//
// Original version written by Sean Barrett in 2007.
@@
-29,11
+29,16
@@
// Bernhard Wodo Evan Balster github:alxprd
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
// Phillip Bennefall Rohit Thiago Goulart
// Bernhard Wodo Evan Balster github:alxprd
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
// Phillip Bennefall Rohit Thiago Goulart
-// github:manxorist
saga m
usix github:infatum
+// github:manxorist
Saga M
usix github:infatum
// Timur Gagiev Maxwell Koo Peter Waller
// Timur Gagiev Maxwell Koo Peter Waller
-// github:audinowho Dougall Johnson
+// github:audinowho Dougall Johnson David Reid
+// github:Clownacy Pedro J. Estebanez Remi Verschelde
+// AnthoFoxo github:morlat Gabriel Ravier
//
// Partial history:
//
// Partial history:
+// 1.22 - 2021-07-11 - various small fixes
+// 1.21 - 2021-07-02 - fix bug for files with no comments
+// 1.20 - 2020-07-11 - several small fixes
// 1.19 - 2020-02-05 - warnings
// 1.18 - 2020-02-02 - fix seek bugs; parse header comments; misc warnings etc.
// 1.17 - 2019-07-08 - fix CVE-2019-13217..CVE-2019-13223 (by ForAllSecure)
// 1.19 - 2020-02-05 - warnings
// 1.18 - 2020-02-02 - fix seek bugs; parse header comments; misc warnings etc.
// 1.17 - 2019-07-08 - fix CVE-2019-13217..CVE-2019-13223 (by ForAllSecure)
@@
-218,6
+223,12
@@
extern int stb_vorbis_decode_frame_pushdata(
// channel. In other words, (*output)[0][0] contains the first sample from
// the first channel, and (*output)[1][0] contains the first sample from
// the second channel.
// channel. In other words, (*output)[0][0] contains the first sample from
// the first channel, and (*output)[1][0] contains the first sample from
// the second channel.
+//
+// *output points into stb_vorbis's internal output buffer storage; these
+// buffers are owned by stb_vorbis and application code should not free
+// them or modify their contents. They are transient and will be overwritten
+// once you ask for more data to get decoded, so be sure to grab any data
+// you need before then.
extern void stb_vorbis_flush_pushdata(stb_vorbis *f);
// inform stb_vorbis that your next datablock will not be contiguous with
extern void stb_vorbis_flush_pushdata(stb_vorbis *f);
// inform stb_vorbis that your next datablock will not be contiguous with
@@
-577,7
+588,7
@@
enum STBVorbisError
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <malloc.h>
#endif
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <malloc.h>
#endif
- #if defined(__linux__) || defined(__linux) || defined(__
EMSCRIPTEN
__)
+ #if defined(__linux__) || defined(__linux) || defined(__
sun__) || defined(__EMSCRIPTEN__) || defined(__NEWLIB
__)
#include <alloca.h>
#endif
#else // STB_VORBIS_NO_CRT
#include <alloca.h>
#endif
#else // STB_VORBIS_NO_CRT
@@
-599,10
+610,9
@@
enum STBVorbisError
#undef __forceinline
#endif
#define __forceinline
#undef __forceinline
#endif
#define __forceinline
- #ifdef alloca
- #undef alloca
- #endif
+ #ifndef alloca
#define alloca __builtin_alloca
#define alloca __builtin_alloca
+ #endif
#elif !defined(_MSC_VER)
#if __GNUC__
#define __forceinline inline
#elif !defined(_MSC_VER)
#if __GNUC__
#define __forceinline inline
@@
-645,6
+655,12
@@
typedef signed int int32;
typedef float codetype;
typedef float codetype;
+#ifdef _MSC_VER
+#define STBV_NOTUSED(v) (void)(v)
+#else
+#define STBV_NOTUSED(v) (void)sizeof(v)
+#endif
+
// @NOTE
//
// Some arrays below are tagged "//varies", which means it's actually
// @NOTE
//
// Some arrays below are tagged "//varies", which means it's actually
@@
-964,7
+980,7
@@
static void *setup_temp_malloc(vorb *f, int sz)
static void setup_temp_free(vorb *f, void *p, int sz)
{
if (f->alloc.alloc_buffer) {
static void setup_temp_free(vorb *f, void *p, int sz)
{
if (f->alloc.alloc_buffer) {
- f->temp_offset += (sz+
3)&~3
;
+ f->temp_offset += (sz+
7)&~7
;
return;
}
free(p);
return;
}
free(p);
@@
-1045,7
+1061,7
@@
static float float32_unpack(uint32 x)
uint32 sign = x & 0x80000000;
uint32 exp = (x & 0x7fe00000) >> 21;
double res = sign ? -(double)mantissa : (double)mantissa;
uint32 sign = x & 0x80000000;
uint32 exp = (x & 0x7fe00000) >> 21;
double res = sign ? -(double)mantissa : (double)mantissa;
- return (float) ldexp((float)res, exp-788);
+ return (float) ldexp((float)res,
(int)
exp-788);
}
}
@@
-1076,6
+1092,7
@@
static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
// find the first entry
for (k=0; k < n; ++k) if (len[k] < NO_CODE) break;
if (k == n) { assert(c->sorted_entries == 0); return TRUE; }
// find the first entry
for (k=0; k < n; ++k) if (len[k] < NO_CODE) break;
if (k == n) { assert(c->sorted_entries == 0); return TRUE; }
+ assert(len[k] < 32); // no error return required, code reading lens checks this
// add to the list
add_entry(c, 0, k, m++, len[k], values);
// add all available leaves
// add to the list
add_entry(c, 0, k, m++, len[k], values);
// add all available leaves
@@
-1089,6
+1106,7
@@
static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
uint32 res;
int z = len[i], y;
if (z == NO_CODE) continue;
uint32 res;
int z = len[i], y;
if (z == NO_CODE) continue;
+ assert(z < 32); // no error return required, code reading lens checks this
// find lowest available leaf (should always be earliest,
// which is what the specification calls for)
// note that this property, and the fact we can never have
// find lowest available leaf (should always be earliest,
// which is what the specification calls for)
// note that this property, and the fact we can never have
@@
-1098,12
+1116,10
@@
static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
while (z > 0 && !available[z]) --z;
if (z == 0) { return FALSE; }
res = available[z];
while (z > 0 && !available[z]) --z;
if (z == 0) { return FALSE; }
res = available[z];
- assert(z >= 0 && z < 32);
available[z] = 0;
add_entry(c, bit_reverse(res), i, m++, len[i], values);
// propagate availability up the tree
if (z != len[i]) {
available[z] = 0;
add_entry(c, bit_reverse(res), i, m++, len[i], values);
// propagate availability up the tree
if (z != len[i]) {
- assert(len[i] >= 0 && len[i] < 32);
for (y=len[i]; y > z; --y) {
assert(available[y] == 0);
available[y] = res + (1 << (32-y));
for (y=len[i]; y > z; --y) {
assert(available[y] == 0);
available[y] = res + (1 << (32-y));
@@
-1603,7
+1619,8
@@
static uint32 get_bits(vorb *f, int n)
f->valid_bits += 8;
}
}
f->valid_bits += 8;
}
}
- if (f->valid_bits < 0) return 0;
+
+ assert(f->valid_bits >= n);
z = f->acc & ((1 << n)-1);
f->acc >>= n;
f->valid_bits -= n;
z = f->acc & ((1 << n)-1);
f->acc >>= n;
f->valid_bits -= n;
@@
-2575,34
+2592,33
@@
static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A,
while (z > base) {
float k00,k11;
while (z > base) {
float k00,k11;
-
- k00 = z[-0] - z[-8];
- k
11 = z[-1] - z[-9
];
-
z[-0] = z[-0] + z[-8
];
-
z[-1] = z[-1] + z[-9
];
-
z[-8] = k00
;
- z[
-9] = k11
;
-
-
k00 = z[ -2] -
z[-10];
-
k11 = z[ -3] -
z[-11];
- z[ -
2] = z[ -2] + z[-10]
;
- z[ -
3] = z[ -3] + z[-11]
;
- z[-10] = (
k00+k
11) * A2;
- z[-11] = (
k11-k
00) * A2;
-
- k00 = z[
-12] - z[ -4]; // reverse to avoid a unary negation
+ float l00,l11;
+
+ k
00 = z[-0] - z[ -8
];
+
k11 = z[-1] - z[ -9
];
+
l00 = z[-2] - z[-10
];
+
l11 = z[-3] - z[-11]
;
+ z[
-0] = z[-0] + z[ -8]
;
+ z[ -1] = z[-1] + z[ -9];
+
z[ -2] = z[-2] +
z[-10];
+
z[ -3] = z[-3] +
z[-11];
+ z[ -
8] = k00
;
+ z[ -
9] = k11
;
+ z[-10] = (
l00+l
11) * A2;
+ z[-11] = (
l11-l
00) * A2;
+
+ k00 = z[
-4] - z[-12];
k11 = z[ -5] - z[-13];
k11 = z[ -5] - z[-13];
+ l00 = z[ -6] - z[-14];
+ l11 = z[ -7] - z[-15];
z[ -4] = z[ -4] + z[-12];
z[ -5] = z[ -5] + z[-13];
z[ -4] = z[ -4] + z[-12];
z[ -5] = z[ -5] + z[-13];
- z[-12] = k11;
- z[-13] = k00;
-
- k00 = z[-14] - z[ -6]; // reverse to avoid a unary negation
- k11 = z[ -7] - z[-15];
z[ -6] = z[ -6] + z[-14];
z[ -7] = z[ -7] + z[-15];
z[ -6] = z[ -6] + z[-14];
z[ -7] = z[ -7] + z[-15];
- z[-14] = (k00+k11) * A2;
- z[-15] = (k00-k11) * A2;
+ z[-12] = k11;
+ z[-13] = -k00;
+ z[-14] = (l11-l00) * A2;
+ z[-15] = (l00+l11) * -A2;
iter_54(z);
iter_54(z-8);
iter_54(z);
iter_54(z-8);
@@
-3067,6
+3083,7
@@
static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *f
for (q=1; q < g->values; ++q) {
j = g->sorted_order[q];
#ifndef STB_VORBIS_NO_DEFER_FLOOR
for (q=1; q < g->values; ++q) {
j = g->sorted_order[q];
#ifndef STB_VORBIS_NO_DEFER_FLOOR
+ STBV_NOTUSED(step2_flag);
if (finalY[j] >= 0)
#else
if (step2_flag[j])
if (finalY[j] >= 0)
#else
if (step2_flag[j])
@@
-3169,6
+3186,7
@@
static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
// WINDOWING
// WINDOWING
+ STBV_NOTUSED(left_end);
n = f->blocksize[m->blockflag];
map = &f->mapping[m->mapping];
n = f->blocksize[m->blockflag];
map = &f->mapping[m->mapping];
@@
-3366,7
+3384,7
@@
static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
// this isn't to spec, but spec would require us to read ahead
// and decode the size of all current frames--could be done,
// but presumably it's not a commonly used feature
// this isn't to spec, but spec would require us to read ahead
// and decode the size of all current frames--could be done,
// but presumably it's not a commonly used feature
- f->current_loc =
-n2; // start of first frame is positioned for discard
+ f->current_loc =
0u - n2; // start of first frame is positioned for discard (NB this is an intentional unsigned overflow/wrap-around)
// we might have to discard samples "from" the next frame too,
// if we're lapping a large block then a small at the start?
f->discard_samples_deferred = n - right_end;
// we might have to discard samples "from" the next frame too,
// if we're lapping a large block then a small at the start?
f->discard_samples_deferred = n - right_end;
@@
-3633,17
+3651,24
@@
static int start_decoder(vorb *f)
//file vendor
len = get32_packet(f);
f->vendor = (char*)setup_malloc(f, sizeof(char) * (len+1));
//file vendor
len = get32_packet(f);
f->vendor = (char*)setup_malloc(f, sizeof(char) * (len+1));
+ if (f->vendor == NULL) return error(f, VORBIS_outofmem);
for(i=0; i < len; ++i) {
f->vendor[i] = get8_packet(f);
}
f->vendor[len] = (char)'\0';
//user comments
f->comment_list_length = get32_packet(f);
for(i=0; i < len; ++i) {
f->vendor[i] = get8_packet(f);
}
f->vendor[len] = (char)'\0';
//user comments
f->comment_list_length = get32_packet(f);
- f->comment_list = (char**)setup_malloc(f, sizeof(char*) * (f->comment_list_length));
+ f->comment_list = NULL;
+ if (f->comment_list_length > 0)
+ {
+ f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length));
+ if (f->comment_list == NULL) return error(f, VORBIS_outofmem);
+ }
for(i=0; i < f->comment_list_length; ++i) {
len = get32_packet(f);
f->comment_list[i] = (char*)setup_malloc(f, sizeof(char) * (len+1));
for(i=0; i < f->comment_list_length; ++i) {
len = get32_packet(f);
f->comment_list[i] = (char*)setup_malloc(f, sizeof(char) * (len+1));
+ if (f->comment_list[i] == NULL) return error(f, VORBIS_outofmem);
for(j=0; j < len; ++j) {
f->comment_list[i][j] = get8_packet(f);
for(j=0; j < len; ++j) {
f->comment_list[i][j] = get8_packet(f);
@@
-3860,8
+3885,7
@@
static int start_decoder(vorb *f)
unsigned int div=1;
for (k=0; k < c->dimensions; ++k) {
int off = (z / div) % c->lookup_values;
unsigned int div=1;
for (k=0; k < c->dimensions; ++k) {
int off = (z / div) % c->lookup_values;
- float val = mults[off];
- val = mults[off]*c->delta_value + c->minimum_value + last;
+ float val = mults[off]*c->delta_value + c->minimum_value + last;
c->multiplicands[j*c->dimensions + k] = val;
if (c->sequence_p)
last = val;
c->multiplicands[j*c->dimensions + k] = val;
if (c->sequence_p)
last = val;
@@
-3944,7
+3968,7
@@
static int start_decoder(vorb *f)
if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
}
for (k=0; k < 1 << g->class_subclasses[j]; ++k) {
if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
}
for (k=0; k < 1 << g->class_subclasses[j]; ++k) {
- g->subclass_books[j][k] = get_bits(f,8)-1;
+ g->subclass_books[j][k] =
(int16)
get_bits(f,8)-1;
if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
}
}
if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
}
}
@@
-4256,7
+4280,7
@@
static void vorbis_init(stb_vorbis *p, const stb_vorbis_alloc *z)
memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start
if (z) {
p->alloc = *z;
memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start
if (z) {
p->alloc = *z;
- p->alloc.alloc_buffer_length_in_bytes
= (p->alloc.alloc_buffer_length_in_bytes+3) & ~3
;
+ p->alloc.alloc_buffer_length_in_bytes
&= ~7
;
p->temp_offset = p->alloc.alloc_buffer_length_in_bytes;
}
p->eof = 0;
p->temp_offset = p->alloc.alloc_buffer_length_in_bytes;
}
p->eof = 0;
@@
-4502,6
+4526,7
@@
stb_vorbis *stb_vorbis_open_pushdata(
*error = VORBIS_need_more_data;
else
*error = p.error;
*error = VORBIS_need_more_data;
else
*error = p.error;
+ vorbis_deinit(&p);
return NULL;
}
f = vorbis_alloc(&p);
return NULL;
}
f = vorbis_alloc(&p);
@@
-4559,7
+4584,7
@@
static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last)
header[i] = get8(f);
if (f->eof) return 0;
if (header[4] != 0) goto invalid;
header[i] = get8(f);
if (f->eof) return 0;
if (header[4] != 0) goto invalid;
- goal = header[22] + (header[23] << 8) + (header[24]<<16) + (header[25]<<24);
+ goal = header[22] + (header[23] << 8) + (header[24]<<16) + (
(uint32)
header[25]<<24);
for (i=22; i < 26; ++i)
header[i] = 0;
crc = 0;
for (i=22; i < 26; ++i)
header[i] = 0;
crc = 0;
@@
-4963,7
+4988,7
@@
unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f)
// set. whoops!
break;
}
// set. whoops!
break;
}
- previous_safe = last_page_loc+1;
+ //previous_safe = last_page_loc+1; // NOTE: not used after this point, but note for debugging
last_page_loc = stb_vorbis_get_file_offset(f);
}
last_page_loc = stb_vorbis_get_file_offset(f);
}
@@
-5074,7
+5099,10
@@
stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const st
stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc)
{
stb_vorbis *f, p;
stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc)
{
stb_vorbis *f, p;
- if (data == NULL) return NULL;
+ if (!data) {
+ if (error) *error = VORBIS_unexpected_eof;
+ return NULL;
+ }
vorbis_init(&p, alloc);
p.stream = (uint8 *) data;
p.stream_end = (uint8 *) data + len;
vorbis_init(&p, alloc);
p.stream = (uint8 *) data;
p.stream_end = (uint8 *) data + len;
@@
-5100,19
+5128,19
@@
stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *err
#define PLAYBACK_LEFT 2
#define PLAYBACK_RIGHT 4
#define PLAYBACK_LEFT 2
#define PLAYBACK_RIGHT 4
-#define L (PLAYBACK_LEFT | PLAYBACK_MONO)
-#define C (PLAYBACK_LEFT | PLAYBACK_RIGHT | PLAYBACK_MONO)
-#define R (PLAYBACK_RIGHT | PLAYBACK_MONO)
+#define
SBV
L (PLAYBACK_LEFT | PLAYBACK_MONO)
+#define
SBV
C (PLAYBACK_LEFT | PLAYBACK_RIGHT | PLAYBACK_MONO)
+#define
SBV
R (PLAYBACK_RIGHT | PLAYBACK_MONO)
static int8 channel_position[7][6] =
{
{ 0 },
static int8 channel_position[7][6] =
{
{ 0 },
- { C },
- {
L,
R },
- {
L, C,
R },
- {
L, R, L,
R },
- {
L, C, R, L,
R },
- {
L, C, R, L, R,
C },
+ {
SBV
C },
+ {
SBVL, SBV
R },
+ {
SBVL, SBVC, SBV
R },
+ {
SBVL, SBVR, SBVL, SBV
R },
+ {
SBVL, SBVC, SBVR, SBVL, SBV
R },
+ {
SBVL, SBVC, SBVR, SBVL, SBVR, SBV
C },
};
};
@@
-5149,11
+5177,11
@@
static void copy_samples(short *dest, float *src, int len)
static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len)
{
static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len)
{
- #define BUFFER_SIZE 32
- float buffer[BUFFER_SIZE];
- int i,j,o,n = BUFFER_SIZE;
+ #define
STB_
BUFFER_SIZE 32
+ float buffer[
STB_
BUFFER_SIZE];
+ int i,j,o,n =
STB_
BUFFER_SIZE;
check_endianness();
check_endianness();
- for (o = 0; o < len; o += BUFFER_SIZE) {
+ for (o = 0; o < len; o +=
STB_
BUFFER_SIZE) {
memset(buffer, 0, sizeof(buffer));
if (o + n > len) n = len - o;
for (j=0; j < num_c; ++j) {
memset(buffer, 0, sizeof(buffer));
if (o + n > len) n = len - o;
for (j=0; j < num_c; ++j) {
@@
-5170,16
+5198,17
@@
static void compute_samples(int mask, short *output, int num_c, float **data, in
output[o+i] = v;
}
}
output[o+i] = v;
}
}
+ #undef STB_BUFFER_SIZE
}
static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len)
{
}
static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len)
{
- #define BUFFER_SIZE 32
- float buffer[BUFFER_SIZE];
- int i,j,o,n = BUFFER_SIZE >> 1;
+ #define
STB_
BUFFER_SIZE 32
+ float buffer[
STB_
BUFFER_SIZE];
+ int i,j,o,n =
STB_
BUFFER_SIZE >> 1;
// o is the offset in the source data
check_endianness();
// o is the offset in the source data
check_endianness();
- for (o = 0; o < len; o += BUFFER_SIZE >> 1) {
+ for (o = 0; o < len; o +=
STB_
BUFFER_SIZE >> 1) {
// o2 is the offset in the output data
int o2 = o << 1;
memset(buffer, 0, sizeof(buffer));
// o2 is the offset in the output data
int o2 = o << 1;
memset(buffer, 0, sizeof(buffer));
@@
-5209,6
+5238,7
@@
static void compute_stereo_samples(short *output, int num_c, float **data, int d
output[o2+i] = v;
}
}
output[o2+i] = v;
}
}
+ #undef STB_BUFFER_SIZE
}
static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples)
}
static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples)
@@
-5281,8
+5311,6
@@
int stb_vorbis_get_samples_short_interleaved(stb_vorbis *f, int channels, short
float **outputs;
int len = num_shorts / channels;
int n=0;
float **outputs;
int len = num_shorts / channels;
int n=0;
- int z = f->channels;
- if (z > channels) z = channels;
while (n < len) {
int k = f->channel_buffer_end - f->channel_buffer_start;
if (n+k >= len) k = len - n;
while (n < len) {
int k = f->channel_buffer_end - f->channel_buffer_start;
if (n+k >= len) k = len - n;
@@
-5301,8
+5329,6
@@
int stb_vorbis_get_samples_short(stb_vorbis *f, int channels, short **buffer, in
{
float **outputs;
int n=0;
{
float **outputs;
int n=0;
- int z = f->channels;
- if (z > channels) z = channels;
while (n < len) {
int k = f->channel_buffer_end - f->channel_buffer_start;
if (n+k >= len) k = len - n;
while (n < len) {
int k = f->channel_buffer_end - f->channel_buffer_start;
if (n+k >= len) k = len - n;