mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-08 09:36:02 -05:00
Move TVScreen data to separate object
This commit is contained in:
parent
a6ec7651fb
commit
44d199cfab
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
@ -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();
|
||||
}
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user