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:
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c175
-rw-r--r--source/blender/imbuf/intern/indexer.c14
2 files changed, 103 insertions, 86 deletions
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 3408f990fd1..7c8eba20a28 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -518,6 +518,48 @@ static void set_ffmpeg_properties(RenderData *rd,
}
}
+static AVRational calc_time_base(uint den, double num, int codec_id)
+{
+ /* Convert the input 'num' to an integer. Simply shift the decimal places until we get an integer
+ * (within a floating point error range).
+ * For example if we have den = 3 and num = 0.1 then the fps is: den/num = 30 fps.
+ * When converthing this to a ffmpeg time base, we want num to be an integer.
+ * So we simply move the decimal places of both numbers. IE den = 30, num = 1.*/
+ float eps = FLT_EPSILON;
+ const uint DENUM_MAX = (codec_id == AV_CODEC_ID_MPEG4) ? (1UL << 16) - 1 : (1UL << 31) - 1;
+
+ /* Calculate the precision of the initial floating point number. */
+ if (num > 1.0) {
+ const uint num_integer_bits = log2_floor_u((unsigned int)num);
+
+ /* Formula for calculating the epsilon value: (power of two range) / (pow mantissa bits)
+ * For example, a float has 23 manitissa bits and the float value 3.5f as a pow2 range of
+ * (4-2=2):
+ * (2) / pow2(23) = floating point precision for 3.5f
+ */
+ eps = (float)(1 << num_integer_bits) * FLT_EPSILON;
+ }
+
+ /* Calculate how many decimal shifts we can do until we run out of precision. */
+ const int max_num_shift = fabsf(log10f(eps));
+ /* Calculate how many times we can shift the denominator. */
+ const int max_den_shift = log10f(DENUM_MAX) - log10f(den);
+ const int max_iter = min_ii(max_num_shift, max_den_shift);
+
+ for (int i = 0; i < max_iter && fabs(num - round(num)) > eps; i++) {
+ /* Increase the number and denominator until both are integers. */
+ num *= 10;
+ den *= 10;
+ eps *= 10;
+ }
+
+ AVRational time_base;
+ time_base.den = den;
+ time_base.num = (int)num;
+
+ return time_base;
+}
+
/* prepare a video stream for the output file */
static AVStream *alloc_video_stream(FFMpegContext *context,
@@ -548,13 +590,24 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
c->codec_id = codec_id;
c->codec_type = AVMEDIA_TYPE_VIDEO;
+ codec = avcodec_find_encoder(c->codec_id);
+ if (!codec) {
+ fprintf(stderr, "Couldn't find valid video codec\n");
+ avcodec_free_context(&c);
+ context->video_codec = NULL;
+ return NULL;
+ }
+
+ /* Load codec defaults into 'c'. */
+ avcodec_get_context_defaults3(c, codec);
+
/* Get some values from the current render settings */
c->width = rectx;
c->height = recty;
- /* FIXME: Really bad hack (tm) for NTSC support */
if (context->ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) {
+ /* FIXME: Really bad hack (tm) for NTSC support */
c->time_base.den = 2997;
c->time_base.num = 100;
}
@@ -562,21 +615,23 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
c->time_base.den = rd->frs_sec;
c->time_base.num = (int)rd->frs_sec_base;
}
- else if (compare_ff(rd->frs_sec_base, 1.001f, 0.000001f)) {
- /* This converts xx/1.001 (which is used in presets) to xx000/1001 (which is used in the rest
- * of the world, including FFmpeg). */
- c->time_base.den = (int)(rd->frs_sec * 1000);
- c->time_base.num = (int)(rd->frs_sec_base * 1000);
- }
else {
- /* This calculates a fraction (DENUM_MAX / num) which approximates the scene frame rate
- * (frs_sec / frs_sec_base). It uses the maximum denominator allowed by FFmpeg.
- */
- const double DENUM_MAX = (codec_id == AV_CODEC_ID_MPEG4) ? (1UL << 16) - 1 : (1UL << 31) - 1;
- const double num = (DENUM_MAX / (double)rd->frs_sec) * rd->frs_sec_base;
+ c->time_base = calc_time_base(rd->frs_sec, rd->frs_sec_base, codec_id);
+ }
- c->time_base.den = (int)DENUM_MAX;
- c->time_base.num = (int)num;
+ /* As per the timebase documentation here:
+ * https://www.ffmpeg.org/ffmpeg-codecs.html#Codec-Options
+ * We want to set the time base to (1 / fps) for fixed frame rate video.
+ * If it is not possible, we want to set the timebase numbers to something as
+ * small as possible.
+ */
+ if (c->time_base.num != 1) {
+ AVRational new_time_base;
+ if (av_reduce(
+ &new_time_base.num, &new_time_base.den, c->time_base.num, c->time_base.den, INT_MAX)) {
+ /* Exact reduction was possible. Use the new value. */
+ c->time_base = new_time_base;
+ }
}
st->time_base = c->time_base;
@@ -588,6 +643,11 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
ffmpeg_dict_set_int(&opts, "lossless", 1);
}
else if (context->ffmpeg_crf >= 0) {
+ /* As per https://trac.ffmpeg.org/wiki/Encode/VP9 we must set the bit rate to zero when
+ * encoding with vp9 in crf mode.
+ * Set this to always be zero for other codecs as well.
+ * We don't care about bit rate in crf mode. */
+ c->bit_rate = 0;
ffmpeg_dict_set_int(&opts, "crf", context->ffmpeg_crf);
}
else {
@@ -627,12 +687,6 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
}
}
- codec = avcodec_find_encoder(c->codec_id);
- if (!codec) {
- avcodec_free_context(&c);
- return NULL;
- }
-
/* Be sure to use the correct pixel format(e.g. RGB, YUV) */
if (codec->pix_fmts) {
@@ -649,12 +703,6 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
c->codec_tag = (('D' << 24) + ('I' << 16) + ('V' << 8) + 'X');
}
- if (codec_id == AV_CODEC_ID_H264) {
- /* correct wrong default ffmpeg param which crash x264 */
- c->qmin = 10;
- c->qmax = 51;
- }
-
/* Keep lossless encodes in the RGB domain. */
if (codec_id == AV_CODEC_ID_HUFFYUV) {
if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
@@ -714,10 +762,14 @@ static AVStream *alloc_video_stream(FFMpegContext *context,
c->thread_type = FF_THREAD_SLICE;
}
- if (avcodec_open2(c, codec, &opts) < 0) {
+ int ret = avcodec_open2(c, codec, &opts);
+
+ if (ret < 0) {
+ fprintf(stderr, "Couldn't initialize video codec: %s\n", av_err2str(ret));
BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
av_dict_free(&opts);
avcodec_free_context(&c);
+ context->video_codec = NULL;
return NULL;
}
av_dict_free(&opts);
@@ -777,6 +829,17 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
c->codec_id = codec_id;
c->codec_type = AVMEDIA_TYPE_AUDIO;
+ codec = avcodec_find_encoder(c->codec_id);
+ if (!codec) {
+ fprintf(stderr, "Couldn't find valid audio codec\n");
+ avcodec_free_context(&c);
+ context->audio_codec = NULL;
+ return NULL;
+ }
+
+ /* Load codec defaults into 'c'. */
+ avcodec_get_context_defaults3(c, codec);
+
c->sample_rate = rd->ffcodecdata.audio_mixrate;
c->bit_rate = context->ffmpeg_audio_bitrate * 1000;
c->sample_fmt = AV_SAMPLE_FMT_S16;
@@ -806,13 +869,6 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
c->sample_fmt = AV_SAMPLE_FMT_FLT;
}
- codec = avcodec_find_encoder(c->codec_id);
- if (!codec) {
- // XXX error("Couldn't find a valid audio codec");
- avcodec_free_context(&c);
- return NULL;
- }
-
if (codec->sample_fmts) {
/* Check if the preferred sample format for this codec is supported.
* this is because, depending on the version of libav,
@@ -852,11 +908,14 @@ static AVStream *alloc_audio_stream(FFMpegContext *context,
set_ffmpeg_properties(rd, c, "audio", &opts);
- if (avcodec_open2(c, codec, &opts) < 0) {
- // XXX error("Couldn't initialize audio codec");
+ int ret = avcodec_open2(c, codec, &opts);
+
+ if (ret < 0) {
+ fprintf(stderr, "Couldn't initialize audio codec: %s\n", av_err2str(ret));
BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
av_dict_free(&opts);
avcodec_free_context(&c);
+ context->audio_codec = NULL;
return NULL;
}
av_dict_free(&opts);
@@ -1636,49 +1695,7 @@ static void ffmpeg_set_expert_options(RenderData *rd)
IDP_FreePropertyContent(rd->ffcodecdata.properties);
}
- if (codec_id == AV_CODEC_ID_H264) {
- /*
- * All options here are for x264, but must be set via ffmpeg.
- * The names are therefore different - Search for "x264 to FFmpeg option mapping"
- * to get a list.
- */
-
- /*
- * Use CABAC coder. Using "coder:1", which should be equivalent,
- * crashes Blender for some reason. Either way - this is no big deal.
- */
- BKE_ffmpeg_property_add_string(rd, "video", "coder:vlc");
-
- /*
- * The other options were taken from the libx264-default.preset
- * included in the ffmpeg distribution.
- */
-
- /* This breaks compatibility for QT. */
- // BKE_ffmpeg_property_add_string(rd, "video", "flags:loop");
- BKE_ffmpeg_property_add_string(rd, "video", "cmp:chroma");
- BKE_ffmpeg_property_add_string(rd, "video", "partitions:parti4x4"); /* Deprecated. */
- BKE_ffmpeg_property_add_string(rd, "video", "partitions:partp8x8"); /* Deprecated. */
- BKE_ffmpeg_property_add_string(rd, "video", "partitions:partb8x8"); /* Deprecated. */
- BKE_ffmpeg_property_add_string(rd, "video", "me:hex");
- BKE_ffmpeg_property_add_string(rd, "video", "subq:6");
- BKE_ffmpeg_property_add_string(rd, "video", "me_range:16");
- BKE_ffmpeg_property_add_string(rd, "video", "qdiff:4");
- BKE_ffmpeg_property_add_string(rd, "video", "keyint_min:25");
- BKE_ffmpeg_property_add_string(rd, "video", "sc_threshold:40");
- BKE_ffmpeg_property_add_string(rd, "video", "i_qfactor:0.71");
- BKE_ffmpeg_property_add_string(rd, "video", "b_strategy:1");
- BKE_ffmpeg_property_add_string(rd, "video", "bf:3");
- BKE_ffmpeg_property_add_string(rd, "video", "refs:2");
- BKE_ffmpeg_property_add_string(rd, "video", "qcomp:0.6");
-
- BKE_ffmpeg_property_add_string(rd, "video", "trellis:0");
- BKE_ffmpeg_property_add_string(rd, "video", "weightb:1");
- BKE_ffmpeg_property_add_string(rd, "video", "8x8dct:1");
- BKE_ffmpeg_property_add_string(rd, "video", "fast-pskip:1");
- BKE_ffmpeg_property_add_string(rd, "video", "wpredp:2");
- }
- else if (codec_id == AV_CODEC_ID_DNXHD) {
+ if (codec_id == AV_CODEC_ID_DNXHD) {
if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT) {
BKE_ffmpeg_property_add_string(rd, "video", "mbd:rd");
}
diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c
index 453df6078ce..e1e6cc677ed 100644
--- a/source/blender/imbuf/intern/indexer.c
+++ b/source/blender/imbuf/intern/indexer.c
@@ -492,13 +492,6 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
rv->c = avcodec_alloc_context3(NULL);
rv->c->codec_type = AVMEDIA_TYPE_VIDEO;
rv->c->codec_id = AV_CODEC_ID_H264;
- rv->c->width = width;
- rv->c->height = height;
- rv->c->gop_size = 10;
- 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);
@@ -513,6 +506,13 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
return NULL;
}
+ avcodec_get_context_defaults3(rv->c, rv->codec);
+
+ rv->c->width = width;
+ rv->c->height = height;
+ rv->c->gop_size = 10;
+ rv->c->max_b_frames = 0;
+
if (rv->codec->pix_fmts) {
rv->c->pix_fmt = rv->codec->pix_fmts[0];
}