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
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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; */
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ffmpeg/rational.h>
|
||||
#include <ffmpeg/avformat.h>
|
||||
#include <ffmpeg/avcodec.h>
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -153,6 +153,7 @@ struct anim {
|
||||
int orientation;
|
||||
size_t framesize;
|
||||
int interlacing;
|
||||
int preseek;
|
||||
|
||||
/* data */
|
||||
struct ImBuf * ibuf1, * ibuf2;
|
||||
|
||||
@@ -88,12 +88,19 @@
|
||||
#ifdef WITH_FFMPEG
|
||||
#include <ffmpeg/avformat.h>
|
||||
#include <ffmpeg/avcodec.h>
|
||||
#include <ffmpeg/rational.h>
|
||||
|
||||
/* #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; i<pFormatCtx->nb_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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
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) {
|
||||
rectf = ibuf->rect_float;
|
||||
|
||||
gamma = 1.0 / gamma;
|
||||
|
||||
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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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; i<pFormatCtx->nb_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);
|
||||
|
||||
83
source/blender/include/BSE_seqeffects.h
Normal file
83
source/blender/include/BSE_seqeffects.h
Normal file
@@ -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
|
||||
|
||||
38
source/blender/include/BSE_seqscopes.h
Normal file
38
source/blender/include/BSE_seqscopes.h
Normal file
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ||
|
||||
|
||||
@@ -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);
|
||||
/* free previous effect and init new effect */
|
||||
struct SeqEffectHandle sh;
|
||||
|
||||
switch(last_seq->type){
|
||||
case SEQ_WIPE:
|
||||
init_wipe_effect(last_seq);
|
||||
break;
|
||||
case SEQ_GLOW:
|
||||
init_glow_effect(last_seq);
|
||||
break;
|
||||
}
|
||||
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);
|
||||
|
||||
@@ -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 <peter@schlaile.de> 2005
|
||||
* Contributor(s): Peter Schlaile <peter [at] schlaile [dot] de> 2005
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
@@ -38,6 +38,7 @@
|
||||
#ifdef WITH_FFMPEG
|
||||
#include <ffmpeg/avformat.h>
|
||||
#include <ffmpeg/avcodec.h>
|
||||
#include <ffmpeg/rational.h>
|
||||
#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; i<pFormatCtx->nb_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) {
|
||||
long decode_pos = 0;
|
||||
|
||||
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;
|
||||
|
||||
av_seek_frame(hdaudio->pFormatCtx, -1,
|
||||
(long long) frame_position * AV_TIME_BASE,
|
||||
AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
|
||||
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) {
|
||||
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;
|
||||
int data_size;
|
||||
int len;
|
||||
uint8_t *audio_pkt_data;
|
||||
int audio_pkt_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;
|
||||
}
|
||||
if(packet.stream_index != hdaudio->audioStream) {
|
||||
av_free_packet(&packet);
|
||||
continue;
|
||||
}
|
||||
|
||||
audio_pkt_size -= len;
|
||||
audio_pkt_data += len;
|
||||
audio_pkt_data = packet.data;
|
||||
audio_pkt_size = packet.size;
|
||||
|
||||
decode_pos +=
|
||||
data_size / sizeof(short);
|
||||
if (decode_pos + data_size
|
||||
/ sizeof(short)
|
||||
> hdaudio->decode_cache_size) {
|
||||
av_free_packet(&packet);
|
||||
break;
|
||||
}
|
||||
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)];
|
||||
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;
|
||||
|
||||
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);
|
||||
hdaudio->frame_position = frame_position;
|
||||
|
||||
if (st_time == AV_NOPTS_VALUE) {
|
||||
st_time = 0;
|
||||
}
|
||||
memcpy(target_buffer, temp_buffer,
|
||||
nb_samples * target_channels * sizeof(short));
|
||||
|
||||
pos += st_time * AV_TIME_BASE * time_base;
|
||||
|
||||
av_seek_frame(hdaudio->pFormatCtx, -1,
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 (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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
2515
source/blender/src/seqeffects.c
Normal file
2515
source/blender/src/seqeffects.c
Normal file
File diff suppressed because it is too large
Load Diff
340
source/blender/src/seqscopes.c
Normal file
340
source/blender/src/seqscopes.c
Normal file
@@ -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 <math.h>
|
||||
#include <string.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user