Blender V4.5
movie_write.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2006 Peter Schlaile.
2 * SPDX-FileCopyrightText: 2023-2024 Blender Authors
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later */
5
9
10#include "movie_write.hh"
11
12#include "DNA_scene_types.h"
13
14#include "MOV_write.hh"
15
16#include "BKE_report.hh"
17
18#ifdef WITH_FFMPEG
19# include <cstdio>
20# include <cstring>
21
22# include "MEM_guardedalloc.h"
23
24# include "BLI_endian_defines.h"
25# include "BLI_fileops.h"
26# include "BLI_math_base.h"
27# include "BLI_math_color.h"
28# include "BLI_path_utils.hh"
29# include "BLI_string.h"
30# include "BLI_threads.h"
31# include "BLI_utildefines.h"
32
33# include "BKE_global.hh"
34# include "BKE_image.hh"
35# include "BKE_main.hh"
36# include "BKE_path_templates.hh"
37
38# include "IMB_imbuf.hh"
39
40# include "MOV_enums.hh"
41# include "MOV_util.hh"
42
43# include "ffmpeg_swscale.hh"
44# include "movie_util.hh"
45
46static constexpr int64_t ffmpeg_autosplit_size = 2'000'000'000;
47
48# define FF_DEBUG_PRINT \
49 if (G.debug & G_DEBUG_FFMPEG) \
50 printf
51
52static void ffmpeg_dict_set_int(AVDictionary **dict, const char *key, int value)
53{
54 av_dict_set_int(dict, key, value, 0);
55}
56
57static void ffmpeg_movie_close(MovieWriter *context);
58static bool ffmpeg_filepath_get(MovieWriter *context,
59 char filepath[FILE_MAX],
60 const RenderData *rd,
61 bool preview,
62 const char *suffix,
64
65static AVFrame *alloc_frame(AVPixelFormat pix_fmt, int width, int height)
66{
67 AVFrame *f = av_frame_alloc();
68 if (f == nullptr) {
69 return nullptr;
70 }
71 const size_t align = ffmpeg_get_buffer_alignment();
72 f->format = pix_fmt;
73 f->width = width;
74 f->height = height;
75 if (av_frame_get_buffer(f, align) < 0) {
76 av_frame_free(&f);
77 return nullptr;
78 }
79 return f;
80}
81
82/* Get the correct file extensions for the requested format,
83 * first is always desired guess_format parameter */
84static const char **get_file_extensions(int format)
85{
86 switch (format) {
87 case FFMPEG_DV: {
88 static const char *rv[] = {".dv", nullptr};
89 return rv;
90 }
91 case FFMPEG_MPEG1: {
92 static const char *rv[] = {".mpg", ".mpeg", nullptr};
93 return rv;
94 }
95 case FFMPEG_MPEG2: {
96 static const char *rv[] = {".dvd", ".vob", ".mpg", ".mpeg", nullptr};
97 return rv;
98 }
99 case FFMPEG_MPEG4: {
100 static const char *rv[] = {".mp4", ".mpg", ".mpeg", nullptr};
101 return rv;
102 }
103 case FFMPEG_AVI: {
104 static const char *rv[] = {".avi", nullptr};
105 return rv;
106 }
107 case FFMPEG_MOV: {
108 static const char *rv[] = {".mov", nullptr};
109 return rv;
110 }
111 case FFMPEG_H264: {
112 /* FIXME: avi for now... */
113 static const char *rv[] = {".avi", nullptr};
114 return rv;
115 }
116
117 case FFMPEG_XVID: {
118 /* FIXME: avi for now... */
119 static const char *rv[] = {".avi", nullptr};
120 return rv;
121 }
122 case FFMPEG_FLV: {
123 static const char *rv[] = {".flv", nullptr};
124 return rv;
125 }
126 case FFMPEG_MKV: {
127 static const char *rv[] = {".mkv", nullptr};
128 return rv;
129 }
130 case FFMPEG_OGG: {
131 static const char *rv[] = {".ogv", ".ogg", nullptr};
132 return rv;
133 }
134 case FFMPEG_WEBM: {
135 static const char *rv[] = {".webm", nullptr};
136 return rv;
137 }
138 case FFMPEG_AV1: {
139 static const char *rv[] = {".mp4", ".mkv", nullptr};
140 return rv;
141 }
142 default:
143 return nullptr;
144 }
145}
146
147/* Write a frame to the output file */
148static bool write_video_frame(MovieWriter *context, AVFrame *frame, ReportList *reports)
149{
150 int ret, success = 1;
151 AVPacket *packet = av_packet_alloc();
152
153 AVCodecContext *c = context->video_codec;
154
155 frame->pts = context->video_time;
156 context->video_time++;
157
158 char error_str[AV_ERROR_MAX_STRING_SIZE];
159 ret = avcodec_send_frame(c, frame);
160 if (ret < 0) {
161 /* Can't send frame to encoder. This shouldn't happen. */
162 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
163 fprintf(stderr, "Can't send video frame: %s\n", error_str);
164 success = -1;
165 }
166
167 while (ret >= 0) {
168 ret = avcodec_receive_packet(c, packet);
169
170 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
171 /* No more packets available. */
172 break;
173 }
174 if (ret < 0) {
175 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
176 fprintf(stderr, "Error encoding frame: %s\n", error_str);
177 break;
178 }
179
180 packet->stream_index = context->video_stream->index;
181 av_packet_rescale_ts(packet, c->time_base, context->video_stream->time_base);
182# ifdef FFMPEG_USE_DURATION_WORKAROUND
183 my_guess_pkt_duration(context->outfile, context->video_stream, packet);
184# endif
185
186 if (av_interleaved_write_frame(context->outfile, packet) != 0) {
187 success = -1;
188 break;
189 }
190 }
191
192 if (!success) {
193 BKE_report(reports, RPT_ERROR, "Error writing frame");
194 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
195 FF_DEBUG_PRINT("ffmpeg: error writing video frame: %s\n", error_str);
196 }
197
198 av_packet_free(&packet);
199
200 return success;
201}
202
203/* read and encode a frame of video from the buffer */
204static AVFrame *generate_video_frame(MovieWriter *context, const ImBuf *image)
205{
206 const uint8_t *pixels = image->byte_buffer.data;
207 const float *pixels_fl = image->float_buffer.data;
208 /* Use float input if needed. */
209 const bool use_float = context->img_convert_frame != nullptr &&
210 context->img_convert_frame->format != AV_PIX_FMT_RGBA;
211 if ((!use_float && (pixels == nullptr)) || (use_float && (pixels_fl == nullptr))) {
212 return nullptr;
213 }
214
215 AVCodecParameters *codec = context->video_stream->codecpar;
216 int height = codec->height;
217 AVFrame *rgb_frame;
218
219 if (context->img_convert_frame != nullptr) {
220 /* Pixel format conversion is needed. */
221 rgb_frame = context->img_convert_frame;
222 }
223 else {
224 /* The output pixel format is Blender's internal pixel format. */
225 rgb_frame = context->current_frame;
226 }
227
228 /* Ensure frame is writable. Some video codecs might have made previous frame
229 * shared (i.e. not writable). */
230 av_frame_make_writable(rgb_frame);
231
232 const size_t linesize_dst = rgb_frame->linesize[0];
233 if (use_float) {
234 /* Float image: need to split up the image into a planar format,
235 * because `libswscale` does not support RGBA->YUV conversions from
236 * packed float formats.
237 * Un-premultiply the image if the output format supports alpha, to
238 * match the format of the byte image. */
239 BLI_assert_msg(rgb_frame->linesize[1] == linesize_dst &&
240 rgb_frame->linesize[2] == linesize_dst &&
241 rgb_frame->linesize[3] == linesize_dst,
242 "ffmpeg frame should be 4 same size planes for a floating point image case");
243 for (int y = 0; y < height; y++) {
244 size_t dst_offset = linesize_dst * (height - y - 1);
245 float *dst_g = reinterpret_cast<float *>(rgb_frame->data[0] + dst_offset);
246 float *dst_b = reinterpret_cast<float *>(rgb_frame->data[1] + dst_offset);
247 float *dst_r = reinterpret_cast<float *>(rgb_frame->data[2] + dst_offset);
248 float *dst_a = reinterpret_cast<float *>(rgb_frame->data[3] + dst_offset);
249 const float *src = pixels_fl + image->x * y * 4;
250
251 if (MOV_codec_supports_alpha(context->ffmpeg_codec, context->ffmpeg_profile)) {
252 for (int x = 0; x < image->x; x++) {
253 float tmp[4];
254 premul_to_straight_v4_v4(tmp, src);
255 *dst_r++ = tmp[0];
256 *dst_g++ = tmp[1];
257 *dst_b++ = tmp[2];
258 *dst_a++ = tmp[3];
259 src += 4;
260 }
261 }
262 else {
263 for (int x = 0; x < image->x; x++) {
264 *dst_r++ = src[0];
265 *dst_g++ = src[1];
266 *dst_b++ = src[2];
267 *dst_a++ = src[3];
268 src += 4;
269 }
270 }
271 }
272 }
273 else {
274 /* Byte image: flip the image vertically, possibly with endian
275 * conversion. */
276 const size_t linesize_src = rgb_frame->width * 4;
277 for (int y = 0; y < height; y++) {
278 uint8_t *target = rgb_frame->data[0] + linesize_dst * (height - y - 1);
279 const uint8_t *src = pixels + linesize_src * y;
280
281# if ENDIAN_ORDER == L_ENDIAN
282 memcpy(target, src, linesize_src);
283
284# elif ENDIAN_ORDER == B_ENDIAN
285 const uint8_t *end = src + linesize_src;
286 while (src != end) {
287 target[3] = src[0];
288 target[2] = src[1];
289 target[1] = src[2];
290 target[0] = src[3];
291
292 target += 4;
293 src += 4;
294 }
295# else
296# error ENDIAN_ORDER should either be L_ENDIAN or B_ENDIAN.
297# endif
298 }
299 }
300
301 /* Convert to the output pixel format, if it's different that Blender's internal one. */
302 if (context->img_convert_frame != nullptr) {
303 BLI_assert(context->img_convert_ctx != nullptr);
304 /* Ensure the frame we are scaling to is writable as well. */
305 av_frame_make_writable(context->current_frame);
306 ffmpeg_sws_scale_frame(context->img_convert_ctx, context->current_frame, rgb_frame);
307 }
308
309 return context->current_frame;
310}
311
312static AVRational calc_time_base(uint den, double num, AVCodecID codec_id)
313{
314 /* Convert the input 'num' to an integer. Simply shift the decimal places until we get an integer
315 * (within a floating point error range).
316 * For example if we have `den = 3` and `num = 0.1` then the fps is: `den/num = 30` fps.
317 * When converting this to a FFMPEG time base, we want num to be an integer.
318 * So we simply move the decimal places of both numbers. i.e. `den = 30`, `num = 1`. */
319 float eps = FLT_EPSILON;
320 const uint DENUM_MAX = (codec_id == AV_CODEC_ID_MPEG4) ? (1UL << 16) - 1 : (1UL << 31) - 1;
321
322 /* Calculate the precision of the initial floating point number. */
323 if (num > 1.0) {
324 const uint num_integer_bits = log2_floor_u(uint(num));
325
326 /* Formula for calculating the epsilon value: (power of two range) / (pow mantissa bits)
327 * For example, a float has 23 mantissa bits and the float value 3.5f as a pow2 range of
328 * (4-2=2):
329 * (2) / pow2(23) = floating point precision for 3.5f
330 */
331 eps = float(1 << num_integer_bits) * FLT_EPSILON;
332 }
333
334 /* Calculate how many decimal shifts we can do until we run out of precision. */
335 const int max_num_shift = fabsf(log10f(eps));
336 /* Calculate how many times we can shift the denominator. */
337 const int max_den_shift = log10f(DENUM_MAX) - log10f(den);
338 const int max_iter = min_ii(max_num_shift, max_den_shift);
339
340 for (int i = 0; i < max_iter && fabs(num - round(num)) > eps; i++) {
341 /* Increase the number and denominator until both are integers. */
342 num *= 10;
343 den *= 10;
344 eps *= 10;
345 }
346
347 AVRational time_base;
348 time_base.den = den;
349 time_base.num = int(num);
350
351 return time_base;
352}
353
354static const AVCodec *get_av1_encoder(
355 MovieWriter *context, RenderData *rd, AVDictionary **opts, int rectx, int recty)
356{
357 /* There are three possible encoders for AV1: `libaom-av1`, librav1e, and `libsvtav1`. librav1e
358 * tends to give the best compression quality while `libsvtav1` tends to be the fastest encoder.
359 * One of each will be picked based on the preset setting, and if a particular encoder is not
360 * available, then use the default returned by FFMpeg. */
361 const AVCodec *codec = nullptr;
362 switch (context->ffmpeg_preset) {
363 case FFM_PRESET_BEST:
364 /* `libaom-av1` may produce better VMAF-scoring videos in several cases, but there are cases
365 * where using a different encoder is desirable, such as in #103849. */
366 codec = avcodec_find_encoder_by_name("librav1e");
367 if (!codec) {
368 /* Fall back to `libaom-av1` if librav1e is not found. */
369 codec = avcodec_find_encoder_by_name("libaom-av1");
370 }
371 break;
373 codec = avcodec_find_encoder_by_name("libsvtav1");
374 break;
375 case FFM_PRESET_GOOD:
376 default:
377 codec = avcodec_find_encoder_by_name("libaom-av1");
378 break;
379 }
380
381 /* Use the default AV1 encoder if the specified encoder wasn't found. */
382 if (!codec) {
383 codec = avcodec_find_encoder(AV_CODEC_ID_AV1);
384 }
385
386 /* Apply AV1 encoder specific settings. */
387 if (codec) {
388 if (STREQ(codec->name, "librav1e")) {
389 /* Set "tiles" to 8 to enable multi-threaded encoding. */
390 if (rd->threads > 8) {
391 ffmpeg_dict_set_int(opts, "tiles", rd->threads);
392 }
393 else {
394 ffmpeg_dict_set_int(opts, "tiles", 8);
395 }
396
397 /* Use a reasonable speed setting based on preset. Speed ranges from 0-10.
398 * Must check context->ffmpeg_preset again in case this encoder was selected due to the
399 * absence of another. */
400 switch (context->ffmpeg_preset) {
401 case FFM_PRESET_BEST:
402 ffmpeg_dict_set_int(opts, "speed", 4);
403 break;
405 ffmpeg_dict_set_int(opts, "speed", 10);
406 break;
407 case FFM_PRESET_GOOD:
408 default:
409 ffmpeg_dict_set_int(opts, "speed", 6);
410 break;
411 }
412 /* Set gop_size as rav1e's "--keyint". */
413 char buffer[64];
414 SNPRINTF(buffer, "keyint=%d", context->ffmpeg_gop_size);
415 av_dict_set(opts, "rav1e-params", buffer, 0);
416 }
417 else if (STREQ(codec->name, "libsvtav1")) {
418 /* Set preset value based on ffmpeg_preset.
419 * Must check `context->ffmpeg_preset` again in case this encoder was selected due to the
420 * absence of another. */
421 switch (context->ffmpeg_preset) {
423 ffmpeg_dict_set_int(opts, "preset", 8);
424 break;
425 case FFM_PRESET_BEST:
426 ffmpeg_dict_set_int(opts, "preset", 3);
427 break;
428 case FFM_PRESET_GOOD:
429 default:
430 ffmpeg_dict_set_int(opts, "preset", 5);
431 break;
432 }
433 }
434 else if (STREQ(codec->name, "libaom-av1")) {
435 /* Speed up libaom-av1 encoding by enabling multi-threading and setting tiles. */
436 ffmpeg_dict_set_int(opts, "row-mt", 1);
437 const char *tiles_string = nullptr;
438 bool tiles_string_is_dynamic = false;
439 if (rd->threads > 0) {
440 /* See if threads is a square. */
441 int threads_sqrt = sqrtf(rd->threads);
442 if (threads_sqrt < 4) {
443 /* Ensure a default minimum. */
444 threads_sqrt = 4;
445 }
446 if (is_power_of_2_i(threads_sqrt) && threads_sqrt * threads_sqrt == rd->threads) {
447 /* Is a square num, therefore just do "sqrt x sqrt" for tiles parameter. */
448 int digits = 0;
449 for (int t_sqrt_copy = threads_sqrt; t_sqrt_copy > 0; t_sqrt_copy /= 10) {
450 ++digits;
451 }
452 /* A char array need only an alignment of 1. */
453 char *tiles_string_mut = (char *)calloc(digits * 2 + 2, 1);
454 BLI_snprintf(tiles_string_mut, digits * 2 + 2, "%dx%d", threads_sqrt, threads_sqrt);
455 tiles_string_is_dynamic = true;
456 tiles_string = tiles_string_mut;
457 }
458 else {
459 /* Is not a square num, set greater side based on longer side, or use a square if both
460 * sides are equal. */
461 int sqrt_p2 = power_of_2_min_i(threads_sqrt);
462 if (sqrt_p2 < 2) {
463 /* Ensure a default minimum. */
464 sqrt_p2 = 2;
465 }
466 int sqrt_p2_next = power_of_2_min_i(int(rd->threads) / sqrt_p2);
467 if (sqrt_p2_next < 1) {
468 sqrt_p2_next = 1;
469 }
470 if (sqrt_p2 > sqrt_p2_next) {
471 /* Ensure sqrt_p2_next is greater or equal to sqrt_p2. */
472 int temp = sqrt_p2;
473 sqrt_p2 = sqrt_p2_next;
474 sqrt_p2_next = temp;
475 }
476 int combined_digits = 0;
477 for (int sqrt_p2_copy = sqrt_p2; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) {
478 ++combined_digits;
479 }
480 for (int sqrt_p2_copy = sqrt_p2_next; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) {
481 ++combined_digits;
482 }
483 /* A char array need only an alignment of 1. */
484 char *tiles_string_mut = (char *)calloc(combined_digits + 2, 1);
485 if (rectx > recty) {
486 BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2_next, sqrt_p2);
487 }
488 else if (rectx < recty) {
489 BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2, sqrt_p2_next);
490 }
491 else {
492 BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2, sqrt_p2);
493 }
494 tiles_string_is_dynamic = true;
495 tiles_string = tiles_string_mut;
496 }
497 }
498 else {
499 /* Thread count unknown, default to 8. */
500 if (rectx > recty) {
501 tiles_string = "4x2";
502 }
503 else if (rectx < recty) {
504 tiles_string = "2x4";
505 }
506 else {
507 tiles_string = "2x2";
508 }
509 }
510 av_dict_set(opts, "tiles", tiles_string, 0);
511 if (tiles_string_is_dynamic) {
512 free((void *)tiles_string);
513 }
514 /* libaom-av1 uses "cpu-used" instead of "preset" for defining compression quality.
515 * This value is in a range from 0-8. 0 and 8 are extremes, but we will allow 8.
516 * Must check context->ffmpeg_preset again in case this encoder was selected due to the
517 * absence of another. */
518 switch (context->ffmpeg_preset) {
520 ffmpeg_dict_set_int(opts, "cpu-used", 8);
521 break;
522 case FFM_PRESET_BEST:
523 ffmpeg_dict_set_int(opts, "cpu-used", 4);
524 break;
525 case FFM_PRESET_GOOD:
526 default:
527 ffmpeg_dict_set_int(opts, "cpu-used", 6);
528 break;
529 }
530 }
531 }
532
533 return codec;
534}
535
536/* Remap H.264 CRF to H.265 CRF: 17..32 range (23 default) to 20..37 range (28 default).
537 * https://trac.ffmpeg.org/wiki/Encode/H.265 */
538static int remap_crf_to_h265_crf(int crf, bool is_10_or_12_bpp)
539{
540 /* 10/12 bit videos seem to need slightly lower CRF value for similar quality. */
541 const int bias = is_10_or_12_bpp ? -3 : 0;
542 switch (crf) {
544 return 20 + bias;
545 case FFM_CRF_HIGH:
546 return 24 + bias;
547 case FFM_CRF_MEDIUM:
548 return 28 + bias;
549 case FFM_CRF_LOW:
550 return 31 + bias;
551 case FFM_CRF_VERYLOW:
552 return 34 + bias;
553 case FFM_CRF_LOWEST:
554 return 37 + bias;
555 }
556 return crf;
557}
558
559static const AVCodec *get_prores_encoder(RenderData *rd, int rectx, int recty)
560{
561 /* The prores_aw encoder currently (April 2025) has issues when encoding alpha with high
562 * resolution but is faster in most cases for similar quality. Use it instead of prores_ks
563 * if possible. (Upstream issue https://trac.ffmpeg.org/ticket/11536) */
565 if ((size_t(rectx) * size_t(recty)) > (3840 * 2160)) {
566 return avcodec_find_encoder_by_name("prores_ks");
567 }
568 }
569 return avcodec_find_encoder_by_name("prores_aw");
570}
571
572/* 10bpp H264: remap 0..51 range to -12..51 range
573 * https://trac.ffmpeg.org/wiki/Encode/H.264#a1.ChooseaCRFvalue */
574static int remap_crf_to_h264_10bpp_crf(int crf)
575{
576 crf = int(-12.0f + (crf / 51.0f) * 63.0f);
577 crf = max_ii(crf, 0);
578 return crf;
579}
580
581static void set_quality_rate_options(const MovieWriter *context,
582 const AVCodecID codec_id,
583 const RenderData *rd,
584 AVDictionary **opts)
585{
586 AVCodecContext *c = context->video_codec;
587
588 /* Handle constant bit rate (CBR) case. */
589 if (!MOV_codec_supports_crf(codec_id) || context->ffmpeg_crf < 0) {
590 c->bit_rate = context->ffmpeg_video_bitrate * 1000;
591 c->rc_max_rate = rd->ffcodecdata.rc_max_rate * 1000;
592 c->rc_min_rate = rd->ffcodecdata.rc_min_rate * 1000;
593 c->rc_buffer_size = rd->ffcodecdata.rc_buffer_size * 1024;
594 return;
595 }
596
597 /* For VP9 bit rate must be set to zero to get CRF mode, just set it to zero for all codecs:
598 * https://trac.ffmpeg.org/wiki/Encode/VP9 */
599 c->bit_rate = 0;
600
601 const bool is_10_bpp = rd->im_format.depth == R_IMF_CHAN_DEPTH_10;
602 const bool is_12_bpp = rd->im_format.depth == R_IMF_CHAN_DEPTH_12;
603 const bool av1_librav1e = codec_id == AV_CODEC_ID_AV1 && STREQ(c->codec->name, "librav1e");
604 const bool av1_libsvtav1 = codec_id == AV_CODEC_ID_AV1 && STREQ(c->codec->name, "libsvtav1");
605
606 /* Handle "lossless" case. */
607 if (context->ffmpeg_crf == FFM_CRF_LOSSLESS) {
608 if (codec_id == AV_CODEC_ID_VP9) {
609 /* VP9 needs "lossless": https://trac.ffmpeg.org/wiki/Encode/VP9#LosslessVP9 */
610 ffmpeg_dict_set_int(opts, "lossless", 1);
611 }
612 else if (codec_id == AV_CODEC_ID_H264 && is_10_bpp) {
613 /* 10bpp H264 needs "qp": https://trac.ffmpeg.org/wiki/Encode/H.264#a1.ChooseaCRFvalue */
614 ffmpeg_dict_set_int(opts, "qp", 0);
615 }
616 else if (codec_id == AV_CODEC_ID_H265) {
617 /* H.265 needs "lossless" in private params; also make it much less verbose. */
618 av_dict_set(opts, "x265-params", "log-level=1:lossless=1", 0);
619 }
620 else if (codec_id == AV_CODEC_ID_AV1 && (av1_librav1e || av1_libsvtav1)) {
621 /* AV1 in some encoders needs qp=0 for lossless. */
622 ffmpeg_dict_set_int(opts, "qp", 0);
623 }
624 else {
625 /* For others crf=0 means lossless. */
626 ffmpeg_dict_set_int(opts, "crf", 0);
627 }
628 return;
629 }
630
631 /* Handle CRF setting cases. */
632 int crf = context->ffmpeg_crf;
633
634 if (codec_id == AV_CODEC_ID_H264 && is_10_bpp) {
635 crf = remap_crf_to_h264_10bpp_crf(crf);
636 }
637 else if (codec_id == AV_CODEC_ID_H265) {
638 crf = remap_crf_to_h265_crf(crf, is_10_bpp || is_12_bpp);
639 /* Make H.265 much less verbose. */
640 av_dict_set(opts, "x265-params", "log-level=1", 0);
641 }
642
643 if (av1_librav1e) {
644 /* Remap crf 0..51 to qp 0..255 for AV1 librav1e. */
645 int qp = int(float(crf) / 51.0f * 255.0f);
646 qp = clamp_i(qp, 0, 255);
647 ffmpeg_dict_set_int(opts, "qp", qp);
648 }
649 else if (av1_libsvtav1) {
650 /* libsvtav1 used to take CRF as "qp" parameter, do that. */
651 ffmpeg_dict_set_int(opts, "qp", crf);
652 }
653 else {
654 ffmpeg_dict_set_int(opts, "crf", crf);
655 }
656}
657
658static AVStream *alloc_video_stream(MovieWriter *context,
659 RenderData *rd,
660 AVCodecID codec_id,
661 AVFormatContext *of,
662 int rectx,
663 int recty,
664 char *error,
665 int error_size)
666{
667 AVStream *st;
668 const AVCodec *codec;
669 AVDictionary *opts = nullptr;
670
671 error[0] = '\0';
672
673 st = avformat_new_stream(of, nullptr);
674 if (!st) {
675 return nullptr;
676 }
677 st->id = 0;
678
679 /* Set up the codec context */
680
681 if (codec_id == AV_CODEC_ID_AV1) {
682 /* Use get_av1_encoder() to get the ideal (hopefully) encoder for AV1 based
683 * on given parameters, and also set up opts. */
684 codec = get_av1_encoder(context, rd, &opts, rectx, recty);
685 }
686 else if (codec_id == AV_CODEC_ID_PRORES) {
687 codec = get_prores_encoder(rd, rectx, recty);
688 }
689 else {
690 codec = avcodec_find_encoder(codec_id);
691 }
692 if (!codec) {
693 fprintf(stderr, "Couldn't find valid video codec\n");
694 context->video_codec = nullptr;
695 return nullptr;
696 }
697
698 context->video_codec = avcodec_alloc_context3(codec);
699 AVCodecContext *c = context->video_codec;
700
701 /* Get some values from the current render settings */
702
703 c->width = rectx;
704 c->height = recty;
705
706 if (context->ffmpeg_type == FFMPEG_DV && rd->frs_sec != 25) {
707 /* FIXME: Really bad hack (tm) for NTSC support */
708 c->time_base.den = 2997;
709 c->time_base.num = 100;
710 }
711 else if (float(int(rd->frs_sec_base)) == rd->frs_sec_base) {
712 c->time_base.den = rd->frs_sec;
713 c->time_base.num = int(rd->frs_sec_base);
714 }
715 else {
716 c->time_base = calc_time_base(rd->frs_sec, rd->frs_sec_base, codec_id);
717 }
718
719 /* As per the time-base documentation here:
720 * https://www.ffmpeg.org/ffmpeg-codecs.html#Codec-Options
721 * We want to set the time base to (1 / fps) for fixed frame rate video.
722 * If it is not possible, we want to set the time-base numbers to something as
723 * small as possible.
724 */
725 if (c->time_base.num != 1) {
726 AVRational new_time_base;
727 if (av_reduce(
728 &new_time_base.num, &new_time_base.den, c->time_base.num, c->time_base.den, INT_MAX))
729 {
730 /* Exact reduction was possible. Use the new value. */
731 c->time_base = new_time_base;
732 }
733 }
734
735 st->time_base = c->time_base;
736
737 c->gop_size = context->ffmpeg_gop_size;
738 c->max_b_frames = context->ffmpeg_max_b_frames;
739
740 set_quality_rate_options(context, codec_id, rd, &opts);
741
742 if (context->ffmpeg_preset) {
743 /* 'preset' is used by h.264, 'deadline' is used by WEBM/VP9. I'm not
744 * setting those properties conditionally based on the video codec,
745 * as the FFmpeg encoder simply ignores unknown settings anyway. */
746 char const *preset_name = nullptr; /* Used by h.264. */
747 char const *deadline_name = nullptr; /* Used by WEBM/VP9. */
748 switch (context->ffmpeg_preset) {
749 case FFM_PRESET_GOOD:
750 preset_name = "medium";
751 deadline_name = "good";
752 break;
753 case FFM_PRESET_BEST:
754 preset_name = "slower";
755 deadline_name = "best";
756 break;
758 preset_name = "superfast";
759 deadline_name = "realtime";
760 break;
761 default:
762 printf("Unknown preset number %i, ignoring.\n", context->ffmpeg_preset);
763 }
764 /* "codec_id != AV_CODEC_ID_AV1" is required due to "preset" already being set by an AV1 codec.
765 */
766 if (preset_name != nullptr && codec_id != AV_CODEC_ID_AV1) {
767 av_dict_set(&opts, "preset", preset_name, 0);
768 }
769 if (deadline_name != nullptr) {
770 av_dict_set(&opts, "deadline", deadline_name, 0);
771 }
772 }
773
774 /* Be sure to use the correct pixel format(e.g. RGB, YUV) */
775
776 const enum AVPixelFormat *pix_fmts = ffmpeg_get_pix_fmts(c, codec);
777 if (pix_fmts) {
778 c->pix_fmt = pix_fmts[0];
779 }
780 else {
781 /* makes HuffYUV happy ... */
782 c->pix_fmt = AV_PIX_FMT_YUV422P;
783 }
784
785 const bool is_10_bpp = rd->im_format.depth == R_IMF_CHAN_DEPTH_10;
786 const bool is_12_bpp = rd->im_format.depth == R_IMF_CHAN_DEPTH_12;
787 const bool is_16_bpp = rd->im_format.depth == R_IMF_CHAN_DEPTH_16;
788 if (is_10_bpp) {
789 c->pix_fmt = AV_PIX_FMT_YUV420P10LE;
790 }
791 else if (is_12_bpp) {
792 c->pix_fmt = AV_PIX_FMT_YUV420P12LE;
793 }
794
795 if (context->ffmpeg_type == FFMPEG_XVID) {
796 /* Alas! */
797 c->pix_fmt = AV_PIX_FMT_YUV420P;
798 c->codec_tag = (('D' << 24) + ('I' << 16) + ('V' << 8) + 'X');
799 }
800
801 if (codec_id == AV_CODEC_ID_H265) {
802 /* H.265 needs hvc1 tag for Apple compatibility, see
803 * https://trac.ffmpeg.org/wiki/Encode/H.265#FinalCutandApplestuffcompatibility
804 * Note that in case we are doing H.265 into an XviD container,
805 * this overwrites the tag set above. But that should not be what anyone does. */
806 c->codec_tag = MKTAG('h', 'v', 'c', '1');
807 }
808
809 /* Keep lossless encodes in the RGB domain. */
810 if (codec_id == AV_CODEC_ID_HUFFYUV) {
812 c->pix_fmt = AV_PIX_FMT_BGRA;
813 }
814 else {
815 c->pix_fmt = AV_PIX_FMT_RGB32;
816 }
817 }
818
819 if (codec_id == AV_CODEC_ID_DNXHD) {
821 /* Set the block decision algorithm to be of the highest quality ("rd" == 2). */
822 c->mb_decision = 2;
823 }
824 }
825
826 if (codec_id == AV_CODEC_ID_FFV1) {
827 if (rd->im_format.planes == R_IMF_PLANES_BW) {
828 c->pix_fmt = AV_PIX_FMT_GRAY8;
829 if (is_10_bpp) {
830 c->pix_fmt = AV_PIX_FMT_GRAY10;
831 }
832 else if (is_12_bpp) {
833 c->pix_fmt = AV_PIX_FMT_GRAY12;
834 }
835 else if (is_16_bpp) {
836 c->pix_fmt = AV_PIX_FMT_GRAY16;
837 }
838 }
839 else if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
840 c->pix_fmt = AV_PIX_FMT_RGB32;
841 if (is_10_bpp) {
842 c->pix_fmt = AV_PIX_FMT_GBRAP10;
843 }
844 else if (is_12_bpp) {
845 c->pix_fmt = AV_PIX_FMT_GBRAP12;
846 }
847 else if (is_16_bpp) {
848 c->pix_fmt = AV_PIX_FMT_GBRAP16;
849 }
850 }
851 else { /* RGB */
852 c->pix_fmt = AV_PIX_FMT_0RGB32;
853 if (is_10_bpp) {
854 c->pix_fmt = AV_PIX_FMT_GBRP10;
855 }
856 else if (is_12_bpp) {
857 c->pix_fmt = AV_PIX_FMT_GBRP12;
858 }
859 else if (is_16_bpp) {
860 c->pix_fmt = AV_PIX_FMT_GBRP16;
861 }
862 }
863 }
864
865 if (codec_id == AV_CODEC_ID_QTRLE) {
866 if (rd->im_format.planes == R_IMF_PLANES_BW) {
867 c->pix_fmt = AV_PIX_FMT_GRAY8;
868 }
869 else if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
870 c->pix_fmt = AV_PIX_FMT_ARGB;
871 }
872 else { /* RGB */
873 c->pix_fmt = AV_PIX_FMT_RGB24;
874 }
875 }
876
877 if (codec_id == AV_CODEC_ID_VP9 && rd->im_format.planes == R_IMF_PLANES_RGBA) {
878 c->pix_fmt = AV_PIX_FMT_YUVA420P;
879 }
880 else if (ELEM(codec_id, AV_CODEC_ID_H264, AV_CODEC_ID_H265, AV_CODEC_ID_VP9, AV_CODEC_ID_AV1) &&
881 (context->ffmpeg_crf == 0))
882 {
883 /* Use 4:4:4 instead of 4:2:0 pixel format for lossless rendering. */
884 c->pix_fmt = AV_PIX_FMT_YUV444P;
885 if (is_10_bpp) {
886 c->pix_fmt = AV_PIX_FMT_YUV444P10LE;
887 }
888 else if (is_12_bpp) {
889 c->pix_fmt = AV_PIX_FMT_YUV444P12LE;
890 }
891 }
892
893 if (codec_id == AV_CODEC_ID_PNG) {
894 if (rd->im_format.planes == R_IMF_PLANES_BW) {
895 c->pix_fmt = AV_PIX_FMT_GRAY8;
896 }
897 else if (rd->im_format.planes == R_IMF_PLANES_RGBA) {
898 c->pix_fmt = AV_PIX_FMT_RGBA;
899 }
900 else { /* RGB */
901 c->pix_fmt = AV_PIX_FMT_RGB24;
902 }
903 }
904 if (codec_id == AV_CODEC_ID_PRORES) {
905 if ((context->ffmpeg_profile >= FFM_PRORES_PROFILE_422_PROXY) &&
906 (context->ffmpeg_profile <= FFM_PRORES_PROFILE_422_HQ))
907 {
908 c->profile = context->ffmpeg_profile;
909 c->pix_fmt = AV_PIX_FMT_YUV422P10LE;
910 }
911 else if ((context->ffmpeg_profile >= FFM_PRORES_PROFILE_4444) &&
912 (context->ffmpeg_profile <= FFM_PRORES_PROFILE_4444_XQ))
913 {
914 c->profile = context->ffmpeg_profile;
915 c->pix_fmt = AV_PIX_FMT_YUV444P10LE;
916
918 c->pix_fmt = AV_PIX_FMT_YUVA444P10LE;
919 }
920 }
921 else {
922 fprintf(stderr, "ffmpeg: invalid profile %d\n", context->ffmpeg_profile);
923 }
924 }
925
926 if (of->oformat->flags & AVFMT_GLOBALHEADER) {
927 FF_DEBUG_PRINT("ffmpeg: using global video header\n");
928 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
929 }
930
931 /* If output pixel format is not RGB(A), setup colorspace metadata. */
932 const AVPixFmtDescriptor *pix_fmt_desc = av_pix_fmt_desc_get(c->pix_fmt);
933 const bool set_bt709 = (pix_fmt_desc->flags & AV_PIX_FMT_FLAG_RGB) == 0;
934 if (set_bt709) {
935 c->color_range = AVCOL_RANGE_MPEG;
936 c->color_primaries = AVCOL_PRI_BT709;
937 c->color_trc = AVCOL_TRC_BT709;
938 c->colorspace = AVCOL_SPC_BT709;
939 }
940
941 /* xasp & yasp got float lately... */
942
943 st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q((double(rd->xasp) / double(rd->yasp)),
944 255);
945 st->avg_frame_rate = av_inv_q(c->time_base);
946
947 if (codec->capabilities & AV_CODEC_CAP_OTHER_THREADS) {
948 c->thread_count = 0;
949 }
950 else {
951 c->thread_count = BLI_system_thread_count();
952 }
953
954 if (codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) {
955 c->thread_type = FF_THREAD_FRAME;
956 }
957 else if (codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
958 c->thread_type = FF_THREAD_SLICE;
959 }
960
961 int ret = avcodec_open2(c, codec, &opts);
962
963 if (ret < 0) {
964 char error_str[AV_ERROR_MAX_STRING_SIZE];
965 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
966 fprintf(stderr, "Couldn't initialize video codec: %s\n", error_str);
967 BLI_strncpy(error, ffmpeg_last_error(), error_size);
968 av_dict_free(&opts);
969 avcodec_free_context(&c);
970 context->video_codec = nullptr;
971 return nullptr;
972 }
973 av_dict_free(&opts);
974
975 /* FFMPEG expects its data in the output pixel format. */
976 context->current_frame = alloc_frame(c->pix_fmt, c->width, c->height);
977
978 if (c->pix_fmt == AV_PIX_FMT_RGBA) {
979 /* Output pixel format is the same we use internally, no conversion necessary. */
980 context->img_convert_frame = nullptr;
981 context->img_convert_ctx = nullptr;
982 }
983 else {
984 /* Output pixel format is different, allocate frame for conversion. */
985 AVPixelFormat src_format = is_10_bpp || is_12_bpp || is_16_bpp ? AV_PIX_FMT_GBRAPF32LE :
986 AV_PIX_FMT_RGBA;
987 context->img_convert_frame = alloc_frame(src_format, c->width, c->height);
988 /* Setup BT.709 coefficients for RGB->YUV conversion, if needed. */
989 context->img_convert_ctx = ffmpeg_sws_get_context(c->width,
990 c->height,
991 src_format,
992 false,
993 -1,
994 c->width,
995 c->height,
996 c->pix_fmt,
997 false,
998 set_bt709 ? AVCOL_SPC_BT709 : -1,
999 SWS_BICUBIC);
1000 }
1001
1002 avcodec_parameters_from_context(st->codecpar, c);
1003
1004 context->video_time = 0.0f;
1005
1006 return st;
1007}
1008
1009static void ffmpeg_add_metadata_callback(void *data,
1010 const char *propname,
1011 char *propvalue,
1012 int /*propvalue_maxncpy*/)
1013{
1014 AVDictionary **metadata = (AVDictionary **)data;
1015 av_dict_set(metadata, propname, propvalue, 0);
1016}
1017
1018static bool start_ffmpeg_impl(MovieWriter *context,
1019 RenderData *rd,
1020 int rectx,
1021 int recty,
1022 const char *suffix,
1024{
1025 /* Handle to the output file */
1026 AVFormatContext *of;
1027 const AVOutputFormat *fmt;
1028 char filepath[FILE_MAX], error[1024];
1029 const char **exts;
1030 int ret = 0;
1031
1032 context->ffmpeg_type = rd->ffcodecdata.type;
1033 context->ffmpeg_codec = mov_av_codec_id_get(rd->ffcodecdata.codec_id_get());
1034 context->ffmpeg_audio_codec = mov_av_codec_id_get(rd->ffcodecdata.audio_codec_id_get());
1035 context->ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate;
1036 context->ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate;
1037 context->ffmpeg_gop_size = rd->ffcodecdata.gop_size;
1038 context->ffmpeg_autosplit = (rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT) != 0;
1039 context->ffmpeg_crf = rd->ffcodecdata.constant_rate_factor;
1040 context->ffmpeg_preset = rd->ffcodecdata.ffmpeg_preset;
1041 context->ffmpeg_profile = 0;
1042
1043 if ((rd->ffcodecdata.flags & FFMPEG_USE_MAX_B_FRAMES) != 0) {
1044 context->ffmpeg_max_b_frames = rd->ffcodecdata.max_b_frames;
1045 }
1046
1047 /* Determine the correct filename */
1048 if (!ffmpeg_filepath_get(context, filepath, rd, context->ffmpeg_preview, suffix, reports)) {
1049 return false;
1050 }
1051 FF_DEBUG_PRINT(
1052 "ffmpeg: starting output to %s:\n"
1053 " type=%d, codec=%d, audio_codec=%d,\n"
1054 " video_bitrate=%d, audio_bitrate=%d,\n"
1055 " gop_size=%d, autosplit=%d\n"
1056 " width=%d, height=%d\n",
1057 filepath,
1058 context->ffmpeg_type,
1059 context->ffmpeg_codec,
1060 context->ffmpeg_audio_codec,
1061 context->ffmpeg_video_bitrate,
1062 context->ffmpeg_audio_bitrate,
1063 context->ffmpeg_gop_size,
1064 context->ffmpeg_autosplit,
1065 rectx,
1066 recty);
1067
1068 /* Sanity checks for the output file extensions. */
1069 exts = get_file_extensions(context->ffmpeg_type);
1070 if (!exts) {
1071 BKE_report(reports, RPT_ERROR, "No valid formats found");
1072 return false;
1073 }
1074
1075 fmt = av_guess_format(nullptr, exts[0], nullptr);
1076 if (!fmt) {
1077 BKE_report(reports, RPT_ERROR, "No valid formats found");
1078 return false;
1079 }
1080
1081 of = avformat_alloc_context();
1082 if (!of) {
1083 BKE_report(reports, RPT_ERROR, "Can't allocate FFmpeg format context");
1084 return false;
1085 }
1086
1087 enum AVCodecID audio_codec = context->ffmpeg_audio_codec;
1088 enum AVCodecID video_codec = context->ffmpeg_codec;
1089
1090 of->url = av_strdup(filepath);
1091 /* Check if we need to force change the codec because of file type codec restrictions */
1092 switch (context->ffmpeg_type) {
1093 case FFMPEG_OGG:
1094 video_codec = AV_CODEC_ID_THEORA;
1095 break;
1096 case FFMPEG_DV:
1097 video_codec = AV_CODEC_ID_DVVIDEO;
1098 break;
1099 case FFMPEG_MPEG1:
1100 video_codec = AV_CODEC_ID_MPEG1VIDEO;
1101 break;
1102 case FFMPEG_MPEG2:
1103 video_codec = AV_CODEC_ID_MPEG2VIDEO;
1104 break;
1105 case FFMPEG_H264:
1106 video_codec = AV_CODEC_ID_H264;
1107 break;
1108 case FFMPEG_XVID:
1109 video_codec = AV_CODEC_ID_MPEG4;
1110 break;
1111 case FFMPEG_FLV:
1112 video_codec = AV_CODEC_ID_FLV1;
1113 break;
1114 case FFMPEG_AV1:
1115 video_codec = AV_CODEC_ID_AV1;
1116 break;
1117 default:
1118 /* These containers are not restricted to any specific codec types.
1119 * Currently we expect these to be `.avi`, `.mov`, `.mkv`, and `.mp4`. */
1120 video_codec = context->ffmpeg_codec;
1121 break;
1122 }
1123
1124 /* Returns after this must 'goto fail;' */
1125
1126# if LIBAVFORMAT_VERSION_MAJOR >= 59
1127 of->oformat = fmt;
1128# else
1129 /* *DEPRECATED* 2022/08/01 For FFMPEG (<5.0) remove this else branch and the `ifdef` above. */
1130 of->oformat = (AVOutputFormat *)fmt;
1131# endif
1132
1133 if (video_codec == AV_CODEC_ID_DVVIDEO) {
1134 if (rectx != 720) {
1135 BKE_report(reports, RPT_ERROR, "Render width has to be 720 pixels for DV!");
1136 goto fail;
1137 }
1138 if (rd->frs_sec != 25 && recty != 480) {
1139 BKE_report(reports, RPT_ERROR, "Render height has to be 480 pixels for DV-NTSC!");
1140 goto fail;
1141 }
1142 if (rd->frs_sec == 25 && recty != 576) {
1143 BKE_report(reports, RPT_ERROR, "Render height has to be 576 pixels for DV-PAL!");
1144 goto fail;
1145 }
1146 }
1147
1148 if (context->ffmpeg_type == FFMPEG_DV) {
1149 audio_codec = AV_CODEC_ID_PCM_S16LE;
1150 if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE &&
1151 rd->ffcodecdata.audio_mixrate != 48000 && rd->ffcodecdata.audio_channels != 2)
1152 {
1153 BKE_report(reports, RPT_ERROR, "FFmpeg only supports 48khz / stereo audio for DV!");
1154 goto fail;
1155 }
1156 }
1157
1158 if (video_codec == AV_CODEC_ID_PRORES) {
1159 context->ffmpeg_profile = rd->ffcodecdata.ffmpeg_prores_profile;
1160 }
1161
1162 if (video_codec != AV_CODEC_ID_NONE) {
1163 context->video_stream = alloc_video_stream(
1164 context, rd, video_codec, of, rectx, recty, error, sizeof(error));
1165 FF_DEBUG_PRINT("ffmpeg: alloc video stream %p\n", context->video_stream);
1166 if (!context->video_stream) {
1167 if (error[0]) {
1169 FF_DEBUG_PRINT("ffmpeg: video stream error: %s\n", error);
1170 }
1171 else {
1172 BKE_report(reports, RPT_ERROR, "Error initializing video stream");
1173 FF_DEBUG_PRINT("ffmpeg: error initializing video stream\n");
1174 }
1175 goto fail;
1176 }
1177 }
1178
1179 if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE) {
1180 context->audio_stream = alloc_audio_stream(context,
1183 audio_codec,
1184 of,
1185 error,
1186 sizeof(error));
1187 if (!context->audio_stream) {
1188 if (error[0]) {
1190 FF_DEBUG_PRINT("ffmpeg: audio stream error: %s\n", error);
1191 }
1192 else {
1193 BKE_report(reports, RPT_ERROR, "Error initializing audio stream");
1194 FF_DEBUG_PRINT("ffmpeg: error initializing audio stream\n");
1195 }
1196 goto fail;
1197 }
1198 }
1199 if (!(fmt->flags & AVFMT_NOFILE)) {
1200 if (avio_open(&of->pb, filepath, AVIO_FLAG_WRITE) < 0) {
1201 BKE_report(reports, RPT_ERROR, "Could not open file for writing");
1202 FF_DEBUG_PRINT("ffmpeg: could not open file %s for writing\n", filepath);
1203 goto fail;
1204 }
1205 }
1206
1207 if (context->stamp_data != nullptr) {
1209 &of->metadata, context->stamp_data, ffmpeg_add_metadata_callback, false);
1210 }
1211
1212 ret = avformat_write_header(of, nullptr);
1213 if (ret < 0) {
1215 RPT_ERROR,
1216 "Could not initialize streams, probably unsupported codec combination");
1217 char error_str[AV_ERROR_MAX_STRING_SIZE];
1218 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
1219 FF_DEBUG_PRINT("ffmpeg: could not write media header: %s\n", error_str);
1220 goto fail;
1221 }
1222
1223 context->outfile = of;
1224 av_dump_format(of, 0, filepath, 1);
1225
1226 return true;
1227
1228fail:
1229 if (of->pb) {
1230 avio_close(of->pb);
1231 }
1232
1233 context->video_stream = nullptr;
1234 context->audio_stream = nullptr;
1235
1236 avformat_free_context(of);
1237 return false;
1238}
1239
1240/* Flush any pending frames. An encoder may use both past and future frames
1241 * to predict inter-frames (H.264 B-frames, for example); it can output
1242 * the frames in a different order from the one it was given. The delayed
1243 * frames must be flushed before we close the stream. */
1244static void flush_delayed_frames(AVCodecContext *c, AVStream *stream, AVFormatContext *outfile)
1245{
1246 char error_str[AV_ERROR_MAX_STRING_SIZE];
1247 AVPacket *packet = av_packet_alloc();
1248
1249 avcodec_send_frame(c, nullptr);
1250
1251 /* Get the packets frames. */
1252 int ret = 1;
1253 while (ret >= 0) {
1254 ret = avcodec_receive_packet(c, packet);
1255
1256 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
1257 /* No more packets to flush. */
1258 break;
1259 }
1260 if (ret < 0) {
1261 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
1262 fprintf(stderr, "Error encoding delayed frame: %s\n", error_str);
1263 break;
1264 }
1265
1266 packet->stream_index = stream->index;
1267 av_packet_rescale_ts(packet, c->time_base, stream->time_base);
1268# ifdef FFMPEG_USE_DURATION_WORKAROUND
1269 my_guess_pkt_duration(outfile, stream, packet);
1270# endif
1271
1272 int write_ret = av_interleaved_write_frame(outfile, packet);
1273 if (write_ret != 0) {
1274 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE, ret);
1275 fprintf(stderr, "Error writing delayed frame: %s\n", error_str);
1276 break;
1277 }
1278 }
1279
1280 av_packet_free(&packet);
1281}
1282
1290static bool ffmpeg_filepath_get(MovieWriter *context,
1291 char filepath[FILE_MAX],
1292 const RenderData *rd,
1293 bool preview,
1294 const char *suffix,
1296{
1297 char autosplit[20];
1298
1299 const char **exts = get_file_extensions(rd->ffcodecdata.type);
1300 const char **fe = exts;
1301 int sfra, efra;
1302
1303 if (!filepath || !exts) {
1304 return false;
1305 }
1306
1307 if (preview) {
1308 sfra = rd->psfra;
1309 efra = rd->pefra;
1310 }
1311 else {
1312 sfra = rd->sfra;
1313 efra = rd->efra;
1314 }
1315
1316 BLI_strncpy(filepath, rd->pic, FILE_MAX);
1317
1320 if (!errors.is_empty()) {
1322 return false;
1323 }
1324
1326
1328
1329 autosplit[0] = '\0';
1330
1331 if ((rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT) != 0) {
1332 if (context) {
1333 SNPRINTF(autosplit, "_%03d", context->ffmpeg_autosplit_count);
1334 }
1335 }
1336
1337 if (rd->scemode & R_EXTENSION) {
1338 while (*fe) {
1339 if (BLI_strcasecmp(filepath + strlen(filepath) - strlen(*fe), *fe) == 0) {
1340 break;
1341 }
1342 fe++;
1343 }
1344
1345 if (*fe == nullptr) {
1346 BLI_strncat(filepath, autosplit, FILE_MAX);
1347
1348 BLI_path_frame_range(filepath, FILE_MAX, sfra, efra, 4);
1349 BLI_strncat(filepath, *exts, FILE_MAX);
1350 }
1351 else {
1352 *(filepath + strlen(filepath) - strlen(*fe)) = '\0';
1353 BLI_strncat(filepath, autosplit, FILE_MAX);
1354 BLI_strncat(filepath, *fe, FILE_MAX);
1355 }
1356 }
1357 else {
1358 if (BLI_path_frame_check_chars(filepath)) {
1359 BLI_path_frame_range(filepath, FILE_MAX, sfra, efra, 4);
1360 }
1361
1362 BLI_strncat(filepath, autosplit, FILE_MAX);
1363 }
1364
1365 BLI_path_suffix(filepath, FILE_MAX, suffix, "");
1366
1367 return true;
1368}
1369
1370static void ffmpeg_get_filepath(char filepath[/*FILE_MAX*/ 1024],
1371 const RenderData *rd,
1372 bool preview,
1373 const char *suffix,
1375{
1376 ffmpeg_filepath_get(nullptr, filepath, rd, preview, suffix, reports);
1377}
1378
1379static MovieWriter *ffmpeg_movie_open(const Scene *scene,
1380 RenderData *rd,
1381 int rectx,
1382 int recty,
1384 bool preview,
1385 const char *suffix)
1386{
1387 MovieWriter *context = MEM_new<MovieWriter>("new FFMPEG context");
1388
1389 context->ffmpeg_codec = AV_CODEC_ID_MPEG4;
1390 context->ffmpeg_audio_codec = AV_CODEC_ID_NONE;
1391 context->ffmpeg_video_bitrate = 1150;
1392 context->ffmpeg_audio_bitrate = 128;
1393 context->ffmpeg_gop_size = 12;
1394 context->ffmpeg_autosplit = false;
1395 context->stamp_data = nullptr;
1396 context->audio_time_total = 0.0;
1397
1398 context->ffmpeg_autosplit_count = 0;
1399 context->ffmpeg_preview = preview;
1400 context->stamp_data = BKE_stamp_info_from_scene_static(scene);
1401
1402 bool success = start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports);
1403
1404 if (success) {
1405 success = movie_audio_open(context,
1406 scene,
1407 preview ? rd->psfra : rd->sfra,
1410 reports);
1411 }
1412
1413 if (!success) {
1414 ffmpeg_movie_close(context);
1415 return nullptr;
1416 }
1417 return context;
1418}
1419
1420static void end_ffmpeg_impl(MovieWriter *context, bool is_autosplit);
1421
1422static bool ffmpeg_movie_append(MovieWriter *context,
1423 RenderData *rd,
1424 int start_frame,
1425 int frame,
1426 const ImBuf *image,
1427 const char *suffix,
1429{
1430 AVFrame *avframe;
1431 bool success = true;
1432
1433 FF_DEBUG_PRINT("ffmpeg: writing frame #%i (%ix%i)\n", frame, image->x, image->y);
1434
1435 if (context->video_stream) {
1436 avframe = generate_video_frame(context, image);
1437 success = (avframe && write_video_frame(context, avframe, reports));
1438 }
1439
1440 if (context->audio_stream) {
1441 /* Add +1 frame because we want to encode audio up until the next video frame. */
1442 write_audio_frames(
1443 context, (frame - start_frame + 1) / (double(rd->frs_sec) / double(rd->frs_sec_base)));
1444 }
1445
1446 if (context->ffmpeg_autosplit) {
1447 if (avio_tell(context->outfile->pb) > ffmpeg_autosplit_size) {
1448 end_ffmpeg_impl(context, true);
1449 context->ffmpeg_autosplit_count++;
1450
1451 success &= start_ffmpeg_impl(context, rd, image->x, image->y, suffix, reports);
1452 }
1453 }
1454
1455 return success;
1456}
1457
1458static void end_ffmpeg_impl(MovieWriter *context, bool is_autosplit)
1459{
1460 FF_DEBUG_PRINT("ffmpeg: closing\n");
1461
1462 movie_audio_close(context, is_autosplit);
1463
1464 if (context->video_stream) {
1465 FF_DEBUG_PRINT("ffmpeg: flush delayed video frames\n");
1466 flush_delayed_frames(context->video_codec, context->video_stream, context->outfile);
1467 }
1468
1469 if (context->audio_stream) {
1470 FF_DEBUG_PRINT("ffmpeg: flush delayed audio frames\n");
1471 flush_delayed_frames(context->audio_codec, context->audio_stream, context->outfile);
1472 }
1473
1474 if (context->outfile) {
1475 av_write_trailer(context->outfile);
1476 }
1477
1478 /* Close the video codec */
1479
1480 context->video_stream = nullptr;
1481 context->audio_stream = nullptr;
1482
1483 av_frame_free(&context->current_frame);
1484 av_frame_free(&context->img_convert_frame);
1485
1486 if (context->outfile != nullptr && context->outfile->oformat) {
1487 if (!(context->outfile->oformat->flags & AVFMT_NOFILE)) {
1488 avio_close(context->outfile->pb);
1489 }
1490 }
1491
1492 if (context->video_codec != nullptr) {
1493 avcodec_free_context(&context->video_codec);
1494 context->video_codec = nullptr;
1495 }
1496 if (context->audio_codec != nullptr) {
1497 avcodec_free_context(&context->audio_codec);
1498 context->audio_codec = nullptr;
1499 }
1500
1501 if (context->outfile != nullptr) {
1502 avformat_free_context(context->outfile);
1503 context->outfile = nullptr;
1504 }
1505 if (context->audio_input_buffer != nullptr) {
1506 av_free(context->audio_input_buffer);
1507 context->audio_input_buffer = nullptr;
1508 }
1509
1510 if (context->audio_deinterleave_buffer != nullptr) {
1511 av_free(context->audio_deinterleave_buffer);
1512 context->audio_deinterleave_buffer = nullptr;
1513 }
1514
1515 if (context->img_convert_ctx != nullptr) {
1516 ffmpeg_sws_release_context(context->img_convert_ctx);
1517 context->img_convert_ctx = nullptr;
1518 }
1519}
1520
1521static void ffmpeg_movie_close(MovieWriter *context)
1522{
1523 if (context == nullptr) {
1524 return;
1525 }
1526 end_ffmpeg_impl(context, false);
1527 if (context->stamp_data) {
1528 BKE_stamp_data_free(context->stamp_data);
1529 }
1530 MEM_delete(context);
1531}
1532
1533#endif /* WITH_FFMPEG */
1534
1535static bool is_imtype_ffmpeg(const char imtype)
1536{
1537 return ELEM(imtype,
1545}
1546
1547MovieWriter *MOV_write_begin(const char imtype,
1548 const Scene *scene,
1549 RenderData *rd,
1550 int rectx,
1551 int recty,
1553 bool preview,
1554 const char *suffix)
1555{
1556 if (!is_imtype_ffmpeg(imtype)) {
1557 BKE_report(reports, RPT_ERROR, "Image format is not a movie format");
1558 return nullptr;
1559 }
1560
1561 MovieWriter *writer = nullptr;
1562#ifdef WITH_FFMPEG
1563 writer = ffmpeg_movie_open(scene, rd, rectx, recty, reports, preview, suffix);
1564#else
1565 UNUSED_VARS(scene, rd, rectx, recty, reports, preview, suffix);
1566#endif
1567 return writer;
1568}
1569
1570bool MOV_write_append(MovieWriter *writer,
1571 RenderData *rd,
1572 int start_frame,
1573 int frame,
1574 const ImBuf *image,
1575 const char *suffix,
1577{
1578 if (writer == nullptr) {
1579 return false;
1580 }
1581
1582#ifdef WITH_FFMPEG
1583 bool ok = ffmpeg_movie_append(writer, rd, start_frame, frame, image, suffix, reports);
1584 return ok;
1585#else
1586 UNUSED_VARS(rd, start_frame, frame, image, suffix, reports);
1587 return false;
1588#endif
1589}
1590
1591void MOV_write_end(MovieWriter *writer)
1592{
1593#ifdef WITH_FFMPEG
1594 if (writer) {
1595 ffmpeg_movie_close(writer);
1596 }
1597#else
1598 UNUSED_VARS(writer);
1599#endif
1600}
1601
1602void MOV_filepath_from_settings(char filepath[/*FILE_MAX*/ 1024],
1603 const RenderData *rd,
1604 bool preview,
1605 const char *suffix,
1607{
1608#ifdef WITH_FFMPEG
1610 ffmpeg_get_filepath(filepath, rd, preview, suffix, reports);
1611 return;
1612 }
1613#else
1614 UNUSED_VARS(rd, preview, suffix, reports);
1615#endif
1616 filepath[0] = '\0';
1617}
StampData * BKE_stamp_info_from_scene_static(const Scene *scene)
void BKE_stamp_data_free(StampData *stamp_data)
void BKE_stamp_info_callback(void *data, StampData *stamp_data, StampCallback callback, bool noskip)
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:882
Functions and classes for applying templates with variable expressions to filepaths.
void BKE_report_path_template_errors(ReportList *reports, eReportType report_type, blender::StringRef path, blender::Span< blender::bke::path_templates::Error > errors)
blender::bke::path_templates::VariableMap BKE_build_template_variables_for_render_path(const RenderData *render_data)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
File and directory operations.
bool BLI_file_ensure_parent_dir_exists(const char *filepath) ATTR_NONNULL(1)
Definition fileops_c.cc:429
void BLI_kdtree_nd_ free(KDTree *tree)
MINLINE int power_of_2_min_i(int n)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
MINLINE int is_power_of_2_i(int n)
MINLINE unsigned int log2_floor_u(unsigned int x)
MINLINE int clamp_i(int value, int min, int max)
MINLINE void premul_to_straight_v4_v4(float straight[4], const float premul[4])
ATTR_WARN_UNUSED_RESULT const size_t num
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
bool bool BLI_path_suffix(char *path, size_t path_maxncpy, const char *suffix, const char *sep) ATTR_NONNULL(1
bool void bool BLI_path_frame_check_chars(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define FILE_MAX
bool BLI_path_frame_range(char *path, size_t path_maxncpy, int sta, int end, int digits) ATTR_NONNULL(1)
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:599
char char size_t char * BLI_strncat(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
int char char int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
size_t BLI_snprintf(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
unsigned int uint
int BLI_system_thread_count(void)
Definition threads.cc:253
#define UNUSED_VARS(...)
#define ELEM(...)
#define STREQ(a, b)
@ R_IMF_PLANES_RGBA
@ R_IMF_PLANES_BW
@ FFMPEG_LOSSLESS_OUTPUT
@ FFMPEG_AUTOSPLIT_OUTPUT
@ FFMPEG_USE_MAX_B_FRAMES
@ R_IMF_IMTYPE_FFMPEG
@ R_IMF_IMTYPE_AVIJPEG
@ R_IMF_IMTYPE_H264
@ R_IMF_IMTYPE_AVIRAW
@ R_IMF_IMTYPE_THEORA
@ R_IMF_IMTYPE_AV1
@ R_IMF_IMTYPE_XVID
@ FFM_PRESET_GOOD
@ FFM_PRESET_REALTIME
@ FFM_PRESET_BEST
@ FFM_CRF_LOW
@ FFM_CRF_MEDIUM
@ FFM_CRF_VERYLOW
@ FFM_CRF_LOSSLESS
@ FFM_CRF_PERC_LOSSLESS
@ FFM_CRF_LOWEST
@ FFM_CRF_HIGH
@ R_IMF_CHAN_DEPTH_16
@ R_IMF_CHAN_DEPTH_12
@ R_IMF_CHAN_DEPTH_10
@ R_EXTENSION
@ FFM_PRORES_PROFILE_422_PROXY
@ FFM_PRORES_PROFILE_4444_XQ
@ FFM_PRORES_PROFILE_422_HQ
@ FFM_PRORES_PROFILE_4444
Read Guarded memory(de)allocation.
@ FFMPEG_H264
Definition MOV_enums.hh:18
@ FFMPEG_FLV
Definition MOV_enums.hh:20
@ FFMPEG_MPEG1
Definition MOV_enums.hh:12
@ FFMPEG_AV1
Definition MOV_enums.hh:25
@ FFMPEG_DV
Definition MOV_enums.hh:17
@ FFMPEG_MPEG2
Definition MOV_enums.hh:13
@ FFMPEG_MKV
Definition MOV_enums.hh:21
@ FFMPEG_MOV
Definition MOV_enums.hh:16
@ FFMPEG_MPEG4
Definition MOV_enums.hh:14
@ FFMPEG_WEBM
Definition MOV_enums.hh:24
@ FFMPEG_AVI
Definition MOV_enums.hh:15
@ FFMPEG_XVID
Definition MOV_enums.hh:19
@ FFMPEG_OGG
Definition MOV_enums.hh:22
ReportList * reports
Definition WM_types.hh:1025
BMesh const char void * data
long long int int64_t
bool is_empty() const
#define fabsf(x)
#define sqrtf(x)
FFMPEG_INLINE size_t ffmpeg_get_buffer_alignment()
FFMPEG_INLINE enum AVPixelFormat * ffmpeg_get_pix_fmts(struct AVCodecContext *context, const AVCodec *codec)
FFMPEG_INLINE void my_guess_pkt_duration(AVFormatContext *s, AVStream *st, AVPacket *pkt)
#define round
#define printf(...)
format
ccl_device_inline float2 fabs(const float2 a)
static void error(const char *str)
bool MOV_codec_supports_alpha(IMB_Ffmpeg_Codec_ID codec_id, int ffmpeg_profile)
bool MOV_codec_supports_crf(IMB_Ffmpeg_Codec_ID codec_id)
MovieWriter * MOV_write_begin(const char imtype, const Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports, bool preview, const char *suffix)
void MOV_filepath_from_settings(char filepath[1024], const RenderData *rd, bool preview, const char *suffix, ReportList *reports)
void MOV_write_end(MovieWriter *writer)
bool MOV_write_append(MovieWriter *writer, RenderData *rd, int start_frame, int frame, const ImBuf *image, const char *suffix, ReportList *reports)
static bool is_imtype_ffmpeg(const char imtype)
int context(const bContext *C, const char *member, bContextDataResult *result)
blender::Vector< Error > BKE_path_apply_template(char *path, int path_max_length, const VariableMap &template_variables)
const btScalar eps
Definition poly34.cpp:11
return ret
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
struct ImageFormatData im_format
char pic[1024]
struct FFMpegCodecData ffcodecdata
i
Definition text_draw.cc:230