Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Antalik <richardantalik@gmail.com>2021-03-16 20:37:23 +0300
committerRichard Antalik <richardantalik@gmail.com>2021-03-16 20:50:32 +0300
commite4f347783320d83e43bc650020013e19b2f22c7f (patch)
treed9375279bb0ad5d74c8419e10dfb5fe7e2c41d01
parent91561629cd0bd622c9d1722701ab88c9e77be660 (diff)
FFmpeg: Improve proxy building performance
Use h264 codec for output. This codec produces smaller files, can be multithreaded and decodes even faster than MJPEG. Quality setting 0-100 corresponds to "Lowest Quality" to "Perceptually Lossless" in Blender's h264 encoding presets. All available cores are used for decoding. Same goes for decoding but only for codecs that supports this (h264, vp9 seems to support this option out of th box as well). Other decoders can probably be optimized in similar way, but threaded encoding provides significant boost already. I have tested variety of codecs, and all were transcoded properly. Reviewed By: sergey, fsiddi Differential Revision: https://developer.blender.org/D10731
-rw-r--r--source/blender/imbuf/intern/indexer.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index c9581c108c0..edaa1b973d0 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -27,6 +27,7 @@
#include "BLI_endian_switch.h"
#include "BLI_fileops.h"
#include "BLI_ghash.h"
+#include "BLI_math.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_threads.h"
@@ -477,7 +478,6 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
struct proxy_output_ctx *rv = MEM_callocN(sizeof(struct proxy_output_ctx), "alloc_proxy_output");
char fname[FILE_MAX];
- int ffmpeg_quality;
rv->proxy_size = proxy_size;
rv->anim = anim;
@@ -496,12 +496,15 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
rv->st->id = 0;
rv->c = rv->st->codec;
- rv->c->thread_count = BLI_system_thread_count();
- rv->c->thread_type = FF_THREAD_SLICE;
rv->c->codec_type = AVMEDIA_TYPE_VIDEO;
- rv->c->codec_id = AV_CODEC_ID_MJPEG;
+ rv->c->codec_id = AV_CODEC_ID_H264;
rv->c->width = width;
rv->c->height = height;
+ rv->c->gop_size = 2;
+ rv->c->max_b_frames = 0;
+ /* Correct wrong default ffmpeg param which crash x264. */
+ rv->c->qmin = 10;
+ rv->c->qmax = 51;
rv->of->oformat->video_codec = rv->c->codec_id;
rv->codec = avcodec_find_encoder(rv->c->codec_id);
@@ -527,11 +530,19 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
rv->c->time_base.num = 1;
rv->st->time_base = rv->c->time_base;
- /* there's no way to set JPEG quality in the same way as in AVI JPEG and image sequence,
- * but this seems to be giving expected quality result */
- ffmpeg_quality = (int)(1.0f + 30.0f * (1.0f - (float)quality / 100.0f) + 0.5f);
- av_opt_set_int(rv->c, "qmin", ffmpeg_quality, 0);
- av_opt_set_int(rv->c, "qmax", ffmpeg_quality, 0);
+ /* This range matches eFFMpegCrf. Crf_range_min corresponds to lowest quality, crf_range_max to
+ * highest quality. */
+ const int crf_range_min = 32;
+ const int crf_range_max = 17;
+ int crf = round_fl_to_int((quality / 100.0f) * (crf_range_max - crf_range_min) + crf_range_min);
+
+ AVDictionary *codec_opts = NULL;
+ /* High quality preset value. */
+ av_dict_set_int(&codec_opts, "crf", crf, 0);
+ /* Prefer smaller filesize. */
+ av_dict_set(&codec_opts, "preset", "slow", 0);
+ /* Thread count. */
+ av_dict_set_int(&codec_opts, "threads", BLI_system_thread_count(), 0);
if (rv->of->flags & AVFMT_GLOBALHEADER) {
rv->c->flags |= CODEC_FLAG_GLOBAL_HEADER;
@@ -545,7 +556,7 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
return 0;
}
- avcodec_open2(rv->c, rv->codec, NULL);
+ avcodec_open2(rv->c, rv->codec, &codec_opts);
rv->orig_height = av_get_cropped_height_from_codec(st->codec);
@@ -783,7 +794,11 @@ static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim,
context->iCodecCtx->workaround_bugs = 1;
- if (avcodec_open2(context->iCodecCtx, context->iCodec, NULL) < 0) {
+ AVDictionary *codec_opts = NULL;
+ /* Thread count. */
+ av_dict_set_int(&codec_opts, "threads", BLI_system_thread_count(), 0);
+
+ if (avcodec_open2(context->iCodecCtx, context->iCodec, &codec_opts) < 0) {
avformat_close_input(&context->iFormatCtx);
MEM_freeN(context);
return NULL;