Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/writeffmpeg.c')
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c69
1 files changed, 50 insertions, 19 deletions
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 0b043e26ab7..1e2791acfee 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -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 AVFormatContext* outfile = 0;
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 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame* frame, ReportLis
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 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame* frame, ReportLis
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 @@ static AVFrame* generate_video_frame(uint8_t* pixels, ReportList *reports)
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 @@ static AVFrame* generate_video_frame(uint8_t* pixels, ReportList *reports)
}
}
- 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 @@ static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
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 @@ static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
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 @@ static AVStream* alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
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 @@ int ffmpeg_property_add_string(RenderData *rd, const char * type, const char * s
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 @@ static void ffmpeg_set_expert_options(RenderData *rd, int preset)
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 @@ void ffmpeg_set_preset(RenderData *rd, int preset)
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 @@ void ffmpeg_set_preset(RenderData *rd, int preset)
break;
}
+
+ ffmpeg_set_expert_options(rd);
}
void ffmpeg_verify_image_type(RenderData *rd, ImageFormatData *imf)
@@ -1388,11 +1421,9 @@ void ffmpeg_verify_image_type(RenderData *rd, ImageFormatData *imf)
}
}
-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