Allows for arbitrary frame rates between 1 and 1000 fps.
Adds min/max frame rates to CLI help.
Removes hardcoded instances of the internal clock rate in favor of hb_video_framerate_get_limits().
Unfortunately, much of the codebase generally refers to clock rate as frame rate, so a little extra care is still necessary going forward.
{ { "60", 450000, }, NULL, 1, },
};
int hb_video_rates_count = sizeof(hb_video_rates) / sizeof(hb_video_rates[0]);
+const int hb_video_rate_clock = 27000000; // 27MHz clock
+int hb_video_rate_min = hb_video_rate_clock / 1000; // Min clock rate from *max* frame rate
+int hb_video_rate_max = hb_video_rate_clock / 1; // Max clock rate from *min* frame rate
hb_rate_t *hb_audio_rates_first_item = NULL;
hb_rate_t *hb_audio_rates_last_item = NULL;
return hb_video_framerate_get_name(hb_video_framerate_get_from_name(name));
}
+void hb_video_framerate_get_limits(int *low, int *high, int *clock)
+{
+ *low = hb_video_rate_min;
+ *high = hb_video_rate_max;
+ *clock = hb_video_rate_clock;
+}
+
const hb_rate_t* hb_video_framerate_get_next(const hb_rate_t *last)
{
if (last == NULL)
int hb_video_framerate_get_from_name(const char *name);
const char* hb_video_framerate_get_name(int framerate);
const char* hb_video_framerate_sanitize_name(const char *name);
+void hb_video_framerate_get_limits(int *low, int *high, int *clock);
const hb_rate_t* hb_video_framerate_get_next(const hb_rate_t *last);
int hb_audio_samplerate_get_best(uint32_t codec, int samplerate, int *sr_shift);
{
hb_work_private_t *pv = w->private_data;
+ int clock_min, clock_max, clock;
+ hb_video_framerate_get_limits(&clock_min, &clock_max, &clock);
+
memset( info, 0, sizeof(*info) );
if (pv->context == NULL)
info->geometry.par.den = pv->context->sample_aspect_ratio.den;
compute_frame_duration( pv );
- info->rate.num = 27000000;
- info->rate.den = pv->duration * 300.;
+ info->rate.num = clock;
+ info->rate.den = pv->duration * (clock / 90000.);
info->profile = pv->context->profile;
info->level = pv->context->level;
hb_work_private_t * pv = calloc( 1, sizeof( hb_work_private_t ) );
w->private_data = pv;
-
pv->job = job;
+ int clock_min, clock_max, clock;
+ hb_video_framerate_get_limits(&clock_min, &clock_max, &clock);
+
switch ( w->codec_param )
{
case AV_CODEC_ID_MPEG4:
fps.num = job->vrate.num;
}
- // If the fps.num is 27000000, there's a good chance this is
- // a standard rate that we have in our hb_video_rates table.
+ // If the fps.num is the internal clock rate, there's a good chance
+ // this is a standard rate that we have in our hb_video_rates table.
// Because of rounding errors and approximations made while
// measuring framerate, the actual value may not be exact. So
// we look for rates that are "close" and make an adjustment
// to fps.den.
- if (fps.num == 27000000)
+ if (fps.num == clock)
{
const hb_rate_t *video_framerate = NULL;
while ((video_framerate = hb_video_framerate_get_next(video_framerate)) != NULL)
int max_tracks;
int ii, ret;
+ int clock_min, clock_max, clock;
+ hb_video_framerate_get_limits(&clock_min, &clock_max, &clock);
+
const char *muxer_name = NULL;
uint8_t default_track_flag = 1;
vrate = job->vrate;
}
- // If the vrate is 27000000, there's a good chance this is
- // a standard rate that we have in our hb_video_rates table.
+ // If the vrate is the internal clock rate, there's a good chance
+ // this is a standard rate that we have in our hb_video_rates table.
// Because of rounding errors and approximations made while
// measuring framerate, the actual value may not be exact. So
// we look for rates that are "close" and make an adjustment
// to fps.den.
- if (vrate.num == 27000000)
+ if (vrate.num == clock)
{
const hb_rate_t *video_framerate = NULL;
while ((video_framerate = hb_video_framerate_get_next(video_framerate)) != NULL)
static int get_video_framerate(hb_value_t *rate_value)
{
- int rate = 0;
- if (hb_value_type(rate_value) != HB_VALUE_TYPE_STRING)
+ // Predefined by name
+ if (hb_value_type(rate_value) == HB_VALUE_TYPE_STRING)
{
- double d;
- d = hb_value_get_double(rate_value);
- if (d != 0 && d <= 600)
+ int rate = 0;
+ const char *rate_name = hb_value_get_string(rate_value);
+ if (!strcasecmp(rate_name, "source") ||
+ !strcasecmp(rate_name, "auto") ||
+ !strcasecmp(rate_name, "same as source"))
{
- // Assume the value is an actual framerate and compute
- // 27Mhz based denominator
- rate = (int)(27000000 / d);
+ return rate;
}
else
- {
- // Assume the value is a 27Mhz based denominator
- rate = (int)d;
- }
- }
- else
- {
- const char *rate_name = hb_value_get_string(rate_value);
- if (strcasecmp(rate_name, "source") &&
- strcasecmp(rate_name, "auto") &&
- strcasecmp(rate_name, "same as source"))
{
rate = hb_video_framerate_get_from_name(rate_name);
- if (rate < 0)
+ if (rate != -1)
{
- // No matching rate found. Error out.
- rate = -1;
+ return rate;
}
}
}
- return rate;
+
+ // Arbitrary
+ int clock_min, clock_max, clock,
+ frame_min, frame_max;
+ hb_video_framerate_get_limits(&clock_min, &clock_max, &clock);
+ frame_min = clock / clock_max;
+ frame_max = clock / clock_min;
+ double rate_d = hb_value_get_double(rate_value);
+ if (rate_d >= frame_min && rate_d <= frame_max)
+ {
+ // Value is a framerate, return clockrate
+ return (int)(clock / rate_d);
+ }
+ else if (rate_d >= clock_min && rate_d <= clock_max)
+ {
+ // Value is already a clockrate
+ return (int)(rate_d);
+ }
+
+ // Value out of bounds
+ return -1;
}
int hb_preset_apply_filters(const hb_dict_t *preset, hb_dict_t *job_dict)
hb_value_t *filters_dict, *filter_list, *filter_dict;
char *filter_str;
+ int clock_min, clock_max, clock;
+ hb_video_framerate_get_limits(&clock_min, &clock_max, &clock);
+
// Create new filters
filters_dict = hb_dict_init();
hb_dict_set(job_dict, "Filters", filters_dict);
if (vrate_den == 0)
filter_str = hb_strdup_printf("%d", fr_mode);
else
- filter_str = hb_strdup_printf("%d:%d:%d", fr_mode, 27000000, vrate_den);
+ filter_str = hb_strdup_printf("%d:%d:%d", fr_mode, clock, vrate_den);
filter_dict = hb_dict_init();
hb_dict_set(filter_dict, "ID", hb_value_int(HB_FILTER_VFR));
****************************************************************************/
static void ShowHelp()
{
- int i;
+ int i, clock_min, clock_max, clock;
const hb_rate_t *rate;
const hb_dither_t *dither;
const hb_mixdown_t *mixdown;
fprintf(out, "/");
}
}
- fprintf( out, ")\n"
+ fprintf( out, "\n"
+" or a number between " );
+ hb_video_framerate_get_limits(&clock_min, &clock_max, &clock);
+ fprintf(out, "%i and %i", (clock / clock_max), (clock / clock_min));
+ fprintf( out, ").\n"
" Be aware that not specifying a framerate lets\n"
" HandBrake preserve a source's time stamps,\n"
" potentially creating variable framerate video\n"