improved timeline drawing with transitions

This commit is contained in:
itsmattkc
2018-08-10 12:55:02 +10:00
parent 9c8b7ac21a
commit d4825761dd
3 changed files with 58 additions and 44 deletions
+1
View File
@@ -24,6 +24,7 @@ Transition* create_transition(int transition_id, Clip* c) {
}
} else {
switch (transition_id) {
case AUDIO_LINEAR_FADE_TRANSITION: return new CrossDissolveTransition();
}
}
qDebug() << "[ERROR] Invalid transition ID";
+13 -5
View File
@@ -25,6 +25,9 @@ void apply_audio_effects(Clip* c, AVFrame* frame, int nb_bytes) {
Effect* e = c->effects.at(j);
if (e->is_enabled()) e->process_audio(frame->data[0], nb_bytes);
}
if (c->opening_transition != NULL) {
}
}
void cache_audio_worker(Clip* c, Clip* nest) {
@@ -38,6 +41,12 @@ void cache_audio_worker(Clip* c, Clip* nest) {
timeline_out = refactor_frame_number(timeline_out, c->sequence->frame_rate, sequence->frame_rate) + nest->timeline_in;
}
//
// (c->clip_in / c->sequence->frame_rate) is the starting point in seconds
// we need to convert it to bytes
//
//
while (written < max_write) {
// gets one frame worth of audio and sends it to the audio buffer
AVFrame* frame = c->cache_A.frames[0];
@@ -48,9 +57,7 @@ void cache_audio_worker(Clip* c, Clip* nest) {
retrieve_next_frame_raw_data(c, frame);
int byte_count = av_samples_get_buffer_size(NULL, frame->channels, frame->nb_samples, static_cast<AVSampleFormat>(frame->format), 1);
apply_audio_effects(c, frame, byte_count);
if (nest != NULL) {
apply_audio_effects(nest, frame, byte_count);
}
if (nest != NULL) apply_audio_effects(nest, frame, byte_count);
} else {
// set by retrieve_next_frame_raw_data indicating no more frames in file,
// but there still may be samples in swresample
@@ -60,13 +67,13 @@ void cache_audio_worker(Clip* c, Clip* nest) {
c->need_new_audio_frame = false;
if (c->audio_just_reset) {
// get precise sample offset for the elected clip_in from this audio frame
float target_sts = 0;
double target_sts = 0;
if (c->audio_target_frame < timeline_in) {
target_sts = clip_frame_to_seconds(c, c->clip_in);
} else {
target_sts = playhead_to_seconds(c, c->audio_target_frame);
}
float frame_sts = (frame->pts * av_q2d(c->stream->time_base));
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;
@@ -87,6 +94,7 @@ void cache_audio_worker(Clip* c, Clip* nest) {
int half_buffer = (audio_ibuffer_size/2);
if (c->audio_buffer_write == 0) {
c->audio_buffer_write = get_buffer_offset_from_frame(qMax(timeline_in, c->audio_target_frame));
int offset = audio_ibuffer_read - c->audio_buffer_write;
if (offset > 0) {
c->audio_buffer_write += offset;
+44 -39
View File
@@ -1588,44 +1588,6 @@ void TimelineWidget::redraw_clips() {
QRect text_rect(clip_rect.left() + CLIP_TEXT_PADDING, clip_rect.top() + CLIP_TEXT_PADDING, clip_rect.width() - CLIP_TEXT_PADDING - 1, clip_rect.height() - CLIP_TEXT_PADDING - 1);
// draw clip transitions
for (int i=0;i<2;i++) {
Transition* t = (i == 0) ? clip->opening_transition : clip->closing_transition;
if (t != NULL) {
int transition_width = panel_timeline->getScreenPointFromFrame(t->length);
int transition_height = clip_rect.height() * 0.6;
if (transition_height <= TRACK_MIN_HEIGHT) {
transition_height = clip_rect.height();
}
int tr_y = clip_rect.y() + ((clip_rect.height()-transition_height)/2);
int tr_x = 0;
if (i == 0) {
tr_x = clip_rect.x();
text_rect.setX(text_rect.x()+transition_width);
thumb_x += transition_width;
} else {
tr_x = clip_rect.right()-transition_width;
text_rect.setWidth(text_rect.width()-transition_width);
}
QRect transition_rect = QRect(tr_x, tr_y, transition_width, transition_height);
clip_painter.fillRect(transition_rect, transition_color);
QRect transition_text_rect(transition_rect.x() + CLIP_TEXT_PADDING, transition_rect.y() + CLIP_TEXT_PADDING, transition_rect.width() - CLIP_TEXT_PADDING, transition_rect.height() - CLIP_TEXT_PADDING);
if (transition_text_rect.width() > MAX_TEXT_WIDTH) {
clip_painter.setPen(QColor(0, 0, 0, 96));
if (i == 0) {
clip_painter.drawLine(transition_rect.bottomLeft(), transition_rect.topRight());
} else {
clip_painter.drawLine(transition_rect.topLeft(), transition_rect.bottomRight());
}
clip_painter.setPen(Qt::white);
clip_painter.drawText(transition_text_rect, 0, t->name, &transition_text_rect);
}
clip_painter.setPen(Qt::black);
clip_painter.drawRect(transition_rect);
}
}
if (clip->media_type == MEDIA_TYPE_FOOTAGE) {
bool draw_checkerboard = false;
QRect checkerboard_rect = clip_rect;
@@ -1644,10 +1606,19 @@ void TimelineWidget::redraw_clips() {
}
if (clip->track < 0) {
int space_for_thumb = clip_rect.width();
if (clip->opening_transition != NULL) {
int ot_width = panel_timeline->getScreenPointFromFrame(clip->opening_transition->length);
thumb_x += ot_width;
space_for_thumb -= ot_width;
}
if (clip->closing_transition != NULL) {
space_for_thumb -= panel_timeline->getScreenPointFromFrame(clip->closing_transition->length);
}
int thumb_y = clip_painter.fontMetrics().height()+CLIP_TEXT_PADDING+CLIP_TEXT_PADDING;
int thumb_height = clip_rect.height()-thumb_y;
int thumb_width = (thumb_height*((double)ms->video_preview.width()/(double)ms->video_preview.height()));
if (thumb_height > thumb_y && text_rect.width() + CLIP_TEXT_PADDING > thumb_width) { // at small clip heights, don't even draw it
if (thumb_height > thumb_y && text_rect.width() + CLIP_TEXT_PADDING > thumb_width && space_for_thumb >= thumb_width) { // at small clip heights, don't even draw it
QRect thumb_rect(thumb_x, clip_rect.y()+thumb_y, thumb_width, thumb_height);
clip_painter.drawImage(thumb_rect, ms->video_preview);
}
@@ -1705,6 +1676,40 @@ void TimelineWidget::redraw_clips() {
}
}
// draw clip transitions
for (int i=0;i<2;i++) {
Transition* t = (i == 0) ? clip->opening_transition : clip->closing_transition;
if (t != NULL) {
int transition_width = panel_timeline->getScreenPointFromFrame(t->length);
int transition_height = clip_rect.height();
int tr_y = clip_rect.y();
int tr_x = 0;
if (i == 0) {
tr_x = clip_rect.x();
text_rect.setX(text_rect.x()+transition_width);
} else {
tr_x = clip_rect.right()-transition_width;
text_rect.setWidth(text_rect.width()-transition_width);
}
QRect transition_rect = QRect(tr_x, tr_y, transition_width, transition_height);
clip_painter.fillRect(transition_rect, transition_color);
QRect transition_text_rect(transition_rect.x() + CLIP_TEXT_PADDING, transition_rect.y() + CLIP_TEXT_PADDING, transition_rect.width() - CLIP_TEXT_PADDING, transition_rect.height() - CLIP_TEXT_PADDING);
if (transition_text_rect.width() > MAX_TEXT_WIDTH) {
clip_painter.setPen(QColor(0, 0, 0, 96));
if (i == 0) {
clip_painter.drawLine(transition_rect.bottomLeft(), transition_rect.topRight());
} else {
clip_painter.drawLine(transition_rect.topLeft(), transition_rect.bottomRight());
}
clip_painter.setPen(Qt::white);
clip_painter.drawText(transition_text_rect, 0, t->name, &transition_text_rect);
}
clip_painter.setPen(Qt::black);
clip_painter.drawRect(transition_rect);
}
}
// top left bevel
clip_painter.setPen(Qt::white);
clip_painter.drawLine(clip_rect.bottomLeft(), clip_rect.topLeft());