Changeset View
Standalone View
source/blender/blenkernel/intern/writeffmpeg.c
| Show First 20 Lines • Show All 293 Lines • ▼ Show 20 Lines | switch (format) { | ||||||||
| case FFMPEG_OGG: { | case FFMPEG_OGG: { | ||||||||
| static const char *rv[] = {".ogv", ".ogg", NULL}; | static const char *rv[] = {".ogv", ".ogg", NULL}; | ||||||||
| return rv; | return rv; | ||||||||
| } | } | ||||||||
| case FFMPEG_WEBM: { | case FFMPEG_WEBM: { | ||||||||
| static const char *rv[] = {".webm", NULL}; | static const char *rv[] = {".webm", NULL}; | ||||||||
| return rv; | return rv; | ||||||||
| } | } | ||||||||
| case FFMPEG_AV1: { | |||||||||
| static const char *rv[] = {".mp4", ".mkv", NULL}; | |||||||||
| return rv; | |||||||||
| } | |||||||||
| default: | default: | ||||||||
| return NULL; | return NULL; | ||||||||
| } | } | ||||||||
| } | } | ||||||||
| /* Write a frame to the output file */ | /* Write a frame to the output file */ | ||||||||
| static int write_video_frame(FFMpegContext *context, AVFrame *frame, ReportList *reports) | static int write_video_frame(FFMpegContext *context, AVFrame *frame, ReportList *reports) | ||||||||
| { | { | ||||||||
| ▲ Show 20 Lines • Show All 140 Lines • ▼ Show 20 Lines | static AVRational calc_time_base(uint den, double num, int codec_id) | ||||||||
| AVRational time_base; | AVRational time_base; | ||||||||
| time_base.den = den; | time_base.den = den; | ||||||||
| time_base.num = (int)num; | time_base.num = (int)num; | ||||||||
| return time_base; | return time_base; | ||||||||
| } | } | ||||||||
| static const AVCodec *get_av1_encoder( | |||||||||
| FFMpegContext *context, RenderData *rd, AVDictionary **opts, int rectx, int recty) | |||||||||
| { | |||||||||
| /* There are three possible encoders for AV1: libaom-av1, librav1e, and libsvtav1. librav1e tends | |||||||||
| * to give the best compression quality while libsvtav1 tends to be the fastest encoder. One of | |||||||||
| * each will be picked based on the preset setting, and if a particular encoder is not available, | |||||||||
| * then use the default returned by FFMpeg. */ | |||||||||
| const AVCodec *codec = NULL; | |||||||||
| switch (context->ffmpeg_preset) { | |||||||||
| case FFM_PRESET_BEST: | |||||||||
| /* Default to libaom-av1 for BEST preset due to it performing better than rav1e in terms of | |||||||||
| * video quality (VMAF scores). Fallback to rav1e if libaom-av1 isn't available. */ | |||||||||
| codec = avcodec_find_encoder_by_name("libaom-av1"); | |||||||||
| if (!codec) { | |||||||||
| codec = avcodec_find_encoder_by_name("librav1e"); | |||||||||
| } | |||||||||
| break; | |||||||||
| case FFM_PRESET_REALTIME: | |||||||||
| codec = avcodec_find_encoder_by_name("libsvtav1"); | |||||||||
| break; | |||||||||
| case FFM_PRESET_GOOD: | |||||||||
| default: | |||||||||
| codec = avcodec_find_encoder_by_name("libaom-av1"); | |||||||||
| break; | |||||||||
| } | |||||||||
| /* Use the default AV1 encoder if the specified encoder wasn't found. */ | |||||||||
| if (!codec) { | |||||||||
| codec = avcodec_find_encoder(AV_CODEC_ID_AV1); | |||||||||
| } | |||||||||
| /* Apply AV1 encoder specific settings. */ | |||||||||
| if (codec) { | |||||||||
| if (strcmp(codec->name, "librav1e") == 0) { | |||||||||
| /* Set "tiles" to 8 to enable multi-threaded encoding. */ | |||||||||
zeddb: For the tile statements here, I would like to know who the numbers came to be.
Is `8` and `3x3`… | |||||||||
Done Inline Actions
From my understanding of it, "tiles" subdivides the frame such that each subdivision can be worked on by a separate thread. For librav1e, this is specified as the total number of subdivisions. For libaom-av1, this is specified for both X and Y axes (hence, the "3x3"). Actually, I will change this to "4x2", since the dimensions of a frame usually have multiple "2" factors in both axes, and "3x3" probably doesn't subdivide things optimally (either the implementation actually subdivides the frame into 9 pieces, or it is treated as a "maximum"). seodisparate: > For the tile statements here, I would like to know who the numbers came to be.
> Is `8` and… | |||||||||
| if (rd->threads > 8) { | |||||||||
| ffmpeg_dict_set_int(opts, "tiles", rd->threads); | |||||||||
| } | |||||||||
| else { | |||||||||
| ffmpeg_dict_set_int(opts, "tiles", 8); | |||||||||
| } | |||||||||
| /* Use a reasonable speed setting based on preset. Speed ranges from 0-10. | |||||||||
| * Must check context->ffmpeg_preset again in case this encoder was selected due to the | |||||||||
| * absence of another. */ | |||||||||
| switch (context->ffmpeg_preset) { | |||||||||
| case FFM_PRESET_BEST: | |||||||||
| ffmpeg_dict_set_int(opts, "speed", 4); | |||||||||
| break; | |||||||||
| case FFM_PRESET_REALTIME: | |||||||||
| ffmpeg_dict_set_int(opts, "speed", 10); | |||||||||
| break; | |||||||||
| case FFM_PRESET_GOOD: | |||||||||
| default: | |||||||||
| ffmpeg_dict_set_int(opts, "speed", 6); | |||||||||
| break; | |||||||||
| } | |||||||||
| if (context->ffmpeg_crf >= 0) { | |||||||||
| /* librav1e does not use -crf, but uses -qp in the range of 0-255. Calculates the roughly | |||||||||
| * equivalent float, and truncates it to an integer. */ | |||||||||
| unsigned int qp_value = ((float)context->ffmpeg_crf) * 255.0F / 51.0F; | |||||||||
| if (qp_value > 255) { | |||||||||
| qp_value = 255; | |||||||||
| } | |||||||||
| ffmpeg_dict_set_int(opts, "qp", qp_value); | |||||||||
| } | |||||||||
| /* Set gop_size as rav1e's "--keyint". */ | |||||||||
| char buffer[64]; | |||||||||
| BLI_snprintf(buffer, sizeof(buffer), "keyint=%d", context->ffmpeg_gop_size); | |||||||||
| av_dict_set(opts, "rav1e-params", buffer, 0); | |||||||||
| } | |||||||||
| else if (strcmp(codec->name, "libsvtav1") == 0) { | |||||||||
| /* Set preset value based on ffmpeg_preset. | |||||||||
| * Must check context->ffmpeg_preset again in case this encoder was selected due to the | |||||||||
| * absence of another. */ | |||||||||
| switch (context->ffmpeg_preset) { | |||||||||
| case FFM_PRESET_REALTIME: | |||||||||
| ffmpeg_dict_set_int(opts, "preset", 8); | |||||||||
| break; | |||||||||
| case FFM_PRESET_BEST: | |||||||||
| ffmpeg_dict_set_int(opts, "preset", 3); | |||||||||
| break; | |||||||||
| case FFM_PRESET_GOOD: | |||||||||
| default: | |||||||||
| ffmpeg_dict_set_int(opts, "preset", 5); | |||||||||
| break; | |||||||||
| } | |||||||||
| if (context->ffmpeg_crf >= 0) { | |||||||||
| /* libsvtav1 does not support crf until FFmpeg builds since 2022-02-24, use qp as fallback. | |||||||||
| */ | |||||||||
| ffmpeg_dict_set_int(opts, "qp", context->ffmpeg_crf); | |||||||||
| } | |||||||||
| } | |||||||||
| else if (strcmp(codec->name, "libaom-av1") == 0) { | |||||||||
| /* Speed up libaom-av1 encoding by enabling multithreading and setting tiles. */ | |||||||||
| ffmpeg_dict_set_int(opts, "row-mt", 1); | |||||||||
| const char *tiles_string = NULL; | |||||||||
| bool tiles_string_is_dynamic = false; | |||||||||
| if (rd->threads > 0) { | |||||||||
| /* See if threads is a square. */ | |||||||||
| int threads_sqrt = sqrtf(rd->threads); | |||||||||
| if (threads_sqrt < 4) { | |||||||||
| /* Ensure a default minimum. */ | |||||||||
| threads_sqrt = 4; | |||||||||
| } | |||||||||
| if (is_power_of_2_i(threads_sqrt) && threads_sqrt * threads_sqrt == rd->threads) { | |||||||||
| /* Is a square num, therefore just do "sqrt x sqrt" for tiles parameter. */ | |||||||||
| int digits = 0; | |||||||||
| for (int t_sqrt_copy = threads_sqrt; t_sqrt_copy > 0; t_sqrt_copy /= 10) { | |||||||||
| ++digits; | |||||||||
| } | |||||||||
| /* A char array need only an alignment of 1. */ | |||||||||
| char *tiles_string_mut = (char *)calloc(digits * 2 + 2, 1); | |||||||||
| BLI_snprintf(tiles_string_mut, digits * 2 + 2, "%dx%d", threads_sqrt, threads_sqrt); | |||||||||
| tiles_string_is_dynamic = true; | |||||||||
| tiles_string = tiles_string_mut; | |||||||||
| } | |||||||||
| else { | |||||||||
| /* Is not a square num, set greater side based on longer side, or use a square if both | |||||||||
| sides are equal. */ | |||||||||
| int sqrt_p2 = power_of_2_min_i(threads_sqrt); | |||||||||
| if (sqrt_p2 < 2) { | |||||||||
| /* Ensure a default minimum. */ | |||||||||
| sqrt_p2 = 2; | |||||||||
| } | |||||||||
| int sqrt_p2_next = power_of_2_min_i((int)rd->threads / sqrt_p2); | |||||||||
| if (sqrt_p2_next < 1) { | |||||||||
| sqrt_p2_next = 1; | |||||||||
| } | |||||||||
| if (sqrt_p2 > sqrt_p2_next) { | |||||||||
| /* Ensure sqrt_p2_next is greater or equal to sqrt_p2. */ | |||||||||
| int temp = sqrt_p2; | |||||||||
| sqrt_p2 = sqrt_p2_next; | |||||||||
| sqrt_p2_next = temp; | |||||||||
| } | |||||||||
| int combined_digits = 0; | |||||||||
| for (int sqrt_p2_copy = sqrt_p2; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) { | |||||||||
| ++combined_digits; | |||||||||
| } | |||||||||
| for (int sqrt_p2_copy = sqrt_p2_next; sqrt_p2_copy > 0; sqrt_p2_copy /= 10) { | |||||||||
| ++combined_digits; | |||||||||
| } | |||||||||
| /* A char array need only an alignment of 1. */ | |||||||||
| char *tiles_string_mut = (char *)calloc(combined_digits + 2, 1); | |||||||||
| if (rectx > recty) { | |||||||||
| BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2_next, sqrt_p2); | |||||||||
| } | |||||||||
| else if (rectx < recty) { | |||||||||
| BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2, sqrt_p2_next); | |||||||||
| } | |||||||||
| else { | |||||||||
| BLI_snprintf(tiles_string_mut, combined_digits + 2, "%dx%d", sqrt_p2, sqrt_p2); | |||||||||
| } | |||||||||
| tiles_string_is_dynamic = true; | |||||||||
| tiles_string = tiles_string_mut; | |||||||||
| } | |||||||||
| } | |||||||||
| else { | |||||||||
| /* Thread count unknown, default to 8. */ | |||||||||
| if (rectx > recty) { | |||||||||
| tiles_string = "4x2"; | |||||||||
| } | |||||||||
| else if (rectx < recty) { | |||||||||
| tiles_string = "2x4"; | |||||||||
| } | |||||||||
| else { | |||||||||
| tiles_string = "2x2"; | |||||||||
| } | |||||||||
| } | |||||||||
| av_dict_set(opts, "tiles", tiles_string, 0); | |||||||||
| if (tiles_string_is_dynamic) { | |||||||||
| free((void *)tiles_string); | |||||||||
| } | |||||||||
| /* libaom-av1 uses "cpu-used" instead of "preset" for defining compression quality. | |||||||||
| * This value is in a range from 0-8. 0 and 8 are extremes, but we will allow 8. | |||||||||
| * Must check context->ffmpeg_preset again in case this encoder was selected due to the | |||||||||
| * absence of another. */ | |||||||||
| switch (context->ffmpeg_preset) { | |||||||||
| case FFM_PRESET_REALTIME: | |||||||||
| ffmpeg_dict_set_int(opts, "cpu-used", 8); | |||||||||
| break; | |||||||||
| case FFM_PRESET_BEST: | |||||||||
| ffmpeg_dict_set_int(opts, "cpu-used", 4); | |||||||||
| break; | |||||||||
| case FFM_PRESET_GOOD: | |||||||||
| default: | |||||||||
| ffmpeg_dict_set_int(opts, "cpu-used", 6); | |||||||||
| break; | |||||||||
| } | |||||||||
| /* CRF related settings is similar to H264 for libaom-av1, so we will rely on those settings | |||||||||
| * applied later. */ | |||||||||
| } | |||||||||
| } | |||||||||
| return codec; | |||||||||
| } | |||||||||
| /* prepare a video stream for the output file */ | /* prepare a video stream for the output file */ | ||||||||
| static AVStream *alloc_video_stream(FFMpegContext *context, | static AVStream *alloc_video_stream(FFMpegContext *context, | ||||||||
| RenderData *rd, | RenderData *rd, | ||||||||
| int codec_id, | int codec_id, | ||||||||
| AVFormatContext *of, | AVFormatContext *of, | ||||||||
| int rectx, | int rectx, | ||||||||
| int recty, | int recty, | ||||||||
| Show All 9 Lines | static AVStream *alloc_video_stream(FFMpegContext *context, | ||||||||
| st = avformat_new_stream(of, NULL); | st = avformat_new_stream(of, NULL); | ||||||||
| if (!st) { | if (!st) { | ||||||||
| return NULL; | return NULL; | ||||||||
| } | } | ||||||||
| st->id = 0; | st->id = 0; | ||||||||
| /* Set up the codec context */ | /* Set up the codec context */ | ||||||||
| if (codec_id == AV_CODEC_ID_AV1) { | |||||||||
| /* Use get_av1_encoder() to get the ideal (hopefully) encoder for AV1 based | |||||||||
Done Inline Actions
Treat comments as sentences: start wit ha capital and end with a fullstop, It would also be very nice if you put the comment from the commit description to the comment explaining why libsvtav1 is used. Something like: /* Use prefer using libsvtav1 for AV1 encoding since it is faster than the default one (typically libaom-av1). * If the libsvtav1 is not available fall-back to the default codec. */ The reason for this is because the explanation which is put in the commit message becomes very hard to track down over time, while the comment in the code is always easily available. sergey: Treat comments as sentences: start wit ha capital and end with a fullstop,
It would also be… | |||||||||
| * on given parameters, and also set up opts. */ | |||||||||
| codec = get_av1_encoder(context, rd, &opts, rectx, recty); | |||||||||
| } | |||||||||
| else { | |||||||||
| codec = avcodec_find_encoder(codec_id); | codec = avcodec_find_encoder(codec_id); | ||||||||
| } | |||||||||
| if (!codec) { | if (!codec) { | ||||||||
| fprintf(stderr, "Couldn't find valid video codec\n"); | fprintf(stderr, "Couldn't find valid video codec\n"); | ||||||||
| context->video_codec = NULL; | context->video_codec = NULL; | ||||||||
| return NULL; | return NULL; | ||||||||
| } | } | ||||||||
| context->video_codec = avcodec_alloc_context3(codec); | context->video_codec = avcodec_alloc_context3(codec); | ||||||||
| AVCodecContext *c = context->video_codec; | AVCodecContext *c = context->video_codec; | ||||||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | else if (context->ffmpeg_crf >= 0) { | ||||||||
| * encoding with vp9 in crf mode. | * encoding with vp9 in crf mode. | ||||||||
| * Set this to always be zero for other codecs as well. | * Set this to always be zero for other codecs as well. | ||||||||
| * We don't care about bit rate in crf mode. */ | * We don't care about bit rate in crf mode. */ | ||||||||
| c->bit_rate = 0; | c->bit_rate = 0; | ||||||||
| ffmpeg_dict_set_int(&opts, "crf", context->ffmpeg_crf); | ffmpeg_dict_set_int(&opts, "crf", context->ffmpeg_crf); | ||||||||
| } | } | ||||||||
| else { | else { | ||||||||
| c->bit_rate = context->ffmpeg_video_bitrate * 1000; | c->bit_rate = context->ffmpeg_video_bitrate * 1000; | ||||||||
| c->rc_max_rate = rd->ffcodecdata.rc_max_rate * 1000; | c->rc_max_rate = rd->ffcodecdata.rc_max_rate * 1000; | ||||||||
Not Done Inline ActionsJust wondering, is there a more semantic way of checking the codec? As in, not string based, but maybe via some enum? sergey: Just wondering, is there a more semantic way of checking the codec? As in, not string based… | |||||||||
Done Inline ActionsTwo possible structs that have codec information is AVCodec[1] and AVCodecContext[2], but only the codec is enumerated, while the encoder/decoder appears to be only be query-able by its string name. [1]: https://ffmpeg.org/doxygen/trunk/structAVCodec.html seodisparate: Two possible structs that have codec information is AVCodec[1] and AVCodecContext[2], but only… | |||||||||
| c->rc_min_rate = rd->ffcodecdata.rc_min_rate * 1000; | c->rc_min_rate = rd->ffcodecdata.rc_min_rate * 1000; | ||||||||
| c->rc_buffer_size = rd->ffcodecdata.rc_buffer_size * 1024; | c->rc_buffer_size = rd->ffcodecdata.rc_buffer_size * 1024; | ||||||||
| } | } | ||||||||
| if (context->ffmpeg_preset) { | if (context->ffmpeg_preset) { | ||||||||
| /* 'preset' is used by h.264, 'deadline' is used by webm/vp9. I'm not | /* 'preset' is used by h.264, 'deadline' is used by webm/vp9. I'm not | ||||||||
| * setting those properties conditionally based on the video codec, | * setting those properties conditionally based on the video codec, | ||||||||
| * as the FFmpeg encoder simply ignores unknown settings anyway. */ | * as the FFmpeg encoder simply ignores unknown settings anyway. */ | ||||||||
| Show All 10 Lines | switch (context->ffmpeg_preset) { | ||||||||
| break; | break; | ||||||||
| case FFM_PRESET_REALTIME: | case FFM_PRESET_REALTIME: | ||||||||
| preset_name = "superfast"; | preset_name = "superfast"; | ||||||||
| deadline_name = "realtime"; | deadline_name = "realtime"; | ||||||||
| break; | break; | ||||||||
| default: | default: | ||||||||
| printf("Unknown preset number %i, ignoring.\n", context->ffmpeg_preset); | printf("Unknown preset number %i, ignoring.\n", context->ffmpeg_preset); | ||||||||
| } | } | ||||||||
| if (preset_name != NULL) { | /* "codec_id != AV_CODEC_ID_AV1" is required due to "preset" already being set by an AV1 codec. | ||||||||
| */ | |||||||||
| if (preset_name != NULL && codec_id != AV_CODEC_ID_AV1) { | |||||||||
| av_dict_set(&opts, "preset", preset_name, 0); | av_dict_set(&opts, "preset", preset_name, 0); | ||||||||
| } | } | ||||||||
| if (deadline_name != NULL) { | if (deadline_name != NULL) { | ||||||||
| av_dict_set(&opts, "deadline", deadline_name, 0); | av_dict_set(&opts, "deadline", deadline_name, 0); | ||||||||
| } | } | ||||||||
| } | } | ||||||||
| /* Be sure to use the correct pixel format(e.g. RGB, YUV) */ | /* Be sure to use the correct pixel format(e.g. RGB, YUV) */ | ||||||||
| ▲ Show 20 Lines • Show All 366 Lines • ▼ Show 20 Lines | case FFMPEG_H264: | ||||||||
| video_codec = AV_CODEC_ID_H264; | video_codec = AV_CODEC_ID_H264; | ||||||||
| break; | break; | ||||||||
| case FFMPEG_XVID: | case FFMPEG_XVID: | ||||||||
| video_codec = AV_CODEC_ID_MPEG4; | video_codec = AV_CODEC_ID_MPEG4; | ||||||||
| break; | break; | ||||||||
| case FFMPEG_FLV: | case FFMPEG_FLV: | ||||||||
| video_codec = AV_CODEC_ID_FLV1; | video_codec = AV_CODEC_ID_FLV1; | ||||||||
| break; | break; | ||||||||
| case FFMPEG_AV1: | |||||||||
| video_codec = AV_CODEC_ID_AV1; | |||||||||
| break; | |||||||||
| default: | default: | ||||||||
| /* These containers are not restricted to any specific codec types. | /* These containers are not restricted to any specific codec types. | ||||||||
| * Currently we expect these to be .avi, .mov, .mkv, and .mp4. | * Currently we expect these to be .avi, .mov, .mkv, and .mp4. | ||||||||
| */ | */ | ||||||||
| video_codec = context->ffmpeg_codec; | video_codec = context->ffmpeg_codec; | ||||||||
| break; | break; | ||||||||
| } | } | ||||||||
| ▲ Show 20 Lines • Show All 515 Lines • ▼ Show 20 Lines | case FFMPEG_PRESET_XVID: | ||||||||
| rd->ffcodecdata.video_bitrate = 6000; | rd->ffcodecdata.video_bitrate = 6000; | ||||||||
| rd->ffcodecdata.gop_size = is_ntsc ? 18 : 15; | rd->ffcodecdata.gop_size = is_ntsc ? 18 : 15; | ||||||||
| rd->ffcodecdata.rc_max_rate = 9000; | rd->ffcodecdata.rc_max_rate = 9000; | ||||||||
| rd->ffcodecdata.rc_min_rate = 0; | rd->ffcodecdata.rc_min_rate = 0; | ||||||||
| rd->ffcodecdata.rc_buffer_size = 224 * 8; | rd->ffcodecdata.rc_buffer_size = 224 * 8; | ||||||||
| rd->ffcodecdata.mux_packet_size = 2048; | rd->ffcodecdata.mux_packet_size = 2048; | ||||||||
| rd->ffcodecdata.mux_rate = 10080000; | rd->ffcodecdata.mux_rate = 10080000; | ||||||||
| break; | break; | ||||||||
| case FFMPEG_PRESET_AV1: | |||||||||
| rd->ffcodecdata.type = FFMPEG_AV1; | |||||||||
| rd->ffcodecdata.codec = AV_CODEC_ID_AV1; | |||||||||
| rd->ffcodecdata.video_bitrate = 6000; | |||||||||
| rd->ffcodecdata.gop_size = is_ntsc ? 18 : 15; | |||||||||
| rd->ffcodecdata.rc_max_rate = 9000; | |||||||||
| rd->ffcodecdata.rc_min_rate = 0; | |||||||||
| rd->ffcodecdata.rc_buffer_size = 224 * 8; | |||||||||
| rd->ffcodecdata.mux_packet_size = 2048; | |||||||||
| rd->ffcodecdata.mux_rate = 10080000; | |||||||||
| break; | |||||||||
| } | } | ||||||||
| } | } | ||||||||
| void BKE_ffmpeg_image_type_verify(RenderData *rd, const ImageFormatData *imf) | void BKE_ffmpeg_image_type_verify(RenderData *rd, const ImageFormatData *imf) | ||||||||
| { | { | ||||||||
| int audio = 0; | int audio = 0; | ||||||||
| if (imf->imtype == R_IMF_IMTYPE_FFMPEG) { | if (imf->imtype == R_IMF_IMTYPE_FFMPEG) { | ||||||||
| Show All 23 Lines | else if (imf->imtype == R_IMF_IMTYPE_XVID) { | ||||||||
| } | } | ||||||||
| } | } | ||||||||
| else if (imf->imtype == R_IMF_IMTYPE_THEORA) { | else if (imf->imtype == R_IMF_IMTYPE_THEORA) { | ||||||||
| if (rd->ffcodecdata.codec != AV_CODEC_ID_THEORA) { | if (rd->ffcodecdata.codec != AV_CODEC_ID_THEORA) { | ||||||||
| BKE_ffmpeg_preset_set(rd, FFMPEG_PRESET_THEORA); | BKE_ffmpeg_preset_set(rd, FFMPEG_PRESET_THEORA); | ||||||||
| audio = 1; | audio = 1; | ||||||||
| } | } | ||||||||
| } | } | ||||||||
| else if (imf->imtype == R_IMF_IMTYPE_AV1) { | |||||||||
| if (rd->ffcodecdata.codec != AV_CODEC_ID_AV1) { | |||||||||
| BKE_ffmpeg_preset_set(rd, FFMPEG_PRESET_AV1); | |||||||||
| audio = 1; | |||||||||
| } | |||||||||
| } | |||||||||
| if (audio && rd->ffcodecdata.audio_codec < 0) { | if (audio && rd->ffcodecdata.audio_codec < 0) { | ||||||||
| rd->ffcodecdata.audio_codec = AV_CODEC_ID_NONE; | rd->ffcodecdata.audio_codec = AV_CODEC_ID_NONE; | ||||||||
| rd->ffcodecdata.audio_bitrate = 128; | rd->ffcodecdata.audio_bitrate = 128; | ||||||||
| } | } | ||||||||
| } | } | ||||||||
| bool BKE_ffmpeg_alpha_channel_is_supported(const RenderData *rd) | bool BKE_ffmpeg_alpha_channel_is_supported(const RenderData *rd) | ||||||||
| ▲ Show 20 Lines • Show All 45 Lines • Show Last 20 Lines | |||||||||
For the tile statements here, I would like to know who the numbers came to be.
Is 8 and 3x3 some magic number that always scales well or could the be tweaked depending on the amount of CPUs available and the output resolution?