session_obj.c compares stream_config.start_threshold against a byte counter, but the tinyalsa plugin populates that field from ALSA sw_params, where start_threshold is defined in frames. No unit conversion occurs between the two.
Call chain
- The plugin's
sw_params op receives the raw ALSA structure — include/tinyalsa/plugin.h:
int (*sw_params) (struct pcm_plugin *plugin, struct snd_pcm_sw_params *params);
- In the ALSA ABI the field is frames, per its own comment —
sound/asound.h:
snd_pcm_uframes_t start_threshold; /* min hw_avail frames for automatic start */
(snd_pcm_uframes_t is unsigned long.)
plugins/tinyalsa/src/agm_pcm_plugin.c:518 copies it with a plain cast — no unit conversion, plus a 64-to-32-bit narrowing:
session_config->start_threshold = (uint32_t)sparams->start_threshold;
service/inc/public/agm/agm_api.h:402 documents the destination field as bytes:
uint32_t start_threshold; /**< start_threshold: number of buffers * buffer size */
- Nothing converts it downstream —
service/src/session_obj.c:2297 and :2845 are plain struct assignments:
sess_obj->stream_config = *stream_config;
service/src/session_obj.c:2533-2536 compares it to an accumulated byte count:
if (sess_obj->stream_config.start_threshold > 0 &&
sess_obj->state == SESSION_PREPARED) {
sess_obj->bytes_written += *count;
if (sess_obj->bytes_written >= sess_obj->stream_config.start_threshold) {
count is bytes, per the public API contract — agm_api.h:1000:
* \param[in] count: actual number of bytes in the buffer.
Consequence
A client setting start_threshold through tinyalsa sw_params gets a session that auto-starts after start_threshold / bytes_per_frame frames instead of start_threshold frames. At stereo 16-bit (4 bytes per frame) the effective prefill is one quarter of what was requested, shrinking the ring-buffer cushion and making underruns more likely under graph load.
Either agm_pcm_plugin.c:518 needs a frames-to-bytes conversion from the session media format, or session_obj.c should accumulate frames rather than bytes — depending on which unit the field is meant to carry.
session_obj.ccomparesstream_config.start_thresholdagainst a byte counter, but the tinyalsa plugin populates that field from ALSAsw_params, wherestart_thresholdis defined in frames. No unit conversion occurs between the two.Call chain
sw_paramsop receives the raw ALSA structure —include/tinyalsa/plugin.h:sound/asound.h:(
snd_pcm_uframes_tisunsigned long.)plugins/tinyalsa/src/agm_pcm_plugin.c:518copies it with a plain cast — no unit conversion, plus a 64-to-32-bit narrowing:service/inc/public/agm/agm_api.h:402documents the destination field as bytes:service/src/session_obj.c:2297and:2845are plain struct assignments:service/src/session_obj.c:2533-2536compares it to an accumulated byte count:countis bytes, per the public API contract —agm_api.h:1000:Consequence
A client setting
start_thresholdthrough tinyalsasw_paramsgets a session that auto-starts afterstart_threshold / bytes_per_frameframes instead ofstart_thresholdframes. At stereo 16-bit (4 bytes per frame) the effective prefill is one quarter of what was requested, shrinking the ring-buffer cushion and making underruns more likely under graph load.Either
agm_pcm_plugin.c:518needs a frames-to-bytes conversion from the session media format, orsession_obj.cshould accumulate frames rather than bytes — depending on which unit the field is meant to carry.