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:
authorSergey Sharybin <sergey.vfx@gmail.com>2012-08-26 15:01:14 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2012-08-26 15:01:14 +0400
commit1b487e994850c0acb647aaa9a36464d613f89f51 (patch)
treebf3a591c736690b113b897caf8a986a5bda44b02
parentaa17fc367bbd8a5a5834c07f3b225547dae11ee5 (diff)
Some FFmpeg changes
- Make FFmpeg initialization called from creator, not from functions which requires FFmpeg. Makes it easier to follow when initialization should happen. - Enable DNxHD codec. It was commented a while ago due to some strange behavior on some platforms. Re-tested it on Linux and Windows and it seemd to be working quite nice. Would let it be tested further, if it wouldn't be stable enough, easy to comment it again. - Make non-error messages from writeffmpeg.c printed only if ffmpeg debug argument was passed to blender. Reduces console pollution with messages which are not useful for general troubleshooting. Error messages would still be printed to the console. - Show FFmpeg error message when video stream failed to allocate. makes it easier to understand what exactly is wrong from Blender interface, no need to restart blender with FFmpeg debug flag and check for console messages. Used custom log callback for this which stores last error message in static variable. This is not thread safe, but with current design FFmpeg routines could not be called form several threads anyway, so think it's fine solution/
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c72
-rw-r--r--source/blender/blenlib/BLI_string.h7
-rw-r--r--source/blender/blenlib/intern/string.c19
-rw-r--r--source/blender/imbuf/IMB_imbuf.h4
-rw-r--r--source/blender/imbuf/intern/anim_movie.c4
-rw-r--r--source/blender/imbuf/intern/util.c51
-rw-r--r--source/blender/makesrna/intern/rna_scene.c2
-rw-r--r--source/creator/creator.c1
-rw-r--r--source/gameengine/VideoTexture/VideoFFmpeg.cpp6
9 files changed, 100 insertions, 66 deletions
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index f22fd74baf4..2e07b4143b0 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -69,8 +69,6 @@
#include "ffmpeg_compat.h"
-extern void do_init_ffmpeg(void);
-
static int ffmpeg_type = 0;
static int ffmpeg_codec = CODEC_ID_MPEG4;
static int ffmpeg_audio_codec = CODEC_ID_NONE;
@@ -101,6 +99,8 @@ static AUD_Device *audio_mixdown_device = 0;
#define FFMPEG_AUTOSPLIT_SIZE 2000000000
+#define PRINT if (G.debug & G_DEBUG_FFMPEG) printf
+
/* Delete a picture buffer */
static void delete_picture(AVFrame *f)
@@ -139,7 +139,7 @@ static int write_audio_frame(void)
if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) {
pkt.pts = av_rescale_q(c->coded_frame->pts,
c->time_base, audio_stream->time_base);
- fprintf(stderr, "Audio Frame PTS: %d\n", (int)pkt.pts);
+ PRINT("Audio Frame PTS: %d\n", (int) pkt.pts);
}
pkt.stream_index = audio_stream->index;
@@ -265,10 +265,10 @@ static int write_video_frame(RenderData *rd, int cfra, AVFrame *frame, ReportLis
packet.pts = av_rescale_q(c->coded_frame->pts,
c->time_base,
video_stream->time_base);
- fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts);
+ PRINT("Video Frame PTS: %d\n", (int)packet.pts);
}
else {
- fprintf(stderr, "Video Frame PTS: not set\n");
+ PRINT("Video Frame PTS: not set\n");
}
if (c->coded_frame->key_frame)
packet.flags |= AV_PKT_FLAG_KEY;
@@ -364,7 +364,7 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop)
char *param;
const AVOption *rv = NULL;
- fprintf(stderr, "FFMPEG expert option: %s: ", prop->name);
+ PRINT("FFMPEG expert option: %s: ", prop->name);
BLI_strncpy(name, prop->name, sizeof(name));
@@ -376,15 +376,15 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop)
switch (prop->type) {
case IDP_STRING:
- fprintf(stderr, "%s.\n", IDP_String(prop));
+ PRINT("%s.\n", IDP_String(prop));
av_set_string3(c, prop->name, IDP_String(prop), 1, &rv);
break;
case IDP_FLOAT:
- fprintf(stderr, "%g.\n", IDP_Float(prop));
+ PRINT("%g.\n", IDP_Float(prop));
rv = av_set_double(c, prop->name, IDP_Float(prop));
break;
case IDP_INT:
- fprintf(stderr, "%d.\n", IDP_Int(prop));
+ PRINT("%d.\n", IDP_Int(prop));
if (param) {
if (IDP_Int(prop)) {
@@ -401,7 +401,7 @@ static void set_ffmpeg_property_option(AVCodecContext *c, IDProperty *prop)
}
if (!rv) {
- fprintf(stderr, "ffmpeg-option not supported: %s! Skipping.\n",
+ PRINT("ffmpeg-option not supported: %s! Skipping.\n",
prop->name);
}
}
@@ -446,11 +446,14 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char
/* prepare a video stream for the output file */
static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContext *of,
- int rectx, int recty)
+ int rectx, int recty, char *error, int error_size)
{
AVStream *st;
AVCodecContext *c;
AVCodec *codec;
+
+ error[0] = '\0';
+
st = av_new_stream(of, 0);
if (!st) return NULL;
@@ -547,13 +550,13 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
// || !strcmp(of->oformat->name, "3gp")
)
{
- fprintf(stderr, "Using global header\n");
+ PRINT("Using global header\n");
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
/* Determine whether we are encoding interlaced material or not */
if (rd->mode & R_FIELDS) {
- fprintf(stderr, "Encoding interlaced video\n");
+ PRINT("Encoding interlaced video\n");
c->flags |= CODEC_FLAG_INTERLACED_DCT;
c->flags |= CODEC_FLAG_INTERLACED_ME;
}
@@ -566,8 +569,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex
set_ffmpeg_properties(rd, c, "video");
if (avcodec_open(c, codec) < 0) {
- //
- //XXX error("Couldn't initialize codec");
+ BLI_strncpy(error, IMB_ffmpeg_last_error(), error_size);
return NULL;
}
@@ -672,7 +674,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
AVFormatContext *of;
AVOutputFormat *fmt;
AVDictionary *opts = NULL;
- char name[256];
+ char name[256], error[1024];
const char **exts;
ffmpeg_type = rd->ffcodecdata.type;
@@ -684,11 +686,9 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
ffmpeg_autosplit = rd->ffcodecdata.flags
& FFMPEG_AUTOSPLIT_OUTPUT;
- do_init_ffmpeg();
-
/* Determine the correct filename */
BKE_ffmpeg_filepath_get(name, rd);
- fprintf(stderr, "Starting output to %s(ffmpeg)...\n"
+ PRINT("Starting output to %s(ffmpeg)...\n"
" Using type=%d, codec=%d, audio_codec=%d,\n"
" video_bitrate=%d, audio_bitrate=%d,\n"
" gop_size=%d, autosplit=%d\n"
@@ -793,10 +793,14 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report
}
if (fmt->video_codec != CODEC_ID_NONE) {
- video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty);
- printf("alloc video stream %p\n", video_stream);
+ video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty, error, sizeof(error));
+ PRINT("alloc video stream %p\n", video_stream);
if (!video_stream) {
- BKE_report(reports, RPT_ERROR, "Error initializing video stream.");
+ if (error[0])
+ BKE_report(reports, RPT_ERROR, error);
+ else
+ BKE_report(reports, RPT_ERROR, "Error initializing video stream.");
+
av_dict_free(&opts);
return 0;
}
@@ -870,10 +874,10 @@ void flush_ffmpeg(void)
packet.pts = av_rescale_q(c->coded_frame->pts,
c->time_base,
video_stream->time_base);
- fprintf(stderr, "Video Frame PTS: %d\n", (int)packet.pts);
+ PRINT("Video Frame PTS: %d\n", (int)packet.pts);
}
else {
- fprintf(stderr, "Video Frame PTS: not set\n");
+ PRINT("Video Frame PTS: not set\n");
}
if (c->coded_frame->key_frame) {
packet.flags |= AV_PKT_FLAG_KEY;
@@ -983,9 +987,9 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i
AVFrame *avframe;
int success = 1;
- fprintf(stderr, "Writing frame %i, "
- "render width=%d, render height=%d\n", frame,
- rectx, recty);
+ PRINT("Writing frame %i, "
+ "render width=%d, render height=%d\n", frame,
+ rectx, recty);
// why is this done before writing the video frame and again at end_ffmpeg?
// write_audio_frames(frame / (((double)rd->frs_sec) / rd->frs_sec_base));
@@ -1013,7 +1017,7 @@ void BKE_ffmpeg_end(void)
{
unsigned int i;
- fprintf(stderr, "Closing ffmpeg...\n");
+ PRINT("Closing ffmpeg...\n");
#if 0
if (audio_stream) { /* SEE UPPER */
@@ -1029,7 +1033,7 @@ void BKE_ffmpeg_end(void)
#endif
if (video_stream && video_stream->codec) {
- fprintf(stderr, "Flushing delayed frames...\n");
+ PRINT("Flushing delayed frames...\n");
flush_ffmpeg();
}
@@ -1041,7 +1045,7 @@ void BKE_ffmpeg_end(void)
if (video_stream && video_stream->codec) {
avcodec_close(video_stream->codec);
- printf("zero video stream %p\n", video_stream);
+ PRINT("zero video stream %p\n", video_stream);
video_stream = 0;
}
@@ -1142,8 +1146,8 @@ IDProperty *BKE_ffmpeg_property_add(RenderData *rd, const char *type, int opt_in
BLI_strncpy(name, o->name, sizeof(name));
}
- fprintf(stderr, "ffmpeg_property_add: %s %d %d %s\n",
- type, parent_index, opt_index, name);
+ PRINT("ffmpeg_property_add: %s %d %d %s\n",
+ type, parent_index, opt_index, name);
prop = IDP_GetPropertyFromGroup(group, name);
if (prop) {
@@ -1316,12 +1320,10 @@ static void ffmpeg_set_expert_options(RenderData *rd)
if (rd->ffcodecdata.flags & FFMPEG_LOSSLESS_OUTPUT)
BKE_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");
+ BKE_ffmpeg_property_add_string(rd, "video", "mbd:rd");
}
-#endif
}
void BKE_ffmpeg_preset_set(RenderData *rd, int preset)
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index a74629e589c..b3d0df04eb1 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -32,6 +32,8 @@
* \ingroup bli
*/
+#include <stdarg.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -140,6 +142,11 @@ __attribute__((nonnull))
;
/*
+ * Replacement for vsnprintf
+ */
+size_t BLI_vsnprintf(char *buffer, size_t count, const char *format, va_list arg);
+
+/*
* Print formatted string into a newly mallocN'd string
* and return it.
*/
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index 7a750a74a33..8501db7c8b8 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -78,22 +78,31 @@ char *BLI_strncpy(char *dst, const char *src, const size_t maxncpy)
return dst;
}
-size_t BLI_snprintf(char *buffer, size_t count, const char *format, ...)
+size_t BLI_vsnprintf(char *buffer, size_t count, const char *format, va_list arg)
{
size_t n;
- va_list arg;
- va_start(arg, format);
n = vsnprintf(buffer, count, format, arg);
-
+
if (n != -1 && n < count) {
buffer[n] = '\0';
}
else {
buffer[count - 1] = '\0';
}
-
+
+ return n;
+}
+
+size_t BLI_snprintf(char *buffer, size_t count, const char *format, ...)
+{
+ size_t n;
+ va_list arg;
+
+ va_start(arg, format);
+ n = BLI_vsnprintf(buffer, count, format, arg);
va_end(arg);
+
return n;
}
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 738e61dbe6e..a04affd4891 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -506,5 +506,9 @@ void IMB_processor_apply_threaded(int buffer_lines, int handle_size, void *init_
void *customdata),
void *(do_thread) (void *));
+/* ffmpeg */
+void IMB_ffmpeg_init(void);
+const char *IMB_ffmpeg_last_error(void);
+
#endif
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index f07a18cb89c..9092d59c351 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -439,8 +439,6 @@ static ImBuf *avi_fetchibuf(struct anim *anim, int position)
#ifdef WITH_FFMPEG
-extern void do_init_ffmpeg(void);
-
static int startffmpeg(struct anim *anim)
{
int i, videoStream;
@@ -463,8 +461,6 @@ static int startffmpeg(struct anim *anim)
streamcount = anim->streamindex;
- do_init_ffmpeg();
-
if (avformat_open_input(&pFormatCtx, anim->name, NULL, NULL) != 0) {
return -1;
}
diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c
index 2b0597d64a5..9ec22f0798e 100644
--- a/source/blender/imbuf/intern/util.c
+++ b/source/blender/imbuf/intern/util.c
@@ -43,6 +43,8 @@
#include "BLI_path_util.h"
#include "BLI_fileops.h"
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
#include "DNA_userdef_types.h"
#include "BKE_global.h"
@@ -220,6 +222,8 @@ static int isqtime(const char *name)
#ifdef WITH_FFMPEG
+static char ffmpeg_last_error[1024];
+
void silence_log_ffmpeg(int quiet)
{
if (quiet) {
@@ -230,21 +234,40 @@ void silence_log_ffmpeg(int quiet)
}
}
-extern void do_init_ffmpeg(void);
-void do_init_ffmpeg(void)
+void ffmpeg_log_callback(void *ptr, int level, const char *format, va_list arg)
{
- static int ffmpeg_init = 0;
- if (!ffmpeg_init) {
- ffmpeg_init = 1;
- av_register_all();
- avdevice_register_all();
- if ((G.debug & G_DEBUG_FFMPEG) == 0) {
- silence_log_ffmpeg(1);
- }
- else {
- silence_log_ffmpeg(0);
- }
+ if (ELEM(level, AV_LOG_FATAL, AV_LOG_ERROR)) {
+ size_t n = BLI_vsnprintf(ffmpeg_last_error, sizeof(ffmpeg_last_error), format, arg);
+
+ /* strip trailing \n */
+ ffmpeg_last_error[n - 1] = '\0';
}
+
+ /* call default logger to print all message to console */
+ av_log_default_callback(ptr, level, format, arg);
+}
+
+void IMB_ffmpeg_init(void)
+{
+ av_register_all();
+ avdevice_register_all();
+
+ if ((G.debug & G_DEBUG_FFMPEG) == 0) {
+ silence_log_ffmpeg(1);
+ }
+ else {
+ silence_log_ffmpeg(0);
+ }
+
+ ffmpeg_last_error[0] = '\0';
+
+ /* set own callback which could store last error to report to UI */
+ av_log_set_callback(ffmpeg_log_callback);
+}
+
+const char *IMB_ffmpeg_last_error(void)
+{
+ return ffmpeg_last_error;
}
static int isffmpeg(const char *filename)
@@ -255,8 +278,6 @@ static int isffmpeg(const char *filename)
AVCodec *pCodec;
AVCodecContext *pCodecCtx;
- do_init_ffmpeg();
-
if (BLI_testextensie(filename, ".swf") ||
BLI_testextensie(filename, ".jpg") ||
BLI_testextensie(filename, ".png") ||
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index a6f3c0095b5..597c2294ade 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -2995,7 +2995,7 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna)
{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 */
+ {CODEC_ID_DNXHD, "DNXHD", 0, "DNxHD", ""},
{0, NULL, 0, NULL, NULL}
};
diff --git a/source/creator/creator.c b/source/creator/creator.c
index 3e884d1aa38..58e1066e5ff 100644
--- a/source/creator/creator.c
+++ b/source/creator/creator.c
@@ -1273,6 +1273,7 @@ int main(int argc, const char **argv)
initglobals(); /* blender.c */
IMB_init();
+ IMB_ffmpeg_init();
BLI_callback_global_init();
diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
index 4586a50e6a9..1ba944aa955 100644
--- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp
+++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp
@@ -52,8 +52,6 @@ const long timeScale = 1000;
#define CATCH_EXCP catch (Exception & exp) \
{ exp.report(); m_status = SourceError; }
-extern "C" void do_init_ffmpeg();
-
// class RenderVideo
// constructor
@@ -521,8 +519,6 @@ void VideoFFmpeg::releaseFrame(AVFrame* frame)
// open video file
void VideoFFmpeg::openFile (char * filename)
{
- do_init_ffmpeg();
-
if (openStream(filename, NULL, NULL) != 0)
return;
@@ -586,8 +582,6 @@ void VideoFFmpeg::openCam (char * file, short camIdx)
char filename[28], rateStr[20];
char *p;
- do_init_ffmpeg();
-
#ifdef WIN32
// video capture on windows only through Video For Windows driver
inputFormat = av_find_input_format("vfwcap");