From 327d413eb3c0c4cf07b71903eaa27e784be172c3 Mon Sep 17 00:00:00 2001 From: Peter Schlaile Date: Tue, 7 Mar 2006 20:01:12 +0000 Subject: this patch features several cleanups and bugfixes for the sequencer: - blur works again (this was a serious bug in gamwarp...) - seperates all sequence effects into a seperate file with a clean interface - thereby fixing some obscure segfaults - seperates the scope views into a seperate file - adds float support to all effects and scope views - removes a bad level call to open_plugin_seq - FFMPEG seeking improved a lot. - FFMPEG compiles with debian sarge version cleanly - Makes hdaudio seek and resample code really work --- source/blender/blenkernel/BKE_bad_level_calls.h | 2 - .../blenkernel/bad_level_call_stubs/stubs.c | 2 - source/blender/blenkernel/intern/writeffmpeg.c | 75 +- .../blender/blenkernel/intern/writeframeserver.c | 8 +- source/blender/blenloader/intern/readfile.c | 8 +- source/blender/imbuf/IMB_imbuf.h | 2 + source/blender/imbuf/intern/IMB_anim.h | 1 + source/blender/imbuf/intern/anim.c | 160 +- source/blender/imbuf/intern/divers.c | 33 +- source/blender/imbuf/intern/scaling.c | 16 +- source/blender/imbuf/intern/util.c | 28 +- source/blender/include/BSE_seqeffects.h | 83 + source/blender/include/BSE_seqscopes.h | 38 + source/blender/include/BSE_sequence.h | 64 - source/blender/makesdna/DNA_sequence_types.h | 3 + source/blender/src/drawseq.c | 13 +- source/blender/src/editseq.c | 125 +- source/blender/src/hddaudio.c | 360 ++- source/blender/src/seqeffects.c | 2515 ++++++++++++++++++++ source/blender/src/seqscopes.c | 340 +++ source/blender/src/sequence.c | 1723 ++------------ 21 files changed, 3679 insertions(+), 1920 deletions(-) create mode 100644 source/blender/include/BSE_seqeffects.h create mode 100644 source/blender/include/BSE_seqscopes.h create mode 100644 source/blender/src/seqeffects.c create mode 100644 source/blender/src/seqscopes.c (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h index 1bc02a02ea6..f261f786dd4 100644 --- a/source/blender/blenkernel/BKE_bad_level_calls.h +++ b/source/blender/blenkernel/BKE_bad_level_calls.h @@ -43,8 +43,6 @@ void free_editText(void); void free_vertexpaint(void); /* readfile.c */ -struct PluginSeq; -void open_plugin_seq(struct PluginSeq *pis, char *seqname); struct SpaceButs; void set_rects_butspace(struct SpaceButs *buts); struct SpaceImaSel; diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index e200c6a88ad..81b6130c021 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -63,8 +63,6 @@ void fluidsimSettingsFree(struct FluidsimSettings* sb); /* readfile.c */ - /* struct PluginSeq; */ -void open_plugin_seq(struct PluginSeq *pis, char *seqname){} /* struct SpaceButs; */ void set_rects_butspace(struct SpaceButs *buts){} /* struct SpaceImaSel; */ diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index b5e318f7279..5d67760f54a 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -28,6 +29,7 @@ #define FFMPEG_OLD_FRAME_RATE 1 #else #define FFMPEG_CODEC_IS_POINTER 1 +#define FFMPEG_CODEC_TIME_BASE 1 #endif #include "BKE_writeffmpeg.h" @@ -77,8 +79,6 @@ static uint8_t* audio_output_buffer = 0; static int audio_outbuf_size = 0; static RenderData *ffmpeg_renderdata; -static int ffmpeg_rectx; -static int ffmpeg_recty; #define FFMPEG_AUTOSPLIT_SIZE 2000000000 @@ -92,11 +92,23 @@ void delete_picture(AVFrame* f) } } +#ifdef FFMPEG_CODEC_IS_POINTER +static AVCodecContext* get_codec_from_stream(AVStream* stream) +{ + return stream->codec; +} +#else +static AVCodecContext* get_codec_from_stream(AVStream* stream) +{ + return &stream->codec; +} +#endif + int write_audio_frame(void) { AVCodecContext* c = NULL; AVPacket pkt; - c = audio_stream->codec; + c = get_codec_from_stream(audio_stream); audiostream_fill(audio_input_buffer, audio_input_frame_size @@ -108,8 +120,12 @@ int write_audio_frame(void) { audio_outbuf_size, (short*) audio_input_buffer); pkt.data = audio_output_buffer; +#ifdef FFMPEG_CODEC_TIME_BASE pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, audio_stream->time_base); +#else + pkt.pts = c->coded_frame->pts; +#endif pkt.stream_index = audio_stream->index; pkt.flags |= PKT_FLAG_KEY; if (av_write_frame(outfile, &pkt) != 0) { @@ -150,9 +166,11 @@ AVOutputFormat* ffmpeg_get_format(int format) f = guess_format("dv", NULL, NULL); break; case FFMPEG_MPEG1: - case FFMPEG_MPEG2: f = guess_format("mpeg", NULL, NULL); break; + case FFMPEG_MPEG2: + f = guess_format("dvd", NULL, NULL); + break; case FFMPEG_MPEG4: f = guess_format("mp4", NULL, NULL); break; @@ -218,11 +236,7 @@ void makeffmpegstring(char* string) { static void write_video_frame(AVFrame* frame) { int outsize = 0; int ret; -#ifdef FFMPEG_CODEC_IS_POINTER - AVCodecContext* c = video_stream->codec; -#else - AVCodecContext* c = &video_stream->codec; -#endif + AVCodecContext* c = get_codec_from_stream(video_stream); frame->pts = G.scene->r.cfra - G.scene->r.sfra; outsize = avcodec_encode_video(c, video_buffer, video_buffersize, @@ -231,9 +245,13 @@ static void write_video_frame(AVFrame* frame) { AVPacket packet; av_init_packet(&packet); +#ifdef FFMPEG_CODEC_TIME_BASE packet.pts = av_rescale_q(c->coded_frame->pts, c->time_base, video_stream->time_base); +#else + packet.pts = c->coded_frame->pts; +#endif if (c->coded_frame->key_frame) packet.flags |= PKT_FLAG_KEY; packet.stream_index = video_stream->index; @@ -252,11 +270,7 @@ static AVFrame* generate_video_frame(uint8_t* pixels) { uint8_t* rendered_frame; -#ifdef FFMPEG_CODEC_IS_POINTER - AVCodecContext* c = video_stream->codec; -#else - AVCodecContext* c = &video_stream->codec; -#endif + AVCodecContext* c = get_codec_from_stream(video_stream); int width = c->width; int height = c->height; AVFrame* rgb_frame; @@ -334,11 +348,7 @@ static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of, /* Set up the codec context */ -#ifdef FFMPEG_CODEC_IS_POINTER - c = st->codec; -#else - c = &st->codec; -#endif + c = get_codec_from_stream(st); c->codec_id = codec_id; c->codec_type = CODEC_TYPE_VIDEO; @@ -348,6 +358,7 @@ static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of, c->width = rectx; c->height = recty; +#ifdef FFMPEG_CODEC_TIME_BASE /* FIXME: Really bad hack (tm) for NTSC support */ if (ffmpeg_type == FFMPEG_DV && G.scene->r.frs_sec != 25) { c->time_base.den = 2997; @@ -356,6 +367,16 @@ static AVStream* alloc_video_stream(int codec_id, AVFormatContext* of, c->time_base.den = G.scene->r.frs_sec; c->time_base.num = 1; } +#else + /* FIXME: Really bad hack (tm) for NTSC support */ + if (ffmpeg_type == FFMPEG_DV && G.scene->r.frs_sec != 25) { + c->frame_rate = 2997; + c->frame_rate_base = 100; + } else { + c->frame_rate = G.scene->r.frs_sec; + c->frame_rate_base = 1; + } +#endif c->gop_size = ffmpeg_gop_size; c->bit_rate = ffmpeg_video_bitrate*1000; @@ -419,7 +440,7 @@ AVStream* alloc_audio_stream(int codec_id, AVFormatContext* of) st = av_new_stream(of, 1); if (!st) return NULL; - c = st->codec; + c = get_codec_from_stream(st); c->codec_id = codec_id; c->codec_type = CODEC_TYPE_AUDIO; @@ -445,7 +466,7 @@ AVStream* alloc_audio_stream(int codec_id, AVFormatContext* of) if (c->frame_size <= 1) { audio_input_frame_size = audio_outbuf_size / c->channels; - switch(st->codec->codec_id) { + switch(c->codec_id) { case CODEC_ID_PCM_S16LE: case CODEC_ID_PCM_S16BE: case CODEC_ID_PCM_U16LE: @@ -600,14 +621,14 @@ void append_ffmpeg(int frame, int *pixels, int rectx, int recty) )) { write_audio_frame(); } - write_video_frame(generate_video_frame(pixels)); + write_video_frame(generate_video_frame((unsigned char*) pixels)); if (ffmpeg_autosplit) { - if (url_fsize(&outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) { + if (url_ftell(&outfile->pb) > FFMPEG_AUTOSPLIT_SIZE) { end_ffmpeg(); ffmpeg_autosplit_count++; - start_ffmpeg_impl(rectx, recty, - ffmpeg_renderdata); + start_ffmpeg_impl(ffmpeg_renderdata, + rectx, recty); } } } @@ -625,8 +646,8 @@ void end_ffmpeg(void) /* Close the video codec */ - if (video_stream && video_stream->codec) { - avcodec_close(video_stream->codec); + if (video_stream && get_codec_from_stream(video_stream)) { + avcodec_close(get_codec_from_stream(video_stream)); } diff --git a/source/blender/blenkernel/intern/writeframeserver.c b/source/blender/blenkernel/intern/writeframeserver.c index b82f9581cf3..58d8f82d454 100644 --- a/source/blender/blenkernel/intern/writeframeserver.c +++ b/source/blender/blenkernel/intern/writeframeserver.c @@ -165,10 +165,7 @@ static int handle_request(char * req) { char * p; char * path; - - if (strlen(req) < 20) { - return -1; - } + int pathlen; if (memcmp(req, "GET ", 4) != 0) { return -1; @@ -188,8 +185,9 @@ static int handle_request(char * req) } write_ppm = 0; + pathlen = strlen(path); - if (memcmp(path, "/images/ppm/", 12) == 0) { + if (pathlen > 12 && memcmp(path, "/images/ppm/", 12) == 0) { write_ppm = 1; return atoi(path + 12); } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 31dfa93d4c5..7e452ddd64c 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -104,7 +104,7 @@ #include "BLI_arithb.h" #include "BLI_storage_types.h" // for relname flags -#include "BKE_bad_level_calls.h" // for reopen_text build_seqar (from WHILE_SEQ) open_plugin_seq set_rects_butspace check_imasel_copy +#include "BKE_bad_level_calls.h" // for reopen_text build_seqar (from WHILE_SEQ) set_rects_butspace check_imasel_copy #include "BKE_action.h" #include "BKE_armature.h" @@ -2718,9 +2718,11 @@ static void direct_link_scene(FileData *fd, Scene *sce) seq->curelem= 0; seq->plugin= newdataadr(fd, seq->plugin); - if(seq->plugin) open_plugin_seq(seq->plugin, seq->name+2); - seq->effectdata= newdataadr(fd, seq->effectdata); + + if (seq->type & SEQ_EFFECT) { + seq->flag |= SEQ_EFFECT_NOT_LOADED; + } seq->strip= newdataadr(fd, seq->strip); if(seq->strip && seq->strip->done==0) { diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 39243ec50d1..c4141b0a868 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -240,6 +240,8 @@ void IMB_close_anim(struct anim * anim); */ int ismovie(char *name); +void IMB_anim_set_preseek(struct anim * anim, int preseek); +int IMB_anim_get_preseek(struct anim * anim); /** * diff --git a/source/blender/imbuf/intern/IMB_anim.h b/source/blender/imbuf/intern/IMB_anim.h index 5d597aa5463..602b13df4ca 100644 --- a/source/blender/imbuf/intern/IMB_anim.h +++ b/source/blender/imbuf/intern/IMB_anim.h @@ -153,6 +153,7 @@ struct anim { int orientation; size_t framesize; int interlacing; + int preseek; /* data */ struct ImBuf * ibuf1, * ibuf2; diff --git a/source/blender/imbuf/intern/anim.c b/source/blender/imbuf/intern/anim.c index bd4b268f685..cd238f5013e 100644 --- a/source/blender/imbuf/intern/anim.c +++ b/source/blender/imbuf/intern/anim.c @@ -88,12 +88,19 @@ #ifdef WITH_FFMPEG #include #include +#include + +/* #define FFMPEG_SEEK_DEBUG 1 */ #if LIBAVFORMAT_VERSION_INT < (49 << 16) #define FFMPEG_OLD_FRAME_RATE 1 #else #define FFMPEG_CODEC_IS_POINTER 1 -#define FFMPEG_HAVE_SKIP_FRAME 1 +#define FFMPEG_HAVE_SKIP_OPTS 1 +#endif + +#ifndef FF_ER_CAREFUL +#define FF_ER_CAREFUL FF_ER_CAREFULL #endif #endif @@ -136,6 +143,7 @@ static int startmovie(struct anim * anim) { anim->framesize = dmImageFrameSize(anim->params); anim->curposition = 0; + anim->preseek = 0; /*printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/ return (0); @@ -439,6 +447,7 @@ static int startavi (struct anim *anim) { anim->framesize = anim->x * anim->y * 4; anim->curposition = 0; + anim->preseek = 0; /* printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/ @@ -493,6 +502,18 @@ static ImBuf * avi_fetchibuf (struct anim *anim, int position) { extern void do_init_ffmpeg(); +#ifdef FFMPEG_CODEC_IS_POINTER +static AVCodecContext* get_codec_from_stream(AVStream* stream) +{ + return stream->codec; +} +#else +static AVCodecContext* get_codec_from_stream(AVStream* stream) +{ + return &stream->codec; +} +#endif + static int startffmpeg(struct anim * anim) { int i, videoStream; @@ -519,12 +540,8 @@ static int startffmpeg(struct anim * anim) { /* Find the first video stream */ videoStream=-1; for(i=0; inb_streams; i++) -#ifdef FFMPEG_CODEC_IS_POINTER - if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) -#else - if(pFormatCtx->streams[i]->codec.codec_type==CODEC_TYPE_VIDEO) -#endif - { + if(get_codec_from_stream(pFormatCtx->streams[i])->codec_type + == CODEC_TYPE_VIDEO) { videoStream=i; break; } @@ -534,11 +551,7 @@ static int startffmpeg(struct anim * anim) { return -1; } -#ifdef FFMPEG_CODEC_IS_POINTER - pCodecCtx=pFormatCtx->streams[videoStream]->codec; -#else - pCodecCtx=&pFormatCtx->streams[videoStream]->codec; -#endif + pCodecCtx = get_codec_from_stream(pFormatCtx->streams[videoStream]); /* Find the decoder for the video stream */ pCodec=avcodec_find_decoder(pCodecCtx->codec_id); @@ -551,11 +564,11 @@ static int startffmpeg(struct anim * anim) { pCodecCtx->workaround_bugs = 1; pCodecCtx->lowres = 0; pCodecCtx->idct_algo= FF_IDCT_AUTO; -#ifdef FFMPEG_HAVE_SKIP_FRAME +#ifdef FFMPEG_HAVE_SKIP_OPTS pCodecCtx->skip_frame= AVDISCARD_DEFAULT; -#endif pCodecCtx->skip_idct= AVDISCARD_DEFAULT; pCodecCtx->skip_loop_filter= AVDISCARD_DEFAULT; +#endif pCodecCtx->error_resilience= FF_ER_CAREFUL; pCodecCtx->error_concealment= 3; @@ -573,7 +586,9 @@ static int startffmpeg(struct anim * anim) { anim->duration = pFormatCtx->duration * pCodecCtx->frame_rate / pCodecCtx->frame_rate_base / AV_TIME_BASE; #else - anim->duration = pFormatCtx->duration * av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate) / AV_TIME_BASE; + anim->duration = pFormatCtx->duration + * av_q2d(pFormatCtx->streams[videoStream]->r_frame_rate) + / AV_TIME_BASE; #endif anim->params = 0; @@ -605,7 +620,12 @@ static int startffmpeg(struct anim * anim) { return -1; } - /*printf("x:%d y:%d size:%d interl:%d dur:%d\n", anim->x, anim->y, anim->framesize, anim->interlacing, anim->duration);*/ + if (pCodecCtx->has_b_frames) { + anim->preseek = 18; /* FIXME: detect gopsize ... */ + } else { + anim->preseek = 0; + } + return (0); } @@ -624,23 +644,50 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { (unsigned char*) ibuf->rect, PIX_FMT_RGBA32, anim->x, anim->y); + if (position != anim->curposition + 1) { + if (position > anim->curposition + 1 + && anim->preseek + && position - (anim->curposition + 1) < anim->preseek) { + while(av_read_frame(anim->pFormatCtx, &packet)>=0) { + if (packet.stream_index == anim->videoStream) { + avcodec_decode_video( + anim->pCodecCtx, + anim->pFrame, &frameFinished, + packet.data, packet.size); + + if (frameFinished) { + anim->curposition++; + } + } + av_free_packet(&packet); + if (position == anim->curposition+1) { + break; + } + } + } + } + if (position != anim->curposition + 1) { int keyframe_found = 0; - int scan_pos = position; - int max_scan = 18; /* max mpeg 1/2 gop size */ #ifdef FFMPEG_OLD_FRAME_RATE - long long pos = (long long) anim->pCodecCtx->frame_rate_base - * position * AV_TIME_BASE - / anim->pCodecCtx->frame_rate; + double frame_rate = + (double) anim->pCodecCtx->frame_rate + / (double) anim->pCodecCtx->frame_rate_base; #else - long long pos = (long long) position * AV_TIME_BASE - / av_q2d(anim->pFormatCtx->streams[anim->videoStream] - ->r_frame_rate); + double frame_rate = + av_q2d(anim->pFormatCtx->streams[anim->videoStream] + ->r_frame_rate); #endif + double time_base = + av_q2d(anim->pFormatCtx->streams[anim->videoStream] + ->time_base); + long long pos = (long long) position * AV_TIME_BASE + / frame_rate; long long st_time = anim->pFormatCtx ->streams[anim->videoStream]->start_time; + if (st_time != AV_NOPTS_VALUE) { - pos += st_time; + pos += st_time * AV_TIME_BASE * time_base; } av_seek_frame(anim->pFormatCtx, -1, @@ -653,49 +700,23 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { if ((packet.flags & PKT_FLAG_KEY) != 0) { keyframe_found = 1; } + av_free_packet(&packet); break; } av_free_packet(&packet); } - /* if all ffmpeg seek bugs are fixed, the following - loop is obsolete ... (but does not hurt very much...) - */ - - while (!keyframe_found && max_scan--) { - scan_pos--; -#ifdef FFMPEG_OLD_FRAME_RATE - pos = (long long) - anim->pCodecCtx->frame_rate_base - * scan_pos * AV_TIME_BASE - / anim->pCodecCtx->frame_rate; -#else - pos = (long long) scan_pos * AV_TIME_BASE - / av_q2d(anim->pFormatCtx - ->streams[anim->videoStream] - ->r_frame_rate); -#endif - av_seek_frame(anim->pFormatCtx, -1, - pos, - AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD); - while(av_read_frame(anim->pFormatCtx, &packet)>=0) { - if(packet.stream_index == anim->videoStream) { - if ((packet.flags & PKT_FLAG_KEY) - != 0) { - keyframe_found = 1; - } - av_free_packet(&packet); - break; - } - av_free_packet(&packet); + if (!keyframe_found) { + int scan_pos = position - anim->preseek; + if (scan_pos < 0) { + scan_pos = 0; } - } - if (max_scan <= 0) { - fprintf(stderr, - "Warning: Key frame not found, " - "doesn't hurt, but _slow_...!\n"); + pos = (long long) scan_pos * AV_TIME_BASE / frame_rate; + if (st_time != AV_NOPTS_VALUE) { + pos += st_time * AV_TIME_BASE * time_base; + } } av_seek_frame(anim->pFormatCtx, -1, @@ -710,6 +731,11 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { && !pos_found) { if (url_ftell(&anim->pFormatCtx->pb) == pos_to_match) { pos_found = 1; + if (anim->pCodecCtx->has_b_frames) { + pos_found++; + /* account for delay caused by + decoding pipeline */ + } } } if(packet.stream_index == anim->videoStream) { @@ -717,7 +743,9 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position) { anim->pFrame, &frameFinished, packet.data, packet.size); - if(frameFinished && pos_found) { + if (frameFinished && pos_found == 2) { + pos_found = 1; + } else if(frameFinished && pos_found == 1) { unsigned char * p =(unsigned char*) ibuf->rect; unsigned char * e = p + anim->x * anim->y * 4; @@ -924,3 +952,13 @@ struct ImBuf * IMB_anim_nextpic(struct anim * anim) { int IMB_anim_get_duration(struct anim *anim) { return anim->duration; } + +void IMB_anim_set_preseek(struct anim * anim, int preseek) +{ + anim->preseek = preseek; +} + +int IMB_anim_get_preseek(struct anim * anim) +{ + return anim->preseek; +} diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 2fc80f6ddcb..c0018d0b336 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -141,25 +141,32 @@ void IMB_interlace(struct ImBuf *ibuf) void IMB_gamwarp(struct ImBuf *ibuf, double gamma) { uchar gam[256]; - int i, do_float=0; - uchar *rect = (uchar *) ibuf->rect; - float *rectf = ibuf->rect_float; + int i; + uchar *rect; + float *rectf; if (ibuf == 0) return; - if (ibuf->rect == 0) return; - if (ibuf->rect != NULL) do_float = 1; if (gamma == 1.0) return; + rect = (uchar *) ibuf->rect; + rectf = ibuf->rect_float; + gamma = 1.0 / gamma; - for (i = 255 ; i >= 0 ; i--) gam[i] = (255.0 * pow(i / 255.0 , - gamma)) + 0.5; - rect = (uchar *) ibuf->rect; - for (i = ibuf->x * ibuf->y ; i>0 ; i--, rect+=4){ - rect[0] = gam[rect[0]]; - rect[1] = gam[rect[1]]; - rect[2] = gam[rect[2]]; - if (do_float) { + if (rect) { + for (i = 255 ; i >= 0 ; i--) + gam[i] = (255.0 * pow(i / 255.0 , + gamma)) + 0.5; + + for (i = ibuf->x * ibuf->y ; i>0 ; i--, rect+=4){ + rect[0] = gam[rect[0]]; + rect[1] = gam[rect[1]]; + rect[2] = gam[rect[2]]; + } + } + + if (rectf) { + for (i = ibuf->x * ibuf->y ; i>0 ; i--, rectf+=4){ rectf[0] = pow(rectf[0] / 255.0, gamma); rectf[1] = pow(rectf[1] / 255.0, gamma); rectf[2] = pow(rectf[2] / 255.0, gamma); diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index c962f1fbde5..8db51f50ee0 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -964,10 +964,18 @@ struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, short newx, short newy) ofsy += stepy; ofsx = 32768; - for (x = newx ; x>0 ; x--){ - if (do_rect) *newrect++ = rect[ofsx >> 16]; - if (do_float) *newrectf++ = rectf[ofsx >> 16]; - ofsx += stepx; + if (do_rect) { + for (x = newx ; x>0 ; x--){ + *newrect++ = rect[ofsx >> 16]; + ofsx += stepx; + } + } + + if (do_float) { + for (x = newx ; x>0 ; x--){ + *newrectf++ = rectf[ofsx >> 16]; + ofsx += stepx; + } } } diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index fdb1bed3870..56a03f56ce2 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -217,6 +217,18 @@ void do_init_ffmpeg() } } +#ifdef FFMPEG_CODEC_IS_POINTER +static AVCodecContext* get_codec_from_stream(AVStream* stream) +{ + return stream->codec; +} +#else +static AVCodecContext* get_codec_from_stream(AVStream* stream) +{ + return &stream->codec; +} +#endif + static int isffmpeg (char *filename) { AVFormatContext *pFormatCtx; @@ -243,21 +255,14 @@ static int isffmpeg (char *filename) { /* Find the first video stream */ videoStream=-1; for(i=0; inb_streams; i++) -#ifdef FFMPEG_CODEC_IS_POINTER - if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) -#else - if(pFormatCtx->streams[i]->codec.codec_type==CODEC_TYPE_VIDEO) -#endif + if(get_codec_from_stream(pFormatCtx->streams[i]) + ->codec_type==CODEC_TYPE_VIDEO) { videoStream=i; break; } -#ifdef FFMPEG_CODEC_IS_POINTER - pCodecCtx=pFormatCtx->streams[videoStream]->codec; -#else - pCodecCtx=&pFormatCtx->streams[videoStream]->codec; -#endif + pCodecCtx = get_codec_from_stream(pFormatCtx->streams[videoStream]); if(videoStream==-1) { avcodec_close(pCodecCtx); @@ -274,9 +279,6 @@ static int isffmpeg (char *filename) { return 0; } - if(pCodec->capabilities & CODEC_CAP_TRUNCATED) - pCodecCtx->flags|=CODEC_FLAG_TRUNCATED; - if(avcodec_open(pCodecCtx, pCodec)<0) { avcodec_close(pCodecCtx); av_close_input_file(pFormatCtx); diff --git a/source/blender/include/BSE_seqeffects.h b/source/blender/include/BSE_seqeffects.h new file mode 100644 index 00000000000..a7fd56593e0 --- /dev/null +++ b/source/blender/include/BSE_seqeffects.h @@ -0,0 +1,83 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Peter Schlaile < peter [at] schlaile [dot] de > + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + */ + +#ifndef BSE_SEQUENCE_EFFECTS_H +#define BSE_SEQUENCE_EFFECTS_H + +/* Wipe effect */ +enum {DO_SINGLE_WIPE, DO_DOUBLE_WIPE, DO_BOX_WIPE, DO_CROSS_WIPE, + DO_IRIS_WIPE,DO_CLOCK_WIPE}; + +struct Sequence; +struct ImBuf; + +struct SeqEffectHandle { + /* constructors & destructor */ + /* init & init_plugin are _only_ called on first creation */ + void (*init)(struct Sequence *seq); + void (*init_plugin)(struct Sequence * seq, const char * fname); + + /* load is called first time after readblenfile in + get_sequence_effect automatically */ + void (*load)(struct Sequence *seq); + + /* duplicate */ + void (*copy)(struct Sequence *dst, struct Sequence * src); + + /* destruct */ + void (*free)(struct Sequence *seq); + + /* returns: 0: no early out, 1: out = ibuf1, 2: out = ibuf2 */ + int (*early_out)(struct Sequence *seq, + float facf0, float facf1); + + /* stores the default facf0 and facf1 if no IPO is present */ + void (*get_default_fac)(struct Sequence * seq, int cfra, + float * facf0, float * facf1); + + /* execute the effect + sequence effects are only required to either support + float-rects or byte-rects + (mixed cases are handled one layer up...) */ + + void (*execute)(struct Sequence *seq, int cfra, + float facf0, float facf1, + int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out); +}; + +struct SeqEffectHandle get_sequence_effect(struct Sequence * seq); + +#endif + diff --git a/source/blender/include/BSE_seqscopes.h b/source/blender/include/BSE_seqscopes.h new file mode 100644 index 00000000000..3dd5e495928 --- /dev/null +++ b/source/blender/include/BSE_seqscopes.h @@ -0,0 +1,38 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Author: Peter Schlaile < peter [at] schlaile [dot] de > + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#ifndef BSE_SEQUENCE_SCOPES_H +#define BSE_SEQUENCE_SCOPES_H + +struct ImBuf; + +struct ImBuf *make_waveform_view_from_ibuf(struct ImBuf * ibuf); +struct ImBuf *make_vectorscope_view_from_ibuf(struct ImBuf * ibuf); + +#endif + diff --git a/source/blender/include/BSE_sequence.h b/source/blender/include/BSE_sequence.h index 686749b303d..65c55d95045 100644 --- a/source/blender/include/BSE_sequence.h +++ b/source/blender/include/BSE_sequence.h @@ -44,9 +44,6 @@ struct Editing; struct ImBuf; struct Scene; -void open_plugin_seq(struct PluginSeq *pis, char *seqname); -struct PluginSeq *add_plugin_seq(char *str, char *seqname); -void free_plugin_seq(struct PluginSeq *pis); void free_stripdata(int len, struct StripElem *se); void free_strip(struct Strip *strip); void new_stripdata(struct Sequence *seq); @@ -58,64 +55,6 @@ void free_editing(struct Editing *ed); void calc_sequence(struct Sequence *seq); void sort_seq(void); void clear_scene_in_allseqs(struct Scene *sce); -void do_alphaover_effect(float facf0, - float facf1, - int x, int y, - unsigned int *rect1, - unsigned int *rect2, - unsigned int *out); -void do_alphaunder_effect(float facf0, float facf1, - int x, int y, - unsigned int *rect1, unsigned int *rect2, - unsigned int *out); -void do_cross_effect(float facf0, float facf1, - int x, int y, - unsigned int *rect1, unsigned int *rect2, - unsigned int *out); -void do_gammacross_effect(float facf0, float facf1, - int x, int y, - unsigned int *rect1, unsigned int *rect2, - unsigned int *out); -void do_add_effect(float facf0, float facf1, - int x, int y, - unsigned int *rect1, unsigned int *rect2, - unsigned int *out); -void do_sub_effect(float facf0, float facf1, - int x, int y, - unsigned int *rect1, unsigned int *rect2, - unsigned int *out); -void do_drop_effect(float facf0, float facf1, - int x, int y, - unsigned int *rect2i, unsigned int *rect1i, - unsigned int *outi); -void do_drop_effect2(float facf0, float facf1, - int x, int y, - unsigned int *rect2, unsigned int *rect1, - unsigned int *out); -void do_mul_effect(float facf0, float facf1, - int x, int y, - unsigned int *rect1, unsigned int *rect2, - unsigned int *out); -/* Wipe effect */ -enum {DO_SINGLE_WIPE, DO_DOUBLE_WIPE, DO_BOX_WIPE, DO_CROSS_WIPE, - DO_IRIS_WIPE,DO_CLOCK_WIPE}; -float in_band(float width,float dist, float perc,int side,int dir); -float check_zone(int x, int y, int xo, int yo, struct Sequence *seq, float facf0); -void init_wipe_effect(struct Sequence *seq); -void do_wipe_effect(struct Sequence *seq, float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out); - -/* Glow effect */ -enum { - GlowR=0, - GlowG=1, - GlowB=2, - GlowA=3 -}; -void RVBlurBitmap2( unsigned char* map, int width, int height, float blur, int quality); -void RVIsolateHighlights (unsigned char* in, unsigned char* out, int width, int height, int threshold, float boost, float clamp); -void RVAddBitmaps (unsigned char* a,unsigned char* b, unsigned char* c, int width, int height); -void init_glow_effect(struct Sequence *seq); -void do_glow_effect(struct Sequence *seq, float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out); void make_black_ibuf(struct ImBuf *ibuf); void multibuf(struct ImBuf *ibuf, float fmul); @@ -126,9 +65,6 @@ void set_meta_stripdata(struct Sequence *seqm); struct ImBuf *give_ibuf_seq(int rectx, int recty, int cfra, int chansel); /* chansel: render this channel. Default=0 (renders end result)*/ -struct ImBuf *make_waveform_view_from_ibuf(struct ImBuf * ibuf); -struct ImBuf *make_vectorscope_view_from_ibuf(struct ImBuf * ibuf); - void free_imbuf_effect_spec(int cfra); void free_imbuf_seq_except(int cfra); void free_imbuf_seq(void); diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 6115a82457f..2505c5c6838 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -126,6 +126,8 @@ typedef struct Sequence { void *effectdata; /* Struct pointer for effect settings */ + int anim_preseek; + int pad; } Sequence; typedef struct MetaStack { @@ -170,6 +172,7 @@ typedef struct GlowVars { #define SEQ_MAKE_PREMUL 64 #define SEQ_REVERSE_FRAMES 128 #define SEQ_IPO_FRAME_LOCKED 256 +#define SEQ_EFFECT_NOT_LOADED 512 /* seq->type WATCH IT: SEQ_EFFECT BIT is used to determine if this is an effect strip!!! */ #define SEQ_IMAGE 0 diff --git a/source/blender/src/drawseq.c b/source/blender/src/drawseq.c index 1712be12368..a0d3232cf2f 100644 --- a/source/blender/src/drawseq.c +++ b/source/blender/src/drawseq.c @@ -70,6 +70,8 @@ #include "BSE_view.h" #include "BSE_drawipo.h" #include "BSE_sequence.h" +#include "BSE_seqeffects.h" +#include "BSE_seqscopes.h" #include "BSE_seqaudio.h" #include "IMB_imbuf_types.h" @@ -596,8 +598,14 @@ static void draw_image_seq(ScrArea *sa) free_ibuf = 1; } - if (sseq->zoom > 0) zoom = sseq->zoom; - else zoom = -1.0/sseq->zoom; + if (sseq->zoom > 0) { + zoom = sseq->zoom; + } else if (sseq->zoom == 0) { + zoom = 1.0; + } else { + zoom = -1.0/sseq->zoom; + } + /* calc location */ x1= (sa->winx-zoom*ibuf->x)/2; y1= (sa->winy-zoom*ibuf->y)/2; @@ -809,6 +817,7 @@ static void seq_panel_properties(short cntrl) // SEQ_HANDLER_PROPERTIES uiDefButS(block, TOG|BIT|7, SEQ_BUT_RELOAD, "Reverse Frames", 10,30,150,19, &last_seq->flag, 0.0, 21.0, 100, 0, "Reverse frame order"); uiDefButF(block, NUM, SEQ_BUT_RELOAD, "Strobe:", 10,10,150,19, &last_seq->strobe, 1.0, 30.0, 100, 0, "Only display every nth frame"); + uiDefButI(block, NUM, SEQ_BUT_RELOAD, "Preseek:", 10,-10,150,19, &last_seq->anim_preseek, 0.0, 50.0, 100, 0, "On MPEG-seeking preseek this many frames"); } else if(last_seq->type==SEQ_RAM_SOUND || diff --git a/source/blender/src/editseq.c b/source/blender/src/editseq.c index 15877c226c2..a1cbcf296d7 100644 --- a/source/blender/src/editseq.c +++ b/source/blender/src/editseq.c @@ -85,6 +85,7 @@ #include "BSE_edit.h" #include "BSE_sequence.h" +#include "BSE_seqeffects.h" #include "BSE_filesel.h" #include "BSE_drawipo.h" #include "BSE_seqaudio.h" @@ -111,15 +112,18 @@ static void shuffle_seq(Sequence *); static void change_plugin_seq(char *str) /* called from fileselect */ { -/* extern Sequence *last_seq; already done few lines before !!!*/ + struct SeqEffectHandle sh; - if(last_seq && last_seq->type!=SEQ_PLUGIN) return; + if(last_seq && last_seq->type != SEQ_PLUGIN) return; - free_plugin_seq(last_seq->plugin); + sh = get_sequence_effect(last_seq); + sh.free(last_seq); + sh.init_plugin(last_seq, str); - last_seq->plugin= (PluginSeq *)add_plugin_seq(str, last_seq->name+2); + last_seq->machine = MAX3(last_seq->seq1->machine, + last_seq->seq2->machine, + last_seq->seq3->machine); - last_seq->machine= MAX3(last_seq->seq1->machine, last_seq->seq2->machine, last_seq->seq3->machine); if( test_overlap_seq(last_seq) ) shuffle_seq(last_seq); BIF_undo_push("Load/change Sequencer plugin"); @@ -404,11 +408,13 @@ void mouse_select_seq(void) if(seq->flag & SELECT) { if(hand==0) seq->flag &= SEQ_DESEL; else if(hand==1) { - if(seq->flag & SEQ_LEFTSEL) seq->flag &= ~SEQ_LEFTSEL; + if(seq->flag & SEQ_LEFTSEL) + seq->flag &= ~SEQ_LEFTSEL; else seq->flag |= SEQ_LEFTSEL; } else if(hand==2) { - if(seq->flag & SEQ_RIGHTSEL) seq->flag &= ~SEQ_RIGHTSEL; + if(seq->flag & SEQ_RIGHTSEL) + seq->flag &= ~SEQ_RIGHTSEL; else seq->flag |= SEQ_RIGHTSEL; } } @@ -553,6 +559,7 @@ static void sfile_to_mv_sequence(SpaceFile *sfile, int cfra, int machine) seq->len= totframe; seq->type= SEQ_MOVIE; seq->anim= anim; + seq->anim_preseek = IMB_anim_get_preseek(anim); calc_sequence(seq); @@ -981,6 +988,7 @@ static int add_seq_effect(int type) float x, y; int cfra, machine; short mval[2]; + struct SeqEffectHandle sh; if(G.scene->ed==0) return 0; ed= G.scene->ed; @@ -1037,23 +1045,14 @@ static int add_seq_effect(int type) seq->type= event_to_efftype(type); - /* Allocate variable structs for effects with settings */ - if(seq->type==SEQ_WIPE){ - init_wipe_effect(seq); - } - else if(seq->type==SEQ_GLOW){ - init_glow_effect(seq); - } + sh = get_sequence_effect(seq); - if(seq->type==SEQ_ALPHAUNDER || seq->type==SEQ_ALPHAOVER) { - seq->seq2= seq1; - seq->seq1= seq2; - } - else { - seq->seq1= seq1; - seq->seq2= seq2; - } + seq->seq1= seq1; + seq->seq2= seq2; seq->seq3= seq3; + + sh.init(seq); + calc_sequence(seq); seq->strip= strip= MEM_callocN(sizeof(Strip), "strip"); @@ -1069,12 +1068,12 @@ static int add_seq_effect(int type) static void load_plugin_seq(char *str) /* called from fileselect */ { Editing *ed; + struct SeqEffectHandle sh; add_seq_effect(10); /* this sets last_seq */ - free_plugin_seq(last_seq->plugin); - - last_seq->plugin= (PluginSeq *)add_plugin_seq(str, last_seq->name+2); + sh = get_sequence_effect(last_seq); + sh.init_plugin(last_seq, str); if(last_seq->plugin==0) { ed= G.scene->ed; @@ -1261,33 +1260,46 @@ void change_sequence(void) if(last_seq==0) return; if(last_seq->type & SEQ_EFFECT) { - event= pupmenu("Change Effect%t|Switch A <-> B %x1|Switch B <-> C %x10|Plugin%x11|Recalculate%x12|Cross%x2|Gamma Cross%x3|Add%x4|Sub%x5|Mul%x6|Alpha Over%x7|Alpha Under%x8|Alpha Over Drop%x9|Wipe%x13|Glow%x14"); - if(event>0) { + event = pupmenu("Change Effect%t" + "|Switch A <-> B %x1" + "|Switch B <-> C %x10" + "|Plugin%x11" + "|Recalculate%x12" + "|Cross%x2" + "|Gamma Cross%x3" + "|Add%x4" + "|Sub%x5" + "|Mul%x6" + "|Alpha Over%x7" + "|Alpha Under%x8" + "|Alpha Over Drop%x9" + "|Wipe%x13" + "|Glow%x14"); + if(event > 0) { if(event==1) { - SWAP(Sequence *, last_seq->seq1, last_seq->seq2); + SWAP(Sequence *,last_seq->seq1,last_seq->seq2); } else if(event==10) { - SWAP(Sequence *, last_seq->seq2, last_seq->seq3); + SWAP(Sequence *,last_seq->seq2,last_seq->seq3); } else if(event==11) { - activate_fileselect(FILE_SPECIAL, "Select Plugin", U.plugseqdir, change_plugin_seq); + activate_fileselect( + FILE_SPECIAL, "Select Plugin", + U.plugseqdir, change_plugin_seq); } - else if(event==12); /* recalculate: only new_stripdata */ + else if(event==12); + /* recalculate: only new_stripdata */ else { - /* to be sure, free plugin */ - free_plugin_seq(last_seq->plugin); - last_seq->plugin= 0; - last_seq->type= event_to_efftype(event); - - switch(last_seq->type){ - case SEQ_WIPE: - init_wipe_effect(last_seq); - break; - case SEQ_GLOW: - init_glow_effect(last_seq); - break; - } + /* free previous effect and init new effect */ + struct SeqEffectHandle sh; + sh = get_sequence_effect(last_seq); + sh.free(last_seq); + + last_seq->type = event_to_efftype(event); + + sh = get_sequence_effect(last_seq); + sh.init(last_seq); } new_stripdata(last_seq); allqueue(REDRAWSEQ, 0); @@ -1296,7 +1308,10 @@ void change_sequence(void) } else if(last_seq->type == SEQ_IMAGE) { if(okee("Change images")) { - activate_fileselect(FILE_SPECIAL, "Select Images", last_imagename, reload_image_strip); + activate_fileselect(FILE_SPECIAL, + "Select Images", + last_imagename, + reload_image_strip); } } else if(last_seq->type == SEQ_MOVIE) { @@ -1379,7 +1394,9 @@ void del_seq(void) while(seq) { seqn= seq->next; if(seq->type & SEQ_EFFECT) { - if( is_a_sequence(seq->seq1)==0 || is_a_sequence(seq->seq2)==0 || is_a_sequence(seq->seq3)==0 ) { + if( is_a_sequence(seq->seq1)==0 + || is_a_sequence(seq->seq2)==0 + || is_a_sequence(seq->seq3)==0 ) { BLI_remlink(ed->seqbasep, seq); if(seq==last_seq) last_seq= 0; free_sequence(seq); @@ -1436,7 +1453,7 @@ static void recurs_dupli_seq(ListBase *old, ListBase *new) seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); seqn->seqbase.first= seqn->seqbase.last= 0; - recurs_dupli_seq(&seq->seqbase, &seqn->seqbase); + recurs_dupli_seq(&seq->seqbase,&seqn->seqbase); } else if(seq->type == SEQ_SCENE) { @@ -1446,7 +1463,7 @@ static void recurs_dupli_seq(ListBase *old, ListBase *new) seqn->strip= MEM_dupallocN(seq->strip); - if(seq->len>0) seqn->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); + if(seq->len>0) seqn->strip->stripdata = MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); seq->flag &= SEQ_DESEL; seqn->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL); @@ -1548,10 +1565,12 @@ static void recurs_dupli_seq(ListBase *old, ListBase *new) if(seqn->ipo) seqn->ipo->id.us++; - if(seq->plugin) { - seqn->plugin= MEM_dupallocN(seq->plugin); - open_plugin_seq(seqn->plugin, seqn->name+2); + if (seq->type & SEQ_EFFECT) { + struct SeqEffectHandle sh; + sh = get_sequence_effect(seq); + sh.copy(seq, seqn); } + seqn->strip= MEM_dupallocN(seq->strip); if(seq->len>0) seq->strip->stripdata= MEM_callocN(seq->len*sizeof(StripElem), "stripelem"); @@ -1795,7 +1814,9 @@ void un_meta(void) while(seq) { seqn= seq->next; if(seq->type & SEQ_EFFECT) { - if( is_a_sequence(seq->seq1)==0 || is_a_sequence(seq->seq2)==0 || is_a_sequence(seq->seq3)==0 ) { + if( is_a_sequence(seq->seq1)==0 + || is_a_sequence(seq->seq2)==0 + || is_a_sequence(seq->seq3)==0 ) { BLI_remlink(ed->seqbasep, seq); if(seq==last_seq) last_seq= 0; free_sequence(seq); diff --git a/source/blender/src/hddaudio.c b/source/blender/src/hddaudio.c index a06ff0c6901..4221bd440b5 100644 --- a/source/blender/src/hddaudio.c +++ b/source/blender/src/hddaudio.c @@ -20,7 +20,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * Contributor(s): Peter Schlaile 2005 + * Contributor(s): Peter Schlaile 2005 * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -38,6 +38,7 @@ #ifdef WITH_FFMPEG #include #include +#include #if LIBAVFORMAT_VERSION_INT < (49 << 16) #define FFMPEG_OLD_FRAME_RATE 1 #else @@ -65,8 +66,12 @@ struct hdaudio { AVCodecContext *pCodecCtx; int frame_position; int frame_duration; + int frame_alloc_duration; + int decode_pos; int frame_size; short * decode_cache; + short * decode_cache_zero; + short * resample_cache; int decode_cache_size; int target_channels; int target_rate; @@ -77,6 +82,20 @@ struct hdaudio { #endif }; +#ifdef WITH_FFMPEG +#ifdef FFMPEG_CODEC_IS_POINTER +static AVCodecContext* get_codec_from_stream(AVStream* stream) +{ + return stream->codec; +} +#else +static AVCodecContext* get_codec_from_stream(AVStream* stream) +{ + return &stream->codec; +} +#endif +#endif + struct hdaudio * sound_open_hdaudio(char * filename) { #ifdef WITH_FFMPEG @@ -104,11 +123,8 @@ struct hdaudio * sound_open_hdaudio(char * filename) /* Find the first audio stream */ audioStream=-1; for(i=0; inb_streams; i++) -#ifdef FFMPEG_CODEC_IS_POINTER - if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO) -#else - if(pFormatCtx->streams[i]->codec.codec_type==CODEC_TYPE_AUDIO) -#endif + if(get_codec_from_stream(pFormatCtx->streams[i]) + ->codec_type == CODEC_TYPE_AUDIO) { audioStream=i; break; @@ -119,11 +135,7 @@ struct hdaudio * sound_open_hdaudio(char * filename) return 0; } -#ifdef FFMPEG_CODEC_IS_POINTER - pCodecCtx=pFormatCtx->streams[audioStream]->codec; -#else - pCodecCtx=&pFormatCtx->streams[audioStream]->codec; -#endif + pCodecCtx = get_codec_from_stream(pFormatCtx->streams[audioStream]); /* Find the decoder for the audio stream */ pCodec = avcodec_find_decoder(pCodecCtx->codec_id); @@ -133,11 +145,6 @@ struct hdaudio * sound_open_hdaudio(char * filename) return 0; } -#if 0 - if(pCodec->capabilities & CODEC_CAP_TRUNCATED) - pCodecCtx->flags|=CODEC_FLAG_TRUNCATED; -#endif - if(avcodec_open(pCodecCtx, pCodec)<0) { avcodec_close(pCodecCtx); av_close_input_file(pFormatCtx); @@ -155,22 +162,23 @@ struct hdaudio * sound_open_hdaudio(char * filename) rval->pCodecCtx = pCodecCtx; rval->pCodec = pCodec; rval->audioStream = audioStream; - rval->frame_position = -1; + rval->frame_position = -10; - /* FIXME: This only works with integer frame rates ... */ - rval->frame_duration = AV_TIME_BASE; + rval->frame_duration = AV_TIME_BASE / 10; + rval->frame_alloc_duration = AV_TIME_BASE; rval->decode_cache_size = (long long) rval->sample_rate * rval->channels - * rval->frame_duration / AV_TIME_BASE + * rval->frame_alloc_duration / AV_TIME_BASE * 2; rval->decode_cache = (short*) MEM_mallocN( rval->decode_cache_size * sizeof(short), "hdaudio decode cache"); - + rval->decode_pos = 0; rval->target_channels = -1; rval->target_rate = -1; rval->resampler = 0; + rval->resample_cache = 0; return rval; #else return 0; @@ -195,21 +203,27 @@ long sound_hdaudio_get_duration(struct hdaudio * hdaudio, int frame_rate) #endif } -void sound_hdaudio_extract(struct hdaudio * hdaudio, - short * target_buffer, - int sample_position /* units of target_rate */, - int target_rate, - int target_channels, - int nb_samples /* in target */) -{ #ifdef WITH_FFMPEG +static void sound_hdaudio_extract_small_block( + struct hdaudio * hdaudio, + short * target_buffer, + int sample_position /* units of target_rate */, + int target_rate, + int target_channels, + int nb_samples /* in target */) +{ AVPacket packet; int frame_position; int frame_size = (long long) target_rate * hdaudio->frame_duration / AV_TIME_BASE; + int in_frame_size = (long long) hdaudio->sample_rate + * hdaudio->frame_duration / AV_TIME_BASE; int rate_conversion = (target_rate != hdaudio->sample_rate) || (target_channels != hdaudio->channels); + int sample_ofs = target_channels * (sample_position % frame_size); + + frame_position = sample_position / frame_size; if (hdaudio == 0) return; @@ -226,94 +240,261 @@ void sound_hdaudio_extract(struct hdaudio * hdaudio, target_rate, hdaudio->sample_rate); hdaudio->target_rate = target_rate; hdaudio->target_channels = target_channels; + if (hdaudio->resample_cache) { + MEM_freeN(hdaudio->resample_cache); + } + + + hdaudio->resample_cache = (short*) MEM_mallocN( + (long long) + hdaudio->target_channels + * frame_size * 2 + * sizeof(short), + "hdaudio resample cache"); + + if (frame_position == hdaudio->frame_position) { + audio_resample(hdaudio->resampler, + hdaudio->resample_cache, + hdaudio->decode_cache_zero, + in_frame_size * 7 / 4); + } } } - frame_position = sample_position / frame_size; + if (frame_position == hdaudio->frame_position + 1 + && in_frame_size * hdaudio->channels <= hdaudio->decode_pos) { + int bl_size = in_frame_size * hdaudio->channels; + int decode_pos = hdaudio->decode_pos; + + hdaudio->frame_position = frame_position; + + memcpy(hdaudio->decode_cache, + hdaudio->decode_cache + bl_size, + (decode_pos - bl_size) * sizeof(short)); + + decode_pos -= bl_size; + + while(av_read_frame(hdaudio->pFormatCtx, &packet) >= 0) { + int data_size; + int len; + uint8_t *audio_pkt_data; + int audio_pkt_size; + + if(packet.stream_index != hdaudio->audioStream) { + av_free_packet(&packet); + continue; + } + + audio_pkt_data = packet.data; + audio_pkt_size = packet.size; + + while (audio_pkt_size > 0) { + len = avcodec_decode_audio( + hdaudio->pCodecCtx, + hdaudio->decode_cache + + decode_pos, + &data_size, + audio_pkt_data, + audio_pkt_size); + if (data_size <= 0) { + continue; + } + if (len < 0) { + audio_pkt_size = 0; + break; + } + + audio_pkt_size -= len; + audio_pkt_data += len; + + decode_pos += data_size / sizeof(short); + if (decode_pos + data_size + / sizeof(short) + > hdaudio->decode_cache_size) { + break; + } + } + av_free_packet(&packet); + + if (decode_pos + data_size / sizeof(short) + > hdaudio->decode_cache_size) { + break; + } + } + + if (rate_conversion) { + audio_resample(hdaudio->resampler, + hdaudio->resample_cache, + hdaudio->decode_cache_zero, + in_frame_size * 7 / 4); + } + + hdaudio->decode_pos = decode_pos; + } if (frame_position != hdaudio->frame_position) { long decode_pos = 0; + long long st_time = hdaudio->pFormatCtx + ->streams[hdaudio->audioStream]->start_time; + double time_base = + av_q2d(hdaudio->pFormatCtx + ->streams[hdaudio->audioStream]->time_base); + long long pos = frame_position * AV_TIME_BASE + * hdaudio->frame_duration / AV_TIME_BASE; hdaudio->frame_position = frame_position; + if (st_time == AV_NOPTS_VALUE) { + st_time = 0; + } + + pos += st_time * AV_TIME_BASE * time_base; + av_seek_frame(hdaudio->pFormatCtx, -1, - (long long) frame_position * AV_TIME_BASE, + pos, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD); + avcodec_flush_buffers(hdaudio->pCodecCtx); + + hdaudio->decode_cache_zero = 0; while(av_read_frame(hdaudio->pFormatCtx, &packet) >= 0) { - if(packet.stream_index == hdaudio->audioStream) { - int data_size; - int len; - uint8_t *audio_pkt_data; - int audio_pkt_size; - - audio_pkt_data = packet.data; - audio_pkt_size = packet.size; - - while (audio_pkt_size > 0) { - len = avcodec_decode_audio( - hdaudio->pCodecCtx, - hdaudio->decode_cache - + decode_pos, - &data_size, - audio_pkt_data, - audio_pkt_size); - if (data_size <= 0) { - continue; - } - if (len < 0) { - audio_pkt_size = 0; - break; + int data_size; + int len; + uint8_t *audio_pkt_data; + int audio_pkt_size; + + if(packet.stream_index != hdaudio->audioStream) { + av_free_packet(&packet); + continue; + } + + audio_pkt_data = packet.data; + audio_pkt_size = packet.size; + + if (!hdaudio->decode_cache_zero + && audio_pkt_size > 0) { + long long diff; + + if (packet.pts == AV_NOPTS_VALUE) { + fprintf(stderr, + "hdaudio: audio " + "pts=NULL audio " + "distortion!\n"); + diff = 0; + } else { + long long pts = packet.pts; + long long spts = (long long) ( + pos / time_base / AV_TIME_BASE + + 0.5); + diff = spts - pts; + if (diff < 0) { + fprintf(stderr, + "hdaudio: " + "negative seek: " + "%lld < %lld " + "audio distortion!!\n", + spts, pts); + diff = 0; } + } - audio_pkt_size -= len; - audio_pkt_data += len; - decode_pos += - data_size / sizeof(short); - if (decode_pos + data_size - / sizeof(short) - > hdaudio->decode_cache_size) { - av_free_packet(&packet); - break; - } + diff *= hdaudio->sample_rate * time_base; + diff *= hdaudio->channels; + + if (diff > hdaudio->decode_cache_size / 2) { + fprintf(stderr, + "hdaudio: audio " + "diff too large!!\n"); + diff = 0; + } + + hdaudio->decode_cache_zero + = hdaudio->decode_cache + diff; + } + + while (audio_pkt_size > 0) { + len = avcodec_decode_audio( + hdaudio->pCodecCtx, + hdaudio->decode_cache + + decode_pos, + &data_size, + audio_pkt_data, + audio_pkt_size); + if (data_size <= 0) { + continue; } - if (decode_pos + data_size / sizeof(short) + if (len < 0) { + audio_pkt_size = 0; + break; + } + + audio_pkt_size -= len; + audio_pkt_data += len; + + decode_pos += data_size / sizeof(short); + if (decode_pos + data_size + / sizeof(short) > hdaudio->decode_cache_size) { break; } } + av_free_packet(&packet); + + if (decode_pos + data_size / sizeof(short) + > hdaudio->decode_cache_size) { + break; + } + } + if (rate_conversion) { + audio_resample(hdaudio->resampler, + hdaudio->resample_cache, + hdaudio->decode_cache_zero, + in_frame_size * 7 / 4); } + hdaudio->decode_pos = decode_pos; } - if (!rate_conversion) { - int ofs = target_channels * (sample_position % frame_size); - memcpy(target_buffer, - hdaudio->decode_cache + ofs, - nb_samples * target_channels * sizeof(short)); - } else { - double ratio = (double) hdaudio->sample_rate / target_rate; - long in_samples = (long) ((nb_samples + 16) * ratio); - short temp_buffer[target_channels * (nb_samples + 64)]; - - int s = audio_resample(hdaudio->resampler, - temp_buffer, - hdaudio->decode_cache - + target_channels * - (long) - (ratio*(sample_position % frame_size)), - in_samples); - if (s < nb_samples || s > nb_samples + 63) { - fprintf(stderr, "resample ouch: %d != %d\n", - s, nb_samples); - } - memcpy(target_buffer, temp_buffer, - nb_samples * target_channels * sizeof(short)); + memcpy(target_buffer, (rate_conversion + ? hdaudio->resample_cache + : hdaudio->decode_cache_zero) + sample_ofs, + nb_samples * target_channels * sizeof(short)); +} +#endif + + +void sound_hdaudio_extract(struct hdaudio * hdaudio, + short * target_buffer, + int sample_position /* units of target_rate */, + int target_rate, + int target_channels, + int nb_samples /* in target */) +{ +#ifdef WITH_FFMPEG + long long max_samples = (long long) target_rate + * hdaudio->frame_duration / AV_TIME_BASE / 4; + + while (nb_samples > max_samples) { + sound_hdaudio_extract_small_block(hdaudio, target_buffer, + sample_position, + target_rate, + target_channels, + max_samples); + target_buffer += max_samples * target_channels; + sample_position += max_samples; + nb_samples -= max_samples; + } + if (nb_samples > 0) { + sound_hdaudio_extract_small_block(hdaudio, target_buffer, + sample_position, + target_rate, + target_channels, + nb_samples); } #else -#endif +#endif } void sound_close_hdaudio(struct hdaudio * hdaudio) @@ -324,6 +505,9 @@ void sound_close_hdaudio(struct hdaudio * hdaudio) avcodec_close(hdaudio->pCodecCtx); av_close_input_file(hdaudio->pFormatCtx); MEM_freeN (hdaudio->decode_cache); + if (hdaudio->resample_cache) { + MEM_freeN(hdaudio->resample_cache); + } free(hdaudio->filename); MEM_freeN (hdaudio); } diff --git a/source/blender/src/seqeffects.c b/source/blender/src/seqeffects.c new file mode 100644 index 00000000000..d1d04a7eb96 --- /dev/null +++ b/source/blender/src/seqeffects.c @@ -0,0 +1,2515 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): Peter Schlaile 2005/2006 + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include +#include +#include + +#include "MEM_guardedalloc.h" +#include "PIL_dynlib.h" +#include "BKE_plugin_types.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#include "DNA_sequence_types.h" +#include "BSE_seqeffects.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "DNA_sequence_types.h" + +#include "BKE_utildefines.h" +#include "BKE_global.h" +#include "BKE_ipo.h" +#include "BKE_texture.h" +#include "BIF_toolbox.h" +#include "BIF_interface.h" + +#include "BSE_sequence.h" + +#include "RE_pipeline.h" // talks to entire render API + +#include "blendef.h" + +/* Glow effect */ +enum { + GlowR=0, + GlowG=1, + GlowB=2, + GlowA=3 +}; + + +/* ********************************************************************** + PLUGINS + ********************************************************************** */ + +static void open_plugin_seq(PluginSeq *pis, const char *seqname) +{ + int (*version)(); + void* (*alloc_private)(); + char *cp; + + /* to be sure: (is tested for) */ + pis->doit= 0; + pis->pname= 0; + pis->varstr= 0; + pis->cfra= 0; + pis->version= 0; + pis->instance_private_data = 0; + + /* clear the error list */ + PIL_dynlib_get_error_as_string(NULL); + + /* if(pis->handle) PIL_dynlib_close(pis->handle); */ + /* pis->handle= 0; */ + + /* open the needed object */ + pis->handle= PIL_dynlib_open(pis->name); + if(test_dlerr(pis->name, pis->name)) return; + + if (pis->handle != 0) { + /* find the address of the version function */ + version= (int (*)())PIL_dynlib_find_symbol(pis->handle, "plugin_seq_getversion"); + if (test_dlerr(pis->name, "plugin_seq_getversion")) return; + + if (version != 0) { + pis->version= version(); + if (pis->version==2 || pis->version==3) { + int (*info_func)(PluginInfo *); + PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info");; + + info_func= (int (*)(PluginInfo *))PIL_dynlib_find_symbol(pis->handle, "plugin_getinfo"); + + if(info_func == NULL) error("No info func"); + else { + info_func(info); + + pis->pname= info->name; + pis->vars= info->nvars; + pis->cfra= info->cfra; + + pis->varstr= info->varstr; + + pis->doit= (void(*)(void))info->seq_doit; + if (info->init) + info->init(); + } + MEM_freeN(info); + + cp= PIL_dynlib_find_symbol(pis->handle, "seqname"); + if(cp) strncpy(cp, seqname, 21); + } else { + printf ("Plugin returned unrecognized version number\n"); + return; + } + } + alloc_private = (void* (*)())PIL_dynlib_find_symbol( + pis->handle, "plugin_seq_alloc_private_data"); + if (alloc_private) { + pis->instance_private_data = alloc_private(); + } + + pis->current_private_data = (void**) + PIL_dynlib_find_symbol( + pis->handle, "plugin_private_data"); + } +} + +static PluginSeq *add_plugin_seq(const char *str, const char *seqname) +{ + PluginSeq *pis; + VarStruct *varstr; + int a; + + pis= MEM_callocN(sizeof(PluginSeq), "PluginSeq"); + + strncpy(pis->name, str, FILE_MAXDIR+FILE_MAXFILE); + open_plugin_seq(pis, seqname); + + if(pis->doit==0) { + if(pis->handle==0) error("no plugin: %s", str); + else error("in plugin: %s", str); + MEM_freeN(pis); + return 0; + } + + /* default values */ + varstr= pis->varstr; + for(a=0; avars; a++, varstr++) { + if( (varstr->type & FLO)==FLO) + pis->data[a]= varstr->def; + else if( (varstr->type & INT)==INT) + *((int *)(pis->data+a))= (int) varstr->def; + } + + return pis; +} + +static void free_plugin_seq(PluginSeq *pis) +{ + if(pis==0) return; + + /* no PIL_dynlib_close: same plugin can be opened multiple times with 1 handle */ + + if (pis->instance_private_data) { + void (*free_private)(void *); + + free_private = (void (*)(void *))PIL_dynlib_find_symbol( + pis->handle, "plugin_seq_free_private_data"); + if (free_private) { + free_private(pis->instance_private_data); + } + } + + MEM_freeN(pis); +} + +static void init_plugin(Sequence * seq, const char * fname) +{ + seq->plugin= (PluginSeq *)add_plugin_seq(fname, seq->name+2); +} + +static void load_plugin(Sequence * seq) +{ + if (seq) { + open_plugin_seq(seq->plugin, seq->name+2); + } +} + +static void copy_plugin(Sequence * dst, Sequence * src) +{ + if(src->plugin) { + dst->plugin= MEM_dupallocN(src->plugin); + open_plugin_seq(dst->plugin, dst->name+2); + } +} + +static void do_plugin_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + char *cp; + + if(seq->plugin && seq->plugin->doit) { + if(seq->plugin->cfra) + *(seq->plugin->cfra)= frame_to_float(cfra); + + cp = PIL_dynlib_find_symbol( + seq->plugin->handle, "seqname"); + + if(cp) strncpy(cp, seq->name+2, 22); + + if (seq->plugin->current_private_data) { + *seq->plugin->current_private_data + = seq->plugin->instance_private_data; + } + + if (seq->plugin->version<=2) { + if(ibuf1) IMB_convert_rgba_to_abgr(ibuf1); + if(ibuf2) IMB_convert_rgba_to_abgr(ibuf2); + if(ibuf3) IMB_convert_rgba_to_abgr(ibuf3); + } + + ((SeqDoit)seq->plugin->doit)( + seq->plugin->data, facf0, facf1, x, y, + ibuf1, ibuf2, out, ibuf3); + + if (seq->plugin->version<=2) { + if(ibuf1) IMB_convert_rgba_to_abgr(ibuf1); + if(ibuf2) IMB_convert_rgba_to_abgr(ibuf2); + if(ibuf3) IMB_convert_rgba_to_abgr(ibuf3); + IMB_convert_rgba_to_abgr(out); + } + } +} + +static int do_plugin_early_out(struct Sequence *seq, + float facf0, float facf1) +{ + return 0; +} + +static void free_plugin(struct Sequence * seq) +{ + free_plugin_seq(seq->plugin); + seq->plugin = 0; +} + +/* ********************************************************************** + ALPHA OVER + ********************************************************************** */ + +static void init_alpha_over_or_under(Sequence * seq) +{ + Sequence * seq1 = seq->seq1; + Sequence * seq2 = seq->seq2; + + seq->seq2= seq1; + seq->seq1= seq2; +} + +static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y, + char * rect1, char *rect2, char *out) +{ + int fac2, mfac, fac, fac4; + int xo, tempc; + char *rt1, *rt2, *rt; + + xo= x; + rt1= (char *)rect1; + rt2= (char *)rect2; + rt= (char *)out; + + fac2= (int)(256.0*facf0); + fac4= (int)(256.0*facf1); + + while(y--) { + + x= xo; + while(x--) { + + /* rt = rt1 over rt2 (alpha from rt1) */ + + fac= fac2; + mfac= 256 - ( (fac2*rt1[3])>>8 ); + + if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2); + else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1); + else { + tempc= ( fac*rt1[0] + mfac*rt2[0])>>8; + if(tempc>255) rt[0]= 255; else rt[0]= tempc; + tempc= ( fac*rt1[1] + mfac*rt2[1])>>8; + if(tempc>255) rt[1]= 255; else rt[1]= tempc; + tempc= ( fac*rt1[2] + mfac*rt2[2])>>8; + if(tempc>255) rt[2]= 255; else rt[2]= tempc; + tempc= ( fac*rt1[3] + mfac*rt2[3])>>8; + if(tempc>255) rt[3]= 255; else rt[3]= tempc; + } + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + fac= fac4; + mfac= 256 - ( (fac4*rt1[3])>>8 ); + + if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2); + else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1); + else { + tempc= ( fac*rt1[0] + mfac*rt2[0])>>8; + if(tempc>255) rt[0]= 255; else rt[0]= tempc; + tempc= ( fac*rt1[1] + mfac*rt2[1])>>8; + if(tempc>255) rt[1]= 255; else rt[1]= tempc; + tempc= ( fac*rt1[2] + mfac*rt2[2])>>8; + if(tempc>255) rt[2]= 255; else rt[2]= tempc; + tempc= ( fac*rt1[3] + mfac*rt2[3])>>8; + if(tempc>255) rt[3]= 255; else rt[3]= tempc; + } + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + +static void do_alphaover_effect_float(float facf0, float facf1, int x, int y, + float * rect1, float *rect2, float *out) +{ + float fac2, mfac, fac, fac4; + int xo; + float *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac2= facf0; + fac4= facf1; + + while(y--) { + + x= xo; + while(x--) { + + /* rt = rt1 over rt2 (alpha from rt1) */ + + fac= fac2; + mfac= 1.0 - (fac2*rt1[3]) ; + + if(fac <= 0.0) { + memcpy(rt, rt2, 4 * sizeof(float)); + } else if(mfac <=0) { + memcpy(rt, rt1, 4 * sizeof(float)); + } else { + rt[0] = fac*rt1[0] + mfac*rt2[0]; + rt[1] = fac*rt1[1] + mfac*rt2[1]; + rt[2] = fac*rt1[2] + mfac*rt2[2]; + rt[3] = fac*rt1[3] + mfac*rt2[3]; + } + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + fac= fac4; + mfac= 1.0 - (fac4*rt1[3]); + + if(fac <= 0.0) { + memcpy(rt, rt2, 4 * sizeof(float)); + } else if(mfac <= 0.0) { + memcpy(rt, rt1, 4 * sizeof(float)); + } else { + rt[0] = fac*rt1[0] + mfac*rt2[0]; + rt[1] = fac*rt1[1] + mfac*rt2[1]; + rt[2] = fac*rt1[2] + mfac*rt2[2]; + rt[3] = fac*rt1[3] + mfac*rt2[3]; + } + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + +static void do_alphaover_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_alphaover_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_alphaover_effect_byte( + facf0, facf1, x, y, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); + } +} + + +/* ********************************************************************** + ALPHA UNDER + ********************************************************************** */ + +void do_alphaunder_effect_byte( + float facf0, float facf1, int x, int y, char *rect1, + char *rect2, char *out) +{ + int fac2, mfac, fac, fac4; + int xo; + char *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac2= (int)(256.0*facf0); + fac4= (int)(256.0*facf1); + + while(y--) { + + x= xo; + while(x--) { + + /* rt = rt1 under rt2 (alpha from rt2) */ + + /* this complex optimalisation is because the + * 'skybuf' can be crossed in + */ + if(rt2[3]==0 && fac2==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1); + else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2); + else { + mfac= rt2[3]; + fac= (fac2*(256-mfac))>>8; + + if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2); + else { + rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8; + rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8; + rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8; + rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8; + } + } + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + if(rt2[3]==0 && fac4==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1); + else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2); + else { + mfac= rt2[3]; + fac= (fac4*(256-mfac))>>8; + + if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2); + else { + rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8; + rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8; + rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8; + rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8; + } + } + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + + +static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y, + float *rect1, float *rect2, + float *out) +{ + float fac2, mfac, fac, fac4; + int xo; + float *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac2= facf0; + fac4= facf1; + + while(y--) { + + x= xo; + while(x--) { + + /* rt = rt1 under rt2 (alpha from rt2) */ + + /* this complex optimalisation is because the + * 'skybuf' can be crossed in + */ + if( rt2[3]<=0 && fac2>=1.0) { + memcpy(rt, rt1, 4 * sizeof(float)); + } else if(rt2[3]>=1.0) { + memcpy(rt, rt2, 4 * sizeof(float)); + } else { + mfac = rt2[3]; + fac = fac2 * (1.0 - mfac); + + if(fac == 0) { + memcpy(rt, rt2, 4 * sizeof(float)); + } else { + rt[0]= fac*rt1[0] + mfac*rt2[0]; + rt[1]= fac*rt1[1] + mfac*rt2[1]; + rt[2]= fac*rt1[2] + mfac*rt2[2]; + rt[3]= fac*rt1[3] + mfac*rt2[3]; + } + } + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + if(rt2[3]<=0 && fac4 >= 1.0) { + memcpy(rt, rt1, 4 * sizeof(float)); + + } else if(rt2[3]>=1.0) { + memcpy(rt, rt2, 4 * sizeof(float)); + } else { + mfac= rt2[3]; + fac= fac4*(1.0-mfac); + + if(fac == 0) { + memcpy(rt, rt2, 4 * sizeof(float)); + } else { + rt[0]= fac * rt1[0] + mfac * rt2[0]; + rt[1]= fac * rt1[1] + mfac * rt2[1]; + rt[2]= fac * rt1[2] + mfac * rt2[2]; + rt[3]= fac * rt1[3] + mfac * rt2[3]; + } + } + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + +static void do_alphaunder_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_alphaunder_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_alphaunder_effect_byte( + facf0, facf1, x, y, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); + } +} + + +/* ********************************************************************** + CROSS + ********************************************************************** */ + +void do_cross_effect_byte(float facf0, float facf1, int x, int y, + char *rect1, char *rect2, + char *out) +{ + int fac1, fac2, fac3, fac4; + int xo; + char *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac2= (int)(256.0*facf0); + fac1= 256-fac2; + fac4= (int)(256.0*facf1); + fac3= 256-fac4; + + while(y--) { + + x= xo; + while(x--) { + + rt[0]= (fac1*rt1[0] + fac2*rt2[0])>>8; + rt[1]= (fac1*rt1[1] + fac2*rt2[1])>>8; + rt[2]= (fac1*rt1[2] + fac2*rt2[2])>>8; + rt[3]= (fac1*rt1[3] + fac2*rt2[3])>>8; + + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + rt[0]= (fac3*rt1[0] + fac4*rt2[0])>>8; + rt[1]= (fac3*rt1[1] + fac4*rt2[1])>>8; + rt[2]= (fac3*rt1[2] + fac4*rt2[2])>>8; + rt[3]= (fac3*rt1[3] + fac4*rt2[3])>>8; + + rt1+= 4; rt2+= 4; rt+= 4; + } + + } +} + +void do_cross_effect_float(float facf0, float facf1, int x, int y, + float*rect1, float *rect2, float *out) +{ + int fac1, fac2, fac3, fac4; + int xo; + float *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac2= facf0; + fac1= 1.0 - fac2; + fac4= facf1; + fac3= 1.0 - fac4; + + while(y--) { + + x= xo; + while(x--) { + + rt[0]= fac1*rt1[0] + fac2*rt2[0]; + rt[1]= fac1*rt1[1] + fac2*rt2[1]; + rt[2]= fac1*rt1[2] + fac2*rt2[2]; + rt[3]= fac1*rt1[3] + fac2*rt2[3]; + + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + rt[0]= fac3*rt1[0] + fac4*rt2[0]; + rt[1]= fac3*rt1[1] + fac4*rt2[1]; + rt[2]= fac3*rt1[2] + fac4*rt2[2]; + rt[3]= fac3*rt1[3] + fac4*rt2[3]; + + rt1+= 4; rt2+= 4; rt+= 4; + } + + } +} + +static void do_cross_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_cross_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_cross_effect_byte( + facf0, facf1, x, y, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); + } +} + + +/* ********************************************************************** + GAMMA CROSS + ********************************************************************** */ + +/* copied code from initrender.c */ +static unsigned short *gamtab = 0; +static unsigned short *igamtab1 = 0; +static int gamma_tabs_refcount = 0; + +#define RE_GAMMA_TABLE_SIZE 400 + +static float gamma_range_table[RE_GAMMA_TABLE_SIZE + 1]; +static float gamfactor_table[RE_GAMMA_TABLE_SIZE]; +static float inv_gamma_range_table[RE_GAMMA_TABLE_SIZE + 1]; +static float inv_gamfactor_table[RE_GAMMA_TABLE_SIZE]; +static float colour_domain_table[RE_GAMMA_TABLE_SIZE + 1]; +static float colour_step; +static float inv_colour_step; +static float valid_gamma; +static float valid_inv_gamma; + +static void makeGammaTables(float gamma) +{ + /* we need two tables: one forward, one backward */ + int i; + + valid_gamma = gamma; + valid_inv_gamma = 1.0 / gamma; + colour_step = 1.0 / RE_GAMMA_TABLE_SIZE; + inv_colour_step = (float) RE_GAMMA_TABLE_SIZE; + + /* We could squeeze out the two range tables to gain some memory. */ + for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) { + colour_domain_table[i] = i * colour_step; + gamma_range_table[i] = pow(colour_domain_table[i], + valid_gamma); + inv_gamma_range_table[i] = pow(colour_domain_table[i], + valid_inv_gamma); + } + + /* The end of the table should match 1.0 carefully. In order to avoid */ + /* rounding errors, we just set this explicitly. The last segment may */ + /* have a different lenght than the other segments, but our */ + /* interpolation is insensitive to that. */ + colour_domain_table[RE_GAMMA_TABLE_SIZE] = 1.0; + gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0; + inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0; + + /* To speed up calculations, we make these calc factor tables. They are */ + /* multiplication factors used in scaling the interpolation. */ + for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++ ) { + gamfactor_table[i] = inv_colour_step + * (gamma_range_table[i + 1] - gamma_range_table[i]) ; + inv_gamfactor_table[i] = inv_colour_step + * (inv_gamma_range_table[i + 1] - inv_gamma_range_table[i]) ; + } + +} /* end of void makeGammaTables(float gamma) */ + + +static float gammaCorrect(float c) +{ + int i; + float res = 0.0; + + i = floor(c * inv_colour_step); + /* Clip to range [0,1]: outside, just do the complete calculation. */ + /* We may have some performance problems here. Stretching up the LUT */ + /* may help solve that, by exchanging LUT size for the interpolation. */ + /* Negative colours are explicitly handled. */ + if (i < 0) res = -pow(abs(c), valid_gamma); + else if (i >= RE_GAMMA_TABLE_SIZE ) res = pow(c, valid_gamma); + else res = gamma_range_table[i] + + ( (c - colour_domain_table[i]) * gamfactor_table[i]); + + return res; +} /* end of float gammaCorrect(float col) */ + +/* ------------------------------------------------------------------------- */ + +static float invGammaCorrect(float col) +{ + int i; + float res = 0.0; + + i = floor(col*inv_colour_step); + /* Negative colours are explicitly handled. */ + if (i < 0) res = -pow(abs(col), valid_inv_gamma); + else if (i >= RE_GAMMA_TABLE_SIZE) res = pow(col, valid_inv_gamma); + else res = inv_gamma_range_table[i] + + ( (col - colour_domain_table[i]) * inv_gamfactor_table[i]); + + return res; +} /* end of float invGammaCorrect(float col) */ + + +static void gamtabs(float gamma) +{ + float val, igamma= 1.0f/gamma; + int a; + + gamtab= MEM_mallocN(65536*sizeof(short), "initGaus2"); + igamtab1= MEM_mallocN(256*sizeof(short), "initGaus2"); + + /* gamtab: in short, out short */ + for(a=0; a<65536; a++) { + val= a; + val/= 65535.0; + + if(gamma==2.0) val= sqrt(val); + else if(gamma!=1.0) val= pow(val, igamma); + + gamtab[a]= (65535.99*val); + } + /* inverse gamtab1 : in byte, out short */ + for(a=1; a<=256; a++) { + if(gamma==2.0) igamtab1[a-1]= a*a-1; + else if(gamma==1.0) igamtab1[a-1]= 256*a-1; + else { + val= a/256.0; + igamtab1[a-1]= (65535.0*pow(val, gamma)) -1 ; + } + } + +} + +static void alloc_or_ref_gammatabs() +{ + if (gamma_tabs_refcount == 0) { + gamtabs(2.0f); + makeGammaTables(2.0f); + } + gamma_tabs_refcount++; +} + +static void init_gammacross(Sequence * seq) +{ + alloc_or_ref_gammatabs(); +} + +static void load_gammacross(Sequence * seq) +{ + alloc_or_ref_gammatabs(); +} + +static void free_gammacross(Sequence * seq) +{ + if (--gamma_tabs_refcount == 0) { + MEM_freeN(gamtab); + MEM_freeN(igamtab1); + gamtab = 0; + igamtab1 = 0; + } + if (gamma_tabs_refcount < 0) { + fprintf(stderr, "seqeffects: free_gammacross double free!\n"); + } +} + +static void do_gammacross_effect_byte(float facf0, float facf1, + int x, int y, + char *rect1, + char *rect2, + char *out) +{ + int fac1, fac2, col; + int xo; + char *rt1, *rt2, *rt; + + xo= x; + rt1= (char *)rect1; + rt2= (char *)rect2; + rt= (char *)out; + + fac2= (int)(256.0*facf0); + fac1= 256-fac2; + + while(y--) { + + x= xo; + while(x--) { + + col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8; + if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + col=(fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8; + if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8; + if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8; + if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8; + if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + col= (fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8; + if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8; + if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8; + if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; + + rt1+= 4; rt2+= 4; rt+= 4; + } + } + +} + +static void do_gammacross_effect_float(float facf0, float facf1, + int x, int y, + float *rect1, float *rect2, + float *out) +{ + float fac1, fac2, col; + int xo; + float *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac2= facf0; + fac1= 1.0 - fac2; + + while(y--) { + + x= xo * 4; + while(x--) { + + *rt= gammaCorrect( + fac1 * invGammaCorrect(*rt1) + + fac2 * invGammaCorrect(*rt2)); + rt1++; rt2++; rt++; + } + + if(y==0) break; + y--; + + x= xo * 4; + while(x--) { + + col= gammaCorrect( + fac1*invGammaCorrect(*rt1) + + fac2*invGammaCorrect(*rt2)); + + rt1++; rt2++; rt++; + } + } +} + +static void do_gammacross_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_gammacross_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_gammacross_effect_byte( + facf0, facf1, x, y, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); + } +} + + +/* ********************************************************************** + ADD + ********************************************************************** */ + +static void do_add_effect_byte(float facf0, float facf1, int x, int y, + unsigned char *rect1, unsigned char *rect2, + unsigned char *out) +{ + int col, xo, fac1, fac3; + char *rt1, *rt2, *rt; + + xo= x; + rt1= (char *)rect1; + rt2= (char *)rect2; + rt= (char *)out; + + fac1= (int)(256.0*facf0); + fac3= (int)(256.0*facf1); + + while(y--) { + + x= xo; + while(x--) { + + col= rt1[0]+ ((fac1*rt2[0])>>8); + if(col>255) rt[0]= 255; else rt[0]= col; + col= rt1[1]+ ((fac1*rt2[1])>>8); + if(col>255) rt[1]= 255; else rt[1]= col; + col= rt1[2]+ ((fac1*rt2[2])>>8); + if(col>255) rt[2]= 255; else rt[2]= col; + col= rt1[3]+ ((fac1*rt2[3])>>8); + if(col>255) rt[3]= 255; else rt[3]= col; + + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + col= rt1[0]+ ((fac3*rt2[0])>>8); + if(col>255) rt[0]= 255; else rt[0]= col; + col= rt1[1]+ ((fac3*rt2[1])>>8); + if(col>255) rt[1]= 255; else rt[1]= col; + col= rt1[2]+ ((fac3*rt2[2])>>8); + if(col>255) rt[2]= 255; else rt[2]= col; + col= rt1[3]+ ((fac3*rt2[3])>>8); + if(col>255) rt[3]= 255; else rt[3]= col; + + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + +static void do_add_effect_float(float facf0, float facf1, int x, int y, + float *rect1, float *rect2, + float *out) +{ + int xo; + float fac1, fac3; + float *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac1= facf0; + fac3= facf1; + + while(y--) { + + x= xo * 4; + while(x--) { + *rt = *rt1 + fac1 * (*rt2); + + rt1++; rt2++; rt++; + } + + if(y==0) break; + y--; + + x= xo * 4; + while(x--) { + *rt = *rt1 + fac3 * (*rt2); + + rt1++; rt2++; rt++; + } + } +} + +static void do_add_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_add_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_add_effect_byte( + facf0, facf1, x, y, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); + } +} + + +/* ********************************************************************** + SUB + ********************************************************************** */ + +static void do_sub_effect_byte(float facf0, float facf1, + int x, int y, + char *rect1, char *rect2, char *out) +{ + int col, xo, fac1, fac3; + char *rt1, *rt2, *rt; + + xo= x; + rt1= (char *)rect1; + rt2= (char *)rect2; + rt= (char *)out; + + fac1= (int)(256.0*facf0); + fac3= (int)(256.0*facf1); + + while(y--) { + + x= xo; + while(x--) { + + col= rt1[0]- ((fac1*rt2[0])>>8); + if(col<0) rt[0]= 0; else rt[0]= col; + col= rt1[1]- ((fac1*rt2[1])>>8); + if(col<0) rt[1]= 0; else rt[1]= col; + col= rt1[2]- ((fac1*rt2[2])>>8); + if(col<0) rt[2]= 0; else rt[2]= col; + col= rt1[3]- ((fac1*rt2[3])>>8); + if(col<0) rt[3]= 0; else rt[3]= col; + + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + col= rt1[0]- ((fac3*rt2[0])>>8); + if(col<0) rt[0]= 0; else rt[0]= col; + col= rt1[1]- ((fac3*rt2[1])>>8); + if(col<0) rt[1]= 0; else rt[1]= col; + col= rt1[2]- ((fac3*rt2[2])>>8); + if(col<0) rt[2]= 0; else rt[2]= col; + col= rt1[3]- ((fac3*rt2[3])>>8); + if(col<0) rt[3]= 0; else rt[3]= col; + + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + +static void do_sub_effect_float(float facf0, float facf1, int x, int y, + float *rect1, float *rect2, + float *out) +{ + int xo; + float fac1, fac3; + float *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac1= facf0; + fac3= facf1; + + while(y--) { + + x= xo * 4; + while(x--) { + *rt = *rt1 - fac1 * (*rt2); + + rt1++; rt2++; rt++; + } + + if(y==0) break; + y--; + + x= xo * 4; + while(x--) { + *rt = *rt1 - fac3 * (*rt2); + + rt1++; rt2++; rt++; + } + } +} + +static void do_sub_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_sub_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_sub_effect_byte( + facf0, facf1, x, y, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); + } +} + +/* ********************************************************************** + DROP + ********************************************************************** */ + +/* Must be > 0 or add precopy, etc to the function */ +#define XOFF 8 +#define YOFF 8 + +static void do_drop_effect_byte(float facf0, float facf1, int x, int y, + unsigned char *rect2i, unsigned char *rect1i, + unsigned char *outi) +{ + int height, width, temp, fac, fac1, fac2; + char *rt1, *rt2, *out; + int field= 1; + + width= x; + height= y; + + fac1= (int)(70.0*facf0); + fac2= (int)(70.0*facf1); + + rt2= (char*) (rect2i + YOFF*width); + rt1= (char*) rect1i; + out= (char*) outi; + for (y=0; y>8); + + *(out++)= MAX2(0, *rt1 - temp); rt1++; + *(out++)= MAX2(0, *rt1 - temp); rt1++; + *(out++)= MAX2(0, *rt1 - temp); rt1++; + *(out++)= MAX2(0, *rt1 - temp); rt1++; + rt2+=4; + } + rt2+=XOFF*4; + } + memcpy(out, rt1, sizeof(int)*YOFF*width); +} + +static void do_drop_effect_float(float facf0, float facf1, int x, int y, + float *rect2i, float *rect1i, + float *outi) +{ + int height, width; + float temp, fac, fac1, fac2; + float *rt1, *rt2, *out; + int field= 1; + + width= x; + height= y; + + fac1= 70.0*facf0; + fac2= 70.0*facf1; + + rt2= (rect2i + YOFF*width); + rt1= rect1i; + out= outi; + for (y=0; yrect_float) { + do_drop_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_drop_effect_byte( + facf0, facf1, x, y, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); + } +} + +/* ********************************************************************** + MUL + ********************************************************************** */ + +static void do_mul_effect_byte(float facf0, float facf1, int x, int y, + unsigned char *rect1, unsigned char *rect2, + unsigned char *out) +{ + int xo, fac1, fac3; + char *rt1, *rt2, *rt; + + xo= x; + rt1= (char *)rect1; + rt2= (char *)rect2; + rt= (char *)out; + + fac1= (int)(256.0*facf0); + fac3= (int)(256.0*facf1); + + /* formula: + * fac*(a*b) + (1-fac)*a => fac*a*(b-1)+a + */ + + while(y--) { + + x= xo; + while(x--) { + + rt[0]= rt1[0] + ((fac1*rt1[0]*(rt2[0]-256))>>16); + rt[1]= rt1[1] + ((fac1*rt1[1]*(rt2[1]-256))>>16); + rt[2]= rt1[2] + ((fac1*rt1[2]*(rt2[2]-256))>>16); + rt[3]= rt1[3] + ((fac1*rt1[3]*(rt2[3]-256))>>16); + + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + rt[0]= rt1[0] + ((fac3*rt1[0]*(rt2[0]-256))>>16); + rt[1]= rt1[1] + ((fac3*rt1[1]*(rt2[1]-256))>>16); + rt[2]= rt1[2] + ((fac3*rt1[2]*(rt2[2]-256))>>16); + rt[3]= rt1[3] + ((fac3*rt1[3]*(rt2[3]-256))>>16); + + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + +static void do_mul_effect_float(float facf0, float facf1, int x, int y, + float *rect1, float *rect2, + float *out) +{ + int xo; + float fac1, fac3; + float *rt1, *rt2, *rt; + + xo= x; + rt1= rect1; + rt2= rect2; + rt= out; + + fac1= facf0; + fac3= facf1; + + /* formula: + * fac*(a*b) + (1-fac)*a => fac*a*(b-1)+a + */ + + while(y--) { + + x= xo; + while(x--) { + + rt[0]= rt1[0] + fac1*rt1[0]*(rt2[0]-1.0); + rt[1]= rt1[1] + fac1*rt1[1]*(rt2[1]-1.0); + rt[2]= rt1[2] + fac1*rt1[2]*(rt2[2]-1.0); + rt[3]= rt1[3] + fac1*rt1[3]*(rt2[3]-1.0); + + rt1+= 4; rt2+= 4; rt+= 4; + } + + if(y==0) break; + y--; + + x= xo; + while(x--) { + + rt[0]= rt1[0] + fac3*rt1[0]*(rt2[0]-1.0); + rt[1]= rt1[1] + fac3*rt1[1]*(rt2[1]-1.0); + rt[2]= rt1[2] + fac3*rt1[2]*(rt2[2]-1.0); + rt[3]= rt1[3] + fac3*rt1[3]*(rt2[3]-1.0); + + rt1+= 4; rt2+= 4; rt+= 4; + } + } +} + +static void do_mul_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_mul_effect_float( + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_mul_effect_byte( + facf0, facf1, x, y, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); + } +} + +/* ********************************************************************** + WIPE + ********************************************************************** */ + +// This function calculates the blur band for the wipe effects +static float in_band(float width,float dist, float perc,int side,int dir){ + + float t1,t2,alpha,percwidth; + if(width == 0) + return (float)side; + if(side == 1) + percwidth = width * perc; + else + percwidth = width * (1 - perc); + + if(width < dist) + return side; + + t1 = dist / width; //percentange of width that is + t2 = 1 / width; //amount of alpha per % point + + if(side == 1) + alpha = (t1*t2*100) + (1-perc); // add point's alpha contrib to current position in wipe + else + alpha = (1-perc) - (t1*t2*100); + + if(dir == 0) + alpha = 1-alpha; + return alpha; +} + +static float check_zone(int x, int y, int xo, int yo, + Sequence *seq, float facf0) +{ + float posx, posy,hyp,hyp2,angle,hwidth,b1,b2,b3,pointdist; + /*some future stuff + float hyp3,hyp4,b4,b5 + */ + float temp1,temp2,temp3,temp4; //some placeholder variables + float halfx = xo/2; + float halfy = yo/2; + float widthf,output=0; + WipeVars *wipe = (WipeVars *)seq->effectdata; + int width; + + angle = wipe->angle; + if(angle < 0){ + x = xo-x; + //y = yo-y + } + angle = pow(fabs(angle)/45,log(xo)/log(2)); + + posy = facf0 * yo; + if(wipe->forward){ + posx = facf0 * xo; + posy = facf0 * yo; + } else{ + posx = xo - facf0 * xo; + posy = yo - facf0 * yo; + } + switch (wipe->wipetype) { + case DO_SINGLE_WIPE: + width = (int)(wipe->edgeWidth*((xo+yo)/2.0)); + hwidth = (float)width/2.0; + + if (angle == 0.0)angle = 0.000001; + b1 = posy - (-angle)*posx; + b2 = y - (-angle)*x; + hyp = fabs(angle*x+y+(-posy-angle*posx))/sqrt(angle*angle+1); + if(angle < 0){ + temp1 = b1; + b1 = b2; + b2 = temp1; + } + if(wipe->forward){ + if(b1 < b2) + output = in_band(width,hyp,facf0,1,1); + else + output = in_band(width,hyp,facf0,0,1); + } + else{ + if(b1 < b2) + output = in_band(width,hyp,facf0,0,1); + else + output = in_band(width,hyp,facf0,1,1); + } + break; + + + case DO_DOUBLE_WIPE: + if(!wipe->forward)facf0 = 1-facf0; // Go the other direction + + width = (int)(wipe->edgeWidth*((xo+yo)/2.0)); // calculate the blur width + hwidth = (float)width/2.0; + if (angle == 0)angle = 0.000001; + b1 = posy/2 - (-angle)*posx/2; + b3 = (yo-posy/2) - (-angle)*(xo-posx/2); + b2 = y - (-angle)*x; + + hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1); + hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1); + + temp1 = xo*(1-facf0/2)-xo*facf0/2; + temp2 = yo*(1-facf0/2)-yo*facf0/2; + pointdist = sqrt(temp1*temp1 + temp2*temp2); + + if(b2 < b1 && b2 < b3 ){ + if(hwidth < pointdist) + output = in_band(hwidth,hyp,facf0,0,1); + } + else if(b2 > b1 && b2 > b3 ){ + if(hwidth < pointdist) + output = in_band(hwidth,hyp2,facf0,0,1); + } + else{ + if( hyp < hwidth && hyp2 > hwidth ) + output = in_band(hwidth,hyp,facf0,1,1); + else if( hyp > hwidth && hyp2 < hwidth ) + output = in_band(hwidth,hyp2,facf0,1,1); + else + output = in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1); + } + if(!wipe->forward)output = 1-output; + break; + case DO_CLOCK_WIPE: + /* + temp1: angle of effect center in rads + temp2: angle of line through (halfx,halfy) and (x,y) in rads + temp3: angle of low side of blur + temp4: angle of high side of blur + */ + output = 1-facf0; + widthf = wipe->edgeWidth*2*3.14159; + temp1 = 2 * 3.14159 * facf0; + + if(wipe->forward){ + temp1 = 2*3.14159-temp1; + } + + x = x - halfx; + y = y - halfy; + + temp2 = asin(abs(y)/sqrt(x*x + y*y)); + if(x <= 0 && y >= 0) + temp2 = 3.14159 - temp2; + else if(x<=0 && y <= 0) + temp2 += 3.14159; + else if(x >= 0 && y <= 0) + temp2 = 2*3.14159 - temp2; + + if(wipe->forward){ + temp3 = temp1-(widthf/2)*facf0; + temp4 = temp1+(widthf/2)*(1-facf0); + } + else{ + temp3 = temp1-(widthf/2)*(1-facf0); + temp4 = temp1+(widthf/2)*facf0; + } + if (temp3 < 0) temp3 = 0; + if (temp4 > 2*3.14159) temp4 = 2*3.14159; + + + if(temp2 < temp3) + output = 0; + else if (temp2 > temp4) + output = 1; + else + output = (temp2-temp3)/(temp4-temp3); + if(x == 0 && y == 0){ + output = 1; + } + if(output != output) + output = 1; + if(wipe->forward) + output = 1 - output; + break; + /* BOX WIPE IS NOT WORKING YET */ + /* case DO_CROSS_WIPE: */ + /* BOX WIPE IS NOT WORKING YET */ + /* case DO_BOX_WIPE: + if(invert)facf0 = 1-facf0; + + width = (int)(wipe->edgeWidth*((xo+yo)/2.0)); + hwidth = (float)width/2.0; + if (angle == 0)angle = 0.000001; + b1 = posy/2 - (-angle)*posx/2; + b3 = (yo-posy/2) - (-angle)*(xo-posx/2); + b2 = y - (-angle)*x; + + hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1); + hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1); + + temp1 = xo*(1-facf0/2)-xo*facf0/2; + temp2 = yo*(1-facf0/2)-yo*facf0/2; + pointdist = sqrt(temp1*temp1 + temp2*temp2); + + if(b2 < b1 && b2 < b3 ){ + if(hwidth < pointdist) + output = in_band(hwidth,hyp,facf0,0,1); + } + else if(b2 > b1 && b2 > b3 ){ + if(hwidth < pointdist) + output = in_band(hwidth,hyp2,facf0,0,1); + } + else{ + if( hyp < hwidth && hyp2 > hwidth ) + output = in_band(hwidth,hyp,facf0,1,1); + else if( hyp > hwidth && hyp2 < hwidth ) + output = in_band(hwidth,hyp2,facf0,1,1); + else + output = in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1); + } + if(invert)facf0 = 1-facf0; + angle = -1/angle; + b1 = posy/2 - (-angle)*posx/2; + b3 = (yo-posy/2) - (-angle)*(xo-posx/2); + b2 = y - (-angle)*x; + + hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1); + hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1); + + if(b2 < b1 && b2 < b3 ){ + if(hwidth < pointdist) + output *= in_band(hwidth,hyp,facf0,0,1); + } + else if(b2 > b1 && b2 > b3 ){ + if(hwidth < pointdist) + output *= in_band(hwidth,hyp2,facf0,0,1); + } + else{ + if( hyp < hwidth && hyp2 > hwidth ) + output *= in_band(hwidth,hyp,facf0,1,1); + else if( hyp > hwidth && hyp2 < hwidth ) + output *= in_band(hwidth,hyp2,facf0,1,1); + else + output *= in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1); + } + + break;*/ + case DO_IRIS_WIPE: + if(xo > yo) yo = xo; + else xo = yo; + + if(!wipe->forward) + facf0 = 1-facf0; + + width = (int)(wipe->edgeWidth*((xo+yo)/2.0)); + hwidth = (float)width/2.0; + + temp1 = (halfx-(halfx)*facf0); + pointdist = sqrt(temp1*temp1 + temp1*temp1); + + temp2 = sqrt((halfx-x)*(halfx-x) + (halfy-y)*(halfy-y)); + if(temp2 > pointdist) + output = in_band(hwidth,fabs(temp2-pointdist),facf0,0,1); + else + output = in_band(hwidth,fabs(temp2-pointdist),facf0,1,1); + + if(!wipe->forward) + output = 1-output; + + break; + } + if (output < 0) output = 0; + else if(output > 1) output = 1; + return output; +} + +static void init_wipe_effect(Sequence *seq) +{ + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = MEM_callocN(sizeof(struct WipeVars), "wipevars"); +} + +static void free_wipe_effect(Sequence *seq) +{ + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = 0; +} + +static void copy_wipe_effect(Sequence *dst, Sequence *src) +{ + dst->effectdata = MEM_dupallocN(src->effectdata); +} + +static void do_wipe_effect_byte(Sequence *seq, float facf0, float facf1, + int x, int y, + unsigned char *rect1, + unsigned char *rect2, unsigned char *out) +{ + int xo, yo; + char *rt1, *rt2, *rt; + rt1 = (char *)rect1; + rt2 = (char *)rect2; + rt = (char *)out; + + xo = x; + yo = y; + for(y=0;yrect_float) { + do_wipe_effect_float(seq, + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_wipe_effect_byte(seq, + facf0, facf1, x, y, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); + } +} + +/* ********************************************************************** + GLOW + ********************************************************************** */ + +static void RVBlurBitmap2_byte ( unsigned char* map, int width,int height, + float blur, + int quality) +/* MUUUCCH better than the previous blur. */ +/* We do the blurring in two passes which is a whole lot faster. */ +/* I changed the math arount to implement an actual Gaussian */ +/* distribution. */ +/* */ +/* Watch out though, it tends to misbehaven with large blur values on */ +/* a small bitmap. Avoid avoid avoid. */ +/*=============================== */ +{ + unsigned char* temp=NULL,*swap; + float *filter=NULL; + int x,y,i,fx,fy; + int index, ix, halfWidth; + float fval, k, curColor[3], curColor2[3], weight=0; + + /* If we're not really blurring, bail out */ + if (blur<=0) + return; + + /* Allocate memory for the tempmap and the blur filter matrix */ + temp= MEM_mallocN( (width*height*4), "blurbitmaptemp"); + if (!temp) + return; + + /* Allocate memory for the filter elements */ + halfWidth = ((quality+1)*blur); + filter = (float *)MEM_mallocN(sizeof(float)*halfWidth*2, "blurbitmapfilter"); + if (!filter){ + MEM_freeN (temp); + return; + } + + /* Apparently we're calculating a bell curve */ + /* based on the standard deviation (or radius) */ + /* This code is based on an example */ + /* posted to comp.graphics.algorithms by */ + /* Blancmange (bmange@airdmhor.gen.nz) */ + + k = -1.0/(2.0*3.14159*blur*blur); + fval=0; + for (ix = 0;ix< halfWidth;ix++){ + weight = (float)exp(k*(ix*ix)); + filter[halfWidth - ix] = weight; + filter[halfWidth + ix] = weight; + } + filter[0] = weight; + + /* Normalize the array */ + fval=0; + for (ix = 0;ix< halfWidth*2;ix++) + fval+=filter[ix]; + + for (ix = 0;ix< halfWidth*2;ix++) + filter[ix]/=fval; + + /* Blur the rows */ + for (y=0;y=0)&&(i=0)&&(i=0)&&(i=0)&&(i0){ + out[index+GlowR]=MIN2(255*clamp, (in[index+GlowR]*boost*intensity)/255); + out[index+GlowG]=MIN2(255*clamp, (in[index+GlowG]*boost*intensity)/255); + out[index+GlowB]=MIN2(255*clamp, (in[index+GlowB]*boost*intensity)/255); + out[index+GlowA]=MIN2(255*clamp, (in[index+GlowA]*boost*intensity)/255); + } + else{ + out[index+GlowR]=0; + out[index+GlowG]=0; + out[index+GlowB]=0; + out[index+GlowA]=0; + } + } + } +} + +static void RVIsolateHighlights_float (float* in, float* out, + int width, int height, int threshold, + float boost, float clamp) +{ + int x,y,index; + float intensity; + + + for(y=0;y< height;y++) { + for (x=0;x< width;x++) { + index= (x+y*width)*4; + + /* Isolate the intensity */ + intensity=(in[index+GlowR]+in[index+GlowG]+in[index+GlowB]-threshold); + if (intensity>0){ + out[index+GlowR]=MIN2(clamp, (in[index+GlowR]*boost*intensity)); + out[index+GlowG]=MIN2(clamp, (in[index+GlowG]*boost*intensity)); + out[index+GlowB]=MIN2(clamp, (in[index+GlowB]*boost*intensity)); + out[index+GlowA]=MIN2(clamp, (in[index+GlowA]*boost*intensity)); + } + else{ + out[index+GlowR]=0; + out[index+GlowG]=0; + out[index+GlowB]=0; + out[index+GlowA]=0; + } + } + } +} + +static void init_glow_effect(Sequence *seq) +{ + GlowVars *glow; + + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = MEM_callocN(sizeof(struct GlowVars), "glowvars"); + + glow = (GlowVars *)seq->effectdata; + glow->fMini = 0.25; + glow->fClamp = 1.0; + glow->fBoost = 0.5; + glow->dDist = 3.0; + glow->dQuality = 3; + glow->bNoComp = 0; +} + +static void free_glow_effect(Sequence *seq) +{ + if(seq->effectdata)MEM_freeN(seq->effectdata); + seq->effectdata = 0; +} + +static void copy_glow_effect(Sequence *dst, Sequence *src) +{ + dst->effectdata = MEM_dupallocN(src->effectdata); +} + +//void do_glow_effect(Cast *cast, float facf0, float facf1, int xo, int yo, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use) +static void do_glow_effect_byte(Sequence *seq, float facf0, float facf1, + int x, int y, char *rect1, + char *rect2, char *out) +{ + unsigned char *outbuf=(unsigned char *)out; + unsigned char *inbuf=(unsigned char *)rect1; + GlowVars *glow = (GlowVars *)seq->effectdata; + + RVIsolateHighlights_byte(inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost, glow->fClamp); + RVBlurBitmap2_byte (outbuf, x, y, glow->dDist,glow->dQuality); + if (!glow->bNoComp) + RVAddBitmaps_byte (inbuf , outbuf, outbuf, x, y); +} + +static void do_glow_effect_float(Sequence *seq, float facf0, float facf1, + int x, int y, + float *rect1, float *rect2, float *out) +{ + float *outbuf = out; + float *inbuf = rect1; + GlowVars *glow = (GlowVars *)seq->effectdata; + + RVIsolateHighlights_float(inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost, glow->fClamp); + RVBlurBitmap2_float (outbuf, x, y, glow->dDist,glow->dQuality); + if (!glow->bNoComp) + RVAddBitmaps_float (inbuf , outbuf, outbuf, x, y); +} + +static void do_glow_effect(Sequence * seq,int cfra, + float facf0, float facf1, int x, int y, + struct ImBuf *ibuf1, struct ImBuf *ibuf2, + struct ImBuf *ibuf3, struct ImBuf *out) +{ + if (out->rect_float) { + do_glow_effect_float(seq, + facf0, facf1, x, y, + ibuf1->rect_float, ibuf2->rect_float, + out->rect_float); + } else { + do_glow_effect_byte(seq, + facf0, facf1, x, y, + (char*) ibuf1->rect, (char*) ibuf2->rect, + (char*) out->rect); + } +} + + +/* ********************************************************************** + sequence effect factory + ********************************************************************** */ + + +static void init_noop(struct Sequence *seq) +{ + +} + +static void load_noop(struct Sequence *seq) +{ + +} + +static void init_plugin_noop(struct Sequence *seq, const char * fname) +{ + +} + +static void free_noop(struct Sequence *seq) +{ + +} + +static int early_out_noop(struct Sequence *seq, + float facf0, float facf1) +{ + return 0; +} + +static int early_out_fade(struct Sequence *seq, + float facf0, float facf1) +{ + if (facf0 == 0.0 && facf1 == 0.0) { + return 1; + } else if (facf0 == 1.0 && facf1 == 1.0) { + return 2; + } + return 0; +} + +static void get_default_fac_noop(struct Sequence *seq, int cfra, + float * facf0, float * facf1) +{ + *facf0 = *facf1 = 1.0; +} + +static void get_default_fac_fade(struct Sequence *seq, int cfra, + float * facf0, float * facf1) +{ + *facf0 = (float)(cfra - seq->startdisp); + *facf1 = (float)(*facf0 + 0.5); + *facf0 /= seq->len; + *facf1 /= seq->len; +} + +static void do_overdrop_effect(struct Sequence * seq, int cfra, + float fac, float facf, + int x, int y, struct ImBuf * ibuf1, + struct ImBuf * ibuf2, + struct ImBuf * ibuf3, + struct ImBuf * out) +{ + do_drop_effect(seq, cfra, fac, facf, x, y, + ibuf1, ibuf2, ibuf3, out); + do_alphaover_effect(seq, cfra, fac, facf, x, y, + ibuf1, ibuf2, ibuf3, out); +} + +struct SeqEffectHandle get_sequence_effect(Sequence * seq) +{ + struct SeqEffectHandle rval; + int sequence_type = seq->type; + + rval.init = init_noop; + rval.init_plugin = init_plugin_noop; + rval.load = load_noop; + rval.free = free_noop; + rval.early_out = early_out_noop; + rval.get_default_fac = get_default_fac_noop; + rval.execute = 0; + + switch (sequence_type) { + case SEQ_CROSS: + rval.execute = do_cross_effect; + rval.early_out = early_out_fade; + rval.get_default_fac = get_default_fac_fade; + break; + case SEQ_GAMCROSS: + rval.init = init_gammacross; + rval.load = load_gammacross; + rval.free = free_gammacross; + rval.early_out = early_out_fade; + rval.get_default_fac = get_default_fac_fade; + rval.execute = do_gammacross_effect; + break; + case SEQ_ADD: + rval.execute = do_add_effect; + break; + case SEQ_SUB: + rval.execute = do_sub_effect; + break; + case SEQ_MUL: + rval.execute = do_mul_effect; + break; + case SEQ_ALPHAOVER: + rval.init = init_alpha_over_or_under; + rval.execute = do_alphaover_effect; + break; + case SEQ_OVERDROP: + rval.execute = do_overdrop_effect; + break; + case SEQ_ALPHAUNDER: + rval.init = init_alpha_over_or_under; + rval.execute = do_alphaunder_effect; + break; + case SEQ_WIPE: + rval.init = init_wipe_effect; + rval.free = free_wipe_effect; + rval.copy = copy_wipe_effect; + rval.early_out = early_out_fade; + rval.get_default_fac = get_default_fac_fade; + rval.execute = do_wipe_effect; + break; + case SEQ_GLOW: + rval.init = init_glow_effect; + rval.free = free_glow_effect; + rval.copy = copy_glow_effect; + rval.execute = do_glow_effect; + break; + case SEQ_PLUGIN: + rval.init_plugin = init_plugin; + rval.load = load_plugin; + rval.free = free_plugin; + rval.copy = copy_plugin; + rval.execute = do_plugin_effect; + rval.early_out = do_plugin_early_out; + rval.get_default_fac = get_default_fac_fade; + break; + } + + if (seq->flag & SEQ_EFFECT_NOT_LOADED) { + rval.load(seq); + seq->flag &= ~SEQ_EFFECT_NOT_LOADED; + } + + return rval; +} diff --git a/source/blender/src/seqscopes.c b/source/blender/src/seqscopes.c new file mode 100644 index 00000000000..a44a5261782 --- /dev/null +++ b/source/blender/src/seqscopes.c @@ -0,0 +1,340 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Author: Peter Schlaile < peter [at] schlaile [dot] de > + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + */ + +#include "BSE_seqscopes.h" +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "BKE_utildefines.h" +#include +#include + +static void rgb_to_yuv(float rgb[3], float yuv[3]) { + yuv[0]= 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2]; + yuv[1]= 0.492*(rgb[2] - yuv[0]); + yuv[2]= 0.877*(rgb[0] - yuv[0]); + + /* Normalize */ + yuv[1]*= 255.0/(122*2.0); + yuv[1]+= 0.5; + + yuv[2]*= 255.0/(157*2.0); + yuv[2]+= 0.5; +} + +static void scope_put_pixel(unsigned char* table, unsigned char * pos) +{ + char newval = table[*pos]; + pos[0] = pos[1] = pos[2] = newval; + pos[3] = 255; +} + +static void wform_put_line(int w, + unsigned char * last_pos, unsigned char * new_pos) +{ + if (last_pos > new_pos) { + unsigned char* temp = new_pos; + new_pos = last_pos; + last_pos = temp; + } + + while (last_pos < new_pos) { + if (last_pos[0] == 0) { + last_pos[0] = last_pos[1] = last_pos[2] = 32; + last_pos[3] = 255; + } + last_pos += 4*w; + } +} + +static struct ImBuf *make_waveform_view_from_ibuf_byte(struct ImBuf * ibuf) +{ + struct ImBuf * rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect, 0); + int x,y; + unsigned char* src = (unsigned char*) ibuf->rect; + unsigned char* tgt = (unsigned char*) rval->rect; + int w = ibuf->x + 3; + int h = 515; + float waveform_gamma = 0.2; + unsigned char wtable[256]; + + for (x = 0; x < 256; x++) { + wtable[x] = (unsigned char) (pow(((float) x + 1)/256, + waveform_gamma)*255); + } + + for (y = 0; y < h; y++) { + unsigned char * last_p = 0; + + for (x = 0; x < w; x++) { + unsigned char * rgb = src + 4 * (ibuf->x * y + x); + float v = 1.0 * + ( 0.299*rgb[0] + + 0.587*rgb[1] + + 0.114*rgb[2]) / 255.0; + unsigned char * p = tgt; + p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1); + + scope_put_pixel(wtable, p); + p += 4 * w; + scope_put_pixel(wtable, p); + + if (last_p != 0) { + wform_put_line(w, last_p, p); + } + last_p = p; + } + } + + for (x = 0; x < w; x++) { + unsigned char * p = tgt + 4 * x; + p[1] = p[3] = 255.0; + p[4 * w + 1] = p[4 * w + 3] = 255.0; + p = tgt + 4 * (w * (h - 1) + x); + p[1] = p[3] = 255.0; + p[-4 * w + 1] = p[-4 * w + 3] = 255.0; + } + + for (y = 0; y < h; y++) { + unsigned char * p = tgt + 4 * w * y; + p[1] = p[3] = 255.0; + p[4 + 1] = p[4 + 3] = 255.0; + p = tgt + 4 * (w * y + w - 1); + p[1] = p[3] = 255.0; + p[-4 + 1] = p[-4 + 3] = 255.0; + } + + return rval; +} + +static struct ImBuf *make_waveform_view_from_ibuf_float(struct ImBuf * ibuf) +{ + struct ImBuf * rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect, 0); + int x,y; + float* src = ibuf->rect_float; + unsigned char* tgt = (unsigned char*) rval->rect; + int w = ibuf->x + 3; + int h = 515; + float waveform_gamma = 0.2; + unsigned char wtable[256]; + + for (x = 0; x < 256; x++) { + wtable[x] = (unsigned char) (pow(((float) x + 1)/256, + waveform_gamma)*255); + } + + for (y = 0; y < h; y++) { + unsigned char * last_p = 0; + + for (x = 0; x < w; x++) { + float * rgb = src + 4 * (ibuf->x * y + x); + float v = 1.0 * + ( 0.299*rgb[0] + + 0.587*rgb[1] + + 0.114*rgb[2]); + unsigned char * p = tgt; + + CLAMP(v, 0.0, 1.0); + + p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1); + + scope_put_pixel(wtable, p); + p += 4 * w; + scope_put_pixel(wtable, p); + + if (last_p != 0) { + wform_put_line(w, last_p, p); + } + last_p = p; + } + } + + for (x = 0; x < w; x++) { + unsigned char * p = tgt + 4 * x; + p[1] = p[3] = 255.0; + p[4 * w + 1] = p[4 * w + 3] = 255.0; + p = tgt + 4 * (w * (h - 1) + x); + p[1] = p[3] = 255.0; + p[-4 * w + 1] = p[-4 * w + 3] = 255.0; + } + + for (y = 0; y < h; y++) { + unsigned char * p = tgt + 4 * w * y; + p[1] = p[3] = 255.0; + p[4 + 1] = p[4 + 3] = 255.0; + p = tgt + 4 * (w * y + w - 1); + p[1] = p[3] = 255.0; + p[-4 + 1] = p[-4 + 3] = 255.0; + } + + return rval; +} + +struct ImBuf *make_waveform_view_from_ibuf(struct ImBuf * ibuf) +{ + if (ibuf->rect_float) { + return make_waveform_view_from_ibuf_float(ibuf); + } else { + return make_waveform_view_from_ibuf_byte(ibuf); + } +} + + +static void vectorscope_put_cross(unsigned char r, unsigned char g, + unsigned char b, + char * tgt, int w, int h, int size) +{ + float rgb[3], yuv[3]; + char * p; + int x = 0; + int y = 0; + + rgb[0]= (float)r/255.0; + rgb[1]= (float)g/255.0; + rgb[2]= (float)b/255.0; + rgb_to_yuv(rgb, yuv); + + p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1)) + + (int) ((yuv[1] * (w - 3) + 1))); + + if (r == 0 && g == 0 && b == 0) { + r = 255; + } + + for (y = -size; y <= size; y++) { + for (x = -size; x <= size; x++) { + char * q = p + 4 * (y * w + x); + q[0] = r; q[1] = g; q[2] = b; q[3] = 255; + } + } +} + +static struct ImBuf *make_vectorscope_view_from_ibuf_byte(struct ImBuf * ibuf) +{ + struct ImBuf * rval = IMB_allocImBuf(515, 515, 32, IB_rect, 0); + int x,y; + char* src = (char*) ibuf->rect; + char* tgt = (char*) rval->rect; + float rgb[3], yuv[3]; + int w = 515; + int h = 515; + float scope_gamma = 0.2; + unsigned char wtable[256]; + + for (x = 0; x < 256; x++) { + wtable[x] = (unsigned char) (pow(((float) x + 1)/256, + scope_gamma)*255); + } + + for (x = 0; x <= 255; x++) { + vectorscope_put_cross(255 , 0,255 - x, tgt, w, h, 1); + vectorscope_put_cross(255 , x, 0, tgt, w, h, 1); + vectorscope_put_cross(255- x, 255, 0, tgt, w, h, 1); + vectorscope_put_cross(0, 255, x, tgt, w, h, 1); + vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1); + vectorscope_put_cross(x, 0, 255, tgt, w, h, 1); + } + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + char * src1 = src + 4 * (ibuf->x * y + x); + char * p; + + rgb[0]= (float)src1[0]/255.0; + rgb[1]= (float)src1[1]/255.0; + rgb[2]= (float)src1[2]/255.0; + rgb_to_yuv(rgb, yuv); + + p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1)) + + (int) ((yuv[1] * (w - 3) + 1))); + scope_put_pixel(wtable, p); + } + } + + vectorscope_put_cross(0, 0, 0, tgt, w, h, 3); + + return rval; +} + +static struct ImBuf *make_vectorscope_view_from_ibuf_float(struct ImBuf * ibuf) +{ + struct ImBuf * rval = IMB_allocImBuf(515, 515, 32, IB_rect, 0); + int x,y; + float* src = ibuf->rect_float; + char* tgt = (char*) rval->rect; + float rgb[3], yuv[3]; + int w = 515; + int h = 515; + float scope_gamma = 0.2; + unsigned char wtable[256]; + + for (x = 0; x < 256; x++) { + wtable[x] = (unsigned char) (pow(((float) x + 1)/256, + scope_gamma)*255); + } + + for (x = 0; x <= 255; x++) { + vectorscope_put_cross(255 , 0,255 - x, tgt, w, h, 1); + vectorscope_put_cross(255 , x, 0, tgt, w, h, 1); + vectorscope_put_cross(255- x, 255, 0, tgt, w, h, 1); + vectorscope_put_cross(0, 255, x, tgt, w, h, 1); + vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1); + vectorscope_put_cross(x, 0, 255, tgt, w, h, 1); + } + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + float * src1 = src + 4 * (ibuf->x * y + x); + char * p; + + memcpy(rgb, src1, 3 * sizeof(float)); + + CLAMP(rgb[0], 0.0, 1.0); + CLAMP(rgb[1], 0.0, 1.0); + CLAMP(rgb[2], 0.0, 1.0); + + rgb_to_yuv(rgb, yuv); + + p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1)) + + (int) ((yuv[1] * (w - 3) + 1))); + scope_put_pixel(wtable, p); + } + } + + vectorscope_put_cross(0, 0, 0, tgt, w, h, 3); + + return rval; +} + +struct ImBuf *make_vectorscope_view_from_ibuf(struct ImBuf * ibuf) +{ + if (ibuf->rect_float) { + return make_vectorscope_view_from_ibuf_float(ibuf); + } else { + return make_vectorscope_view_from_ibuf_byte(ibuf); + } +} diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index 3fbe9735626..71c258bf3f6 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -23,7 +23,7 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * - * Contributor(s): Peter Schlaile 2005/2006 + * Contributor(s): Peter Schlaile 2005/2006 * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ @@ -33,7 +33,6 @@ #include #include "MEM_guardedalloc.h" -#include "PIL_dynlib.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -47,7 +46,6 @@ #include "DNA_view3d_types.h" #include "BKE_utildefines.h" -#include "BKE_plugin_types.h" #include "BKE_global.h" #include "BKE_texture.h" #include "BKE_image.h" @@ -64,138 +62,14 @@ #include "BIF_editsound.h" #include "BSE_sequence.h" +#include "BSE_seqeffects.h" #include "RE_pipeline.h" // talks to entire render API #include "blendef.h" -static void do_build_seq_depend(Sequence * seq, int cfra); - int seqrectx, seqrecty; -/* support for plugin sequences: */ - -void open_plugin_seq(PluginSeq *pis, char *seqname) -{ - int (*version)(); - void* (*alloc_private)(); - char *cp; - - /* to be sure: (is tested for) */ - pis->doit= 0; - pis->pname= 0; - pis->varstr= 0; - pis->cfra= 0; - pis->version= 0; - pis->instance_private_data = 0; - - /* clear the error list */ - PIL_dynlib_get_error_as_string(NULL); - - /* if(pis->handle) PIL_dynlib_close(pis->handle); */ - /* pis->handle= 0; */ - - /* open the needed object */ - pis->handle= PIL_dynlib_open(pis->name); - if(test_dlerr(pis->name, pis->name)) return; - - if (pis->handle != 0) { - /* find the address of the version function */ - version= (int (*)())PIL_dynlib_find_symbol(pis->handle, "plugin_seq_getversion"); - if (test_dlerr(pis->name, "plugin_seq_getversion")) return; - - if (version != 0) { - pis->version= version(); - if (pis->version==2 || pis->version==3) { - int (*info_func)(PluginInfo *); - PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info");; - - info_func= (int (*)(PluginInfo *))PIL_dynlib_find_symbol(pis->handle, "plugin_getinfo"); - - if(info_func == NULL) error("No info func"); - else { - info_func(info); - - pis->pname= info->name; - pis->vars= info->nvars; - pis->cfra= info->cfra; - - pis->varstr= info->varstr; - - pis->doit= (void(*)(void))info->seq_doit; - if (info->init) - info->init(); - } - MEM_freeN(info); - - cp= PIL_dynlib_find_symbol(pis->handle, "seqname"); - if(cp) strncpy(cp, seqname, 21); - } else { - printf ("Plugin returned unrecognized version number\n"); - return; - } - } - alloc_private = (void* (*)())PIL_dynlib_find_symbol( - pis->handle, "plugin_seq_alloc_private_data"); - if (alloc_private) { - pis->instance_private_data = alloc_private(); - } - - pis->current_private_data = (void**) - PIL_dynlib_find_symbol( - pis->handle, "plugin_private_data"); - } -} - -PluginSeq *add_plugin_seq(char *str, char *seqname) -{ - PluginSeq *pis; - VarStruct *varstr; - int a; - - pis= MEM_callocN(sizeof(PluginSeq), "PluginSeq"); - - strncpy(pis->name, str, FILE_MAXDIR+FILE_MAXFILE); - open_plugin_seq(pis, seqname); - - if(pis->doit==0) { - if(pis->handle==0) error("no plugin: %s", str); - else error("in plugin: %s", str); - MEM_freeN(pis); - return 0; - } - - /* default values */ - varstr= pis->varstr; - for(a=0; avars; a++, varstr++) { - if( (varstr->type & FLO)==FLO) - pis->data[a]= varstr->def; - else if( (varstr->type & INT)==INT) - *((int *)(pis->data+a))= (int) varstr->def; - } - - return pis; -} - -void free_plugin_seq(PluginSeq *pis) -{ - if(pis==0) return; - - /* no PIL_dynlib_close: same plugin can be opened multiple times with 1 handle */ - - if (pis->instance_private_data) { - void (*free_private)(void *); - - free_private = (void (*)(void *))PIL_dynlib_find_symbol( - pis->handle, "plugin_seq_free_private_data"); - if (free_private) { - free_private(pis->instance_private_data); - } - } - - MEM_freeN(pis); -} - /* ***************** END PLUGIN ************************ */ void free_stripdata(int len, StripElem *se) @@ -247,12 +121,15 @@ void free_sequence(Sequence *seq) extern Sequence *last_seq; if(seq->strip) free_strip(seq->strip); - if(seq->effectdata) MEM_freeN(seq->effectdata); if(seq->anim) IMB_free_anim(seq->anim); if(seq->hdaudio) sound_close_hdaudio(seq->hdaudio); - free_plugin_seq(seq->plugin); + if (seq->type & SEQ_EFFECT) { + struct SeqEffectHandle sh = get_sequence_effect(seq); + + sh.free(seq); + } if(seq==last_seq) last_seq= 0; @@ -467,1158 +344,65 @@ void clear_scene_in_allseqs(Scene *sce) /* ***************** DO THE SEQUENCE ***************** */ -void do_alphaover_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out) -{ - int fac2, mfac, fac, fac4; - int xo, tempc; - char *rt1, *rt2, *rt; - - xo= x; - rt1= (char *)rect1; - rt2= (char *)rect2; - rt= (char *)out; - - fac2= (int)(256.0*facf0); - fac4= (int)(256.0*facf1); - - while(y--) { - - x= xo; - while(x--) { - - /* rt = rt1 over rt2 (alpha from rt1) */ - - fac= fac2; - mfac= 256 - ( (fac2*rt1[3])>>8 ); - - if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2); - else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1); - else { - tempc= ( fac*rt1[0] + mfac*rt2[0])>>8; - if(tempc>255) rt[0]= 255; else rt[0]= tempc; - tempc= ( fac*rt1[1] + mfac*rt2[1])>>8; - if(tempc>255) rt[1]= 255; else rt[1]= tempc; - tempc= ( fac*rt1[2] + mfac*rt2[2])>>8; - if(tempc>255) rt[2]= 255; else rt[2]= tempc; - tempc= ( fac*rt1[3] + mfac*rt2[3])>>8; - if(tempc>255) rt[3]= 255; else rt[3]= tempc; - } - rt1+= 4; rt2+= 4; rt+= 4; - } - - if(y==0) break; - y--; - - x= xo; - while(x--) { - - fac= fac4; - mfac= 256 - ( (fac4*rt1[3])>>8 ); - - if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2); - else if(mfac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt1); - else { - tempc= ( fac*rt1[0] + mfac*rt2[0])>>8; - if(tempc>255) rt[0]= 255; else rt[0]= tempc; - tempc= ( fac*rt1[1] + mfac*rt2[1])>>8; - if(tempc>255) rt[1]= 255; else rt[1]= tempc; - tempc= ( fac*rt1[2] + mfac*rt2[2])>>8; - if(tempc>255) rt[2]= 255; else rt[2]= tempc; - tempc= ( fac*rt1[3] + mfac*rt2[3])>>8; - if(tempc>255) rt[3]= 255; else rt[3]= tempc; - } - rt1+= 4; rt2+= 4; rt+= 4; - } - } -} - -void do_alphaunder_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out) -{ - int fac2, mfac, fac, fac4; - int xo; - char *rt1, *rt2, *rt; - - xo= x; - rt1= (char *)rect1; - rt2= (char *)rect2; - rt= (char *)out; - - fac2= (int)(256.0*facf0); - fac4= (int)(256.0*facf1); - - while(y--) { - - x= xo; - while(x--) { - - /* rt = rt1 under rt2 (alpha from rt2) */ - - /* this complex optimalisation is because the - * 'skybuf' can be crossed in - */ - if(rt2[3]==0 && fac2==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1); - else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2); - else { - mfac= rt2[3]; - fac= (fac2*(256-mfac))>>8; - - if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2); - else { - rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8; - rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8; - rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8; - rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8; - } - } - rt1+= 4; rt2+= 4; rt+= 4; - } - - if(y==0) break; - y--; - - x= xo; - while(x--) { - - if(rt2[3]==0 && fac4==256) *( (unsigned int *)rt) = *( (unsigned int *)rt1); - else if(rt2[3]==255) *( (unsigned int *)rt) = *( (unsigned int *)rt2); - else { - mfac= rt2[3]; - fac= (fac4*(256-mfac))>>8; - - if(fac==0) *( (unsigned int *)rt) = *( (unsigned int *)rt2); - else { - rt[0]= ( fac*rt1[0] + mfac*rt2[0])>>8; - rt[1]= ( fac*rt1[1] + mfac*rt2[1])>>8; - rt[2]= ( fac*rt1[2] + mfac*rt2[2])>>8; - rt[3]= ( fac*rt1[3] + mfac*rt2[3])>>8; - } - } - rt1+= 4; rt2+= 4; rt+= 4; - } - } -} - - -void do_cross_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out) -{ - int fac1, fac2, fac3, fac4; - int xo; - char *rt1, *rt2, *rt; - - xo= x; - rt1= (char *)rect1; - rt2= (char *)rect2; - rt= (char *)out; - - fac2= (int)(256.0*facf0); - fac1= 256-fac2; - fac4= (int)(256.0*facf1); - fac3= 256-fac4; - - while(y--) { - - x= xo; - while(x--) { - - rt[0]= (fac1*rt1[0] + fac2*rt2[0])>>8; - rt[1]= (fac1*rt1[1] + fac2*rt2[1])>>8; - rt[2]= (fac1*rt1[2] + fac2*rt2[2])>>8; - rt[3]= (fac1*rt1[3] + fac2*rt2[3])>>8; - - rt1+= 4; rt2+= 4; rt+= 4; - } - - if(y==0) break; - y--; - - x= xo; - while(x--) { - - rt[0]= (fac3*rt1[0] + fac4*rt2[0])>>8; - rt[1]= (fac3*rt1[1] + fac4*rt2[1])>>8; - rt[2]= (fac3*rt1[2] + fac4*rt2[2])>>8; - rt[3]= (fac3*rt1[3] + fac4*rt2[3])>>8; - - rt1+= 4; rt2+= 4; rt+= 4; - } - - } -} - -/* copied code from initrender.c */ -static unsigned short *gamtab, *igamtab1; - -static void gamtabs(float gamma) -{ - float val, igamma= 1.0f/gamma; - int a; - - gamtab= MEM_mallocN(65536*sizeof(short), "initGaus2"); - igamtab1= MEM_mallocN(256*sizeof(short), "initGaus2"); - - /* gamtab: in short, out short */ - for(a=0; a<65536; a++) { - val= a; - val/= 65535.0; - - if(gamma==2.0) val= sqrt(val); - else if(gamma!=1.0) val= pow(val, igamma); - - gamtab[a]= (65535.99*val); - } - /* inverse gamtab1 : in byte, out short */ - for(a=1; a<=256; a++) { - if(gamma==2.0) igamtab1[a-1]= a*a-1; - else if(gamma==1.0) igamtab1[a-1]= 256*a-1; - else { - val= a/256.0; - igamtab1[a-1]= (65535.0*pow(val, gamma)) -1 ; - } - } - -} - -void do_gammacross_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out) -{ - int fac1, fac2, col; - int xo; - char *rt1, *rt2, *rt; - - gamtabs(2.0f); - - xo= x; - rt1= (char *)rect1; - rt2= (char *)rect2; - rt= (char *)out; - - fac2= (int)(256.0*facf0); - fac1= 256-fac2; - - while(y--) { - - x= xo; - while(x--) { - - col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8; - if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; - col=(fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8; - if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; - col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8; - if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; - col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8; - if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; - - rt1+= 4; rt2+= 4; rt+= 4; - } - - if(y==0) break; - y--; - - x= xo; - while(x--) { - - col= (fac1*igamtab1[rt1[0]] + fac2*igamtab1[rt2[0]])>>8; - if(col>65535) rt[0]= 255; else rt[0]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; - col= (fac1*igamtab1[rt1[1]] + fac2*igamtab1[rt2[1]])>>8; - if(col>65535) rt[1]= 255; else rt[1]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; - col= (fac1*igamtab1[rt1[2]] + fac2*igamtab1[rt2[2]])>>8; - if(col>65535) rt[2]= 255; else rt[2]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; - col= (fac1*igamtab1[rt1[3]] + fac2*igamtab1[rt2[3]])>>8; - if(col>65535) rt[3]= 255; else rt[3]= ( (char *)(gamtab+col))[MOST_SIG_BYTE]; - - rt1+= 4; rt2+= 4; rt+= 4; - } - } - - MEM_freeN(gamtab); - MEM_freeN(igamtab1); -} - -void do_add_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out) -{ - int col, xo, fac1, fac3; - char *rt1, *rt2, *rt; - - xo= x; - rt1= (char *)rect1; - rt2= (char *)rect2; - rt= (char *)out; - - fac1= (int)(256.0*facf0); - fac3= (int)(256.0*facf1); - - while(y--) { - - x= xo; - while(x--) { - - col= rt1[0]+ ((fac1*rt2[0])>>8); - if(col>255) rt[0]= 255; else rt[0]= col; - col= rt1[1]+ ((fac1*rt2[1])>>8); - if(col>255) rt[1]= 255; else rt[1]= col; - col= rt1[2]+ ((fac1*rt2[2])>>8); - if(col>255) rt[2]= 255; else rt[2]= col; - col= rt1[3]+ ((fac1*rt2[3])>>8); - if(col>255) rt[3]= 255; else rt[3]= col; - - rt1+= 4; rt2+= 4; rt+= 4; - } - - if(y==0) break; - y--; - - x= xo; - while(x--) { - - col= rt1[0]+ ((fac3*rt2[0])>>8); - if(col>255) rt[0]= 255; else rt[0]= col; - col= rt1[1]+ ((fac3*rt2[1])>>8); - if(col>255) rt[1]= 255; else rt[1]= col; - col= rt1[2]+ ((fac3*rt2[2])>>8); - if(col>255) rt[2]= 255; else rt[2]= col; - col= rt1[3]+ ((fac3*rt2[3])>>8); - if(col>255) rt[3]= 255; else rt[3]= col; - - rt1+= 4; rt2+= 4; rt+= 4; - } - } -} - -void do_sub_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out) -{ - int col, xo, fac1, fac3; - char *rt1, *rt2, *rt; - - xo= x; - rt1= (char *)rect1; - rt2= (char *)rect2; - rt= (char *)out; - - fac1= (int)(256.0*facf0); - fac3= (int)(256.0*facf1); - - while(y--) { - - x= xo; - while(x--) { - - col= rt1[0]- ((fac1*rt2[0])>>8); - if(col<0) rt[0]= 0; else rt[0]= col; - col= rt1[1]- ((fac1*rt2[1])>>8); - if(col<0) rt[1]= 0; else rt[1]= col; - col= rt1[2]- ((fac1*rt2[2])>>8); - if(col<0) rt[2]= 0; else rt[2]= col; - col= rt1[3]- ((fac1*rt2[3])>>8); - if(col<0) rt[3]= 0; else rt[3]= col; - - rt1+= 4; rt2+= 4; rt+= 4; - } - - if(y==0) break; - y--; - - x= xo; - while(x--) { - - col= rt1[0]- ((fac3*rt2[0])>>8); - if(col<0) rt[0]= 0; else rt[0]= col; - col= rt1[1]- ((fac3*rt2[1])>>8); - if(col<0) rt[1]= 0; else rt[1]= col; - col= rt1[2]- ((fac3*rt2[2])>>8); - if(col<0) rt[2]= 0; else rt[2]= col; - col= rt1[3]- ((fac3*rt2[3])>>8); - if(col<0) rt[3]= 0; else rt[3]= col; - - rt1+= 4; rt2+= 4; rt+= 4; - } - } -} - -/* Must be > 0 or add precopy, etc to the function */ -#define XOFF 8 -#define YOFF 8 - -void do_drop_effect(float facf0, float facf1, int x, int y, unsigned int *rect2i, unsigned int *rect1i, unsigned int *outi) -{ - int height, width, temp, fac, fac1, fac2; - char *rt1, *rt2, *out; - int field= 1; - - width= x; - height= y; - - fac1= (int)(70.0*facf0); - fac2= (int)(70.0*facf1); - - rt2= (char*) (rect2i + YOFF*width); - rt1= (char*) rect1i; - out= (char*) outi; - for (y=0; y>8); - - *(out++)= MAX2(0, *rt1 - temp); rt1++; - *(out++)= MAX2(0, *rt1 - temp); rt1++; - *(out++)= MAX2(0, *rt1 - temp); rt1++; - *(out++)= MAX2(0, *rt1 - temp); rt1++; - rt2+=4; - } - rt2+=XOFF*4; - } - memcpy(out, rt1, sizeof(int)*YOFF*width); -} - - /* WATCH: rect2 and rect1 reversed */ -void do_drop_effect2(float facf0, float facf1, int x, int y, unsigned int *rect2, unsigned int *rect1, unsigned int *out) -{ - int col, xo, yo, temp, fac1, fac3; - int xofs= -8, yofs= 8; - char *rt1, *rt2, *rt; - - xo= x; - yo= y; - - rt2= (char *)(rect2 + yofs*x + xofs); - - rt1= (char *)rect1; - rt= (char *)out; - - fac1= (int)(70.0*facf0); - fac3= (int)(70.0*facf1); - - while(y-- > 0) { - - temp= y-yofs; - if(temp > 0 && temp < yo) { - - x= xo; - while(x--) { - - temp= x+xofs; - if(temp > 0 && temp < xo) { - - temp= ((fac1*rt2[3])>>8); - - col= rt1[0]- temp; - if(col<0) rt[0]= 0; else rt[0]= col; - col= rt1[1]- temp; - if(col<0) rt[1]= 0; else rt[1]= col; - col= rt1[2]- temp; - if(col<0) rt[2]= 0; else rt[2]= col; - col= rt1[3]- temp; - if(col<0) rt[3]= 0; else rt[3]= col; - } - else *( (unsigned int *)rt) = *( (unsigned int *)rt1); - - rt1+= 4; rt2+= 4; rt+= 4; - } - } - else { - x= xo; - while(x--) { - *( (unsigned int *)rt) = *( (unsigned int *)rt1); - rt1+= 4; rt2+= 4; rt+= 4; - } - } - - if(y==0) break; - y--; - - temp= y-yofs; - if(temp > 0 && temp < yo) { - - x= xo; - while(x--) { - - temp= x+xofs; - if(temp > 0 && temp < xo) { - - temp= ((fac3*rt2[3])>>8); - - col= rt1[0]- temp; - if(col<0) rt[0]= 0; else rt[0]= col; - col= rt1[1]- temp; - if(col<0) rt[1]= 0; else rt[1]= col; - col= rt1[2]- temp; - if(col<0) rt[2]= 0; else rt[2]= col; - col= rt1[3]- temp; - if(col<0) rt[3]= 0; else rt[3]= col; - } - else *( (unsigned int *)rt) = *( (unsigned int *)rt1); - - rt1+= 4; rt2+= 4; rt+= 4; - } - } - else { - x= xo; - while(x--) { - *( (unsigned int *)rt) = *( (unsigned int *)rt1); - rt1+= 4; rt2+= 4; rt+= 4; - } - } - } -} - - -void do_mul_effect(float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out) -{ - int xo, fac1, fac3; - char *rt1, *rt2, *rt; - - xo= x; - rt1= (char *)rect1; - rt2= (char *)rect2; - rt= (char *)out; - - fac1= (int)(256.0*facf0); - fac3= (int)(256.0*facf1); - - /* formula: - * fac*(a*b) + (1-fac)*a => fac*a*(b-1)+a - */ - - while(y--) { - - x= xo; - while(x--) { - - rt[0]= rt1[0] + ((fac1*rt1[0]*(rt2[0]-256))>>16); - rt[1]= rt1[1] + ((fac1*rt1[1]*(rt2[1]-256))>>16); - rt[2]= rt1[2] + ((fac1*rt1[2]*(rt2[2]-256))>>16); - rt[3]= rt1[3] + ((fac1*rt1[3]*(rt2[3]-256))>>16); - - rt1+= 4; rt2+= 4; rt+= 4; - } - - if(y==0) break; - y--; - - x= xo; - while(x--) { - - rt[0]= rt1[0] + ((fac3*rt1[0]*(rt2[0]-256))>>16); - rt[1]= rt1[1] + ((fac3*rt1[1]*(rt2[1]-256))>>16); - rt[2]= rt1[2] + ((fac3*rt1[2]*(rt2[2]-256))>>16); - rt[3]= rt1[3] + ((fac3*rt1[3]*(rt2[3]-256))>>16); - - rt1+= 4; rt2+= 4; rt+= 4; - } - } -} - -// This function calculates the blur band for the wipe effects -float in_band(float width,float dist, float perc,int side,int dir){ - - float t1,t2,alpha,percwidth; - if(width == 0) - return (float)side; - if(side == 1) - percwidth = width * perc; - else - percwidth = width * (1 - perc); - - if(width < dist) - return side; - - t1 = dist / width; //percentange of width that is - t2 = 1 / width; //amount of alpha per % point - - if(side == 1) - alpha = (t1*t2*100) + (1-perc); // add point's alpha contrib to current position in wipe - else - alpha = (1-perc) - (t1*t2*100); - - if(dir == 0) - alpha = 1-alpha; - return alpha; -} - -float check_zone(int x, int y, int xo, int yo, Sequence *seq, float facf0) { - - float posx, posy,hyp,hyp2,angle,hwidth,b1,b2,b3,pointdist; - /*some future stuff - float hyp3,hyp4,b4,b5 - */ - float temp1,temp2,temp3,temp4; //some placeholder variables - float halfx = xo/2; - float halfy = yo/2; - float widthf,output=0; - WipeVars *wipe = (WipeVars *)seq->effectdata; - int width; - - angle = wipe->angle; - if(angle < 0){ - x = xo-x; - //y = yo-y - } - angle = pow(fabs(angle)/45,log(xo)/log(2)); - - posy = facf0 * yo; - if(wipe->forward){ - posx = facf0 * xo; - posy = facf0 * yo; - } else{ - posx = xo - facf0 * xo; - posy = yo - facf0 * yo; - } - switch (wipe->wipetype) { - case DO_SINGLE_WIPE: - width = (int)(wipe->edgeWidth*((xo+yo)/2.0)); - hwidth = (float)width/2.0; - - if (angle == 0.0)angle = 0.000001; - b1 = posy - (-angle)*posx; - b2 = y - (-angle)*x; - hyp = fabs(angle*x+y+(-posy-angle*posx))/sqrt(angle*angle+1); - if(angle < 0){ - temp1 = b1; - b1 = b2; - b2 = temp1; - } - if(wipe->forward){ - if(b1 < b2) - output = in_band(width,hyp,facf0,1,1); - else - output = in_band(width,hyp,facf0,0,1); - } - else{ - if(b1 < b2) - output = in_band(width,hyp,facf0,0,1); - else - output = in_band(width,hyp,facf0,1,1); - } - break; - - - case DO_DOUBLE_WIPE: - if(!wipe->forward)facf0 = 1-facf0; // Go the other direction - - width = (int)(wipe->edgeWidth*((xo+yo)/2.0)); // calculate the blur width - hwidth = (float)width/2.0; - if (angle == 0)angle = 0.000001; - b1 = posy/2 - (-angle)*posx/2; - b3 = (yo-posy/2) - (-angle)*(xo-posx/2); - b2 = y - (-angle)*x; - - hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1); - hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1); - - temp1 = xo*(1-facf0/2)-xo*facf0/2; - temp2 = yo*(1-facf0/2)-yo*facf0/2; - pointdist = sqrt(temp1*temp1 + temp2*temp2); - - if(b2 < b1 && b2 < b3 ){ - if(hwidth < pointdist) - output = in_band(hwidth,hyp,facf0,0,1); - } - else if(b2 > b1 && b2 > b3 ){ - if(hwidth < pointdist) - output = in_band(hwidth,hyp2,facf0,0,1); - } - else{ - if( hyp < hwidth && hyp2 > hwidth ) - output = in_band(hwidth,hyp,facf0,1,1); - else if( hyp > hwidth && hyp2 < hwidth ) - output = in_band(hwidth,hyp2,facf0,1,1); - else - output = in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1); - } - if(!wipe->forward)output = 1-output; - break; - case DO_CLOCK_WIPE: - /* - temp1: angle of effect center in rads - temp2: angle of line through (halfx,halfy) and (x,y) in rads - temp3: angle of low side of blur - temp4: angle of high side of blur - */ - output = 1-facf0; - widthf = wipe->edgeWidth*2*3.14159; - temp1 = 2 * 3.14159 * facf0; - - if(wipe->forward){ - temp1 = 2*3.14159-temp1; - } - - x = x - halfx; - y = y - halfy; - - temp2 = asin(abs(y)/sqrt(x*x + y*y)); - if(x <= 0 && y >= 0) - temp2 = 3.14159 - temp2; - else if(x<=0 && y <= 0) - temp2 += 3.14159; - else if(x >= 0 && y <= 0) - temp2 = 2*3.14159 - temp2; - - if(wipe->forward){ - temp3 = temp1-(widthf/2)*facf0; - temp4 = temp1+(widthf/2)*(1-facf0); - } - else{ - temp3 = temp1-(widthf/2)*(1-facf0); - temp4 = temp1+(widthf/2)*facf0; - } - if (temp3 < 0) temp3 = 0; - if (temp4 > 2*3.14159) temp4 = 2*3.14159; - - - if(temp2 < temp3) - output = 0; - else if (temp2 > temp4) - output = 1; - else - output = (temp2-temp3)/(temp4-temp3); - if(x == 0 && y == 0){ - output = 1; - } - if(output != output) - output = 1; - if(wipe->forward) - output = 1 - output; - break; - /* BOX WIPE IS NOT WORKING YET */ - /* case DO_CROSS_WIPE: */ - /* BOX WIPE IS NOT WORKING YET */ - /* case DO_BOX_WIPE: - if(invert)facf0 = 1-facf0; - - width = (int)(wipe->edgeWidth*((xo+yo)/2.0)); - hwidth = (float)width/2.0; - if (angle == 0)angle = 0.000001; - b1 = posy/2 - (-angle)*posx/2; - b3 = (yo-posy/2) - (-angle)*(xo-posx/2); - b2 = y - (-angle)*x; - - hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1); - hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1); - - temp1 = xo*(1-facf0/2)-xo*facf0/2; - temp2 = yo*(1-facf0/2)-yo*facf0/2; - pointdist = sqrt(temp1*temp1 + temp2*temp2); - - if(b2 < b1 && b2 < b3 ){ - if(hwidth < pointdist) - output = in_band(hwidth,hyp,facf0,0,1); - } - else if(b2 > b1 && b2 > b3 ){ - if(hwidth < pointdist) - output = in_band(hwidth,hyp2,facf0,0,1); - } - else{ - if( hyp < hwidth && hyp2 > hwidth ) - output = in_band(hwidth,hyp,facf0,1,1); - else if( hyp > hwidth && hyp2 < hwidth ) - output = in_band(hwidth,hyp2,facf0,1,1); - else - output = in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1); - } - if(invert)facf0 = 1-facf0; - angle = -1/angle; - b1 = posy/2 - (-angle)*posx/2; - b3 = (yo-posy/2) - (-angle)*(xo-posx/2); - b2 = y - (-angle)*x; - - hyp = abs(angle*x+y+(-posy/2-angle*posx/2))/sqrt(angle*angle+1); - hyp2 = abs(angle*x+y+(-(yo-posy/2)-angle*(xo-posx/2)))/sqrt(angle*angle+1); - - if(b2 < b1 && b2 < b3 ){ - if(hwidth < pointdist) - output *= in_band(hwidth,hyp,facf0,0,1); - } - else if(b2 > b1 && b2 > b3 ){ - if(hwidth < pointdist) - output *= in_band(hwidth,hyp2,facf0,0,1); - } - else{ - if( hyp < hwidth && hyp2 > hwidth ) - output *= in_band(hwidth,hyp,facf0,1,1); - else if( hyp > hwidth && hyp2 < hwidth ) - output *= in_band(hwidth,hyp2,facf0,1,1); - else - output *= in_band(hwidth,hyp2,facf0,1,1) * in_band(hwidth,hyp,facf0,1,1); - } - - break;*/ - case DO_IRIS_WIPE: - if(xo > yo) yo = xo; - else xo = yo; - - if(!wipe->forward) - facf0 = 1-facf0; - - width = (int)(wipe->edgeWidth*((xo+yo)/2.0)); - hwidth = (float)width/2.0; - - temp1 = (halfx-(halfx)*facf0); - pointdist = sqrt(temp1*temp1 + temp1*temp1); - - temp2 = sqrt((halfx-x)*(halfx-x) + (halfy-y)*(halfy-y)); - if(temp2 > pointdist) - output = in_band(hwidth,fabs(temp2-pointdist),facf0,0,1); - else - output = in_band(hwidth,fabs(temp2-pointdist),facf0,1,1); - - if(!wipe->forward) - output = 1-output; - - break; - } - if (output < 0) output = 0; - else if(output > 1) output = 1; - return output; -} - -void init_wipe_effect(Sequence *seq) -{ - if(seq->effectdata)MEM_freeN(seq->effectdata); - seq->effectdata = MEM_callocN(sizeof(struct WipeVars), "wipevars"); -} - -void do_wipe_effect(Sequence *seq, float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out) -{ - int xo, yo; - char *rt1, *rt2, *rt; - rt1 = (char *)rect1; - rt2 = (char *)rect2; - rt = (char *)out; - - xo = x; - yo = y; - for(y=0;y=0)&&(i=0)&&(i0){ - out[index+GlowR]=MIN2(255*clamp, (in[index+GlowR]*boost*intensity)/255); - out[index+GlowG]=MIN2(255*clamp, (in[index+GlowG]*boost*intensity)/255); - out[index+GlowB]=MIN2(255*clamp, (in[index+GlowB]*boost*intensity)/255); - out[index+GlowA]=MIN2(255*clamp, (in[index+GlowA]*boost*intensity)/255); - } - else{ - out[index+GlowR]=0; - out[index+GlowG]=0; - out[index+GlowB]=0; - out[index+GlowA]=0; - } - } - } -} - -void init_glow_effect(Sequence *seq) -{ - GlowVars *glow; - - if(seq->effectdata)MEM_freeN(seq->effectdata); - seq->effectdata = MEM_callocN(sizeof(struct GlowVars), "glowvars"); - - glow = (GlowVars *)seq->effectdata; - glow->fMini = 0.25; - glow->fClamp = 1.0; - glow->fBoost = 0.5; - glow->dDist = 3.0; - glow->dQuality = 3; - glow->bNoComp = 0; -} - - -//void do_glow_effect(Cast *cast, float facf0, float facf1, int xo, int yo, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *outbuf, ImBuf *use) -void do_glow_effect(Sequence *seq, float facf0, float facf1, int x, int y, unsigned int *rect1, unsigned int *rect2, unsigned int *out) -{ - unsigned char *outbuf=(unsigned char *)out; - unsigned char *inbuf=(unsigned char *)rect1; - GlowVars *glow = (GlowVars *)seq->effectdata; - - RVIsolateHighlights (inbuf, outbuf , x, y, glow->fMini*765, glow->fBoost, glow->fClamp); - RVBlurBitmap2 (outbuf, x, y, glow->dDist,glow->dQuality); - if (!glow->bNoComp) - RVAddBitmaps (inbuf , outbuf, outbuf, x, y); -} - void make_black_ibuf(ImBuf *ibuf) { - unsigned int *rect; + int *rect; + float *rect_float; int tot; - if(ibuf==0 || ibuf->rect==0) return; + if(ibuf==0 || (ibuf->rect==0 && ibuf->rect_float==0)) return; tot= ibuf->x*ibuf->y; + rect= ibuf->rect; - while(tot--) *(rect++)= 0; + rect_float = ibuf->rect_float; + if (rect) { + memset(rect, 0, tot * sizeof(char) * 4); + } + + if (rect_float) { + memset(rect_float, 0, tot * sizeof(float) * 4); + } } void multibuf(ImBuf *ibuf, float fmul) { char *rt; + float *rt_float; + int a, mul, icol; mul= (int)(256.0*fmul); a= ibuf->x*ibuf->y; rt= (char *)ibuf->rect; - while(a--) { - - icol= (mul*rt[0])>>8; - if(icol>254) rt[0]= 255; else rt[0]= icol; - icol= (mul*rt[1])>>8; - if(icol>254) rt[1]= 255; else rt[1]= icol; - icol= (mul*rt[2])>>8; - if(icol>254) rt[2]= 255; else rt[2]= icol; - icol= (mul*rt[3])>>8; - if(icol>254) rt[3]= 255; else rt[3]= icol; - - rt+= 4; + rt_float = ibuf->rect_float; + + if (rt) { + while(a--) { + + icol= (mul*rt[0])>>8; + if(icol>254) rt[0]= 255; else rt[0]= icol; + icol= (mul*rt[1])>>8; + if(icol>254) rt[1]= 255; else rt[1]= icol; + icol= (mul*rt[2])>>8; + if(icol>254) rt[2]= 255; else rt[2]= icol; + icol= (mul*rt[3])>>8; + if(icol>254) rt[3]= 255; else rt[3]= icol; + + rt+= 4; + } + } + if (rt_float) { + while(a--) { + rt_float[0] *= fmul; + rt_float[1] *= fmul; + rt_float[2] *= fmul; + rt_float[3] *= fmul; + + rt_float += 4; + } } } @@ -1627,7 +411,7 @@ void do_effect(int cfra, Sequence *seq, StripElem *se) StripElem *se1, *se2, *se3; float fac, facf; int x, y; - char *cp; + struct SeqEffectHandle sh = get_sequence_effect(seq); if(se->se1==0 || se->se2==0 || se->se3==0) { make_black_ibuf(se->ibuf); @@ -1653,47 +437,38 @@ void do_effect(int cfra, Sequence *seq, StripElem *se) do_seq_ipo(seq); fac= seq->facf0; facf= seq->facf1; - } - else if ( seq->type==SEQ_CROSS || seq->type==SEQ_GAMCROSS || seq->type==SEQ_PLUGIN || seq->type==SEQ_WIPE) { - fac= (float)(cfra - seq->startdisp); - facf= (float)(fac+0.5); - fac /= seq->len; - facf /= seq->len; - } - else { - fac= facf= 1.0; + } else { + sh.get_default_fac(seq, cfra, &fac, &facf); } if( G.scene->r.mode & R_FIELDS ); else facf= fac; - /* FIXME: This should be made available to external plugins too... */ - if (seq->type == SEQ_CROSS || seq->type == SEQ_GAMCROSS || - seq->type == SEQ_WIPE) { - if (fac == 0.0 && facf == 0.0) { - if (se1->ibuf==0) { - make_black_ibuf(se->ibuf); - return; - } - if (se->ibuf != se1->ibuf) { - IMB_freeImBuf(se->ibuf); - se->ibuf = se1->ibuf; - IMB_refImBuf(se->ibuf); - } + switch (sh.early_out(seq, fac, facf)) { + case 0: + break; + case 1: + if (se1->ibuf==0) { + make_black_ibuf(se->ibuf); return; - } else if (fac == 1.0 && facf == 1.0) { - if (se2->ibuf==0) { - make_black_ibuf(se->ibuf); - return; - } - if (se->ibuf != se2->ibuf) { - IMB_freeImBuf(se->ibuf); - se->ibuf = se2->ibuf; - IMB_refImBuf(se->ibuf); - } + } + if (se->ibuf != se1->ibuf) { + IMB_freeImBuf(se->ibuf); + se->ibuf = se1->ibuf; + IMB_refImBuf(se->ibuf); + } + return; + case 2: + if (se2->ibuf==0) { + make_black_ibuf(se->ibuf); return; - } - } - + } + if (se->ibuf != se2->ibuf) { + IMB_freeImBuf(se->ibuf); + se->ibuf = se2->ibuf; + IMB_refImBuf(se->ibuf); + } + return; + } if (se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0) { make_black_ibuf(se->ibuf); @@ -1703,78 +478,22 @@ void do_effect(int cfra, Sequence *seq, StripElem *se) x= se2->ibuf->x; y= se2->ibuf->y; - switch(seq->type) { - case SEQ_CROSS: - do_cross_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect); - break; - case SEQ_GAMCROSS: - do_gammacross_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect); - break; - case SEQ_ADD: - do_add_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect); - break; - case SEQ_SUB: - do_sub_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect); - break; - case SEQ_MUL: - do_mul_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect); - break; - case SEQ_ALPHAOVER: - do_alphaover_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect); - break; - case SEQ_OVERDROP: - do_drop_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect); - do_alphaover_effect(fac, facf, x, y, se1->ibuf->rect, se->ibuf->rect, se->ibuf->rect); - break; - case SEQ_ALPHAUNDER: - do_alphaunder_effect(fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect); - break; - case SEQ_WIPE: - do_wipe_effect(seq, fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect); - break; - case SEQ_GLOW: - do_glow_effect(seq, fac, facf, x, y, se1->ibuf->rect, se2->ibuf->rect, se->ibuf->rect); - break; - case SEQ_PLUGIN: - if(seq->plugin && seq->plugin->doit) { - - if((G.f & G_PLAYANIM)==0) waitcursor(1); - - if(seq->plugin->cfra) - *(seq->plugin->cfra)= frame_to_float(CFRA); - - cp = PIL_dynlib_find_symbol( - seq->plugin->handle, "seqname"); - - if(cp) strncpy(cp, seq->name+2, 22); - - if (seq->plugin->current_private_data) { - *seq->plugin->current_private_data - = seq->plugin->instance_private_data; - } - - if (seq->plugin->version<=2) { - if(se1->ibuf) IMB_convert_rgba_to_abgr(se1->ibuf); - if(se2->ibuf) IMB_convert_rgba_to_abgr(se2->ibuf); - if(se3->ibuf) IMB_convert_rgba_to_abgr(se3->ibuf); - } - - ((SeqDoit)seq->plugin->doit)( - seq->plugin->data, fac, facf, x, y, - se1->ibuf, se2->ibuf, se->ibuf, se3->ibuf); - - if (seq->plugin->version<=2) { - if(se1->ibuf) IMB_convert_rgba_to_abgr(se1->ibuf); - if(se2->ibuf) IMB_convert_rgba_to_abgr(se2->ibuf); - if(se3->ibuf) IMB_convert_rgba_to_abgr(se3->ibuf); - IMB_convert_rgba_to_abgr(se->ibuf); - } + if (!se1->ibuf->rect_float && se->ibuf->rect_float) { + IMB_float_from_rect(se1->ibuf); + } + if (!se2->ibuf->rect_float && se->ibuf->rect_float) { + IMB_float_from_rect(se2->ibuf); + } - if((G.f & G_PLAYANIM)==0) waitcursor(0); - } - break; + if (!se1->ibuf->rect && !se->ibuf->rect_float) { + IMB_rect_from_float(se1->ibuf); + } + if (!se2->ibuf->rect && !se->ibuf->rect_float) { + IMB_rect_from_float(se2->ibuf); } + sh.execute(seq, cfra, fac, facf, x, y, se1->ibuf, se2->ibuf, se3->ibuf, + se->ibuf); } StripElem *give_stripelem(Sequence *seq, int cfra) @@ -1927,8 +646,12 @@ static void do_seq_unref_cfra(ListBase *seqbase, int cfra) if(seq->seqbase.first) { - if(cfra< seq->start) do_seq_unref_cfra(&seq->seqbase, seq->start); - else if(cfra> seq->start+seq->len-1) do_seq_unref_cfra(&seq->seqbase, seq->start+seq->len-1); + if(cfra< seq->start) do_seq_unref_cfra( + &seq->seqbase, seq->start); + else if(cfra> seq->start+seq->len-1) + do_seq_unref_cfra( + &seq->seqbase, + seq->start+seq->len-1); else do_seq_unref_cfra(&seq->seqbase, cfra); } @@ -1951,16 +674,25 @@ static void do_seq_test_unref_cfra(ListBase *seqbase, int cfra) if(seq->seqbase.first) { - if(cfra< seq->start) do_seq_test_unref_cfra(&seq->seqbase, seq->start); - else if(cfra> seq->start+seq->len-1) do_seq_test_unref_cfra(&seq->seqbase, seq->start+seq->len-1); - else do_seq_test_unref_cfra(&seq->seqbase, cfra); + if(cfra< seq->start) + do_seq_test_unref_cfra( + &seq->seqbase, seq->start); + else if(cfra> seq->start+seq->len-1) + do_seq_test_unref_cfra( + &seq->seqbase, + seq->start+seq->len-1); + else do_seq_test_unref_cfra( + &seq->seqbase, cfra); } if (seq->curelem && seq->curelem->ibuf && seq->curelem->isneeded) { - if (IMB_cache_limiter_get_refcount(seq->curelem->ibuf)) { - fprintf(stderr, "refcount Arggh: %p, %d\n", - seq, seq->type); + if (IMB_cache_limiter_get_refcount( + seq->curelem->ibuf)) { + fprintf(stderr, + "sequence.c: imbuf-refcount " + "Arggh: %p, %d\n", + seq, seq->type); } } } @@ -1968,43 +700,36 @@ static void do_seq_test_unref_cfra(ListBase *seqbase, int cfra) } } +static void do_build_seq_depend(Sequence * seq, int cfra); + static void do_effect_depend(int cfra, Sequence * seq, StripElem *se) { float fac, facf; + struct SeqEffectHandle sh = get_sequence_effect(seq); if(seq->ipo && seq->ipo->curve.first) { do_seq_ipo(seq); fac= seq->facf0; facf= seq->facf1; - } else if ( seq->type == SEQ_CROSS - || seq->type == SEQ_GAMCROSS - || seq->type == SEQ_PLUGIN - || seq->type == SEQ_WIPE) { - fac= (float)(cfra - seq->startdisp); - facf= (float)(fac+0.5); - fac /= seq->len; - facf /= seq->len; } else { - fac= facf= 1.0; - } + sh.get_default_fac(seq, cfra, &fac, &facf); + } if( G.scene->r.mode & R_FIELDS ); else facf= fac; - /* FIXME: This should be made available to external plugins too... */ - if (seq->type == SEQ_CROSS || seq->type == SEQ_GAMCROSS || - seq->type == SEQ_WIPE) { - if (fac == 0.0 && facf == 0.0) { - do_build_seq_depend(seq->seq1, cfra); - } else if (fac == 1.0 && facf == 1.0) { - do_build_seq_depend(seq->seq2, cfra); - } else { - do_build_seq_depend(seq->seq1, cfra); - do_build_seq_depend(seq->seq2, cfra); - } - } else { + switch (sh.early_out(seq, fac, facf)) { + case 0: do_build_seq_depend(seq->seq1, cfra); do_build_seq_depend(seq->seq2, cfra); + break; + case 1: + do_build_seq_depend(seq->seq1, cfra); + break; + case 2: + do_build_seq_depend(seq->seq2, cfra); + break; } + do_build_seq_depend(seq->seq3, cfra); } @@ -2120,16 +845,22 @@ static void do_build_seq_ibuf(Sequence * seq, int cfra) if(seq->type==SEQ_IMAGE) { if(se->ok && se->ibuf==0) { + /* if playanim or render: + no waitcursor */ + if((G.f & G_PLAYANIM)==0) + waitcursor(1); - /* if playanim or render: no waitcursor */ - if((G.f & G_PLAYANIM)==0) waitcursor(1); - - strncpy(name, seq->strip->dir, FILE_MAXDIR-1); + strncpy(name, seq->strip->dir, + FILE_MAXDIR-1); strncat(name, se->name, FILE_MAXFILE); - BLI_convertstringcode(name, G.sce, G.scene->r.cfra); - se->ibuf= IMB_loadiffname(name, IB_rect); + BLI_convertstringcode(name, + G.sce, + G.scene->r.cfra); + se->ibuf= IMB_loadiffname(name, + IB_rect); - if((G.f & G_PLAYANIM)==0) waitcursor(0); + if((G.f & G_PLAYANIM)==0) + waitcursor(0); if(se->ibuf==0) se->ok= 0; else { @@ -2146,10 +877,6 @@ static void do_build_seq_ibuf(Sequence * seq, int cfra) } else if(seq->type==SEQ_MOVIE) { if(se->ok && se->ibuf==0) { - - /* if playanim r render: no waitcursor */ - if((G.f & G_PLAYANIM)==0) waitcursor(1); - if(seq->anim==0) { strncpy(name, seq->strip->dir, FILE_MAXDIR-1); strncat(name, seq->strip->stripdata->name, FILE_MAXFILE-1); @@ -2158,6 +885,9 @@ static void do_build_seq_ibuf(Sequence * seq, int cfra) seq->anim = openanim(name, IB_rect); } if(seq->anim) { + IMB_anim_set_preseek( + seq->anim, + seq->anim_preseek); se->ibuf = IMB_anim_absolute(seq->anim, se->nr); } @@ -2172,7 +902,6 @@ static void do_build_seq_ibuf(Sequence * seq, int cfra) if(seq->mul==0.0) seq->mul= 1.0; if(seq->mul != 1.0) multibuf(se->ibuf, seq->mul); } - if((G.f & G_PLAYANIM)==0) waitcursor(0); } } else if(seq->type==SEQ_SCENE && se->ibuf==0 && seq->scene) { // scene can be NULL after deletions @@ -2438,180 +1167,6 @@ ImBuf *give_ibuf_seq(int rectx, int recty, int cfra, int chanshown) } -static void rgb_to_yuv(float rgb[3], float yuv[3]) { - yuv[0]= 0.299*rgb[0] + 0.587*rgb[1] + 0.114*rgb[2]; - yuv[1]= 0.492*(rgb[2] - yuv[0]); - yuv[2]= 0.877*(rgb[0] - yuv[0]); - - /* Normalize */ - yuv[1]*= 255.0/(122*2.0); - yuv[1]+= 0.5; - - yuv[2]*= 255.0/(157*2.0); - yuv[2]+= 0.5; -} - -static void scope_put_pixel(unsigned char* table, unsigned char * pos) -{ - char newval = table[*pos]; - pos[0] = pos[1] = pos[2] = newval; - pos[3] = 255; -} - -static void wform_put_line(int w, - unsigned char * last_pos, unsigned char * new_pos) -{ - if (last_pos > new_pos) { - unsigned char* temp = new_pos; - new_pos = last_pos; - last_pos = temp; - } - - while (last_pos < new_pos) { - if (last_pos[0] == 0) { - last_pos[0] = last_pos[1] = last_pos[2] = 32; - last_pos[3] = 255; - } - last_pos += 4*w; - } -} - -struct ImBuf *make_waveform_view_from_ibuf(struct ImBuf * ibuf) -{ - struct ImBuf * rval = IMB_allocImBuf(ibuf->x + 3, 515, 32, IB_rect, 0); - int x,y; - unsigned char* src = (unsigned char*) ibuf->rect; - unsigned char* tgt = (unsigned char*) rval->rect; - int w = ibuf->x + 3; - int h = 515; - float waveform_gamma = 0.2; - unsigned char wtable[256]; - - for (x = 0; x < 256; x++) { - wtable[x] = (unsigned char) (pow(((float) x + 1)/256, - waveform_gamma)*255); - } - - for (y = 0; y < h; y++) { - unsigned char * last_p = 0; - - for (x = 0; x < w; x++) { - unsigned char * rgb = src + 4 * (ibuf->x * y + x); - float v = 1.0 * - ( 0.299*rgb[0] - + 0.587*rgb[1] - + 0.114*rgb[2]) / 255.0; - unsigned char * p = tgt; - p += 4 * (w * ((int) (v * (h - 3)) + 1) + x + 1); - - scope_put_pixel(wtable, p); - p += 4 * w; - scope_put_pixel(wtable, p); - - if (last_p != 0) { - wform_put_line(w, last_p, p); - } - last_p = p; - } - } - - for (x = 0; x < w; x++) { - unsigned char * p = tgt + 4 * x; - p[1] = p[3] = 255.0; - p[4 * w + 1] = p[4 * w + 3] = 255.0; - p = tgt + 4 * (w * (h - 1) + x); - p[1] = p[3] = 255.0; - p[-4 * w + 1] = p[-4 * w + 3] = 255.0; - } - - for (y = 0; y < h; y++) { - unsigned char * p = tgt + 4 * w * y; - p[1] = p[3] = 255.0; - p[4 + 1] = p[4 + 3] = 255.0; - p = tgt + 4 * (w * y + w - 1); - p[1] = p[3] = 255.0; - p[-4 + 1] = p[-4 + 3] = 255.0; - } - - return rval; -} - -static void vectorscope_put_cross(unsigned char r, unsigned char g, - unsigned char b, - char * tgt, int w, int h, int size) -{ - float rgb[3], yuv[3]; - char * p; - int x = 0; - int y = 0; - - rgb[0]= (float)r/255.0; - rgb[1]= (float)g/255.0; - rgb[2]= (float)b/255.0; - rgb_to_yuv(rgb, yuv); - - p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1)) - + (int) ((yuv[1] * (w - 3) + 1))); - - if (r == 0 && g == 0 && b == 0) { - r = 255; - } - - for (y = -size; y <= size; y++) { - for (x = -size; x <= size; x++) { - char * q = p + 4 * (y * w + x); - q[0] = r; q[1] = g; q[2] = b; q[3] = 255; - } - } -} - -struct ImBuf *make_vectorscope_view_from_ibuf(struct ImBuf * ibuf) -{ - struct ImBuf * rval = IMB_allocImBuf(515, 515, 32, IB_rect, 0); - int x,y; - char* src = (char*) ibuf->rect; - char* tgt = (char*) rval->rect; - float rgb[3], yuv[3]; - int w = 515; - int h = 515; - float scope_gamma = 0.2; - unsigned char wtable[256]; - - for (x = 0; x < 256; x++) { - wtable[x] = (unsigned char) (pow(((float) x + 1)/256, - scope_gamma)*255); - } - - for (x = 0; x <= 255; x++) { - vectorscope_put_cross(255 , 0,255 - x, tgt, w, h, 1); - vectorscope_put_cross(255 , x, 0, tgt, w, h, 1); - vectorscope_put_cross(255- x, 255, 0, tgt, w, h, 1); - vectorscope_put_cross(0, 255, x, tgt, w, h, 1); - vectorscope_put_cross(0, 255 - x, 255, tgt, w, h, 1); - vectorscope_put_cross(x, 0, 255, tgt, w, h, 1); - } - - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - char * src1 = src + 4 * (ibuf->x * y + x); - char * p; - - rgb[0]= (float)src1[0]/255.0; - rgb[1]= (float)src1[1]/255.0; - rgb[2]= (float)src1[2]/255.0; - rgb_to_yuv(rgb, yuv); - - p = tgt + 4 * (w * (int) ((yuv[2] * (h - 3) + 1)) - + (int) ((yuv[1] * (w - 3) + 1))); - scope_put_pixel(wtable, p); - } - } - - vectorscope_put_cross(0, 0, 0, tgt, w, h, 3); - - return rval; -} - void free_imbuf_effect_spec(int cfra) { Sequence *seq; -- cgit v1.2.3