[Bf-blender-cvs] [a7e7479] master: FFmpeg interface improvements

Sybren A. Stüvel noreply at git.blender.org
Wed Sep 21 15:28:47 CEST 2016


Commit: a7e74791221e2ef9b44ee1b3eb9ece37785aa62a
Author: Sybren A. Stüvel
Date:   Wed Sep 21 15:01:51 2016 +0200
Branches: master
https://developer.blender.org/rBa7e74791221e2ef9b44ee1b3eb9ece37785aa62a

FFmpeg interface improvements

This patch changes a couple of things in the video output encoding.

{F362527}

- Clearer separation between container and codec. No more "format", as this is
  too ambiguous. As a result, codecs were removed from the container list.
- Added FFmpeg speed presets, so the user can choosen from the range "Very
  slow" to "Ultra fast". By default no preset is used.
- Added Constant Rate Factor (CRF) mode, which allows changing the bit-rate
  depending on the desired quality and the input. This generally produces the
  best quality videos, at the expense of not knowing the exact bit-rate and
  file size.
- Added optional maximum of non-B-frames between B-frames (`max_b_frames`).
- Presets were adjusted for these changes, and new presets added. One of the
  new presets is [recommended](https://trac.ffmpeg.org/wiki/Encode/VFX#H.264)
  for reviewing videos, as it allows players to scrub through it easily. Might
  be nice in weeklies. This preset also requires control over the
  `max_b_frames` setting.

GUI-only changes:
- Renamed "MPEG" in the output file format menu with "FFmpeg", as this is more
  accurate. After all, FFmpeg is used when this option is chosen, which can
  also output non-MPEG files.
- Certain parts of the GUI are disabled when not in use:
    - bit rate options are not used when a constant rate factor is given.
    - audio bitrate & volume are not used when no audio is exported.

Note that I did not touch `BKE_ffmpeg_preset_set()`. There are currently two
preset systems for FFmpeg (`BKE_ffmpeg_preset_set()` and the Python preset
system). Before we do more work on `BKE_ffmpeg_preset_set()`, I think it's a
good idea to determine whether we want to keep it at all.

After this patch has been accepted, I'd be happy to go through the code and
remove any then-obsolete bits, such as the handling of "XVID" as a container
format.

Reviewers: sergey, mont29, brecht

Subscribers: mpan3, Blendify, brecht, fsiddi

Tags: #bf_blender

Differential Revision: https://developer.blender.org/D2242

===================================================================

D	release/scripts/presets/ffmpeg/DV.py
R100	release/scripts/presets/ffmpeg/DVD.py	release/scripts/presets/ffmpeg/DVD (note_colon_ this changes render resolution).py
D	release/scripts/presets/ffmpeg/SVCD.py
D	release/scripts/presets/ffmpeg/VCD.py
A	release/scripts/presets/ffmpeg/h264 in MP4.py
A	release/scripts/presets/ffmpeg/h264 in Matroska for scrubbing.py
R091	release/scripts/presets/ffmpeg/h264.py	release/scripts/presets/ffmpeg/h264 in Matroska.py
R090	release/scripts/presets/ffmpeg/theora.py	release/scripts/presets/ffmpeg/ogg_theora.py
M	release/scripts/presets/ffmpeg/xvid.py
M	release/scripts/startup/bl_ui/properties_render.py
M	source/blender/blenkernel/intern/image.c
M	source/blender/blenkernel/intern/writeffmpeg.c
M	source/blender/blenloader/intern/versioning_270.c
M	source/blender/makesdna/DNA_scene_types.h
M	source/blender/makesrna/intern/rna_scene.c

===================================================================

diff --git a/release/scripts/presets/ffmpeg/DV.py b/release/scripts/presets/ffmpeg/DV.py
deleted file mode 100644
index a95d861..0000000
--- a/release/scripts/presets/ffmpeg/DV.py
+++ /dev/null
@@ -1,14 +0,0 @@
-import bpy
-is_ntsc = (bpy.context.scene.render.fps != 25)
-
-bpy.context.scene.render.ffmpeg.format = "DV"
-bpy.context.scene.render.resolution_x = 720
-
-if is_ntsc:
-    bpy.context.scene.render.resolution_y = 480
-else:
-    bpy.context.scene.render.resolution_y = 576
-
-bpy.context.scene.render.ffmpeg.audio_mixrate = 48000
-bpy.context.scene.render.ffmpeg.audio_codec = "PCM"
-bpy.context.scene.render.ffmpeg.audio_channels = "STEREO"
diff --git a/release/scripts/presets/ffmpeg/DVD.py b/release/scripts/presets/ffmpeg/DVD (note_colon_ this changes render resolution).py
similarity index 100%
rename from release/scripts/presets/ffmpeg/DVD.py
rename to release/scripts/presets/ffmpeg/DVD (note_colon_ this changes render resolution).py
diff --git a/release/scripts/presets/ffmpeg/SVCD.py b/release/scripts/presets/ffmpeg/SVCD.py
deleted file mode 100644
index deaf969..0000000
--- a/release/scripts/presets/ffmpeg/SVCD.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import bpy
-is_ntsc = (bpy.context.scene.render.fps != 25)
-
-bpy.context.scene.render.ffmpeg.format = "MPEG2"
-bpy.context.scene.render.resolution_x = 480
-
-if is_ntsc:
-    bpy.context.scene.render.resolution_y = 480
-    bpy.context.scene.render.ffmpeg.gopsize = 18
-else:
-    bpy.context.scene.render.resolution_y = 576
-    bpy.context.scene.render.ffmpeg.gopsize = 15
-
-bpy.context.scene.render.ffmpeg.video_bitrate = 2040
-bpy.context.scene.render.ffmpeg.maxrate = 2516
-bpy.context.scene.render.ffmpeg.minrate = 0
-bpy.context.scene.render.ffmpeg.buffersize = 224 * 8
-bpy.context.scene.render.ffmpeg.packetsize = 2324
-bpy.context.scene.render.ffmpeg.muxrate = 0
-
-bpy.context.scene.render.ffmpeg.audio_bitrate = 224
-bpy.context.scene.render.ffmpeg.audio_mixrate = 44100
-bpy.context.scene.render.ffmpeg.audio_codec = "MP2"
-bpy.context.scene.render.ffmpeg.audio_channels = "STEREO"
diff --git a/release/scripts/presets/ffmpeg/VCD.py b/release/scripts/presets/ffmpeg/VCD.py
deleted file mode 100644
index 3e57be7..0000000
--- a/release/scripts/presets/ffmpeg/VCD.py
+++ /dev/null
@@ -1,24 +0,0 @@
-import bpy
-is_ntsc = (bpy.context.scene.render.fps != 25)
-
-bpy.context.scene.render.ffmpeg.format = "MPEG1"
-bpy.context.scene.render.resolution_x = 352
-
-if is_ntsc:
-    bpy.context.scene.render.resolution_y = 240
-    bpy.context.scene.render.ffmpeg.gopsize = 18
-else:
-    bpy.context.scene.render.resolution_y = 288
-    bpy.context.scene.render.ffmpeg.gopsize = 15
-
-bpy.context.scene.render.ffmpeg.video_bitrate = 1150
-bpy.context.scene.render.ffmpeg.maxrate = 1150
-bpy.context.scene.render.ffmpeg.minrate = 1150
-bpy.context.scene.render.ffmpeg.buffersize = 40 * 8
-bpy.context.scene.render.ffmpeg.packetsize = 2324
-bpy.context.scene.render.ffmpeg.muxrate = 2352 * 75 * 8
-
-bpy.context.scene.render.ffmpeg.audio_bitrate = 224
-bpy.context.scene.render.ffmpeg.audio_mixrate = 44100
-bpy.context.scene.render.ffmpeg.audio_codec = "MP2"
-bpy.context.scene.render.ffmpeg.audio_channels = "STEREO"
diff --git a/release/scripts/presets/ffmpeg/h264.py b/release/scripts/presets/ffmpeg/h264 in MP4.py
similarity index 83%
copy from release/scripts/presets/ffmpeg/h264.py
copy to release/scripts/presets/ffmpeg/h264 in MP4.py
index e1dbdc1..0e9c32c 100644
--- a/release/scripts/presets/ffmpeg/h264.py
+++ b/release/scripts/presets/ffmpeg/h264 in MP4.py	
@@ -1,13 +1,14 @@
 import bpy
 is_ntsc = (bpy.context.scene.render.fps != 25)
 
-bpy.context.scene.render.ffmpeg.format = "H264"
+bpy.context.scene.render.ffmpeg.format = "MPEG4"
 bpy.context.scene.render.ffmpeg.codec = "H264"
 
 if is_ntsc:
     bpy.context.scene.render.ffmpeg.gopsize = 18
 else:
     bpy.context.scene.render.ffmpeg.gopsize = 15
+bpy.context.scene.render.ffmpeg.use_max_b_frames = False
 
 bpy.context.scene.render.ffmpeg.video_bitrate = 6000
 bpy.context.scene.render.ffmpeg.maxrate = 9000
diff --git a/release/scripts/presets/ffmpeg/h264 in Matroska for scrubbing.py b/release/scripts/presets/ffmpeg/h264 in Matroska for scrubbing.py
new file mode 100644
index 0000000..eb1889d
--- /dev/null
+++ b/release/scripts/presets/ffmpeg/h264 in Matroska for scrubbing.py	
@@ -0,0 +1,14 @@
+"""Sets up FFmpeg to output files that can easily be scrubbed through.
+
+Information was taken from https://trac.ffmpeg.org/wiki/Encode/VFX#H.264
+"""
+
+import bpy
+
+bpy.context.scene.render.ffmpeg.format = "MKV"
+bpy.context.scene.render.ffmpeg.codec = "H264"
+
+bpy.context.scene.render.ffmpeg.gopsize = 1
+bpy.context.scene.render.ffmpeg.constant_rate_factor = 'PERC_LOSSLESS'
+bpy.context.scene.render.ffmpeg.use_max_b_frames = True
+bpy.context.scene.render.ffmpeg.max_b_frames = 0
diff --git a/release/scripts/presets/ffmpeg/h264.py b/release/scripts/presets/ffmpeg/h264 in Matroska.py
similarity index 91%
rename from release/scripts/presets/ffmpeg/h264.py
rename to release/scripts/presets/ffmpeg/h264 in Matroska.py
index e1dbdc1..1fe066d 100644
--- a/release/scripts/presets/ffmpeg/h264.py
+++ b/release/scripts/presets/ffmpeg/h264 in Matroska.py	
@@ -1,7 +1,7 @@
 import bpy
 is_ntsc = (bpy.context.scene.render.fps != 25)
 
-bpy.context.scene.render.ffmpeg.format = "H264"
+bpy.context.scene.render.ffmpeg.format = "MKV"
 bpy.context.scene.render.ffmpeg.codec = "H264"
 
 if is_ntsc:
diff --git a/release/scripts/presets/ffmpeg/theora.py b/release/scripts/presets/ffmpeg/ogg_theora.py
similarity index 90%
rename from release/scripts/presets/ffmpeg/theora.py
rename to release/scripts/presets/ffmpeg/ogg_theora.py
index 88f1ac9..b450b67 100644
--- a/release/scripts/presets/ffmpeg/theora.py
+++ b/release/scripts/presets/ffmpeg/ogg_theora.py
@@ -8,6 +8,7 @@ if is_ntsc:
     bpy.context.scene.render.ffmpeg.gopsize = 18
 else:
     bpy.context.scene.render.ffmpeg.gopsize = 15
+bpy.context.scene.render.ffmpeg.use_max_b_frames = False
 
 bpy.context.scene.render.ffmpeg.video_bitrate = 6000
 bpy.context.scene.render.ffmpeg.maxrate = 9000
diff --git a/release/scripts/presets/ffmpeg/xvid.py b/release/scripts/presets/ffmpeg/xvid.py
index e69ab66..dba0f71 100644
--- a/release/scripts/presets/ffmpeg/xvid.py
+++ b/release/scripts/presets/ffmpeg/xvid.py
@@ -1,12 +1,14 @@
 import bpy
 is_ntsc = (bpy.context.scene.render.fps != 25)
 
-bpy.context.scene.render.ffmpeg.format = "XVID"
+bpy.context.scene.render.ffmpeg.format = "AVI"
+bpy.context.scene.render.ffmpeg.codec = "MPEG4"
 
 if is_ntsc:
     bpy.context.scene.render.ffmpeg.gopsize = 18
 else:
     bpy.context.scene.render.ffmpeg.gopsize = 15
+bpy.context.scene.render.ffmpeg.use_max_b_frames = False
 
 bpy.context.scene.render.ffmpeg.video_bitrate = 6000
 bpy.context.scene.render.ffmpeg.maxrate = 9000
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 152d4e9..850606e 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -461,31 +461,42 @@ class RENDER_PT_encoding(RenderButtonsPanel, Panel):
 
         split = layout.split()
         split.prop(rd.ffmpeg, "format")
-        if ffmpeg.format in {'AVI', 'QUICKTIME', 'MKV', 'OGG', 'MPEG4'}:
-            split.prop(ffmpeg, "codec")
-            if ffmpeg.codec == 'H264':
-                row = layout.row()
-                row.label()
-                row.prop(ffmpeg, "use_lossless_output")
-        elif rd.ffmpeg.format == 'H264':
-            split.prop(ffmpeg, "use_lossless_output")
-        else:
-            split.label()
+        split.prop(ffmpeg, "use_autosplit")
+
+        layout.separator()
+
+        needs_codec = ffmpeg.format in {'AVI', 'QUICKTIME', 'MKV', 'OGG', 'MPEG4'}
+        if needs_codec:
+            layout.prop(ffmpeg, "codec")
 
+        if ffmpeg.codec in {'DNXHD'}:
+            layout.prop(ffmpeg, "use_lossless_output")
+
+        # Output quality
+        if needs_codec and ffmpeg.codec in {'H264', 'MPEG4'}:
+            layout.prop(ffmpeg, "constant_rate_factor")
+
+        # Encoding speed
+        layout.prop(ffmpeg, "ffmpeg_preset")
+        # I-frames
+        layout.prop(ffmpeg, "gopsize")
+        # B-Frames
         row = layout.row()
-        row.prop(ffmpeg, "video_bitrate")
-        row.prop(ffmpeg, "gopsize")
+        row.prop(ffmpeg, "use_max_b_frames", text='Max B-frames')
+        pbox = row.split()
+        pbox.prop(ffmpeg, "max_b_frames", text='')
+        pbox.enabled = ffmpeg.use_max_b_frames
 
         split = layout.split()
-
+        split.enabled = ffmpeg.constant_rate_factor == 'NONE'
         col = split.column()
         col.label(text="Rate:")
+        col.prop(ffmpeg, "video_bitrate")
         col.prop(ffmpeg, "minrate", text="Minimum")
         col.prop(ffmpeg, "maxrate", text="Maximum")
         col.prop(ffmpeg, "buffersize", text="Buffer")
 
         col = split.column()
-        col.prop(ffmpeg, "use_autosplit")
         col.label(text="Mux:")
         col.prop(ffmpeg, "muxrate", text="Rate")
         col.prop(ffmpeg, "packetsize", text="Packet Size")
@@ -497,6 +508,7 @@ class RENDER_PT_encoding(RenderButtonsPanel, Panel):
             layout.prop(ffmpeg, "audio_codec", text="Audio Codec")
 
         row = layout.row()
+        row.enabled = ffmpeg.audio_codec != 'NONE'
         row.prop(ffmpeg, "audio_bitrate")
         row.prop(ffmpeg, "audio_volume", slider=True)
 
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index 8a9cb73..a4eef2f 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -1325,7 +1325,7 @@ char BKE_imtype_from_arg(const char *imtype_arg)
 	else if (STREQ(imtype_arg, "EXR")) return R_IMF_IMTYPE_OPENEXR;
 	else if (STREQ(imtype_arg, "MULTILAYER")) return R_IMF_IMTYPE_MULTILAYER;
 #endif
-	else if (STREQ(imtype_arg, "MPEG")) return R_IMF_IMTYPE_FFMPEG;
+	else if (STREQ(imtype_arg, "FFMPEG")) return R_IMF_IMTYPE_FFMPEG;
 	else if (STREQ(imtype_arg, "FRAMESERVER")) return R_IMF_IMTYPE_FRAMESERVER;
 #ifdef WITH_CINEON
 	else if (STREQ(imtype_arg, "CINEON")) return R_IMF_IMTYPE_CINEON;
diff -

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list