From d6531927510ad3885176158afa643fee6ec30882 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 22 Dec 2009 12:01:32 +0000 Subject: Reports: writing movies now uses the reports mechanism to throw errors. Also fixes bug #19463: screencast to xvid ffmpeg crash. --- source/blender/blenkernel/BKE_writeavi.h | 12 ++- source/blender/blenkernel/BKE_writeffmpeg.h | 5 +- source/blender/blenkernel/BKE_writeframeserver.h | 7 +- source/blender/blenkernel/intern/writeavi.c | 19 ++-- source/blender/blenkernel/intern/writeffmpeg.c | 120 +++++++++++---------- .../blender/blenkernel/intern/writeframeserver.c | 48 ++++----- source/blender/editors/screen/screen_ops.c | 24 +++-- source/blender/editors/screen/screendump.c | 20 +++- source/blender/quicktime/apple/qtkit_export.m | 100 ++++++++--------- source/blender/quicktime/apple/quicktime_export.c | 83 +++++++------- source/blender/quicktime/quicktime_export.h | 4 +- source/blender/render/extern/include/RE_pipeline.h | 3 +- source/blender/render/intern/source/pipeline.c | 28 +++-- .../blender/windowmanager/intern/wm_event_system.c | 8 +- source/creator/creator.c | 9 +- 15 files changed, 265 insertions(+), 225 deletions(-) diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h index 4ef63b069c2..a8d38dda103 100644 --- a/source/blender/blenkernel/BKE_writeavi.h +++ b/source/blender/blenkernel/BKE_writeavi.h @@ -37,17 +37,19 @@ extern "C" { /* generic blender movie support, could move to own module */ struct RenderData; +struct ReportList; struct Scene; -void start_avi(struct Scene *scene, struct RenderData *rd, int rectx, int recty); + +int start_avi(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); void end_avi(void); -void append_avi(struct RenderData *rd, int frame, int *pixels, int rectx, int recty); +int append_avi(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); void makeavistring (struct RenderData *rd, char *string); typedef struct bMovieHandle { - void (*start_movie)(struct Scene *scene, struct RenderData *rd, int rectx, int recty); - void (*append_movie)(struct RenderData *rd, int frame, int *pixels, int rectx, int recty); + int (*start_movie)(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); + int (*append_movie)(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); void (*end_movie)(void); - int (*get_next_frame)(struct RenderData *rd); /* optional */ + int (*get_next_frame)(struct RenderData *rd, struct ReportList *reports); /* optional */ } bMovieHandle; bMovieHandle *BKE_get_movie_handle(int imtype); diff --git a/source/blender/blenkernel/BKE_writeffmpeg.h b/source/blender/blenkernel/BKE_writeffmpeg.h index 07e0e01ef7e..6ec8320f026 100644 --- a/source/blender/blenkernel/BKE_writeffmpeg.h +++ b/source/blender/blenkernel/BKE_writeffmpeg.h @@ -57,11 +57,12 @@ extern "C" { struct IDProperty; struct RenderData; +struct ReportList; struct Scene; -extern void start_ffmpeg(struct Scene *scene, struct RenderData *rd, int rectx, int recty); +extern int start_ffmpeg(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); extern void end_ffmpeg(void); -extern void append_ffmpeg(struct RenderData *rd, int frame, int *pixels, int rectx, int recty); +extern int append_ffmpeg(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); extern void ffmpeg_set_preset(struct RenderData *rd, int preset); extern void ffmpeg_verify_image_type(struct RenderData *rd); diff --git a/source/blender/blenkernel/BKE_writeframeserver.h b/source/blender/blenkernel/BKE_writeframeserver.h index 6a38abe977f..50b905cfd75 100644 --- a/source/blender/blenkernel/BKE_writeframeserver.h +++ b/source/blender/blenkernel/BKE_writeframeserver.h @@ -33,12 +33,13 @@ extern "C" { #endif struct RenderData; +struct ReportList; struct Scene; -extern void start_frameserver(struct Scene *scene, struct RenderData *rd, int rectx, int recty); +extern int start_frameserver(struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports); extern void end_frameserver(void); -extern void append_frameserver(struct RenderData *rd, int frame, int *pixels, int rectx, int recty); -extern int frameserver_loop(struct RenderData *rd); +extern int append_frameserver(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, struct ReportList *reports); +extern int frameserver_loop(struct RenderData *rd, struct ReportList *reports); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index 7c58a4f9499..ec3d1185179 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -40,6 +40,7 @@ #include "BLI_blenlib.h" #include "BKE_global.h" +#include "BKE_report.h" #include "BKE_utildefines.h" #include "BKE_writeavi.h" #include "AVI_avi.h" @@ -127,7 +128,7 @@ void makeavistring (RenderData *rd, char *string) } } -void start_avi(struct Scene *scene, RenderData *rd, int rectx, int recty) +int start_avi(Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports) { int x, y; char name[256]; @@ -153,10 +154,10 @@ void start_avi(struct Scene *scene, RenderData *rd, int rectx, int recty) else format = AVI_FORMAT_MJPEG; if (AVI_open_compress (name, avi, 1, format) != AVI_ERROR_NONE) { - printf("cannot open or start AVI movie file"); + BKE_report(reports, RPT_ERROR, "Cannot open or start AVI movie file."); MEM_freeN (avi); avi = NULL; - return; + return 0; } AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_WIDTH, &x); @@ -170,18 +171,17 @@ void start_avi(struct Scene *scene, RenderData *rd, int rectx, int recty) /* avi->odd_fields= (rd->mode & R_ODDFIELD)?1:0; */ printf("Created avi: %s\n", name); + return 1; } -void append_avi(RenderData *rd, int frame, int *pixels, int rectx, int recty) +int append_avi(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports) { unsigned int *rt1, *rt2, *rectot; int x, y; char *cp, rt; - if (avi == NULL) { - G.afbreek = 1; - return; - } + if (avi == NULL) + return 0; /* note that libavi free's the buffer... stupid interface - zr */ rectot= MEM_mallocN(rectx*recty*sizeof(int), "rectot"); @@ -205,6 +205,8 @@ void append_avi(RenderData *rd, int frame, int *pixels, int rectx, int recty) AVI_write_frame (avi, (frame-sframe), AVI_FORMAT_RGB32, rectot, rectx*recty*4); // printf ("added frame %3d (frame %3d in avi): ", frame, frame-sframe); + + return 1; } void end_avi(void) @@ -215,3 +217,4 @@ void end_avi(void) MEM_freeN (avi); avi= NULL; } + diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 1953058fddf..417679417e4 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -52,23 +52,24 @@ #define snprintf _snprintf #endif -#include "BKE_writeffmpeg.h" - #include "MEM_guardedalloc.h" + +#include "DNA_scene_types.h" + #include "BLI_blenlib.h" +#include "AUD_C-API.h" /* must be before BKE_sound.h for define */ + #include "BKE_global.h" #include "BKE_idprop.h" +#include "BKE_main.h" +#include "BKE_report.h" +#include "BKE_sound.h" +#include "BKE_writeffmpeg.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" -#include "DNA_scene_types.h" - -#include "AUD_C-API.h" -#include "BKE_sound.h" -#include "BKE_main.h" - #ifdef HAVE_CONFIG_H #include #endif @@ -239,10 +240,10 @@ static const char** get_file_extensions(int format) } /* Write a frame to the output file */ -static void write_video_frame(RenderData *rd, AVFrame* frame) +static int write_video_frame(RenderData *rd, AVFrame* frame, ReportList *reports) { int outsize = 0; - int ret; + int ret, success= 1; AVCodecContext* c = get_codec_from_stream(video_stream); #ifdef FFMPEG_CODEC_TIME_BASE frame->pts = rd->cfra - rd->sfra; @@ -276,14 +277,17 @@ static void write_video_frame(RenderData *rd, AVFrame* frame) packet.size = outsize; ret = av_interleaved_write_frame(outfile, &packet); } else ret = 0; + if (ret != 0) { - G.afbreek = 1; - //XXX error("Error writing frame"); + success= 0; + BKE_report(reports, RPT_ERROR, "Error writing frame."); } + + return success; } /* read and encode a frame of audio from the buffer */ -static AVFrame* generate_video_frame(uint8_t* pixels) +static AVFrame* generate_video_frame(uint8_t* pixels, ReportList *reports) { uint8_t* rendered_frame; @@ -295,8 +299,7 @@ static AVFrame* generate_video_frame(uint8_t* pixels) if (c->pix_fmt != PIX_FMT_BGR32) { rgb_frame = alloc_picture(PIX_FMT_BGR32, width, height); if (!rgb_frame) { - G.afbreek=1; - //XXX error("Couldn't allocate temporary frame"); + BKE_report(reports, RPT_ERROR, "Couldn't allocate temporary frame."); return NULL; } } else { @@ -613,7 +616,7 @@ static AVStream* alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex } /* essential functions -- start, append, end */ -static void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) +static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, ReportList *reports) { /* Handle to the output file */ AVFormatContext* of; @@ -648,22 +651,19 @@ static void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) exts = get_file_extensions(ffmpeg_type); if (!exts) { - G.afbreek = 1; /* Abort render */ - //XXX error("No valid formats found"); - return; + BKE_report(reports, RPT_ERROR, "No valid formats found."); + return 0; } fmt = guess_format(NULL, exts[0], NULL); if (!fmt) { - G.afbreek = 1; /* Abort render */ - //XXX error("No valid formats found"); - return; + BKE_report(reports, RPT_ERROR, "No valid formats found."); + return 0; } of = av_alloc_format_context(); if (!of) { - G.afbreek = 1; - //XXX error("Error opening output file"); - return; + BKE_report(reports, RPT_ERROR, "Error opening output file"); + return 0; } of->oformat = fmt; @@ -711,22 +711,16 @@ static void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) } if (fmt->video_codec == CODEC_ID_DVVIDEO) { if (rectx != 720) { - G.afbreek = 1; - //XXX error("Render width has to be 720 pixels for DV!"); - return; + BKE_report(reports, RPT_ERROR, "Render width has to be 720 pixels for DV!"); + return 0; } if (rd->frs_sec != 25 && recty != 480) { - G.afbreek = 1; - //XXX error("Render height has to be 480 pixels " - // "for DV-NTSC!"); - return; - + BKE_report(reports, RPT_ERROR, "Render height has to be 480 pixels for DV-NTSC!"); + return 0; } if (rd->frs_sec == 25 && recty != 576) { - G.afbreek = 1; - //XXX error("Render height has to be 576 pixels " - // "for DV-PAL!"); - return; + BKE_report(reports, RPT_ERROR, "Render height has to be 576 pixels for DV-PAL!"); + return 0; } } @@ -735,46 +729,42 @@ static void start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty) if (ffmpeg_type == FFMPEG_DV) { fmt->audio_codec = CODEC_ID_PCM_S16LE; if (ffmpeg_multiplex_audio && rd->ffcodecdata.audio_mixrate != 48000) { - G.afbreek = 1; - //XXX error("FFMPEG only supports 48khz / stereo " - // "audio for DV!"); - return; + BKE_report(reports, RPT_ERROR, "FFMPEG only supports 48khz / stereo audio for DV!"); + return 0; } } video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty); + printf("alloc video stream %p\n", video_stream); if (!video_stream) { - G.afbreek = 1; - //XXX error("Error initializing video stream"); - return; + BKE_report(reports, RPT_ERROR, "Error initializing video stream."); + return 0; } if (ffmpeg_multiplex_audio) { audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of); if (!audio_stream) { - G.afbreek = 1; - //XXX error("Error initializing audio stream"); - return; + BKE_report(reports, RPT_ERROR, "Error initializing audio stream."); + return 0; } //XXX audiostream_play(SFRA, 0, 1); } if (av_set_parameters(of, NULL) < 0) { - G.afbreek = 1; - //XXX error("Error setting output parameters"); - return; + BKE_report(reports, RPT_ERROR, "Error setting output parameters."); + return 0; } if (!(fmt->flags & AVFMT_NOFILE)) { if (url_fopen(&of->pb, name, URL_WRONLY) < 0) { - G.afbreek = 1; - // - //XXX error("Could not open file for writing"); - return; + BKE_report(reports, RPT_ERROR, "Could not open file for writing."); + return 0; } } av_write_header(of); outfile = of; dump_format(of, 0, name, 1); + + return 1; } /* ********************************************************************** @@ -831,11 +821,13 @@ static void makeffmpegstring(RenderData* rd, char* string) { } } -void start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty) +int start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports) { + int success; + ffmpeg_autosplit_count = 0; - start_ffmpeg_impl(rd, rectx, recty); + success = start_ffmpeg_impl(rd, rectx, recty, reports); if(ffmpeg_multiplex_audio && audio_stream) { @@ -846,6 +838,8 @@ void start_ffmpeg(struct Scene *scene, RenderData *rd, int rectx, int recty) specs.rate = rd->ffcodecdata.audio_mixrate; audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->efra, rd->ffcodecdata.audio_volume); } + + return success; } void end_ffmpeg(void); @@ -870,22 +864,29 @@ static void write_audio_frames() } } -void append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty) +int append_ffmpeg(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports) { + AVFrame* avframe; + int success; + fprintf(stderr, "Writing frame %i, " "render width=%d, render height=%d\n", frame, rectx, recty); write_audio_frames(); - write_video_frame(rd, generate_video_frame((unsigned char*) pixels)); + + avframe= generate_video_frame((unsigned char*) pixels, reports); + success= (avframe && write_video_frame(rd, avframe, reports)); if (ffmpeg_autosplit) { if (url_ftell(OUTFILE_PB) > FFMPEG_AUTOSPLIT_SIZE) { end_ffmpeg(); ffmpeg_autosplit_count++; - start_ffmpeg_impl(rd, rectx, recty); + success &= start_ffmpeg_impl(rd, rectx, recty, reports); } } + + return success; } @@ -914,6 +915,7 @@ void end_ffmpeg(void) if (video_stream && get_codec_from_stream(video_stream)) { avcodec_close(get_codec_from_stream(video_stream)); video_stream = 0; + printf("zero video stream %p\n", video_stream); } diff --git a/source/blender/blenkernel/intern/writeframeserver.c b/source/blender/blenkernel/intern/writeframeserver.c index 0780cd0dc48..20d858fffeb 100644 --- a/source/blender/blenkernel/intern/writeframeserver.c +++ b/source/blender/blenkernel/intern/writeframeserver.c @@ -48,6 +48,7 @@ #include "DNA_userdef_types.h" #include "BKE_global.h" +#include "BKE_report.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -101,48 +102,45 @@ static int closesocket(int fd) } #endif -void start_frameserver(struct Scene *scene, RenderData *rd, int rectx, int recty) +int start_frameserver(struct Scene *scene, RenderData *rd, int rectx, int recty, ReportList *reports) { - struct sockaddr_in addr; + struct sockaddr_in addr; int arg = 1; if (!startup_socket_system()) { - G.afbreek = 1; - //XXX error("Can't startup socket system"); - return; + BKE_report(reports, RPT_ERROR, "Can't startup socket system"); + return 0; } if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { shutdown_socket_system(); - G.afbreek = 1; /* Abort render */ - //XXX error("Can't open socket"); - return; - } + BKE_report(reports, RPT_ERROR, "Can't open socket"); + return 0; + } - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - (char*) &arg, sizeof(arg)); + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*) &arg, sizeof(arg)); addr.sin_family = AF_INET; - addr.sin_port = htons(U.frameserverport); - addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons(U.frameserverport); + addr.sin_addr.s_addr = INADDR_ANY; if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { shutdown_socket_system(); - G.afbreek = 1; /* Abort render */ - //XXX error("Can't bind to socket"); - return; - } + BKE_report(reports, RPT_ERROR, "Can't bind to socket"); + return 0; + } - if (listen(sock, SOMAXCONN) < 0) { + if (listen(sock, SOMAXCONN) < 0) { shutdown_socket_system(); - G.afbreek = 1; /* Abort render */ - //XXX error("Can't establish listen backlog"); - return; - } + BKE_report(reports, RPT_ERROR, "Can't establish listen backlog"); + return 0; + } connsock = -1; render_width = rectx; render_height = recty; + + return 1; } static char index_page[] @@ -249,7 +247,7 @@ static int handle_request(RenderData *rd, char * req) return -1; } -int frameserver_loop(RenderData *rd) +int frameserver_loop(RenderData *rd, ReportList *reports) { fd_set readfds; struct timeval tv; @@ -355,7 +353,7 @@ static void serve_ppm(int *pixels, int rectx, int recty) connsock = -1; } -void append_frameserver(RenderData *rd, int frame, int *pixels, int rectx, int recty) +int append_frameserver(RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports) { fprintf(stderr, "Serving frame: %d\n", frame); if (write_ppm) { @@ -365,6 +363,8 @@ void append_frameserver(RenderData *rd, int frame, int *pixels, int rectx, int r closesocket(connsock); connsock = -1; } + + return 0; } void end_frameserver() diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index fe1587a965d..f0cf338be06 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -2810,7 +2810,7 @@ static int screen_render_exec(bContext *C, wmOperator *op) RE_test_break_cb(re, NULL, (int (*)(void *)) blender_test_break); if(RNA_boolean_get(op->ptr, "animation")) - RE_BlenderAnim(re, scene, scene->r.sfra, scene->r.efra, scene->r.frame_step); + RE_BlenderAnim(re, scene, scene->r.sfra, scene->r.efra, scene->r.frame_step, op->reports); else RE_BlenderFrame(re, scene, scene->r.cfra); @@ -2831,6 +2831,7 @@ typedef struct RenderJob { ImageUser iuser; short *stop; short *do_update; + ReportList *reports; } RenderJob; static void render_freejob(void *rjv) @@ -3035,7 +3036,7 @@ static void render_startjob(void *rjv, short *stop, short *do_update) #endif if(rj->anim) - RE_BlenderAnim(rj->re, rj->scene, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->r.frame_step); + RE_BlenderAnim(rj->re, rj->scene, rj->scene->r.sfra, rj->scene->r.efra, rj->scene->r.frame_step, rj->reports); else RE_BlenderFrame(rj->re, rj->scene, rj->scene->r.cfra); } @@ -3108,6 +3109,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event) rj->anim= RNA_boolean_get(op->ptr, "animation"); rj->iuser.scene= scene; rj->iuser.ok= 1; + rj->reports= op->reports; /* setup job */ steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY); @@ -3139,8 +3141,6 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event) WM_jobs_start(CTX_wm_manager(C), steve); - G.afbreek= 0; - WM_cursor_wait(0); WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene); @@ -3185,6 +3185,7 @@ typedef struct OGLRender { GPUOffScreen *ofs; int sizex, sizey; + ReportList *reports; bMovieHandle *mh; int cfrao, nfra; @@ -3383,9 +3384,9 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, wmEvent *even if(ibuf) { if(BKE_imtype_is_movie(scene->r.imtype)) { - oglrender->mh->append_movie(&scene->r, CFRA, (int*)ibuf->rect, oglrender->sizex, oglrender->sizey); - printf("Append frame %d", scene->r.cfra); - ok= 1; + ok= oglrender->mh->append_movie(&scene->r, CFRA, (int*)ibuf->rect, oglrender->sizex, oglrender->sizey, oglrender->reports); + if(ok) + printf("Append frame %d", scene->r.cfra); } else { BKE_makepicstring(scene, name, scene->r.pic, scene->r.cfra, scene->r.imtype); @@ -3439,9 +3440,14 @@ static int screen_opengl_render_invoke(bContext *C, wmOperator *op, wmEvent *eve oglrender= op->customdata; scene= oglrender->scene; + oglrender->reports= op->reports; oglrender->mh= BKE_get_movie_handle(scene->r.imtype); - if(BKE_imtype_is_movie(scene->r.imtype)) - oglrender->mh->start_movie(scene, &scene->r, oglrender->sizex, oglrender->sizey); + if(BKE_imtype_is_movie(scene->r.imtype)) { + if(!oglrender->mh->start_movie(scene, &scene->r, oglrender->sizex, oglrender->sizey, oglrender->reports)) { + screen_opengl_render_end(C, oglrender); + return OPERATOR_CANCELLED; + } + } oglrender->cfrao= scene->r.cfra; oglrender->nfra= SFRA; diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 81c3f4d6814..088be194fe8 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -42,6 +42,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_report.h" #include "BKE_utildefines.h" #include "BKE_writeavi.h" @@ -185,6 +186,7 @@ typedef struct ScreenshotJob { int x, y, dumpsx, dumpsy; short *stop; short *do_update; + ReportList reports; } ScreenshotJob; @@ -227,8 +229,12 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update) rd.frs_sec= 10; rd.frs_sec_base= 1.0f; - if(BKE_imtype_is_movie(rd.imtype)) - mh->start_movie(sj->scene, &rd, sj->dumpsx, sj->dumpsy); + if(BKE_imtype_is_movie(rd.imtype)) { + if(!mh->start_movie(sj->scene, &rd, sj->dumpsx, sj->dumpsy, &sj->reports)) { + printf("screencast job stopped\n"); + return; + } + } else mh= NULL; @@ -242,8 +248,10 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update) if(sj->dumprect) { if(mh) { - mh->append_movie(&rd, cfra, (int *)sj->dumprect, sj->dumpsx, sj->dumpsy); - printf("Append frame %d\n", cfra); + if(mh->append_movie(&rd, cfra, (int *)sj->dumprect, sj->dumpsx, sj->dumpsy, &sj->reports)) + printf("Append frame %d\n", cfra); + else + break; } else { ImBuf *ibuf= IMB_allocImBuf(sj->dumpsx, sj->dumpsy, rd.planes, 0, 0); @@ -286,7 +294,7 @@ static int screencast_exec(bContext *C, wmOperator *op) bScreen *screen= CTX_wm_screen(C); wmJob *steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), screen, 0); ScreenshotJob *sj= MEM_callocN(sizeof(ScreenshotJob), "screenshot job"); - + /* setup sj */ if(RNA_boolean_get(op->ptr, "full")) { wmWindow *win= CTX_wm_window(C); @@ -304,6 +312,8 @@ static int screencast_exec(bContext *C, wmOperator *op) } sj->scene= CTX_data_scene(C); + BKE_reports_init(&sj->reports, RPT_PRINT); + /* setup job */ WM_jobs_customdata(steve, sj, screenshot_freejob); WM_jobs_timer(steve, 0.1, 0, NC_SCREEN|ND_SCREENCAST); diff --git a/source/blender/quicktime/apple/qtkit_export.m b/source/blender/quicktime/apple/qtkit_export.m index c7759055d7e..38baacf009e 100644 --- a/source/blender/quicktime/apple/qtkit_export.m +++ b/source/blender/quicktime/apple/qtkit_export.m @@ -154,68 +154,68 @@ void makeqtstring (RenderData *rd, char *string) { #pragma mark export functions -void start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty) +int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, ReportList *reports) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSError *error; char name[2048]; + int success= 1; + if(qtexport == NULL) qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport"); - if (G.afbreek != 1) { - - if(qtexport == NULL) qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport"); - - [QTMovie enterQTKitOnThread]; - - /* Check first if the QuickTime 7.2.1 initToWritableFile: method is available */ - if ([[[[QTMovie alloc] init] autorelease] respondsToSelector:@selector(initToWritableFile:error:)] != YES) { - G.afbreek = 1; - fprintf(stderr, "\nUnable to create quicktime movie, need Quicktime rev 7.2.1 or later"); - } - else { - makeqtstring(rd, name); - qtexport->filename = [NSString stringWithCString:name - encoding:[NSString defaultCStringEncoding]]; - qtexport->movie = [[QTMovie alloc] initToWritableFile:qtexport->filename error:&error]; - - if(qtexport->movie == nil) { - G.afbreek = 1; - NSLog(@"Unable to create quicktime movie : %@",[error localizedDescription]); - [QTMovie exitQTKitOnThread]; - } else { - [qtexport->movie retain]; - [qtexport->filename retain]; - [qtexport->movie setAttribute:[NSNumber numberWithBool:YES] forKey:QTMovieEditableAttribute]; - [qtexport->movie setAttribute:@"Made with Blender" forKey:QTMovieCopyrightAttribute]; - - qtexport->frameDuration = QTMakeTime(rd->frs_sec_base*1000, rd->frs_sec*1000); - - /* specifying the codec attributes : try to retrieve them from render data first*/ - if (rd->qtcodecsettings.codecType) { - qtexport->frameAttributes = [NSDictionary dictionaryWithObjectsAndKeys: - stringWithCodecType(rd->qtcodecsettings.codecType), - QTAddImageCodecType, - [NSNumber numberWithLong:((rd->qtcodecsettings.codecSpatialQuality)*codecLosslessQuality)/100], - QTAddImageCodecQuality, - nil]; - } - else { - qtexport->frameAttributes = [NSDictionary dictionaryWithObjectsAndKeys:@"jpeg", - QTAddImageCodecType, - [NSNumber numberWithLong:codecHighQuality], - QTAddImageCodecQuality, - nil]; - } - [qtexport->frameAttributes retain]; + [QTMovie enterQTKitOnThread]; + + /* Check first if the QuickTime 7.2.1 initToWritableFile: method is available */ + if ([[[[QTMovie alloc] init] autorelease] respondsToSelector:@selector(initToWritableFile:error:)] != YES) { + BKE_report(reports, RPT_EROR, "\nUnable to create quicktime movie, need Quicktime rev 7.2.1 or later"); + success= 0; + } + else { + makeqtstring(rd, name); + qtexport->filename = [NSString stringWithCString:name + encoding:[NSString defaultCStringEncoding]]; + qtexport->movie = [[QTMovie alloc] initToWritableFile:qtexport->filename error:&error]; + + if(qtexport->movie == nil) { + BKE_report(reports, RPT_ERROR, "Unable to create quicktime movie."); + success= 0; + NSLog(@"Unable to create quicktime movie : %@",[error localizedDescription]); + [QTMovie exitQTKitOnThread]; + } else { + [qtexport->movie retain]; + [qtexport->filename retain]; + [qtexport->movie setAttribute:[NSNumber numberWithBool:YES] forKey:QTMovieEditableAttribute]; + [qtexport->movie setAttribute:@"Made with Blender" forKey:QTMovieCopyrightAttribute]; + + qtexport->frameDuration = QTMakeTime(rd->frs_sec_base*1000, rd->frs_sec*1000); + + /* specifying the codec attributes : try to retrieve them from render data first*/ + if (rd->qtcodecsettings.codecType) { + qtexport->frameAttributes = [NSDictionary dictionaryWithObjectsAndKeys: + stringWithCodecType(rd->qtcodecsettings.codecType), + QTAddImageCodecType, + [NSNumber numberWithLong:((rd->qtcodecsettings.codecSpatialQuality)*codecLosslessQuality)/100], + QTAddImageCodecQuality, + nil]; } + else { + qtexport->frameAttributes = [NSDictionary dictionaryWithObjectsAndKeys:@"jpeg", + QTAddImageCodecType, + [NSNumber numberWithLong:codecHighQuality], + QTAddImageCodecQuality, + nil]; + } + [qtexport->frameAttributes retain]; } } [pool drain]; + + return success; } -void append_qt(struct RenderData *rd, int frame, int *pixels, int rectx, int recty) +int append_qt(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSBitmapImageRep *blBitmapFormatImage; @@ -235,7 +235,7 @@ void append_qt(struct RenderData *rd, int frame, int *pixels, int rectx, int rec bitsPerPixel:32]; if (!blBitmapFormatImage) { [pool drain]; - return; + return 0; } from_Ptr = (unsigned char*)pixels; @@ -257,6 +257,8 @@ void append_qt(struct RenderData *rd, int frame, int *pixels, int rectx, int rec [blBitmapFormatImage release]; [frameImage release]; [pool drain]; + + return 1; } diff --git a/source/blender/quicktime/apple/quicktime_export.c b/source/blender/quicktime/apple/quicktime_export.c index 68fd60d89d2..a5737e93271 100644 --- a/source/blender/quicktime/apple/quicktime_export.c +++ b/source/blender/quicktime/apple/quicktime_export.c @@ -503,7 +503,7 @@ void makeqtstring (RenderData *rd, char *string) { } -void start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty) { +int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, ReportList *reports) { OSErr err = noErr; char name[2048]; @@ -515,6 +515,7 @@ void start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty) #else char *qtname; #endif + int success= 1; if(qtexport == NULL) qtexport = MEM_callocN(sizeof(QuicktimeExport), "QuicktimeExport"); @@ -534,57 +535,57 @@ void start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty) check_renderbutton_framerate(rd); } - if (G.afbreek != 1) { - sframe = (rd->sfra); + sframe = (rd->sfra); - makeqtstring(rd, name); + makeqtstring(rd, name); #ifdef __APPLE__ - EnterMoviesOnThread(0); - sprintf(theFullPath, "%s", name); - - /* hack: create an empty file to make FSPathMakeRef() happy */ - myFile = open(theFullPath, O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRUSR|S_IWUSR); - if (myFile < 0) { - printf("error while creating file!\n"); - /* do something? */ - } - close(myFile); - err = FSPathMakeRef((const UInt8 *)theFullPath, &myRef, 0); - CheckError(err, "FsPathMakeRef error"); - err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &qtexport->theSpec, NULL); - CheckError(err, "FsGetCatalogInfoRef error"); + EnterMoviesOnThread(0); + sprintf(theFullPath, "%s", name); + + /* hack: create an empty file to make FSPathMakeRef() happy */ + myFile = open(theFullPath, O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRUSR|S_IWUSR); + if (myFile < 0) { + printf("error while creating file!\n"); + /* do something? */ + } + close(myFile); + err = FSPathMakeRef((const UInt8 *)theFullPath, &myRef, 0); + CheckError(err, "FsPathMakeRef error"); + err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &qtexport->theSpec, NULL); + CheckError(err, "FsGetCatalogInfoRef error"); #endif #ifdef _WIN32 - qtname = get_valid_qtname(name); - sprintf(theFullPath, "%s", qtname); - strcpy(name, qtname); - MEM_freeN(qtname); - - CopyCStringToPascal(theFullPath, qtexport->qtfilename); - err = FSMakeFSSpec(0, 0L, qtexport->qtfilename, &qtexport->theSpec); + qtname = get_valid_qtname(name); + sprintf(theFullPath, "%s", qtname); + strcpy(name, qtname); + MEM_freeN(qtname); + + CopyCStringToPascal(theFullPath, qtexport->qtfilename); + err = FSMakeFSSpec(0, 0L, qtexport->qtfilename, &qtexport->theSpec); #endif - err = CreateMovieFile (&qtexport->theSpec, - kMyCreatorType, - smCurrentScript, - createMovieFileDeleteCurFile | createMovieFileDontCreateResFile, - &qtexport->resRefNum, - &qtexport->theMovie ); - CheckError(err, "CreateMovieFile error"); - - if(err != noErr) { - G.afbreek = 1; -// XXX error("Unable to create Quicktime movie: %s", name); + err = CreateMovieFile (&qtexport->theSpec, + kMyCreatorType, + smCurrentScript, + createMovieFileDeleteCurFile | createMovieFileDontCreateResFile, + &qtexport->resRefNum, + &qtexport->theMovie ); + CheckError(err, "CreateMovieFile error"); + + if(err != noErr) { + BKE_reportf(reports, RPT_ERROR, "Unable to create Quicktime movie: %s", name); + success= 0; #ifdef __APPLE__ - ExitMoviesOnThread(); + ExitMoviesOnThread(); #endif - } else { - printf("Created QuickTime movie: %s\n", name); + } else { + printf("Created QuickTime movie: %s\n", name); - QT_CreateMyVideoTrack(rectx, recty); - } + QT_CreateMyVideoTrack(rectx, recty); } + + return success; } diff --git a/source/blender/quicktime/quicktime_export.h b/source/blender/quicktime/quicktime_export.h index 69f679693f6..543371999ed 100644 --- a/source/blender/quicktime/quicktime_export.h +++ b/source/blender/quicktime/quicktime_export.h @@ -46,8 +46,8 @@ struct RenderData; struct Scene; struct wmOperatorType; -void start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty); //for movie handle (BKE writeavi.c now) -void append_qt(struct RenderData *rd, int frame, int *pixels, int rectx, int recty); +int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, ReportList *reports); //for movie handle (BKE writeavi.c now) +int append_qt(struct RenderData *rd, int frame, int *pixels, int rectx, int recty, ReportList *reports); void end_qt(void); /*RNA helper functions */ diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 477a4baead9..76e3e002513 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -44,6 +44,7 @@ struct RenderData; struct RenderEngine; struct RenderEngineType; struct RenderResult; +struct ReportList; struct Scene; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -200,7 +201,7 @@ void RE_TileProcessor(struct Render *re, int firsttile, int threaded); /* only RE_NewRender() needed, main Blender render calls */ void RE_BlenderFrame(struct Render *re, struct Scene *scene, int frame); -void RE_BlenderAnim(struct Render *re, struct Scene *scene, int sfra, int efra, int tfra); +void RE_BlenderAnim(struct Render *re, struct Scene *scene, int sfra, int efra, int tfra, struct ReportList *reports); void RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode); void RE_WriteRenderResult(RenderResult *rr, char *filename, int compress); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index f7d3d6f419a..e2b290f655b 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2752,10 +2752,11 @@ void RE_BlenderFrame(Render *re, Scene *scene, int frame) re->result_ok= 1; } -static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh) +static int do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh, ReportList *reports) { char name[FILE_MAX]; RenderResult rres; + int ok= 1; RE_AcquireResultImage(re, &rres); @@ -2768,7 +2769,7 @@ static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh) dofree = 1; } RE_ResultGet32(re, (unsigned int *)rres.rect32); - mh->append_movie(&re->r, scene->r.cfra, rres.rect32, rres.rectx, rres.recty); + ok= mh->append_movie(&re->r, scene->r.cfra, rres.rect32, rres.rectx, rres.recty, reports); if(dofree) { MEM_freeN(rres.rect32); } @@ -2785,7 +2786,6 @@ static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh) } else { ImBuf *ibuf= IMB_allocImBuf(rres.rectx, rres.recty, scene->r.planes, 0, 0); - int ok; /* if not exists, BKE_write_ibuf makes one */ ibuf->rect= (unsigned int *)rres.rect32; @@ -2802,7 +2802,6 @@ static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh) if(ok==0) { printf("Render error: cannot save %s\n", name); - G.afbreek=1; } else printf("Saved: %s", name); @@ -2826,10 +2825,12 @@ static void do_write_image_or_movie(Render *re, Scene *scene, bMovieHandle *mh) BLI_timestr(re->i.lastframetime, name); printf(" Time: %s\n", name); fflush(stdout); /* needed for renderd !! (not anymore... (ton)) */ + + return ok; } /* saves images to disk */ -void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra) +void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra, ReportList *reports) { bMovieHandle *mh= BKE_get_movie_handle(scene->r.imtype); unsigned int lay; @@ -2846,18 +2847,20 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra) re->result_ok= 0; if(BKE_imtype_is_movie(scene->r.imtype)) - mh->start_movie(scene, &re->r, re->rectx, re->recty); - + if(!mh->start_movie(scene, &re->r, re->rectx, re->recty, reports)) + G.afbreek= 1; + if (mh->get_next_frame) { while (!(G.afbreek == 1)) { - int nf = mh->get_next_frame(&re->r); + int nf = mh->get_next_frame(&re->r, reports); if (nf >= 0 && nf >= scene->r.sfra && nf <= scene->r.efra) { scene->r.cfra = re->r.cfra = nf; do_render_all_options(re); if(re->test_break(re->tbh) == 0) { - do_write_image_or_movie(re, scene, mh); + if(!do_write_image_or_movie(re, scene, mh, reports)) + G.afbreek= 1; } } else { if(re->test_break(re->tbh)) @@ -2907,8 +2910,11 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra, int tfra) do_render_all_options(re); - if(re->test_break(re->tbh) == 0) - do_write_image_or_movie(re, scene, mh); + if(re->test_break(re->tbh) == 0) { + if(!G.afbreek) + if(!do_write_image_or_movie(re, scene, mh, reports)) + G.afbreek= 1; + } else G.afbreek= 1; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 435f3823fed..6b0368fbf8a 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -305,7 +305,7 @@ static int wm_operator_exec(bContext *C, wmOperator *op, int repeat) if(op->type->exec) retval= op->type->exec(C, op); - if(!(retval & OPERATOR_RUNNING_MODAL)) + if(retval & (OPERATOR_FINISHED|OPERATOR_CANCELLED)) if(op->reports->list.first) uiPupMenuReports(C, op->reports); @@ -435,11 +435,11 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P /* Note, if the report is given as an argument then assume the caller will deal with displaying them * currently python only uses this */ - if(!(retval & OPERATOR_RUNNING_MODAL) && reports==NULL) { + if((retval & (OPERATOR_FINISHED|OPERATOR_CANCELLED)) && reports==NULL) if(op->reports->list.first) /* only show the report if the report list was not given in the function */ uiPupMenuReports(C, op->reports); - if (retval & OPERATOR_FINISHED) /* todo - this may conflict with the other wm_operator_print, if theres ever 2 prints for 1 action will may need to add modal check here */ + if (retval & OPERATOR_FINISHED) { /* todo - this may conflict with the other wm_operator_print, if theres ever 2 prints for 1 action will may need to add modal check here */ if(G.f & G_DEBUG) wm_operator_print(op); } @@ -884,7 +884,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand CTX_wm_region_set(C, NULL); } - if(!(retval & OPERATOR_RUNNING_MODAL)) + if(retval & (OPERATOR_FINISHED|OPERATOR_CANCELLED)) if(op->reports->list.first) uiPupMenuReports(C, op->reports); diff --git a/source/creator/creator.c b/source/creator/creator.c index c080062347d..cad79395b76 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -651,10 +651,13 @@ int main(int argc, char **argv) if (a < argc) { int frame = atoi(argv[a]); Render *re = RE_NewRender(scene->id.name); + ReportList reports; + + BKE_reports_init(&reports, RPT_PRINT); frame = MIN2(MAXFRAME, MAX2(MINAFRAME, frame)); - RE_BlenderAnim(re, scene, frame, frame, scene->r.frame_step); + RE_BlenderAnim(re, scene, frame, frame, scene->r.frame_step, &reports); } } else { printf("\nError: no blend loaded. cannot use '-f'.\n"); @@ -664,7 +667,9 @@ int main(int argc, char **argv) if (CTX_data_scene(C)) { Scene *scene= CTX_data_scene(C); Render *re= RE_NewRender(scene->id.name); - RE_BlenderAnim(re, scene, scene->r.sfra, scene->r.efra, scene->r.frame_step); + ReportList reports; + BKE_reports_init(&reports, RPT_PRINT); + RE_BlenderAnim(re, scene, scene->r.sfra, scene->r.efra, scene->r.frame_step, &reports); } else { printf("\nError: no blend loaded. cannot use '-a'.\n"); } -- cgit v1.2.3