Skip to content

Commit c813134

Browse files
committed
rtl_fm: stream padding
1 parent 581b6b6 commit c813134

File tree

1 file changed

+35
-28
lines changed

1 file changed

+35
-28
lines changed

src/rtl_fm.c

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
*
3131
* todo:
3232
* sanity checks
33-
* pad output on hop
3433
* frequency ranges could be stored better
3534
* auto-hop after time limit
3635
* peak detector to tune onto stronger signals
@@ -188,6 +187,8 @@ struct output_state
188187
pthread_rwlock_t rw;
189188
pthread_cond_t ready;
190189
pthread_mutex_t ready_m;
190+
pthread_mutex_t trycond_m;
191+
int trycond;
191192
};
192193

193194
struct controller_state
@@ -238,7 +239,9 @@ void usage(void)
238239
"\t no-mod: enable no-mod direct sampling\n"
239240
"\t offset: enable offset tuning\n"
240241
"\t wav: generate WAV header\n"
241-
"\t pad: pad output with zeros (broken)\n"
242+
#ifndef _WIN32
243+
"\t pad: pad output gaps with zeros\n"
244+
#endif
242245
"\tfilename ('-' means stdout)\n"
243246
"\t omitting the filename also uses stdout\n\n"
244247
"Experimental options:\n"
@@ -927,18 +930,21 @@ static void *demod_thread_fn(void *arg)
927930
if (d->exit_flag) {
928931
do_exit = 1;
929932
}
933+
pthread_rwlock_wrlock(&o->rw);
934+
o->result = d->lowpassed;
935+
o->result_len = d->lp_len;
936+
pthread_rwlock_unlock(&o->rw);
930937
if (controller.freq_len > 1 && d->squelch_level && \
931938
d->squelch_hits > d->conseq_squelch) {
932939
unmark_shared_buffer(d->lowpassed);
933940
d->squelch_hits = d->conseq_squelch + 1; /* hair trigger */
934941
safe_cond_signal(&controller.hop, &controller.hop_m);
935942
continue;
936943
}
937-
pthread_rwlock_wrlock(&o->rw);
938-
o->result = d->lowpassed;
939-
o->result_len = d->lp_len;
940-
pthread_rwlock_unlock(&o->rw);
941944
safe_cond_signal(&o->ready, &o->ready_m);
945+
pthread_mutex_lock(&o->trycond_m);
946+
o->trycond = 0;
947+
pthread_mutex_unlock(&o->trycond_m);
942948
}
943949
return 0;
944950
}
@@ -954,7 +960,7 @@ static int get_nanotime(struct timespec *ts)
954960

955961
rv = gettimeofday(&tv, NULL);
956962
ts->tv_sec = tv.tv_sec;
957-
ts->tv_nsec = tv.tv_usec * 1000;
963+
ts->tv_nsec = tv.tv_usec * 1000L;
958964
#endif
959965
return rv;
960966
}
@@ -964,11 +970,9 @@ static void *output_thread_fn(void *arg)
964970
{
965971
int r = 0;
966972
struct output_state *s = arg;
967-
//struct timespec abstime;
968973
struct timespec start_time;
969974
struct timespec now_time;
970-
struct timespec fut_time;
971-
int64_t interval, delay, samples, samples2, i;
975+
int64_t i, duration, samples, samples_now;
972976
samples = 0L;
973977
#ifndef _WIN32
974978
get_nanotime(&start_time);
@@ -984,34 +988,33 @@ static void *output_thread_fn(void *arg)
984988
}
985989
#ifndef _WIN32
986990
/* padding requires output at constant rate */
987-
/* figure out how to do this with windows HPET */
988-
pthread_mutex_lock(&s->ready_m);
989-
delay = 1000000000L * (int64_t)s->result_len / (int64_t)s->rate;
990-
get_nanotime(&fut_time);
991-
fut_time.tv_nsec += delay;
992-
r = pthread_cond_timedwait(&s->ready, &s->ready_m, &fut_time);
993-
pthread_mutex_unlock(&s->ready_m);
994-
if (r != ETIMEDOUT) {
991+
/* pthread_cond_timedwait is terrible, roll our own trycond */
992+
// figure out how to do this with windows HPET
993+
usleep(2000);
994+
pthread_mutex_lock(&s->trycond_m);
995+
r = s->trycond;
996+
s->trycond = 1;
997+
pthread_mutex_unlock(&s->trycond_m);
998+
if (r == 0) {
995999
pthread_rwlock_rdlock(&s->rw);
9961000
fwrite(s->result, 2, s->result_len, s->file);
9971001
unmark_shared_buffer(s->result);
998-
samples += s->result_len;
1002+
samples += (int64_t)s->result_len;
9991003
pthread_rwlock_unlock(&s->rw);
10001004
continue;
10011005
}
10021006
get_nanotime(&now_time);
1003-
interval = now_time.tv_sec - start_time.tv_sec;
1004-
interval *= 1000000000L;
1005-
interval += (now_time.tv_nsec - start_time.tv_nsec);
1006-
samples2 = interval * (int64_t)s->rate / 1000000000L;
1007-
samples2 -= samples;
1008-
//fprintf(stderr, "%lli %lli %lli\n", delay, interval, samples);
1009-
/* there must be a better way to write zeros */
1010-
for (i=0L; i<samples2; i++) {
1007+
duration = now_time.tv_sec - start_time.tv_sec;
1008+
duration *= 1000000000L;
1009+
duration += (now_time.tv_nsec - start_time.tv_nsec);
1010+
samples_now = (duration * (int64_t)s->rate) / 1000000000L;
1011+
if (samples_now < samples) {
1012+
continue;}
1013+
for (i=samples; i<samples_now; i++) {
10111014
fputc(0, s->file);
10121015
fputc(0, s->file);
10131016
}
1014-
samples += samples2;
1017+
samples = samples_now;
10151018
#endif
10161019
}
10171020
return 0;
@@ -1163,6 +1166,8 @@ void output_init(struct output_state *s)
11631166
pthread_rwlock_init(&s->rw, NULL);
11641167
pthread_cond_init(&s->ready, NULL);
11651168
pthread_mutex_init(&s->ready_m, NULL);
1169+
pthread_mutex_init(&s->trycond_m, NULL);
1170+
s->trycond = 1;
11661171
s->result = NULL;
11671172
}
11681173

@@ -1171,6 +1176,7 @@ void output_cleanup(struct output_state *s)
11711176
pthread_rwlock_destroy(&s->rw);
11721177
pthread_cond_destroy(&s->ready);
11731178
pthread_mutex_destroy(&s->ready_m);
1179+
pthread_mutex_destroy(&s->trycond_m);
11741180
}
11751181

11761182
void controller_init(struct controller_state *s)
@@ -1430,6 +1436,7 @@ int main(int argc, char **argv)
14301436
signal(SIGPIPE, SIG_IGN);
14311437
#else
14321438
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE );
1439+
output.padded = 0;
14331440
#endif
14341441

14351442
if (demod.deemph) {

0 commit comments

Comments
 (0)