From d68cb8a25201663f832307990b2a98cc60d8ab14 Mon Sep 17 00:00:00 2001 From: jstebbins Date: Fri, 11 Mar 2011 22:40:30 +0000 Subject: 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 --- gtk/src/ghb.ui | 105 +++++++++++++++++++++++++++++++++--- gtk/src/hb-backend.c | 120 ++++++++++++++++++++++++++++-------------- gtk/src/hb-backend.h | 2 +- gtk/src/internal_defaults.xml | 2 + gtk/src/main.c | 9 ++++ gtk/src/makedeps.py | 4 +- gtk/src/queuehandler.c | 25 ++++----- gtk/src/x264handler.c | 26 +++++++++ 8 files changed, 233 insertions(+), 60 deletions(-) (limited to 'gtk/src') 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 @@ True - False + True HandBrake 500 400 @@ -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. +FFMpeg's and Theora's scale is more linear. These encoders do not have a lossless mode. adjustment5 3 GTK_POS_TOP @@ -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. +FFMpeg's and Theora's scale is more linear. These encoders do not have a lossless mode. Constant Quality: True True @@ -2584,6 +2584,12 @@ For source audio that has a wide dynamic range (very loud and very soft sequence + + vertical + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + vertical True @@ -3474,13 +3480,99 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1 + + True + True + 0 + 0 + + + + + + vertical + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + + + True + 0 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + none + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 6 + 2 + 12 + 2 + + + 40 + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + etched-in + + + True + True + Your selected options will appear here. + You can edit these and add additional options. + GTK_WRAP_CHAR + False + + + + + + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + <small><b>Current FFMpeg MPEG-4 Advanced Option String</b></small> + True + + + + + False + True + 2 + 1 + + + + + True + True + 0 + 1 + + + - + True - H.264 + Advanced 4 @@ -3559,7 +3651,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1 - False + True 1 @@ -3603,6 +3695,7 @@ no-fast-pskip=0:no-dct-decimate=0:cabac=1 + False 2 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 @@ 0.60 VideoTargetSize 700 + lavcOption + x264Option 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, "Turbo: On\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, - "x264 Options: %s\n", x264opts); - g_free(x264opts); + "Advanced Options: %s\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; +} + -- cgit v1.2.3