Video Decoder: Improved performance (slightly reduces CPU usage)

This commit is contained in:
Souryo 2016-08-25 20:43:20 -04:00
parent fc20c2019c
commit d03e66839f
2 changed files with 72 additions and 46 deletions

View file

@ -7,6 +7,8 @@
DefaultVideoFilter::DefaultVideoFilter() DefaultVideoFilter::DefaultVideoFilter()
{ {
InitDecodeTables();
InitConversionMatrix(_pictureSettings.Hue, _pictureSettings.Saturation); InitConversionMatrix(_pictureSettings.Hue, _pictureSettings.Saturation);
} }
@ -87,56 +89,75 @@ void DefaultVideoFilter::YiqToRgb(double y, double i, double q, double &r, doubl
b = std::max(0.0, std::min(1.0, (y + _yiqToRgbMatrix[4] * i + _yiqToRgbMatrix[5] * q))); b = std::max(0.0, std::min(1.0, (y + _yiqToRgbMatrix[4] * i + _yiqToRgbMatrix[5] * q)));
} }
void DefaultVideoFilter::InitDecodeTables()
{
for(int i = 0; i < 256; i++) {
for(int j = 0; j < 8; j++) {
double redColor = i;
double greenColor = i;
double blueColor = i;
if(j & 0x01) {
//Intensify red
redColor *= 1.1;
greenColor *= 0.9;
blueColor *= 0.9;
}
if(j & 0x02) {
//Intensify green
greenColor *= 1.1;
redColor *= 0.9;
blueColor *= 0.9;
}
if(j & 0x04) {
//Intensify blue
blueColor *= 1.1;
redColor *= 0.9;
greenColor *= 0.9;
}
redColor = (redColor > 255 ? 255 : redColor) / 255.0;
greenColor = (greenColor > 255 ? 255 : greenColor) / 255.0;
blueColor = (blueColor > 255 ? 255 : blueColor) / 255.0;
_redDecodeTable[i][j] = redColor;
_greenDecodeTable[i][j] = greenColor;
_blueDecodeTable[i][j] = blueColor;
}
}
}
uint32_t DefaultVideoFilter::ProcessIntensifyBits(uint16_t ppuPixel, double scanlineIntensity) uint32_t DefaultVideoFilter::ProcessIntensifyBits(uint16_t ppuPixel, double scanlineIntensity)
{ {
uint32_t pixelOutput = EmulationSettings::GetRgbPalette()[ppuPixel & 0x3F]; uint32_t pixelOutput = EmulationSettings::GetRgbPalette()[ppuPixel & 0x3F];
uint32_t intensifyBits = (ppuPixel >> 6) & 0x07;
//Incorrect emphasis bit implementation, but will do for now. if(intensifyBits || _needToProcess || scanlineIntensity < 1.0) {
double redChannel = (double)((pixelOutput & 0xFF0000) >> 16); //Incorrect emphasis bit implementation, but will do for now.
double greenChannel = (double)((pixelOutput & 0xFF00) >> 8); double redChannel = _redDecodeTable[((pixelOutput & 0xFF0000) >> 16)][intensifyBits];
double blueChannel = (double)(pixelOutput & 0xFF); double greenChannel = _greenDecodeTable[((pixelOutput & 0xFF00) >> 8)][intensifyBits];
double blueChannel = _blueDecodeTable[(pixelOutput & 0xFF)][intensifyBits];
if(ppuPixel & 0x40) { //Apply brightness, contrast, hue & saturation
//Intensify red if(_needToProcess) {
redChannel *= 1.1; double y, i, q;
greenChannel *= 0.9; RgbToYiq(redChannel, greenChannel, blueChannel, y, i, q);
blueChannel *= 0.9; y *= _pictureSettings.Contrast * 0.5f + 1;
y += _pictureSettings.Brightness * 0.5f;
YiqToRgb(y, i, q, redChannel, greenChannel, blueChannel);
}
if(scanlineIntensity < 1.0) {
redChannel *= scanlineIntensity;
greenChannel *= scanlineIntensity;
blueChannel *= scanlineIntensity;
}
int r = std::min(255, (int)(redChannel * 255));
int g = std::min(255, (int)(greenChannel * 255));
int b = std::min(255, (int)(blueChannel * 255));
return 0xFF000000 | (r << 16) | (g << 8) | b;
} else {
return pixelOutput;
} }
if(ppuPixel & 0x80) {
//Intensify green
greenChannel *= 1.1;
redChannel *= 0.9;
blueChannel *= 0.9;
}
if(ppuPixel & 0x100) {
//Intensify blue
blueChannel *= 1.1;
redChannel *= 0.9;
greenChannel *= 0.9;
}
redChannel = (float)(redChannel > 255 ? 255 : redChannel) / 255.0;
greenChannel = (float)(greenChannel > 255 ? 255 : greenChannel) / 255.0;
blueChannel = (float)(blueChannel > 255 ? 255 : blueChannel) / 255.0;
//Apply brightness, contrast, hue & saturation
if(_needToProcess) {
double y, i, q;
RgbToYiq(redChannel, greenChannel, blueChannel, y, i, q);
y *= _pictureSettings.Contrast * 0.5f + 1;
y += _pictureSettings.Brightness * 0.5f;
YiqToRgb(y, i, q, redChannel, greenChannel, blueChannel);
}
if(scanlineIntensity < 1.0) {
redChannel *= scanlineIntensity;
greenChannel *= scanlineIntensity;
blueChannel *= scanlineIntensity;
}
int r = std::min(255, (int)(redChannel * 255));
int g = std::min(255, (int)(greenChannel * 255));
int b = std::min(255, (int)(blueChannel * 255));
return 0xFF000000 | (r << 16) | (g << 8) | b;
} }

View file

@ -6,10 +6,15 @@
class DefaultVideoFilter : public BaseVideoFilter class DefaultVideoFilter : public BaseVideoFilter
{ {
private: private:
double _redDecodeTable[256][8];
double _greenDecodeTable[256][8];
double _blueDecodeTable[256][8];
double _yiqToRgbMatrix[6]; double _yiqToRgbMatrix[6];
PictureSettings _pictureSettings; PictureSettings _pictureSettings;
bool _needToProcess = false; bool _needToProcess = false;
void InitDecodeTables();
void InitConversionMatrix(double hueShift, double saturationShift); void InitConversionMatrix(double hueShift, double saturationShift);
void RgbToYiq(double r, double g, double b, double &y, double &i, double &q); void RgbToYiq(double r, double g, double b, double &y, double &i, double &q);