Skip to content

Commit

Permalink
- improve start up performance
Browse files Browse the repository at this point in the history
  • Loading branch information
igorshevach committed Nov 7, 2023
1 parent c812e28 commit 8e96bcc
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 28 deletions.
2 changes: 1 addition & 1 deletion transcoder/tests/config_a.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
"throttler": {
"maxDataRate": 1.5,
"coldSeconds": 0,
"useStatsDataRate": false,
"minThrottleWaitMs": 1
},
"frameDropper1": {
Expand Down
2 changes: 1 addition & 1 deletion transcoder/tests/config_v.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"throttler": {
"maxDataRate": 1.5,
"coldSeconds": 1,
"useStatsDataRate": false,
"minThrottleWaitMs": 1
},
"frameDropper1": {
Expand Down
55 changes: 32 additions & 23 deletions transcoder/utils/throttler.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,18 @@
#include "json_parser.h"

static void doThrottle(float maxDataRate,
float coldSeconds,
int minThrottleWaitMs,
bool useStatsDataRate,
double minThrottleWaitMs,
samples_stats_t *stats,
AVRational targetFramerate);

int
throttler_init(samples_stats_t *stats,throttler_t *throttler) {
json_value_t *config = GetConfig();
json_get_double(config,"throttler.maxDataRate",INFINITY,(double*)&throttler->maxDataRate);
*(bool*)&throttler->enabled = throttler->maxDataRate < INFINITY;
if(throttler->enabled){
json_get_double(config,"throttler.coldSeconds",0,(double*)&throttler->coldSeconds);
json_get_int(config,"throttler.minThrottleWaitMs",1,(int*)&throttler->minThrottleWaitMs);
if(throttler->maxDataRate < INFINITY){
json_get_bool(config,"throttler.useStatsDataRate",false,(bool*)&throttler->useStatsDataRate);
json_get_double(config,"throttler.minThrottleWaitMs",1,(double*)&throttler->minThrottleWaitMs);
throttler->stats = stats;
}
return 0;
Expand All @@ -34,12 +33,14 @@ throttler_process(throttler_t *throttler,transcode_session_t *transcode_session)
const transcode_mediaInfo_t *mediaInfo = transcode_session ? transcode_session->currentMediaInfo : NULL;
if(mediaInfo && mediaInfo->codecParams){
const bool isVideo = mediaInfo->codecParams->codec_type == AVMEDIA_TYPE_VIDEO;
// TODO: currently only AAC 'fps' is supported, MP3 and opus etc.
// may have a different frame allocation schemes
const AVRational frameRate = isVideo ? mediaInfo->frameRate :
(AVRational){ .num = mediaInfo->codecParams->sample_rate ,
.den = 1024 };

doThrottle(throttler->maxDataRate,
throttler->coldSeconds,
throttler->useStatsDataRate,
throttler->minThrottleWaitMs,
throttler->stats,
frameRate);
Expand All @@ -50,36 +51,44 @@ throttler_process(throttler_t *throttler,transcode_session_t *transcode_session)
static
void
doThrottle(float maxDataRate,
float coldSeconds,
int minThrottleWaitMs,
bool useStatsDataRate,
double minThrottleWaitMs,
samples_stats_t *stats,
AVRational targetFramerate)
{

if(targetFramerate.den > 0 && targetFramerate.num > 0) {
float currentDataRate;
const double currentDataRate = useStatsDataRate ? stats->currentRate :
stats->currentFrameRate * targetFramerate.den / (float)targetFramerate.num;

samples_stats_log(CATEGORY_RECEIVER,AV_LOG_DEBUG,stats,"throttleThread-Stats");

if(stats->totalFrames * targetFramerate.den < coldSeconds * targetFramerate.num ) {
return;
}
// when starting up use actual number of frames received so far and
// not the speed at which they accumulate
const currentFrameRate = __MIN(stats->totalFrames,stats->currentFrameRate);
currentDataRate = currentFrameRate * targetFramerate.den / (float)targetFramerate.num;
samples_stats_log(CATEGORY_RECEIVER,AV_LOG_DEBUG,stats,"Throttle-Stats");

LOGGER(CATEGORY_THROTTLER,
AV_LOG_DEBUG,"throttleThread. data rate current: %.3f max: %.3f",
AV_LOG_DEBUG,"%s. data rate current: %.3f max: %.3f",
__FUNCTION__,
currentDataRate,
maxDataRate);

if(currentDataRate > maxDataRate) {
// going to sleep for a period of time gained due to race
int throttleWaitUSec = (currentDataRate - maxDataRate) * 1000 * 1000; //av_rescale(1000 * 1000,targetFramerate.den,targetFramerate.num);
const int minThrottleWaitMs = 1;
int throttleWindowUs;
if(stats->totalFrames * targetFramerate.den < targetFramerate.num) {
// during startup frame rate is not stable and usually is high
// due to system delays related to various factors. therefore.
// we must work with high pressures in small intervals of time.
// In order to not overshoot we take smaller intervals proportional to
// time passed since beginning.
throttleWindowUs = av_rescale_q(1000*1000,
(AVRational){stats->totalFrames,1},
targetFramerate);
} else {
throttleWindowUs = 1000 * 1000;
}
int throttleWaitUSec = (currentDataRate - maxDataRate) * throttleWindowUs;
if(throttleWaitUSec > minThrottleWaitMs * 1000) {
LOGGER(CATEGORY_THROTTLER,AV_LOG_INFO,"throttleThread. throttling %.3f ms",throttleWaitUSec / 1000.f);
LOGGER(CATEGORY_THROTTLER,AV_LOG_INFO,"%s. throttling %.3f ms",
__FUNCTION__,
throttleWaitUSec / 1000.f);
stats->throttleWait += av_rescale_q(throttleWaitUSec, clockScale, standard_timebase);
av_usleep(throttleWaitUSec);
}
Expand Down
5 changes: 2 additions & 3 deletions transcoder/utils/throttler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
#define Throttler_h

typedef struct {
const bool enabled;
const bool useStatsDataRate;
const double maxDataRate;
const double coldSeconds;
const int minThrottleWaitMs;
const double minThrottleWaitMs;
samples_stats_t *stats;
} throttler_t;

Expand Down

0 comments on commit 8e96bcc

Please sign in to comment.