diff options
-rw-r--r-- | source/blender/blenkernel/intern/writeffmpeg.c | 72 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_string.h | 7 | ||||
-rw-r--r-- | source/blender/blenlib/intern/string.c | 19 | ||||
-rw-r--r-- | source/blender/imbuf/IMB_imbuf.h | 4 | ||||
-rw-r--r-- | source/blender/imbuf/intern/anim_movie.c | 4 | ||||
-rw-r--r-- | source/blender/imbuf/intern/util.c | 51 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_scene.c | 2 | ||||
-rw-r--r-- | source/creator/creator.c | 1 | ||||
-rw-r--r-- | source/gameengine/VideoTexture/VideoFFmpeg.cpp | 6 |
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"); |