summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gtk/src/ghb.ui105
-rw-r--r--gtk/src/hb-backend.c120
-rw-r--r--gtk/src/hb-backend.h2
-rw-r--r--gtk/src/internal_defaults.xml2
-rw-r--r--gtk/src/main.c9
-rw-r--r--gtk/src/makedeps.py4
-rw-r--r--gtk/src/queuehandler.c25
-rw-r--r--gtk/src/x264handler.c26
-rw-r--r--libhb/common.h6
-rw-r--r--libhb/decavcodec.c3
-rw-r--r--libhb/encavcodec.c339
-rw-r--r--libhb/encx264.c8
-rw-r--r--libhb/hbffmpeg.h1
-rw-r--r--libhb/muxmkv.c5
-rw-r--r--libhb/muxmp4.c12
-rw-r--r--libhb/work.c4
-rw-r--r--macosx/Controller.m20
-rw-r--r--macosx/HBPreviewController.m6
-rw-r--r--macosx/InstantHandBrake/ExpressController.m4
-rwxr-xr-xscripts/manicure.rb12
-rw-r--r--test/test.c98
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">&lt;small&gt;&lt;b&gt;Current FFMpeg MPEG-4 Advanced Option String&lt;/b&gt;&lt;/small&gt;</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( &param, 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;