Large performance regression fixed by moving mutex further into the Timeline::GetFrame method - only when generating a new frame (allowing cache to actually work freely). Adding mutex back to FFmpegReader::GetFrame. Removing redundant mutex from ReaderBase.h. Adding mutex to all methods that call shrink_to_fit().

This commit is contained in:
Jonathan Thomas
2022-10-11 18:14:36 -05:00
parent 245186f2a0
commit 5f9c4e06d8
5 changed files with 22 additions and 11 deletions

View File

@@ -206,8 +206,8 @@ int FFmpegReader::IsHardwareDecodeSupported(int codecid)
void FFmpegReader::Open() {
// Open reader if not already open
if (!is_open) {
// Prevent calls to GetFrame when Closing
const std::lock_guard<std::recursive_mutex> lock(processingMutex);
// Prevent async calls to the following code
const std::lock_guard<std::recursive_mutex> lock(getFrameMutex);
// Initialize format context
pFormatCtx = NULL;
@@ -580,8 +580,8 @@ void FFmpegReader::Open() {
void FFmpegReader::Close() {
// Close all objects, if reader is 'open'
if (is_open) {
// Prevent calls to GetFrame when Closing
const std::lock_guard<std::recursive_mutex> lock(processingMutex);
// Prevent async calls to the following code
const std::lock_guard<std::recursive_mutex> lock(getFrameMutex);
// Mark as "closed"
is_open = false;
@@ -881,13 +881,16 @@ std::shared_ptr<Frame> FFmpegReader::GetFrame(int64_t requested_frame) {
// Return the cached frame
return frame;
} else {
// Check the cache a 2nd time (due to a potential previous lock)
// Prevent async calls to the remainder of this code
const std::lock_guard<std::recursive_mutex> lock(getFrameMutex);
// Check the cache a 2nd time (due to the potential previous lock)
frame = final_cache.GetFrame(requested_frame);
if (frame) {
// Debug output
ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::GetFrame", "returned cached frame on 2nd look", requested_frame);
// Return the cached frame
} else {
// Frame is not in cache
// Reset seek count
@@ -2078,6 +2081,9 @@ bool FFmpegReader::IsPartialFrame(int64_t requested_frame) {
// Check the working queue, and move finished frames to the finished queue
void FFmpegReader::CheckWorkingFrames(int64_t requested_frame) {
// Prevent async calls to the following code
const std::lock_guard<std::recursive_mutex> lock(getFrameMutex);
// Get a list of current working queue frames in the cache (in-progress frames)
std::vector<std::shared_ptr<openshot::Frame>> working_frames = working_cache.GetFrames();
std::vector<std::shared_ptr<openshot::Frame>>::iterator working_itr;

View File

@@ -84,6 +84,9 @@ void FrameMapper::AddField(Field field)
// Clear both the fields & frames lists
void FrameMapper::Clear() {
// Prevent async calls to the following code
const std::lock_guard<std::recursive_mutex> lock(getFrameMutex);
// Clear the fields & frames lists
fields.clear();
fields.shrink_to_fit();
@@ -104,6 +107,9 @@ void FrameMapper::Init()
// Skip initialization
return;
// Prevent async calls to the following code
const std::lock_guard<std::recursive_mutex> lock(getFrameMutex);
// Clear the fields & frames lists
Clear();

View File

@@ -152,7 +152,7 @@ namespace openshot
std::shared_ptr<openshot::Frame> AudioPlaybackThread::getFrame()
{
if (source) return source->getFrame();
return std::shared_ptr<openshot::Frame>();
return std::shared_ptr<openshot::Frame>();
}
// Seek the audio thread

View File

@@ -77,7 +77,6 @@ namespace openshot
protected:
/// Mutex for multiple threads
std::recursive_mutex getFrameMutex;
std::recursive_mutex processingMutex;
openshot::ClipBase* clip; ///< Pointer to the parent clip instance (if any)
public:

View File

@@ -853,9 +853,6 @@ bool Timeline::isEqual(double a, double b)
// Get an openshot::Frame object for a specific frame number of this reader.
std::shared_ptr<Frame> Timeline::GetFrame(int64_t requested_frame)
{
// Get lock (to prevent the same frame from being generated by more than 1 thread)
const std::lock_guard<std::recursive_mutex> lock(getFrameMutex);
// Adjust out of bounds frame number
if (requested_frame < 1)
requested_frame = 1;
@@ -874,6 +871,9 @@ std::shared_ptr<Frame> Timeline::GetFrame(int64_t requested_frame)
}
else
{
// Prevent async calls to the following code
const std::lock_guard<std::recursive_mutex> lock(getFrameMutex);
// Get a list of clips that intersect with the requested section of timeline
// This also opens the readers for intersecting clips, and marks non-intersecting clips as 'needs closing'
std::vector<Clip*> nearby_clips;