1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-12-23 10:05:46 -05:00

Move TVScreen data to separate object

This commit is contained in:
Vort 2020-08-04 17:02:06 +03:00
parent a6ec7651fb
commit 44d199cfab
4 changed files with 145 additions and 98 deletions

View File

@ -486,6 +486,7 @@ void ATVDemodSink::applyChannelSettings(int channelSampleRate, int channelFreque
m_samplesPerLine - m_numberSamplesPerLineSignals,
m_settings.m_nbLines - m_numberOfBlackLines
);
m_tvScreenData = m_registeredTVScreen->getData();
}
m_fieldIndex = 0;
@ -579,6 +580,7 @@ void ATVDemodSink::applySettings(const ATVDemodSettings& settings, bool force)
m_samplesPerLine - m_numberSamplesPerLineSignals,
m_settings.m_nbLines - m_numberOfBlackLines
);
m_tvScreenData = m_registeredTVScreen->getData();
}
m_fieldIndex = 0;

View File

@ -20,6 +20,7 @@
#include <QElapsedTimer>
#include <vector>
#include <memory>
#include "dsp/channelsamplesink.h"
#include "dsp/basebandsamplesink.h"
@ -108,6 +109,7 @@ private:
//*************** ATV PARAMETERS ***************
TVScreenAnalog *m_registeredTVScreen;
std::shared_ptr<TVScreenAnalogData> m_tvScreenData;
//int m_intNumberSamplePerLine;
int m_numberSamplesPerHTopNom; //!< number of samples per horizontal synchronization pulse (pulse in ultra-black) - nominal value
@ -198,7 +200,7 @@ private:
inline void processSample(float& sample, int& sampleVideo)
{
// Filling pixel on the current line - reference index 0 at start of sync pulse
m_registeredTVScreen->setDataColor(m_sampleIndex - m_numberSamplesPerHSync, sampleVideo);
m_tvScreenData->setSampleValue(m_sampleIndex - m_numberSamplesPerHSync, sampleVideo);
if (m_settings.m_hSync)
{
@ -325,7 +327,7 @@ private:
float shiftSamples = 0.0f;
if (m_hSyncShiftCount != 0)
shiftSamples = m_hSyncShiftSum / m_hSyncShiftCount;
m_registeredTVScreen->selectRow(rowIndex,
m_tvScreenData->selectRow(rowIndex,
shiftSamples < -1.0f ? -1.0f : (shiftSamples > 1.0f ? 1.0f : shiftSamples));
}
@ -358,7 +360,7 @@ private:
// TODO: CHANGE
float shiftSamples = m_hSyncShiftSum / m_hSyncShiftCount;
m_registeredTVScreen->selectRow(m_rowIndex,
m_tvScreenData->setSampleValue(m_rowIndex,
shiftSamples < -1.0f ? -1.0f : (shiftSamples > 1.0f ? 1.0f : shiftSamples));
}
};

View File

@ -31,8 +31,8 @@ static const char* vertexShaderSource =
"}\n";
static const char* fragmentShaderSource =
"uniform highp sampler2D uTexture1;\n"
"uniform highp sampler2D uTexture2;\n"
"uniform highp sampler2D tex1;\n"
"uniform highp sampler2D tex2;\n"
"uniform highp float imw;\n"
"uniform highp float imh;\n"
"uniform highp float tlw;\n"
@ -44,8 +44,8 @@ static const char* fragmentShaderSource =
" float tys = (texCoordVar.y + tlhh) * imh;\n"
" float p1y = floor(tys) * tlh - tlhh;\n"
" float p3y = p1y + tlh;\n"
" float tshift1 = texture2D(uTexture2, vec2(0.0, p1y)).r;\n"
" float tshift3 = texture2D(uTexture2, vec2(0.0, p3y)).r;\n"
" float tshift1 = texture2D(tex2, vec2(0.0, p1y)).r;\n"
" float tshift3 = texture2D(tex2, vec2(0.0, p3y)).r;\n"
" float shift1 = (1.0 - tshift1 * 2.0) * tlw;\n"
" float shift3 = (1.0 - tshift3 * 2.0) * tlw;\n"
" float txs1 = (texCoordVar.x + shift1 + tlhw) * imw;\n"
@ -54,10 +54,10 @@ static const char* fragmentShaderSource =
" float p3x = floor(txs3) * tlw - tlhw;\n"
" float p2x = p1x + tlw;\n"
" float p4x = p3x + tlw;\n"
" float p1 = texture2D(uTexture1, vec2(p1x, p1y)).r;\n"
" float p2 = texture2D(uTexture1, vec2(p2x, p1y)).r;\n"
" float p3 = texture2D(uTexture1, vec2(p3x, p3y)).r;\n"
" float p4 = texture2D(uTexture1, vec2(p4x, p3y)).r;\n"
" float p1 = texture2D(tex1, vec2(p1x, p1y)).r;\n"
" float p2 = texture2D(tex1, vec2(p2x, p1y)).r;\n"
" float p3 = texture2D(tex1, vec2(p3x, p3y)).r;\n"
" float p4 = texture2D(tex1, vec2(p4x, p3y)).r;\n"
" float p12 = mix(p1, p2, fract(txs1));\n"
" float p34 = mix(p3, p4, fract(txs3));\n"
" float p = mix(p12, p34, fract(tys));\n"
@ -67,11 +67,8 @@ static const char* fragmentShaderSource =
TVScreenAnalog::TVScreenAnalog(QWidget *parent)
: QGLWidget(parent)
{
m_objCurrentRow = nullptr;
m_isDataChanged = false;
m_time = 0.0f;
m_cols = 1;
m_rows = 1;
m_data = std::make_shared<TVScreenAnalogData>(5, 1);
connect(&m_objTimer, SIGNAL(timeout()), this, SLOT(tick()));
m_objTimer.start(40); // capped at 25 FPS
@ -81,15 +78,21 @@ void TVScreenAnalog::cleanup()
{
m_shader = nullptr;
m_imageTexture = nullptr;
m_objCurrentRow = nullptr;
m_lineShiftsTexture = nullptr;
}
std::shared_ptr<TVScreenAnalogData> TVScreenAnalog::getData()
{
return m_data;
}
void TVScreenAnalog::resizeTVScreen(int intCols, int intRows)
{
qDebug("TVScreen::resizeTVScreen: cols: %d, rows: %d", intCols, intRows);
m_cols = intCols + 4;
m_rows = intRows;
int colsAdj = intCols + 4;
if (m_data->getWidth() != colsAdj || m_data->getHeight() != intRows)
m_data = std::make_shared<TVScreenAnalogData>(colsAdj, intRows);
}
void TVScreenAnalog::resizeGL(int intWidth, int intHeight)
@ -99,7 +102,6 @@ void TVScreenAnalog::resizeGL(int intWidth, int intHeight)
void TVScreenAnalog::initializeGL()
{
m_objMutex.lock();
initializeOpenGLFunctions();
m_shader = std::make_shared<QOpenGLShaderProgram>(this);
@ -109,31 +111,30 @@ void TVScreenAnalog::initializeGL()
m_vertexAttribIndex = m_shader->attributeLocation("vertex");
m_texCoordAttribIndex = m_shader->attributeLocation("texCoord");
m_objTextureLoc1 = m_shader->uniformLocation("uTexture1");
m_objTextureLoc2 = m_shader->uniformLocation("uTexture2");
m_objImageWidthLoc = m_shader->uniformLocation("imw");
m_objImageHeightLoc = m_shader->uniformLocation("imh");
m_objTexelWidthLoc = m_shader->uniformLocation("tlw");
m_objTexelHeightLoc = m_shader->uniformLocation("tlh");
initializeTextures();
m_textureLoc1 = m_shader->uniformLocation("tex1");
m_textureLoc2 = m_shader->uniformLocation("tex2");
m_imageWidthLoc = m_shader->uniformLocation("imw");
m_imageHeightLoc = m_shader->uniformLocation("imh");
m_texelWidthLoc = m_shader->uniformLocation("tlw");
m_texelHeightLoc = m_shader->uniformLocation("tlh");
connect(QOpenGLContext::currentContext(), &QOpenGLContext::aboutToBeDestroyed,
this, &TVScreenAnalog::cleanup); // TODO: when migrating to QOpenGLWidget
m_objMutex.unlock();
}
void TVScreenAnalog::initializeTextures()
{
m_image = std::make_shared<QImage>(m_cols, m_rows, QImage::Format_ARGB32);
m_lineShifts = std::make_shared<QImage>(1, m_rows, QImage::Format_ARGB32);
m_image->fill(0);
m_lineShifts->fill(127);
m_imageTexture = std::make_shared<QOpenGLTexture>(QOpenGLTexture::Target2D);
m_lineShiftsTexture = std::make_shared<QOpenGLTexture>(QOpenGLTexture::Target2D);
m_imageTexture->setSize(m_data->getWidth(), m_data->getHeight());
m_lineShiftsTexture->setSize(1, m_data->getHeight());
m_imageTexture->setFormat(QOpenGLTexture::RGBA8_UNorm);
m_lineShiftsTexture->setFormat(QOpenGLTexture::RGBA8_UNorm);
m_imageTexture->setAutoMipMapGenerationEnabled(false);
m_lineShiftsTexture->setAutoMipMapGenerationEnabled(false);
m_imageTexture->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
m_lineShiftsTexture->allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
m_imageTexture = std::make_shared<QOpenGLTexture>(*m_image, QOpenGLTexture::DontGenerateMipMaps);
m_lineShiftsTexture = std::make_shared<QOpenGLTexture>(*m_lineShifts, QOpenGLTexture::DontGenerateMipMaps);
m_imageTexture->setMinificationFilter(QOpenGLTexture::Nearest);
m_imageTexture->setMagnificationFilter(QOpenGLTexture::Nearest);
m_lineShiftsTexture->setMinificationFilter(QOpenGLTexture::Nearest);
@ -151,69 +152,45 @@ void TVScreenAnalog::renderImage()
void TVScreenAnalog::tick()
{
if (m_isDataChanged) {
if (m_isDataChanged)
{
update();
}
}
void TVScreenAnalog::selectRow(int intLine, float shift)
{
if (!m_image || m_image->height() != m_rows)
return;
if ((intLine < m_rows) && (intLine >= 0))
{
m_objCurrentRow = (int*)m_image->scanLine(intLine);
m_lineShifts->setPixel(0, intLine, (1.0f + shift) * 127.5f);
}
else
{
m_objCurrentRow = nullptr;
}
}
void TVScreenAnalog::setDataColor(int intCol, int objColor)
{
if ((intCol < m_cols - 2) &&
(intCol >= -2) &&
(m_objCurrentRow != nullptr))
{
m_objCurrentRow[intCol + 2] = objColor;
}
}
void TVScreenAnalog::paintGL()
{
if (!m_objMutex.tryLock(2))
return;
m_isDataChanged = false;
if (m_image->width() != m_cols || m_image->height() != m_rows)
if (!m_imageTexture ||
m_imageTexture->width() != m_data->getWidth() ||
m_imageTexture->height() != m_data->getHeight())
{
initializeTextures();
}
float imageWidth = m_image->width();
float imageHeight = m_image->height();
float imageWidth = m_data->getWidth();
float imageHeight = m_data->getHeight();
float texelWidth = 1.0f / imageWidth;
float texelHeight = 1.0f / imageHeight;
m_shader->bind();
m_shader->setUniformValue(m_objTextureLoc1, 0);
m_shader->setUniformValue(m_objTextureLoc2, 1);
m_shader->setUniformValue(m_objImageWidthLoc, imageWidth);
m_shader->setUniformValue(m_objImageHeightLoc, imageHeight);
m_shader->setUniformValue(m_objTexelWidthLoc, texelWidth);
m_shader->setUniformValue(m_objTexelHeightLoc, texelHeight);
m_shader->setUniformValue(m_textureLoc1, 0);
m_shader->setUniformValue(m_textureLoc2, 1);
m_shader->setUniformValue(m_imageWidthLoc, imageWidth);
m_shader->setUniformValue(m_imageHeightLoc, imageHeight);
m_shader->setUniformValue(m_texelWidthLoc, texelWidth);
m_shader->setUniformValue(m_texelHeightLoc, texelHeight);
glActiveTexture(GL_TEXTURE0);
m_imageTexture->bind();
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
m_image->width(), m_image->height(), GL_RGBA, GL_UNSIGNED_BYTE, m_image->constScanLine(0));
m_data->getWidth(), m_data->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, m_data->getImageData());
glActiveTexture(GL_TEXTURE1);
m_lineShiftsTexture->bind();
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
1, m_image->height(), GL_RGBA, GL_UNSIGNED_BYTE, m_lineShifts->constScanLine(0));
1, m_data->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, m_data->getLineShiftData());
float rectHalfWidth = 1.0f + 4 * texelWidth;
GLfloat vertices[] =
@ -241,6 +218,4 @@ void TVScreenAnalog::paintGL()
glDisableVertexAttribArray(m_texCoordAttribIndex);
m_shader->release();
m_objMutex.unlock();
}

