kymera_latency_manager_data_t latency_data;
static uint32 Kymera_LatencyManagerGetLatencyForSeid(uint8 seid);
static uint32 latencyManager_GetBaseLatency(void)
{
KYMERA_INTERNAL_A2DP_START_T *params = KymeraGetLatencyData()->a2dp_start_params;
uint32 latency = TWS_STANDARD_LATENCY_MS;
if (params)
{
if (params->codec_settings.seid == AV_SEID_APTXHD_SNK)
{
latency = APTX_HD_LATENCY_MS;
}
}
return latency;
}
static void kymera_LatencyManagerReconfigureComplete(void)
{
DEBUG_LOG("kymera_LatencyManagerReconfigureComplete");
Kymera_LatencyManagerClearAdjustingLatency();
}
static void kymera_LatencyManagerConfigureRtpStartup(uint8 seid)
{
kymeraTaskData *theKymera = KymeraGetTaskData();
Operator op_rtp_decoder;
if (GET_OP_FROM_CHAIN(op_rtp_decoder, theKymera->chain_input_handle, OPR_RTP_DECODER))
{
uint32 latency_ms = Kymera_LatencyManagerGetLatencyForSeid(seid);
/* With a normal TWM sync startup, the RTP decoder startup period/correction
has to be disabled to avoid a glitch on secondary if the primary makes
a latency correction. When resuming from a muted latency adjustment,
any glitches are masked and the startup correction may be applied.
*/
Kymera_A2dpConfigureRtpDecoderStartupPeriod(op_rtp_decoder, latency_ms / 2);
}
}
static void kymera_LatencyManagerMuteStream(void)
{
kymera_latency_manager_data_t * data = KymeraGetLatencyData();
KYMERA_INTERNAL_A2DP_START_T *params = KymeraGetLatencyData()->a2dp_start_params;
PanicNull(params);
#if defined(INCLUDE_STEREO) && !defined(ENABLE_TWM_SPEAKER)
Kymera_A2dpCommonStop(KymeraGetTaskData()->media_source);
PanicFalse(Kymera_A2dpStart(¶ms->codec_settings, params->max_bitrate, VOLUME_MUTE_IN_DB, params->nq2q_ttp));
kymera_LatencyManagerConfigureRtpStartup(params->codec_settings.seid);
data->current_latency = Kymera_LatencyManagerGetLatencyForSeid(params->codec_settings.seid);
#else
{
bool forwarding = Kymera_A2dpIsForwarding();
if (forwarding)
{
Kymera_A2dpStopForwarding(MirrorProfile_GetA2dpAudioSyncTransportSource());
}
Kymera_A2dpCommonStop(KymeraGetTaskData()->media_source);
PanicFalse(Kymera_A2dpStart(¶ms->codec_settings, params->max_bitrate, VOLUME_MUTE_IN_DB, params->nq2q_ttp));
kymera_LatencyManagerConfigureRtpStartup(params->codec_settings.seid);
data->current_latency = Kymera_LatencyManagerGetLatencyForSeid(params->codec_settings.seid);
if (forwarding)
{
/* Mirroring forwarding only requires the forwarding sync */
a2dp_codec_settings settings = {0};
settings.sink = MirrorProfile_GetA2dpAudioSyncTransportSink();
Kymera_A2dpStartForwarding(&settings);
}
SyncStartA2dp_SetStartTime(VmGetTimerTime());
SyncStartA2dp_ForceSinkAudioSynchronized();
}
#endif /* INCLUDE_STEREO */
}
void Kymera_LatencyManagerHandleToneEnd(void)
{
uint16 seid = Kymera_GetCurrentSeid();
KYMERA_INTERNAL_A2DP_START_T *params = KymeraGetLatencyData()->a2dp_start_params;
if (!Kymera_LatencyManagerIsReconfigInProgress())
{
return;
}
DEBUG_LOG("Kymera_LatencyManagerHandleToneEnd");
if ((seid == AV_SEID_INVALID) || !params || !SinkIsValid(params->codec_settings.sink))
{
/* Streaming is disconnected while we were trying to Mute Audio. */
kymera_LatencyManagerReconfigureComplete();
}
else
{
/* Boost system clocks to reduce transition time */
appPowerPerformanceProfileRequest();
appKymeraBoostDspClockToMax();
kymera_LatencyManagerMuteStream();
MessageSendLater(KymeraGetTask(),
KYMERA_INTERNAL_LATENCY_MANAGER_MUTE_COMPLETE,
NULL,
Kymera_LatencyManagerConfigMuteDurationMs());
appPowerPerformanceProfileRelinquish();
}
}
void Kymera_LatencyManagerHandleMuteComplete(void)
{
KYMERA_INTERNAL_A2DP_START_T *params = KymeraGetLatencyData()->a2dp_start_params;
DEBUG_LOG("Kymera_LatencyManagerHandleMuteComplete");
if(params)
{
Kymera_A2dpHandleInternalSetVolume(params->volume_in_db);
}
else
{
/* A2DP got disconnected while Mute was in progress. Hence the stored params
have been deleted. Mark reconfiguration as complete. */
DEBUG_LOG("Kymera_LatencyManagerHandleMuteComplete: a2dp_start_params are NULL!");
}
kymera_LatencyManagerReconfigureComplete();
}