This commit is contained in:
itsmattkc
2019-03-20 13:35:49 +11:00
parent afa1271134
commit 1bd4b110fd
6 changed files with 82 additions and 37 deletions
+67 -32
View File
@@ -117,7 +117,7 @@ void Cacher::CacheAudioWorker() {
long target_frame = audio_target_frame;
bool temp_reverse = (playback_speed_ < 0);
bool reverse_audio = (clip->reversed() != temp_reverse);
bool reverse_audio = IsReversed();
long frame_skip = 0;
double last_fr = clip->sequence->frame_rate;
@@ -462,6 +462,12 @@ void Cacher::CacheAudioWorker() {
QMetaObject::invokeMethod(panel_sequence_viewer, "play_wake", Qt::QueuedConnection);
}
bool Cacher::IsReversed()
{
// Here, the Clip reverse and reversed playback speed cancel each other out to produce normal playback
return (clip->reversed() != playback_speed_ < 0);
}
void Cacher::CacheVideoWorker() {
// is this media a still image?
@@ -496,6 +502,9 @@ void Cacher::CacheVideoWorker() {
// main thread waits until cacher starts fully, wake it up here
WakeMainThread();
// determine if this media is reversed, which will affect how the queue is constructed
bool reversed = IsReversed();
// get the timestamp we want in terms of the media's timebase
int64_t target_pts = seconds_to_timestamp(clip, playhead_to_clip_seconds(clip, playhead_));
@@ -573,39 +582,55 @@ void Cacher::CacheVideoWorker() {
// for FRAME_QUEUE_TYPE_FRAMES, this is used to store the maximum number of frames that can be added
int64_t minimum_ts;
if (olive::CurrentConfig.previous_queue_type == olive::FRAME_QUEUE_TYPE_FRAMES) {
// get the maximum number of previous frames that can be in the queue
minimum_ts = qCeil(olive::CurrentConfig.previous_queue_size);
} else {
// get the minimum frame timestamp that can be added to the queue
minimum_ts = target_pts - seconds_to_timestamp(clip, olive::CurrentConfig.previous_queue_size);
}
// check if we can add more frames to this queue or not
// for FRAME_QUEUE_TYPE_SECONDS, this is used to store the maximum timestamp
// for FRAME_QUEUE_TYPE_FRAMES, this is used to store the maximum number of frames that can be added
int64_t maximum_ts;
bool start_loop = true;
// Get queue configuration
int previous_queue_type, upcoming_queue_type;
double previous_queue_size, upcoming_queue_size;
if (olive::CurrentConfig.upcoming_queue_type == olive::FRAME_QUEUE_TYPE_FRAMES) {
maximum_ts = qCeil(olive::CurrentConfig.upcoming_queue_size);
// 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;
} 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;
}
// if we already have the maximum number of upcoming frames, don't bother running the below loop at all
if (frames_greater_than_target >= maximum_ts) {
start_loop = false;
}
// Determine "previous" queue statistics
if (previous_queue_type == olive::FRAME_QUEUE_TYPE_FRAMES) {
// get the maximum number of previous frames that can be in the queue
minimum_ts = qCeil(previous_queue_size);
} else {
// get the minimum frame timestamp that can be added to the queue
minimum_ts = qRound(target_pts - second_pts * previous_queue_size);
}
// Determine "upcoming" queue statistics
if (upcoming_queue_type == olive::FRAME_QUEUE_TYPE_FRAMES) {
maximum_ts = qCeil(upcoming_queue_size);
} else {
// get the maximum frame timestamp that can be added to the queue
maximum_ts = target_pts + seconds_to_timestamp(clip, olive::CurrentConfig.upcoming_queue_size);
// if the latest frame is already past the maximum queue seconds
if (latest_pts > maximum_ts) {
start_loop = false;
}
maximum_ts = qRound(target_pts + second_pts * upcoming_queue_size);
}
// if we already have the maximum number of upcoming frames, don't bother running the retrieving any frames at all
bool start_loop = true;
if ((upcoming_queue_type == olive::FRAME_QUEUE_TYPE_FRAMES && frames_greater_than_target >= maximum_ts)
|| (upcoming_queue_type == olive::FRAME_QUEUE_TYPE_SECONDS && latest_pts > maximum_ts)) {
start_loop = false;
}
if (start_loop) {
interrupt_ = false;
@@ -631,7 +656,7 @@ void Cacher::CacheVideoWorker() {
} else if (decoded_frame->pts != AV_NOPTS_VALUE) {
// check if this frame exceeds the minimum timestamp
if (olive::CurrentConfig.previous_queue_type == olive::FRAME_QUEUE_TYPE_SECONDS
if (previous_queue_type == olive::FRAME_QUEUE_TYPE_SECONDS
&& decoded_frame->pts < minimum_ts) {
// if so, we don't need it
@@ -641,16 +666,26 @@ void Cacher::CacheVideoWorker() {
if (retrieved_frame == nullptr) {
if (decoded_frame->pts == target_pts) {
SetRetrievedFrame(decoded_frame);
} else if (seeked_to_zero) {
// If this flag is set, it means this was somehow the earliest frame we could get for this timestamp
// We retrieved the exact frame we're looking for
SetRetrievedFrame(decoded_frame);
seeked_to_zero = false;
} else if (decoded_frame->pts > target_pts) {
if (queue_.size() > 0) {
SetRetrievedFrame(queue_.last());
} else if (seeked_to_zero) {
// If this flag is set but we still got a frame after the target timestamp, it means this was somehow
// the earliest frame we could get
SetRetrievedFrame(decoded_frame);
seeked_to_zero = false;
}
} else if (decoded_frame->pts > target_pts
&& queue_.size() > 0) {
SetRetrievedFrame(queue_.last());
}
}
@@ -661,7 +696,7 @@ void Cacher::CacheVideoWorker() {
// check the amount of previous frames in the queue by using the current queue size for if we need to
// remove any old entries (assumes the queue is chronological)
if (olive::CurrentConfig.previous_queue_type == olive::FRAME_QUEUE_TYPE_FRAMES) {
if (previous_queue_type == olive::FRAME_QUEUE_TYPE_FRAMES) {
int previous_frame_count = 0;
@@ -693,7 +728,7 @@ void Cacher::CacheVideoWorker() {
}
// check if the queue is full according to olive::CurrentConfig
if (olive::CurrentConfig.upcoming_queue_type == olive::FRAME_QUEUE_TYPE_FRAMES) {
if (upcoming_queue_type == olive::FRAME_QUEUE_TYPE_FRAMES) {
// if this frame is later than the target, it's an "upcoming" frame
if (decoded_frame->pts > target_pts) {
+5
View File
@@ -570,6 +570,11 @@ private:
* audio to the audio buffer which will later be sent to the audio output device.
*/
void CacheAudioWorker();
/**
* @brief Internal function using the Cacher's known information to determine whether this media is playing in reverse
*/
bool IsReversed();
};
#endif // CACHER_H
+1 -1
View File
@@ -391,7 +391,7 @@ void ExportThread::run() {
if (params.video_enabled) {
do {
// TODO optimize by rendering the next frame while encoding the last
renderer->start_render(nullptr, olive::ActiveSequence.get(), nullptr, video_frame->data[0], video_frame->linesize[0]/4);
renderer->start_render(nullptr, olive::ActiveSequence.get(), 1, nullptr, video_frame->data[0], video_frame->linesize[0]/4);
waitCond.wait(&mutex);
if (!continueEncode) break;
} while (renderer->did_texture_fail());
+4 -1
View File
@@ -148,7 +148,7 @@ void RenderThread::paint() {
params.video = true;
params.texture_failed = false;
params.wait_for_mutexes = true;
params.playback_speed = 1;
params.playback_speed = playback_speed_;
params.blend_mode_program = blend_mode_program;
params.premultiply_program = premultiply_program;
params.backend_buffer1 = back_buffer_1.buffer();
@@ -230,6 +230,7 @@ void RenderThread::paint() {
void RenderThread::start_render(QOpenGLContext *share,
Sequence* s,
int playback_speed,
const QString& save,
GLvoid* pixels,
int pixel_linesize,
@@ -238,6 +239,8 @@ void RenderThread::start_render(QOpenGLContext *share,
seq = s;
playback_speed_ = playback_speed;
// stall any dependent actions
texture_failed = true;
+2
View File
@@ -53,6 +53,7 @@ public:
void paint();
void start_render(QOpenGLContext* share,
Sequence *s,
int playback_speed,
const QString &save = nullptr,
GLvoid *pixels = nullptr,
int pixel_linesize = 0,
@@ -102,6 +103,7 @@ private:
QOpenGLShaderProgram* ocio_shader;
Sequence* seq;
int playback_speed_;
int divider;
int tex_width;
int tex_height;
+3 -3
View File
@@ -169,7 +169,7 @@ void ViewerWidget::save_frame() {
fn += selected_ext;
}
renderer->start_render(context(), viewer->seq.get(), fn);
renderer->start_render(context(), viewer->seq.get(), 1, fn);
}
}
@@ -229,7 +229,7 @@ void ViewerWidget::frame_update() {
update();
} else {
doneCurrent();
renderer->start_render(context(), viewer->seq.get());
renderer->start_render(context(), viewer->seq.get(), viewer->get_playback_speed());
}
// render the audio
@@ -613,7 +613,7 @@ void ViewerWidget::paintGL() {
if (renderer->did_texture_fail() && !viewer->playing) {
doneCurrent();
renderer->start_render(context(), viewer->seq.get());
renderer->start_render(context(), viewer->seq.get(), viewer->get_playback_speed());
}
}
}