1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-09-28 15:56:33 -04: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_samplesPerLine - m_numberSamplesPerLineSignals,
m_settings.m_nbLines - m_numberOfBlackLines m_settings.m_nbLines - m_numberOfBlackLines
); );
m_tvScreenData = m_registeredTVScreen->getData();
} }
m_fieldIndex = 0; m_fieldIndex = 0;
@ -579,6 +580,7 @@ void ATVDemodSink::applySettings(const ATVDemodSettings& settings, bool force)
m_samplesPerLine - m_numberSamplesPerLineSignals, m_samplesPerLine - m_numberSamplesPerLineSignals,
m_settings.m_nbLines - m_numberOfBlackLines m_settings.m_nbLines - m_numberOfBlackLines
); );
m_tvScreenData = m_registeredTVScreen->getData();
} }
m_fieldIndex = 0; m_fieldIndex = 0;

View File

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

View File

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

View File

@ -26,6 +26,7 @@
#include "export.h" #include "export.h"
#include <memory> #include <memory>
#include <algorithm>
#include <QImage> #include <QImage>
#include <QMutex> #include <QMutex>
@ -35,43 +36,110 @@
#include <QOpenGLFunctions> #include <QOpenGLFunctions>
#include <QOpenGLShaderProgram> #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 class SDRGUI_API TVScreenAnalog : public QGLWidget, protected QOpenGLFunctions
{ {
Q_OBJECT Q_OBJECT
QTimer m_objTimer; QTimer m_objTimer;
QMutex m_objMutex;
bool m_isDataChanged; bool m_isDataChanged;
int m_objTextureLoc1; int m_textureLoc1;
int m_objTextureLoc2; int m_textureLoc2;
int m_objImageWidthLoc; int m_imageWidthLoc;
int m_objImageHeightLoc; int m_imageHeightLoc;
int m_objTexelWidthLoc; int m_texelWidthLoc;
int m_objTexelHeightLoc; int m_texelHeightLoc;
int m_vertexAttribIndex; int m_vertexAttribIndex;
int m_texCoordAttribIndex; int m_texCoordAttribIndex;
std::shared_ptr<TVScreenAnalogData> m_data;
std::shared_ptr<QOpenGLShaderProgram> m_shader; 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_imageTexture;
std::shared_ptr<QOpenGLTexture> m_lineShiftsTexture; std::shared_ptr<QOpenGLTexture> m_lineShiftsTexture;
public: public:
TVScreenAnalog(QWidget *parent); TVScreenAnalog(QWidget *parent);
std::shared_ptr<TVScreenAnalogData> getData();
void resizeTVScreen(int intCols, int intRows); void resizeTVScreen(int intCols, int intRows);
void selectRow(int intLine, float shift);
void setDataColor(int intCol, int objColor);
void renderImage(); void renderImage();
private: private: