merge of long discussed new pipeline
This commit is contained in:
+118
-84
@@ -1,20 +1,20 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
@@ -28,63 +28,67 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <QOpenGLFramebufferObject>
|
||||
#include <QtMath>
|
||||
#include <QAudioOutput>
|
||||
#include <QStatusBar>
|
||||
#include <math.h>
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "project/projectelements.h"
|
||||
#include "rendering/audio.h"
|
||||
#include "rendering/renderfunctions.h"
|
||||
#include "panels/panels.h"
|
||||
#include "global/timing.h"
|
||||
#include "global/config.h"
|
||||
#include "global/global.h"
|
||||
#include "global/debug.h"
|
||||
#include "ui/mainwindow.h"
|
||||
|
||||
// Enable verbose audio messages - good for debugging reversed audio
|
||||
//#define AUDIOWARNINGS
|
||||
|
||||
const AVPixelFormat kDestPixFmt = AV_PIX_FMT_RGBA;
|
||||
const AVSampleFormat kDestSampleFmt = AV_SAMPLE_FMT_S16;
|
||||
const AVSampleFormat kDestSampleFmt = AV_SAMPLE_FMT_FLTP;
|
||||
|
||||
double bytes_to_seconds(int nb_bytes, int nb_channels, int sample_rate) {
|
||||
return (double(nb_bytes >> 1) / nb_channels / sample_rate);
|
||||
double samples_to_seconds(int nb_samples, int nb_channels, int sample_rate) {
|
||||
return (double(nb_samples) / double(nb_channels) / double(sample_rate));
|
||||
}
|
||||
|
||||
void apply_audio_effects(Clip* clip, double timecode_start, AVFrame* frame, int nb_bytes, QVector<Clip*> nests) {
|
||||
int samples_to_bytes(int nb_samples, int nb_channels) {
|
||||
return nb_samples * nb_channels * sizeof(float);
|
||||
}
|
||||
|
||||
void apply_audio_effects(Clip* clip, double timecode_start, AVFrame* frame, int nb_samples, int nb_channels, QVector<Clip*> nests) {
|
||||
// perform all audio effects
|
||||
double timecode_end;
|
||||
timecode_end = timecode_start + bytes_to_seconds(nb_bytes, frame->channels, frame->sample_rate);
|
||||
timecode_end = timecode_start + samples_to_seconds(nb_samples, frame->channels, frame->sample_rate);
|
||||
|
||||
for (int j=0;j<clip->effects.size();j++) {
|
||||
Effect* e = clip->effects.at(j).get();
|
||||
Node* e = clip->effects.at(j).get();
|
||||
if (e->IsEnabled()) {
|
||||
e->process_audio(timecode_start, timecode_end, frame->data[0], nb_bytes, 2);
|
||||
e->process_audio(timecode_start, timecode_end, reinterpret_cast<float**>(frame->data), nb_samples, nb_channels, kTransitionNone);
|
||||
}
|
||||
}
|
||||
if (clip->opening_transition != nullptr) {
|
||||
if (clip->media() != nullptr && clip->media()->get_type() == MEDIA_TYPE_FOOTAGE) {
|
||||
double transition_start = (clip->clip_in(true) / clip->sequence->frame_rate);
|
||||
double transition_end = (clip->clip_in(true) + clip->opening_transition->get_length()) / clip->sequence->frame_rate;
|
||||
double transition_start = (clip->clip_in(true) / clip->track()->sequence()->frame_rate);
|
||||
double transition_end = (clip->clip_in(true) + clip->opening_transition->get_length()) / clip->track()->sequence()->frame_rate;
|
||||
if (timecode_end < transition_end) {
|
||||
double adjustment = transition_end - transition_start;
|
||||
double adjusted_range_start = (timecode_start - transition_start) / adjustment;
|
||||
double adjusted_range_end = (timecode_end - transition_start) / adjustment;
|
||||
clip->opening_transition->process_audio(adjusted_range_start, adjusted_range_end, frame->data[0], nb_bytes, kTransitionOpening);
|
||||
clip->opening_transition->process_audio(adjusted_range_start, adjusted_range_end, reinterpret_cast<float**>(frame->data), nb_samples, nb_channels, kTransitionOpening);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clip->closing_transition != nullptr) {
|
||||
if (clip->media() != nullptr && clip->media()->get_type() == MEDIA_TYPE_FOOTAGE) {
|
||||
long length_with_transitions = clip->timeline_out(true) - clip->timeline_in(true);
|
||||
double transition_start = (clip->clip_in(true) + length_with_transitions - clip->closing_transition->get_length()) / clip->sequence->frame_rate;
|
||||
double transition_end = (clip->clip_in(true) + length_with_transitions) / clip->sequence->frame_rate;
|
||||
double transition_start = (clip->clip_in(true) + length_with_transitions - clip->closing_transition->get_length()) / clip->track()->sequence()->frame_rate;
|
||||
double transition_end = (clip->clip_in(true) + length_with_transitions) / clip->track()->sequence()->frame_rate;
|
||||
if (timecode_start > transition_start) {
|
||||
double adjustment = transition_end - transition_start;
|
||||
double adjusted_range_start = (timecode_start - transition_start) / adjustment;
|
||||
double adjusted_range_end = (timecode_end - transition_start) / adjustment;
|
||||
clip->closing_transition->process_audio(adjusted_range_start, adjusted_range_end, frame->data[0], nb_bytes, kTransitionClosing);
|
||||
clip->closing_transition->process_audio(adjusted_range_start, adjusted_range_end, reinterpret_cast<float**>(frame->data), nb_samples, nb_channels, kTransitionClosing);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,9 +97,10 @@ void apply_audio_effects(Clip* clip, double timecode_start, AVFrame* frame, int
|
||||
Clip* next_nest = nests.last();
|
||||
nests.removeLast();
|
||||
apply_audio_effects(next_nest,
|
||||
timecode_start + (double(clip->timeline_in(true)-clip->clip_in(true))/clip->sequence->frame_rate),
|
||||
timecode_start + (double(clip->timeline_in(true)-clip->clip_in(true))/clip->track()->sequence()->frame_rate),
|
||||
frame,
|
||||
nb_bytes,
|
||||
nb_samples,
|
||||
nb_channels,
|
||||
nests);
|
||||
}
|
||||
}
|
||||
@@ -122,16 +127,16 @@ void Cacher::CacheAudioWorker() {
|
||||
bool reverse_audio = IsReversed();
|
||||
|
||||
long frame_skip = 0;
|
||||
double last_fr = clip->sequence->frame_rate;
|
||||
double last_fr = clip->track()->sequence()->frame_rate;
|
||||
if (!nests_.isEmpty()) {
|
||||
for (int i=nests_.size()-1;i>=0;i--) {
|
||||
timeline_in = rescale_frame_number(timeline_in, last_fr, nests_.at(i)->sequence->frame_rate) + nests_.at(i)->timeline_in(true) - nests_.at(i)->clip_in(true);
|
||||
timeline_out = rescale_frame_number(timeline_out, last_fr, nests_.at(i)->sequence->frame_rate) + nests_.at(i)->timeline_in(true) - nests_.at(i)->clip_in(true);
|
||||
target_frame = rescale_frame_number(target_frame, last_fr, nests_.at(i)->sequence->frame_rate) + nests_.at(i)->timeline_in(true) - nests_.at(i)->clip_in(true);
|
||||
timeline_in = rescale_frame_number(timeline_in, last_fr, nests_.at(i)->track()->sequence()->frame_rate) + nests_.at(i)->timeline_in(true) - nests_.at(i)->clip_in(true);
|
||||
timeline_out = rescale_frame_number(timeline_out, last_fr, nests_.at(i)->track()->sequence()->frame_rate) + nests_.at(i)->timeline_in(true) - nests_.at(i)->clip_in(true);
|
||||
target_frame = rescale_frame_number(target_frame, last_fr, nests_.at(i)->track()->sequence()->frame_rate) + nests_.at(i)->timeline_in(true) - nests_.at(i)->clip_in(true);
|
||||
|
||||
timeline_out = qMin(timeline_out, nests_.at(i)->timeline_out(true));
|
||||
|
||||
frame_skip = rescale_frame_number(frame_skip, last_fr, nests_.at(i)->sequence->frame_rate);
|
||||
frame_skip = rescale_frame_number(frame_skip, last_fr, nests_.at(i)->track()->sequence()->frame_rate);
|
||||
|
||||
long validator = nests_.at(i)->timeline_in(true) - timeline_in;
|
||||
if (validator > 0) {
|
||||
@@ -139,12 +144,13 @@ void Cacher::CacheAudioWorker() {
|
||||
//timeline_in = nests_.at(i)->timeline_in(true);
|
||||
}
|
||||
|
||||
last_fr = nests_.at(i)->sequence->frame_rate;
|
||||
last_fr = nests_.at(i)->track()->sequence()->frame_rate;
|
||||
}
|
||||
}
|
||||
|
||||
if (temp_reverse) {
|
||||
long seq_end = olive::ActiveSequence->getEndFrame();
|
||||
// FIXME breakable?
|
||||
long seq_end = Timeline::GetTopSequence()->GetEndFrame();
|
||||
timeline_in = seq_end - timeline_in;
|
||||
timeline_out = seq_end - timeline_out;
|
||||
target_frame = seq_end - target_frame;
|
||||
@@ -156,16 +162,16 @@ void Cacher::CacheAudioWorker() {
|
||||
|
||||
while (true) {
|
||||
AVFrame* frame;
|
||||
int nb_bytes = INT_MAX;
|
||||
int nb_samples = INT_MAX;
|
||||
|
||||
if (clip->media() == nullptr) {
|
||||
frame = frame_;
|
||||
nb_bytes = frame->nb_samples * av_get_bytes_per_sample(static_cast<AVSampleFormat>(frame->format)) * frame->channels;
|
||||
while ((frame_sample_index_ == -1 || frame_sample_index_ >= nb_bytes) && nb_bytes > 0) {
|
||||
nb_samples = frame->nb_samples;
|
||||
while ((frame_sample_index_ == -1 || frame_sample_index_ >= nb_samples) && nb_samples > 0) {
|
||||
// create "new frame"
|
||||
memset(frame_->data[0], 0, nb_bytes);
|
||||
apply_audio_effects(clip, bytes_to_seconds(frame->pts, frame->channels, frame->sample_rate), frame, nb_bytes, nests_);
|
||||
frame_->pts += nb_bytes;
|
||||
memset(frame_->data[0], 0, nb_samples);
|
||||
apply_audio_effects(clip, samples_to_seconds(frame->pts, frame->channels, frame->sample_rate), frame, nb_samples, frame->channels, nests_);
|
||||
frame_->pts += nb_samples;
|
||||
frame_sample_index_ = 0;
|
||||
if (audio_buffer_write == 0) {
|
||||
audio_buffer_write = get_buffer_offset_from_frame(last_fr, qMax(timeline_in, target_frame));
|
||||
@@ -183,7 +189,7 @@ void Cacher::CacheAudioWorker() {
|
||||
|
||||
// retrieve frame
|
||||
bool new_frame = false;
|
||||
while ((frame_sample_index_ == -1 || frame_sample_index_ >= nb_bytes) && nb_bytes > 0) {
|
||||
while ((frame_sample_index_ == -1 || frame_sample_index_ >= nb_samples) && nb_samples > 0) {
|
||||
|
||||
// no more audio left in frame, get a new one
|
||||
if (!reached_end) {
|
||||
@@ -337,10 +343,10 @@ void Cacher::CacheAudioWorker() {
|
||||
if (frame_sample_index_ < 0) {
|
||||
frame_sample_index_ = 0;
|
||||
} else {
|
||||
frame_sample_index_ -= nb_bytes;
|
||||
frame_sample_index_ -= nb_samples;
|
||||
}
|
||||
|
||||
nb_bytes = frame->nb_samples * av_get_bytes_per_sample(static_cast<AVSampleFormat>(frame->format)) * frame->channels;
|
||||
nb_samples = frame->nb_samples;
|
||||
|
||||
if (audio_just_reset) {
|
||||
// get precise sample offset for the elected clip_in from this audio frame
|
||||
@@ -355,7 +361,7 @@ void Cacher::CacheAudioWorker() {
|
||||
dout << "fsts:" << frame_sts << "tsts:" << target_sts << "nbs:" << nb_samples << "nbb:" << nb_bytes << "rev_targetToSec:" << (reverse_target * timebase);
|
||||
dout << "fsi-calc:" << frame_sample_index;
|
||||
#endif
|
||||
if (reverse_audio) frame_sample_index_ = nb_bytes - frame_sample_index_;
|
||||
if (reverse_audio) frame_sample_index_ = nb_samples - frame_sample_index_;
|
||||
audio_just_reset = false;
|
||||
}
|
||||
|
||||
@@ -392,9 +398,19 @@ void Cacher::CacheAudioWorker() {
|
||||
#endif
|
||||
|
||||
// apply any audio effects to the data
|
||||
if (nb_bytes == INT_MAX) nb_bytes = frame->nb_samples * av_get_bytes_per_sample(static_cast<AVSampleFormat>(frame->format)) * frame->channels;
|
||||
if (nb_samples == INT_MAX) {
|
||||
nb_samples = frame->nb_samples;
|
||||
}
|
||||
if (new_frame) {
|
||||
apply_audio_effects(clip, bytes_to_seconds(audio_buffer_write, 2, current_audio_freq()) + audio_ibuffer_timecode + ((double)clip->clip_in(true)/clip->sequence->frame_rate) - ((double)timeline_in/last_fr), frame, nb_bytes, nests_);
|
||||
apply_audio_effects(clip,
|
||||
samples_to_seconds(audio_buffer_write, 2, current_audio_freq())
|
||||
+ audio_ibuffer_timecode
|
||||
+ (double(clip->clip_in(true))/clip->track()->sequence()->frame_rate)
|
||||
- (double(timeline_in)/last_fr),
|
||||
frame,
|
||||
nb_samples,
|
||||
frame->channels,
|
||||
nests_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,30 +418,25 @@ void Cacher::CacheAudioWorker() {
|
||||
if (frame->nb_samples == 0) {
|
||||
break;
|
||||
} else {
|
||||
qint64 buffer_timeline_out = get_buffer_offset_from_frame(clip->sequence->frame_rate, timeline_out);
|
||||
qint64 buffer_timeline_out = get_buffer_offset_from_frame(clip->track()->sequence()->frame_rate, timeline_out);
|
||||
|
||||
audio_write_lock.lock();
|
||||
|
||||
int sample_skip = 4*qMax(0, qAbs(playback_speed_)-1);
|
||||
int sample_byte_size = av_get_bytes_per_sample(static_cast<AVSampleFormat>(frame->format));
|
||||
int sample_skip = qMax(0, qAbs(playback_speed_)-1);
|
||||
|
||||
while (frame_sample_index_ < nb_bytes
|
||||
while (frame_sample_index_ < nb_samples
|
||||
&& audio_buffer_write < audio_ibuffer_read+(audio_ibuffer_size>>1)
|
||||
&& audio_buffer_write < buffer_timeline_out) {
|
||||
for (int i=0;i<frame->channels;i++) {
|
||||
int upper_byte_index = (audio_buffer_write+1)%audio_ibuffer_size;
|
||||
int lower_byte_index = (audio_buffer_write)%audio_ibuffer_size;
|
||||
qint16 old_sample = static_cast<qint16>((audio_ibuffer[upper_byte_index] & 0xFF) << 8 | (audio_ibuffer[lower_byte_index] & 0xFF));
|
||||
qint16 new_sample = static_cast<qint16>((frame->data[0][frame_sample_index_+1] & 0xFF) << 8 | (frame->data[0][frame_sample_index_] & 0xFF));
|
||||
qint16 mixed_sample = mix_audio_sample(old_sample, new_sample);
|
||||
int buffer_index = audio_buffer_write%audio_ibuffer_size;
|
||||
|
||||
audio_ibuffer[upper_byte_index] = quint8((mixed_sample >> 8) & 0xFF);
|
||||
audio_ibuffer[lower_byte_index] = quint8(mixed_sample & 0xFF);
|
||||
audio_ibuffer[buffer_index] += reinterpret_cast<float*>(frame->data[i])[frame_sample_index_];
|
||||
|
||||
audio_buffer_write+=sample_byte_size;
|
||||
frame_sample_index_+=sample_byte_size;
|
||||
audio_buffer_write++;
|
||||
}
|
||||
|
||||
frame_sample_index_++;
|
||||
|
||||
frame_sample_index_ += sample_skip;
|
||||
|
||||
if (audio_reset_) break;
|
||||
@@ -443,7 +454,7 @@ void Cacher::CacheAudioWorker() {
|
||||
if (audio_thread != nullptr) audio_thread->notifyReceiver();
|
||||
}
|
||||
|
||||
if (frame_sample_index_ >= nb_bytes) {
|
||||
if (frame_sample_index_ >= nb_samples) {
|
||||
frame_sample_index_ = -1;
|
||||
} else {
|
||||
// assume we have no more data to send
|
||||
@@ -597,15 +608,15 @@ void Cacher::CacheVideoWorker() {
|
||||
// For reversed playback, we flip the queue stats as "upcoming" frames are going to be played before the "previous"
|
||||
// frames now
|
||||
if (reversed) {
|
||||
previous_queue_type = olive::CurrentConfig.upcoming_queue_type;
|
||||
previous_queue_size = olive::CurrentConfig.upcoming_queue_size;
|
||||
upcoming_queue_type = olive::CurrentConfig.previous_queue_type;
|
||||
upcoming_queue_size = olive::CurrentConfig.previous_queue_size;
|
||||
previous_queue_type = olive::config.upcoming_queue_type;
|
||||
previous_queue_size = olive::config.upcoming_queue_size;
|
||||
upcoming_queue_type = olive::config.previous_queue_type;
|
||||
upcoming_queue_size = olive::config.previous_queue_size;
|
||||
} else {
|
||||
previous_queue_type = olive::CurrentConfig.previous_queue_type;
|
||||
previous_queue_size = olive::CurrentConfig.previous_queue_size;
|
||||
upcoming_queue_type = olive::CurrentConfig.upcoming_queue_type;
|
||||
upcoming_queue_size = olive::CurrentConfig.upcoming_queue_size;
|
||||
previous_queue_type = olive::config.previous_queue_type;
|
||||
previous_queue_size = olive::config.previous_queue_size;
|
||||
upcoming_queue_type = olive::config.upcoming_queue_type;
|
||||
upcoming_queue_size = olive::config.upcoming_queue_size;
|
||||
}
|
||||
|
||||
// Determine "previous" queue statistics
|
||||
@@ -794,7 +805,7 @@ void Cacher::CacheVideoWorker() {
|
||||
void Cacher::Reset() {
|
||||
// if we seek to a whole other place in the timeline, we'll need to reset the cache with new values
|
||||
if (clip->media() == nullptr) {
|
||||
if (clip->track() >= 0) {
|
||||
if (clip->type() == olive::kTypeAudio) {
|
||||
// a null-media audio clip is usually an auto-generated sound clip such as Tone or Noise
|
||||
reached_end = false;
|
||||
audio_target_frame = playhead_;
|
||||
@@ -859,10 +870,8 @@ Cacher::Cacher(Clip* c) :
|
||||
{}
|
||||
|
||||
void Cacher::OpenWorker() {
|
||||
qint64 time_start = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
// set some defaults for the audio cacher
|
||||
if (clip->track() >= 0) {
|
||||
if (clip->type() == olive::kTypeAudio) {
|
||||
audio_reset_ = false;
|
||||
frame_sample_index_ = -1;
|
||||
audio_buffer_write = 0;
|
||||
@@ -870,10 +879,10 @@ void Cacher::OpenWorker() {
|
||||
reached_end = false;
|
||||
|
||||
if (clip->media() == nullptr) {
|
||||
if (clip->track() >= 0) {
|
||||
if (clip->type() == olive::kTypeAudio) {
|
||||
frame_ = av_frame_alloc();
|
||||
frame_->format = kDestSampleFmt;
|
||||
frame_->channel_layout = clip->sequence->audio_layout;
|
||||
frame_->channel_layout = clip->track()->sequence()->audio_layout;
|
||||
frame_->channels = av_get_channel_layout_nb_channels(frame_->channel_layout);
|
||||
frame_->sample_rate = current_audio_freq();
|
||||
frame_->nb_samples = 2048;
|
||||
@@ -891,7 +900,8 @@ void Cacher::OpenWorker() {
|
||||
QByteArray ba;
|
||||
|
||||
// do we have a proxy?
|
||||
if (m->proxy
|
||||
if ((!olive::Global->is_exporting() || !olive::config.dont_use_proxies_on_export)
|
||||
&& m->proxy
|
||||
&& !m->proxy_path.isEmpty()
|
||||
&& QFileInfo::exists(m->proxy_path)) {
|
||||
ba = m->proxy_path.toUtf8();
|
||||
@@ -989,7 +999,26 @@ void Cacher::OpenWorker() {
|
||||
last_filter = yadif_filter;
|
||||
}
|
||||
|
||||
const char* chosen_format = av_get_pix_fmt_name(kDestPixFmt);
|
||||
AVPixelFormat possible_pix_fmts[] = {
|
||||
AV_PIX_FMT_RGBA,
|
||||
AV_PIX_FMT_RGBA64,
|
||||
AV_PIX_FMT_NONE
|
||||
};
|
||||
|
||||
AVPixelFormat pix_fmt = avcodec_find_best_pix_fmt_of_list(possible_pix_fmts,
|
||||
static_cast<AVPixelFormat>(stream->codecpar->format),
|
||||
1,
|
||||
nullptr);
|
||||
|
||||
if (pix_fmt == AV_PIX_FMT_RGBA) {
|
||||
qDebug() << "This is an 8-bit image.";
|
||||
media_pixel_format_ = olive::PIX_FMT_RGBA8;
|
||||
} else {
|
||||
qDebug() << "This is an HDR image.";
|
||||
media_pixel_format_ = olive::PIX_FMT_RGBA16;
|
||||
}
|
||||
|
||||
const char* chosen_format = av_get_pix_fmt_name(pix_fmt);
|
||||
snprintf(filter_args, sizeof(filter_args), "pix_fmts=%s", chosen_format);
|
||||
|
||||
AVFilterContext* format_conv;
|
||||
@@ -1011,8 +1040,8 @@ void Cacher::OpenWorker() {
|
||||
|
||||
reverse_frame->format = kDestSampleFmt;
|
||||
reverse_frame->nb_samples = current_audio_freq()*10;
|
||||
reverse_frame->channel_layout = clip->sequence->audio_layout;
|
||||
reverse_frame->channels = av_get_channel_layout_nb_channels(clip->sequence->audio_layout);
|
||||
reverse_frame->channel_layout = clip->track()->sequence()->audio_layout;
|
||||
reverse_frame->channels = av_get_channel_layout_nb_channels(clip->track()->sequence()->audio_layout);
|
||||
av_frame_get_buffer(reverse_frame, 0);
|
||||
|
||||
queue_.append(reverse_frame);
|
||||
@@ -1092,13 +1121,13 @@ void Cacher::OpenWorker() {
|
||||
frame_ = av_frame_alloc();
|
||||
}
|
||||
|
||||
qInfo() << "Clip opened on track" << clip->track() << "(took" << (QDateTime::currentMSecsSinceEpoch() - time_start) << "ms)";
|
||||
qInfo() << "Clip opened on track" << clip->track();
|
||||
|
||||
is_valid_state_ = true;
|
||||
}
|
||||
|
||||
void Cacher::CacheWorker() {
|
||||
if (clip->track() < 0) {
|
||||
if (clip->type() == olive::kTypeVideo) {
|
||||
// clip is a video track, start caching video
|
||||
CacheVideoWorker();
|
||||
} else {
|
||||
@@ -1189,7 +1218,7 @@ void Cacher::Open()
|
||||
caching_ = true;
|
||||
queued_ = false;
|
||||
|
||||
start((clip->track() < 0) ? QThread::HighPriority : QThread::TimeCriticalPriority);
|
||||
start((clip->type() == olive::kTypeVideo) ? QThread::HighPriority : QThread::TimeCriticalPriority);
|
||||
}
|
||||
|
||||
void Cacher::Cache(long playhead, bool scrubbing, QVector<Clip*>& nests, int playback_speed)
|
||||
@@ -1338,6 +1367,11 @@ ClipQueue *Cacher::queue()
|
||||
return &queue_;
|
||||
}
|
||||
|
||||
const olive::PixelFormat &Cacher::media_pixel_format()
|
||||
{
|
||||
return media_pixel_format_;
|
||||
}
|
||||
|
||||
int Cacher::RetrieveFrameFromDecoder(AVFrame* f) {
|
||||
int result = 0;
|
||||
int receive_ret;
|
||||
|
||||
Reference in New Issue
Block a user