diff options
author | jstebbins <[email protected]> | 2011-03-11 22:40:30 +0000 |
---|---|---|
committer | jstebbins <[email protected]> | 2011-03-11 22:40:30 +0000 |
commit | d68cb8a25201663f832307990b2a98cc60d8ab14 (patch) | |
tree | 936279196cd07e6d68b19b6a79de61ec1e6acfbe /gtk/src | |
parent | 4aaed20c697c1a7e8fe7e039cf1949a320758286 (diff) |
Add parameter parsing and b-frame support to ffmpeg mpeg-4 encoder
The cli will now accept ':' separated parameters using the '-x' option
for ffmpeg mpeg-4. The linux gui has an entry box on the advanced tab
to add options. The option keys and values are the same as what the
ffmpeg command line allows.
Calculation of DTS timestamps was added to encavcodec.c in order to allow
out of order b-frames. The algorithm is similar to what x264 uses.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@3839 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'gtk/src')
-rw-r--r-- | gtk/src/ghb.ui | 105 | ||||
-rw-r--r-- | gtk/src/hb-backend.c | 120 | ||||
-rw-r--r-- | gtk/src/hb-backend.h | 2 | ||||
-rw-r--r-- | gtk/src/internal_defaults.xml | 2 | ||||
-rw-r--r-- | gtk/src/main.c | 9 | ||||
-rw-r--r-- | gtk/src/makedeps.py | 4 | ||||
-rw-r--r-- | gtk/src/queuehandler.c | 25 | ||||
-rw-r--r-- | gtk/src/x264handler.c | 26 |
8 files changed, 233 insertions, 60 deletions
diff --git a/gtk/src/ghb.ui b/gtk/src/ghb.ui index bbe733628..98675dd05 100644 --- a/gtk/src/ghb.ui +++ b/gtk/src/ghb.ui @@ -531,7 +531,7 @@ <object class="GtkWindow" id="hb_window"> <property name="visible">True</property> - <property name="resizable">False</property> + <property name="resizable">True</property> <property name="title" translatable="yes">HandBrake</property> <property name="default_width">500</property> <property name="default_height">400</property> @@ -1841,7 +1841,7 @@ 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> +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> @@ -1866,7 +1866,7 @@ FFmpeg's and Theora's scale is more linear. These encoders do not have a lossle 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> +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> @@ -2584,6 +2584,12 @@ For source audio that has a wide dynamic range (very loud and very soft sequence </packing> </child> <child> + <object class="GtkHBox" id="advanced_tab"> + <property name="orientation">vertical</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="GtkVBox" id="x264_tab"> <property name="orientation">vertical</property> <property name="visible">True</property> @@ -3475,12 +3481,98 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property> </child> </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="padding">0</property> + <property name="position">0</property> + </packing> + + </child> + <child> + <object class="GtkVBox" id="lavc_mpeg4_tab"> + <property name="orientation">vertical</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="hbox86"> + <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="spacing">2</property> + </object> + <packing> + <property name="expand">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkFrame" id="frame18"> + <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="label_xalign">0</property> + <property name="shadow_type">none</property> + <child> + <object class="GtkAlignment" id="alignment33"> + <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="top_padding">6</property> + <property name="bottom_padding">2</property> + <property name="left_padding">12</property> + <property name="right_padding">2</property> + <child> + <object class="GtkScrolledWindow" id="scrolledwindow7"> + <property name="height_request">40</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">etched-in</property> + <child> + <object class="GtkTextView" id="lavcOption"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="tooltip-text" translatable="yes">Your selected options will appear here. + You can edit these and add additional options.</property> + <property name="wrap_mode">GTK_WRAP_CHAR</property> + <property name="accepts_tab">False</property> + <signal handler="lavc_focus_out_cb" name="focus_out_event"/> + </object> + </child> + </object> + </child> + </object> + </child> + <child type="label"> + <object class="GtkLabel" id="label75"> + <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="label" translatable="yes"><small><b>Current FFMpeg MPEG-4 Advanced Option String</b></small></property> + <property name="use_markup">True</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">2</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="padding">0</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> </packing> </child> <child type="tab"> - <object class="GtkLabel" id="x264_tab_label"> + <object class="GtkLabel" id="advanced_tab_label"> <property name="visible">True</property> - <property name="label" translatable="yes">H.264</property> + <property name="label" translatable="yes">Advanced</property> </object> <packing> <property name="position">4</property> @@ -3559,7 +3651,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property> </object> <packing> - <property name="expand">False</property> + <property name="expand">True</property> <property name="position">1</property> </packing> </child> @@ -3603,6 +3695,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1</property> </child> </object> <packing> + <property name="expand">False</property> <property name="position">2</property> </packing> </child> diff --git a/gtk/src/hb-backend.c b/gtk/src/hb-backend.c index 0f7bba1a9..fbcd4a679 100644 --- a/gtk/src/hb-backend.c +++ b/gtk/src/hb-backend.c @@ -2824,24 +2824,54 @@ init_ui_combo_boxes(GtkBuilder *builder) } } -static const char * turbo_opts = +static const char * turbo_lavc_opts = ""; + +static const char * turbo_x264_opts = "ref=1:subme=2:me=dia:analyse=none:trellis=0:" "no-fast-pskip=0:8x8dct=0"; -// Construct the x264 options string +// Construct the advanced options string // The result is allocated, so someone must free it at some point. gchar* -ghb_build_x264opts_string(GValue *settings) +ghb_build_advanced_opts_string(GValue *settings) { gchar *result; - gchar *opts = ghb_settings_get_string(settings, "x264Option"); - if (opts != NULL) - { - result = opts; - } - else + + gint vcodec = ghb_settings_combo_int(settings, "VideoEncoder"); + + switch (vcodec) { - result = g_strdup(""); + case HB_VCODEC_X264: + { + gchar *opts = ghb_settings_get_string(settings, "x264Option"); + if (opts != NULL) + { + result = opts; + } + else + { + result = g_strdup(""); + } + } break; + + case HB_VCODEC_FFMPEG: + { + gchar *opts = ghb_settings_get_string(settings, "lavcOption"); + if (opts != NULL) + { + result = opts; + } + else + { + result = g_strdup(""); + } + } break; + + case HB_VCODEC_THEORA: + default: + { + result = g_strdup(""); + } break; } return result; } @@ -4369,7 +4399,7 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex) hb_list_t * list; hb_title_t * title; hb_job_t * job; - static gchar *x264opts; + static gchar *advanced_opts; gint sub_id = 0; gboolean tweaks = FALSE; gchar *detel_str = NULL; @@ -4784,17 +4814,17 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex) } } - // TODO: libhb holds onto a reference to the x264opts and is not + // TODO: libhb holds onto a reference to the advanced_opts and is not // finished with it until encoding the job is done. But I can't // find a way to get at the job before it is removed in order to // free up the memory I am allocating here. // The short story is THIS LEAKS. - x264opts = ghb_build_x264opts_string(js); + advanced_opts = ghb_build_advanced_opts_string(js); - if( *x264opts == '\0' ) + if( advanced_opts && *advanced_opts == '\0' ) { - g_free(x264opts); - x264opts = NULL; + g_free(advanced_opts); + advanced_opts = NULL; } if (job->indepth_scan == 1) @@ -4807,7 +4837,7 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex) */ job->pass = -1; job->indepth_scan = 1; - job->x264opts = NULL; + job->advanced_opts = NULL; /* * Add the pre-scan job @@ -4829,48 +4859,60 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex) /* * If turbo options have been selected then append them - * to the x264opts now (size includes one ':' and the '\0') + * to the advanced_opts now (size includes one ':' and the '\0') */ if( ghb_settings_get_boolean(js, "VideoTurboTwoPass") ) { - gchar *tmp_x264opts; + gchar *tmp_advanced_opts; gchar *extra_opts; - gint badapt; - badapt = ghb_lookup_badapt(x264opts); - if (badapt == 2) + if (job->vcodec == HB_VCODEC_X264) { - extra_opts = g_strdup_printf("%s", turbo_opts); + gint badapt; + + badapt = ghb_lookup_badapt(advanced_opts); + if (badapt == 2) + { + extra_opts = g_strdup_printf("%s", turbo_x264_opts); + } + else + { + extra_opts = g_strdup_printf("%s:weightb=0", turbo_x264_opts); + } + } + else if (job->vcodec == HB_VCODEC_FFMPEG) + { + extra_opts = g_strdup_printf("%s", turbo_lavc_opts); } else { - extra_opts = g_strdup_printf("%s:weightb=0", turbo_opts); + extra_opts = g_strdup(""); } - - if ( x264opts ) + + if ( advanced_opts ) { - tmp_x264opts = g_strdup_printf("%s:%s", x264opts, extra_opts); + tmp_advanced_opts = g_strdup_printf("%s:%s", advanced_opts, extra_opts); } else { /* - * No x264opts to modify, but apply the turbo options + * No advanced_opts to modify, but apply the turbo options * anyway as they may be modifying defaults */ - tmp_x264opts = g_strdup_printf("%s", extra_opts); + tmp_advanced_opts = g_strdup_printf("%s", extra_opts); } g_free(extra_opts); - job->x264opts = tmp_x264opts; + job->advanced_opts = tmp_advanced_opts; } else { - job->x264opts = x264opts; + job->advanced_opts = advanced_opts; } job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24); hb_add( h, job ); - //if (job->x264opts != NULL) - // g_free(job->x264opts); + //if (job->advanced_opts != NULL) + // g_free(job->advanced_opts); job->pass = 2; /* @@ -4880,21 +4922,21 @@ add_job(hb_handle_t *h, GValue *js, gint unique_id, gint titleindex) * attribute of the job). */ job->indepth_scan = 0; - job->x264opts = x264opts; + job->advanced_opts = advanced_opts; job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24); hb_add( h, job ); - //if (job->x264opts != NULL) - // g_free(job->x264opts); + //if (job->advanced_opts != NULL) + // g_free(job->advanced_opts); } else { - job->x264opts = x264opts; + job->advanced_opts = advanced_opts; job->indepth_scan = 0; job->pass = 0; job->sequence_id = (unique_id & 0xFFFFFF) | (sub_id++ << 24); hb_add( h, job ); - //if (job->x264opts != NULL) - // g_free(job->x264opts); + //if (job->advanced_opts != NULL) + // g_free(job->advanced_opts); } // clean up audio list diff --git a/gtk/src/hb-backend.h b/gtk/src/hb-backend.h index 8109fde33..3056422aa 100644 --- a/gtk/src/hb-backend.h +++ b/gtk/src/hb-backend.h @@ -152,7 +152,7 @@ gint ghb_find_subtitle_track( gint ghb_pick_subtitle_track(signal_user_data_t *ud); gint ghb_find_cc_track(gint titleindex); gint ghb_longest_title(void); -gchar* ghb_build_x264opts_string(GValue *settings); +gchar* ghb_build_advanced_opts_string(GValue *settings); GdkPixbuf* ghb_get_preview_image( gint titleindex, gint index, signal_user_data_t *ud, gint *width, gint *height); diff --git a/gtk/src/internal_defaults.xml b/gtk/src/internal_defaults.xml index 3041bc342..51fa9bc18 100644 --- a/gtk/src/internal_defaults.xml +++ b/gtk/src/internal_defaults.xml @@ -349,6 +349,8 @@ <real>0.60</real> <key>VideoTargetSize</key> <integer>700</integer> + <key>lavcOption</key> + <string></string> <key>x264Option</key> <string></string> </dict> diff --git a/gtk/src/main.c b/gtk/src/main.c index 72617eb2b..6c6b268ce 100644 --- a/gtk/src/main.c +++ b/gtk/src/main.c @@ -962,6 +962,15 @@ main (int argc, char *argv[]) widget = GHB_WIDGET(ud->builder, "subtitle_table"); gtk_widget_set_size_request(widget, -1, height); + widget = GHB_WIDGET (ud->builder, "hb_window"); + + GdkGeometry geo = { + -1, -1, 1024, 768, 200, 200, 10, 10, 0, 0, GDK_GRAVITY_NORTH_WEST + }; + GdkWindowHints geo_mask; + geo_mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE | GDK_HINT_BASE_SIZE; + gtk_window_set_geometry_hints( GTK_WINDOW(widget), widget, &geo, geo_mask); + // Everything should be go-to-go. Lets rock! gtk_main (); diff --git a/gtk/src/makedeps.py b/gtk/src/makedeps.py index 3950acc44..fd8db094a 100644 --- a/gtk/src/makedeps.py +++ b/gtk/src/makedeps.py @@ -46,8 +46,8 @@ dep_map = ( DepEntry("PictureAutoCrop", "PictureBottomCrop", "FALSE", False, False), DepEntry("PictureAutoCrop", "PictureLeftCrop", "FALSE", False, False), DepEntry("PictureAutoCrop", "PictureRightCrop", "FALSE", False, False), - DepEntry("VideoEncoder", "x264_tab", "x264", False, False), - DepEntry("VideoEncoder", "x264_tab_label", "x264", False, False), + DepEntry("VideoEncoder", "x264_tab", "x264", False, True), + DepEntry("VideoEncoder", "lavc_mpeg4_tab", "ffmpeg", False, True), DepEntry("VideoEncoder", "Mp4iPodCompatible", "x264", False, False), DepEntry("AudioEncoderActual", "AudioBitrate", "ac3pass|dtspass", True, False), DepEntry("AudioEncoderActual", "AudioSamplerate", "ac3pass|dtspass", True, False), diff --git a/gtk/src/queuehandler.c b/gtk/src/queuehandler.c index 69efbd8ca..58def99c2 100644 --- a/gtk/src/queuehandler.c +++ b/gtk/src/queuehandler.c @@ -259,14 +259,14 @@ add_to_queue_list(signal_user_data_t *ud, GValue *settings, GtkTreeIter *piter) vqvalue = ghb_settings_get_double(settings, "VideoQualitySlider"); vq_desc = "Constant Quality:"; vqstr = g_strdup_printf("%d", (gint)vqvalue); - if (strcmp(vcodec_abbr, "x264") == 0) - { - vq_units = "(RF)"; - } - else - { - vq_units = "(QP)"; - } + if (strcmp(vcodec_abbr, "x264") == 0) + { + vq_units = "(RF)"; + } + else + { + vq_units = "(QP)"; + } } fps = ghb_settings_get_string(settings, "VideoFramerate"); if (strcmp("source", fps) == 0) @@ -385,12 +385,13 @@ add_to_queue_list(signal_user_data_t *ud, GValue *settings, GtkTreeIter *piter) { g_string_append_printf(str, "<b>Turbo:</b> <small>On</small>\n"); } - if (strcmp(vcodec_abbr, "x264") == 0) + if (strcmp(vcodec_abbr, "x264") == 0 || + strcmp(vcodec_abbr, "ffmpeg") == 0) { - gchar *x264opts = ghb_build_x264opts_string(settings); + gchar *opts = ghb_build_advanced_opts_string(settings); g_string_append_printf(str, - "<b>x264 Options:</b> <small>%s</small>\n", x264opts); - g_free(x264opts); + "<b>Advanced Options:</b> <small>%s</small>\n", opts); + g_free(opts); } // Add the audios gint count, ii; diff --git a/gtk/src/x264handler.c b/gtk/src/x264handler.c index d9f1fd7a0..06d2eb909 100644 --- a/gtk/src/x264handler.c +++ b/gtk/src/x264handler.c @@ -1064,3 +1064,29 @@ sanitize_x264opts(signal_user_data_t *ud, const gchar *options) return result; } +G_MODULE_EXPORT gboolean +lavc_focus_out_cb(GtkWidget *widget, GdkEventFocus *event, + signal_user_data_t *ud) +{ + ghb_widget_to_setting(ud->settings, widget); + +#if 0 + gchar *options, *sopts; + **************************************************************** + When there are lavc widget in the future, this will be populated + **************************************************************** + options = ghb_settings_get_string(ud->settings, "x264Option"); + sopts = sanitize_x264opts(ud, options); + ignore_options_update = TRUE; + if (sopts != NULL && strcmp(sopts, options) != 0) + { + ghb_ui_update(ud, "x264Option", ghb_string_value(sopts)); + ghb_x264_parse_options(ud, sopts); + } + g_free(options); + g_free(sopts); + ignore_options_update = FALSE; +#endif + return FALSE; +} + |