diff options
author | jstebbins <[email protected]> | 2011-01-28 23:18:21 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2011-01-28 23:18:21 +0000 |
commit | f839f412fb7c05e20201d3b09560e5ba085a4fe1 (patch) | |
tree | 92be215f512b5801337b3363bbb3ed597a72dcbc | |
parent | 5eac1c0562ead268ffa4ace6bf86981c7f884faf (diff) |
LinGui: add CFR option for "Same as source" framerate.
Since there seem to be a lot of players that do not properly support VFR,
add a CFR option that can be used with "Same as source". The framerate to
use comes from the title and the cfr flag is set in the job.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@3770 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r-- | gtk/src/callbacks.c | 26 | ||||
-rw-r--r-- | gtk/src/ghb.ui | 294 | ||||
-rw-r--r-- | gtk/src/hb-backend.c | 12 | ||||
-rw-r--r-- | gtk/src/internal_defaults.xml | 22 | ||||
-rw-r--r-- | gtk/src/makedeps.py | 3 | ||||
-rw-r--r-- | gtk/src/presets.c | 111 | ||||
-rw-r--r-- | gtk/src/settings.c | 44 |
7 files changed, 353 insertions, 159 deletions
diff --git a/gtk/src/callbacks.c b/gtk/src/callbacks.c index f225ff93a..3bc6c0d41 100644 --- a/gtk/src/callbacks.c +++ b/gtk/src/callbacks.c @@ -1584,6 +1584,28 @@ ptop_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) } G_MODULE_EXPORT void +framerate_changed_cb(GtkWidget *widget, signal_user_data_t *ud) +{ + ghb_widget_to_setting(ud->settings, widget); + + if (ghb_settings_combo_int(ud->settings, "VideoFramerate") != 0) + { + if (!ghb_settings_get_boolean(ud->settings, "VideoFrameratePFR")) + { + ghb_ui_update(ud, "VideoFramerateCFR", ghb_boolean_value(TRUE)); + } + } + if (ghb_settings_combo_int(ud->settings, "VideoFramerate") == 0 && + ghb_settings_get_boolean(ud->settings, "VideoFrameratePFR")) + { + ghb_ui_update(ud, "VideoFramerateVFR", ghb_boolean_value(TRUE)); + } + ghb_check_dependency(ud, widget, NULL); + ghb_clear_presets_selection(ud); + ghb_live_reset(ud); +} + +G_MODULE_EXPORT void setting_widget_changed_cb(GtkWidget *widget, signal_user_data_t *ud) { ghb_widget_to_setting(ud->settings, widget); @@ -2159,7 +2181,7 @@ ghb_cancel_encode(signal_user_data_t *ud, const gchar *extra_msg) NULL); response = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy (dialog); - switch (response) + switch ((int)response) { case 1: ghb_stop_queue(); @@ -2197,7 +2219,7 @@ ghb_cancel_encode2(signal_user_data_t *ud, const gchar *extra_msg) NULL); response = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy (dialog); - switch (response) + switch ((int)response) { case 1: ghb_stop_queue(); diff --git a/gtk/src/ghb.ui b/gtk/src/ghb.ui index 71b66db24..7297f1177 100644 --- a/gtk/src/ghb.ui +++ b/gtk/src/ghb.ui @@ -1751,7 +1751,7 @@ <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="tooltip-text" translatable="yes">Output framerate. 'Same as source' is recomended. If your source video has a variable framerate, 'Same as source' will preserve it.</property> - <signal handler="setting_widget_changed_cb" name="changed"/> + <signal handler="framerate_changed_cb" name="changed"/> </object> </child> </object> @@ -1767,12 +1767,12 @@ </packing> </child> <child> - <object class="GtkCheckButton" id="VideoFrameratePFR"> + <object class="GtkRadioButton" id="VideoFramerateCFR"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Enables variable framerate output with a peak rate determined by the framerate setting</property> - <property name="label" translatable="yes">Peak Framerate (VFR)</property> + <property name="tooltip-text" translatable="yes">Enables constant framerate output.</property> + <property name="label" translatable="yes">Constant Framerate</property> <property name="draw_indicator">True</property> <signal handler="setting_widget_changed_cb" name="toggled"/> </object> @@ -1782,13 +1782,14 @@ </packing> </child> <child> - <object class="GtkCheckButton" id="VideoTwoPass"> + <object class="GtkRadioButton" id="VideoFrameratePFR"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Perform 2 Pass Encoding. 'Bitrate' or 'Target Size' options are prerequisites. During the 1st pass, statistics about the video are collected. Then in the second pass, those statistics are used to make bitrate allocation decisions.</property> - <property name="label" translatable="yes">2-Pass Encoding</property> + <property name="tooltip-text" translatable="yes">Enables variable framerate output with a peak rate determined by the framerate setting. VFR is not compatible with some players.</property> + <property name="label" translatable="yes">Peak Framerate (VFR)</property> <property name="draw_indicator">True</property> + <property name="group">VideoFramerateCFR</property> <signal handler="setting_widget_changed_cb" name="toggled"/> </object> <packing> @@ -1797,22 +1798,15 @@ </packing> </child> <child> - <object class="GtkAlignment" id="alignment13"> + <object class="GtkRadioButton" id="VideoFramerateVFR"> <property name="visible">True</property> + <property name="can_focus">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="left_padding">16</property> - <child> - <object class="GtkCheckButton" id="VideoTurboTwoPass"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">During the 1st pass of a 2 pass encode, use settings that speed things along.</property> - <property name="label" translatable="yes">Turbo First Pass</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal handler="setting_widget_changed_cb" name="toggled"/> - </object> - </child> + <property name="tooltip-text" translatable="yes">Enables variable framerate output. VFR is not compatible with some players.</property> + <property name="label" translatable="yes">Variable Framerate</property> + <property name="draw_indicator">True</property> + <property name="group">VideoFramerateCFR</property> + <signal handler="setting_widget_changed_cb" name="toggled"/> </object> <packing> <property name="expand">False</property> @@ -1833,150 +1827,180 @@ <property name="top_padding">48</property> <property name="right_padding">24</property> <child> - <object class="GtkVBox" id="vbox47"> - <property name="orientation">vertical</property> + <object class="GtkTable" id="table8"> + <property name="n_rows">6</property> + <property name="n_columns">3</property> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <child> - <object class="GtkHBox" id="hbox62"> + <object class="GtkHScale" id="VideoQualitySlider"> <property name="visible">True</property> + <property name="can_focus">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <child> - <object class="GtkRadioButton" id="vquality_type_bitrate"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Set the average bitrate. The instantaneous bitrate can be much higher or lower at any point in time. But the average over a long duration will be the value set here. If you need to limit instantaneous bitrate, look into x264's vbv-bufsize and vbv-maxrate settings.</property> - <property name="label" translatable="yes">Bitrate (kbps): </property> - <property name="draw_indicator">True</property> - <signal handler="setting_widget_changed_cb" name="toggled"/> - </object> - <packing> - <property name="expand">False</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="alignment15"> - <property name="visible">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="xalign">0.11999999731779099</property> - <property name="xscale">0.10000000149011612</property> - <child> - <object class="GtkSpinButton" id="VideoAvgBitrate"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Set the average bitrate. The instantaneous bitrate can be much higher or lower at any point in time. But the average over a long duration will be the value set here. If you need to limit instantaneous bitrate, look into x264 vbv-bufsize and vbv-maxrate.</property> - <property name="adjustment">adjustment3</property> - <signal handler="setting_widget_changed_cb" name="value_changed"/> - </object> - </child> - </object> - <packing> - <property name="position">1</property> - </packing> - </child> + <property name="tooltip-text" translatable="yes">Set the desired quality factor. The encoder targets a certain quality. The scale used by each video encoder is different. + +x264's scale is logarithmic and lower values coorespond to higher quality. So small decreases in value will result in progressively larger increases in the resulting file size. A value of 0 means lossless and will result in a file size that is larger than the original source, unless the source was also lossless. + +FFmpeg's and Theora's scale is more linear. These encoders do not have a lossless mode.</property> + <property name="adjustment">adjustment5</property> + <property name="digits">3</property> + <property name="value_pos">GTK_POS_TOP</property> + <signal handler="vquality_changed_cb" name="value_changed"/> + <signal handler="format_vquality_cb" name="format-value"/> </object> <packing> - <property name="expand">False</property> - <property name="position">0</property> + <property name="left_attach">0</property> + <property name="right_attach">3</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="y_options">GTK_FILL</property> + <property name="x_options">GTK_FILL|GTK_EXPAND</property> </packing> </child> <child> - <object class="GtkHBox" id="hbox56"> + <object class="GtkRadioButton" id="vquality_type_constant"> <property name="visible">True</property> + <property name="can_focus">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <child> - <object class="GtkRadioButton" id="vquality_type_target"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Set the desired final size of the output file. This uses the known duration of the video to calculate the bitrate that will be required to achieve the desired size.</property> - <property name="label" translatable="yes">Target Size (MB):</property> - <property name="draw_indicator">True</property> - <property name="group">vquality_type_bitrate</property> - <signal handler="target_size_changed_cb" name="toggled"/> - </object> - <packing> - <property name="expand">False</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="alignment16"> - <property name="visible">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="xalign">0.11999999731779099</property> - <property name="xscale">0.10000000149011612</property> - <child> - <object class="GtkSpinButton" id="VideoTargetSize"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Set the desired final size of the output file. This uses the known duration of the video to calculate the bitrate that will be required to achieve the desired size.</property> - <property name="adjustment">adjustment4</property> - <signal handler="target_size_changed_cb" name="value_changed"/> - </object> - </child> - </object> - <packing> - <property name="position">1</property> - </packing> - </child> + <property name="tooltip-text" translatable="yes">Set the desired quality factor. The encoder targets a certain quality. The scale used by each video encoder is different. + +x264's scale is logarithmic and lower values coorespond to higher quality. So small decreases in value will result in progressively larger increases in the resulting file size. A value of 0 means lossless and will result in a file size that is larger than the original source, unless the source was also lossless. + +FFmpeg's and Theora's scale is more linear. These encoders do not have a lossless mode.</property> + <property name="label" translatable="yes">Constant Quality:</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal handler="setting_widget_changed_cb" name="toggled"/> </object> <packing> - <property name="expand">False</property> - <property name="position">1</property> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> </packing> </child> <child> - <object class="GtkHBox" id="hbox57"> + <object class="GtkRadioButton" id="vquality_type_bitrate"> <property name="visible">True</property> + <property name="can_focus">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip-text" translatable="yes">Set the average bitrate. The instantaneous bitrate can be much higher or lower at any point in time. But the average over a long duration will be the value set here. If you need to limit instantaneous bitrate, look into x264's vbv-bufsize and vbv-maxrate settings.</property> + <property name="label" translatable="yes">Bitrate (kbps): </property> + <property name="group">vquality_type_constant</property> + <property name="draw_indicator">True</property> + <signal handler="setting_widget_changed_cb" name="toggled"/> + </object> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options">GTK_FILL</property> + <property name="x_options">GTK_FILL</property> + </packing> + </child> + <child> + <object class="GtkSpinButton" id="VideoAvgBitrate"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip-text" translatable="yes">Set the average bitrate. The instantaneous bitrate can be much higher or lower at any point in time. But the average over a long duration will be the value set here. If you need to limit instantaneous bitrate, look into x264 vbv-bufsize and vbv-maxrate.</property> + <property name="adjustment">adjustment3</property> + <signal handler="setting_widget_changed_cb" name="value_changed"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options">GTK_FILL</property> + <property name="x_options"></property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="vquality_type_target"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip-text" translatable="yes">Set the desired final size of the output file. This uses the known duration of the video to calculate the bitrate that will be required to achieve the desired size.</property> + <property name="label" translatable="yes">Target Size (MB):</property> + <property name="draw_indicator">True</property> + <property name="group">vquality_type_constant</property> + <signal handler="target_size_changed_cb" name="toggled"/> + </object> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="y_options">GTK_FILL</property> + <property name="x_options">GTK_FILL</property> + </packing> + </child> + <child> + <object class="GtkSpinButton" id="VideoTargetSize"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip-text" translatable="yes">Set the desired final size of the output file. This uses the known duration of the video to calculate the bitrate that will be required to achieve the desired size.</property> + <property name="adjustment">adjustment4</property> + <signal handler="target_size_changed_cb" name="value_changed"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="y_options">GTK_FILL</property> + <property name="x_options"></property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="VideoTwoPass"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="tooltip-text" translatable="yes">Perform 2 Pass Encoding. 'Bitrate' or 'Target Size' options are prerequisites. During the 1st pass, statistics about the video are collected. Then in the second pass, those statistics are used to make bitrate allocation decisions.</property> + <property name="label" translatable="yes">2-Pass Encoding</property> + <property name="draw_indicator">True</property> + <signal handler="setting_widget_changed_cb" name="toggled"/> + </object> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + <property name="y_options">GTK_FILL</property> + <property name="x_options">GTK_FILL</property> + </packing> + </child> + <child> + <object class="GtkAlignment" id="alignment13"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="left_padding">16</property> <child> - <object class="GtkRadioButton" id="vquality_type_constant"> + <object class="GtkCheckButton" id="VideoTurboTwoPass"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Set the desired quality factor. The encoder targets a certain quality. The scale used by each video encoder is different. - -x264's scale is logarithmic and lower values coorespond to higher quality. So small decreases in value will result in progressively larger increases in the resulting file size. A value of 0 means lossless and will result in a file size that is larger than the original source, unless the source was also lossless. - -FFmpeg's and Theora's scale is more linear. These encoders do not have a lossless mode.</property> - <property name="label" translatable="yes">Constant Quality:</property> + <property name="tooltip-text" translatable="yes">During the 1st pass of a 2 pass encode, use settings that speed things along.</property> + <property name="label" translatable="yes">Turbo First Pass</property> <property name="active">True</property> <property name="draw_indicator">True</property> - <property name="group">vquality_type_target</property> <signal handler="setting_widget_changed_cb" name="toggled"/> </object> - <packing> - <property name="expand">False</property> - </packing> </child> </object> <packing> - <property name="expand">False</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkHScale" id="VideoQualitySlider"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="tooltip-text" translatable="yes">Set the desired quality factor. The encoder targets a certain quality. The scale used by each video encoder is different. - -x264's scale is logarithmic and lower values coorespond to higher quality. So small decreases in value will result in progressively larger increases in the resulting file size. A value of 0 means lossless and will result in a file size that is larger than the original source, unless the source was also lossless. - -FFmpeg's and Theora's scale is more linear. These encoders do not have a lossless mode.</property> - <property name="adjustment">adjustment5</property> - <property name="digits">3</property> - <property name="value_pos">GTK_POS_BOTTOM</property> - <signal handler="vquality_changed_cb" name="value_changed"/> - <signal handler="format_vquality_cb" name="format-value"/> - </object> - <packing> - <property name="expand">False</property> - <property name="position">3</property> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + <property name="y_options">GTK_FILL</property> + <property name="x_options">GTK_FILL</property> </packing> </child> </object> diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c index c5e1cadf1..80297203c 100644 --- a/gtk/src/hb-backend.c +++ b/gtk/src/hb-backend.c @@ -4632,18 +4632,18 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex) { job->vrate = title->rate; job->vrate_base = title->rate_base; - job->cfr = 0; } else { job->vrate = 27000000; job->vrate_base = vrate; - gboolean pfr = ghb_settings_get_boolean(js, "VideoFrameratePFR"); - if (pfr) - job->cfr = 2; - else - job->cfr = 1; } + if (ghb_settings_get_boolean(js, "VideoFrameratePFR")) + job->cfr = 2; + else if (ghb_settings_get_boolean(js, "VideoFramerateCFR")) + job->cfr = 1; + else + job->cfr = 0; const GValue *audio_list; gint count, ii; diff --git a/gtk/src/internal_defaults.xml b/gtk/src/internal_defaults.xml index 568da2fa9..67d786f63 100644 --- a/gtk/src/internal_defaults.xml +++ b/gtk/src/internal_defaults.xml @@ -114,6 +114,12 @@ <string></string> <key>SrtOffset</key> <integer>0</integer> + <key>VideoFramerateCFR</key> + <false /> + <key>VideoFrameratePFR</key> + <false /> + <key>VideoFramerateVFR</key> + <false /> </dict> <key>Preferences</key> <dict> @@ -200,20 +206,20 @@ </dict> <key>XlatPresets</key> <dict> - <key>anamorphic</key> - <true /> <key>autoscale</key> <false /> - <key>par_width</key> - <integer>0</integer> - <key>par_height</key> - <integer>0</integer> <key>vquality_type_bitrate</key> <false /> <key>vquality_type_constant</key> <false /> <key>vquality_type_target</key> <false /> + <key>VideoFramerateCFR</key> + <false /> + <key>VideoFrameratePFR</key> + <false /> + <key>VideoFramerateVFR</key> + <false /> </dict> <key>Presets</key> <dict> @@ -273,8 +279,8 @@ <integer>0</integer> <key>VideoFramerate</key> <string>source</string> - <key>VideoFrameratePFR</key> - <false /> + <key>VideoFramerateMode</key> + <string>vfr</string> <key>VideoGrayScale</key> <false /> <key>Mp4HttpOptimize</key> diff --git a/gtk/src/makedeps.py b/gtk/src/makedeps.py index 121c5654a..2e07eda3e 100644 --- a/gtk/src/makedeps.py +++ b/gtk/src/makedeps.py @@ -25,7 +25,8 @@ dep_map = ( DepEntry("vquality_type_constant", "VideoQualitySlider", "TRUE", False, False), DepEntry("vquality_type_constant", "VideoTwoPass", "TRUE", True, False), DepEntry("vquality_type_constant", "VideoTurboTwoPass", "TRUE", True, False), - DepEntry("VideoFramerate", "VideoFrameratePFR", "source", True, False), + DepEntry("VideoFramerate", "VideoFrameratePFR", "source", True, True), + DepEntry("VideoFramerate", "VideoFramerateVFR", "source", False, True), DepEntry("VideoTwoPass", "VideoTurboTwoPass", "TRUE", False, False), DepEntry("FileFormat", "Mp4LargeFile", "mp4", False, True), DepEntry("FileFormat", "Mp4HttpOptimize", "mp4", False, True), diff --git a/gtk/src/presets.c b/gtk/src/presets.c index db3cd6d0c..17e00346b 100644 --- a/gtk/src/presets.c +++ b/gtk/src/presets.c @@ -2682,8 +2682,81 @@ import_xlat_preset(GValue *dict) ghb_boolean_value_new(TRUE)); } break; } + import_value_xlat(dict); + GValue *mode = ghb_dict_lookup(dict, "VideoFramerateMode"); + if (mode == NULL) + { + GValue *fr = ghb_dict_lookup(dict, "VideoFramerate"); + if (fr) + { + gchar *str; + gboolean pfr = FALSE; + GValue *pfr_val = ghb_dict_lookup(dict, "VideoFrameratePFR"); + if (pfr_val) + { + pfr = ghb_value_boolean(pfr_val); + } + str = ghb_value_string(fr); + if (strcmp(str, "source") == 0) + { + ghb_dict_insert(dict, g_strdup("VideoFramerateCFR"), + ghb_boolean_value_new(FALSE)); + ghb_dict_insert(dict, g_strdup("VideoFramerateVFR"), + ghb_boolean_value_new(TRUE)); + } + else if (!pfr) + { + ghb_dict_insert(dict, g_strdup("VideoFramerateCFR"), + ghb_boolean_value_new(TRUE)); + ghb_dict_insert(dict, g_strdup("VideoFramerateVFR"), + ghb_boolean_value_new(FALSE)); + } + else + { + ghb_dict_insert(dict, g_strdup("VideoFramerateCFR"), + ghb_boolean_value_new(FALSE)); + ghb_dict_insert(dict, g_strdup("VideoFramerateVFR"), + ghb_boolean_value_new(FALSE)); + } + g_free(str); + } + } + else + { + gchar *str; + str = ghb_value_string(mode); + if (strcmp(str, "cfr") == 0) + { + ghb_dict_insert(dict, g_strdup("VideoFramerateCFR"), + ghb_boolean_value_new(TRUE)); + ghb_dict_insert(dict, g_strdup("VideoFrameratePFR"), + ghb_boolean_value_new(FALSE)); + ghb_dict_insert(dict, g_strdup("VideoFramerateVFR"), + ghb_boolean_value_new(FALSE)); + } + else if (strcmp(str, "pfr") == 0) + { + ghb_dict_insert(dict, g_strdup("VideoFramerateCFR"), + ghb_boolean_value_new(FALSE)); + ghb_dict_insert(dict, g_strdup("VideoFrameratePFR"), + ghb_boolean_value_new(TRUE)); + ghb_dict_insert(dict, g_strdup("VideoFramerateVFR"), + ghb_boolean_value_new(FALSE)); + } + else + { + ghb_dict_insert(dict, g_strdup("VideoFramerateCFR"), + ghb_boolean_value_new(FALSE)); + ghb_dict_insert(dict, g_strdup("VideoFrameratePFR"), + ghb_boolean_value_new(FALSE)); + ghb_dict_insert(dict, g_strdup("VideoFramerateVFR"), + ghb_boolean_value_new(TRUE)); + } + g_free(str); + } + gdouble vquality; const GValue *gval; @@ -2787,6 +2860,22 @@ export_xlat_preset(GValue *dict) ghb_int_value_new(2)); } + if (ghb_value_boolean(preset_dict_get_value(dict, "VideoFramerateCFR"))) + { + ghb_dict_insert(dict, g_strdup("VideoFramerateMode"), + ghb_string_value_new("cfr")); + } + else if (ghb_value_boolean(preset_dict_get_value(dict, "VideoFrameratePFR"))) + { + ghb_dict_insert(dict, g_strdup("VideoFramerateMode"), + ghb_string_value_new("pfr")); + } + else + { + ghb_dict_insert(dict, g_strdup("VideoFramerateMode"), + ghb_string_value_new("vfr")); + } + GValue *alist, *adict; gint count, ii; @@ -2806,11 +2895,25 @@ export_xlat_preset(GValue *dict) } } + GValue *internal; + GHashTableIter iter; + gchar *key; + GValue *value; + internal = plist_get_dict(internalPlist, "XlatPresets"); + ghb_dict_iter_init(&iter, internal); + // middle (void*) cast prevents gcc warning "defreferencing type-punned + // pointer will break strict-aliasing rules" + while (g_hash_table_iter_next( + &iter, (gpointer*)(void*)&key, (gpointer*)(void*)&value)) + { + ghb_dict_remove(dict, key); + } + + // remove obsolete keys ghb_dict_remove(dict, "UsesMaxPictureSettings"); - ghb_dict_remove(dict, "autoscale"); - ghb_dict_remove(dict, "vquality_type_target"); - ghb_dict_remove(dict, "vquality_type_bitrate"); - ghb_dict_remove(dict, "vquality_type_constant"); + ghb_dict_remove(dict, "VFR"); + ghb_dict_remove(dict, "VideoFrameratePFR"); + export_value_xlat(dict); } diff --git a/gtk/src/settings.c b/gtk/src/settings.c index 34c649758..afe41803c 100644 --- a/gtk/src/settings.c +++ b/gtk/src/settings.c @@ -222,8 +222,16 @@ ghb_widget_value(GtkWidget *widget) { g_debug("\tradio_button"); gboolean bval; - bval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - value = ghb_boolean_value_new(bval); + bval = gtk_toggle_button_get_inconsistent(GTK_TOGGLE_BUTTON(widget)); + if (bval) + { + value = ghb_boolean_value_new(FALSE); + } + else + { + bval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + value = ghb_boolean_value_new(bval); + } } else if (type == GTK_TYPE_CHECK_BUTTON) { @@ -427,6 +435,26 @@ ghb_widget_boolean(GtkWidget *widget) return bval; } +static void check_radio_consistency(GValue *settings, GtkWidget *widget) +{ + const gchar *key = NULL; + GValue *value; + + if (widget == NULL) return; + if (G_OBJECT_TYPE(widget) == GTK_TYPE_RADIO_BUTTON) + { + // Find corresponding setting + key = ghb_get_setting_key(widget); + if (key == NULL) return; + value = ghb_widget_value(widget); + if (value == NULL) return; + if (ghb_value_boolean(value) == ghb_settings_get_boolean(settings, key)) + { + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(widget), FALSE); + } + } +} + void ghb_widget_to_setting(GValue *settings, GtkWidget *widget) { @@ -441,6 +469,7 @@ ghb_widget_to_setting(GValue *settings, GtkWidget *widget) value = ghb_widget_value(widget); if (value != NULL) { + check_radio_consistency(settings, widget); ghb_settings_take_value(settings, key, value); } else @@ -474,7 +503,16 @@ update_widget(GtkWidget *widget, const GValue *value) else if (type == GTK_TYPE_RADIO_BUTTON) { g_debug("radio button"); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), ival); + int cur_val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + if (cur_val && !ival) + { + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(widget), TRUE); + } + else + { + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(widget), FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), ival); + } } else if (type == GTK_TYPE_CHECK_BUTTON) { |