mostly finished speed
This commit is contained in:
+46
-28
@@ -73,28 +73,38 @@ void SpeedDialog::run() {
|
||||
double clip_percent;
|
||||
|
||||
// get default frame rate/percentage
|
||||
clip_percent = c->speed;
|
||||
if (c->track < 0) {
|
||||
double media_frame_rate = c->getMediaFrameRate();
|
||||
|
||||
clip_percent = c->frame_rate / media_frame_rate;
|
||||
|
||||
// get "default" frame rate"
|
||||
if (enable_frame_rate) {
|
||||
// check if frame rate is equal to default
|
||||
if (!qIsNaN(default_frame_rate) && !qFuzzyCompare(media_frame_rate, default_frame_rate)) {
|
||||
default_frame_rate = NAN;
|
||||
bool process_video = true;
|
||||
if (c->media_type == MEDIA_TYPE_FOOTAGE) {
|
||||
Media* m = static_cast<Media*>(c->media);
|
||||
if (m != NULL) {
|
||||
MediaStream* ms = m->get_stream_from_file_index(true, c->media_stream);
|
||||
if (ms != NULL && ms->infinite_length) {
|
||||
process_video = false;
|
||||
}
|
||||
}
|
||||
if (!qIsNaN(current_frame_rate) && !qFuzzyCompare(c->frame_rate, current_frame_rate)) {
|
||||
current_frame_rate = NAN;
|
||||
}
|
||||
} else {
|
||||
default_frame_rate = media_frame_rate;
|
||||
current_frame_rate = c->frame_rate;
|
||||
}
|
||||
|
||||
enable_frame_rate = true;
|
||||
} else {
|
||||
clip_percent = c->frame_rate;
|
||||
if (process_video) {
|
||||
double media_frame_rate = c->getMediaFrameRate();
|
||||
|
||||
// get "default" frame rate"
|
||||
if (enable_frame_rate) {
|
||||
// check if frame rate is equal to default
|
||||
if (!qIsNaN(default_frame_rate) && !qFuzzyCompare(media_frame_rate, default_frame_rate)) {
|
||||
default_frame_rate = NAN;
|
||||
}
|
||||
if (!qIsNaN(current_frame_rate) && !qFuzzyCompare(media_frame_rate*c->speed, current_frame_rate)) {
|
||||
current_frame_rate = NAN;
|
||||
}
|
||||
} else {
|
||||
default_frame_rate = media_frame_rate;
|
||||
current_frame_rate = media_frame_rate*c->speed;
|
||||
}
|
||||
|
||||
enable_frame_rate = true;
|
||||
}
|
||||
}
|
||||
|
||||
// get default length
|
||||
@@ -145,21 +155,29 @@ void SpeedDialog::frame_rate_update() {
|
||||
}
|
||||
|
||||
void SpeedDialog::accept() {
|
||||
// TODO make undoable lmao
|
||||
for (int i=0;i<clips.size();i++) {
|
||||
Clip* c = clips.at(i);
|
||||
close_clip(c);
|
||||
if (c->track < 0) {
|
||||
if (!qIsNaN(frame_rate->value())) {
|
||||
// TODO add validators
|
||||
c->timeline_out = c->timeline_in + (c->getLength() * (c->frame_rate / frame_rate->value()));
|
||||
c->frame_rate = frame_rate->value();
|
||||
}
|
||||
} else {
|
||||
if (!qIsNaN(percent->value())) {
|
||||
c->timeline_out = c->timeline_in + (c->getLength() * (c->frame_rate / percent->value()));
|
||||
c->frame_rate = percent->value();
|
||||
long proposed_out = c->timeline_out;
|
||||
if (!qIsNaN(percent->value())) {
|
||||
double multiplier = (c->speed / percent->value());
|
||||
proposed_out = c->timeline_in + (c->getLength() * multiplier);
|
||||
c->clip_in *= multiplier;
|
||||
c->speed = percent->value();
|
||||
}
|
||||
if (proposed_out > c->timeline_out) {
|
||||
for (int i=0;i<c->sequence->clips.size();i++) {
|
||||
Clip* compare = c->sequence->clips.at(i);
|
||||
if (compare != NULL
|
||||
&& compare->track == c->track
|
||||
&& compare->timeline_in >= c->timeline_out && compare->timeline_in < proposed_out) {
|
||||
proposed_out = compare->timeline_in;
|
||||
}
|
||||
}
|
||||
}
|
||||
c->timeline_out = proposed_out;
|
||||
|
||||
c->recalculateMaxLength();
|
||||
}
|
||||
panel_timeline->redraw_all_clips(true);
|
||||
|
||||
+4
-4
@@ -756,7 +756,7 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
||||
|
||||
// backwards compatibility code
|
||||
c->autoscale = false;
|
||||
c->frame_rate = 0;
|
||||
c->speed = 1.0;
|
||||
|
||||
c->media = NULL;
|
||||
for (int j=0;j<stream.attributes().size();j++) {
|
||||
@@ -788,8 +788,8 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
||||
media_id = attr.value().toInt();
|
||||
} else if (attr.name() == "stream") {
|
||||
stream_id = attr.value().toInt();
|
||||
} else if (attr.name() == "framerate") {
|
||||
c->frame_rate = attr.value().toDouble();
|
||||
} else if (attr.name() == "speed") {
|
||||
c->speed = attr.value().toDouble();
|
||||
} else if (attr.name() == "sequence") {
|
||||
c->media_type = MEDIA_TYPE_SEQUENCE;
|
||||
|
||||
@@ -1089,7 +1089,7 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int
|
||||
|
||||
stream.writeAttribute("autoscale", QString::number(c->autoscale));
|
||||
|
||||
stream.writeAttribute("framerate", QString::number(c->frame_rate, 'f', 10));
|
||||
stream.writeAttribute("speed", QString::number(c->speed, 'f', 10));
|
||||
|
||||
stream.writeAttribute("type", QString::number(c->media_type));
|
||||
switch (c->media_type) {
|
||||
|
||||
+5
-14
@@ -110,19 +110,10 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
||||
|
||||
if (c->audio_just_reset) {
|
||||
// get precise sample offset for the elected clip_in from this audio frame
|
||||
double target_sts = 0;
|
||||
if (c->audio_target_frame < timeline_in) {
|
||||
target_sts = ((double) c->clip_in / c->sequence->frame_rate);
|
||||
} else {
|
||||
target_sts = playhead_to_seconds(c, c->audio_target_frame);
|
||||
}
|
||||
double target_sts = playhead_to_seconds(c, c->audio_target_frame);
|
||||
double frame_sts = (frame->pts * av_q2d(c->stream->time_base));
|
||||
int nb_samples = qRound((target_sts - frame_sts)*c->sequence->audio_frequency);
|
||||
if (nb_samples == 0) {
|
||||
c->frame_sample_index = 0;
|
||||
} else {
|
||||
c->frame_sample_index = av_samples_get_buffer_size(NULL, av_get_channel_layout_nb_channels(c->sequence->audio_layout), nb_samples, AV_SAMPLE_FMT_S16, 1);
|
||||
}
|
||||
c->frame_sample_index = (nb_samples == 0) ? 0 : av_samples_get_buffer_size(NULL, av_get_channel_layout_nb_channels(c->sequence->audio_layout), nb_samples, AV_SAMPLE_FMT_S16, 1);
|
||||
c->audio_just_reset = false;
|
||||
}
|
||||
|
||||
@@ -280,7 +271,7 @@ void cache_video_worker(Clip* c, long playhead, ClipCache* cache) {
|
||||
}
|
||||
|
||||
void reset_cache(Clip* c, long target_frame) {
|
||||
// if we seek to a whole other place in the timeline, we'll need to reset the cache with new values
|
||||
// if we seek to a whole other place in the timeline, we'll need to reset the cache with new values
|
||||
switch (c->media_type) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
{
|
||||
@@ -482,7 +473,7 @@ void open_clip_worker(Clip* clip) {
|
||||
NULL,
|
||||
sequence->audio_layout,
|
||||
static_cast<AVSampleFormat>(sample_format),
|
||||
sequence->audio_frequency,
|
||||
sequence->audio_frequency / clip->speed,
|
||||
clip->codecCtx->channel_layout,
|
||||
static_cast<AVSampleFormat>(clip->stream->codecpar->format),
|
||||
clip->stream->codecpar->sample_rate,
|
||||
@@ -497,7 +488,7 @@ void open_clip_worker(Clip* clip) {
|
||||
clip->cache_A.frames[0]->format = sample_format;
|
||||
clip->cache_A.frames[0]->channel_layout = sequence->audio_layout;
|
||||
clip->cache_A.frames[0]->channels = av_get_channel_layout_nb_channels(clip->cache_A.frames[0]->channel_layout);
|
||||
clip->cache_A.frames[0]->sample_rate = sequence->audio_frequency;
|
||||
clip->cache_A.frames[0]->sample_rate = sequence->audio_frequency / clip->speed;
|
||||
av_frame_make_writable(clip->cache_A.frames[0]);
|
||||
|
||||
clip->audio_reset = true;
|
||||
|
||||
@@ -110,7 +110,7 @@ bool get_clip_frame(Clip* c, long playhead) {
|
||||
MediaStream* ms = static_cast<Media*>(c->media)->get_stream_from_file_index(c->track < 0, c->media_stream);
|
||||
|
||||
long sequence_clip_time = playhead - c->timeline_in + c->clip_in;
|
||||
long clip_time = refactor_frame_number(sequence_clip_time, c->sequence->frame_rate, c->frame_rate);
|
||||
long clip_time = refactor_frame_number(sequence_clip_time, c->sequence->frame_rate, c->getMediaFrameRate()*c->speed);
|
||||
|
||||
AVFrame* current_frame = NULL;
|
||||
bool no_frame = false;
|
||||
@@ -213,7 +213,7 @@ bool get_clip_frame(Clip* c, long playhead) {
|
||||
|
||||
double playhead_to_seconds(Clip* c, long playhead) {
|
||||
// returns time in seconds
|
||||
return (qMax((long) 0, playhead - c->timeline_in) + c->clip_in)/c->sequence->frame_rate;
|
||||
return ((qMax(0L, playhead - c->timeline_in) + c->clip_in)/c->sequence->frame_rate)*c->speed;
|
||||
}
|
||||
|
||||
long seconds_to_clip_frame(Clip* c, double seconds) {
|
||||
|
||||
+4
-6
@@ -54,7 +54,7 @@ Clip* Clip::copy(Sequence* s) {
|
||||
copy->media_type = media_type;
|
||||
copy->media_stream = media_stream;
|
||||
copy->autoscale = autoscale;
|
||||
copy->frame_rate = frame_rate;
|
||||
copy->speed = speed;
|
||||
|
||||
for (int i=0;i<effects.size();i++) {
|
||||
copy->effects.append(effects.at(i)->copy(copy));
|
||||
@@ -63,6 +63,8 @@ Clip* Clip::copy(Sequence* s) {
|
||||
if (opening_transition != NULL) copy->opening_transition = opening_transition->copy();
|
||||
if (closing_transition != NULL) copy->closing_transition = closing_transition->copy();
|
||||
|
||||
copy->recalculateMaxLength();
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
@@ -173,11 +175,7 @@ long Clip::getLength() {
|
||||
void Clip::recalculateMaxLength() {
|
||||
double fr = this->sequence->frame_rate;
|
||||
|
||||
if (track < 0) {
|
||||
fr *= (getMediaFrameRate()/frame_rate);
|
||||
} else {
|
||||
fr /= frame_rate;
|
||||
}
|
||||
fr /= speed;
|
||||
|
||||
switch (media_type) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
|
||||
+3
-4
@@ -71,7 +71,7 @@ struct Clip
|
||||
int media_stream;
|
||||
int getWidth();
|
||||
int getHeight();
|
||||
double frame_rate;
|
||||
double speed;
|
||||
long calculated_length;
|
||||
|
||||
// other variables (should be "duplicated" in copy())
|
||||
@@ -110,15 +110,14 @@ struct Clip
|
||||
AVFilterContext* buffersink_ctx;
|
||||
AVFilterContext* buffersrc_ctx;
|
||||
|
||||
// video playback variables
|
||||
// SwsContext* sws_ctx;
|
||||
// video playback variables
|
||||
QOpenGLFramebufferObject** fbo;
|
||||
QOpenGLTexture* texture;
|
||||
long texture_frame;
|
||||
bool autoscale;
|
||||
|
||||
// audio playback variables
|
||||
// SwrContext* swr_ctx;
|
||||
SwrContext* swr_ctx;
|
||||
int frame_sample_index;
|
||||
int audio_buffer_write;
|
||||
bool audio_reset;
|
||||
|
||||
+14
-11
@@ -330,6 +330,7 @@ void TimelineWidget::dropEvent(QDropEvent* event) {
|
||||
c->timeline_out = g.out;
|
||||
c->clip_in = g.clip_in;
|
||||
c->track = g.track;
|
||||
c->speed = 1.0;
|
||||
if (c->media_type == MEDIA_TYPE_FOOTAGE) {
|
||||
Media* m = static_cast<Media*>(c->media);
|
||||
if (m->video_tracks.size() == 0) {
|
||||
@@ -347,8 +348,7 @@ void TimelineWidget::dropEvent(QDropEvent* event) {
|
||||
c->color_r = 128;
|
||||
c->color_g = 128;
|
||||
c->color_b = 192;
|
||||
}
|
||||
c->frame_rate = (c->track < 0) ? m->get_stream_from_file_index(true, c->media_stream)->video_frame_rate : 1.0;
|
||||
}
|
||||
c->name = m->name;
|
||||
} else if (c->media_type == MEDIA_TYPE_SEQUENCE) {
|
||||
// sequence (red?ish?)
|
||||
@@ -357,10 +357,9 @@ void TimelineWidget::dropEvent(QDropEvent* event) {
|
||||
c->color_b = 128;
|
||||
|
||||
Sequence* media = static_cast<Sequence*>(c->media);
|
||||
c->frame_rate = (c->track < 0) ? media->frame_rate : 1.0;
|
||||
c->name = media->name;
|
||||
}
|
||||
|
||||
c->recalculateMaxLength();
|
||||
added_clips.append(c);
|
||||
}
|
||||
|
||||
@@ -619,7 +618,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
c->color_b = 64;
|
||||
c->track = g.track;
|
||||
|
||||
c->frame_rate = (c->track < 0) ? sequence->frame_rate : 1.0;
|
||||
c->speed = 1.0;
|
||||
|
||||
QVector<Clip*> add;
|
||||
add.append(c);
|
||||
@@ -1734,7 +1733,7 @@ void TimelineWidget::redraw_clips() {
|
||||
int channel_height = clip_rect.height()/ms->audio_channels;
|
||||
|
||||
for (int i=0;i<waveform_limit;i++) {
|
||||
int waveform_index = qFloor((((clip->clip_in + ((double) (i*clip->frame_rate)/panel_timeline->zoom))/media_length) * ms->audio_preview.size())/divider)*divider;
|
||||
int waveform_index = qFloor((((clip->clip_in + ((double) i/panel_timeline->zoom))/media_length) * ms->audio_preview.size())/divider)*divider;
|
||||
|
||||
int rectified_height = 0;
|
||||
|
||||
@@ -1742,13 +1741,17 @@ void TimelineWidget::redraw_clips() {
|
||||
int mid = clip_rect.top()+channel_height*j+(channel_height/2);
|
||||
int offset = waveform_index+(j*2);
|
||||
|
||||
qint8 min = (double)ms->audio_preview.at(offset) / 128.0 * (channel_height/2);
|
||||
qint8 max = (double)ms->audio_preview.at(offset+1) / 128.0 * (channel_height/2);
|
||||
if ((offset + 1) < ms->audio_preview.size()) {
|
||||
qint8 min = (double)ms->audio_preview.at(offset) / 128.0 * (channel_height/2);
|
||||
qint8 max = (double)ms->audio_preview.at(offset+1) / 128.0 * (channel_height/2);
|
||||
|
||||
if (config.rectified_waveforms) {
|
||||
rectified_height += (max - min);
|
||||
if (config.rectified_waveforms) {
|
||||
rectified_height += (max - min);
|
||||
} else {
|
||||
clip_painter.drawLine(clip_rect.left()+i, mid+min, clip_rect.left()+i, mid+max);
|
||||
}
|
||||
} else {
|
||||
clip_painter.drawLine(clip_rect.left()+i, mid+min, clip_rect.left()+i, mid+max);
|
||||
qDebug() << "tried to reach" << offset + 1 << "limit:" << ms->audio_preview.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-14
@@ -180,12 +180,7 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
|
||||
|
||||
// if clip starts within one second and/or hasn't finished yet
|
||||
if (c != NULL && !(nest != NULL && !same_sign(c->track, nest->track))) {
|
||||
bool clip_is_active = false;
|
||||
|
||||
// backwards compatibilty
|
||||
if (c->frame_rate == 0 && c->track >= 0) {
|
||||
c->frame_rate = 1.0;
|
||||
}
|
||||
bool clip_is_active = false;
|
||||
|
||||
switch (c->media_type) {
|
||||
case MEDIA_TYPE_FOOTAGE:
|
||||
@@ -194,9 +189,6 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
|
||||
if (m->ready) {
|
||||
MediaStream* ms = m->get_stream_from_file_index(c->track < 0, c->media_stream);
|
||||
if (ms != NULL && is_clip_active(c, playhead)) {
|
||||
// backwards compatibility
|
||||
if (c->frame_rate == 0 && c->track < 0) c->frame_rate = ms->video_frame_rate;
|
||||
|
||||
// if thread is already working, we don't want to touch this,
|
||||
// but we also don't want to hang the UI thread
|
||||
if (!c->open) {
|
||||
@@ -212,13 +204,8 @@ GLuint ViewerWidget::compose_sequence(Clip* nest, bool render_audio) {
|
||||
}
|
||||
break;
|
||||
case MEDIA_TYPE_SEQUENCE:
|
||||
// backwards compatibility
|
||||
if (c->frame_rate == 0 == c->track < 0) c->frame_rate = static_cast<Sequence*>(c->media)->frame_rate;
|
||||
case MEDIA_TYPE_SOLID:
|
||||
case MEDIA_TYPE_TONE:
|
||||
// backwards compatibility
|
||||
if (c->frame_rate == 0 && c->track < 0) c->frame_rate = s->frame_rate;
|
||||
|
||||
if (is_clip_active(c, playhead)) {
|
||||
if (!c->open) open_clip(c, !rendering);
|
||||
clip_is_active = true;
|
||||
|
||||
Reference in New Issue
Block a user