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:
2006-03-07 20:01:12 +00:00
parent 9ce587e211
commit 327d413eb3
21 changed files with 3683 additions and 1924 deletions

View File

@@ -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;

View File

@@ -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; */

View File

@@ -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));
}

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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);
/**
*

View File

@@ -153,6 +153,7 @@ struct anim {
int orientation;
size_t framesize;
int interlacing;
int preseek;
/* data */
struct ImBuf * ibuf1, * ibuf2;

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}
}
}

View File

@@ -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);

View 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

View 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

View File

@@ -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);

View File

@@ -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

View File

@@ -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 ||

View File

@@ -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);

View File

@@ -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);
}

File diff suppressed because it is too large Load Diff

View 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