From a3cb0d6cb9e4a8be8fffa0fb7e9dfeb43f7b2795 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Fri, 5 Oct 2018 01:32:34 +1000 Subject: [PATCH] mostly finished speed --- dialogs/speeddialog.cpp | 74 +++++++++++++++++++++++++---------------- panels/project.cpp | 8 ++--- playback/cacher.cpp | 19 +++-------- playback/playback.cpp | 4 +-- project/clip.cpp | 10 +++--- project/clip.h | 7 ++-- ui/timelinewidget.cpp | 25 ++++++++------ ui/viewerwidget.cpp | 15 +-------- 8 files changed, 79 insertions(+), 83 deletions(-) diff --git a/dialogs/speeddialog.cpp b/dialogs/speeddialog.cpp index aba335bed..b10aa2a7a 100644 --- a/dialogs/speeddialog.cpp +++ b/dialogs/speeddialog.cpp @@ -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(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;itrack < 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;isequence->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); diff --git a/panels/project.cpp b/panels/project.cpp index 29385bd8c..e363f3d3c 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -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;jframe_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) { diff --git a/playback/cacher.cpp b/playback/cacher.cpp index e6ee7088f..b2770a282 100644 --- a/playback/cacher.cpp +++ b/playback/cacher.cpp @@ -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(sample_format), - sequence->audio_frequency, + sequence->audio_frequency / clip->speed, clip->codecCtx->channel_layout, static_cast(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; diff --git a/playback/playback.cpp b/playback/playback.cpp index c87d5243e..6178f36d5 100644 --- a/playback/playback.cpp +++ b/playback/playback.cpp @@ -110,7 +110,7 @@ bool get_clip_frame(Clip* c, long playhead) { MediaStream* ms = static_cast(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) { diff --git a/project/clip.cpp b/project/clip.cpp index 72e06dddf..b4e332238 100644 --- a/project/clip.cpp +++ b/project/clip.cpp @@ -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;ieffects.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: diff --git a/project/clip.h b/project/clip.h index 15d26dfde..cb55b7f41 100644 --- a/project/clip.h +++ b/project/clip.h @@ -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; diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 7fdfe57dd..c70ae4517 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -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(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(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 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;iclip_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(); } } diff --git a/ui/viewerwidget.cpp b/ui/viewerwidget.cpp index 24984a5f7..021805ec7 100644 --- a/ui/viewerwidget.cpp +++ b/ui/viewerwidget.cpp @@ -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(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;