{ "translations": { "Please select a file." : "Choazit ur restr mar-plij.", "File is too big" : "Re vras eo ar restr", "The selected file is not an image." : "N'eo ket ur skeudenn ar restr choazet.", "The selected file cannot be read." : "N'eo ket posubl lenn ar restr choazet.", "The file was uploaded" : "Kaset eo bet ar restr", "No file was uploaded" : "N'eus restr ebet a zo bet kaset", "Invalid file provided" : "Ar restr roet n'eo ket unan aotreet", "No image or file provided" : "Skeudenn pe restr roet ebet", "Unknown filetype" : "N'eo ket anavezet stumm ar restr", "An error occurred. Please contact your admin." : "Ur fazi a zo bet. Galvit o merour mar-plij.", "Invalid image" : "N'eo ket aotreet ar skeudenn", "No temporary profile picture available, try again" : "N'ez eus skeudenn trolinenn vak ebet, klaskit adarre", "No crop data provided" : "Roadenn sternglotadur ebet", "No valid crop data provided" : "N'ez eus roadenn sternglotadur mat ebet", "Crop is not square" : "Ar sternglotadur n'eo ket ur c'harrez", "State token does not match" : "Ne glot ket ar jedouer ar stad", "Invalid app password" : "N'eo ket mat ar ger-tremen meziant", "Could not complete login" : "Dibosupl peurechuiñ an anavezadur", "Your login token is invalid or has expired" : "Ho jedouer anavezadur a zo re gozh pe n'eus ket deus outañ", "Login" : "Anv arveriad", "Password reset is disabled" : "N'eo ket posupl cheñch ar ger-tremen", "%s password reset" : "Ger-tremen %s cheñchet", "Password reset" : "Ger-tremen cheñchet", "Click the following button to reset your password. If you have not requested the password reset, then ignore this email." : "Klikit war ar bouton-mañ evit cheñch ho ker-tremen. Ma n'ho peus ket goulennet cheñch ho ker-tremen, na daolit ket pled ouzh ar gemenadenn-mañ.", "Click the following link to reset your password. If you have not requested the password reset, then ignore this email." : "Klikit war al liamm evit cheñch ho ker-tremen. Ma n'ho peus ket goulennet cheñch ho ker-tremen, na daolit ket pled ouzh ar gemenadenn-mañ.", "Reset your password" : "Cheñchit ho ker-tremen", "Nextcloud Server" : "Servijour Nextcloud", "Some of your link shares have been removed" : "Liammoù rannet 'zo a zo bet lamet", "Due to a security bug we had to remove some of your link shares. Please see the link for more information." : "Abalamour d'ur gudenn surentez hon eus lamet liammoù 'zo ho poa rannet. Sellit ouzh al liamm evit muioc'h a ditouroù.", "Preparing update" : "O prientiñ un adnevezadenn", "[%d / %d]: %s" : "[%d/%d] : %s", "Repair step:" : "Pazenn adaozañ :", "Repair info:" : "Keleier adaozañ :", "Repair warning:" : "Kemennadenn adaozañ :", "Repair error:" : "Fazi adaozañ :", "Turned on maintenance mode" : "Lakaet eo ar mod trezalc'hiñ war elum", "Turned off maintenance mode" : "Lazhet eo ar mod trezalc'hiñ", "Maintenance mode is kept active" : "Mod trezalc'hiñ o labourat", "Updating database schema" : "Oc'h adneveziñ brastres ar roadennoù-diaz", "Updated database" : "Roadennoù-diaz adnevezet ", "Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)" : "O wiriekat m'az eo brastres an diaz roadennoù %s hizivadus (gallout a ra kemer kalzik amzer hervez ment an diaz roadennoù)", "Updated \"%1$s\" to %2$s" : "Adnevezet \"%1$s\" da %2$s", "Set log level to debug" : "Lakaat ar gazetenn war live debug", "Reset log level" : "Live kazetenn adlakaet d'e stad orin", "Starting code integrity check" : "O kregiñ ar gwiriekaat evit eunded ar c'hod", "Finished code integrity check" : "Echuet ar gwiriekaat evit eunded ar c'hod", "%s (incompatible)" : "%s (diglot)", "The following apps have been disabled: %s" : "Disaotreet eo bet ar meziantoù-mañ : %s", "Already up to date" : "Adnevezet dija", "Error occurred while checking server setup" : "Ur vazi a zo bet pa omp o gwiriañ staliadur ar servijour", "unknown text" : "testenn dianv", "Hello world!" : "Demat d'ar bed !", "sunny" : "heoliek", "Hello {name}, the weather is {weather}" : "Demat deoc'h {name}, {weather} eo an amzer", "Hello {name}" : "Demat deoc'h {name}", "These are your search results" : "Setu disoc'hoù o enklask", "new" : "nevez", "_download %n file_::_download %n files_" : ["O pellgargañ %n restr","O pellgargañ %n restr","O pellgargañ %n restr","O pellgargañ %n restr","O pellgargañ %n restr"], "The update is in progress, leaving this page might interrupt the process in some environments." : "An adnevezadenn a zo o treiñ, na zilezik ket ar bajenn, m'o all e hel beza troc'het an oberenn war endroioù zo.", "Update to {version}" : "Oc'h adneveziñ da {version}", "An error occurred." : "Ur fazi a zo bet.", "Please reload the page." : "Mar-plij adkargit ar bajenn", "The update was unsuccessful. For more information check our forum post covering this issue." : "Graet eo bet an adnevesadenn; Evit muioc'h a titouroù sellit ouzh gemenadenoù ar forum diwar benn ze.", "The update was unsuccessful. Please report this issue to the Nextcloud community." : "An adnevesadenn a zo bet c'hwitet. Mar-plij, kemenit Nexcloud community eus ar gudenn.", "Apps" : "Meziant", "More apps" : "Muioc'h a veziantoù", "No" : "Nan", "Yes" : "Ya", "Date" : "Deiz", "Today" : "Hiziv", "Load more results" : "Kagañ muioc'h a disoc'hoù", "Searching …" : "O klask ...", "Start typing to search" : "Krogit da skrivañ evit klask", "Log in" : "Kennaskañ", "Logging in …" : "O kennaskañ…", "Server side authentication failed!" : "Dilesa kostez servijour c'hwited !", "Please contact your administrator." : "Mar-plij galvit o merour", "An internal error occurred." : "Ur fazi diabarzh a zo bet.", "Please try again or contact your administrator." : "Mar-plij, klaskit en dro pe galvit o merour.", "Password" : "Ger-tremen", "We have detected multiple invalid login attempts from your IP. Therefore your next login is throttled up to 30 seconds." : "Gwelet on eus eo bet klasket mon-tre dro dre o IP. Ne vo posuple deoc'h klask en dro a-benn 30 eilenn.", "Log in with a device" : "Mon-tre gan un ardivink", "Your account is not setup for passwordless login." : "N'eo ket arventennet ho kont evit kennaskañ hep ger-tremen.", "Passwordless authentication is not supported in your browser." : "Ne vez ket degemeret gant ho furcher an anaouadur hep ger-tremen.", "Passwordless authentication is only available over a secure connection." : "Dilesa hep ger-tremen a vez kinniget fant ur c'henstagadur sur nemetken.", "Reset password" : "Cheñch ger-tremen", "Couldn't send reset email. Please contact your administrator." : "N'eo ket posuple kas ar postel adober. Mar-plij, kelaouit o merour.", "Back to login" : "Distro d'ar c'hennask", "New password" : "Ger-tremen nevez", "Your files are encrypted. There will be no way to get your data back after your password is reset. If you are not sure what to do, please contact your administrator before you continue. Do you really want to continue?" : "Sifret eo ar restr. ne vo ket posupl deoc'h adtapout ho roadenno goude bezhañ cheñchet ho ger-tremenn. Ma n'oc'h ket sur petra ober, goulenit d'ho merour a raok kendec'hel. C'hoant ho peus kendec'hel ?", "I know what I'm doing" : "Gouzout a ran petra a ran", "Resetting password" : "Oc'h adtermeniñ ar ger-tremen", "Recommended apps" : "Meziantoù kinniget", "Loading apps …" : "O kargañ ar meziant", "App download or installation failed" : "Pellgargan pe staliadur ar meziant c'hwited", "Skip" : "Tremen", "Installing apps …" : "O stallia ar meziant ...", "Install recommended apps" : "Staliit ar meziantoù kinniget", "Schedule work & meetings, synced with all your devices." : "Implij amzer & emvodoù, kemprenet gant toud o ardivinkoù.", "Keep your colleagues and friends in one place without leaking their private info." : "Kavit o mignoned ha genseurted en ul lec'h, hep reiñ o ditouroù prevez.", "Simple email app nicely integrated with Files, Contacts and Calendar." : "Ur meziant email simpl enfammet gant Restroù, Darempredoù ha Deizataer.", "Settings menu" : "Roll-mezioù an arventennoù", "Reset search" : "Adkregiñ an enklask", "Search contacts …" : "Klask darempred ...", "Could not load your contacts" : "N'eo ket posuple kargañ an darempredoù", "No contacts found" : "Darmpred ebet kavet", "Install the Contacts app" : "Stalliaén ar meziant darempredoù", "Loading your contacts …" : "O kargañ o darempredoù", "Looking for {term} …" : "O klask {term} ...", "Loading more results …" : "O kargañ muioc'h a zisoc'hoù ...", "Search" : "Klask", "No results for {query}" : "Disoc'h ebet evit {query}", "Forgot password?" : "Ger-tremen ankouaet?", "Back" : "Distro", "Search {types} …" : "Klask {types} ...", "Choose" : "Dibab", "Copy" : "Eilañ", "Move" : "Diplasañ", "OK" : "OK", "read-only" : "lennable nemetken", "_{count} file conflict_::_{count} file conflicts_" : ["{count} diemglev restr","{count} diemglev restr","{count} diemglev restr","{count} diemglev restr","{count} diemglev restr"], "One file conflict" : "Diemglev gant ur restr", "New Files" : "Restroù nevez", "Already existing files" : "Bez ez eus dija eus ar rentr", "Which files do you want to keep?" : "Peseurt restroù o peus c'houant gouarn", "If you select both versions, the copied file will have a number added to its name." : "M'a choazit an daou stumm, an restr eilet en do un niver ouzhenned war e anv", "Cancel" : "Arrest", "Continue" : "Kendec'hel", "(all selected)" : "(dibab pep tra)", "({count} selected)" : "({count} dibabet)", "Error loading file exists template" : "Ur fazi zo bet pa voe karget ar restr", "Saving …" : "Orc'h enrolliñ", "seconds ago" : "eilenn zo", "Connection to server lost" : "Kelet eo bet ar c'henstagañ gant ar servijour", "_Problem loading page, reloading in %n second_::_Problem loading page, reloading in %n seconds_" : ["Ur gudenn zo evit kargañ ar bajenn, adkargit a ben %n eilenn","Ur gudenn zo evit kargañ ar bajenn, adkargit a ben %n eilenn","Ur gudenn zo evit kargañ ar bajenn, adkargit a ben %n eilenn","Ur gudenn zo evit kargañ ar bajenn, adkargit a ben %n eilenn","Ur gudenn zo evit kargañ ar bajenn, adkargit a ben %n eilenn"], "Add to a project" : "Ouzhpennañ d'ar raktres", "Show details" : "Diskouel ar munudoù", "Hide details" : "Skoachañ ar munudoù", "Rename project" : "Adenvel ar raktres", "Failed to rename the project" : "C'hwitet eo bet adenvel ar raktres", "Failed to create a project" : "Krouiñ ar raktres a zo bet c'hwitet", "Failed to add the item to the project" : "C'hwitet eo bet ouzhpennaden an dra er raktres", "Connect items to a project to make them easier to find" : "Kenstagit traoù d'o raktres m'a vefe aesoc'h da gavout", "Type to search for existing projects" : "Skrivit evit klask ar raktresoù dija krouet", "New in" : "Nevez e-bazh", "View changelog" : "Sellet ar changelog", "Very weak password" : "Ger-tremen skanv kenan", "Weak password" : "Ger-tremen skanv", "So-so password" : "Ger-tremen skañvig", "Good password" : "Ger-tremen mat", "Strong password" : "Ger-tremen kreñv", "No action available" : "Oberen ebet posuple", "Error fetching contact actions" : "Ur fazi a zo bet en ur tapout an darempred", "Non-existing tag #{tag}" : "N'ez eus ket eus ar c'hlav #{tag}", "Invisible" : "Diwelus", "Delete" : "Dilemel", "Rename" : "Adenvel", "Collaborative tags" : "Klav rannet", "No tags found" : "Klav ebet kavet", "Personal" : "Personel", "Accounts" : "Kontoù", "Admin" : "Merour", "Help" : "Skoazell", "Access forbidden" : "N'oc'h ket aotreet tremen", "Back to %s" : "Distro da %s", "Too many requests" : "Re a goulennoù", "There were too many requests from your network. Retry later or contact your administrator if this is an error." : "Re a goulennoù a zo bet eus ar rouedat. Klaskit en dro diwezhatoc'h pe galvit ho merour m'az eus ur fazi.", "Error" : "Fazi", "Internal Server Error" : "Fazi servijour diabazh", "The server was unable to complete your request." : "N'eo ket gouest ar servijour ober pez o peus goulennet.", "If this happens again, please send the technical details below to the server administrator." : "M'a c'hoarvez an dra ze adare, kasit ar munudoù teknikel dindan d'o merour servijour mar-plij.", "More details can be found in the server log." : "Munudoù all a zo posuple kavout e kazetenn ar servijour", "Technical details" : "Munidoù teknikel", "Remote Address: %s" : "Chom-loc'h pell : %s", "Request ID: %s" : "ID goulennet : %s", "Type: %s" : "Stumm : %s", "Code: %s" : "Kod : %s", "Message: %s" : "Kemenadenn : %s", "File: %s" : "Restr : %s", "Line: %s" : "Linenn :%s", "Trace" : "Trace", "Security warning" : "Kemmenadenn surentez", "Your data directory and files are probably accessible from the internet because the .htaccess file does not work." : "O teuliad ha restroù rouadennoù a zo posuple tizhout a dalek ar roaedad, peogwir ne gerzh ket ar restr .htaccess.", "For information how to properly configure your server, please see the documentation." : "Evit kaout titouroù diwar benn penaos stumman mat o servijour, sellit ouz an dielvadur mar-plij.", "Create an admin account" : "Krouiñ ur c'hont merour", "Show password" : "Diskouez ar ger-tremen", "Storage & database" : "Lec'h renkañ ha roadennoù-diaz", "Data folder" : "Teuliat roadennoù", "Configure the database" : "Stumman ar roadennoù-diaz", "Only %s is available." : "%s digarg nemetken", "Install and activate additional PHP modules to choose other database types." : "Lakaat ha difraeañ molladoù PHP ouzhpenn evit dibab doare roadennoù-diaz all", "For more details check out the documentation." : "Sellit ouz an dielladur evit munudoù ouzhpenn.", "Database password" : "Roadennoù-diaz ar gerioù-trermen", "Database name" : "Roadennoù-diaz an anvioù", "Database tablespace" : "Lec'h berniañ ar roadennoù-diaz", "Database host" : "Roadenn-diaz ostiz", "Please specify the port number along with the host name (e.g., localhost:5432)." : "Lakit an niverenn porzh gant an anv ostiz (skouer, localhost:5432).", "Performance warning" : "Diwallit ouzh mont en dro", "You chose SQLite as database." : "Choazet o peus SQLite evel roadennoù-diaz.", "SQLite should only be used for minimal and development instances. For production we recommend a different database backend." : "SQLite a zlefe beahñ implijet evit azgoulennoù bihañ ha/pe dioren. Kinniget eo kemer ur backend roadennoù-diaz all evit ar c'hendec'h.", "If you use clients for file syncing, the use of SQLite is highly discouraged." : "M'a vez implijet ar c'hliant evit ar c'hemprenañ, kinniget eo implij un dra kreñvoc'h eget SQLite", "Need help?" : "Sikour o po ?", "See the documentation" : "Sellit ouz an dielladur", "It looks like you are trying to reinstall your Nextcloud. However the file CAN_INSTALL is missing from your config directory. Please create the file CAN_INSTALL in your config folder to continue." : "Seblant a ra bezhañ emaoc'h o adstaliañ Nexcloud. N'ez eus ket eus arrestr CAN_INSTALL en o teuliad config. Crouit ar restr CAN_INSTALL en teuliad config evit kendec'hel.", "Could not remove CAN_INSTALL from the config folder. Please remove this file manually." : "N'eo ket posupl lemel CAN_INSTALL eus an teuliad config. Lamit anezhañ gan an dorn mar-plij.", "This application requires JavaScript for correct operation. Please {linkstart}enable JavaScript{linkend} and reload the page." : "Ezhomp en deus ar meziant eus JavaScript evit kerzhout mat. Mar-plij, {linkstart}aotreit JavaScript{linkend} hag adkargit ar bajenn.", "Skip to main content" : "Kit d'an dalc'h penna", "Skip to navigation of app" : "Mont d'ar meziant merdeerezh", "Go to %s" : "Mont da %s", "Get your own fre
/* Copyright 2015 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <assert.h>
#include <string.h>
#include <rfb/CConnection.h>
#include <rfb/DecodeManager.h>
#include <rfb/Decoder.h>
#include <rfb/Exception.h>
#include <rfb/Region.h>
#include <rfb/LogWriter.h>
#include <rfb/util.h>
#include <rdr/Exception.h>
#include <rdr/MemOutStream.h>
#include <os/Mutex.h>
using namespace rfb;
static LogWriter vlog("DecodeManager");
DecodeManager::DecodeManager(CConnection *conn_) :
conn(conn_), threadException(nullptr)
{
size_t cpuCount;
memset(decoders, 0, sizeof(decoders));
memset(stats, 0, sizeof(stats));
queueMutex = new os::Mutex();
producerCond = new os::Condition(queueMutex);
consumerCond = new os::Condition(queueMutex);
cpuCount = os::Thread::getSystemCPUCount();
if (cpuCount == 0) {
vlog.error("Unable to determine the number of CPU cores on this system");
cpuCount = 1;
} else {
vlog.info("Detected %d CPU core(s)", (int)cpuCount);
// No point creating more threads than this, they'll just end up
// wasting CPU fighting for locks
if (cpuCount > 4)
cpuCount = 4;
}
vlog.info("Creating %d decoder thread(s)", (int)cpuCount);
while (cpuCount--) {
// Twice as many possible entries in the queue as there
// are worker threads to make sure they don't stall
freeBuffers.push_back(new rdr::MemOutStream());
freeBuffers.push_back(new rdr::MemOutStream());
threads.push_back(new DecodeThread(this));
}
}
DecodeManager::~DecodeManager()
{
logStats();
while (!threads.empty()) {
delete threads.back();
threads.pop_back();
}
delete threadException;
while (!freeBuffers.empty()) {
delete freeBuffers.back();
freeBuffers.pop_back();
}
delete consumerCond;
delete producerCond;
delete queueMutex;
for (Decoder* decoder : decoders)
delete decoder;
}
bool DecodeManager::decodeRect(const Rect& r, int encoding,
ModifiablePixelBuffer* pb)
{
Decoder *decoder;
rdr::MemOutStream *bufferStream;
int equiv;
QueueEntry *entry;
assert(pb != nullptr);
if (!Decoder::supported(encoding)) {
vlog.error("Unknown encoding %d", encoding);
throw rdr::Exception("Unknown encoding");
}
if (!decoders[encoding]) {
decoders[encoding] = Decoder::createDecoder(encoding);
if (!decoders[encoding]) {
vlog.error("Unknown encoding %d", encoding);
throw rdr::Exception("Unknown encoding");
}
}
decoder = decoders[encoding];
// Wait for an available memory buffer
queueMutex->lock();
// FIXME: Should we return and let other things run here?
while (freeBuffers.empty())
producerCond->wait();
// Don't pop the buffer in case we throw an exception
// whilst reading
bufferStream = freeBuffers.front();
queueMutex->unlock();
// First check if any thread has encountered a problem
throwThreadException();
// Read the rect
bufferStream->clear();
try {
if (!decoder->readRect(r, conn->getInStream(), conn->server, bufferStream))
return false;
} catch (rdr::Exception& e) {
throw Exception("Error reading rect: %s", e.str());
}
stats[encoding].rects++;
stats[encoding].bytes += 12 + bufferStream->length();
stats[encoding].pixels += r.area();
equiv = 12 + r.area() * (conn->server.pf().bpp/8);
stats[encoding].equivalent += equiv;
// Then try to put it on the queue
entry = new QueueEntry;
entry->active = false;
entry->rect = r;
entry->encoding = encoding;
entry->decoder = decoder;
entry->server = &conn->server;
entry->pb = pb;
entry->bufferStream = bufferStream;
decoder->getAffectedRegion(r, bufferStream->data(),
bufferStream->length(), conn->server,
&entry->affectedRegion);
queueMutex->lock();
// The workers add buffers to the end so it's safe to assume
// the front is still the same buffer
freeBuffers.pop_front();
workQueue.push_back(entry);
// We only put a single entry on the queue so waking a single
// thread is sufficient
consumerCond->signal();
queueMutex->unlock();
return true;
}
void DecodeManager::flush()
{
queueMutex->lock();
while (!workQueue.empty())
producerCond->wait();
queueMutex->unlock();
throwThreadException();
}
void DecodeManager::logStats()
{
size_t i;
unsigned rects;
unsigned long long pixels, bytes, equivalent;
double ratio;
rects = 0;
pixels = bytes = equivalent = 0;
for (i = 0;i < (sizeof(stats)/sizeof(stats[0]));i++) {
// Did this class do anything at all?
if (stats[i].rects == 0)
continue;
rects += stats[i].rects;
pixels += stats[i].pixels;
bytes += stats[i].bytes;
equivalent += stats[i].equivalent;
ratio = (double)stats[i].equivalent / stats[i].bytes;
vlog.info(" %s: %s, %s", encodingName(i),
siPrefix(stats[i].rects, "rects").c_str(),
siPrefix(stats[i].pixels, "pixels").c_str());
vlog.info(" %*s %s (1:%g ratio)",
(int)strlen(encodingName(i)), "",
iecPrefix(stats[i].bytes, "B").c_str(), ratio);
}
ratio = (double)equivalent / bytes;
vlog.info(" Total: %s, %s",
siPrefix(rects, "rects").c_str(),
siPrefix(pixels, "pixels").c_str());
vlog.info(" %s (1:%g ratio)",
iecPrefix(bytes, "B").c_str(), ratio);
}
void DecodeManager::setThreadException(const rdr::Exception& e)
{
os::AutoMutex a(queueMutex);
if (threadException != nullptr)
return;
threadException = new rdr::Exception("Exception on worker thread: %s", e.str());
}
void DecodeManager::throwThreadException()
{
os::AutoMutex a(queueMutex);
if (threadException == nullptr)
return;
rdr::Exception e(*threadException);
delete threadException;
threadException = nullptr;
throw e;
}
DecodeManager::DecodeThread::DecodeThread(DecodeManager* manager_)
: manager(manager_), stopRequested(false)
{
start();
}
DecodeManager::DecodeThread::~DecodeThread()
{
stop();
wait();
}
void DecodeManager::DecodeThread::stop()
{
os::AutoMutex a(manager->queueMutex);
if (!isRunning())
return;
stopRequested = true;
// We can't wake just this thread, so wake everyone
manager->consumerCond->broadcast();
}
void DecodeManager::DecodeThread::worker()
{
manager->queueMutex->lock();
while (!stopRequested) {
DecodeManager::QueueEntry *entry;
// Look for an available entry in the work queue
entry = findEntry();
if (entry == nullptr) {
// Wait and try again
manager->consumerCond->wait();
continue;
}
// This is ours now
entry->active = true;
manager->queueMutex->unlock();
// Do the actual decoding
try {
entry->decoder->decodeRect(entry->rect, entry->bufferStream->data(),
entry->bufferStream->length(),
*entry->server, entry->pb);
} catch (rdr::Exception& e) {
manager->setThreadException(e);
} catch(...) {
assert(false);
}
manager->queueMutex->lock();
// Remove the entry from the queue and give back the memory buffer
manager->freeBuffers.push_back(entry->bufferStream);
manager->workQueue.remove(entry);
delete entry;
// Wake the main thread in case it is waiting for a memory buffer
manager->producerCond->signal();
// This rect might have been blocking multiple other rects, so
// wake up every worker thread
if (manager->workQueue.size() > 1)
manager->consumerCond->broadcast();
}
manager->queueMutex->unlock();
}
DecodeManager::QueueEntry* DecodeManager::DecodeThread::findEntry()
{
Region lockedRegion;
if (manager->workQueue.empty())
return nullptr;
if (!manager->workQueue.front()->active)
return manager->workQueue.front();
for (DecodeManager::QueueEntry* entry : manager->workQueue) {
// Another thread working on this?
if (entry->active)
goto next;
// If this is an ordered decoder then make sure this is the first
// rectangle in the queue for that decoder
if (entry->decoder->flags & DecoderOrdered) {
for (DecodeManager::QueueEntry* entry2 : manager->workQueue) {
if (entry2 == entry)
break;
if (entry->encoding == entry2->encoding)
goto next;
}
}
// For a partially ordered decoder we must ask the decoder for each
// pair of rectangles.
if (entry->decoder->flags & DecoderPartiallyOrdered) {
for (DecodeManager::QueueEntry* entry2 : manager->workQueue) {
if (entry2 == entry)
break;
if (entry->encoding != entry2->encoding)
continue;
if (entry->decoder->doRectsConflict(entry->rect,
entry->bufferStream->data(),
entry->bufferStream->length(),
entry2->rect,
entry2->bufferStream->data(),
entry2->bufferStream->length(),
*entry->server))
goto next;
}
}
// Check overlap with earlier rectangles
if (!lockedRegion.intersect(entry->affectedRegion).is_empty())
goto next;
return entry;
next:
lockedRegion.assign_union(entry->affectedRegion);
}
return nullptr;
}