View File

@ -26,6 +26,7 @@
#include "export.h"
#include <memory>
#include <algorithm>
#include <QImage>
#include <QMutex>
@ -35,43 +36,110 @@
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
class TVScreenAnalogData
{
public:
TVScreenAnalogData(int width, int height)
{
m_width = width;
m_height = height;
m_imageData = new int[width * height];
m_lineShiftData = new int[height];
m_outOfBoundsLine = new int[width];
m_currentLine = m_outOfBoundsLine;
std::fill(m_imageData, m_imageData + width * height, 0);
std::fill(m_lineShiftData, m_lineShiftData + height, 127);
}
~TVScreenAnalogData()
{
delete[] m_imageData;
delete[] m_lineShiftData;
delete[] m_outOfBoundsLine;
}
int getWidth()
{
return m_width;
}
int getHeight()
{
return m_height;
}
const int* getImageData()
{
return m_imageData;
}
const int* getLineShiftData()
{
return m_lineShiftData;
}
void selectRow(int line, float shift)
{
if ((line < m_height) && (line >= 0))
{
m_currentLine = m_imageData + line * m_width;
m_lineShiftData[line] = (1.0f + shift) * 127.5f;
}
else
{
m_currentLine = m_outOfBoundsLine;
}
}
void setSampleValue(int column, int value)
{
if ((column < m_width - 2) && (column >= -2))
{
m_currentLine[column + 2] = value;
}
}
private:
int m_width;
int m_height;
int* m_imageData;
int* m_lineShiftData;
int* m_currentLine;
int* m_outOfBoundsLine;
};
class SDRGUI_API TVScreenAnalog : public QGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
QTimer m_objTimer;
QMutex m_objMutex;
bool m_isDataChanged;
int m_objTextureLoc1;
int m_objTextureLoc2;
int m_objImageWidthLoc;
int m_objImageHeightLoc;
int m_objTexelWidthLoc;
int m_objTexelHeightLoc;
int m_textureLoc1;
int m_textureLoc2;
int m_imageWidthLoc;
int m_imageHeightLoc;
int m_texelWidthLoc;
int m_texelHeightLoc;
int m_vertexAttribIndex;
int m_texCoordAttribIndex;
std::shared_ptr<TVScreenAnalogData> m_data;
std::shared_ptr<QOpenGLShaderProgram> m_shader;
float m_time;
int m_cols;
int m_rows;
int* m_objCurrentRow;
std::shared_ptr<QImage> m_image;
std::shared_ptr<QImage> m_lineShifts;
std::shared_ptr<QOpenGLTexture> m_imageTexture;
std::shared_ptr<QOpenGLTexture> m_lineShiftsTexture;
public:
TVScreenAnalog(QWidget *parent);
std::shared_ptr<TVScreenAnalogData> getData();
void resizeTVScreen(int intCols, int intRows);
void selectRow(int intLine, float shift);
void setDataColor(int intCol, int objColor);
void renderImage();
private: