thumbnail/waveform generation
This commit is contained in:
+1
-1
@@ -10,7 +10,7 @@ class SourceTable : public QTreeWidget
|
||||
public:
|
||||
SourceTable(QWidget* parent = 0);
|
||||
protected:
|
||||
void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent *event);
|
||||
// void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
private:
|
||||
};
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ class TimelineHeader : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TimelineHeader(QWidget *parent = nullptr);
|
||||
explicit TimelineHeader(QWidget *parent = 0);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
|
||||
+55
-17
@@ -19,12 +19,13 @@
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
#include <QPointF>
|
||||
#include <QtMath>
|
||||
|
||||
TimelineWidget::TimelineWidget(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
bottom_align = false;
|
||||
setMouseTracking(true);
|
||||
track_height = 40;
|
||||
track_height = 80;
|
||||
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
@@ -54,13 +55,13 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
|
||||
g.clip_in = 0;
|
||||
for (int j=0;j<m->audio_tracks.size();j++) {
|
||||
g.track = j;
|
||||
g.media_stream = m->audio_tracks[j];
|
||||
g.media_stream = m->audio_tracks.at(j);
|
||||
ignore_infinite_length = true;
|
||||
panel_timeline->ghosts.append(g);
|
||||
}
|
||||
for (int j=0;j<m->video_tracks.size();j++) {
|
||||
g.track = -1-j;
|
||||
g.media_stream = m->video_tracks[j];
|
||||
g.media_stream = m->video_tracks.at(j);
|
||||
if (m->video_tracks[j]->infinite_length && !ignore_infinite_length) g.out = g.in + 100;
|
||||
panel_timeline->ghosts.append(g);
|
||||
}
|
||||
@@ -150,6 +151,10 @@ void TimelineWidget::dropEvent(QDropEvent* event) {
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::mouseDoubleClickEvent(QMouseEvent *event) {
|
||||
|
||||
}
|
||||
|
||||
void TimelineWidget::mousePressEvent(QMouseEvent *event) {
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_EDIT || panel_timeline->tool == TIMELINE_TOOL_RAZOR) {
|
||||
panel_timeline->drag_frame_start = panel_timeline->cursor_frame;
|
||||
@@ -200,6 +205,7 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) {
|
||||
case TIMELINE_TOOL_EDIT:
|
||||
panel_timeline->seek(panel_timeline->drag_frame_start);
|
||||
panel_timeline->selecting = true;
|
||||
|
||||
break;
|
||||
case TIMELINE_TOOL_RAZOR:
|
||||
{
|
||||
@@ -609,7 +615,8 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
panel_timeline->seek(qMin(panel_timeline->drag_frame_start, panel_timeline->cursor_frame));
|
||||
} else if (panel_timeline->moving_init) {
|
||||
if (panel_timeline->moving_proc) {
|
||||
update_ghosts((QPoint&) event->pos());
|
||||
QPoint pos = event->pos();
|
||||
update_ghosts(pos);
|
||||
} else {
|
||||
// set up movement
|
||||
// create ghosts
|
||||
@@ -702,26 +709,34 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
QPoint pos = event->pos();
|
||||
|
||||
int lim = 5;
|
||||
int mouse_track = getTrackFromScreenPoint(pos.y());
|
||||
int mouse_track = getTrackFromScreenPoint(pos.y());
|
||||
long mouse_frame_lower = panel_timeline->getFrameFromScreenPoint(pos.x()-lim)-1;
|
||||
long mouse_frame_upper = panel_timeline->getFrameFromScreenPoint(pos.x()+lim)+1;
|
||||
bool found = false;
|
||||
bool found = false;
|
||||
int closeness = INT_MAX;
|
||||
for (int i=0;i<sequence->clip_count();i++) {
|
||||
Clip* c = sequence->get_clip(i);
|
||||
if (c->track == mouse_track) {
|
||||
if (c->timeline_in > mouse_frame_lower && c->timeline_in < mouse_frame_upper) {
|
||||
panel_timeline->trim_target = i;
|
||||
panel_timeline->trim_in = true;
|
||||
found = true;
|
||||
break;
|
||||
} else if (c->timeline_out > mouse_frame_lower && c->timeline_out < mouse_frame_upper) {
|
||||
panel_timeline->trim_target = i;
|
||||
panel_timeline->trim_in = false;
|
||||
found = true;
|
||||
break;
|
||||
int nc = abs(c->timeline_in + 1 - panel_timeline->cursor_frame);
|
||||
if (nc < closeness) {
|
||||
panel_timeline->trim_target = i;
|
||||
panel_timeline->trim_in = true;
|
||||
closeness = nc;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (c->timeline_out > mouse_frame_lower && c->timeline_out < mouse_frame_upper) {
|
||||
int nc = abs(c->timeline_out - 1 - panel_timeline->cursor_frame);
|
||||
if (nc < closeness) {
|
||||
panel_timeline->trim_target = i;
|
||||
panel_timeline->trim_in = false;
|
||||
closeness = nc;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
setCursor(Qt::SizeHorCursor);
|
||||
} else {
|
||||
@@ -765,6 +780,29 @@ void TimelineWidget::redraw_clips() {
|
||||
|
||||
QRect clip_rect(panel_timeline->getScreenPointFromFrame(clip->timeline_in), getScreenPointFromTrack(clip->track), clip->getLength() * panel_timeline->zoom, track_height);
|
||||
clip_painter.fillRect(clip_rect, QColor(clip->color_r, clip->color_g, clip->color_b));
|
||||
|
||||
// draw thumbnail/waveform
|
||||
if (clip->media_stream->preview_lock.tryLock()) {
|
||||
if (clip->media_stream->preview_done) {
|
||||
if (clip->track < 0) {
|
||||
int thumb_y = clip_painter.fontMetrics().height()+CLIP_TEXT_PADDING+CLIP_TEXT_PADDING;
|
||||
int thumb_height = clip_rect.height()-thumb_y;
|
||||
if (thumb_height > thumb_y) { // at small clip heights, don't even draw it
|
||||
QRect thumb_rect(clip_rect.x(), clip_rect.y()+thumb_y, (thumb_height*((float)clip->media_stream->preview.width()/(float)clip->media_stream->preview.height())), thumb_height);
|
||||
clip_painter.drawImage(thumb_rect, clip->media_stream->preview);
|
||||
}
|
||||
} else {
|
||||
long length = clip->media->get_length_in_frames(clip->sequence->frame_rate);
|
||||
int waveform_x = ((float)clip->clip_in/(float)length) * clip->media_stream->preview.width();
|
||||
int waveform_width = (((float)clip->getLength()/(float)length) * clip->media_stream->preview.width());
|
||||
qDebug() << waveform_x << waveform_width;
|
||||
QRect source(waveform_x, 0, waveform_width, clip->media_stream->preview.height());
|
||||
clip_painter.drawImage(clip_rect, clip->media_stream->preview, source);
|
||||
}
|
||||
}
|
||||
clip->media_stream->preview_lock.unlock();
|
||||
}
|
||||
|
||||
clip_painter.setPen(Qt::white);
|
||||
clip_painter.drawLine(clip_rect.bottomLeft(), clip_rect.topLeft());
|
||||
clip_painter.drawLine(clip_rect.topLeft(), clip_rect.topRight());
|
||||
@@ -883,7 +921,7 @@ int TimelineWidget::getTrackFromScreenPoint(int y) {
|
||||
}
|
||||
int temp_track_height = track_height;
|
||||
if (show_track_lines) temp_track_height--;
|
||||
return (int)floor((float) (y)/ (float) temp_track_height);
|
||||
return (int)qFloor((float) (y)/ (float) temp_track_height);
|
||||
}
|
||||
|
||||
int TimelineWidget::getScreenPointFromTrack(int track) {
|
||||
|
||||
+2
-1
@@ -15,7 +15,7 @@ class TimelineWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TimelineWidget(QWidget *parent = nullptr);
|
||||
explicit TimelineWidget(QWidget *parent = 0);
|
||||
|
||||
bool bottom_align;
|
||||
|
||||
@@ -24,6 +24,7 @@ protected:
|
||||
void paintEvent(QPaintEvent*) override;
|
||||
void resizeEvent(QResizeEvent*) override;
|
||||
|
||||
void mouseDoubleClickEvent(QMouseEvent *event);
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
|
||||
@@ -7,7 +7,7 @@ class ViewerContainer : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ViewerContainer(QWidget *parent = nullptr);
|
||||
explicit ViewerContainer(QWidget *parent = 0);
|
||||
float aspect_ratio;
|
||||
QWidget* child;
|
||||
void adjust();
|
||||
|
||||
+54
-54
@@ -35,13 +35,13 @@ void ViewerWidget::retry() {
|
||||
}
|
||||
|
||||
void ViewerWidget::initializeGL() {
|
||||
initializeOpenGLFunctions();
|
||||
initializeOpenGLFunctions();
|
||||
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
//void ViewerWidget::resizeGL(int w, int h)
|
||||
@@ -54,63 +54,63 @@ void ViewerWidget::paintEvent(QPaintEvent *e) {
|
||||
|
||||
void ViewerWidget::paintGL()
|
||||
{
|
||||
if (multithreaded) retry_timer.stop();
|
||||
if (multithreaded) retry_timer.stop();
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
long playhead = panel_timeline->playhead;
|
||||
long playhead = panel_timeline->playhead;
|
||||
|
||||
handle_media(sequence, playhead, multithreaded);
|
||||
texture_failed = false;
|
||||
texture_failed = false;
|
||||
|
||||
bool render_audio = (panel_timeline->playing || force_audio);
|
||||
|
||||
cc_lock.lock();
|
||||
cc_lock.lock();
|
||||
|
||||
for (int i=0;i<current_clips.size();i++) {
|
||||
Clip* c = current_clips.at(i);
|
||||
for (int i=0;i<current_clips.size();i++) {
|
||||
Clip* c = current_clips.at(i);
|
||||
|
||||
if (!c->open) {
|
||||
qDebug() << "[WARNING] Tried to display clip" << i << "but it's closed";
|
||||
texture_failed = true;
|
||||
} else if (is_clip_active(c, playhead)) {
|
||||
if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
// start preparing cache
|
||||
get_clip_frame(c, playhead);
|
||||
if (!c->open) {
|
||||
qDebug() << "[WARNING] Tried to display clip" << i << "but it's closed";
|
||||
texture_failed = true;
|
||||
} else if (is_clip_active(c, playhead)) {
|
||||
if (c->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
// start preparing cache
|
||||
get_clip_frame(c, playhead);
|
||||
|
||||
if (c->texture == NULL) {
|
||||
qDebug() << "[WARNING] Texture hasn't been created yet";
|
||||
texture_failed = true;
|
||||
} else if (playhead >= c->timeline_in) {
|
||||
glLoadIdentity();
|
||||
int half_width = c->sequence->width/2;
|
||||
int half_height = c->sequence->height/2;
|
||||
glOrtho(-half_width, half_width, half_height,- half_height, -1, 1);
|
||||
if (c->texture == NULL) {
|
||||
qDebug() << "[WARNING] Texture hasn't been created yet";
|
||||
texture_failed = true;
|
||||
} else if (playhead >= c->timeline_in) {
|
||||
glLoadIdentity();
|
||||
int half_width = c->sequence->width/2;
|
||||
int half_height = c->sequence->height/2;
|
||||
glOrtho(-half_width, half_width, half_height,- half_height, -1, 1);
|
||||
int anchor_x = c->media_stream->video_width/2;
|
||||
int anchor_y = c->media_stream->video_height/2;
|
||||
|
||||
// perform all transform effects
|
||||
// perform all transform effects
|
||||
for (int j=0;j<c->effects.size();j++) {
|
||||
c->effects.at(j)->process_gl(&anchor_x, &anchor_y);
|
||||
}
|
||||
}
|
||||
|
||||
int anchor_right = c->media_stream->video_width - anchor_x;
|
||||
int anchor_bottom = c->media_stream->video_height - anchor_y;
|
||||
int anchor_right = c->media_stream->video_width - anchor_x;
|
||||
int anchor_bottom = c->media_stream->video_height - anchor_y;
|
||||
|
||||
c->texture->bind();
|
||||
c->texture->bind();
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 0.0);
|
||||
glVertex2f(-anchor_x, -anchor_y);
|
||||
glTexCoord2f(1.0, 0.0);
|
||||
glVertex2f(anchor_right, -anchor_y);
|
||||
glTexCoord2f(1.0, 1.0);
|
||||
glVertex2f(anchor_right, anchor_bottom);
|
||||
glTexCoord2f(0.0, 1.0);
|
||||
glVertex2f(-anchor_x, anchor_bottom);
|
||||
glEnd();
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0, 0.0);
|
||||
glVertex2f(-anchor_x, -anchor_y);
|
||||
glTexCoord2f(1.0, 0.0);
|
||||
glVertex2f(anchor_right, -anchor_y);
|
||||
glTexCoord2f(1.0, 1.0);
|
||||
glVertex2f(anchor_right, anchor_bottom);
|
||||
glTexCoord2f(0.0, 1.0);
|
||||
glVertex2f(-anchor_x, anchor_bottom);
|
||||
glEnd();
|
||||
|
||||
c->texture->release();
|
||||
c->texture->release();
|
||||
}
|
||||
} else if (render_audio &&
|
||||
c->stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
|
||||
@@ -119,8 +119,8 @@ void ViewerWidget::paintGL()
|
||||
// clip is not caching, start caching audio
|
||||
c->lock.unlock();
|
||||
cache_clip(c, playhead, false, false, c->reset_audio);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (panel_timeline->playing) {
|
||||
@@ -137,13 +137,13 @@ void ViewerWidget::paintGL()
|
||||
}
|
||||
}
|
||||
|
||||
cc_lock.unlock();
|
||||
cc_lock.unlock();
|
||||
|
||||
if (texture_failed) {
|
||||
if (multithreaded) {
|
||||
retry_timer.start();
|
||||
} else {
|
||||
paintGL();
|
||||
}
|
||||
}
|
||||
if (texture_failed) {
|
||||
if (multithreaded) {
|
||||
retry_timer.start();
|
||||
} else {
|
||||
paintGL();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -14,15 +14,15 @@ class ViewerWidget : public QOpenGLWidget, public QOpenGLFunctions
|
||||
Q_OBJECT
|
||||
public:
|
||||
ViewerWidget(QWidget *parent = 0);
|
||||
void initializeGL();
|
||||
// void resizeGL(int w, int h);
|
||||
void paintGL();
|
||||
|
||||
bool multithreaded;
|
||||
bool force_audio;
|
||||
bool enable_paint;
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void initializeGL() override;
|
||||
// void resizeGL(int w, int h);
|
||||
void paintGL() override;
|
||||
private:
|
||||
QTimer retry_timer;
|
||||
private slots:
|
||||
|
||||
Reference in New Issue
Block a user