[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [43964] trunk/blender/source/blender: FFmpeg output fixes and small improvement

Sergey Sharybin sergey.vfx at gmail.com
Tue Feb 7 18:11:57 CET 2012


Revision: 43964
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=43964
Author:   nazgul
Date:     2012-02-07 17:11:56 +0000 (Tue, 07 Feb 2012)
Log Message:
-----------
FFmpeg output fixes and small improvement

Most part of this commit fixes issues with FFmpeg output with
currently supported codecs:

- avcodec_encode_video might return zero which doesn't mean error
  happened, but blender will handle this as error and will stop
  rendering to video file.
- Changing output video codec wouldn't update "expert" options
  set for video output which leads to some sideeffects like
  ignored Lossless option for x264 codec.

This fixes allowed to add QTRLE codec easily.

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_writeffmpeg.h
    trunk/blender/source/blender/blenkernel/intern/writeffmpeg.c
    trunk/blender/source/blender/makesrna/intern/rna_scene.c

Modified: trunk/blender/source/blender/blenkernel/BKE_writeffmpeg.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_writeffmpeg.h	2012-02-07 17:10:50 UTC (rev 43963)
+++ trunk/blender/source/blender/blenkernel/BKE_writeffmpeg.h	2012-02-07 17:11:56 UTC (rev 43964)
@@ -74,7 +74,7 @@
 
 extern void ffmpeg_set_preset(struct RenderData *rd, int preset);
 extern void ffmpeg_verify_image_type(struct RenderData *rd, struct ImageFormatData *imf);
-extern void ffmpeg_verify_lossless_format(struct RenderData *rd, struct ImageFormatData *imf);
+extern void ffmpeg_verify_codec_settings(struct RenderData *rd);
 
 extern struct IDProperty *ffmpeg_property_add(struct RenderData *Rd, const char *type, int opt_index, int parent_index);
 extern int ffmpeg_property_add_string(struct RenderData *rd, const char *type, const char *str);

Modified: trunk/blender/source/blender/blenkernel/intern/writeffmpeg.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/writeffmpeg.c	2012-02-07 17:10:50 UTC (rev 43963)
+++ trunk/blender/source/blender/blenkernel/intern/writeffmpeg.c	2012-02-07 17:11:56 UTC (rev 43964)
@@ -49,6 +49,8 @@
 #  include "AUD_C-API.h"
 #endif
 
+#include "BLI_utildefines.h"
+
 #include "BKE_global.h"
 #include "BKE_idprop.h"
 #include "BKE_main.h"
@@ -76,6 +78,7 @@
 static AVStream* video_stream = 0;
 static AVStream* audio_stream = 0;
 static AVFrame* current_frame = 0;
+static int img_convert_fmt = 0;
 static struct SwsContext *img_convert_ctx = 0;
 
 static uint8_t* video_buffer = 0;
@@ -250,7 +253,8 @@
 
 	outsize = avcodec_encode_video(c, video_buffer, video_buffersize, 
 					   frame);
-	if (outsize != 0) {
+
+	if (outsize > 0) {
 		AVPacket packet;
 		av_init_packet(&packet);
 
@@ -268,14 +272,13 @@
 		packet.data = video_buffer;
 		packet.size = outsize;
 		ret = av_interleaved_write_frame(outfile, &packet);
-	} else {
-		ret = 0;
+		success = (ret == 0);
+	} else if (outsize < 0) {
+		success = 0;
 	}
 
-	if (ret != 0) {
-		success= 0;
+	if (!success)
 		BKE_report(reports, RPT_ERROR, "Error writing frame.");
-	}
 
 	return success;
 }
@@ -290,8 +293,8 @@
 	int height = c->height;
 	AVFrame* rgb_frame;
 
-	if (c->pix_fmt != PIX_FMT_BGR32) {
-		rgb_frame = alloc_picture(PIX_FMT_BGR32, width, height);
+	if (c->pix_fmt != img_convert_fmt) {
+		rgb_frame = alloc_picture(img_convert_fmt, width, height);
 		if (!rgb_frame) {
 			BKE_report(reports, RPT_ERROR, "Couldn't allocate temporary frame.");
 			return NULL;
@@ -341,7 +344,7 @@
 		}
 	}
 
-	if (c->pix_fmt != PIX_FMT_BGR32) {
+	if (c->pix_fmt != img_convert_fmt) {
 		sws_scale(img_convert_ctx, (const uint8_t * const*) rgb_frame->data,
 		          rgb_frame->linesize, 0, c->height,
 		          current_frame->data, current_frame->linesize);
@@ -483,7 +486,9 @@
 	if (!codec) return NULL;
 	
 	/* Be sure to use the correct pixel format(e.g. RGB, YUV) */
-	
+
+	img_convert_fmt = PIX_FMT_BGR32;
+
 	if (codec->pix_fmts) {
 		c->pix_fmt = codec->pix_fmts[0];
 	} else {
@@ -509,6 +514,13 @@
 		c->pix_fmt = PIX_FMT_RGB32;
 	}
 
+	if ( codec_id == CODEC_ID_QTRLE ) {
+		if (rd->im_format.planes ==  R_IMF_PLANES_RGBA) {
+			c->pix_fmt = PIX_FMT_ARGB;
+			img_convert_fmt = PIX_FMT_BGRA;
+		}
+	}
+
 	if ((of->oformat->flags & AVFMT_GLOBALHEADER)
 //		|| !strcmp(of->oformat->name, "mp4")
 //	    || !strcmp(of->oformat->name, "mov")
@@ -538,14 +550,26 @@
 		return NULL;
 	}
 
-	video_buffersize = avpicture_get_size(c->pix_fmt, c->width, c->height);
+	if ( codec_id == CODEC_ID_QTRLE ) {
+		// normally it should be enough to have buffer with actual image size,
+		// but some codecs like QTRLE might store extra information in this buffer,
+		// so it should be a way larger
+
+		// maximum video buffer size is 6-bytes per pixel, plus DPX header size (1664)
+		// (from FFmpeg sources)
+		int size = c->width * c->height;
+		video_buffersize = 7*size + 10000;
+	}
+	else
+		video_buffersize = avpicture_get_size(c->pix_fmt, c->width, c->height);
+
 	video_buffer = (uint8_t*)MEM_mallocN(video_buffersize*sizeof(uint8_t),
 						 "FFMPEG video buffer");
 	
 	current_frame = alloc_picture(c->pix_fmt, c->width, c->height);
 
 	img_convert_ctx = sws_getContext(c->width, c->height,
-					 PIX_FMT_BGR32,
+					 img_convert_fmt,
 					 c->width, c->height,
 					 c->pix_fmt,
 					 SWS_BICUBIC,
@@ -1200,12 +1224,14 @@
 	return 1;
 }
 
-static void ffmpeg_set_expert_options(RenderData *rd, int preset)
+static void ffmpeg_set_expert_options(RenderData *rd)
 {
+	int codec_id = rd->ffcodecdata.codec;
+
 	if(rd->ffcodecdata.properties)
 		IDP_FreeProperty(rd->ffcodecdata.properties);
 
-	if(preset == FFMPEG_PRESET_H264) {
+	if(codec_id == CODEC_ID_H264) {
 		/*
 		 * All options here are for x264, but must be set via ffmpeg.
 		 * The names are therefore different - Search for "x264 to FFmpeg option mapping"
@@ -1248,6 +1274,12 @@
 		if(rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT)
 			ffmpeg_property_add_string(rd, "video", "cqp:0");
 	}
+#if 0	/* disabled for after release */
+	else if(codec_id == CODEC_ID_DNXHD) {
+		if(rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT)
+			ffmpeg_property_add_string(rd, "video", "mbd:rd");
+	}
+#endif
 }
 
 void ffmpeg_set_preset(RenderData *rd, int preset)
@@ -1317,7 +1349,6 @@
 		rd->ffcodecdata.mux_packet_size = 2048;
 		rd->ffcodecdata.mux_rate = 10080000;
 
-		ffmpeg_set_expert_options(rd, preset);
 		break;
 
 	case FFMPEG_PRESET_THEORA:
@@ -1341,6 +1372,8 @@
 		break;
 
 	}
+
+	ffmpeg_set_expert_options(rd);
 }
 
 void ffmpeg_verify_image_type(RenderData *rd, ImageFormatData *imf)
@@ -1388,11 +1421,9 @@
 	}
 }
 
-void ffmpeg_verify_lossless_format(RenderData *rd, ImageFormatData *imf)
+void ffmpeg_verify_codec_settings(RenderData *rd)
 {
-	if(imf->imtype == R_IMF_IMTYPE_H264) {
-		ffmpeg_set_expert_options(rd, FFMPEG_PRESET_H264);
-	}
+	ffmpeg_set_expert_options(rd);
 }
 
 #endif

Modified: trunk/blender/source/blender/makesrna/intern/rna_scene.c
===================================================================
--- trunk/blender/source/blender/makesrna/intern/rna_scene.c	2012-02-07 17:10:50 UTC (rev 43963)
+++ trunk/blender/source/blender/makesrna/intern/rna_scene.c	2012-02-07 17:11:56 UTC (rev 43964)
@@ -710,8 +710,22 @@
 	 * where 'BW' will force greyscale even if the output format writes
 	 * as RGBA, this is age old blender convention and not sure how useful
 	 * it really is but keep it for now - campbell */
-	const char chan_flag= BKE_imtype_valid_channels(imf->imtype) | (is_render ? IMA_CHAN_FLAG_BW : 0);
+	char chan_flag= BKE_imtype_valid_channels(imf->imtype) | (is_render ? IMA_CHAN_FLAG_BW : 0);
 
+#ifdef WITH_FFMPEG
+	/* a WAY more crappy case than B&W flag: depending on codec, file format MIGHT support
+	 * alpha channel. for example MPEG format with h264 codec can't do alpha channel, but
+	 * the same MPEG format with QTRLE codec can easily handle alpga channel.
+	 * not sure how to deal with such cases in a nicer way (sergey) */
+	if(is_render) {
+		Scene *scene = ptr->id.data;
+		RenderData *rd = &scene->r;
+
+		if (rd->ffcodecdata.codec == CODEC_ID_QTRLE)
+			chan_flag |= IMA_CHAN_FLAG_ALPHA;
+	}
+#endif
+
 	if (chan_flag == (IMA_CHAN_FLAG_BW|IMA_CHAN_FLAG_RGB|IMA_CHAN_FLAG_ALPHA)) {
 		return image_color_mode_items;
 	}
@@ -897,8 +911,17 @@
 		rd->ffcodecdata.flags |= FFMPEG_LOSSLESS_OUTPUT;
 	else
 		rd->ffcodecdata.flags &= ~FFMPEG_LOSSLESS_OUTPUT;
-	ffmpeg_verify_lossless_format(rd, &rd->im_format);
+
+	ffmpeg_verify_codec_settings(rd);
 }
+
+static void rna_FFmpegSettings_codec_settings_update(Main *UNUSED(bmain), Scene *UNUSED(scene_unused), PointerRNA *ptr)
+{
+	Scene *scene = (Scene *) ptr->id.data;
+	RenderData *rd = &scene->r;
+
+	ffmpeg_verify_codec_settings(rd);
+}
 #endif
 
 static int rna_RenderSettings_active_layer_index_get(PointerRNA *ptr)
@@ -2809,6 +2832,8 @@
 		{CODEC_ID_THEORA, "THEORA", 0, "Theora", ""},
 		{CODEC_ID_FLV1, "FLASH", 0, "Flash Video", ""},
 		{CODEC_ID_FFV1, "FFV1", 0, "FFmpeg video codec #1", ""},
+		{CODEC_ID_QTRLE, "QTRLE", 0, "QTRLE", ""},
+		/* {CODEC_ID_DNXHD, "DNXHD", 0, "DNxHD", ""},*/ /* disabled for after release */
 		{0, NULL, 0, NULL, NULL}};
 
 	static EnumPropertyItem ffmpeg_audio_codec_items[] = {
@@ -2840,17 +2865,17 @@
 	RNA_def_property_enum_bitflag_sdna(prop, NULL, "type");
 	RNA_def_property_enum_items(prop, ffmpeg_format_items);
 	RNA_def_property_ui_text(prop, "Format", "Output file format");
-	RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+	RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_FFmpegSettings_codec_settings_update");
 
 	prop = RNA_def_property(srna, "codec", PROP_ENUM, PROP_NONE);
 	RNA_def_property_enum_bitflag_sdna(prop, NULL, "codec");
 	RNA_def_property_enum_items(prop, ffmpeg_codec_items);
 	RNA_def_property_ui_text(prop, "Codec", "FFmpeg codec to use");
-	RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
+	RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, "rna_FFmpegSettings_codec_settings_update");
 
 	prop = RNA_def_property(srna, "video_bitrate", PROP_INT, PROP_NONE);
 	RNA_def_property_int_sdna(prop, NULL, "video_bitrate");
-	RNA_def_property_range(prop, 1, 14000);
+	RNA_def_property_range(prop, 1, 220000);
 	RNA_def_property_ui_text(prop, "Bitrate", "Video bitrate (kb/s)");
 	RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL);
 




More information about the Bf-blender-cvs mailing list