Test: making screencast movies inside Blender!
Hotkey: CTRL+F3. Stop with ESC

Keep in mind it's unfinished :)

Just nice to see how simple cleaner code with the new event 
system and job manager can be put to work!

- it uses currently output directory and image/movie 
  settings from scene. No buttons for this yet.
- Framerate is hardcoded 10 fps
- Thread job takes care of open/write/close movie
  or save image files.
- For speed it uses glReadPixels from backbuffer. Have
  to consult Brecht for nifty triple buffer trick.
- On file reads it stops now.
This commit is contained in:
2009-02-14 18:31:19 +00:00
parent 7dce015c90
commit aba3c36e33
3 changed files with 109 additions and 16 deletions

View File

@@ -59,6 +59,7 @@ void ed_screen_context(const bContext *C, bContextDataMember member, bContextDat
/* screendump.c */
void SCREEN_OT_screenshot(struct wmOperatorType *ot);
void SCREEN_OT_screencast(struct wmOperatorType *ot);
#endif /* ED_SCREEN_INTERN_H */

View File

@@ -2038,15 +2038,16 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
return;
/* xmin here is first subrect x coord, xmax defines subrect width */
xmin = renrect->xmin;
xmax = renrect->xmax - xmin;
xmin = renrect->xmin + rr->crop;
xmax = renrect->xmax - xmin - rr->crop;
if (xmax<2) return;
ymin= renrect->ymin;
ymax= renrect->ymax - ymin;
ymin= renrect->ymin + rr->crop;
ymax= renrect->ymax - ymin - rr->crop;
if(ymax<2)
return;
renrect->ymin= renrect->ymax;
}
else {
xmin = ymin = rr->crop;
@@ -2087,7 +2088,7 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec
float *rf= rectf;
char *rc= rectc;
/* crop offset */
/* XXX temp. because crop offset */
if( rectc >= (char *)(ibuf->rect)) {
for(x1= 0; x1<xmax; x1++, rf += 4, rc+=4) {
rc[0]= FTOCHAR(rf[0]);
@@ -2267,6 +2268,7 @@ void ED_operatortypes_screen(void)
WM_operatortype_append(SCREEN_OT_screen_set);
WM_operatortype_append(SCREEN_OT_screen_full_area);
WM_operatortype_append(SCREEN_OT_screenshot);
WM_operatortype_append(SCREEN_OT_screencast);
/*frame changes*/
WM_operatortype_append(SCREEN_OT_frame_offset);
@@ -2303,6 +2305,7 @@ void ED_keymap_screen(wmWindowManager *wm)
WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", DOWNARROWKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "SCREEN_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "SCREEN_OT_screenshot", F3KEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "SCREEN_OT_screencast", F3KEY, KM_PRESS, KM_ALT, 0);
/* tests */
WM_keymap_add_item(keymap, "SCREEN_OT_region_split", SKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);

View File

@@ -43,6 +43,7 @@
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_utildefines.h"
#include "BKE_writeavi.h"
#include "BIF_gl.h"
@@ -52,8 +53,13 @@
#include "WM_types.h"
#include "WM_api.h"
#include "PIL_time.h"
#include "ED_fileselect.h"
#include "ED_screen.h"
#include "ED_screen_types.h"
#include "screen_intern.h"
typedef struct ScreenshotData {
unsigned int *dumprect;
@@ -177,10 +183,11 @@ void SCREEN_OT_screenshot(wmOperatorType *ot)
}
/* *************** screenshot movie job ************************* */
#if 0
typedef struct ScreenshotJob {
Scene *scene;
unsigned int *dumprect;
int dumpsx, dumpsy;
int x, y, dumpsx, dumpsy;
short *stop;
short *do_update;
} ScreenshotJob;
@@ -190,6 +197,9 @@ static void screenshot_freejob(void *sjv)
{
ScreenshotJob *sj= sjv;
if(sj->dumprect)
MEM_freeN(sj->dumprect);
MEM_freeN(sj);
}
@@ -198,7 +208,15 @@ static void screenshot_freejob(void *sjv)
static void screenshot_updatejob(void *sjv)
{
ScreenshotJob *sj= sjv;
unsigned int *dumprect;
if(sj->dumprect==NULL) {
dumprect= MEM_mallocN(sizeof(int) * sj->dumpsx * sj->dumpsy, "dumprect");
glReadPixels(sj->x, sj->y, sj->dumpsx, sj->dumpsy, GL_RGBA, GL_UNSIGNED_BYTE, dumprect);
glFinish();
sj->dumprect= dumprect;
}
}
@@ -206,38 +224,110 @@ static void screenshot_updatejob(void *sjv)
static void screenshot_startjob(void *sjv, short *stop, short *do_update)
{
ScreenshotJob *sj= sjv;
RenderData rd= sj->scene->r;
bMovieHandle *mh= BKE_get_movie_handle(sj->scene->r.imtype);
int cfra= 1;
/* we need this as local variables for renderdata */
rd.frs_sec= 10;
rd.frs_sec_base= 1.0f;
if(BKE_imtype_is_movie(rd.imtype))
mh->start_movie(&rd, sj->dumpsx, sj->dumpsy);
else
mh= NULL;
sj->stop= stop;
sj->do_update= do_update;
*do_update= 1; // wait for opengl rect
while(*stop==0 && G.afbreek==0) {
if(sj->dumprect) {
if(mh) {
mh->append_movie(&rd, cfra, sj->dumprect, sj->dumpsx, sj->dumpsy);
printf("Append frame %d\n", cfra);
}
else {
ImBuf *ibuf= IMB_allocImBuf(sj->dumpsx, sj->dumpsy, rd.planes, 0, 0);
char name[FILE_MAXDIR+FILE_MAXFILE];
int ok;
BKE_makepicstring(sj->scene, name, rd.pic, cfra, rd.imtype);
ibuf->rect= sj->dumprect;
ok= BKE_write_ibuf(sj->scene, ibuf, name, rd.imtype, rd.subimtype, rd.quality);
if(ok==0) {
printf("Write error: cannot save %s\n", name);
break;
}
else printf("Saved: %s\n", name);
/* imbuf knows which rects are not part of ibuf */
IMB_freeImBuf(ibuf);
}
MEM_freeN(sj->dumprect);
sj->dumprect= NULL;
*do_update= 1;
cfra++;
}
else
PIL_sleep_ms(50);
}
if(mh)
mh->end_movie();
printf("screencast job stopped\n");
}
static int screenshot_job_invoke(const bContext *C, wmOperator *op, wmEvent *event)
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);
ScreenshotJob *sj= MEM_callocN(sizeof(ScreenshotJob), "screenshot job");
/* customdata for preview thread */
/* setup sj */
if(RNA_boolean_get(op->ptr, "full")) {
wmWindow *win= CTX_wm_window(C);
sj->x= 0;
sj->y= 0;
sj->dumpsx= win->sizex;
sj->dumpsy= win->sizey;
}
else {
ScrArea *curarea= CTX_wm_area(C);
sj->x= curarea->totrct.xmin;
sj->y= curarea->totrct.ymin;
sj->dumpsx= curarea->totrct.xmax - sj->x;
sj->dumpsy= curarea->totrct.ymax - sj->y;
}
sj->scene= CTX_data_scene(C);
/* setup job */
WM_jobs_customdata(steve, sj, screenshot_freejob);
WM_jobs_timer(steve, 0.1, 0, 0);
WM_jobs_callbacks(steve, screenshot_startjob, NULL, screenshot_updatejob);
G.afbreek= 0; // XXX?
WM_jobs_start(steve);
return OPERATOR_FINISHED;
}
void SCREEN_OT_screenshot_movie(wmOperatorType *ot)
void SCREEN_OT_screencast(wmOperatorType *ot)
{
ot->name= "Make Screenshot";
ot->idname= "SCREEN_OT_screenshot_movie";
ot->name= "Make Screencast";
ot->idname= "SCREEN_OT_screencast";
ot->invoke= screenshot_invoke;
ot->exec= screenshot_exec;
ot->invoke= WM_operator_confirm;
ot->exec= screencast_exec;
ot->poll= WM_operator_winactive;
ot->flag= 0;
@@ -247,5 +337,4 @@ void SCREEN_OT_screenshot_movie(wmOperatorType *ot)
}
#endif