Basically, if you want to drop frames so that you output 15 for every 30 you get as input, you're outputting 0.5 frames per input frame. Similarly, for a 30->20 dropping, you're outputting 0.67 frames per input frame.
So, as a trivial solution, you could keep a count of the fractional number of frames you're expected to output, and output a single frame when that count goes to one or above.
As a rough sketch, with just an integer loop taking place of the frames:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
double sum = 0;
double rate = argc >= 2 ? atoi(argv[1]) / 30.0 : 0.5;
for (int i = 0; i < 30; i++) {
sum += rate;
if (sum >= 1) {
sum -= 1;
/* pretend we output this frame */
printf("%d\n", i);
}
}
}
Run as foo 20 or something like that to get 20 out of 30 printed.
Or approximately 20 out of 30. That's not entirely accurate because of rounding issues, and the fact that 2/3 can't be represented exactly as binary floating point value. You could modify it to count with rationals instead, so could present 20/30 exactly.
Of course, any divider that doesn't divide 30 exactly will produce jittery output.
For 5 FPS, you could just use modulo again, since 5 divides 30 exactly. Just invert the sense of the test from dropping a fraction to accepting a fraction, e.g. if (framenumber % 5 == 0) { accept frame }