From 33868a7481daef47668e234910ba295bd53671af Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 6 Jan 2019 11:33:25 +1100 Subject: [PATCH] backend for frame rate conform done --- panels/project.cpp | 38 ++-- panels/timeline.cpp | 2 +- panels/viewer.cpp | 2 +- playback/cacher.cpp | 25 +-- playback/playback.cpp | 4 +- project/footage.cpp | 66 +++---- project/footage.h | 57 +++--- project/media.cpp | 400 +++++++++++++++++++++--------------------- 8 files changed, 300 insertions(+), 294 deletions(-) diff --git a/panels/project.cpp b/panels/project.cpp index 9edfb2bc4..3c924b933 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -181,13 +181,13 @@ Sequence* create_sequence_from_media(QVector& media_list) { if (m->ready) { if (!got_video_values) { for (int j=0;jvideo_tracks.size();j++) { - const FootageStream& ms = m->video_tracks.at(j); - s->width = ms.video_width; - s->height = ms.video_height; - if (ms.video_frame_rate != 0) { - s->frame_rate = ms.video_frame_rate; + const FootageStream& ms = m->video_tracks.at(j); + s->width = ms.video_width; + s->height = ms.video_height; + if (ms.video_frame_rate != 0) { + s->frame_rate = ms.video_frame_rate * m->speed; - if (ms.video_interlacing != VIDEO_PROGRESSIVE) s->frame_rate *= 2; + if (ms.video_interlacing != VIDEO_PROGRESSIVE) s->frame_rate *= 2; // only break with a decent frame rate, otherwise there may be a better candidate got_video_values = true; @@ -197,8 +197,8 @@ Sequence* create_sequence_from_media(QVector& media_list) { } if (!got_audio_values) { for (int j=0;jaudio_tracks.size();j++) { - const FootageStream& ms = m->audio_tracks.at(j); - s->audio_frequency = ms.audio_frequency; + const FootageStream& ms = m->audio_tracks.at(j); + s->audio_frequency = ms.audio_frequency; got_audio_values = true; break; } @@ -853,22 +853,22 @@ void Project::save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, stream.writeAttribute("in", QString::number(f->in)); stream.writeAttribute("out", QString::number(f->out)); for (int j=0;jvideo_tracks.size();j++) { - const FootageStream& ms = f->video_tracks.at(j); + const FootageStream& ms = f->video_tracks.at(j); stream.writeStartElement("video"); - stream.writeAttribute("id", QString::number(ms.file_index)); - stream.writeAttribute("width", QString::number(ms.video_width)); - stream.writeAttribute("height", QString::number(ms.video_height)); - stream.writeAttribute("framerate", QString::number(ms.video_frame_rate, 'f', 10)); - stream.writeAttribute("infinite", QString::number(ms.infinite_length)); + stream.writeAttribute("id", QString::number(ms.file_index)); + stream.writeAttribute("width", QString::number(ms.video_width)); + stream.writeAttribute("height", QString::number(ms.video_height)); + stream.writeAttribute("framerate", QString::number(ms.video_frame_rate, 'f', 10)); + stream.writeAttribute("infinite", QString::number(ms.infinite_length)); stream.writeEndElement(); } for (int j=0;jaudio_tracks.size();j++) { - const FootageStream& ms = f->audio_tracks.at(j); + const FootageStream& ms = f->audio_tracks.at(j); stream.writeStartElement("audio"); - stream.writeAttribute("id", QString::number(ms.file_index)); - stream.writeAttribute("channels", QString::number(ms.audio_channels)); - stream.writeAttribute("layout", QString::number(ms.audio_layout)); - stream.writeAttribute("frequency", QString::number(ms.audio_frequency)); + stream.writeAttribute("id", QString::number(ms.file_index)); + stream.writeAttribute("channels", QString::number(ms.audio_channels)); + stream.writeAttribute("layout", QString::number(ms.audio_layout)); + stream.writeAttribute("frequency", QString::number(ms.audio_frequency)); stream.writeEndElement(); } stream.writeEndElement(); diff --git a/panels/timeline.cpp b/panels/timeline.cpp index 3326ac371..3ba55d0ef 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -178,7 +178,7 @@ void Timeline::create_ghosts_from_media(Sequence* seq, long entry_point, QVector can_import = m->ready; if (m->using_inout) { double source_fr = 30; - if (m->video_tracks.size() > 0 && !qIsNull(m->video_tracks.at(0).video_frame_rate)) source_fr = m->video_tracks.at(0).video_frame_rate; + if (m->video_tracks.size() > 0 && !qIsNull(m->video_tracks.at(0).video_frame_rate)) source_fr = m->video_tracks.at(0).video_frame_rate * m->speed; default_clip_in = refactor_frame_number(m->in, source_fr, seq->frame_rate); default_clip_out = refactor_frame_number(m->out, source_fr, seq->frame_rate); } diff --git a/panels/viewer.cpp b/panels/viewer.cpp index 37520ba62..65ff704c3 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -576,7 +576,7 @@ void Viewer::set_media(Media* m) { const FootageStream& video_stream = footage->video_tracks.at(0); seq->width = video_stream.video_width; seq->height = video_stream.video_height; - if (video_stream.video_frame_rate > 0 && !video_stream.infinite_length) seq->frame_rate = video_stream.video_frame_rate; + if (video_stream.video_frame_rate > 0 && !video_stream.infinite_length) seq->frame_rate = video_stream.video_frame_rate * footage->speed; Clip* c = new Clip(seq); c->media = media; diff --git a/playback/cacher.cpp b/playback/cacher.cpp index ef6687c9e..7df2ad948 100644 --- a/playback/cacher.cpp +++ b/playback/cacher.cpp @@ -247,7 +247,8 @@ void cache_audio_worker(Clip* c, bool scrubbing, QVector& nests) { #ifdef AUDIOWARNINGS dout << "pre cutoff deets::: rev_frame.pts:" << rev_frame->pts << "rev_frame.nb_samples" << rev_frame->nb_samples << "rev_target:" << c->reverse_target; #endif - rev_frame->nb_samples = qRound64(static_cast(c->reverse_target - rev_frame->pts) / c->stream->codecpar->sample_rate * (current_audio_freq() / c->speed)); + double playback_speed = c->speed * c->media->to_footage()->speed; + rev_frame->nb_samples = qRound64(static_cast(c->reverse_target - rev_frame->pts) / c->stream->codecpar->sample_rate * (current_audio_freq() / playback_speed)); #ifdef AUDIOWARNINGS dout << "post cutoff deets::" << rev_frame->nb_samples; #endif @@ -451,7 +452,7 @@ void cache_video_worker(Clip* c, long playhead) { AVFrame* frame = av_frame_alloc(); Footage* media = c->media->to_footage(); - const FootageStream* ms = media->get_stream_from_file_index(true, c->media_stream); + const FootageStream* ms = media->get_stream_from_file_index(true, c->media_stream); while ((retr_ret = av_buffersink_get_frame(c->buffersink_ctx, frame)) == AVERROR(EAGAIN)) { if (c->multithreaded && c->cacher->interrupt) return; // abort @@ -546,7 +547,7 @@ void reset_cache(Clip* c, long target_frame) { c->frame->pts = 0; } } else { - const FootageStream* ms = c->media->to_footage()->get_stream_from_file_index(c->track < 0, c->media_stream); + const FootageStream* ms = c->media->to_footage()->get_stream_from_file_index(c->track < 0, c->media_stream); if (ms->infinite_length) { /*avcodec_flush_buffers(c->codecCtx); av_seek_frame(c->formatCtx, ms->file_index, 0, AVSEEK_FLAG_BACKWARD);*/ @@ -640,7 +641,7 @@ void open_clip_worker(Clip* clip) { Footage* m = clip->media->to_footage(); QByteArray ba = m->url.toUtf8(); const char* filename = ba.constData(); - const FootageStream* ms = m->get_stream_from_file_index(clip->track < 0, clip->media_stream); + const FootageStream* ms = m->get_stream_from_file_index(clip->track < 0, clip->media_stream); int errCode = avformat_open_input( &clip->formatCtx, @@ -670,7 +671,7 @@ void open_clip_worker(Clip* clip) { clip->codecCtx = avcodec_alloc_context3(clip->codec); avcodec_parameters_to_context(clip->codecCtx, clip->stream->codecpar); - clip->max_queue_size = (ms->infinite_length) ? 1 : qCeil(ms->video_frame_rate*0.5); + clip->max_queue_size = (ms->infinite_length) ? 1 : qCeil(ms->video_frame_rate * m->speed * 0.5); if (ms->video_interlacing != VIDEO_PROGRESSIVE) clip->max_queue_size *= 2; clip->opts = NULL; @@ -797,7 +798,9 @@ void open_clip_worker(Clip* clip) { int target_sample_rate = current_audio_freq(); - if (qFuzzyCompare(clip->speed, 1.0)) { + double playback_speed = clip->speed * m->speed; + + if (qFuzzyCompare(playback_speed, 1.0)) { avfilter_link(clip->buffersrc_ctx, 0, clip->buffersink_ctx, 0); } else if (clip->maintain_audio_pitch) { AVFilterContext* previous_filter = clip->buffersrc_ctx; @@ -805,10 +808,10 @@ void open_clip_worker(Clip* clip) { char speed_param[10]; - if (clip->speed != 1.0) { - double base = (clip->speed > 1.0) ? 2.0 : 0.5; +// if (playback_speed != 1.0) { + double base = (playback_speed > 1.0) ? 2.0 : 0.5; - double speedlog = log(clip->speed) / log(base); + double speedlog = log(playback_speed) / log(base); int whole2 = qFloor(speedlog); speedlog -= whole2; @@ -826,11 +829,11 @@ void open_clip_worker(Clip* clip) { last_filter = NULL; avfilter_graph_create_filter(&last_filter, avfilter_get_by_name("atempo"), "atempo", speed_param, NULL, clip->filter_graph); avfilter_link(previous_filter, 0, last_filter, 0); - } +// } avfilter_link(last_filter, 0, clip->buffersink_ctx, 0); } else { - target_sample_rate = qRound64(target_sample_rate / clip->speed); + target_sample_rate = qRound64(target_sample_rate / playback_speed); avfilter_link(clip->buffersrc_ctx, 0, clip->buffersink_ctx, 0); } diff --git a/playback/playback.cpp b/playback/playback.cpp index dfb67461a..cd6c906d7 100644 --- a/playback/playback.cpp +++ b/playback/playback.cpp @@ -266,7 +266,9 @@ double playhead_to_clip_seconds(Clip* c, long playhead) { // returns time in seconds long clip_frame = playhead_to_clip_frame(c, playhead); if (c->reverse) clip_frame = c->getMaximumLength() - clip_frame - 1; - return ((double) clip_frame/c->sequence->frame_rate)*c->speed; + double secs = ((double) clip_frame/c->sequence->frame_rate)*c->speed; + if (c->media != NULL && c->media->get_type() == MEDIA_TYPE_FOOTAGE) secs *= c->media->to_footage()->speed; + return secs; } int64_t seconds_to_timestamp(Clip* c, double seconds) { diff --git a/project/footage.cpp b/project/footage.cpp index ec3a8baa1..e63d343f2 100644 --- a/project/footage.cpp +++ b/project/footage.cpp @@ -11,55 +11,55 @@ extern "C" { #include "project/clip.h" -Footage::Footage() : ready(false), preview_gen(NULL), invalid(false), in(0), out(0) { - ready_lock.lock(); +Footage::Footage() : ready(false), preview_gen(NULL), invalid(false), in(0), out(0), speed(1.0) { + ready_lock.lock(); } Footage::~Footage() { - reset(); + reset(); } void Footage::reset() { if (preview_gen != NULL) { preview_gen->cancel(); preview_gen->wait(); - } - video_tracks.clear(); - audio_tracks.clear(); - ready = false; + } + video_tracks.clear(); + audio_tracks.clear(); + ready = false; } long Footage::get_length_in_frames(double frame_rate) { - if (length >= 0) return qFloor(((double) length / (double) AV_TIME_BASE) * frame_rate); - return 0; + if (length >= 0) return qFloor(((double) length / (double) AV_TIME_BASE) * frame_rate / speed); + return 0; } FootageStream* Footage::get_stream_from_file_index(bool video, int index) { - if (video) { - for (int i=0;i>1; - int sqx = (diff < 0) ? -diff : 0; - int sqy = (diff > 0) ? diff : 0; - p.drawImage(sqx, sqy, video_preview); - video_preview_square = QIcon(pixmap); + // generate square version for QListView? + int square_size = qMax(video_preview.width(), video_preview.height()); + QPixmap pixmap(square_size, square_size); + pixmap.fill(Qt::transparent); + QPainter p(&pixmap); + int diff = (video_preview.width() - video_preview.height())>>1; + int sqx = (diff < 0) ? -diff : 0; + int sqy = (diff > 0) ? diff : 0; + p.drawImage(sqx, sqy, video_preview); + video_preview_square = QIcon(pixmap); } diff --git a/project/footage.h b/project/footage.h index effbced64..d6408857b 100644 --- a/project/footage.h +++ b/project/footage.h @@ -23,45 +23,46 @@ struct FootageStream { int video_width; int video_height; bool infinite_length; - double video_frame_rate; - int video_interlacing; + double video_frame_rate; + int video_interlacing; int video_auto_interlacing; - int audio_channels; - int audio_layout; - int audio_frequency; - bool enabled; + int audio_channels; + int audio_layout; + int audio_frequency; + bool enabled; - // preview thumbnail/waveform - bool preview_done; - QImage video_preview; - QIcon video_preview_square; + // preview thumbnail/waveform + bool preview_done; + QImage video_preview; + QIcon video_preview_square; QVector audio_preview; - void make_square_thumb(); + void make_square_thumb(); }; struct Footage { - Footage(); - ~Footage(); + Footage(); + ~Footage(); - QString url; - QString name; + QString url; + QString name; int64_t length; - QVector video_tracks; - QVector audio_tracks; - int save_id; - bool ready; - bool invalid; + QVector video_tracks; + QVector audio_tracks; + int save_id; + bool ready; + bool invalid; + double speed; - PreviewGenerator* preview_gen; - QMutex ready_lock; + PreviewGenerator* preview_gen; + QMutex ready_lock; - bool using_inout; - long in; - long out; + bool using_inout; + long in; + long out; - long get_length_in_frames(double frame_rate); - FootageStream *get_stream_from_file_index(bool video, int index); - void reset(); + long get_length_in_frames(double frame_rate); + FootageStream *get_stream_from_file_index(bool video, int index); + void reset(); }; #endif // FOOTAGE_H diff --git a/project/media.cpp b/project/media.cpp index bf72646cb..1ecb0cc8b 100644 --- a/project/media.cpp +++ b/project/media.cpp @@ -13,311 +13,311 @@ #include "debug.h" extern "C" { - #include - #include + #include + #include } QString get_interlacing_name(int interlacing) { - switch (interlacing) { - case VIDEO_PROGRESSIVE: return "None (Progressive)"; - case VIDEO_TOP_FIELD_FIRST: return "Top Field First"; - case VIDEO_BOTTOM_FIELD_FIRST: return "Bottom Field First"; - default: return "Invalid"; - } + switch (interlacing) { + case VIDEO_PROGRESSIVE: return "None (Progressive)"; + case VIDEO_TOP_FIELD_FIRST: return "Top Field First"; + case VIDEO_BOTTOM_FIELD_FIRST: return "Bottom Field First"; + default: return "Invalid"; + } } QString get_channel_layout_name(int channels, uint64_t layout) { - switch (channels) { - case 0: return "Invalid"; break; - case 1: return "Mono"; break; - case 2: return "Stereo"; break; - default: { - char buf[50]; - av_get_channel_layout_string(buf, sizeof(buf), channels, layout); - return QString(buf); - } - } + switch (channels) { + case 0: return "Invalid"; break; + case 1: return "Mono"; break; + case 2: return "Stereo"; break; + default: { + char buf[50]; + av_get_channel_layout_string(buf, sizeof(buf), channels, layout); + return QString(buf); + } + } } Media::Media(Media* iparent) : - parent(iparent), - throbber(NULL), - root(false), - type(-1) + parent(iparent), + throbber(NULL), + root(false), + type(-1) {} Media::~Media() { - switch (get_type()) { - case MEDIA_TYPE_FOOTAGE: delete to_footage(); break; - case MEDIA_TYPE_SEQUENCE: if (object != NULL) delete to_sequence(); break; - } - if (throbber != NULL) delete throbber; - qDeleteAll(children); + switch (get_type()) { + case MEDIA_TYPE_FOOTAGE: delete to_footage(); break; + case MEDIA_TYPE_SEQUENCE: if (object != NULL) delete to_sequence(); break; + } + if (throbber != NULL) delete throbber; + qDeleteAll(children); } Footage *Media::to_footage() { - return static_cast(object); + return static_cast(object); } Sequence *Media::to_sequence() { - return static_cast(object); + return static_cast(object); } void Media::set_footage(Footage *f) { - type = MEDIA_TYPE_FOOTAGE; - object = f; + type = MEDIA_TYPE_FOOTAGE; + object = f; } void Media::set_sequence(Sequence *s) { - set_icon(QIcon(":/icons/sequence.png")); - type = MEDIA_TYPE_SEQUENCE; - object = s; - if (s != NULL) update_tooltip(); + set_icon(QIcon(":/icons/sequence.png")); + type = MEDIA_TYPE_SEQUENCE; + object = s; + if (s != NULL) update_tooltip(); } void Media::set_folder() { - if (folder_name.isEmpty()) folder_name = "New Folder"; - set_icon(QIcon(":/icons/folder.png")); - type = MEDIA_TYPE_FOLDER; - object = NULL; + if (folder_name.isEmpty()) folder_name = "New Folder"; + set_icon(QIcon(":/icons/folder.png")); + type = MEDIA_TYPE_FOLDER; + object = NULL; } void Media::set_icon(const QIcon &ico) { - icon = ico; + icon = ico; } void Media::set_parent(Media *p) { - parent = p; + parent = p; } void Media::update_tooltip(const QString& error) { - switch (type) { - case MEDIA_TYPE_FOOTAGE: - { - Footage* f = to_footage(); - tooltip = "Name: " + f->name + "\nFilename: " + f->url + "\n"; + switch (type) { + case MEDIA_TYPE_FOOTAGE: + { + Footage* f = to_footage(); + tooltip = "Name: " + f->name + "\nFilename: " + f->url + "\n"; - if (error.isEmpty()) { - if (f->video_tracks.size() > 0) { - tooltip += "Video Dimensions: "; - for (int i=0;ivideo_tracks.size();i++) { - if (i > 0) { - tooltip += ", "; - } - tooltip += QString::number(f->video_tracks.at(i).video_width) + "x" + QString::number(f->video_tracks.at(i).video_height); - } - tooltip += "\n"; + if (error.isEmpty()) { + if (f->video_tracks.size() > 0) { + tooltip += "Video Dimensions: "; + for (int i=0;ivideo_tracks.size();i++) { + if (i > 0) { + tooltip += ", "; + } + tooltip += QString::number(f->video_tracks.at(i).video_width) + "x" + QString::number(f->video_tracks.at(i).video_height); + } + tooltip += "\n"; - if (!f->video_tracks.at(0).infinite_length) { - tooltip += "Frame Rate: "; - for (int i=0;ivideo_tracks.size();i++) { - if (i > 0) { - tooltip += ", "; - } - if (f->video_tracks.at(i).video_interlacing == VIDEO_PROGRESSIVE) { - tooltip += QString::number(f->video_tracks.at(i).video_frame_rate); - } else { - tooltip += QString::number(f->video_tracks.at(i).video_frame_rate * 2); - tooltip += " fields (" + QString::number(f->video_tracks.at(i).video_frame_rate) + " frames)"; - } - } - tooltip += "\n"; - } + if (!f->video_tracks.at(0).infinite_length) { + tooltip += "Frame Rate: "; + for (int i=0;ivideo_tracks.size();i++) { + if (i > 0) { + tooltip += ", "; + } + if (f->video_tracks.at(i).video_interlacing == VIDEO_PROGRESSIVE) { + tooltip += QString::number(f->video_tracks.at(i).video_frame_rate * f->speed); + } else { + tooltip += QString::number(f->video_tracks.at(i).video_frame_rate * f->speed * 2); + tooltip += " fields (" + QString::number(f->video_tracks.at(i).video_frame_rate * f->speed) + " frames)"; + } + } + tooltip += "\n"; + } - tooltip += "Interlacing: "; - for (int i=0;ivideo_tracks.size();i++) { - if (i > 0) { - tooltip += ", "; - } - tooltip += get_interlacing_name(f->video_tracks.at(i).video_interlacing); - } - } + tooltip += "Interlacing: "; + for (int i=0;ivideo_tracks.size();i++) { + if (i > 0) { + tooltip += ", "; + } + tooltip += get_interlacing_name(f->video_tracks.at(i).video_interlacing); + } + } - if (f->audio_tracks.size() > 0) { - tooltip += "\n"; + if (f->audio_tracks.size() > 0) { + tooltip += "\n"; - tooltip += "Audio Frequency: "; - for (int i=0;iaudio_tracks.size();i++) { - if (i > 0) { - tooltip += ", "; - } - tooltip += QString::number(f->audio_tracks.at(i).audio_frequency); - } - tooltip += "\n"; + tooltip += "Audio Frequency: "; + for (int i=0;iaudio_tracks.size();i++) { + if (i > 0) { + tooltip += ", "; + } + tooltip += QString::number(f->audio_tracks.at(i).audio_frequency * f->speed); + } + tooltip += "\n"; - tooltip += "Audio Channels: "; - for (int i=0;iaudio_tracks.size();i++) { - if (i > 0) { - tooltip += ", "; - } - tooltip += get_channel_layout_name(f->audio_tracks.at(i).audio_channels, f->audio_tracks.at(i).audio_layout); - } - // tooltip += "\n"; - } - } else { - tooltip += error; - } - } - break; - case MEDIA_TYPE_SEQUENCE: - { - Sequence* s = to_sequence(); - tooltip = "Name: " + s->name - + "\nVideo Dimensions: " + QString::number(s->width) + "x" + QString::number(s->height) - + "\nFrame Rate: " + QString::number(s->frame_rate) - + "\nAudio Frequency: " + QString::number(s->audio_frequency) - + "\nAudio Layout: " + get_channel_layout_name(av_get_channel_layout_nb_channels(s->audio_layout), s->audio_layout); - } - break; - } + tooltip += "Audio Channels: "; + for (int i=0;iaudio_tracks.size();i++) { + if (i > 0) { + tooltip += ", "; + } + tooltip += get_channel_layout_name(f->audio_tracks.at(i).audio_channels, f->audio_tracks.at(i).audio_layout); + } + // tooltip += "\n"; + } + } else { + tooltip += error; + } + } + break; + case MEDIA_TYPE_SEQUENCE: + { + Sequence* s = to_sequence(); + tooltip = "Name: " + s->name + + "\nVideo Dimensions: " + QString::number(s->width) + "x" + QString::number(s->height) + + "\nFrame Rate: " + QString::number(s->frame_rate) + + "\nAudio Frequency: " + QString::number(s->audio_frequency) + + "\nAudio Layout: " + get_channel_layout_name(av_get_channel_layout_nb_channels(s->audio_layout), s->audio_layout); + } + break; + } } void *Media::to_object() { - return object; + return object; } int Media::get_type() { - return type; + return type; } const QString &Media::get_name() { - switch (type) { - case MEDIA_TYPE_FOOTAGE: return to_footage()->name; - case MEDIA_TYPE_SEQUENCE: return to_sequence()->name; + switch (type) { + case MEDIA_TYPE_FOOTAGE: return to_footage()->name; + case MEDIA_TYPE_SEQUENCE: return to_sequence()->name; default: return folder_name; } } void Media::set_name(const QString &n) { - switch (type) { - case MEDIA_TYPE_FOOTAGE: to_footage()->name = n; break; - case MEDIA_TYPE_SEQUENCE: to_sequence()->name = n; break; - case MEDIA_TYPE_FOLDER: folder_name = n; break; - } + switch (type) { + case MEDIA_TYPE_FOOTAGE: to_footage()->name = n; break; + case MEDIA_TYPE_SEQUENCE: to_sequence()->name = n; break; + case MEDIA_TYPE_FOLDER: folder_name = n; break; + } } double Media::get_frame_rate(int stream) { - switch (get_type()) { + switch (get_type()) { case MEDIA_TYPE_FOOTAGE: { Footage* f = to_footage(); - if (stream < 0) return f->video_tracks.at(0).video_frame_rate; - return f->get_stream_from_file_index(true, stream)->video_frame_rate; + if (stream < 0) return f->video_tracks.at(0).video_frame_rate * f->speed; + return f->get_stream_from_file_index(true, stream)->video_frame_rate * f->speed; + } + case MEDIA_TYPE_SEQUENCE: return to_sequence()->frame_rate; } - case MEDIA_TYPE_SEQUENCE: return to_sequence()->frame_rate; - } return NULL; } int Media::get_sampling_rate(int stream) { - switch (get_type()) { + switch (get_type()) { case MEDIA_TYPE_FOOTAGE: { Footage* f = to_footage(); - if (stream < 0) return f->audio_tracks.at(0).audio_frequency; - return to_footage()->get_stream_from_file_index(false, stream)->audio_frequency; + if (stream < 0) return f->audio_tracks.at(0).audio_frequency * f->speed; + return to_footage()->get_stream_from_file_index(false, stream)->audio_frequency * f->speed; } - case MEDIA_TYPE_SEQUENCE: return to_sequence()->audio_frequency; - } - return 0; + case MEDIA_TYPE_SEQUENCE: return to_sequence()->audio_frequency; + } + return 0; } void Media::appendChild(Media *child) { - child->set_parent(this); - children.append(child); + child->set_parent(this); + children.append(child); } bool Media::setData(int col, const QVariant &value) { - if (col == 0) { - QString n = value.toString(); - if (!n.isEmpty() && get_name() != n) { - undo_stack.push(new MediaRename(this, value.toString())); - return true; - } - } - return false; + if (col == 0) { + QString n = value.toString(); + if (!n.isEmpty() && get_name() != n) { + undo_stack.push(new MediaRename(this, value.toString())); + return true; + } + } + return false; } Media *Media::child(int row) { - return children.value(row); + return children.value(row); } int Media::childCount() const { - return children.count(); + return children.count(); } int Media::columnCount() const { - return 3; + return 3; } QVariant Media::data(int column, int role) { - switch (role) { - case Qt::DecorationRole: - if (column == 0) { - if (get_type() == MEDIA_TYPE_FOOTAGE) { - Footage* f = to_footage(); - if (f->video_tracks.size() > 0 - && f->video_tracks.at(0).preview_done) { - return f->video_tracks.at(0).video_preview_square; - } - } + switch (role) { + case Qt::DecorationRole: + if (column == 0) { + if (get_type() == MEDIA_TYPE_FOOTAGE) { + Footage* f = to_footage(); + if (f->video_tracks.size() > 0 + && f->video_tracks.at(0).preview_done) { + return f->video_tracks.at(0).video_preview_square; + } + } - return icon; - } - break; - case Qt::DisplayRole: - switch (column) { - case 0: return (root) ? "Name" : get_name(); - case 1: - if (root) return "Duration"; - if (get_type() == MEDIA_TYPE_SEQUENCE) { - Sequence* s = to_sequence(); - return frame_to_timecode(s->getEndFrame(), config.timecode_view, s->frame_rate); - } - if (get_type() == MEDIA_TYPE_FOOTAGE) { - Footage* f = to_footage(); - double r = 30; + return icon; + } + break; + case Qt::DisplayRole: + switch (column) { + case 0: return (root) ? "Name" : get_name(); + case 1: + if (root) return "Duration"; + if (get_type() == MEDIA_TYPE_SEQUENCE) { + Sequence* s = to_sequence(); + return frame_to_timecode(s->getEndFrame(), config.timecode_view, s->frame_rate); + } + if (get_type() == MEDIA_TYPE_FOOTAGE) { + Footage* f = to_footage(); + double r = 30; - if (f->video_tracks.size() > 0 && !qIsNull(f->video_tracks.at(0).video_frame_rate)) - r = f->video_tracks.at(0).video_frame_rate; + if (f->video_tracks.size() > 0 && !qIsNull(f->video_tracks.at(0).video_frame_rate)) + r = f->video_tracks.at(0).video_frame_rate * f->speed; long len = f->get_length_in_frames(r); if (len > 0) return frame_to_timecode(len, config.timecode_view, r); - } - break; - case 2: - if (root) return "Rate"; - if (get_type() == MEDIA_TYPE_SEQUENCE) return QString::number(get_frame_rate()) + " FPS"; - if (get_type() == MEDIA_TYPE_FOOTAGE) { - Footage* f = to_footage(); + } + break; + case 2: + if (root) return "Rate"; + if (get_type() == MEDIA_TYPE_SEQUENCE) return QString::number(get_frame_rate()) + " FPS"; + if (get_type() == MEDIA_TYPE_FOOTAGE) { + Footage* f = to_footage(); double r; if (f->video_tracks.size() > 0 && !qIsNull(r = get_frame_rate())) { return QString::number(get_frame_rate()) + " FPS"; - } else if (f->audio_tracks.size() > 0) { - return QString::number(get_sampling_rate()) + " Hz"; - } - } - break; - } - break; - case Qt::ToolTipRole: - return tooltip; - } - return QVariant(); + } else if (f->audio_tracks.size() > 0) { + return QString::number(get_sampling_rate()) + " Hz"; + } + } + break; + } + break; + case Qt::ToolTipRole: + return tooltip; + } + return QVariant(); } int Media::row() const { - if (parent) { - return parent->children.indexOf(const_cast(this)); - } - return 0; + if (parent) { + return parent->children.indexOf(const_cast(this)); + } + return 0; } Media *Media::parentItem() { - return parent; + return parent; } void Media::removeChild(int i) { - children.removeAt(i); + children.removeAt(i); }