fixed several things
This commit is contained in:
+1
-1
@@ -28,7 +28,7 @@
|
||||
|
||||
long refactor_frame_number(long framenumber, double source_frame_rate, double target_frame_rate) {
|
||||
if (source_frame_rate == target_frame_rate) return framenumber;
|
||||
return qRound(((double)framenumber/source_frame_rate)*target_frame_rate);
|
||||
return qFloor(((double)framenumber/source_frame_rate)*target_frame_rate);
|
||||
}
|
||||
|
||||
void draw_selection_rectangle(QPainter& painter, const QRect& rect) {
|
||||
|
||||
+34
-9
@@ -345,9 +345,21 @@ void cache_video_worker(Clip* c, long playhead, ClipCache* cache) {
|
||||
}
|
||||
}*/
|
||||
|
||||
if (!error) {
|
||||
// setting the cache to written even if it hasn't reached_end prevents playback from
|
||||
// signaling a seek/reset because it wasn't able to find the frame
|
||||
cache->written = true;
|
||||
cache->unread = true;
|
||||
}
|
||||
|
||||
/* new AVFilter solution */
|
||||
if (!c->reached_end) {
|
||||
while (i < c->cache_size) {
|
||||
if (c->skip_type == SKIP_TYPE_SEEK) {
|
||||
long seek_frame = refactor_frame_number(i + cache->offset, c->getMediaFrameRate(), c->getMediaFrameRate()*c->speed);
|
||||
reset_cache(c, seek_frame);
|
||||
}
|
||||
|
||||
av_frame_unref(cache->frames[i]);
|
||||
|
||||
int ret = (c->filter_graph == NULL) ? AVERROR(EAGAIN) : av_buffersink_get_frame(c->buffersink_ctx, cache->frames[i]);
|
||||
@@ -381,22 +393,18 @@ void cache_video_worker(Clip* c, long playhead, ClipCache* cache) {
|
||||
}
|
||||
} else {
|
||||
i++;
|
||||
cache->write_count = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cache->write_count = i;
|
||||
|
||||
if (!error) {
|
||||
// setting the cache to written even if it hasn't reached_end prevents playback from
|
||||
// signaling a seek/reset because it wasn't able to find the frame
|
||||
cache->written = true;
|
||||
cache->unread = true;
|
||||
}
|
||||
|
||||
cache->mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void reset_cache(Clip* c, long target_frame) {
|
||||
// if we seek to a whole other place in the timeline, we'll need to reset the cache with new values
|
||||
switch (c->media_type) {
|
||||
@@ -415,11 +423,12 @@ void reset_cache(Clip* c, long target_frame) {
|
||||
|
||||
// play up to the frame we actually want
|
||||
long retrieved_frame = 0;
|
||||
target_frame--;
|
||||
AVFrame* temp = av_frame_alloc();
|
||||
do {
|
||||
retrieve_next_frame(c, temp);
|
||||
if (retrieved_frame == 0) {
|
||||
if (target_frame != 0) retrieved_frame = floor(temp->pts * timebase * av_q2d(c->stream->avg_frame_rate));
|
||||
if (target_frame != -1) retrieved_frame = floor(temp->pts * timebase * av_q2d(c->stream->avg_frame_rate));
|
||||
} else {
|
||||
retrieved_frame++;
|
||||
}
|
||||
@@ -517,9 +526,25 @@ void open_clip_worker(Clip* clip) {
|
||||
char filter_args[512];
|
||||
|
||||
if (clip->stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
/* SKIP_TYPE_SEEK is used if a video is playing at a speed so fast
|
||||
* that it is quicker to seek to the next frame than to just play
|
||||
* up to it (e.g. 2000% speed would require playing and skipping
|
||||
* 20 frames per frame and it many cases it would be quicker to
|
||||
* seek to it and cache in memory instead.
|
||||
*
|
||||
* TODO there could probably be a better heuristic than
|
||||
* (speed >= 5) for using seek mode. Experiment with the value
|
||||
* but also in the future perhaps we could implement a system
|
||||
* of testing how long it takes to seek vs how long it takes to
|
||||
* decode a frame and compare them to choose with method.
|
||||
*/
|
||||
clip->skip_type = (clip->speed < 5) ? SKIP_TYPE_DISCARD : SKIP_TYPE_SEEK;
|
||||
|
||||
// create memory cache for video
|
||||
clip->cache_size = (ms->infinite_length) ? 1 : ceil(av_q2d(clip->stream->avg_frame_rate)/4); // cache is half a second in total
|
||||
|
||||
// if (clip->skip_type == SKIP_TYPE_SEEK) clip->cache_size *= 2;
|
||||
|
||||
clip->cache_A.frames = new AVFrame* [clip->cache_size];
|
||||
clip->cache_B.frames = new AVFrame* [clip->cache_size];
|
||||
|
||||
@@ -544,7 +569,7 @@ void open_clip_worker(Clip* clip) {
|
||||
enum AVPixelFormat pix_fmts[] = { static_cast<AVPixelFormat>(dest_format), AV_PIX_FMT_NONE };
|
||||
if (av_opt_set_int_list(clip->buffersink_ctx, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN) < 0) {
|
||||
qDebug() << "[ERROR] Could not set output pixel format";
|
||||
}
|
||||
}
|
||||
|
||||
bool interlaced = false;
|
||||
if (interlaced) {
|
||||
|
||||
+16
-12
@@ -115,7 +115,9 @@ bool get_clip_frame(Clip* c, long playhead) {
|
||||
sequence_clip_time = c->getMaximumLength() - sequence_clip_time - 1;
|
||||
}
|
||||
|
||||
long clip_time = refactor_frame_number(sequence_clip_time, c->sequence->frame_rate, c->getMediaFrameRate()*c->speed);
|
||||
double rate = c->getMediaFrameRate();
|
||||
if (c->skip_type == SKIP_TYPE_DISCARD) rate *= c->speed;
|
||||
long clip_time = refactor_frame_number(sequence_clip_time, c->sequence->frame_rate, rate);
|
||||
|
||||
AVFrame* current_frame = NULL;
|
||||
bool no_frame = false;
|
||||
@@ -139,28 +141,29 @@ bool get_clip_frame(Clip* c, long playhead) {
|
||||
long cache_offset = 0;
|
||||
bool cache_needs_reset = false;
|
||||
|
||||
// TODO just removed a bunch of mutexes - is this safe????
|
||||
if (c->cache_A.written && clip_time >= c->cache_A.offset && clip_time < c->cache_A.offset + c->cache_size) {
|
||||
if (clip_time < c->cache_A.offset + c->cache_A.write_count) {
|
||||
if (c->cache_A.mutex.tryLock()) { // lock in case cacher is still writing to it
|
||||
if (clip_time < (c->cache_A.offset + c->cache_A.write_count)) {
|
||||
// if (c->cache_A.mutex.tryLock()) { // lock in case cacher is still writing to it
|
||||
using_cache_A = true;
|
||||
c->cache_A.unread = false;
|
||||
cache = c->cache_A.frames;
|
||||
cache_offset = c->cache_A.offset;
|
||||
c->cache_A.mutex.unlock();
|
||||
}
|
||||
// c->cache_A.mutex.unlock();
|
||||
// }
|
||||
} else {
|
||||
// frame is coming but isn't here yet, no need to reset cache
|
||||
no_frame = true;
|
||||
}
|
||||
} else if (c->cache_B.written && clip_time >= c->cache_B.offset && clip_time < c->cache_B.offset + c->cache_size) {
|
||||
if (clip_time < c->cache_B.offset + c->cache_B.write_count) {
|
||||
if (c->cache_B.mutex.tryLock()) { // lock in case cacher is still writing to it
|
||||
if (clip_time < (c->cache_B.offset + c->cache_B.write_count)) {
|
||||
// if (c->cache_B.mutex.tryLock()) { // lock in case cacher is still writing to it
|
||||
using_cache_B = true;
|
||||
c->cache_B.unread = false;
|
||||
cache = c->cache_B.frames;
|
||||
cache_offset = c->cache_B.offset;
|
||||
c->cache_B.mutex.unlock();
|
||||
}
|
||||
// c->cache_B.mutex.unlock();
|
||||
// }
|
||||
} else {
|
||||
// frame is coming but isn't here yet, no need to reset cache
|
||||
no_frame = true;
|
||||
@@ -201,6 +204,8 @@ bool get_clip_frame(Clip* c, long playhead) {
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "current_frame is NULL:" << (current_frame == NULL);
|
||||
|
||||
if (current_frame != NULL) {
|
||||
// set up opengl texture
|
||||
if (c->texture == NULL) {
|
||||
@@ -216,11 +221,10 @@ bool get_clip_frame(Clip* c, long playhead) {
|
||||
c->texture->setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, current_frame->data[0]);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
c->texture_frame = clip_time;
|
||||
|
||||
return true;
|
||||
} else if (!no_frame) {
|
||||
} else {
|
||||
texture_failed = true;
|
||||
qDebug() << "[ERROR] Failed to retrieve frame from cache (R:" << clip_time << "| A:" << c->cache_A.offset << "-" << c->cache_A.offset+c->cache_size-1 << "| B:" << c->cache_B.offset << "-" << c->cache_B.offset+c->cache_size-1 << "| WA:" << c->cache_A.written << "| WB:" << c->cache_B.written << ")";
|
||||
if (!no_frame) qDebug() << "[ERROR] Failed to retrieve frame from cache (R:" << clip_time << "| A:" << c->cache_A.offset << "-" << c->cache_A.offset+c->cache_size-1 << "| B:" << c->cache_B.offset << "-" << c->cache_B.offset+c->cache_size-1 << "| WA:" << c->cache_A.written << "| WB:" << c->cache_B.written << ")";
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
#include <QMutex>
|
||||
#include <QVector>
|
||||
|
||||
#define SKIP_TYPE_DISCARD 0
|
||||
#define SKIP_TYPE_SEEK 1
|
||||
|
||||
class Cacher;
|
||||
class Effect;
|
||||
class Transition;
|
||||
@@ -74,6 +77,7 @@ struct Clip
|
||||
double speed;
|
||||
bool reverse;
|
||||
long calculated_length;
|
||||
int skip_type;
|
||||
|
||||
// other variables (should be "duplicated" in copy())
|
||||
QList<Effect*> effects;
|
||||
|
||||
Reference in New Issue
Block a user