ffmpeg: allow decoders immediate access to frames even while indexing

Previously, FFmpeg decoders needed to wait for the initial index to finish
before they could retrieve frames. Now they can retrieve frames while the
index is occurring, provided the appropriate frame has already been indexed (if
not, the retrieve will need to wait still).
This commit is contained in:
itsmattkc
2020-02-15 13:57:29 +11:00
parent 97dadace1f
commit f5de19dd6b
6 changed files with 199 additions and 114 deletions
+5
View File
@@ -140,6 +140,11 @@ StreamID Stream::ToID() const
return StreamID(footage_->filename(), index_);
}
QMutex* Stream::index_process_lock()
{
return &index_process_lock_;
}
void Stream::FootageSetEvent(Footage*)
{
}
+6 -1
View File
@@ -103,7 +103,7 @@ public:
StreamID ToID() const;
QMutex index_lock_;
QMutex* index_process_lock();
protected:
virtual void FootageSetEvent(Footage*);
@@ -112,6 +112,9 @@ protected:
virtual void SaveCustomParameters(QXmlStreamWriter* writer) const;
signals:
void IndexChanged();
private:
Footage* footage_;
@@ -125,6 +128,8 @@ private:
bool enabled_;
QMutex index_process_lock_;
};
using StreamPtr = std::shared_ptr<Stream>;
+91
View File
@@ -20,6 +20,8 @@
#include "videostream.h"
#include <QFile>
VideoStream::VideoStream()
{
set_type(kVideo);
@@ -41,3 +43,92 @@ void VideoStream::set_frame_rate(const rational &frame_rate)
{
frame_rate_ = frame_rate;
}
int64_t VideoStream::get_closest_timestamp_in_frame_index(const int64_t &ts)
{
QMutexLocker locker(&index_access_lock_);
if (ts <= 0) {
return frame_index_.first();
}
// Use index to find closest frame in file
for (int i=0;i<frame_index_.size();i++) {
int64_t this_ts = frame_index_.at(i);
if (this_ts == ts) {
return ts;
} else if (this_ts > ts) {
return frame_index_.at(i - 1);
}
}
return frame_index_.last();
}
void VideoStream::clear_frame_index()
{
QMutexLocker locker(&index_access_lock_);
frame_index_.clear();
}
void VideoStream::append_frame_index(const int64_t &ts)
{
QMutexLocker locker(&index_access_lock_);
frame_index_.append(ts);
}
bool VideoStream::is_frame_index_empty()
{
QMutexLocker locker(&index_access_lock_);
return frame_index_.isEmpty();
}
int64_t VideoStream::last_frame_index_timestamp()
{
QMutexLocker locker(&index_access_lock_);
return frame_index_.last();
}
bool VideoStream::load_frame_index(const QString &s)
{
// Load index from file
QFile index_file(s);
if (index_file.exists() && index_file.open(QFile::ReadOnly)) {
QMutexLocker locker(&index_access_lock_);
// Resize based on filesize
frame_index_.resize(static_cast<size_t>(index_file.size()) / sizeof(int64_t));
// Read frame index into vector
index_file.read(reinterpret_cast<char*>(frame_index_.data()),
index_file.size());
index_file.close();
}
return false;
}
bool VideoStream::save_frame_index(const QString &s)
{
QFile index_file(s);
if (index_file.open(QFile::WriteOnly)) {
// Write index in binary
QMutexLocker locker(&index_access_lock_);
index_file.write(reinterpret_cast<const char*>(frame_index_.constData()),
frame_index_.size() * static_cast<int>(sizeof(int64_t)));
index_file.close();
return true;
}
return false;
}
+13
View File
@@ -38,9 +38,22 @@ public:
const rational& frame_rate() const;
void set_frame_rate(const rational& frame_rate);
int64_t get_closest_timestamp_in_frame_index(const int64_t& ts);
void clear_frame_index();
void append_frame_index(const int64_t& ts);
bool is_frame_index_empty();
int64_t last_frame_index_timestamp();
bool load_frame_index(const QString& s);
bool save_frame_index(const QString& s);
private:
rational frame_rate_;
QVector<int64_t> frame_index_;
QMutex index_access_lock_;
};
using VideoStreamPtr = std::shared_ptr<VideoStream>;