46static constexpr int64_t ffmpeg_autosplit_size = 2'000'000'000;
48# define FF_DEBUG_PRINT \
49 if (G.debug & G_DEBUG_FFMPEG) \
52static void ffmpeg_dict_set_int(AVDictionary **dict,
const char *key,
int value)
54 av_dict_set_int(dict, key, value, 0);
57static void ffmpeg_movie_close(MovieWriter *context);
58static bool ffmpeg_filepath_get(MovieWriter *context,
65static AVFrame *alloc_frame(AVPixelFormat pix_fmt,
int width,
int height)
67 AVFrame *f = av_frame_alloc();
75 if (av_frame_get_buffer(f, align) < 0) {
84static const char **get_file_extensions(
int format)
88 static const char *rv[] = {
".dv",
nullptr};
92 static const char *rv[] = {
".mpg",
".mpeg",
nullptr};
96 static const char *rv[] = {
".dvd",
".vob",
".mpg",
".mpeg",
nullptr};
100 static const char *rv[] = {
".mp4",
".mpg",
".mpeg",
nullptr};
104 static const char *rv[] = {
".avi",
nullptr};
108 static const char *rv[] = {
".mov",
nullptr};
113 static const char *rv[] = {
".avi",
nullptr};
119 static const char *rv[] = {
".avi",
nullptr};
123 static const char *rv[] = {
".flv",
nullptr};
127 static const char *rv[] = {
".mkv",
nullptr};
131 static const char *rv[] = {
".ogv",
".ogg",
nullptr};
135 static const char *rv[] = {
".webm",
nullptr};
139 static const char *rv[] = {
".mp4",
".mkv",
nullptr};
148static bool write_video_frame(MovieWriter *context, AVFrame *frame,
ReportList *
reports)
150 int ret, success = 1;
151 AVPacket *packet = av_packet_alloc();
153 AVCodecContext *c =
context->video_codec;
155 frame->pts =
context->video_time;
158 char error_str[AV_ERROR_MAX_STRING_SIZE];
159 ret = avcodec_send_frame(c, frame);
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);
168 ret = avcodec_receive_packet(c, packet);
170 if (
ret == AVERROR(EAGAIN) ||
ret == AVERROR_EOF) {
175 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE,
ret);
176 fprintf(stderr,
"Error encoding frame: %s\n", error_str);
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
186 if (av_interleaved_write_frame(
context->outfile, packet) != 0) {
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);
198 av_packet_free(&packet);
204static AVFrame *generate_video_frame(MovieWriter *context,
const ImBuf *image)
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))) {
215 AVCodecParameters *codec =
context->video_stream->codecpar;
216 int height = codec->height;
219 if (
context->img_convert_frame !=
nullptr) {
221 rgb_frame =
context->img_convert_frame;
225 rgb_frame =
context->current_frame;
230 av_frame_make_writable(rgb_frame);
232 const size_t linesize_dst = rgb_frame->linesize[0];
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;
252 for (
int x = 0;
x < image->
x;
x++) {
263 for (
int x = 0;
x < image->
x;
x++) {
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;
281# if ENDIAN_ORDER == L_ENDIAN
282 memcpy(target, src, linesize_src);
284# elif ENDIAN_ORDER == B_ENDIAN
285 const uint8_t *end = src + linesize_src;
296# error ENDIAN_ORDER should either be L_ENDIAN or B_ENDIAN.
302 if (
context->img_convert_frame !=
nullptr) {
305 av_frame_make_writable(
context->current_frame);
306 ffmpeg_sws_scale_frame(
context->img_convert_ctx,
context->current_frame, rgb_frame);
312static AVRational calc_time_base(
uint den,
double num, AVCodecID codec_id)
319 float eps = FLT_EPSILON;
320 const uint DENUM_MAX = (codec_id == AV_CODEC_ID_MPEG4) ? (1UL << 16) - 1 : (1UL << 31) - 1;
331 eps = float(1 << num_integer_bits) * FLT_EPSILON;
335 const int max_num_shift =
fabsf(log10f(
eps));
337 const int max_den_shift = log10f(DENUM_MAX) - log10f(den);
338 const int max_iter =
min_ii(max_num_shift, max_den_shift);
347 AVRational time_base;
349 time_base.num = int(
num);
354static const AVCodec *get_av1_encoder(
355 MovieWriter *context,
RenderData *rd, AVDictionary **opts,
int rectx,
int recty)
361 const AVCodec *codec =
nullptr;
362 switch (
context->ffmpeg_preset) {
366 codec = avcodec_find_encoder_by_name(
"librav1e");
369 codec = avcodec_find_encoder_by_name(
"libaom-av1");
373 codec = avcodec_find_encoder_by_name(
"libsvtav1");
377 codec = avcodec_find_encoder_by_name(
"libaom-av1");
383 codec = avcodec_find_encoder(AV_CODEC_ID_AV1);
388 if (
STREQ(codec->name,
"librav1e")) {
391 ffmpeg_dict_set_int(opts,
"tiles", rd->
threads);
394 ffmpeg_dict_set_int(opts,
"tiles", 8);
400 switch (
context->ffmpeg_preset) {
402 ffmpeg_dict_set_int(opts,
"speed", 4);
405 ffmpeg_dict_set_int(opts,
"speed", 10);
409 ffmpeg_dict_set_int(opts,
"speed", 6);
415 av_dict_set(opts,
"rav1e-params", buffer, 0);
417 else if (
STREQ(codec->name,
"libsvtav1")) {
421 switch (
context->ffmpeg_preset) {
423 ffmpeg_dict_set_int(opts,
"preset", 8);
426 ffmpeg_dict_set_int(opts,
"preset", 3);
430 ffmpeg_dict_set_int(opts,
"preset", 5);
434 else if (
STREQ(codec->name,
"libaom-av1")) {
436 ffmpeg_dict_set_int(opts,
"row-mt", 1);
437 const char *tiles_string =
nullptr;
438 bool tiles_string_is_dynamic =
false;
442 if (threads_sqrt < 4) {
449 for (
int t_sqrt_copy = threads_sqrt; t_sqrt_copy > 0; t_sqrt_copy /= 10) {
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;
467 if (sqrt_p2_next < 1) {
470 if (sqrt_p2 > sqrt_p2_next) {
473 sqrt_p2 = sqrt_p2_next;
476 int combined_digits = 0;
477 for (
int sqrt_p2_copy = sqrt_p2; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) {
480 for (
int sqrt_p2_copy = sqrt_p2_next; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) {
484 char *tiles_string_mut = (
char *)calloc(combined_digits + 2, 1);
486 BLI_snprintf(tiles_string_mut, combined_digits + 2,
"%dx%d", sqrt_p2_next, sqrt_p2);
488 else if (rectx < recty) {
489 BLI_snprintf(tiles_string_mut, combined_digits + 2,
"%dx%d", sqrt_p2, sqrt_p2_next);
492 BLI_snprintf(tiles_string_mut, combined_digits + 2,
"%dx%d", sqrt_p2, sqrt_p2);
494 tiles_string_is_dynamic =
true;
495 tiles_string = tiles_string_mut;
501 tiles_string =
"4x2";
503 else if (rectx < recty) {
504 tiles_string =
"2x4";
507 tiles_string =
"2x2";
510 av_dict_set(opts,
"tiles", tiles_string, 0);
511 if (tiles_string_is_dynamic) {
512 free((
void *)tiles_string);
518 switch (
context->ffmpeg_preset) {
520 ffmpeg_dict_set_int(opts,
"cpu-used", 8);
523 ffmpeg_dict_set_int(opts,
"cpu-used", 4);
527 ffmpeg_dict_set_int(opts,
"cpu-used", 6);
538static int remap_crf_to_h265_crf(
int crf,
bool is_10_or_12_bpp)
541 const int bias = is_10_or_12_bpp ? -3 : 0;
559static const AVCodec *get_prores_encoder(
RenderData *rd,
int rectx,
int recty)
565 if ((
size_t(rectx) *
size_t(recty)) > (3840 * 2160)) {
566 return avcodec_find_encoder_by_name(
"prores_ks");
569 return avcodec_find_encoder_by_name(
"prores_aw");
574static int remap_crf_to_h264_10bpp_crf(
int crf)
576 crf = int(-12.0f + (crf / 51.0f) * 63.0f);
581static void set_quality_rate_options(
const MovieWriter *context,
582 const AVCodecID codec_id,
586 AVCodecContext *c =
context->video_codec;
590 c->bit_rate =
context->ffmpeg_video_bitrate * 1000;
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");
608 if (codec_id == AV_CODEC_ID_VP9) {
610 ffmpeg_dict_set_int(opts,
"lossless", 1);
612 else if (codec_id == AV_CODEC_ID_H264 && is_10_bpp) {
614 ffmpeg_dict_set_int(opts,
"qp", 0);
616 else if (codec_id == AV_CODEC_ID_H265) {
618 av_dict_set(opts,
"x265-params",
"log-level=1:lossless=1", 0);
620 else if (codec_id == AV_CODEC_ID_AV1 && (av1_librav1e || av1_libsvtav1)) {
622 ffmpeg_dict_set_int(opts,
"qp", 0);
626 ffmpeg_dict_set_int(opts,
"crf", 0);
634 if (codec_id == AV_CODEC_ID_H264 && is_10_bpp) {
635 crf = remap_crf_to_h264_10bpp_crf(crf);
637 else if (codec_id == AV_CODEC_ID_H265) {
638 crf = remap_crf_to_h265_crf(crf, is_10_bpp || is_12_bpp);
640 av_dict_set(opts,
"x265-params",
"log-level=1", 0);
645 int qp = int(
float(crf) / 51.0f * 255.0f);
647 ffmpeg_dict_set_int(opts,
"qp", qp);
649 else if (av1_libsvtav1) {
651 ffmpeg_dict_set_int(opts,
"qp", crf);
654 ffmpeg_dict_set_int(opts,
"crf", crf);
658static AVStream *alloc_video_stream(MovieWriter *context,
668 const AVCodec *codec;
669 AVDictionary *opts =
nullptr;
673 st = avformat_new_stream(of,
nullptr);
681 if (codec_id == AV_CODEC_ID_AV1) {
684 codec = get_av1_encoder(context, rd, &opts, rectx, recty);
686 else if (codec_id == AV_CODEC_ID_PRORES) {
687 codec = get_prores_encoder(rd, rectx, recty);
690 codec = avcodec_find_encoder(codec_id);
693 fprintf(stderr,
"Couldn't find valid video codec\n");
694 context->video_codec =
nullptr;
698 context->video_codec = avcodec_alloc_context3(codec);
699 AVCodecContext *c =
context->video_codec;
708 c->time_base.den = 2997;
709 c->time_base.num = 100;
712 c->time_base.den = rd->
frs_sec;
725 if (c->time_base.num != 1) {
726 AVRational new_time_base;
728 &new_time_base.num, &new_time_base.den, c->time_base.num, c->time_base.den, INT_MAX))
731 c->time_base = new_time_base;
735 st->time_base = c->time_base;
737 c->gop_size =
context->ffmpeg_gop_size;
738 c->max_b_frames =
context->ffmpeg_max_b_frames;
740 set_quality_rate_options(context, codec_id, rd, &opts);
746 char const *preset_name =
nullptr;
747 char const *deadline_name =
nullptr;
748 switch (
context->ffmpeg_preset) {
750 preset_name =
"medium";
751 deadline_name =
"good";
754 preset_name =
"slower";
755 deadline_name =
"best";
758 preset_name =
"superfast";
759 deadline_name =
"realtime";
762 printf(
"Unknown preset number %i, ignoring.\n",
context->ffmpeg_preset);
766 if (preset_name !=
nullptr && codec_id != AV_CODEC_ID_AV1) {
767 av_dict_set(&opts,
"preset", preset_name, 0);
769 if (deadline_name !=
nullptr) {
770 av_dict_set(&opts,
"deadline", deadline_name, 0);
778 c->pix_fmt = pix_fmts[0];
782 c->pix_fmt = AV_PIX_FMT_YUV422P;
789 c->pix_fmt = AV_PIX_FMT_YUV420P10LE;
791 else if (is_12_bpp) {
792 c->pix_fmt = AV_PIX_FMT_YUV420P12LE;
797 c->pix_fmt = AV_PIX_FMT_YUV420P;
798 c->codec_tag = ((
'D' << 24) + (
'I' << 16) + (
'V' << 8) +
'X');
801 if (codec_id == AV_CODEC_ID_H265) {
806 c->codec_tag = MKTAG(
'h',
'v',
'c',
'1');
810 if (codec_id == AV_CODEC_ID_HUFFYUV) {
812 c->pix_fmt = AV_PIX_FMT_BGRA;
815 c->pix_fmt = AV_PIX_FMT_RGB32;
819 if (codec_id == AV_CODEC_ID_DNXHD) {
826 if (codec_id == AV_CODEC_ID_FFV1) {
828 c->pix_fmt = AV_PIX_FMT_GRAY8;
830 c->pix_fmt = AV_PIX_FMT_GRAY10;
832 else if (is_12_bpp) {
833 c->pix_fmt = AV_PIX_FMT_GRAY12;
835 else if (is_16_bpp) {
836 c->pix_fmt = AV_PIX_FMT_GRAY16;
840 c->pix_fmt = AV_PIX_FMT_RGB32;
842 c->pix_fmt = AV_PIX_FMT_GBRAP10;
844 else if (is_12_bpp) {
845 c->pix_fmt = AV_PIX_FMT_GBRAP12;
847 else if (is_16_bpp) {
848 c->pix_fmt = AV_PIX_FMT_GBRAP16;
852 c->pix_fmt = AV_PIX_FMT_0RGB32;
854 c->pix_fmt = AV_PIX_FMT_GBRP10;
856 else if (is_12_bpp) {
857 c->pix_fmt = AV_PIX_FMT_GBRP12;
859 else if (is_16_bpp) {
860 c->pix_fmt = AV_PIX_FMT_GBRP16;
865 if (codec_id == AV_CODEC_ID_QTRLE) {
867 c->pix_fmt = AV_PIX_FMT_GRAY8;
870 c->pix_fmt = AV_PIX_FMT_ARGB;
873 c->pix_fmt = AV_PIX_FMT_RGB24;
878 c->pix_fmt = AV_PIX_FMT_YUVA420P;
880 else if (
ELEM(codec_id, AV_CODEC_ID_H264, AV_CODEC_ID_H265, AV_CODEC_ID_VP9, AV_CODEC_ID_AV1) &&
884 c->pix_fmt = AV_PIX_FMT_YUV444P;
886 c->pix_fmt = AV_PIX_FMT_YUV444P10LE;
888 else if (is_12_bpp) {
889 c->pix_fmt = AV_PIX_FMT_YUV444P12LE;
893 if (codec_id == AV_CODEC_ID_PNG) {
895 c->pix_fmt = AV_PIX_FMT_GRAY8;
898 c->pix_fmt = AV_PIX_FMT_RGBA;
901 c->pix_fmt = AV_PIX_FMT_RGB24;
904 if (codec_id == AV_CODEC_ID_PRORES) {
908 c->profile =
context->ffmpeg_profile;
909 c->pix_fmt = AV_PIX_FMT_YUV422P10LE;
914 c->profile =
context->ffmpeg_profile;
915 c->pix_fmt = AV_PIX_FMT_YUV444P10LE;
918 c->pix_fmt = AV_PIX_FMT_YUVA444P10LE;
922 fprintf(stderr,
"ffmpeg: invalid profile %d\n",
context->ffmpeg_profile);
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;
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;
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;
943 st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q((
double(rd->
xasp) /
double(rd->
yasp)),
945 st->avg_frame_rate = av_inv_q(c->time_base);
947 if (codec->capabilities & AV_CODEC_CAP_OTHER_THREADS) {
954 if (codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) {
955 c->thread_type = FF_THREAD_FRAME;
957 else if (codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
958 c->thread_type = FF_THREAD_SLICE;
961 int ret = avcodec_open2(c, codec, &opts);
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);
969 avcodec_free_context(&c);
970 context->video_codec =
nullptr;
976 context->current_frame = alloc_frame(c->pix_fmt, c->width, c->height);
978 if (c->pix_fmt == AV_PIX_FMT_RGBA) {
980 context->img_convert_frame =
nullptr;
981 context->img_convert_ctx =
nullptr;
985 AVPixelFormat src_format = is_10_bpp || is_12_bpp || is_16_bpp ? AV_PIX_FMT_GBRAPF32LE :
987 context->img_convert_frame = alloc_frame(src_format, c->width, c->height);
989 context->img_convert_ctx = ffmpeg_sws_get_context(c->width,
998 set_bt709 ? AVCOL_SPC_BT709 : -1,
1002 avcodec_parameters_from_context(st->codecpar, c);
1009static void ffmpeg_add_metadata_callback(
void *
data,
1010 const char *propname,
1014 AVDictionary **metadata = (AVDictionary **)
data;
1015 av_dict_set(metadata, propname, propvalue, 0);
1018static bool start_ffmpeg_impl(MovieWriter *context,
1026 AVFormatContext *of;
1027 const AVOutputFormat *fmt;
1034 context->ffmpeg_audio_codec = mov_av_codec_id_get(rd->
ffcodecdata.audio_codec_id_get());
1048 if (!ffmpeg_filepath_get(context, filepath, rd,
context->ffmpeg_preview, suffix,
reports)) {
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",
1061 context->ffmpeg_video_bitrate,
1062 context->ffmpeg_audio_bitrate,
1069 exts = get_file_extensions(
context->ffmpeg_type);
1075 fmt = av_guess_format(
nullptr, exts[0],
nullptr);
1081 of = avformat_alloc_context();
1087 enum AVCodecID audio_codec =
context->ffmpeg_audio_codec;
1088 enum AVCodecID video_codec =
context->ffmpeg_codec;
1090 of->url = av_strdup(filepath);
1092 switch (
context->ffmpeg_type) {
1094 video_codec = AV_CODEC_ID_THEORA;
1097 video_codec = AV_CODEC_ID_DVVIDEO;
1100 video_codec = AV_CODEC_ID_MPEG1VIDEO;
1103 video_codec = AV_CODEC_ID_MPEG2VIDEO;
1106 video_codec = AV_CODEC_ID_H264;
1109 video_codec = AV_CODEC_ID_MPEG4;
1112 video_codec = AV_CODEC_ID_FLV1;
1115 video_codec = AV_CODEC_ID_AV1;
1120 video_codec =
context->ffmpeg_codec;
1126# if LIBAVFORMAT_VERSION_MAJOR >= 59
1130 of->oformat = (AVOutputFormat *)fmt;
1133 if (video_codec == AV_CODEC_ID_DVVIDEO) {
1138 if (rd->
frs_sec != 25 && recty != 480) {
1142 if (rd->
frs_sec == 25 && recty != 576) {
1149 audio_codec = AV_CODEC_ID_PCM_S16LE;
1150 if (
context->ffmpeg_audio_codec != AV_CODEC_ID_NONE &&
1158 if (video_codec == AV_CODEC_ID_PRORES) {
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);
1169 FF_DEBUG_PRINT(
"ffmpeg: video stream error: %s\n",
error);
1173 FF_DEBUG_PRINT(
"ffmpeg: error initializing video stream\n");
1179 if (
context->ffmpeg_audio_codec != AV_CODEC_ID_NONE) {
1180 context->audio_stream = alloc_audio_stream(context,
1190 FF_DEBUG_PRINT(
"ffmpeg: audio stream error: %s\n",
error);
1194 FF_DEBUG_PRINT(
"ffmpeg: error initializing audio stream\n");
1199 if (!(fmt->flags & AVFMT_NOFILE)) {
1200 if (avio_open(&of->pb, filepath, AVIO_FLAG_WRITE) < 0) {
1202 FF_DEBUG_PRINT(
"ffmpeg: could not open file %s for writing\n", filepath);
1207 if (
context->stamp_data !=
nullptr) {
1209 &of->metadata,
context->stamp_data, ffmpeg_add_metadata_callback,
false);
1212 ret = avformat_write_header(of,
nullptr);
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);
1224 av_dump_format(of, 0, filepath, 1);
1233 context->video_stream =
nullptr;
1234 context->audio_stream =
nullptr;
1236 avformat_free_context(of);
1244static void flush_delayed_frames(AVCodecContext *c, AVStream *stream, AVFormatContext *outfile)
1246 char error_str[AV_ERROR_MAX_STRING_SIZE];
1247 AVPacket *packet = av_packet_alloc();
1249 avcodec_send_frame(c,
nullptr);
1254 ret = avcodec_receive_packet(c, packet);
1256 if (
ret == AVERROR(EAGAIN) ||
ret == AVERROR_EOF) {
1261 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE,
ret);
1262 fprintf(stderr,
"Error encoding delayed frame: %s\n", error_str);
1266 packet->stream_index = stream->index;
1267 av_packet_rescale_ts(packet, c->time_base, stream->time_base);
1268# ifdef FFMPEG_USE_DURATION_WORKAROUND
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);
1280 av_packet_free(&packet);
1290static bool ffmpeg_filepath_get(MovieWriter *context,
1300 const char **fe = exts;
1303 if (!filepath || !exts) {
1329 autosplit[0] =
'\0';
1339 if (
BLI_strcasecmp(filepath + strlen(filepath) - strlen(*fe), *fe) == 0) {
1345 if (*fe ==
nullptr) {
1352 *(filepath + strlen(filepath) - strlen(*fe)) =
'\0';
1370static void ffmpeg_get_filepath(
char filepath[ 1024],
1376 ffmpeg_filepath_get(
nullptr, filepath, rd, preview, suffix,
reports);
1379static MovieWriter *ffmpeg_movie_open(
const Scene *scene,
1387 MovieWriter *
context = MEM_new<MovieWriter>(
"new FFMPEG context");
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;
1398 context->ffmpeg_autosplit_count = 0;
1399 context->ffmpeg_preview = preview;
1402 bool success = start_ffmpeg_impl(context, rd, rectx, recty, suffix,
reports);
1405 success = movie_audio_open(context,
1414 ffmpeg_movie_close(context);
1420static void end_ffmpeg_impl(MovieWriter *context,
bool is_autosplit);
1422static bool ffmpeg_movie_append(MovieWriter *context,
1431 bool success =
true;
1433 FF_DEBUG_PRINT(
"ffmpeg: writing frame #%i (%ix%i)\n", frame, image->
x, image->
y);
1436 avframe = generate_video_frame(context, image);
1437 success = (avframe && write_video_frame(context, avframe,
reports));
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++;
1451 success &= start_ffmpeg_impl(context, rd, image->
x, image->
y, suffix,
reports);
1458static void end_ffmpeg_impl(MovieWriter *context,
bool is_autosplit)
1460 FF_DEBUG_PRINT(
"ffmpeg: closing\n");
1462 movie_audio_close(context, is_autosplit);
1465 FF_DEBUG_PRINT(
"ffmpeg: flush delayed video frames\n");
1470 FF_DEBUG_PRINT(
"ffmpeg: flush delayed audio frames\n");
1475 av_write_trailer(
context->outfile);
1480 context->video_stream =
nullptr;
1481 context->audio_stream =
nullptr;
1483 av_frame_free(&
context->current_frame);
1484 av_frame_free(&
context->img_convert_frame);
1487 if (!(
context->outfile->oformat->flags & AVFMT_NOFILE)) {
1488 avio_close(
context->outfile->pb);
1492 if (
context->video_codec !=
nullptr) {
1493 avcodec_free_context(&
context->video_codec);
1494 context->video_codec =
nullptr;
1496 if (
context->audio_codec !=
nullptr) {
1497 avcodec_free_context(&
context->audio_codec);
1498 context->audio_codec =
nullptr;
1501 if (
context->outfile !=
nullptr) {
1502 avformat_free_context(
context->outfile);
1505 if (
context->audio_input_buffer !=
nullptr) {
1506 av_free(
context->audio_input_buffer);
1507 context->audio_input_buffer =
nullptr;
1510 if (
context->audio_deinterleave_buffer !=
nullptr) {
1511 av_free(
context->audio_deinterleave_buffer);
1512 context->audio_deinterleave_buffer =
nullptr;
1515 if (
context->img_convert_ctx !=
nullptr) {
1516 ffmpeg_sws_release_context(
context->img_convert_ctx);
1517 context->img_convert_ctx =
nullptr;
1521static void ffmpeg_movie_close(MovieWriter *context)
1523 if (context ==
nullptr) {
1526 end_ffmpeg_impl(context,
false);
1530 MEM_delete(context);
1561 MovieWriter *writer =
nullptr;
1563 writer = ffmpeg_movie_open(scene, rd, rectx, recty,
reports, preview, suffix);
1578 if (writer ==
nullptr) {
1583 bool ok = ffmpeg_movie_append(writer, rd, start_frame, frame, image, suffix,
reports);
1595 ffmpeg_movie_close(writer);
1610 ffmpeg_get_filepath(filepath, rd, preview, suffix,
reports);
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()
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)
#define BLI_assert_msg(a, msg)
File and directory operations.
bool BLI_file_ensure_parent_dir_exists(const char *filepath) ATTR_NONNULL(1)
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
bool BLI_path_frame_range(char *path, size_t path_maxncpy, int sta, int end, int digits) ATTR_NONNULL(1)
#define SNPRINTF(dst, format,...)
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
int BLI_system_thread_count(void)
@ FFMPEG_AUTOSPLIT_OUTPUT
@ FFMPEG_USE_MAX_B_FRAMES
@ FFM_PRORES_PROFILE_422_PROXY
@ FFM_PRORES_PROFILE_4444_XQ
@ FFM_PRORES_PROFILE_422_HQ
@ FFM_PRORES_PROFILE_4444
Read Guarded memory(de)allocation.
BMesh const char void * data
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)
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)
int ffmpeg_prores_profile
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
struct ImageFormatData im_format
struct FFMpegCodecData ffcodecdata