51static constexpr int64_t ffmpeg_autosplit_size = 2'000'000'000;
53static void ffmpeg_dict_set_int(AVDictionary **dict,
const char *key,
int value)
55 av_dict_set_int(dict, key, value, 0);
58static void ffmpeg_movie_close(MovieWriter *context);
59static bool ffmpeg_filepath_get(MovieWriter *context,
67static AVFrame *alloc_frame(AVPixelFormat pix_fmt,
int width,
int height)
69 AVFrame *f = av_frame_alloc();
77 if (av_frame_get_buffer(f, align) < 0) {
86static const char **get_file_extensions(
int format)
90 static const char *rv[] = {
".dv",
nullptr};
94 static const char *rv[] = {
".mpg",
".mpeg",
nullptr};
98 static const char *rv[] = {
".dvd",
".vob",
".mpg",
".mpeg",
nullptr};
102 static const char *rv[] = {
".mp4",
".mpg",
".mpeg",
nullptr};
106 static const char *rv[] = {
".avi",
nullptr};
110 static const char *rv[] = {
".mov",
nullptr};
115 static const char *rv[] = {
".avi",
nullptr};
121 static const char *rv[] = {
".avi",
nullptr};
125 static const char *rv[] = {
".flv",
nullptr};
129 static const char *rv[] = {
".mkv",
nullptr};
133 static const char *rv[] = {
".ogv",
".ogg",
nullptr};
137 static const char *rv[] = {
".webm",
nullptr};
141 static const char *rv[] = {
".mp4",
".mkv",
nullptr};
149static void add_hdr_mastering_display_metadata(AVCodecParameters *codecpar,
153 if (c->color_primaries != AVCOL_PRI_BT2020) {
157 int max_luminance = 0;
158 if (c->color_trc == AVCOL_TRC_ARIB_STD_B67) {
160 max_luminance = 1000;
162 else if (c->color_trc == AVCOL_TRC_SMPTEST2084) {
170 max_luminance = 1000;
173 max_luminance = 2000;
176 max_luminance = 4000;
179 max_luminance = 10000;
185 if (max_luminance == 0) {
189 AVPacketSideData *side_data = av_packet_side_data_new(&codecpar->coded_side_data,
190 &codecpar->nb_coded_side_data,
191 AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
192 sizeof(AVMasteringDisplayMetadata),
194 if (side_data ==
nullptr) {
195 CLOG_ERROR(&
LOG,
"Failed to attached mastering display metadata to stream");
199 AVMasteringDisplayMetadata *mastering_metadata =
reinterpret_cast<AVMasteringDisplayMetadata *
>(
203 mastering_metadata->has_primaries = 1;
204 mastering_metadata->display_primaries[0][0] = av_make_q(34000, 50000);
205 mastering_metadata->display_primaries[0][1] = av_make_q(16000, 50000);
206 mastering_metadata->display_primaries[1][0] = av_make_q(13250, 50000);
207 mastering_metadata->display_primaries[1][1] = av_make_q(34500, 50000);
208 mastering_metadata->display_primaries[2][0] = av_make_q(7500, 50000);
209 mastering_metadata->display_primaries[2][1] = av_make_q(3000, 50000);
211 mastering_metadata->white_point[0] = av_make_q(15635, 50000);
212 mastering_metadata->white_point[1] = av_make_q(16450, 50000);
214 mastering_metadata->has_luminance = 1;
215 mastering_metadata->min_luminance = av_make_q(1, 10000);
216 mastering_metadata->max_luminance = av_make_q(max_luminance, 1);
220static bool write_video_frame(MovieWriter *context, AVFrame *frame,
ReportList *reports)
222 int ret, success = 1;
223 AVPacket *packet = av_packet_alloc();
225 AVCodecContext *c =
context->video_codec;
227 frame->pts =
context->video_time;
230 char error_str[AV_ERROR_MAX_STRING_SIZE];
231 ret = avcodec_send_frame(c, frame);
234 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE,
ret);
240 ret = avcodec_receive_packet(c, packet);
242 if (
ret == AVERROR(EAGAIN) ||
ret == AVERROR_EOF) {
247 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE,
ret);
252 packet->stream_index =
context->video_stream->index;
253 av_packet_rescale_ts(packet, c->time_base,
context->video_stream->time_base);
254# ifdef FFMPEG_USE_DURATION_WORKAROUND
258 if (av_interleaved_write_frame(
context->outfile, packet) != 0) {
266 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE,
ret);
267 CLOG_INFO(&
LOG,
"ffmpeg: error writing video frame: %s", error_str);
270 av_packet_free(&packet);
286static ImBuf *alloc_imbuf_for_colorspace_transform(
const ImBuf *input_ibuf)
313 num_pixels * input_ibuf->
channels *
sizeof(
float));
336static AVFrame *generate_video_frame(MovieWriter *context,
const ImBuf *input_ibuf)
339 const bool use_float =
340 context->img_convert_frame !=
nullptr &&
341 !(
context->img_convert_frame->format == AV_PIX_FMT_RGBA &&
342 ELEM(
context->img_convert_frame->colorspace, AVCOL_SPC_RGB, AVCOL_SPC_UNSPECIFIED));
345 alloc_imbuf_for_colorspace_transform(input_ibuf) :
351 if ((!use_float && (pixels ==
nullptr)) || (use_float && (pixels_fl ==
nullptr))) {
352 if (image != input_ibuf) {
358 AVCodecParameters *codec =
context->video_stream->codecpar;
359 int height = codec->height;
362 if (
context->img_convert_frame !=
nullptr) {
364 rgb_frame =
context->img_convert_frame;
368 rgb_frame =
context->current_frame;
373 av_frame_make_writable(rgb_frame);
375 const size_t linesize_dst = rgb_frame->linesize[0];
383 rgb_frame->linesize[2] == linesize_dst &&
384 rgb_frame->linesize[3] == linesize_dst,
385 "ffmpeg frame should be 4 same size planes for a floating point image case");
386 for (
int y = 0;
y < height;
y++) {
387 size_t dst_offset = linesize_dst * (height -
y - 1);
388 float *dst_g =
reinterpret_cast<float *
>(rgb_frame->data[0] + dst_offset);
389 float *dst_b =
reinterpret_cast<float *
>(rgb_frame->data[1] + dst_offset);
390 float *dst_r =
reinterpret_cast<float *
>(rgb_frame->data[2] + dst_offset);
391 float *dst_a =
reinterpret_cast<float *
>(rgb_frame->data[3] + dst_offset);
392 const float *src = pixels_fl + image->
x *
y * 4;
395 for (
int x = 0;
x < image->
x;
x++) {
406 for (
int x = 0;
x < image->
x;
x++) {
418 const size_t linesize_src = rgb_frame->width * 4;
419 for (
int y = 0;
y < height;
y++) {
420 uint8_t *target = rgb_frame->data[0] + linesize_dst * (height -
y - 1);
421 const uint8_t *src = pixels + linesize_src *
y;
425 memcpy(target, src, linesize_src);
430 if (
context->img_convert_frame !=
nullptr) {
433 av_frame_make_writable(
context->current_frame);
434 ffmpeg_sws_scale_frame(
context->img_convert_ctx,
context->current_frame, rgb_frame);
437 if (image != input_ibuf) {
444static AVRational calc_time_base(
uint den,
double num, AVCodecID codec_id)
451 float eps = FLT_EPSILON;
452 const uint DENUM_MAX = (codec_id == AV_CODEC_ID_MPEG4) ? (1UL << 16) - 1 : (1UL << 31) - 1;
463 eps =
float(1 << num_integer_bits) * FLT_EPSILON;
467 const int max_num_shift =
fabsf(log10f(
eps));
469 const int max_den_shift = log10f(DENUM_MAX) - log10f(den);
470 const int max_iter =
min_ii(max_num_shift, max_den_shift);
479 AVRational time_base;
481 time_base.num = int(
num);
486static const AVCodec *get_av1_encoder(
487 MovieWriter *context,
const RenderData *rd, AVDictionary **opts,
int rectx,
int recty)
493 const AVCodec *codec =
nullptr;
494 switch (
context->ffmpeg_preset) {
498 codec = avcodec_find_encoder_by_name(
"librav1e");
501 codec = avcodec_find_encoder_by_name(
"libaom-av1");
505 codec = avcodec_find_encoder_by_name(
"libsvtav1");
509 codec = avcodec_find_encoder_by_name(
"libaom-av1");
515 codec = avcodec_find_encoder(AV_CODEC_ID_AV1);
520 if (
STREQ(codec->name,
"librav1e")) {
523 ffmpeg_dict_set_int(opts,
"tiles", rd->
threads);
526 ffmpeg_dict_set_int(opts,
"tiles", 8);
532 switch (
context->ffmpeg_preset) {
534 ffmpeg_dict_set_int(opts,
"speed", 4);
537 ffmpeg_dict_set_int(opts,
"speed", 10);
541 ffmpeg_dict_set_int(opts,
"speed", 6);
547 av_dict_set(opts,
"rav1e-params", buffer, 0);
549 else if (
STREQ(codec->name,
"libsvtav1")) {
553 switch (
context->ffmpeg_preset) {
555 ffmpeg_dict_set_int(opts,
"preset", 8);
558 ffmpeg_dict_set_int(opts,
"preset", 3);
562 ffmpeg_dict_set_int(opts,
"preset", 5);
566 else if (
STREQ(codec->name,
"libaom-av1")) {
568 ffmpeg_dict_set_int(opts,
"row-mt", 1);
569 const char *tiles_string =
nullptr;
570 bool tiles_string_is_dynamic =
false;
574 if (threads_sqrt < 4) {
581 for (
int t_sqrt_copy = threads_sqrt; t_sqrt_copy > 0; t_sqrt_copy /= 10) {
585 char *tiles_string_mut = (
char *)calloc(digits * 2 + 2, 1);
586 BLI_snprintf_utf8(tiles_string_mut, digits * 2 + 2,
"%dx%d", threads_sqrt, threads_sqrt);
587 tiles_string_is_dynamic =
true;
588 tiles_string = tiles_string_mut;
599 if (sqrt_p2_next < 1) {
602 if (sqrt_p2 > sqrt_p2_next) {
605 sqrt_p2 = sqrt_p2_next;
608 int combined_digits = 0;
609 for (
int sqrt_p2_copy = sqrt_p2; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) {
612 for (
int sqrt_p2_copy = sqrt_p2_next; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) {
616 char *tiles_string_mut = (
char *)calloc(combined_digits + 2, 1);
619 tiles_string_mut, combined_digits + 2,
"%dx%d", sqrt_p2_next, sqrt_p2);
621 else if (rectx < recty) {
623 tiles_string_mut, combined_digits + 2,
"%dx%d", sqrt_p2, sqrt_p2_next);
626 BLI_snprintf_utf8(tiles_string_mut, combined_digits + 2,
"%dx%d", sqrt_p2, sqrt_p2);
628 tiles_string_is_dynamic =
true;
629 tiles_string = tiles_string_mut;
635 tiles_string =
"4x2";
637 else if (rectx < recty) {
638 tiles_string =
"2x4";
641 tiles_string =
"2x2";
644 av_dict_set(opts,
"tiles", tiles_string, 0);
645 if (tiles_string_is_dynamic) {
646 free((
void *)tiles_string);
652 switch (
context->ffmpeg_preset) {
654 ffmpeg_dict_set_int(opts,
"cpu-used", 8);
657 ffmpeg_dict_set_int(opts,
"cpu-used", 4);
661 ffmpeg_dict_set_int(opts,
"cpu-used", 6);
672static int remap_crf_to_h265_crf(
int crf,
bool is_10_or_12_bpp)
675 const int bias = is_10_or_12_bpp ? -3 : 0;
693static const AVCodec *get_prores_encoder(
const ImageFormatData *imf,
int rectx,
int recty)
699 if ((
size_t(rectx) *
size_t(recty)) > (3840 * 2160)) {
700 return avcodec_find_encoder_by_name(
"prores_ks");
703 return avcodec_find_encoder_by_name(
"prores_aw");
708static int remap_crf_to_h264_10bpp_crf(
int crf)
710 crf = int(-12.0f + (crf / 51.0f) * 63.0f);
715static void set_quality_rate_options(
const MovieWriter *context,
716 const AVCodecID codec_id,
721 AVCodecContext *c =
context->video_codec;
725 c->bit_rate =
context->ffmpeg_video_bitrate * 1000;
738 const bool av1_librav1e = codec_id == AV_CODEC_ID_AV1 &&
STREQ(c->codec->name,
"librav1e");
739 const bool av1_libsvtav1 = codec_id == AV_CODEC_ID_AV1 &&
STREQ(c->codec->name,
"libsvtav1");
743 if (codec_id == AV_CODEC_ID_VP9) {
745 ffmpeg_dict_set_int(opts,
"lossless", 1);
747 else if (codec_id == AV_CODEC_ID_H264 && is_10_bpp) {
749 ffmpeg_dict_set_int(opts,
"qp", 0);
751 else if (codec_id == AV_CODEC_ID_H265) {
753 av_dict_set(opts,
"x265-params",
"log-level=1:lossless=1", 0);
755 else if (codec_id == AV_CODEC_ID_AV1 && (av1_librav1e || av1_libsvtav1)) {
757 ffmpeg_dict_set_int(opts,
"qp", 0);
761 ffmpeg_dict_set_int(opts,
"crf", 0);
769 if (codec_id == AV_CODEC_ID_H264 && is_10_bpp) {
770 crf = remap_crf_to_h264_10bpp_crf(crf);
772 else if (codec_id == AV_CODEC_ID_H265) {
773 crf = remap_crf_to_h265_crf(crf, is_10_bpp || is_12_bpp);
775 av_dict_set(opts,
"x265-params",
"log-level=1", 0);
780 int qp = int(
float(crf) / 51.0f * 255.0f);
782 ffmpeg_dict_set_int(opts,
"qp", qp);
784 else if (av1_libsvtav1) {
786 ffmpeg_dict_set_int(opts,
"qp", crf);
789 ffmpeg_dict_set_int(opts,
"crf", crf);
793static void set_colorspace_options(AVCodecContext *c,
const ColorSpace *colorspace)
795 const AVPixFmtDescriptor *pix_fmt_desc = av_pix_fmt_desc_get(c->pix_fmt);
796 const bool is_rgb_format = (pix_fmt_desc->flags & AV_PIX_FMT_FLAG_RGB);
797 const bool rgb_matrix =
false;
804 c->color_primaries = AVColorPrimaries(cicp[0]);
805 c->color_trc = AVColorTransferCharacteristic(cicp[1]);
806 c->colorspace = (is_rgb_format) ? AVCOL_SPC_RGB : AVColorSpace(cicp[2]);
807 c->color_range = AVCOL_RANGE_JPEG;
809 else if (!is_rgb_format) {
813 c->color_primaries = AVCOL_PRI_BT709;
814 c->color_trc = AVCOL_TRC_BT709;
815 c->colorspace = AVCOL_SPC_BT709;
817 c->color_range = AVCOL_RANGE_MPEG;
824static AVStream *alloc_video_stream(MovieWriter *context,
835 const AVCodec *codec;
836 AVDictionary *opts =
nullptr;
840 st = avformat_new_stream(of,
nullptr);
848 if (codec_id == AV_CODEC_ID_AV1) {
851 codec = get_av1_encoder(context, rd, &opts, rectx, recty);
853 else if (codec_id == AV_CODEC_ID_PRORES) {
854 codec = get_prores_encoder(imf, rectx, recty);
857 codec = avcodec_find_encoder(codec_id);
861 context->video_codec =
nullptr;
865 context->video_codec = avcodec_alloc_context3(codec);
866 AVCodecContext *c =
context->video_codec;
875 c->time_base.den = 2997;
876 c->time_base.num = 100;
879 c->time_base.den = rd->
frs_sec;
892 if (c->time_base.num != 1) {
893 AVRational new_time_base;
895 &new_time_base.num, &new_time_base.den, c->time_base.num, c->time_base.den, INT_MAX))
898 c->time_base = new_time_base;
902 st->time_base = c->time_base;
904 c->gop_size =
context->ffmpeg_gop_size;
905 c->max_b_frames =
context->ffmpeg_max_b_frames;
907 set_quality_rate_options(context, codec_id, &rd->
ffcodecdata, imf, &opts);
913 char const *preset_name =
nullptr;
914 char const *deadline_name =
nullptr;
915 switch (
context->ffmpeg_preset) {
917 preset_name =
"medium";
918 deadline_name =
"good";
921 preset_name =
"slower";
922 deadline_name =
"best";
925 preset_name =
"superfast";
926 deadline_name =
"realtime";
933 if (preset_name !=
nullptr && codec_id != AV_CODEC_ID_AV1) {
934 av_dict_set(&opts,
"preset", preset_name, 0);
936 if (deadline_name !=
nullptr) {
937 av_dict_set(&opts,
"deadline", deadline_name, 0);
945 c->pix_fmt = pix_fmts[0];
949 c->pix_fmt = AV_PIX_FMT_YUV422P;
957 c->pix_fmt = AV_PIX_FMT_YUV420P10LE;
959 else if (is_12_bpp) {
960 c->pix_fmt = AV_PIX_FMT_YUV420P12LE;
965 c->pix_fmt = AV_PIX_FMT_YUV420P;
966 c->codec_tag = ((
'D' << 24) + (
'I' << 16) + (
'V' << 8) +
'X');
969 if (codec_id == AV_CODEC_ID_H265) {
974 c->codec_tag = MKTAG(
'h',
'v',
'c',
'1');
978 if (codec_id == AV_CODEC_ID_HUFFYUV) {
980 c->pix_fmt = AV_PIX_FMT_BGRA;
983 c->pix_fmt = AV_PIX_FMT_RGB32;
987 if (codec_id == AV_CODEC_ID_DNXHD) {
994 if (codec_id == AV_CODEC_ID_FFV1) {
996 c->pix_fmt = AV_PIX_FMT_GRAY8;
998 c->pix_fmt = AV_PIX_FMT_GRAY10;
1000 else if (is_12_bpp) {
1001 c->pix_fmt = AV_PIX_FMT_GRAY12;
1003 else if (is_16_bpp) {
1004 c->pix_fmt = AV_PIX_FMT_GRAY16;
1008 c->pix_fmt = AV_PIX_FMT_RGB32;
1010 c->pix_fmt = AV_PIX_FMT_GBRAP10;
1012 else if (is_12_bpp) {
1013 c->pix_fmt = AV_PIX_FMT_GBRAP12;
1015 else if (is_16_bpp) {
1016 c->pix_fmt = AV_PIX_FMT_GBRAP16;
1020 c->pix_fmt = AV_PIX_FMT_0RGB32;
1022 c->pix_fmt = AV_PIX_FMT_GBRP10;
1024 else if (is_12_bpp) {
1025 c->pix_fmt = AV_PIX_FMT_GBRP12;
1027 else if (is_16_bpp) {
1028 c->pix_fmt = AV_PIX_FMT_GBRP16;
1033 if (codec_id == AV_CODEC_ID_QTRLE) {
1035 c->pix_fmt = AV_PIX_FMT_GRAY8;
1038 c->pix_fmt = AV_PIX_FMT_ARGB;
1041 c->pix_fmt = AV_PIX_FMT_RGB24;
1046 c->pix_fmt = AV_PIX_FMT_YUVA420P;
1048 else if (
ELEM(codec_id, AV_CODEC_ID_H264, AV_CODEC_ID_H265, AV_CODEC_ID_VP9, AV_CODEC_ID_AV1) &&
1052 c->pix_fmt = AV_PIX_FMT_YUV444P;
1054 c->pix_fmt = AV_PIX_FMT_YUV444P10LE;
1056 else if (is_12_bpp) {
1057 c->pix_fmt = AV_PIX_FMT_YUV444P12LE;
1061 if (codec_id == AV_CODEC_ID_PNG) {
1063 c->pix_fmt = AV_PIX_FMT_GRAY8;
1066 c->pix_fmt = AV_PIX_FMT_RGBA;
1069 c->pix_fmt = AV_PIX_FMT_RGB24;
1072 if (codec_id == AV_CODEC_ID_PRORES) {
1076 c->profile =
context->ffmpeg_profile;
1077 c->pix_fmt = AV_PIX_FMT_YUV422P10LE;
1082 c->profile =
context->ffmpeg_profile;
1083 c->pix_fmt = AV_PIX_FMT_YUV444P10LE;
1086 c->pix_fmt = AV_PIX_FMT_YUVA444P10LE;
1094 if (of->oformat->flags & AVFMT_GLOBALHEADER) {
1096 c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
1102 set_colorspace_options(c, display_colorspace);
1106 st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q((
double(rd->
xasp) /
double(rd->
yasp)),
1108 st->avg_frame_rate = av_inv_q(c->time_base);
1110 if (codec->capabilities & AV_CODEC_CAP_OTHER_THREADS) {
1111 c->thread_count = 0;
1114 c->thread_count = MOV_thread_count();
1117 if (codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) {
1118 c->thread_type = FF_THREAD_FRAME;
1120 else if (codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
1121 c->thread_type = FF_THREAD_SLICE;
1124 int ret = avcodec_open2(c, codec, &opts);
1127 char error_str[AV_ERROR_MAX_STRING_SIZE];
1128 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE,
ret);
1129 CLOG_ERROR(&
LOG,
"Couldn't initialize video codec: %s\n", error_str);
1131 av_dict_free(&opts);
1132 avcodec_free_context(&c);
1133 context->video_codec =
nullptr;
1136 av_dict_free(&opts);
1139 context->current_frame = alloc_frame(c->pix_fmt, c->width, c->height);
1141 if (c->pix_fmt == AV_PIX_FMT_RGBA &&
ELEM(c->colorspace, AVCOL_SPC_RGB, AVCOL_SPC_UNSPECIFIED)) {
1143 context->img_convert_frame =
nullptr;
1144 context->img_convert_ctx =
nullptr;
1149 const AVPixelFormat src_format = is_10_bpp || is_12_bpp || is_16_bpp ? AV_PIX_FMT_GBRAPF32LE :
1151 context->img_convert_frame = alloc_frame(src_format, c->width, c->height);
1152 context->img_convert_ctx = ffmpeg_sws_get_context(
1161 c->color_range == AVCOL_RANGE_JPEG,
1162 c->colorspace != AVCOL_SPC_RGB ? c->colorspace : -1,
1166 avcodec_parameters_from_context(st->codecpar, c);
1168 add_hdr_mastering_display_metadata(st->codecpar, c, imf);
1175static void ffmpeg_add_metadata_callback(
void *
data,
1176 const char *propname,
1180 AVDictionary **metadata = (AVDictionary **)
data;
1181 av_dict_set(metadata, propname, propvalue, 0);
1184static bool start_ffmpeg_impl(MovieWriter *context,
1194 AVFormatContext *of;
1195 const AVOutputFormat *fmt;
1202 context->ffmpeg_audio_codec = mov_av_codec_id_get(rd->
ffcodecdata.audio_codec_id_get());
1216 if (!ffmpeg_filepath_get(context, filepath, scene, rd,
context->ffmpeg_preview, suffix, reports))
1221 "ffmpeg: starting output to %s:\n"
1222 " type=%d, codec=%d, audio_codec=%d,\n"
1223 " video_bitrate=%d, audio_bitrate=%d,\n"
1224 " gop_size=%d, autosplit=%d\n"
1225 " width=%d, height=%d",
1230 context->ffmpeg_video_bitrate,
1231 context->ffmpeg_audio_bitrate,
1238 exts = get_file_extensions(
context->ffmpeg_type);
1244 fmt = av_guess_format(
nullptr, exts[0],
nullptr);
1250 of = avformat_alloc_context();
1256 enum AVCodecID audio_codec =
context->ffmpeg_audio_codec;
1257 enum AVCodecID video_codec =
context->ffmpeg_codec;
1259 of->url = av_strdup(filepath);
1261 switch (
context->ffmpeg_type) {
1263 video_codec = AV_CODEC_ID_THEORA;
1266 video_codec = AV_CODEC_ID_DVVIDEO;
1269 video_codec = AV_CODEC_ID_MPEG1VIDEO;
1272 video_codec = AV_CODEC_ID_MPEG2VIDEO;
1275 video_codec = AV_CODEC_ID_H264;
1278 video_codec = AV_CODEC_ID_MPEG4;
1281 video_codec = AV_CODEC_ID_FLV1;
1284 video_codec = AV_CODEC_ID_AV1;
1289 video_codec =
context->ffmpeg_codec;
1295# if LIBAVFORMAT_VERSION_MAJOR >= 59
1299 of->oformat = (AVOutputFormat *)fmt;
1302 if (video_codec == AV_CODEC_ID_DVVIDEO) {
1307 if (rd->
frs_sec != 25 && recty != 480) {
1311 if (rd->
frs_sec == 25 && recty != 576) {
1318 audio_codec = AV_CODEC_ID_PCM_S16LE;
1319 if (
context->ffmpeg_audio_codec != AV_CODEC_ID_NONE &&
1327 if (video_codec == AV_CODEC_ID_PRORES) {
1331 if (video_codec != AV_CODEC_ID_NONE) {
1332 context->video_stream = alloc_video_stream(
1333 context, rd, imf, video_codec, of, rectx, recty,
error,
sizeof(
error));
1348 if (
context->ffmpeg_audio_codec != AV_CODEC_ID_NONE) {
1349 context->audio_stream = alloc_audio_stream(context,
1368 if (!(fmt->flags & AVFMT_NOFILE)) {
1369 if (avio_open(&of->pb, filepath, AVIO_FLAG_WRITE) < 0) {
1371 CLOG_INFO(&
LOG,
"ffmpeg: could not open file %s for writing", filepath);
1376 if (
context->stamp_data !=
nullptr) {
1378 &of->metadata,
context->stamp_data, ffmpeg_add_metadata_callback,
false);
1381 ret = avformat_write_header(of,
nullptr);
1385 "Could not initialize streams, probably unsupported codec combination");
1386 char error_str[AV_ERROR_MAX_STRING_SIZE];
1387 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE,
ret);
1388 CLOG_INFO(&
LOG,
"ffmpeg: could not write media header: %s", error_str);
1393 av_dump_format(of, 0, filepath, 1);
1402 context->video_stream =
nullptr;
1403 context->audio_stream =
nullptr;
1405 avformat_free_context(of);
1413static void flush_delayed_frames(AVCodecContext *c, AVStream *stream, AVFormatContext *outfile)
1415 char error_str[AV_ERROR_MAX_STRING_SIZE];
1416 AVPacket *packet = av_packet_alloc();
1418 avcodec_send_frame(c,
nullptr);
1423 ret = avcodec_receive_packet(c, packet);
1425 if (
ret == AVERROR(EAGAIN) ||
ret == AVERROR_EOF) {
1430 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE,
ret);
1431 CLOG_ERROR(&
LOG,
"Error encoding delayed frame: %s", error_str);
1435 packet->stream_index = stream->index;
1436 av_packet_rescale_ts(packet, c->time_base, stream->time_base);
1437# ifdef FFMPEG_USE_DURATION_WORKAROUND
1441 int write_ret = av_interleaved_write_frame(outfile, packet);
1442 if (write_ret != 0) {
1443 av_make_error_string(error_str, AV_ERROR_MAX_STRING_SIZE,
ret);
1444 CLOG_ERROR(&
LOG,
"Error writing delayed frame: %s", error_str);
1449 av_packet_free(&packet);
1459static bool ffmpeg_filepath_get(MovieWriter *context,
1470 const char **fe = exts;
1473 if (!filepath || !exts) {
1493 filepath,
FILE_MAX, template_variables);
1502 CLOG_ERROR(&
LOG,
"Couldn't create directory for file %s: %s", filepath, std::strerror(errno));
1506 autosplit[0] =
'\0';
1516 if (
BLI_strcasecmp(filepath + strlen(filepath) - strlen(*fe), *fe) == 0) {
1522 if (*fe ==
nullptr) {
1529 *(filepath + strlen(filepath) - strlen(*fe)) =
'\0';
1547static void ffmpeg_get_filepath(
char filepath[ 1024],
1554 ffmpeg_filepath_get(
nullptr, filepath, scene, rd, preview, suffix, reports);
1557static MovieWriter *ffmpeg_movie_open(
const Scene *scene,
1566 MovieWriter *
context = MEM_new<MovieWriter>(
"new FFMPEG context");
1568 context->ffmpeg_codec = AV_CODEC_ID_MPEG4;
1569 context->ffmpeg_audio_codec = AV_CODEC_ID_NONE;
1570 context->ffmpeg_video_bitrate = 1150;
1571 context->ffmpeg_audio_bitrate = 128;
1572 context->ffmpeg_gop_size = 12;
1573 context->ffmpeg_autosplit =
false;
1574 context->stamp_data =
nullptr;
1575 context->audio_time_total = 0.0;
1577 context->ffmpeg_autosplit_count = 0;
1578 context->ffmpeg_preview = preview;
1581 bool success = start_ffmpeg_impl(context, scene, rd, imf, rectx, recty, suffix, reports);
1584 success = movie_audio_open(context,
1593 ffmpeg_movie_close(context);
1599static void end_ffmpeg_impl(MovieWriter *context,
bool is_autosplit);
1601static bool ffmpeg_movie_append(MovieWriter *context,
1612 bool success =
true;
1614 CLOG_INFO(&
LOG,
"ffmpeg: writing frame #%i (%ix%i)", frame, image->
x, image->
y);
1617 avframe = generate_video_frame(context, image);
1618 success = (avframe && write_video_frame(context, avframe, reports));
1627 if (
context->ffmpeg_autosplit) {
1628 if (avio_tell(
context->outfile->pb) > ffmpeg_autosplit_size) {
1629 end_ffmpeg_impl(context,
true);
1630 context->ffmpeg_autosplit_count++;
1632 success &= start_ffmpeg_impl(context, scene, rd, imf, image->
x, image->
y, suffix, reports);
1639static void end_ffmpeg_impl(MovieWriter *context,
bool is_autosplit)
1643 movie_audio_close(context, is_autosplit);
1656 av_write_trailer(
context->outfile);
1661 context->video_stream =
nullptr;
1662 context->audio_stream =
nullptr;
1664 av_frame_free(&
context->current_frame);
1665 av_frame_free(&
context->img_convert_frame);
1668 if (!(
context->outfile->oformat->flags & AVFMT_NOFILE)) {
1669 avio_close(
context->outfile->pb);
1673 if (
context->video_codec !=
nullptr) {
1674 avcodec_free_context(&
context->video_codec);
1675 context->video_codec =
nullptr;
1677 if (
context->audio_codec !=
nullptr) {
1678 avcodec_free_context(&
context->audio_codec);
1679 context->audio_codec =
nullptr;
1682 if (
context->outfile !=
nullptr) {
1683 avformat_free_context(
context->outfile);
1686 if (
context->audio_input_buffer !=
nullptr) {
1687 av_free(
context->audio_input_buffer);
1688 context->audio_input_buffer =
nullptr;
1691 if (
context->audio_deinterleave_buffer !=
nullptr) {
1692 av_free(
context->audio_deinterleave_buffer);
1693 context->audio_deinterleave_buffer =
nullptr;
1696 if (
context->img_convert_ctx !=
nullptr) {
1697 ffmpeg_sws_release_context(
context->img_convert_ctx);
1698 context->img_convert_ctx =
nullptr;
1702static void ffmpeg_movie_close(MovieWriter *context)
1704 if (context ==
nullptr) {
1707 end_ffmpeg_impl(context,
false);
1711 MEM_delete(context);
1730 MovieWriter *writer =
nullptr;
1732 writer = ffmpeg_movie_open(scene, rd, imf, rectx, recty, reports, preview, suffix);
1734 UNUSED_VARS(scene, rd, imf, rectx, recty, reports, preview, suffix);
1749 if (writer ==
nullptr) {
1754 bool ok = ffmpeg_movie_append(
1755 writer, scene, rd, imf, start_frame, frame, image, suffix, reports);
1758 UNUSED_VARS(scene, rd, imf, start_frame, frame, image, suffix, reports);
1767 ffmpeg_movie_close(writer);
1783 ffmpeg_get_filepath(filepath, scene, 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 evaluating template expressions in filepaths.
void BKE_report_path_template_errors(ReportList *reports, eReportType report_type, blender::StringRef path, blender::Span< blender::bke::path_templates::Error > errors)
void BKE_add_template_variables_for_render_path(blender::bke::path_templates::VariableMap &variables, const Scene &scene)
void BKE_add_template_variables_general(blender::bke::path_templates::VariableMap &variables, const ID *path_owner_id)
blender::Vector< blender::bke::path_templates::Error > BKE_path_apply_template(char *path, int path_maxncpy, const blender::bke::path_templates::VariableMap &template_variables)
void BKE_report(ReportList *reports, eReportType type, const char *message)
blender::ocio::ColorSpace ColorSpace
#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
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
size_t size_t size_t BLI_snprintf_utf8(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
#define SNPRINTF_UTF8(dst, format,...)
#define CLOG_ERROR(clg_ref,...)
#define CLOG_WARN(clg_ref,...)
#define CLOG_STR_INFO(clg_ref, str)
#define CLOG_INFO(clg_ref,...)
@ 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
bool IMB_colormanagement_space_to_cicp(const ColorSpace *colorspace, const ColorManagedFileOutput output, const bool rgb_matrix, int cicp[4])
const ColorSpace * IMB_colormangement_display_get_color_space(const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings)
void IMB_assign_float_buffer(ImBuf *ibuf, float *buffer_data, ImBufOwnership ownership)
bool IMB_alpha_affects_rgb(const ImBuf *ibuf)
void IMB_buffer_float_from_byte(float *rect_to, const unsigned char *rect_from, int profile_to, int profile_from, bool predivide, int width, int height, int stride_to, int stride_from)
void IMB_freeImBuf(ImBuf *ibuf)
size_t IMB_get_pixel_count(const ImBuf *ibuf)
Get the length of the data of the given image buffer in pixels.
ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
@ IB_alphamode_channel_packed
Read Guarded memory(de)allocation.
BMesh const char void * data
static constexpr int64_t not_found
constexpr int64_t find(char c, int64_t pos=0) const
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)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
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)
void MOV_write_end(MovieWriter *writer)
void MOV_filepath_from_settings(char filepath[1024], const Scene *scene, const RenderData *rd, bool preview, const char *suffix, ReportList *reports)
MovieWriter * MOV_write_begin(const Scene *scene, const RenderData *rd, const ImageFormatData *imf, int rectx, int recty, ReportList *reports, bool preview, const char *suffix)
bool MOV_write_append(MovieWriter *writer, const Scene *scene, const RenderData *rd, const ImageFormatData *imf, int start_frame, int frame, const ImBuf *image, const char *suffix, ReportList *reports)
int context(const bContext *C, const char *member, bContextDataResult *result)
int ffmpeg_prores_profile
const ColorSpace * colorspace
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
struct ImageFormatData im_format
struct FFMpegCodecData ffcodecdata