diff options
-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 | ||||
-rw-r--r-- | libhb/common.h | 6 | ||||
-rw-r--r-- | libhb/decavcodec.c | 3 | ||||
-rw-r--r-- | libhb/encavcodec.c | 339 | ||||
-rw-r--r-- | libhb/encx264.c | 8 | ||||
-rw-r--r-- | libhb/hbffmpeg.h | 1 | ||||
-rw-r--r-- | libhb/muxmkv.c | 5 | ||||
-rw-r--r-- | libhb/muxmp4.c | 12 | ||||
-rw-r--r-- | libhb/work.c | 4 | ||||
-rw-r--r-- | macosx/Controller.m | 20 | ||||
-rw-r--r-- | macosx/HBPreviewController.m | 6 | ||||
-rw-r--r-- | macosx/InstantHandBrake/ExpressController.m | 4 | ||||
-rwxr-xr-x | scripts/manicure.rb | 12 | ||||
-rw-r--r-- | test/test.c | 98 |
21 files changed, 623 insertions, 188 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; +} + diff --git a/libhb/common.h b/libhb/common.h index 031b8b642..fc7b13916 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -220,8 +220,8 @@ struct hb_job_s vrate, vrate_base: output framerate is vrate / vrate_base cfr: 0 (vfr), 1 (cfr), 2 (pfr) [see render.c] pass: 0, 1 or 2 (or -1 for scan) - x264opts: string of extra x264 options - areBframes: boolean to note if b-frames are included in x264opts */ + advanced_opts: string of extra advanced encoder options + areBframes: boolean to note if b-frames are included in advanced_opts */ #define HB_VCODEC_MASK 0x0000FF #define HB_VCODEC_FFMPEG 0x000001 #define HB_VCODEC_X264 0x000002 @@ -237,7 +237,7 @@ struct hb_job_s int vfr; int cfr; int pass; - char *x264opts; + char *advanced_opts; int areBframes; int color_matrix; diff --git a/libhb/decavcodec.c b/libhb/decavcodec.c index df5575d98..5fe5f8e81 100644 --- a/libhb/decavcodec.c +++ b/libhb/decavcodec.c @@ -1684,8 +1684,7 @@ static int decavcodecaiWork( hb_work_object_t *w, hb_buffer_t **buf_in, // if the packet has a timestamp use it if we don't have a timestamp yet // or if there's been a timing discontinuity of more than 100ms. - if ( in->start >= 0 && - ( pv->pts_next < 0 || ( in->start - pv->pts_next ) > 90*100 ) ) + if ( in->start >= 0 ) { pv->pts_next = in->start; } diff --git a/libhb/encavcodec.c b/libhb/encavcodec.c index 07fc748a8..fd95f64b1 100644 --- a/libhb/encavcodec.c +++ b/libhb/encavcodec.c @@ -7,11 +7,37 @@ #include "hb.h" #include "hbffmpeg.h" +/* + * The frame info struct remembers information about each frame across calls + * to avcodec_encode_video. Since frames are uniquely identified by their + * frame number, we use this as an index. + * + * The size of the array is chosen so that two frames can't use the same + * slot during the encoder's max frame delay (set by the standard as 16 + * frames) and so that, up to some minimum frame rate, frames are guaranteed + * to map to * different slots. + */ +#define FRAME_INFO_SIZE 32 +#define FRAME_INFO_MASK (FRAME_INFO_SIZE - 1) + struct hb_work_private_s { hb_job_t * job; AVCodecContext * context; FILE * file; + + int frameno_in; + int frameno_out; + hb_buffer_t * delay_head; + hb_buffer_t * delay_tail; + + int64_t dts_delay; + + struct { + int64_t start; + int64_t stop; + int64_t renderOffset; + } frame_info[FRAME_INFO_SIZE]; }; int encavcodecInit( hb_work_object_t *, hb_job_t * ); @@ -44,39 +70,11 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) hb_log( "hb_work_encavcodec_init: avcodec_find_encoder " "failed" ); } - context = avcodec_alloc_context(); - if( job->vquality < 0.0 ) - { - /* Rate control */ - context->bit_rate = 1000 * job->vbitrate; - context->bit_rate_tolerance = 10 * context->bit_rate; - } - else - { - /* Constant quantizer */ - // These settings produce better image quality than - // what was previously used - context->flags |= CODEC_FLAG_QSCALE; - if (job->vquality < 1.0) - { - float vquality; - vquality = 31 - job->vquality * 31; - // A value of 0 has undefined behavior - // and ffmpeg qp has integral increments - if (vquality < 1.0) - vquality = 1.0; - context->global_quality = FF_QP2LAMBDA * vquality + 0.5; - } - else - { - context->global_quality = FF_QP2LAMBDA * job->vquality + 0.5; - } - context->mb_decision = 1; - hb_log( "encavcodec: encoding at constant quantizer %d", - context->global_quality ); - } - context->width = job->width; - context->height = job->height; + context = avcodec_alloc_context3( codec ); + + // Set things in context that we will allow the user to + // override with advanced settings. + context->thread_count = ( hb_get_cpu_count() * 3 / 2 ); if( job->pass == 2 ) { @@ -89,6 +87,13 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) rate_num = job->vrate_base; rate_den = job->vrate; } + + // If the rate_den is 27000000, 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 rate_num. if (rate_den == 27000000) { int ii; @@ -114,6 +119,92 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) } context->time_base = (AVRational) { rate_num, rate_den }; context->gop_size = 10 * (int)( (double)job->vrate / (double)job->vrate_base + 0.5 ); + + /* + This section passes the string advanced_opts to avutil for parsing + into an AVCodecContext. + + The string is set up like this: + option1=value1:option2=value2 + + So, you have to iterate through based on the colons, and then put + the left side of the equals sign in "name" and the right side into + "value." Then you hand those strings off to avutil for interpretation. + */ + if( job->advanced_opts != NULL && *job->advanced_opts != '\0' ) + { + char *opts, *opts_start; + + opts = opts_start = strdup(job->advanced_opts); + + if( opts_start ) + { + while( *opts ) + { + char *name = opts; + char *value; + int ret; + + opts += strcspn( opts, ":" ); + if( *opts ) + { + *opts = 0; + opts++; + } + + value = strchr( name, '=' ); + if( value ) + { + *value = 0; + value++; + } + + /* Here's where the strings are passed to avutil for parsing. */ + ret = av_set_string3( context, name, value, 1, NULL ); + + /* Let avutil sanity check the options for us*/ + if( ret == AVERROR(ENOENT) ) + hb_log( "avcodec options: Unknown option %s", name ); + if( ret == AVERROR(EINVAL) ) + hb_log( "avcodec options: Bad argument %s=%s", name, value ? value : "(null)" ); + } + } + free(opts_start); + } + + // Now set the things in context that we don't want to allow + // the user to override. + if( job->vquality < 0.0 ) + { + /* Rate control */ + context->bit_rate = 1000 * job->vbitrate; + context->bit_rate_tolerance = 10 * context->bit_rate; + } + else + { + /* Constant quantizer */ + // These settings produce better image quality than + // what was previously used + context->flags |= CODEC_FLAG_QSCALE; + if (job->vquality < 1.0) + { + float vquality; + vquality = 31 - job->vquality * 31; + // A value of 0 has undefined behavior + // and ffmpeg qp has integral increments + if (vquality < 1.0) + vquality = 1.0; + context->global_quality = FF_QP2LAMBDA * vquality + 0.5; + } + else + { + context->global_quality = FF_QP2LAMBDA * job->vquality + 0.5; + } + hb_log( "encavcodec: encoding at constant quantizer %d", + context->global_quality ); + } + context->width = job->width; + context->height = job->height; context->pix_fmt = PIX_FMT_YUV420P; if( job->anamorphic.mode ) @@ -170,17 +261,15 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) } pv->context = context; + if ( context->has_b_frames ) + { + job->areBframes = 1; + } if( ( job->mux & HB_MUX_MP4 ) && job->pass != 1 ) { -#if 0 - /* Hem hem */ - w->config->mpeg4.length = 15; - memcpy( w->config->mpeg4.bytes, context->extradata + 15, 15 ); -#else w->config->mpeg4.length = context->extradata_size; memcpy( w->config->mpeg4.bytes, context->extradata, context->extradata_size ); -#endif } return 0; @@ -209,6 +298,109 @@ void encavcodecClose( hb_work_object_t * w ) w->private_data = NULL; } +/* + * see comments in definition of 'frame_info' in pv struct for description + * of what these routines are doing. + */ +static void save_frame_info( hb_work_private_t * pv, hb_buffer_t * in ) +{ + int i = pv->frameno_in & FRAME_INFO_MASK; + pv->frame_info[i].start = in->start; + pv->frame_info[i].stop = in->stop; +} + +static int64_t get_frame_start( hb_work_private_t * pv, int64_t frameno ) +{ + int i = frameno & FRAME_INFO_MASK; + return pv->frame_info[i].start; +} + +static int64_t get_frame_stop( hb_work_private_t * pv, int64_t frameno ) +{ + int i = frameno & FRAME_INFO_MASK; + return pv->frame_info[i].stop; +} + +static void compute_dts_offset( hb_work_private_t * pv, hb_buffer_t * buf ) +{ + if ( pv->job->areBframes ) + { + if ( ( pv->frameno_in - 1 ) == pv->job->areBframes ) + { + pv->dts_delay = buf->start; + pv->job->config.h264.init_delay = pv->dts_delay; + } + } +} + +// Generate DTS by rearranging PTS in this sequence: +// pts0 - delay, pts1 - delay, pts2 - delay, pts1, pts2, pts3... +// +// Where pts0 - ptsN are in decoded monotonically increasing presentation +// order and delay == pts1 (1 being the number of frames the decoder must +// delay before it has suffecient information to decode). The number of +// frames to delay is set by job->areBframes, so it is configurable. +// This guarantees that DTS <= PTS for any frame. +// +// This is similar to how x264 generates DTS +static hb_buffer_t * process_delay_list( hb_work_private_t * pv, hb_buffer_t * buf ) +{ + if ( pv->job->areBframes ) + { + // Has dts_delay been set yet? + if ( pv->frameno_in <= pv->job->areBframes ) + { + // dts_delay not yet set. queue up buffers till it is set. + if ( pv->delay_tail == NULL ) + { + pv->delay_head = pv->delay_tail = buf; + } + else + { + pv->delay_tail->next = buf; + pv->delay_tail = buf; + } + return NULL; + } + + // We have dts_delay. Apply it to any queued buffers renderOffset + // and return all queued buffers. + if ( pv->delay_tail == NULL && buf != NULL ) + { + pv->frameno_out++; + // Use the cached frame info to get the start time of Nth frame + // Note that start Nth frame != start time this buffer since the + // output buffers have rearranged start times. + int64_t start = get_frame_start( pv, pv->frameno_out ); + buf->renderOffset = start - pv->dts_delay; + return buf; + } + else + { + pv->delay_tail->next = buf; + buf = pv->delay_head; + while ( buf ) + { + pv->frameno_out++; + // Use the cached frame info to get the start time of Nth frame + // Note that start Nth frame != start time this buffer since the + // output buffers have rearranged start times. + int64_t start = get_frame_start( pv, pv->frameno_out ); + buf->renderOffset = start - pv->dts_delay; + } + buf = pv->delay_head; + pv->delay_head = pv->delay_tail = NULL; + return buf; + } + } + else if ( buf ) + { + buf->renderOffset = buf->start - pv->dts_delay; + return buf; + } + return NULL; +} + /*********************************************************************** * Work *********************************************************************** @@ -241,15 +433,78 @@ int encavcodecWork( hb_work_object_t * w, hb_buffer_t ** buf_in, // doesn't do the trick. It must be set in the AVFrame. frame->quality = pv->context->global_quality; + // Bizarro ffmpeg appears to require the input AVFrame.pts to be + // set to a frame number. Setting it to an actual pts causes + // jerky video. + // frame->pts = in->start; + frame->pts = ++pv->frameno_in; + + // Remember info about this frame that we need to pass across + // the avcodec_encode_video call (since it reorders frames). + save_frame_info( pv, in ); + compute_dts_offset( pv, in ); + if ( pv->context->codec ) { /* Should be way too large */ buf = hb_video_buffer_init( job->width, job->height ); buf->size = avcodec_encode_video( pv->context, buf->data, buf->alloc, frame ); - buf->start = in->start; - buf->stop = in->stop; - buf->frametype = pv->context->coded_frame->key_frame ? HB_FRAME_KEY : HB_FRAME_REF; + if ( buf->size <= 0 ) + { + hb_buffer_close( &buf ); + } + else + { + int64_t frameno = pv->context->coded_frame->pts; + buf->start = get_frame_start( pv, frameno ); + buf->stop = get_frame_stop( pv, frameno ); + switch ( pv->context->coded_frame->pict_type ) + { + case FF_P_TYPE: + { + buf->frametype = HB_FRAME_P; + } break; + + case FF_B_TYPE: + { + buf->frametype = HB_FRAME_B; + } break; + + case FF_S_TYPE: + { + buf->frametype = HB_FRAME_P; + } break; + + case FF_SP_TYPE: + { + buf->frametype = HB_FRAME_P; + } break; + + case FF_BI_TYPE: + case FF_SI_TYPE: + case FF_I_TYPE: + { + if ( pv->context->coded_frame->key_frame ) + { + buf->frametype = HB_FRAME_IDR; + } + else + { + buf->frametype = HB_FRAME_I; + } + } break; + + default: + { + if ( pv->context->coded_frame->key_frame ) + buf->frametype = HB_FRAME_KEY; + else + buf->frametype = HB_FRAME_REF; + } break; + } + buf = process_delay_list( pv, buf ); + } } else { diff --git a/libhb/encx264.c b/libhb/encx264.c index 2c64321ba..67ea45b1a 100644 --- a/libhb/encx264.c +++ b/libhb/encx264.c @@ -133,7 +133,7 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) param.i_log_level = X264_LOG_INFO; /* - This section passes the string x264opts to libx264 for parsing into + This section passes the string advanced_opts to libx264 for parsing into parameter names and values. The string is set up like this: @@ -147,11 +147,11 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) Merritt implemented in the Mplayer/Mencoder project. */ - if( job->x264opts != NULL && *job->x264opts != '\0' ) + if( job->advanced_opts != NULL && *job->advanced_opts != '\0' ) { char *x264opts, *x264opts_start; - x264opts = x264opts_start = strdup(job->x264opts); + x264opts = x264opts_start = strdup(job->advanced_opts); while( x264opts_start && *x264opts ) { @@ -176,7 +176,7 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) /* Here's where the strings are passed to libx264 for parsing. */ ret = x264_param_parse( ¶m, name, value ); - /* Let x264 sanity check the options for us*/ + /* Let x264 sanity check the options for us*/ if( ret == X264_PARAM_BAD_NAME ) hb_log( "x264 options: Unknown suboption %s", name ); if( ret == X264_PARAM_BAD_VALUE ) diff --git a/libhb/hbffmpeg.h b/libhb/hbffmpeg.h index 097fae250..205bd0f64 100644 --- a/libhb/hbffmpeg.h +++ b/libhb/hbffmpeg.h @@ -2,6 +2,7 @@ Homepage: <http://handbrake.fr/>. It may be used under the terms of the GNU General Public License. */ +#include "libavcodec/opt.h" #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libswscale/swscale.h" diff --git a/libhb/muxmkv.c b/libhb/muxmkv.c index f169e3de1..63f3e94cd 100644 --- a/libhb/muxmkv.c +++ b/libhb/muxmkv.c @@ -107,6 +107,8 @@ static int MKVInit( hb_mux_object_t * m ) track->codecID = MK_VCODEC_MP4ASP; track->codecPrivate = job->config.mpeg4.bytes; track->codecPrivateSize = job->config.mpeg4.length; + if (job->areBframes) + track->minCache = 1; break; case HB_VCODEC_THEORA: { @@ -448,7 +450,8 @@ static int MKVMux( hb_mux_object_t * m, hb_mux_data_t * mux_data, } mk_addFrameData(m->file, mux_data->track, buf->data, buf->size); mk_setFrameFlags(m->file, mux_data->track, timecode, - ((job->vcodec == HB_VCODEC_X264 && + (((job->vcodec == HB_VCODEC_X264 || + job->vcodec == HB_VCODEC_FFMPEG) && mux_data == job->mux_data) ? (buf->frametype == HB_FRAME_IDR) : ((buf->frametype & HB_FRAME_KEY) != 0)), 0 ); diff --git a/libhb/muxmp4.c b/libhb/muxmp4.c index 7cd4e0fcf..9387d6499 100644 --- a/libhb/muxmp4.c +++ b/libhb/muxmp4.c @@ -886,7 +886,8 @@ static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data, { /* Video */ - if( job->vcodec == HB_VCODEC_X264 ) + if( job->vcodec == HB_VCODEC_X264 || + job->vcodec == HB_VCODEC_FFMPEG ) { if ( buf && buf->start < buf->renderOffset ) { @@ -905,7 +906,8 @@ static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data, if ( !buf ) return 0; - if( job->vcodec == HB_VCODEC_X264 ) + if( job->vcodec == HB_VCODEC_X264 || + job->vcodec == HB_VCODEC_FFMPEG ) { // x264 supplies us with DTS, so offset is PTS - DTS offset = buf->start - buf->renderOffset; @@ -942,7 +944,8 @@ static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data, } } - if( job->vcodec == HB_VCODEC_X264 ) + if( job->vcodec == HB_VCODEC_X264 || + job->vcodec == HB_VCODEC_FFMPEG ) { // x264 supplies us with DTS if ( m->delay_buf ) @@ -1014,7 +1017,8 @@ static int MP4Mux( hb_mux_object_t * m, hb_mux_data_t * mux_data, } /* Here's where the sample actually gets muxed. */ - if( job->vcodec == HB_VCODEC_X264 && mux_data == job->mux_data ) + if( ( job->vcodec == HB_VCODEC_X264 || job->vcodec == HB_VCODEC_FFMPEG ) + && mux_data == job->mux_data ) { /* Compute dependency flags. * diff --git a/libhb/work.c b/libhb/work.c index a5f0e7418..39d926d3c 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -270,8 +270,8 @@ void hb_display_job_info( hb_job_t * job ) case HB_VCODEC_X264: hb_log( " + encoder: x264" ); - if( job->x264opts != NULL && *job->x264opts != '\0' ) - hb_log( " + options: %s", job->x264opts); + if( job->advanced_opts != NULL && *job->advanced_opts != '\0' ) + hb_log( " + options: %s", job->advanced_opts); break; case HB_VCODEC_THEORA: diff --git a/macosx/Controller.m b/macosx/Controller.m index 8d458b065..4bdc32895 100644 --- a/macosx/Controller.m +++ b/macosx/Controller.m @@ -2625,9 +2625,9 @@ fWorkingCount = 0; * which will determine which subtitles to enable, if any. */ job->pass = -1; - x264opts_tmp = job->x264opts; + x264opts_tmp = job->advanced_opts; - job->x264opts = NULL; + job->advanced_opts = NULL; job->indepth_scan = 1; @@ -2636,7 +2636,7 @@ fWorkingCount = 0; * Add the pre-scan job */ hb_add( fQueueEncodeLibhb, job ); - job->x264opts = x264opts_tmp; + job->advanced_opts = x264opts_tmp; } @@ -2652,8 +2652,8 @@ fWorkingCount = 0; job->pass = 2; - job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */ - strcpy(job->x264opts, [[queueToApply objectForKey:@"x264Option"] UTF8String]); + job->advanced_opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */ + strcpy(job->advanced_opts, [[queueToApply objectForKey:@"x264Option"] UTF8String]); hb_add( fQueueEncodeLibhb, job ); @@ -3026,9 +3026,9 @@ fWorkingCount = 0; /* Below Sends x264 options to the core library if x264 is selected*/ /* Lets use this as per Nyx, Thanks Nyx!*/ - job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */ + job->advanced_opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */ /* For previews we ignore the turbo option for the first pass of two since we only use 1 pass */ - strcpy(job->x264opts, [[fAdvancedOptions optionsString] UTF8String]); + strcpy(job->advanced_opts, [[fAdvancedOptions optionsString] UTF8String]); } @@ -3479,7 +3479,7 @@ bool one_burned = FALSE; /* Below Sends x264 options to the core library if x264 is selected*/ /* Lets use this as per Nyx, Thanks Nyx!*/ - job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */ + job->advanced_opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */ /* Turbo first pass if two pass and Turbo First pass is selected */ if( [[queueToApply objectForKey:@"VideoTwoPass"] intValue] == 1 && [[queueToApply objectForKey:@"VideoTurboTwoPass"] intValue] == 1 ) { @@ -3488,11 +3488,11 @@ bool one_burned = FALSE; /* append the "Turbo" string variable to the existing opts string. Note: the "Turbo" string must be appended, not prepended to work properly*/ NSString *firstPassOptStringCombined = [[queueToApply objectForKey:@"x264Option"] stringByAppendingString:firstPassOptStringTurbo]; - strcpy(job->x264opts, [firstPassOptStringCombined UTF8String]); + strcpy(job->advanced_opts, [firstPassOptStringCombined UTF8String]); } else { - strcpy(job->x264opts, [[queueToApply objectForKey:@"x264Option"] UTF8String]); + strcpy(job->advanced_opts, [[queueToApply objectForKey:@"x264Option"] UTF8String]); } } diff --git a/macosx/HBPreviewController.m b/macosx/HBPreviewController.m index a4d8b8455..a674c58b5 100644 --- a/macosx/HBPreviewController.m +++ b/macosx/HBPreviewController.m @@ -893,15 +893,15 @@ * which will determine which subtitles to enable, if any. */ job->pass = -1; - x264opts_tmp = job->x264opts; + x264opts_tmp = job->advanced_opts; - job->x264opts = NULL; + job->advanced_opts = NULL; job->indepth_scan = 1; /* * Add the pre-scan job */ hb_add( fPreviewLibhb, job ); - job->x264opts = x264opts_tmp; + job->advanced_opts = x264opts_tmp; } /* Go ahead and perform the actual encoding preview scan */ job->indepth_scan = 0; diff --git a/macosx/InstantHandBrake/ExpressController.m b/macosx/InstantHandBrake/ExpressController.m index 37ab8b0ec..912df1ffa 100644 --- a/macosx/InstantHandBrake/ExpressController.m +++ b/macosx/InstantHandBrake/ExpressController.m @@ -387,8 +387,8 @@ job->mux = [currentPreset muxer]; job->vcodec = [currentPreset videoCodec]; - job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */ - strcpy(job->x264opts, [[currentPreset videoCodecOptions] UTF8String]); + job->advanced_opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */ + strcpy(job->advanced_opts, [[currentPreset videoCodecOptions] UTF8String]); job->chapter_markers = 1; job->vquality = -1.0; diff --git a/scripts/manicure.rb b/scripts/manicure.rb index f458aec1d..5ca5b8b26 100755 --- a/scripts/manicure.rb +++ b/scripts/manicure.rb @@ -483,7 +483,7 @@ class Display if hash["VideoTwoPass"] == 1 then commandString << " -2" end if hash["VideoTurboTwoPass"] == 1 then commandString << " -T" end - #x264 Options + #Advanced Options if hash["x264Option"] != "" commandString << " -x " commandString << hash["x264Option"] @@ -731,7 +731,7 @@ class Display if hash["VideoTwoPass"] == 1 then commandString << " -2" end if hash["VideoTurboTwoPass"] == 1 then commandString << " -T" end - #x264 Options + #Advanced Options if hash["x264Option"] != "" commandString << " -x " commandString << hash["x264Option"] @@ -938,11 +938,11 @@ class Display end end - #x264 Options + #Advanced Options if hash["x264Option"] != "" - commandString << "if( !x264opts )\n " + commandString << "if( !advanced_opts )\n " commandString << "{\n " - commandString << " x264opts = strdup(\"" + commandString << " advanced_opts = strdup(\"" commandString << hash["x264Option"] << "\");\n " commandString << "}\n " end @@ -1256,7 +1256,7 @@ class Display if hash["VideoTwoPass"] == 1 then commandString << " -2" end if hash["VideoTurboTwoPass"] == 1 then commandString << " -T" end - #x264 Options + #Advanced Options if hash["x264Option"] != "" commandString << " -x " commandString << hash["x264Option"] diff --git a/test/test.c b/test/test.c index 3529ef2cb..e957c7cd7 100644 --- a/test/test.c +++ b/test/test.c @@ -108,8 +108,8 @@ static int chapter_start = 0; static int chapter_end = 0; static int chapter_markers = 0; static char * marker_file = NULL; -static char *x264opts = NULL; -static char *x264opts2 = NULL; +static char *advanced_opts = NULL; +static char *advanced_opts2 = NULL; static int maxHeight = 0; static int maxWidth = 0; static int turbo_opts_enabled = 0; @@ -352,8 +352,8 @@ int main( int argc, char ** argv ) if( acodecs ) free( acodecs ); if( anames ) free( anames ); if (native_language ) free (native_language ); - if( x264opts ) free (x264opts ); - if( x264opts2 ) free (x264opts2 ); + if( advanced_opts ) free (advanced_opts ); + if( advanced_opts2 ) free (advanced_opts2 ); if (preset_name) free (preset_name); if( stop_at_string ) free( stop_at_string ); if( start_at_string ) free( start_at_string ); @@ -638,9 +638,9 @@ static int HandleEvents( hb_handle_t * h ) dynamic_range_compression = strdup("0.0,0.0"); } maxWidth = 720; - if( !x264opts ) + if( !advanced_opts ) { - x264opts = strdup("cabac=0:ref=2:me=umh:bframes=0:weightp=0:8x8dct=0:trellis=0:subme=6"); + advanced_opts = strdup("cabac=0:ref=2:me=umh:bframes=0:weightp=0:8x8dct=0:trellis=0:subme=6"); } if( !anamorphic_mode ) { @@ -684,9 +684,9 @@ static int HandleEvents( hb_handle_t * h ) dynamic_range_compression = strdup("0.0"); } maxWidth = 320; - if( !x264opts ) + if( !advanced_opts ) { - x264opts = strdup("level=30:bframes=0:weightp=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:subme=6:8x8dct=0:trellis=0"); + advanced_opts = strdup("level=30:bframes=0:weightp=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:subme=6:8x8dct=0:trellis=0"); } job->chapter_markers = 1; @@ -725,9 +725,9 @@ static int HandleEvents( hb_handle_t * h ) dynamic_range_compression = strdup("0.0"); } maxWidth = 480; - if( !x264opts ) + if( !advanced_opts ) { - x264opts = strdup("cabac=0:ref=2:me=umh:bframes=0:weightp=0:subme=6:8x8dct=0:trellis=0"); + advanced_opts = strdup("cabac=0:ref=2:me=umh:bframes=0:weightp=0:subme=6:8x8dct=0:trellis=0"); } job->chapter_markers = 1; @@ -855,9 +855,9 @@ static int HandleEvents( hb_handle_t * h ) dynamic_range_compression = strdup("0.0,0.0"); } maxWidth = 960; - if( !x264opts ) + if( !advanced_opts ) { - x264opts = strdup("cabac=0:ref=2:me=umh:b-pyramid=none:b-adapt=2:weightb=0:trellis=0:weightp=0:vbv-maxrate=9500:vbv-bufsize=9500"); + advanced_opts = strdup("cabac=0:ref=2:me=umh:b-pyramid=none:b-adapt=2:weightb=0:trellis=0:weightp=0:vbv-maxrate=9500:vbv-bufsize=9500"); } if( !anamorphic_mode ) { @@ -943,9 +943,9 @@ static int HandleEvents( hb_handle_t * h ) { dynamic_range_compression = strdup("0.0"); } - if( !x264opts ) + if( !advanced_opts ) { - x264opts = strdup("ref=2:bframes=2:subme=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0"); + advanced_opts = strdup("ref=2:bframes=2:subme=6:mixed-refs=0:weightb=0:8x8dct=0:trellis=0"); } if( !anamorphic_mode ) { @@ -987,9 +987,9 @@ static int HandleEvents( hb_handle_t * h ) { dynamic_range_compression = strdup("0.0,0.0"); } - if( !x264opts ) + if( !advanced_opts ) { - x264opts = strdup("b-adapt=2:rc-lookahead=50"); + advanced_opts = strdup("b-adapt=2:rc-lookahead=50"); } detelecine = 1; decomb = 1; @@ -1068,9 +1068,9 @@ static int HandleEvents( hb_handle_t * h ) { dynamic_range_compression = strdup("0.0,0.0"); } - if( !x264opts ) + if( !advanced_opts ) { - x264opts = strdup("ref=1:b-pyramid=none:weightp=0:subme=5:me=umh:no-fast-pskip=1:cabac=0:weightb=0:8x8dct=0:trellis=0"); + advanced_opts = strdup("ref=1:b-pyramid=none:weightp=0:subme=5:me=umh:no-fast-pskip=1:cabac=0:weightb=0:8x8dct=0:trellis=0"); } if( !anamorphic_mode ) { @@ -1114,9 +1114,9 @@ static int HandleEvents( hb_handle_t * h ) dynamic_range_compression = strdup("0.0"); } maxWidth = 480; - if( !x264opts ) + if( !advanced_opts ) { - x264opts = strdup("level=30:cabac=0:ref=1:analyse=all:me=umh:no-fast-pskip=1:psy-rd=0,0:bframes=0:weightp=0:subme=6:8x8dct=0:trellis=0"); + advanced_opts = strdup("level=30:cabac=0:ref=1:analyse=all:me=umh:no-fast-pskip=1:psy-rd=0,0:bframes=0:weightp=0:subme=6:8x8dct=0:trellis=0"); } job->chapter_markers = 1; @@ -1156,9 +1156,9 @@ static int HandleEvents( hb_handle_t * h ) dynamic_range_compression = strdup("0.0"); } maxWidth = 640; - if( !x264opts ) + if( !advanced_opts ) { - x264opts = strdup("level=30:bframes=0:weightp=0:cabac=0:ref=1:vbv-maxrate=1500:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:psy-rd=0,0:subme=6:8x8dct=0:trellis=0"); + advanced_opts = strdup("level=30:bframes=0:weightp=0:cabac=0:ref=1:vbv-maxrate=1500:vbv-bufsize=2000:analyse=all:me=umh:no-fast-pskip=1:psy-rd=0,0:subme=6:8x8dct=0:trellis=0"); } job->chapter_markers = 1; @@ -2181,13 +2181,13 @@ static int HandleEvents( hb_handle_t * h ) job->color_matrix = color_matrix; } - if( x264opts != NULL && *x264opts != '\0' ) + if( advanced_opts != NULL && *advanced_opts != '\0' ) { - job->x264opts = x264opts; + job->advanced_opts = advanced_opts; } else /*avoids a bus error crash when options aren't specified*/ { - job->x264opts = NULL; + job->advanced_opts = NULL; } if (maxWidth) job->maxWidth = maxWidth; @@ -2226,7 +2226,7 @@ static int HandleEvents( hb_handle_t * h ) if( subtitle_scan ) { - char *x264opts_tmp; + char *advanced_opts_tmp; /* * When subtitle scan is enabled do a fast pre-scan job @@ -2234,9 +2234,9 @@ static int HandleEvents( hb_handle_t * h ) */ job->pass = -1; - x264opts_tmp = job->x264opts; + advanced_opts_tmp = job->advanced_opts; - job->x264opts = NULL; + job->advanced_opts = NULL; job->indepth_scan = subtitle_scan; fprintf( stderr, "Subtitle Scan Enabled - enabling " @@ -2247,7 +2247,7 @@ static int HandleEvents( hb_handle_t * h ) */ hb_add( h, job ); - job->x264opts = x264opts_tmp; + job->advanced_opts = advanced_opts_tmp; } if( twoPass ) @@ -2261,40 +2261,40 @@ static int HandleEvents( hb_handle_t * h ) job->indepth_scan = 0; - if (x264opts) + if (advanced_opts) { - x264opts2 = strdup(x264opts); + advanced_opts2 = strdup(advanced_opts); } /* * 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( turbo_opts_enabled ) { - int size = (x264opts ? strlen(x264opts) : 0) + strlen(turbo_opts) + 2; - char *tmp_x264opts; + int size = (advanced_opts ? strlen(advanced_opts) : 0) + strlen(turbo_opts) + 2; + char *tmp_advanced_opts; - tmp_x264opts = malloc(size * sizeof(char)); - if( x264opts ) + tmp_advanced_opts = malloc(size * sizeof(char)); + if( advanced_opts ) { - snprintf( tmp_x264opts, size, "%s:%s", - x264opts, turbo_opts ); - free( x264opts ); + snprintf( tmp_advanced_opts, size, "%s:%s", + advanced_opts, turbo_opts ); + free( advanced_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 */ - snprintf( tmp_x264opts, size, "%s", + snprintf( tmp_advanced_opts, size, "%s", turbo_opts ); } - x264opts = tmp_x264opts; + advanced_opts = tmp_advanced_opts; fprintf( stderr, "Modified x264 options for pass 1 to append turbo options: %s\n", - x264opts ); + advanced_opts ); - job->x264opts = x264opts; + job->advanced_opts = advanced_opts; } hb_add( h, job ); @@ -2307,7 +2307,7 @@ static int HandleEvents( hb_handle_t * h ) */ job->indepth_scan = 0; - job->x264opts = x264opts2; + job->advanced_opts = advanced_opts2; hb_add( h, job ); } @@ -2464,8 +2464,8 @@ static void ShowHelp() "### Video Options------------------------------------------------------------\n\n" " -e, --encoder <string> Set video library encoder (ffmpeg,x264,theora)\n" " (default: ffmpeg)\n" - " -x, --x264opts <string> Specify advanced x264 options in the\n" - " same style as mencoder:\n" + " -x, --encopts <string> Specify advanced encoder options in the\n" + " same style as mencoder (x264 and ffmpeg only):\n" " option1=value1:option2=value2\n" " -q, --quality <number> Set video quality\n" " -S, --size <MB> Set target size\n" @@ -2853,7 +2853,7 @@ static int ParseOptions( int argc, char ** argv ) { "ab", required_argument, NULL, 'B' }, { "rate", required_argument, NULL, 'r' }, { "arate", required_argument, NULL, 'R' }, - { "x264opts", required_argument, NULL, 'x' }, + { "encopts", required_argument, NULL, 'x' }, { "turbo", no_argument, NULL, 'T' }, { "maxHeight", required_argument, NULL, 'Y' }, { "maxWidth", required_argument, NULL, 'X' }, @@ -3254,7 +3254,7 @@ static int ParseOptions( int argc, char ** argv ) } break; case 'x': - x264opts = strdup( optarg ); + advanced_opts = strdup( optarg ); break; case 'T': turbo_opts_enabled = 1; |