Large refactor of OpenMP integration (or rather the removal of OpenMP on the Timeline and FFmpeg-related classes). The logic behind this decision, was based on profiling libopenshot and the amount of wasted CPU idle time on all the various threads. The slow code is still synchronous, and all the threads must wait on each other, adding additional overhead. So, removing lots of unneeded threads, and simplifying the underlying Timeline->Clip->FFmpegReader flow. Also, removed 2 calls to QPainter::drawImage, by improving the flexibility of Clip->GetFrame.

This commit is contained in:
Jonathan Thomas
2021-02-17 19:44:44 -06:00
parent 15695e3c0c
commit 3daa5bdb7b
15 changed files with 1006 additions and 1211 deletions

View File

@@ -754,13 +754,11 @@ void Frame::AddColor(int new_width, int new_height, std::string new_color)
// Create new image object, and fill with pixel data
const GenericScopedLock<juce::CriticalSection> lock(addingImageSection);
#pragma omp critical (AddImage)
{
image = std::make_shared<QImage>(new_width, new_height, QImage::Format_RGBA8888_Premultiplied);
image = std::make_shared<QImage>(new_width, new_height, QImage::Format_RGBA8888_Premultiplied);
// Fill with solid color
image->fill(QColor(QString::fromStdString(color)));
// Fill with solid color
image->fill(QColor(QString::fromStdString(color)));
}
// Update height and width
width = image->width();
height = image->height();
@@ -775,12 +773,7 @@ void Frame::AddImage(
// Create new buffer
{
const GenericScopedLock<juce::CriticalSection> lock(addingImageSection);
int buffer_size = new_width * new_height * bytes_per_pixel;
qbuffer = new unsigned char[buffer_size]();
// Copy buffer data
memcpy((unsigned char*)qbuffer, pixels_, buffer_size);
qbuffer = pixels_;
} // Release addingImageSection lock
// Create new image object from pixel data
@@ -804,19 +797,16 @@ void Frame::AddImage(std::shared_ptr<QImage> new_image)
// assign image data
const GenericScopedLock<juce::CriticalSection> lock(addingImageSection);
#pragma omp critical (AddImage)
{
image = new_image;
image = new_image;
// Always convert to Format_RGBA8888_Premultiplied (if different)
if (image->format() != QImage::Format_RGBA8888_Premultiplied)
*image = image->convertToFormat(QImage::Format_RGBA8888_Premultiplied);
// Always convert to Format_RGBA8888_Premultiplied (if different)
if (image->format() != QImage::Format_RGBA8888_Premultiplied)
*image = image->convertToFormat(QImage::Format_RGBA8888_Premultiplied);
// Update height and width
width = image->width();
height = image->height();
has_image_data = true;
}
// Update height and width
width = image->width();
height = image->height();
has_image_data = true;
}
// Add (or replace) pixel data to the frame (for only the odd or even lines)
@@ -834,15 +824,12 @@ void Frame::AddImage(std::shared_ptr<QImage> new_image, bool only_odd_lines)
} else {
// Ignore image of different sizes or formats
bool ret=false;
#pragma omp critical (AddImage)
{
if (image == new_image || image->size() != new_image->size()) {
ret = true;
}
else if (new_image->format() != QImage::Format_RGBA8888_Premultiplied) {
new_image = std::make_shared<QImage>(
if (image == new_image || image->size() != new_image->size()) {
ret = true;
}
else if (new_image->format() != QImage::Format_RGBA8888_Premultiplied) {
new_image = std::make_shared<QImage>(
new_image->convertToFormat(QImage::Format_RGBA8888_Premultiplied));
}
}
if (ret) {
return;
@@ -850,26 +837,23 @@ void Frame::AddImage(std::shared_ptr<QImage> new_image, bool only_odd_lines)
// Get the frame's image
const GenericScopedLock<juce::CriticalSection> lock(addingImageSection);
#pragma omp critical (AddImage)
{
unsigned char *pixels = image->bits();
const unsigned char *new_pixels = new_image->constBits();
unsigned char *pixels = image->bits();
const unsigned char *new_pixels = new_image->constBits();
// Loop through the scanlines of the image (even or odd)
int start = 0;
if (only_odd_lines)
start = 1;
// Loop through the scanlines of the image (even or odd)
int start = 0;
if (only_odd_lines)
start = 1;
for (int row = start; row < image->height(); row += 2) {
int offset = row * image->bytesPerLine();
memcpy(pixels + offset, new_pixels + offset, image->bytesPerLine());
}
// Update height and width
height = image->height();
width = image->width();
has_image_data = true;
for (int row = start; row < image->height(); row += 2) {
int offset = row * image->bytesPerLine();
memcpy(pixels + offset, new_pixels + offset, image->bytesPerLine());
}
// Update height and width
height = image->height();
width = image->width();
has_image_data = true;
}
}
@@ -891,31 +875,29 @@ void Frame::ResizeAudio(int channels, int length, int rate, ChannelLayout layout
// Add audio samples to a specific channel
void Frame::AddAudio(bool replaceSamples, int destChannel, int destStartSample, const float* source, int numSamples, float gainToApplyToSource = 1.0f) {
const GenericScopedLock<juce::CriticalSection> lock(addingAudioSection);
#pragma omp critical (adding_audio)
{
// Clamp starting sample to 0
int destStartSampleAdjusted = max(destStartSample, 0);
// Extend audio container to hold more (or less) samples and channels.. if needed
int new_length = destStartSampleAdjusted + numSamples;
int new_channel_length = audio->getNumChannels();
if (destChannel >= new_channel_length)
new_channel_length = destChannel + 1;
if (new_length > audio->getNumSamples() || new_channel_length > audio->getNumChannels())
audio->setSize(new_channel_length, new_length, true, true, false);
// Clamp starting sample to 0
int destStartSampleAdjusted = max(destStartSample, 0);
// Clear the range of samples first (if needed)
if (replaceSamples)
audio->clear(destChannel, destStartSampleAdjusted, numSamples);
// Extend audio container to hold more (or less) samples and channels.. if needed
int new_length = destStartSampleAdjusted + numSamples;
int new_channel_length = audio->getNumChannels();
if (destChannel >= new_channel_length)
new_channel_length = destChannel + 1;
if (new_length > audio->getNumSamples() || new_channel_length > audio->getNumChannels())
audio->setSize(new_channel_length, new_length, true, true, false);
// Add samples to frame's audio buffer
audio->addFrom(destChannel, destStartSampleAdjusted, source, numSamples, gainToApplyToSource);
has_audio_data = true;
// Clear the range of samples first (if needed)
if (replaceSamples)
audio->clear(destChannel, destStartSampleAdjusted, numSamples);
// Calculate max audio sample added
if (new_length > max_audio_sample)
max_audio_sample = new_length;
}
// Add samples to frame's audio buffer
audio->addFrom(destChannel, destStartSampleAdjusted, source, numSamples, gainToApplyToSource);
has_audio_data = true;
// Calculate max audio sample added
if (new_length > max_audio_sample)
max_audio_sample = new_length;
}
// Apply gain ramp (i.e. fading volume)
@@ -958,7 +940,7 @@ cv::Mat Frame::GetImageCV()
if (!image)
// Fill with black
AddColor(width, height, color);
// if (imagecv.empty())
// Convert Qimage to Mat
imagecv = Qimage2mat(image);