Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/writeffmpeg.c
| Show First 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | |||||
| typedef struct FFMpegContext { | typedef struct FFMpegContext { | ||||
| int ffmpeg_type; | int ffmpeg_type; | ||||
| int ffmpeg_codec; | int ffmpeg_codec; | ||||
| int ffmpeg_audio_codec; | int ffmpeg_audio_codec; | ||||
| int ffmpeg_video_bitrate; | int ffmpeg_video_bitrate; | ||||
| int ffmpeg_audio_bitrate; | int ffmpeg_audio_bitrate; | ||||
| int ffmpeg_gop_size; | int ffmpeg_gop_size; | ||||
| int ffmpeg_max_b_frames; | |||||
| int ffmpeg_autosplit; | int ffmpeg_autosplit; | ||||
| int ffmpeg_autosplit_count; | int ffmpeg_autosplit_count; | ||||
| bool ffmpeg_preview; | bool ffmpeg_preview; | ||||
| int ffmpeg_crf; /* set to 0 to not use CRF mode; we have another flag for lossless anyway. */ | |||||
| int ffmpeg_preset; /* see FFMpegPreset */ | |||||
| AVFormatContext *outfile; | AVFormatContext *outfile; | ||||
| AVStream *video_stream; | AVStream *video_stream; | ||||
| AVStream *audio_stream; | AVStream *audio_stream; | ||||
| AVFrame *current_frame; | AVFrame *current_frame; | ||||
| struct SwsContext *img_convert_ctx; | struct SwsContext *img_convert_ctx; | ||||
| uint8_t *audio_input_buffer; | uint8_t *audio_input_buffer; | ||||
| uint8_t *audio_deinterleave_buffer; | uint8_t *audio_deinterleave_buffer; | ||||
| ▲ Show 20 Lines • Show All 471 Lines • ▼ Show 20 Lines | else if ((float) ((int) rd->frs_sec_base) == rd->frs_sec_base) { | ||||
| c->time_base.num = (int) rd->frs_sec_base; | c->time_base.num = (int) rd->frs_sec_base; | ||||
| } | } | ||||
| else { | else { | ||||
| c->time_base.den = rd->frs_sec * 100000; | c->time_base.den = rd->frs_sec * 100000; | ||||
| c->time_base.num = ((double) rd->frs_sec_base) * 100000; | c->time_base.num = ((double) rd->frs_sec_base) * 100000; | ||||
| } | } | ||||
| c->gop_size = context->ffmpeg_gop_size; | c->gop_size = context->ffmpeg_gop_size; | ||||
| c->max_b_frames = context->ffmpeg_max_b_frames; | |||||
| if (context->ffmpeg_crf >= 0) { | |||||
| ffmpeg_dict_set_int(&opts, "crf", context->ffmpeg_crf); | |||||
| } 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; | ||||
| 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) { | |||||
| char const * preset_name; | |||||
| switch(context->ffmpeg_preset) { | |||||
| case FFM_PRESET_ULTRAFAST: preset_name = "ultrafast"; break; | |||||
| case FFM_PRESET_SUPERFAST: preset_name = "superfast"; break; | |||||
| case FFM_PRESET_VERYFAST: preset_name = "veryfast"; break; | |||||
| case FFM_PRESET_FASTER: preset_name = "faster"; break; | |||||
| case FFM_PRESET_FAST: preset_name = "fast"; break; | |||||
| case FFM_PRESET_MEDIUM: preset_name = "medium"; break; | |||||
| case FFM_PRESET_SLOW: preset_name = "slow"; break; | |||||
| case FFM_PRESET_SLOWER: preset_name = "slower"; break; | |||||
| case FFM_PRESET_VERYSLOW: preset_name = "veryslow"; break; | |||||
| default: | |||||
| printf("Unknown preset number %i, ignoring.\n", context->ffmpeg_preset); | |||||
| preset_name = NULL; | |||||
| } | |||||
| if (preset_name != NULL) { | |||||
| av_dict_set(&opts, "preset", preset_name, 0); | |||||
| } | |||||
| } | |||||
| #if 0 | #if 0 | ||||
| /* this options are not set in ffmpeg.c and leads to artifacts with MPEG-4 | /* this options are not set in ffmpeg.c and leads to artifacts with MPEG-4 | ||||
| * see #33586: Encoding to mpeg4 makes first frame(s) blocky | * see #33586: Encoding to mpeg4 makes first frame(s) blocky | ||||
| */ | */ | ||||
| c->rc_initial_buffer_occupancy = rd->ffcodecdata.rc_buffer_size * 3 / 4; | c->rc_initial_buffer_occupancy = rd->ffcodecdata.rc_buffer_size * 3 / 4; | ||||
| c->rc_buffer_aggressivity = 1.0; | c->rc_buffer_aggressivity = 1.0; | ||||
| #endif | #endif | ||||
| ▲ Show 20 Lines • Show All 239 Lines • ▼ Show 20 Lines | static int start_ffmpeg_impl(FFMpegContext *context, struct RenderData *rd, int rectx, int recty, const char *suffix, ReportList *reports) | ||||
| context->ffmpeg_type = rd->ffcodecdata.type; | context->ffmpeg_type = rd->ffcodecdata.type; | ||||
| context->ffmpeg_codec = rd->ffcodecdata.codec; | context->ffmpeg_codec = rd->ffcodecdata.codec; | ||||
| context->ffmpeg_audio_codec = rd->ffcodecdata.audio_codec; | context->ffmpeg_audio_codec = rd->ffcodecdata.audio_codec; | ||||
| context->ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate; | context->ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate; | ||||
| context->ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate; | context->ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate; | ||||
| context->ffmpeg_gop_size = rd->ffcodecdata.gop_size; | context->ffmpeg_gop_size = rd->ffcodecdata.gop_size; | ||||
| context->ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT; | context->ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT; | ||||
| context->ffmpeg_crf = rd->ffcodecdata.constant_rate_factor; | |||||
| context->ffmpeg_preset = rd->ffcodecdata.ffmpeg_preset; | |||||
| if ((rd->ffcodecdata.flags & FFMPEG_USE_MAX_B_FRAMES) != 0) { | |||||
| context->ffmpeg_max_b_frames = rd->ffcodecdata.max_b_frames; | |||||
| } | |||||
| /* Determine the correct filename */ | /* Determine the correct filename */ | ||||
| ffmpeg_filepath_get(context, name, rd, context->ffmpeg_preview, suffix); | ffmpeg_filepath_get(context, name, rd, context->ffmpeg_preview, suffix); | ||||
| PRINT("Starting output to %s(ffmpeg)...\n" | PRINT("Starting output to %s(ffmpeg)...\n" | ||||
| " Using type=%d, codec=%d, audio_codec=%d,\n" | " Using type=%d, codec=%d, audio_codec=%d,\n" | ||||
| " video_bitrate=%d, audio_bitrate=%d,\n" | " video_bitrate=%d, audio_bitrate=%d,\n" | ||||
| " gop_size=%d, autosplit=%d\n" | " gop_size=%d, autosplit=%d\n" | ||||
| " render width=%d, render height=%d\n", | " render width=%d, render height=%d\n", | ||||
| Show All 17 Lines | if (!of) { | ||||
| BKE_report(reports, RPT_ERROR, "Error opening output file"); | BKE_report(reports, RPT_ERROR, "Error opening output file"); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| /* Returns after this must 'goto fail;' */ | /* Returns after this must 'goto fail;' */ | ||||
| of->oformat = fmt; | of->oformat = fmt; | ||||
| /* Only bother with setting packet size & mux rate when CRF is not used. */ | |||||
| if (context->ffmpeg_crf == 0) { | |||||
| of->packet_size = rd->ffcodecdata.mux_packet_size; | of->packet_size = rd->ffcodecdata.mux_packet_size; | ||||
| if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE) { | if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE) { | ||||
| ffmpeg_dict_set_int(&opts, "muxrate", rd->ffcodecdata.mux_rate); | ffmpeg_dict_set_int(&opts, "muxrate", rd->ffcodecdata.mux_rate); | ||||
| } | } | ||||
| else { | else { | ||||
| av_dict_set(&opts, "muxrate", "0", 0); | av_dict_set(&opts, "muxrate", "0", 0); | ||||
| } | } | ||||
| } | |||||
| ffmpeg_dict_set_int(&opts, "preload", (int)(0.5 * AV_TIME_BASE)); | ffmpeg_dict_set_int(&opts, "preload", (int)(0.5 * AV_TIME_BASE)); | ||||
| of->max_delay = (int)(0.7 * AV_TIME_BASE); | of->max_delay = (int)(0.7 * AV_TIME_BASE); | ||||
| fmt->audio_codec = context->ffmpeg_audio_codec; | fmt->audio_codec = context->ffmpeg_audio_codec; | ||||
| BLI_strncpy(of->filename, name, sizeof(of->filename)); | BLI_strncpy(of->filename, name, sizeof(of->filename)); | ||||
| ▲ Show 20 Lines • Show All 628 Lines • ▼ Show 20 Lines | #ifdef FFMPEG_HAVE_DEPRECATED_FLAGS2 | ||||
| BKE_ffmpeg_property_add_string(rd, "video", "directpred:3"); | BKE_ffmpeg_property_add_string(rd, "video", "directpred:3"); | ||||
| BKE_ffmpeg_property_add_string(rd, "video", "flags2:fastpskip"); | BKE_ffmpeg_property_add_string(rd, "video", "flags2:fastpskip"); | ||||
| BKE_ffmpeg_property_add_string(rd, "video", "flags2:wpred"); | BKE_ffmpeg_property_add_string(rd, "video", "flags2:wpred"); | ||||
| #else | #else | ||||
| BKE_ffmpeg_property_add_string(rd, "video", "8x8dct:1"); | BKE_ffmpeg_property_add_string(rd, "video", "8x8dct:1"); | ||||
| BKE_ffmpeg_property_add_string(rd, "video", "fast-pskip:1"); | BKE_ffmpeg_property_add_string(rd, "video", "fast-pskip:1"); | ||||
| BKE_ffmpeg_property_add_string(rd, "video", "wpredp:2"); | BKE_ffmpeg_property_add_string(rd, "video", "wpredp:2"); | ||||
| #endif | #endif | ||||
| if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT) { | |||||
| #ifdef FFMPEG_HAVE_DEPRECATED_FLAGS2 | |||||
| BKE_ffmpeg_property_add_string(rd, "video", "cqp:0"); | |||||
| #else | |||||
| BKE_ffmpeg_property_add_string(rd, "video", "qp:0"); | |||||
| #endif | |||||
| } | |||||
| } | } | ||||
| else if (codec_id == AV_CODEC_ID_DNXHD) { | else if (codec_id == AV_CODEC_ID_DNXHD) { | ||||
| if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT) | if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT) | ||||
| BKE_ffmpeg_property_add_string(rd, "video", "mbd:rd"); | BKE_ffmpeg_property_add_string(rd, "video", "mbd:rd"); | ||||
| } | } | ||||
| } | } | ||||
| void BKE_ffmpeg_preset_set(RenderData *rd, int preset) | void BKE_ffmpeg_preset_set(RenderData *rd, int preset) | ||||
| ▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | void BKE_ffmpeg_image_type_verify(RenderData *rd, ImageFormatData *imf) | ||||
| int audio = 0; | int audio = 0; | ||||
| if (imf->imtype == R_IMF_IMTYPE_FFMPEG) { | if (imf->imtype == R_IMF_IMTYPE_FFMPEG) { | ||||
| if (rd->ffcodecdata.type <= 0 || | if (rd->ffcodecdata.type <= 0 || | ||||
| rd->ffcodecdata.codec <= 0 || | rd->ffcodecdata.codec <= 0 || | ||||
| rd->ffcodecdata.audio_codec <= 0 || | rd->ffcodecdata.audio_codec <= 0 || | ||||
| rd->ffcodecdata.video_bitrate <= 1) | rd->ffcodecdata.video_bitrate <= 1) | ||||
| { | { | ||||
| rd->ffcodecdata.codec = AV_CODEC_ID_MPEG2VIDEO; | BKE_ffmpeg_preset_set(rd, FFMPEG_PRESET_H264); | ||||
| rd->ffcodecdata.constant_rate_factor = FFM_CRF_MEDIUM; | |||||
| BKE_ffmpeg_preset_set(rd, FFMPEG_PRESET_DVD); | rd->ffcodecdata.ffmpeg_preset = FFM_PRESET_MEDIUM; | ||||
| rd->ffcodecdata.type = FFMPEG_MKV; | |||||
| } | } | ||||
| if (rd->ffcodecdata.type == FFMPEG_OGG) { | if (rd->ffcodecdata.type == FFMPEG_OGG) { | ||||
| rd->ffcodecdata.type = FFMPEG_MPEG2; | rd->ffcodecdata.type = FFMPEG_MPEG2; | ||||
| } | } | ||||
| audio = 1; | audio = 1; | ||||
| } | } | ||||
| else if (imf->imtype == R_IMF_IMTYPE_H264) { | else if (imf->imtype == R_IMF_IMTYPE_H264) { | ||||
| ▲ Show 20 Lines • Show All 78 Lines • Show Last 20 Lines | |||||