extremely limited speed support implemented #120
This commit is contained in:
+81
-14
@@ -6,36 +6,103 @@
|
|||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
#include "ui/labelslider.h"
|
#include "ui/labelslider.h"
|
||||||
|
#include "project/clip.h"
|
||||||
|
#include "project/sequence.h"
|
||||||
|
#include "io/media.h"
|
||||||
|
#include "playback/playback.h"
|
||||||
|
|
||||||
SpeedDialog::SpeedDialog(QWidget *parent) : QDialog(parent) {
|
SpeedDialog::SpeedDialog(QWidget *parent) : QDialog(parent) {
|
||||||
QGridLayout* layout = new QGridLayout();
|
QVBoxLayout* main_layout = new QVBoxLayout();
|
||||||
layout->setSpacing(6);
|
setLayout(main_layout);
|
||||||
layout->setMargin(9);
|
|
||||||
|
|
||||||
setLayout(layout);
|
QGridLayout* grid = new QGridLayout();
|
||||||
|
grid->setSpacing(6);
|
||||||
|
|
||||||
layout->addWidget(new QLabel("Speed:"), 0, 0);
|
grid->addWidget(new QLabel("Speed:"), 0, 0);
|
||||||
percent = new LabelSlider();
|
percent = new LabelSlider();
|
||||||
|
percent->decimal_places = 2;
|
||||||
percent->set_display_type(LABELSLIDER_PERCENT);
|
percent->set_display_type(LABELSLIDER_PERCENT);
|
||||||
layout->addWidget(percent, 0, 1);
|
grid->addWidget(percent, 0, 1);
|
||||||
|
|
||||||
layout->addWidget(new QLabel("Frame Rate:"), 1, 0);
|
grid->addWidget(new QLabel("Frame Rate:"), 1, 0);
|
||||||
frame_rate = new LabelSlider();
|
frame_rate = new LabelSlider();
|
||||||
layout->addWidget(frame_rate, 1, 1);
|
frame_rate->decimal_places = 3;
|
||||||
|
grid->addWidget(frame_rate, 1, 1);
|
||||||
|
|
||||||
layout->addWidget(new QLabel("Duration:"), 2, 0);
|
grid->addWidget(new QLabel("Duration:"), 2, 0);
|
||||||
duration = new LabelSlider();
|
duration = new LabelSlider();
|
||||||
duration->set_display_type(LABELSLIDER_FRAMENUMBER);
|
duration->set_display_type(LABELSLIDER_FRAMENUMBER);
|
||||||
layout->addWidget(duration, 2, 1);
|
grid->addWidget(duration, 2, 1);
|
||||||
|
|
||||||
|
main_layout->addLayout(grid);
|
||||||
|
|
||||||
QHBoxLayout* reverseLayout = new QHBoxLayout();
|
|
||||||
reverse = new QCheckBox("Reverse");
|
reverse = new QCheckBox("Reverse");
|
||||||
reverseLayout->addWidget(reverse);
|
main_layout->addWidget(reverse);
|
||||||
layout->addLayout(reverseLayout, 3, 0, 2, 1);
|
main_layout->addWidget(new QCheckBox("Maintain Audio Pitch"));
|
||||||
|
main_layout->addWidget(new QCheckBox("Ripple"));
|
||||||
|
|
||||||
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||||
layout->addWidget(buttonBox, 4, 0, 2, 1);
|
buttonBox->setCenterButtons(true);
|
||||||
|
main_layout->addWidget(buttonBox);
|
||||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||||
|
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||||
|
|
||||||
|
connect(percent, SIGNAL(valueChanged()), this, SLOT(percent_update()));
|
||||||
|
connect(frame_rate, SIGNAL(valueChanged()), this, SLOT(frame_rate_update()));
|
||||||
|
connect(duration, SIGNAL(valueChanged()), this, SLOT(duration_update()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpeedDialog::run() {
|
||||||
|
if (clips.size() > 1) {
|
||||||
|
qDebug() << "[WARNING] Setting multiple clip speeds at once is unsupported and may break things - sorry!";
|
||||||
|
}
|
||||||
|
|
||||||
|
normal_fr = 1;
|
||||||
|
|
||||||
|
Clip* first_clip = clips.at(0);
|
||||||
|
|
||||||
|
switch (first_clip->media_type) {
|
||||||
|
case MEDIA_TYPE_FOOTAGE:
|
||||||
|
normal_fr = static_cast<Media*>(first_clip->media)->get_stream_from_file_index(true, first_clip->media_stream)->video_frame_rate;
|
||||||
|
break;
|
||||||
|
case MEDIA_TYPE_SEQUENCE:
|
||||||
|
normal_fr = static_cast<Sequence*>(first_clip->media)->frame_rate;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
frame_rate->set_default_value(first_clip->frame_rate);
|
||||||
|
percent->set_default_value((first_clip->frame_rate / normal_fr) * 100);
|
||||||
|
duration->set_default_value(first_clip->getLength());
|
||||||
|
|
||||||
|
exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpeedDialog::percent_update() {
|
||||||
|
double pc = (percent->value()*0.01);
|
||||||
|
frame_rate->set_value(normal_fr * pc, false);
|
||||||
|
duration->set_value(clips.at(0)->getLength() / pc, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpeedDialog::duration_update() {
|
||||||
|
double pc = clips.at(0)->getLength() / duration->value();
|
||||||
|
frame_rate->set_value(normal_fr * pc, false);
|
||||||
|
percent->set_value(pc * 100, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpeedDialog::frame_rate_update() {
|
||||||
|
double fr = (frame_rate->value());
|
||||||
|
double pc = (fr / normal_fr);
|
||||||
|
percent->set_value(pc * 100, false);
|
||||||
|
duration->set_value(clips.at(0)->getLength() / pc, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpeedDialog::accept() {
|
||||||
|
for (int i=0;i<clips.size();i++) {
|
||||||
|
clips.at(i)->frame_rate = frame_rate->value();
|
||||||
|
close_clip(clips.at(i));
|
||||||
|
}
|
||||||
|
QDialog::accept();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,25 @@ class QCheckBox;
|
|||||||
|
|
||||||
class SpeedDialog : public QDialog
|
class SpeedDialog : public QDialog
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
SpeedDialog(QWidget* parent = 0);
|
SpeedDialog(QWidget* parent = 0);
|
||||||
QVector<Clip*> clips;
|
QVector<Clip*> clips;
|
||||||
|
|
||||||
|
void run();
|
||||||
|
private slots:
|
||||||
|
void percent_update();
|
||||||
|
void duration_update();
|
||||||
|
void frame_rate_update();
|
||||||
|
void accept();
|
||||||
private:
|
private:
|
||||||
LabelSlider* percent;
|
LabelSlider* percent;
|
||||||
LabelSlider* duration;
|
LabelSlider* duration;
|
||||||
LabelSlider* frame_rate;
|
LabelSlider* frame_rate;
|
||||||
|
|
||||||
QCheckBox* reverse;
|
QCheckBox* reverse;
|
||||||
|
|
||||||
|
double normal_fr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SPEEDDIALOG_H
|
#endif // SPEEDDIALOG_H
|
||||||
|
|||||||
@@ -46,12 +46,3 @@ MediaStream* Media::get_stream_from_file_index(bool video, int index) {
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int guess_layout_from_channels(int channel_count) {
|
|
||||||
if (channel_count == 1) {
|
|
||||||
return AV_CH_LAYOUT_MONO;
|
|
||||||
} else {
|
|
||||||
qDebug() << "[WARNING] Could not detect audio channel layout - assuming stereo";
|
|
||||||
return AV_CH_LAYOUT_STEREO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -50,6 +50,4 @@ struct Media {
|
|||||||
void reset();
|
void reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
int guess_layout_from_channels(int channel_count);
|
|
||||||
|
|
||||||
#endif // MEDIA_H
|
#endif // MEDIA_H
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ void PreviewGenerator::generate_waveform() {
|
|||||||
avcodec_open2(codec_ctx[i], codec, NULL);
|
avcodec_open2(codec_ctx[i], codec, NULL);
|
||||||
|
|
||||||
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && codec_ctx[i]->channel_layout == 0) {
|
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && codec_ctx[i]->channel_layout == 0) {
|
||||||
codec_ctx[i]->channel_layout = guess_layout_from_channels(fmt_ctx->streams[i]->codecpar->channels);
|
codec_ctx[i]->channel_layout = av_get_default_channel_layout(fmt_ctx->streams[i]->codecpar->channels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -300,7 +300,7 @@ void MainWindow::openSpeedDialog() {
|
|||||||
s.clips.append(c);
|
s.clips.append(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s.clips.size() > 0) s.exec();
|
if (s.clips.size() > 0) s.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-41
@@ -685,46 +685,7 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
|||||||
} else if (attr.name() == "duration") {
|
} else if (attr.name() == "duration") {
|
||||||
m->length = attr.value().toLongLong();
|
m->length = attr.value().toLongLong();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*while (!(stream.name() == child_search && stream.isEndElement())) {
|
|
||||||
stream.readNext();
|
|
||||||
if (stream.isStartElement()) {
|
|
||||||
if (stream.name() == "video") {
|
|
||||||
MediaStream* ms = new MediaStream();
|
|
||||||
for (int j=0;j<stream.attributes().size();j++) {
|
|
||||||
const QXmlStreamAttribute& attr = stream.attributes().at(j);
|
|
||||||
if (attr.name() == "id") {
|
|
||||||
ms->file_index = attr.value().toInt();
|
|
||||||
} else if (attr.name() == "width") {
|
|
||||||
ms->video_width = attr.value().toInt();
|
|
||||||
} else if (attr.name() == "height") {
|
|
||||||
ms->video_height = attr.value().toInt();
|
|
||||||
} else if (attr.name() == "framerate") {
|
|
||||||
ms->video_frame_rate = attr.value().toDouble();
|
|
||||||
} else if (attr.name() == "infinite") {
|
|
||||||
ms->infinite_length = (attr.value().toInt() == 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m->video_tracks.append(ms);
|
|
||||||
} else if (stream.name() == "audio") {
|
|
||||||
MediaStream* ms = new MediaStream();
|
|
||||||
for (int j=0;j<stream.attributes().size();j++) {
|
|
||||||
const QXmlStreamAttribute& attr = stream.attributes().at(j);
|
|
||||||
if (attr.name() == "id") {
|
|
||||||
ms->file_index = attr.value().toInt();
|
|
||||||
} else if (attr.name() == "channels") {
|
|
||||||
ms->audio_channels = attr.value().toInt();
|
|
||||||
} else if (attr.name() == "layout") {
|
|
||||||
ms->audio_layout = attr.value().toInt();
|
|
||||||
} else if (attr.name() == "frequency") {
|
|
||||||
ms->audio_frequency = attr.value().toInt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m->audio_tracks.append(ms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
set_footage_of_tree(item, m);
|
set_footage_of_tree(item, m);
|
||||||
|
|
||||||
@@ -794,7 +755,8 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
|||||||
Clip* c = new Clip(s);
|
Clip* c = new Clip(s);
|
||||||
|
|
||||||
// backwards compatibility code
|
// backwards compatibility code
|
||||||
c->autoscale = false;
|
c->autoscale = false;
|
||||||
|
c->frame_rate = 0;
|
||||||
|
|
||||||
c->media = NULL;
|
c->media = NULL;
|
||||||
for (int j=0;j<stream.attributes().size();j++) {
|
for (int j=0;j<stream.attributes().size();j++) {
|
||||||
@@ -826,6 +788,8 @@ bool Project::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
|
|||||||
media_id = attr.value().toInt();
|
media_id = attr.value().toInt();
|
||||||
} else if (attr.name() == "stream") {
|
} else if (attr.name() == "stream") {
|
||||||
stream_id = attr.value().toInt();
|
stream_id = attr.value().toInt();
|
||||||
|
} else if (attr.name() == "framerate") {
|
||||||
|
c->frame_rate = attr.value().toDouble();
|
||||||
} else if (attr.name() == "sequence") {
|
} else if (attr.name() == "sequence") {
|
||||||
c->media_type = MEDIA_TYPE_SEQUENCE;
|
c->media_type = MEDIA_TYPE_SEQUENCE;
|
||||||
|
|
||||||
@@ -1125,6 +1089,8 @@ void Project::save_folder(QXmlStreamWriter& stream, QTreeWidgetItem* parent, int
|
|||||||
|
|
||||||
stream.writeAttribute("autoscale", QString::number(c->autoscale));
|
stream.writeAttribute("autoscale", QString::number(c->autoscale));
|
||||||
|
|
||||||
|
stream.writeAttribute("framerate", QString::number(c->frame_rate));
|
||||||
|
|
||||||
stream.writeAttribute("type", QString::number(c->media_type));
|
stream.writeAttribute("type", QString::number(c->media_type));
|
||||||
switch (c->media_type) {
|
switch (c->media_type) {
|
||||||
case MEDIA_TYPE_FOOTAGE:
|
case MEDIA_TYPE_FOOTAGE:
|
||||||
|
|||||||
+21
-16
@@ -170,7 +170,6 @@ void cache_audio_worker(Clip* c, Clip* nest) {
|
|||||||
} else {
|
} else {
|
||||||
long buffer_timeline_out = get_buffer_offset_from_frame(timeline_out);
|
long buffer_timeline_out = get_buffer_offset_from_frame(timeline_out);
|
||||||
audio_write_lock.lock();
|
audio_write_lock.lock();
|
||||||
qDebug() << "starting to write:" << audio_ibuffer_read;
|
|
||||||
while (c->frame_sample_index < nb_bytes
|
while (c->frame_sample_index < nb_bytes
|
||||||
&& c->audio_buffer_write < audio_ibuffer_read+audio_ibuffer_size
|
&& c->audio_buffer_write < audio_ibuffer_read+audio_ibuffer_size
|
||||||
&& c->audio_buffer_write < buffer_timeline_out) {
|
&& c->audio_buffer_write < buffer_timeline_out) {
|
||||||
@@ -207,6 +206,8 @@ void cache_video_worker(Clip* c, long playhead, ClipCache* cache) {
|
|||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
double fr_ratio = qRound((c->sequence->frame_rate / c->frame_rate)*100)*0.01;
|
||||||
|
|
||||||
/* old swscale solution
|
/* old swscale solution
|
||||||
if (!c->reached_end) {
|
if (!c->reached_end) {
|
||||||
while (i < c->cache_size) {
|
while (i < c->cache_size) {
|
||||||
@@ -227,11 +228,19 @@ void cache_video_worker(Clip* c, long playhead, ClipCache* cache) {
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (ret == AVERROR(EAGAIN)) {
|
if (ret == AVERROR(EAGAIN)) {
|
||||||
ret = retrieve_next_frame(c, c->frame);
|
ret = retrieve_next_frame(c, c->frame);
|
||||||
|
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
if ((ret = av_buffersrc_add_frame_flags(c->buffersrc_ctx, c->frame, AV_BUFFERSRC_FLAG_KEEP_REF)) < 0) {
|
// optimization: mathematically determine based on the sequence and clips' frame rates whether this frame will actually be shown
|
||||||
qDebug() << "[ERROR] Could not feed filtergraph -" << ret;
|
double timeline_frame = (i+cache->offset) * fr_ratio;
|
||||||
error = true;
|
|
||||||
break;
|
if (qFloor(timeline_frame) == timeline_frame) {
|
||||||
|
if ((ret = av_buffersrc_add_frame_flags(c->buffersrc_ctx, c->frame, AV_BUFFERSRC_FLAG_KEEP_REF)) < 0) {
|
||||||
|
qDebug() << "[ERROR] Could not feed filtergraph -" << ret;
|
||||||
|
error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ret == AVERROR_EOF) {
|
if (ret == AVERROR_EOF) {
|
||||||
@@ -442,29 +451,25 @@ void open_clip_worker(Clip* clip) {
|
|||||||
clip->stream->codecpar->sample_aspect_ratio.den
|
clip->stream->codecpar->sample_aspect_ratio.den
|
||||||
);
|
);
|
||||||
|
|
||||||
char errormsg[100];
|
avfilter_graph_create_filter(&clip->buffersrc_ctx, avfilter_get_by_name("buffer"), "in", args, NULL, clip->filter_graph);
|
||||||
|
|
||||||
AVFilter* buffersrc = avfilter_get_by_name("buffer");
|
AVFilterContext* negate_ctx;
|
||||||
AVFilter* buffersink = avfilter_get_by_name("buffersink");
|
avfilter_graph_create_filter(&negate_ctx, avfilter_get_by_name("setpts"), "rev", "0.5*PTS", NULL, clip->filter_graph);
|
||||||
|
|
||||||
if (buffersrc == NULL || buffersink == NULL) {
|
avfilter_graph_create_filter(&clip->buffersink_ctx, avfilter_get_by_name("buffersink"), "out", NULL, NULL, clip->filter_graph);
|
||||||
qDebug() << "lol";
|
|
||||||
}
|
|
||||||
|
|
||||||
avfilter_graph_create_filter(&clip->buffersrc_ctx, buffersrc, "in", args, NULL, clip->filter_graph);
|
|
||||||
avfilter_graph_create_filter(&clip->buffersink_ctx, buffersink, "out", NULL, NULL, clip->filter_graph);
|
|
||||||
|
|
||||||
enum AVPixelFormat pix_fmts[] = { static_cast<AVPixelFormat>(dest_format), AV_PIX_FMT_NONE };
|
enum AVPixelFormat pix_fmts[] = { static_cast<AVPixelFormat>(dest_format), AV_PIX_FMT_NONE };
|
||||||
av_opt_set_int_list(clip->buffersink_ctx, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
|
av_opt_set_int_list(clip->buffersink_ctx, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN);
|
||||||
|
|
||||||
avfilter_link(clip->buffersrc_ctx, 0, clip->buffersink_ctx, 0);
|
avfilter_link(clip->buffersrc_ctx, 0, negate_ctx, 0);
|
||||||
|
avfilter_link(negate_ctx, 0, clip->buffersink_ctx, 0);
|
||||||
|
|
||||||
avfilter_graph_config(clip->filter_graph, NULL);
|
avfilter_graph_config(clip->filter_graph, NULL);
|
||||||
} else if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
} else if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||||
// if FFmpeg can't pick up the channel layout (usually WAV), assume
|
// if FFmpeg can't pick up the channel layout (usually WAV), assume
|
||||||
// based on channel count (doesn't support surround sound sources yet)
|
// based on channel count (doesn't support surround sound sources yet)
|
||||||
if (clip->codecCtx->channel_layout == 0) {
|
if (clip->codecCtx->channel_layout == 0) {
|
||||||
clip->codecCtx->channel_layout = guess_layout_from_channels(clip->stream->codecpar->channels);
|
clip->codecCtx->channel_layout = av_get_default_channel_layout(clip->stream->codecpar->channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
// init resampling context
|
// init resampling context
|
||||||
|
|||||||
@@ -114,8 +114,13 @@ bool get_clip_frame(Clip* c, long playhead) {
|
|||||||
// do we need to update the texture?
|
// do we need to update the texture?
|
||||||
MediaStream* ms = static_cast<Media*>(c->media)->get_stream_from_file_index(c->track < 0, c->media_stream);
|
MediaStream* ms = static_cast<Media*>(c->media)->get_stream_from_file_index(c->track < 0, c->media_stream);
|
||||||
|
|
||||||
|
// backwards compatibilty code
|
||||||
|
if (c->frame_rate == 0) {
|
||||||
|
c->frame_rate = ms->video_frame_rate;
|
||||||
|
}
|
||||||
|
|
||||||
long sequence_clip_time = playhead - c->timeline_in + c->clip_in;
|
long sequence_clip_time = playhead - c->timeline_in + c->clip_in;
|
||||||
long clip_time = refactor_frame_number(sequence_clip_time, c->sequence->frame_rate, ms->video_frame_rate);
|
long clip_time = refactor_frame_number(sequence_clip_time, c->sequence->frame_rate, c->frame_rate);
|
||||||
|
|
||||||
AVFrame* current_frame = NULL;
|
AVFrame* current_frame = NULL;
|
||||||
bool no_frame = false;
|
bool no_frame = false;
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ Clip* Clip::copy(Sequence* s) {
|
|||||||
copy->media_type = media_type;
|
copy->media_type = media_type;
|
||||||
copy->media_stream = media_stream;
|
copy->media_stream = media_stream;
|
||||||
copy->autoscale = autoscale;
|
copy->autoscale = autoscale;
|
||||||
|
copy->frame_rate = frame_rate;
|
||||||
|
|
||||||
for (int i=0;i<effects.size();i++) {
|
for (int i=0;i<effects.size();i++) {
|
||||||
copy->effects.append(effects.at(i)->copy(copy));
|
copy->effects.append(effects.at(i)->copy(copy));
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ struct Clip
|
|||||||
int media_stream;
|
int media_stream;
|
||||||
int getWidth();
|
int getWidth();
|
||||||
int getHeight();
|
int getHeight();
|
||||||
|
double frame_rate;
|
||||||
|
|
||||||
// other variables (should be "duplicated" in copy())
|
// other variables (should be "duplicated" in copy())
|
||||||
QList<Effect*> effects;
|
QList<Effect*> effects;
|
||||||
|
|||||||
+3
-2
@@ -21,6 +21,7 @@ LabelSlider::LabelSlider(QWidget* parent) : QLabel(parent) {
|
|||||||
set_value(0, false);
|
set_value(0, false);
|
||||||
set = false;
|
set = false;
|
||||||
display_type = LABELSLIDER_NORMAL;
|
display_type = LABELSLIDER_NORMAL;
|
||||||
|
decimal_places = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LabelSlider::set_display_type(int type) {
|
void LabelSlider::set_display_type(int type) {
|
||||||
@@ -54,9 +55,9 @@ bool LabelSlider::is_dragging() {
|
|||||||
QString LabelSlider::valueToString(double v) {
|
QString LabelSlider::valueToString(double v) {
|
||||||
switch (display_type) {
|
switch (display_type) {
|
||||||
case LABELSLIDER_FRAMENUMBER: return frame_to_timecode(v, config.timecode_view, sequence->frame_rate);
|
case LABELSLIDER_FRAMENUMBER: return frame_to_timecode(v, config.timecode_view, sequence->frame_rate);
|
||||||
case LABELSLIDER_PERCENT: return QString::number(v, 'f', 1) + "%";
|
case LABELSLIDER_PERCENT: return QString::number(v, 'f', decimal_places) + "%";
|
||||||
}
|
}
|
||||||
return QString::number(v, 'f', 1);
|
return QString::number(v, 'f', decimal_places);
|
||||||
}
|
}
|
||||||
|
|
||||||
double LabelSlider::getPreviousValue() {
|
double LabelSlider::getPreviousValue() {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ public:
|
|||||||
bool is_dragging();
|
bool is_dragging();
|
||||||
virtual QString valueToString(double v);
|
virtual QString valueToString(double v);
|
||||||
double getPreviousValue();
|
double getPreviousValue();
|
||||||
|
int decimal_places;
|
||||||
protected:
|
protected:
|
||||||
void mousePressEvent(QMouseEvent *ev);
|
void mousePressEvent(QMouseEvent *ev);
|
||||||
void mouseMoveEvent(QMouseEvent *ev);
|
void mouseMoveEvent(QMouseEvent *ev);
|
||||||
|
|||||||
+10
-4
@@ -329,6 +329,7 @@ void TimelineWidget::dropEvent(QDropEvent* event) {
|
|||||||
c->timeline_in = g.in;
|
c->timeline_in = g.in;
|
||||||
c->timeline_out = g.out;
|
c->timeline_out = g.out;
|
||||||
c->clip_in = g.clip_in;
|
c->clip_in = g.clip_in;
|
||||||
|
c->track = g.track;
|
||||||
if (c->media_type == MEDIA_TYPE_FOOTAGE) {
|
if (c->media_type == MEDIA_TYPE_FOOTAGE) {
|
||||||
Media* m = static_cast<Media*>(c->media);
|
Media* m = static_cast<Media*>(c->media);
|
||||||
if (m->video_tracks.size() == 0) {
|
if (m->video_tracks.size() == 0) {
|
||||||
@@ -347,6 +348,9 @@ void TimelineWidget::dropEvent(QDropEvent* event) {
|
|||||||
c->color_g = 128;
|
c->color_g = 128;
|
||||||
c->color_b = 192;
|
c->color_b = 192;
|
||||||
}
|
}
|
||||||
|
if (c->track < 0) {
|
||||||
|
c->frame_rate = m->get_stream_from_file_index(true, c->media_stream)->video_frame_rate;
|
||||||
|
}
|
||||||
c->name = m->name;
|
c->name = m->name;
|
||||||
} else if (c->media_type == MEDIA_TYPE_SEQUENCE) {
|
} else if (c->media_type == MEDIA_TYPE_SEQUENCE) {
|
||||||
// sequence (red?ish?)
|
// sequence (red?ish?)
|
||||||
@@ -354,11 +358,11 @@ void TimelineWidget::dropEvent(QDropEvent* event) {
|
|||||||
c->color_g = 128;
|
c->color_g = 128;
|
||||||
c->color_b = 128;
|
c->color_b = 128;
|
||||||
|
|
||||||
c->name = static_cast<Sequence*>(c->media)->name;
|
Sequence* media = static_cast<Sequence*>(c->media);
|
||||||
|
c->frame_rate = media->frame_rate;
|
||||||
|
c->name = media->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
c->track = g.track;
|
|
||||||
|
|
||||||
added_clips.append(c);
|
added_clips.append(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -617,11 +621,13 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
|||||||
c->color_b = 64;
|
c->color_b = 64;
|
||||||
c->track = g.track;
|
c->track = g.track;
|
||||||
|
|
||||||
|
if (c->track < 0) c->frame_rate = sequence->frame_rate;
|
||||||
|
|
||||||
QVector<Clip*> add;
|
QVector<Clip*> add;
|
||||||
add.append(c);
|
add.append(c);
|
||||||
ca->append(new AddClipCommand(sequence, add));
|
ca->append(new AddClipCommand(sequence, add));
|
||||||
|
|
||||||
int clipIndex = sequence->clips.size();
|
// int clipIndex = sequence->clips.size();
|
||||||
if (c->track < 0) {
|
if (c->track < 0) {
|
||||||
// default video effects (before custom effects)
|
// default video effects (before custom effects)
|
||||||
c->effects.append(create_effect(VIDEO_TRANSFORM_EFFECT, c));
|
c->effects.append(create_effect(VIDEO_TRANSFORM_EFFECT, c));
|
||||||
|
|||||||
Reference in New Issue
Block a user