a2dp: improve a2dp sink codec data flushing

Let codec decides when rtp packet need to be sent (terminated by MTU size in most case).
LDAC encoding loop can now be terminated by reading if frame_num is written, no 'frame_count' updating is needed.
RTP payload fragmentation can now be implemented more easily based on this.
This commit is contained in:
Huang-Huang Bao 2021-03-31 17:50:15 +08:00 committed by Wim Taymans
parent 7b9792ffab
commit 5c93f780cf
6 changed files with 56 additions and 170 deletions

View file

@ -377,11 +377,6 @@ static void codec_deinit(void *data)
free(this); free(this);
} }
static int codec_get_num_blocks(void *data)
{
return 1;
}
static int codec_get_block_size(void *data) static int codec_get_block_size(void *data)
{ {
struct impl *this = data; struct impl *this = data;
@ -407,7 +402,7 @@ static int codec_start_encode (void *data,
static int codec_encode(void *data, static int codec_encode(void *data,
const void *src, size_t src_size, const void *src, size_t src_size,
void *dst, size_t dst_size, void *dst, size_t dst_size,
size_t *dst_out) size_t *dst_out, int *need_flush)
{ {
struct impl *this = data; struct impl *this = data;
int res; int res;
@ -445,6 +440,7 @@ static int codec_encode(void *data,
return -EINVAL; return -EINVAL;
*dst_out = out_args.numOutBytes; *dst_out = out_args.numOutBytes;
*need_flush = 1;
return out_args.numInSamples * this->samplesize; return out_args.numInSamples * this->samplesize;
} }
@ -498,7 +494,6 @@ const struct a2dp_codec a2dp_codec_aac = {
.init = codec_init, .init = codec_init,
.deinit = codec_deinit, .deinit = codec_deinit,
.get_block_size = codec_get_block_size, .get_block_size = codec_get_block_size,
.get_num_blocks = codec_get_num_blocks,
.start_encode = codec_start_encode, .start_encode = codec_start_encode,
.encode = codec_encode, .encode = codec_encode,
.abr_process = codec_abr_process, .abr_process = codec_abr_process,

View file

@ -43,6 +43,8 @@ struct impl {
size_t mtu; size_t mtu;
int codesize; int codesize;
int frame_length; int frame_length;
int frame_count;
int max_frames;
bool hd; bool hd;
}; };
@ -202,19 +204,6 @@ static int codec_increase_bitpool(void *data)
return -ENOTSUP; return -ENOTSUP;
} }
static int codec_get_num_blocks(void *data)
{
struct impl *this = data;
size_t frame_count;
if (this->hd)
frame_count = (this->mtu - sizeof(struct rtp_header)) / this->frame_length;
else
frame_count = this->mtu / this->frame_length;
return frame_count;
}
static int codec_get_block_size(void *data) static int codec_get_block_size(void *data)
{ {
struct impl *this = data; struct impl *this = data;
@ -247,6 +236,11 @@ static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
this->frame_length = this->hd ? 6 : 4; this->frame_length = this->hd ? 6 : 4;
this->codesize = 4 * 3 * 2; this->codesize = 4 * 3 * 2;
if (this->hd)
this->max_frames = (this->mtu - sizeof(struct rtp_header)) / this->frame_length;
else
this->max_frames = this->mtu / this->frame_length;
return this; return this;
error_errno: error_errno:
@ -277,6 +271,8 @@ static int codec_start_encode (void *data,
{ {
struct impl *this = data; struct impl *this = data;
this->frame_count = 0;
if (!this->hd) if (!this->hd)
return 0; return 0;
@ -287,21 +283,31 @@ static int codec_start_encode (void *data,
this->header->pt = 1; this->header->pt = 1;
this->header->sequence_number = htons(seqnum); this->header->sequence_number = htons(seqnum);
this->header->timestamp = htonl(timestamp); this->header->timestamp = htonl(timestamp);
this->header->ssrc = htonl(1);
return sizeof(struct rtp_header); return sizeof(struct rtp_header);
} }
static int codec_encode(void *data, static int codec_encode(void *data,
const void *src, size_t src_size, const void *src, size_t src_size,
void *dst, size_t dst_size, void *dst, size_t dst_size,
size_t *dst_out) size_t *dst_out, int *need_flush)
{ {
struct impl *this = data; struct impl *this = data;
size_t avail_dst_size;
int res; int res;
res = aptx_encode(this->aptx, src, src_size, avail_dst_size = (this->max_frames - this->frame_count) * this->frame_length;
dst, dst_size, dst_out); if (SPA_UNLIKELY(dst_size < avail_dst_size)) {
*need_flush = 1;
return 0;
}
res = aptx_encode(this->aptx, src, src_size,
dst, avail_dst_size, dst_out);
if(SPA_UNLIKELY(res < 0))
return -EINVAL;
this->frame_count += *dst_out / this->frame_length;
*need_flush = this->frame_count >= this->max_frames;
return res; return res;
} }
@ -352,7 +358,6 @@ const struct a2dp_codec a2dp_codec_aptx = {
.init = codec_init, .init = codec_init,
.deinit = codec_deinit, .deinit = codec_deinit,
.get_block_size = codec_get_block_size, .get_block_size = codec_get_block_size,
.get_num_blocks = codec_get_num_blocks,
.abr_process = codec_abr_process, .abr_process = codec_abr_process,
.start_encode = codec_start_encode, .start_encode = codec_start_encode,
.encode = codec_encode, .encode = codec_encode,
@ -376,7 +381,6 @@ const struct a2dp_codec a2dp_codec_aptx_hd = {
.init = codec_init, .init = codec_init,
.deinit = codec_deinit, .deinit = codec_deinit,
.get_block_size = codec_get_block_size, .get_block_size = codec_get_block_size,
.get_num_blocks = codec_get_num_blocks,
.abr_process = codec_abr_process, .abr_process = codec_abr_process,
.start_encode = codec_start_encode, .start_encode = codec_start_encode,
.encode = codec_encode, .encode = codec_encode,

View file

@ -76,50 +76,6 @@ struct impl {
int codesize; int codesize;
int frame_length; int frame_length;
int frame_count; int frame_count;
int frame_count_factor;
const struct props *props;
};
enum {
LDACBT_EQMID_BITRATE_990000 = 0, /* LDACBT_EQMID_HQ */
LDACBT_EQMID_BITRATE_660000, /* LDACBT_EQMID_SQ */
LDACBT_EQMID_BITRATE_330000, /* LDACBT_EQMID_MQ */
LDACBT_EQMID_BITRATE_492000,
LDACBT_EQMID_BITRATE_396000,
LDACBT_EQMID_BITRATE_282000,
LDACBT_EQMID_BITRATE_246000,
LDACBT_EQMID_BITRATE_216000,
LDACBT_EQMID_BITRATE_198000,
LDACBT_EQMID_BITRATE_180000,
LDACBT_EQMID_BITRATE_162000,
LDACBT_EQMID_BITRATE_150000,
LDACBT_EQMID_BITRATE_138000
};
struct ldac_config
{
int eqmid;
int frame_count; /* number of ldac frames in packet */
int frame_length; /* ldac frame length */
int frame_length_1ch; /* ldac frame length per channel */
};
static const struct ldac_config ldac_config_table[] = {
{ LDACBT_EQMID_BITRATE_990000, 2, 330, 165},
{ LDACBT_EQMID_BITRATE_660000, 3, 220, 110},
{ LDACBT_EQMID_BITRATE_492000, 4, 164, 82},
{ LDACBT_EQMID_BITRATE_396000, 5, 132, 66},
{ LDACBT_EQMID_BITRATE_330000, 6, 110, 55},
{ LDACBT_EQMID_BITRATE_282000, 7, 94, 47},
{ LDACBT_EQMID_BITRATE_246000, 8, 82, 41},
{ LDACBT_EQMID_BITRATE_216000, 9, 72, 36},
{ LDACBT_EQMID_BITRATE_198000, 10, 66, 33},
{ LDACBT_EQMID_BITRATE_180000, 11, 60, 30},
{ LDACBT_EQMID_BITRATE_162000, 12, 54, 27},
{ LDACBT_EQMID_BITRATE_150000, 13, 50, 25},
{ LDACBT_EQMID_BITRATE_138000, 14, 46, 23},
}; };
static int codec_fill_caps(const struct a2dp_codec *codec, uint32_t flags, uint8_t caps[A2DP_MAX_CAPS_SIZE]) static int codec_fill_caps(const struct a2dp_codec *codec, uint32_t flags, uint8_t caps[A2DP_MAX_CAPS_SIZE])
@ -265,23 +221,6 @@ static int codec_enum_config(const struct a2dp_codec *codec,
return *param == NULL ? -EIO : 1; return *param == NULL ? -EIO : 1;
} }
static int update_frame_info(struct impl *this)
{
const struct ldac_config *config;
this->eqmid = ldacBT_get_eqmid(this->ldac);
for (size_t i = 0; i < SPA_N_ELEMENTS(ldac_config_table); ++i) {
config = &ldac_config_table[i];
if (config->eqmid != this->eqmid)
continue;
this->frame_count = config->frame_count;
this->frame_length = config->frame_length;
return 0;
}
return -EINVAL;
}
static int codec_reduce_bitpool(void *data) static int codec_reduce_bitpool(void *data)
{ {
#ifdef ENABLE_LDAC_ABR #ifdef ENABLE_LDAC_ABR
@ -292,7 +231,6 @@ static int codec_reduce_bitpool(void *data)
if (this->eqmid == LDACBT_EQMID_BITRATE_330000 || !this->enable_abr) if (this->eqmid == LDACBT_EQMID_BITRATE_330000 || !this->enable_abr)
return this->eqmid; return this->eqmid;
res = ldacBT_alter_eqmid_priority(this->ldac, LDACBT_EQMID_INC_CONNECTION); res = ldacBT_alter_eqmid_priority(this->ldac, LDACBT_EQMID_INC_CONNECTION);
update_frame_info(this);
return res; return res;
#endif #endif
} }
@ -307,17 +245,10 @@ static int codec_increase_bitpool(void *data)
if (!this->enable_abr) if (!this->enable_abr)
return this->eqmid; return this->eqmid;
res = ldacBT_alter_eqmid_priority(this->ldac, LDACBT_EQMID_INC_QUALITY); res = ldacBT_alter_eqmid_priority(this->ldac, LDACBT_EQMID_INC_QUALITY);
update_frame_info(this);
return res; return res;
#endif #endif
} }
static int codec_get_num_blocks(void *data)
{
struct impl *this = data;
return this->frame_count * this->frame_count_factor;
}
static int codec_get_block_size(void *data) static int codec_get_block_size(void *data)
{ {
struct impl *this = data; struct impl *this = data;
@ -450,7 +381,7 @@ static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
this->mtu = mtu; this->mtu = mtu;
this->frequency = info->info.raw.rate; this->frequency = info->info.raw.rate;
this->codesize = info->info.raw.channels; this->codesize = info->info.raw.channels * LDACBT_ENC_LSU;
switch (info->info.raw.format) { switch (info->info.raw.format) {
case SPA_AUDIO_FORMAT_F32: case SPA_AUDIO_FORMAT_F32:
@ -474,23 +405,6 @@ static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
goto error; goto error;
} }
switch(conf->frequency) {
case LDACBT_SAMPLING_FREQ_044100:
case LDACBT_SAMPLING_FREQ_048000:
this->codesize *= 128;
this->frame_count_factor = 1;
break;
case LDACBT_SAMPLING_FREQ_088200:
case LDACBT_SAMPLING_FREQ_096000:
/* ldac ecoder has a constant encoding lsu: LDACBT_ENC_LSU=128 */
this->codesize *= 128;
this->frame_count_factor = 2;
break;
default:
res = -EINVAL;
goto error;
}
res = ldacBT_init_handle_encode(this->ldac, res = ldacBT_init_handle_encode(this->ldac,
this->mtu, this->mtu,
this->eqmid, this->eqmid,
@ -513,8 +427,6 @@ static void *codec_init(const struct a2dp_codec *codec, uint32_t flags,
goto error; goto error;
#endif #endif
update_frame_info(this);
return this; return this;
error_errno: error_errno:
@ -562,8 +474,6 @@ static int codec_update_props(void *data, void *props)
if ((res = ldacBT_set_eqmid(this->ldac, this->eqmid)) < 0) if ((res = ldacBT_set_eqmid(this->ldac, this->eqmid)) < 0)
goto error; goto error;
if ((res = update_frame_info(this)) < 0)
goto error;
return 0; return 0;
error: error:
return res; return res;
@ -576,7 +486,6 @@ static int codec_abr_process(void *data, size_t unsent)
int res; int res;
res = ldac_ABR_Proc(this->ldac, this->ldac_abr, res = ldac_ABR_Proc(this->ldac, this->ldac_abr,
unsent / LDAC_ABR_MAX_PACKET_NBYTES, this->enable_abr); unsent / LDAC_ABR_MAX_PACKET_NBYTES, this->enable_abr);
update_frame_info(this);
return res; return res;
#else #else
return -ENOTSUP; return -ENOTSUP;
@ -604,7 +513,7 @@ static int codec_start_encode (void *data,
static int codec_encode(void *data, static int codec_encode(void *data,
const void *src, size_t src_size, const void *src, size_t src_size,
void *dst, size_t dst_size, void *dst, size_t dst_size,
size_t *dst_out) size_t *dst_out, int *need_flush)
{ {
struct impl *this = data; struct impl *this = data;
int res, src_used, dst_used, frame_num = 0; int res, src_used, dst_used, frame_num = 0;
@ -613,12 +522,13 @@ static int codec_encode(void *data,
dst_used = dst_size; dst_used = dst_size;
res = ldacBT_encode(this->ldac, (void*)src, &src_used, dst, &dst_used, &frame_num); res = ldacBT_encode(this->ldac, (void*)src, &src_used, dst, &dst_used, &frame_num);
if (res < 0) if (SPA_UNLIKELY(res < 0))
return -EINVAL; return -EINVAL;
*dst_out = dst_used; *dst_out = dst_used;
this->payload->frame_count += frame_num; this->payload->frame_count += frame_num;
*need_flush = this->payload->frame_count > 0;
return src_used; return src_used;
} }
@ -644,7 +554,6 @@ const struct a2dp_codec a2dp_codec_ldac = {
.deinit = codec_deinit, .deinit = codec_deinit,
.update_props = codec_update_props, .update_props = codec_update_props,
.get_block_size = codec_get_block_size, .get_block_size = codec_get_block_size,
.get_num_blocks = codec_get_num_blocks,
.abr_process = codec_abr_process, .abr_process = codec_abr_process,
.start_encode = codec_start_encode, .start_encode = codec_start_encode,
.encode = codec_encode, .encode = codec_encode,

View file

@ -45,7 +45,7 @@ struct impl {
size_t mtu; size_t mtu;
int codesize; int codesize;
int frame_length; int max_frames;
int min_bitpool; int min_bitpool;
int max_bitpool; int max_bitpool;
@ -86,7 +86,7 @@ static int codec_fill_caps(const struct a2dp_codec *codec, uint32_t flags,
static uint8_t default_bitpool(uint8_t freq, uint8_t mode, bool xq) static uint8_t default_bitpool(uint8_t freq, uint8_t mode, bool xq)
{ {
/* A2DP spec v1.2 states that all SNK implementation shall handle bitrates /* A2DP spec v1.2 states that all SNK implementation shall handle bitrates
* of up to 512 kbps (~ bitpool = 86 stereo, or 2x43 dual channel at 44.1KHz * of up to 512 kbps (~ bitpool = 86 stereo, or 2x43 dual channel at 44.1KHz
* or ~ bitpool = 78 stereo, or 2x39 dual channel at 48KHz). */ * or ~ bitpool = 78 stereo, or 2x39 dual channel at 48KHz). */
switch (freq) { switch (freq) {
case SBC_SAMPLING_FREQ_16000: case SBC_SAMPLING_FREQ_16000:
@ -325,9 +325,13 @@ static int codec_validate_config(const struct a2dp_codec *codec, uint32_t flags,
static int codec_set_bitpool(struct impl *this, int bitpool) static int codec_set_bitpool(struct impl *this, int bitpool)
{ {
size_t rtp_size = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
this->sbc.bitpool = SPA_CLAMP(bitpool, this->min_bitpool, this->max_bitpool); this->sbc.bitpool = SPA_CLAMP(bitpool, this->min_bitpool, this->max_bitpool);
this->codesize = sbc_get_codesize(&this->sbc); this->codesize = sbc_get_codesize(&this->sbc);
this->frame_length = sbc_get_frame_length(&this->sbc); this->max_frames = (this->mtu - rtp_size) / sbc_get_frame_length(&this->sbc);
if (this->max_frames > 15)
this->max_frames = 15;
return this->sbc.bitpool; return this->sbc.bitpool;
} }
@ -422,18 +426,6 @@ static int codec_increase_bitpool(void *data)
return codec_set_bitpool(this, this->sbc.bitpool + 1); return codec_set_bitpool(this, this->sbc.bitpool + 1);
} }
static int codec_get_num_blocks(void *data)
{
struct impl *this = data;
size_t rtp_size = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
size_t frame_count = (this->mtu - rtp_size) / this->frame_length;
/* frame_count is only 4 bit number */
if (frame_count > 15)
frame_count = 15;
return frame_count;
}
static int codec_get_block_size(void *data) static int codec_get_block_size(void *data)
{ {
struct impl *this = data; struct impl *this = data;
@ -580,17 +572,19 @@ static int codec_start_encode (void *data,
static int codec_encode(void *data, static int codec_encode(void *data,
const void *src, size_t src_size, const void *src, size_t src_size,
void *dst, size_t dst_size, void *dst, size_t dst_size,
size_t *dst_out) size_t *dst_out, int *need_flush)
{ {
struct impl *this = data; struct impl *this = data;
int res; int res;
res = sbc_encode(&this->sbc, src, src_size, res = sbc_encode(&this->sbc, src, src_size,
dst, dst_size, (ssize_t*)dst_out); dst, dst_size, (ssize_t*)dst_out);
if (SPA_UNLIKELY(res < 0))
return -EINVAL;
spa_assert(res == this->codesize);
if (res >= this->codesize) this->payload->frame_count += res / this->codesize;
this->payload->frame_count += res / this->codesize; *need_flush = this->payload->frame_count >= this->max_frames;
return res; return res;
} }
@ -636,7 +630,6 @@ const struct a2dp_codec a2dp_codec_sbc = {
.init = codec_init, .init = codec_init,
.deinit = codec_deinit, .deinit = codec_deinit,
.get_block_size = codec_get_block_size, .get_block_size = codec_get_block_size,
.get_num_blocks = codec_get_num_blocks,
.abr_process = codec_abr_process, .abr_process = codec_abr_process,
.start_encode = codec_start_encode, .start_encode = codec_start_encode,
.encode = codec_encode, .encode = codec_encode,
@ -659,7 +652,6 @@ const struct a2dp_codec a2dp_codec_sbc_xq = {
.init = codec_init, .init = codec_init,
.deinit = codec_deinit, .deinit = codec_deinit,
.get_block_size = codec_get_block_size, .get_block_size = codec_get_block_size,
.get_num_blocks = codec_get_num_blocks,
.abr_process = codec_abr_process, .abr_process = codec_abr_process,
.start_encode = codec_start_encode, .start_encode = codec_start_encode,
.encode = codec_encode, .encode = codec_encode,

View file

@ -371,7 +371,6 @@ struct a2dp_codec {
int (*update_props) (void *data, void *props); int (*update_props) (void *data, void *props);
int (*get_block_size) (void *data); int (*get_block_size) (void *data);
int (*get_num_blocks) (void *data);
int (*abr_process) (void *data, size_t unsent); int (*abr_process) (void *data, size_t unsent);
@ -380,7 +379,7 @@ struct a2dp_codec {
int (*encode) (void *data, int (*encode) (void *data,
const void *src, size_t src_size, const void *src, size_t src_size,
void *dst, size_t dst_size, void *dst, size_t dst_size,
size_t *dst_out); size_t *dst_out, int *need_flush);
int (*start_decode) (void *data, int (*start_decode) (void *data,
const void *src, size_t src_size, uint16_t *seqnum, uint32_t *timestamp); const void *src, size_t src_size, uint16_t *seqnum, uint32_t *timestamp);

View file

@ -133,10 +133,11 @@ struct impl {
void *codec_data; void *codec_data;
struct spa_audio_info codec_format; struct spa_audio_info codec_format;
int need_flush;
uint32_t block_size; uint32_t block_size;
uint32_t num_blocks;
uint8_t buffer[4096]; uint8_t buffer[4096];
uint32_t buffer_used; uint32_t buffer_used;
uint32_t header_size;
uint32_t frame_count; uint32_t frame_count;
uint16_t seqnum; uint16_t seqnum;
uint32_t timestamp; uint32_t timestamp;
@ -376,11 +377,6 @@ static int impl_node_set_param(void *object, uint32_t id, uint32_t flags,
return 0; return 0;
} }
static void update_num_blocks(struct impl *this)
{
this->num_blocks = this->codec->get_num_blocks(this->codec_data);
}
static int reset_buffer(struct impl *this) static int reset_buffer(struct impl *this)
{ {
if (this->codec_props_changed && this->codec_props if (this->codec_props_changed && this->codec_props
@ -388,10 +384,12 @@ static int reset_buffer(struct impl *this)
this->codec->update_props(this->codec_data, this->codec_props); this->codec->update_props(this->codec_data, this->codec_props);
this->codec_props_changed = false; this->codec_props_changed = false;
} }
this->need_flush = 0;
this->frame_count = 0; this->frame_count = 0;
this->buffer_used = this->codec->start_encode(this->codec_data, this->buffer_used = this->codec->start_encode(this->codec_data,
this->buffer, sizeof(this->buffer), this->buffer, sizeof(this->buffer),
this->seqnum++, this->timestamp); this->seqnum++, this->timestamp);
this->header_size = this->buffer_used;
this->timestamp = this->sample_count; this->timestamp = this->sample_count;
return 0; return 0;
} }
@ -415,7 +413,6 @@ static int send_buffer(struct impl *this)
if (unsent >= 0) { if (unsent >= 0) {
unsent = this->fd_buffer_size - unsent; unsent = this->fd_buffer_size - unsent;
this->codec->abr_process(this->codec_data, unsent); this->codec->abr_process(this->codec_data, unsent);
update_num_blocks(this);
} }
spa_log_trace(this->log, NAME " %p: send %d %u %u %u %u", spa_log_trace(this->log, NAME " %p: send %d %u %u %u %u",
@ -441,11 +438,6 @@ static bool want_flush(struct impl *this)
return (this->frame_count * this->block_size / this->port.frame_size >= MIN_LATENCY); return (this->frame_count * this->block_size / this->port.frame_size >= MIN_LATENCY);
} }
static bool need_flush(struct impl *this)
{
return (this->frame_count >= this->num_blocks);
}
static int encode_buffer(struct impl *this, const void *data, uint32_t size) static int encode_buffer(struct impl *this, const void *data, uint32_t size)
{ {
int processed; int processed;
@ -458,7 +450,7 @@ static int encode_buffer(struct impl *this, const void *data, uint32_t size)
this, size, this->buffer_used, port->frame_size, this->block_size, this, size, this->buffer_used, port->frame_size, this->block_size,
this->frame_count); this->frame_count);
if (need_flush(this)) if (this->need_flush)
return 0; return 0;
if (this->buffer_used >= sizeof(this->buffer)) if (this->buffer_used >= sizeof(this->buffer))
@ -479,7 +471,7 @@ static int encode_buffer(struct impl *this, const void *data, uint32_t size)
from_data, from_size, from_data, from_size,
this->buffer + this->buffer_used, this->buffer + this->buffer_used,
sizeof(this->buffer) - this->buffer_used, sizeof(this->buffer) - this->buffer_used,
&out_encoded); &out_encoded, &this->need_flush);
if (processed < 0) if (processed < 0)
return processed; return processed;
@ -499,10 +491,10 @@ static int encode_buffer(struct impl *this, const void *data, uint32_t size)
static int flush_buffer(struct impl *this) static int flush_buffer(struct impl *this)
{ {
spa_log_trace(this->log, NAME" %p: used:%d num_blocks:%d block_size:%d", this, spa_log_trace(this->log, NAME" %p: used:%d block_size:%d", this,
this->buffer_used, this->num_blocks, this->block_size); this->buffer_used, this->block_size);
if (want_flush(this) || need_flush(this)) if (this->need_flush || want_flush(this))
return send_buffer(this); return send_buffer(this);
return 0; return 0;
@ -536,12 +528,11 @@ static void enable_flush(struct impl *this, bool enabled)
static int flush_data(struct impl *this, uint64_t now_time) static int flush_data(struct impl *this, uint64_t now_time)
{ {
int written; int written;
uint32_t total_frames, iter_buffer_used; uint32_t total_frames;
struct port *port = &this->port; struct port *port = &this->port;
total_frames = 0; total_frames = 0;
again: again:
iter_buffer_used = this->buffer_used;
while (!spa_list_is_empty(&port->ready)) { while (!spa_list_is_empty(&port->ready)) {
uint8_t *src; uint8_t *src;
uint32_t n_bytes, n_frames; uint32_t n_bytes, n_frames;
@ -599,8 +590,7 @@ again:
spa_log_trace(this->log, NAME " %p: written %u frames", this, total_frames); spa_log_trace(this->log, NAME " %p: written %u frames", this, total_frames);
} }
iter_buffer_used = this->buffer_used - iter_buffer_used; if (written > 0 && this->buffer_used == this->header_size) {
if (written > 0 && iter_buffer_used == 0) {
enable_flush(this, false); enable_flush(this, false);
return 0; return 0;
} }
@ -610,7 +600,6 @@ again:
spa_log_trace(this->log, NAME" %p: delay flush", this); spa_log_trace(this->log, NAME" %p: delay flush", this);
if (now_time - this->last_error > SPA_NSEC_PER_SEC / 2) { if (now_time - this->last_error > SPA_NSEC_PER_SEC / 2) {
this->codec->reduce_bitpool(this->codec_data); this->codec->reduce_bitpool(this->codec_data);
update_num_blocks(this);
this->last_error = now_time; this->last_error = now_time;
} }
enable_flush(this, true); enable_flush(this, true);
@ -623,7 +612,6 @@ again:
else if (written > 0) { else if (written > 0) {
if (now_time - this->last_error > SPA_NSEC_PER_SEC) { if (now_time - this->last_error > SPA_NSEC_PER_SEC) {
this->codec->increase_bitpool(this->codec_data); this->codec->increase_bitpool(this->codec_data);
update_num_blocks(this);
this->last_error = now_time; this->last_error = now_time;
} }
if (!spa_list_is_empty(&port->ready)) if (!spa_list_is_empty(&port->ready))
@ -746,15 +734,14 @@ static int do_start(struct impl *this)
this->seqnum = 0; this->seqnum = 0;
this->block_size = this->codec->get_block_size(this->codec_data); this->block_size = this->codec->get_block_size(this->codec_data);
update_num_blocks(this);
if (this->block_size > sizeof(this->tmp_buffer)) { if (this->block_size > sizeof(this->tmp_buffer)) {
spa_log_error(this->log, "block-size %d > %zu", spa_log_error(this->log, "block-size %d > %zu",
this->block_size, sizeof(this->tmp_buffer)); this->block_size, sizeof(this->tmp_buffer));
return -EIO; return -EIO;
} }
spa_log_debug(this->log, NAME " %p: block_size %d num_blocks:%d", this, spa_log_debug(this->log, NAME " %p: block_size %d", this,
this->block_size, this->num_blocks); this->block_size);
val = this->codec->send_buf_size > 0 val = this->codec->send_buf_size > 0
/* The kernel doubles the SO_SNDBUF option value set by setsockopt(). */ /* The kernel doubles the SO_SNDBUF option value set by setsockopt(). */