diff --git a/tools/ld-analyse/ld-analyse.pro b/tools/ld-analyse/ld-analyse.pro
index 7cf2b7f50..385bafa22 100644
--- a/tools/ld-analyse/ld-analyse.pro
+++ b/tools/ld-analyse/ld-analyse.pro
@@ -82,6 +82,7 @@ HEADERS += \
../library/tbc/filters.h \
../library/tbc/jsonio.h \
../library/tbc/lddecodemetadata.h \
+ ../library/tbc/linenumber.h \
../library/tbc/logging.h \
../library/tbc/sourcevideo.h \
../library/tbc/vbidecoder.h \
diff --git a/tools/ld-analyse/mainwindow.cpp b/tools/ld-analyse/mainwindow.cpp
index 90af71995..4c70e4542 100644
--- a/tools/ld-analyse/mainwindow.cpp
+++ b/tools/ld-analyse/mainwindow.cpp
@@ -72,7 +72,7 @@ MainWindow::MainWindow(QString inputFilenameParam, QWidget *parent) :
if (tbcSource.getIsWidescreen()) aspectRatio = Aspect::DAR_169;
// Connect to the scan line changed signal from the oscilloscope dialogue
- connect(oscilloscopeDialog, &OscilloscopeDialog::scanLineChanged, this, &MainWindow::scanLineChangedSignalHandler);
+ connect(oscilloscopeDialog, &OscilloscopeDialog::scopeCoordsChanged, this, &MainWindow::scopeCoordsChangedSignalHandler);
lastScopeLine = 1;
lastScopeDot = 1;
@@ -453,8 +453,8 @@ void MainWindow::updateOscilloscopeDialogue()
{
// Update the oscilloscope dialogue
oscilloscopeDialog->showTraceImage(tbcSource.getScanLineData(lastScopeLine),
- lastScopeLine, lastScopeDot,
- tbcSource.getFrameHeight());
+ lastScopeDot, lastScopeLine - 1,
+ tbcSource.getFrameWidth(), tbcSource.getFrameHeight());
}
// Menu bar signal handlers -------------------------------------------------------------------------------------------
@@ -875,14 +875,14 @@ void MainWindow::on_aspectPushButton_clicked()
// Miscellaneous handler methods --------------------------------------------------------------------------------------
// Handler called when another class changes the currenly selected scan line
-void MainWindow::scanLineChangedSignalHandler(qint32 scanLine, qint32 pictureDot)
+void MainWindow::scopeCoordsChangedSignalHandler(qint32 xCoord, qint32 yCoord)
{
- qDebug() << "MainWindow::scanLineChangedSignalHandler(): Called with scanLine =" << scanLine << "and picture dot" << pictureDot;
+ qDebug() << "MainWindow::scanLineChangedSignalHandler(): Called with xCoord =" << xCoord << "and yCoord =" << yCoord;
if (tbcSource.getIsSourceLoaded()) {
// Show the oscilloscope dialogue for the selected scan-line
- lastScopeDot = pictureDot;
- lastScopeLine = scanLine;
+ lastScopeDot = xCoord;
+ lastScopeLine = yCoord + 1;
updateOscilloscopeDialogue();
oscilloscopeDialog->show();
diff --git a/tools/ld-analyse/mainwindow.h b/tools/ld-analyse/mainwindow.h
index 32fd00573..61af7ef14 100644
--- a/tools/ld-analyse/mainwindow.h
+++ b/tools/ld-analyse/mainwindow.h
@@ -98,7 +98,7 @@ private slots:
void on_aspectPushButton_clicked();
// Miscellaneous handlers
- void scanLineChangedSignalHandler(qint32 scanLine, qint32 pictureDot);
+ void scopeCoordsChangedSignalHandler(qint32 xCoord, qint32 yCoord);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void chromaDecoderConfigChangedSignalHandler();
diff --git a/tools/ld-analyse/oscilloscopedialog.cpp b/tools/ld-analyse/oscilloscopedialog.cpp
index 2cc736332..09e866e7e 100644
--- a/tools/ld-analyse/oscilloscopedialog.cpp
+++ b/tools/ld-analyse/oscilloscopedialog.cpp
@@ -34,14 +34,17 @@ OscilloscopeDialog::OscilloscopeDialog(QWidget *parent) :
ui->setupUi(this);
setWindowFlags(Qt::Window);
- maximumScanLines = 625;
- lastScopeLine = 0;
- lastScopeDot = 0;
+ maximumX = 1135;
+ maximumY = 625;
+ lastScopeX = 0;
+ lastScopeY = 0;
scopeWidth = 0;
// Configure the GUI
- ui->scanLineSpinBox->setMinimum(1);
- ui->scanLineSpinBox->setMaximum(625);
+ ui->xCoordSpinBox->setMinimum(0);
+ ui->xCoordSpinBox->setMaximum(maximumX - 1);
+ ui->yCoordSpinBox->setMinimum(0);
+ ui->yCoordSpinBox->setMaximum(maximumY - 1);
ui->previousPushButton->setAutoRepeat(true);
ui->previousPushButton->setAutoRepeatInterval(50);
@@ -58,19 +61,18 @@ OscilloscopeDialog::~OscilloscopeDialog()
delete ui;
}
-void OscilloscopeDialog::showTraceImage(TbcSource::ScanLineData scanLineData, qint32 scanLine, qint32 pictureDot, qint32 frameHeight)
+void OscilloscopeDialog::showTraceImage(TbcSource::ScanLineData scanLineData, qint32 xCoord, qint32 yCoord, qint32 frameWidth, qint32 frameHeight)
{
- qDebug() << "OscilloscopeDialog::showTraceImage(): Called for scan-line" << scanLine << "with picture dot" << pictureDot;
+ qDebug() << "OscilloscopeDialog::showTraceImage(): Called with xCoord =" << xCoord << "and yCoord =" << yCoord;
- // Set the dialogue title based on the scan-line
- this->setWindowTitle("Oscilloscope trace for scan-line #" + QString::number(scanLine));
+ // Store coordinates
+ maximumX = frameWidth;
+ maximumY = frameHeight;
+ lastScopeX = xCoord;
+ lastScopeY = yCoord;
// Get the raw field data for the selected line
- QImage traceImage;
- lastScopeLine = scanLine;
- lastScopeDot = pictureDot;
-
- traceImage = getFieldLineTraceImage(scanLineData, pictureDot);
+ QImage traceImage = getFieldLineTraceImage(scanLineData, lastScopeX);
// Add the QImage to the QLabel in the dialogue
ui->scopeLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
@@ -78,12 +80,22 @@ void OscilloscopeDialog::showTraceImage(TbcSource::ScanLineData scanLineData, qi
ui->scopeLabel->setScaledContents(true);
ui->scopeLabel->setPixmap(QPixmap::fromImage(traceImage));
- // Update the scan-line spinbox
- ui->scanLineSpinBox->setMaximum(frameHeight);
- ui->scanLineSpinBox->setValue(scanLine);
+ // Update the X coordinate spinbox
+ ui->xCoordSpinBox->setMaximum(maximumX - 1);
+ ui->xCoordSpinBox->setValue(lastScopeX);
+
+ // Update the Y coordinate spinbox
+ ui->yCoordSpinBox->setMaximum(maximumY - 1);
+ ui->yCoordSpinBox->setValue(lastScopeY);
+
+ // Update the line number displays
+ ui->standardLineLabel->setText(QString("%1 line %2")
+ .arg(scanLineData.systemDescription)
+ .arg(scanLineData.lineNumber.standard()));
+ ui->fieldLineLabel->setText(QString("Field %1 line %2")
+ .arg(scanLineData.lineNumber.isFirstField() ? "1" : "2")
+ .arg(scanLineData.lineNumber.field1()));
- // Update the maximum scan-lines limit
- maximumScanLines = frameHeight;
// QT Bug workaround for some macOS versions
#if defined(Q_OS_MACOS)
repaint();
@@ -233,43 +245,50 @@ QImage OscilloscopeDialog::getFieldLineTraceImage(TbcSource::ScanLineData scanLi
void OscilloscopeDialog::on_previousPushButton_clicked()
{
- if (ui->scanLineSpinBox->value() != 1) {
- emit scanLineChanged(ui->scanLineSpinBox->value() - 1, lastScopeDot);
+ if (ui->yCoordSpinBox->value() != 0) {
+ emit scopeCoordsChanged(lastScopeX, ui->yCoordSpinBox->value() - 1);
}
}
void OscilloscopeDialog::on_nextPushButton_clicked()
{
- if (ui->scanLineSpinBox->value() < maximumScanLines) {
- emit scanLineChanged(ui->scanLineSpinBox->value() + 1, lastScopeDot);
+ if (ui->yCoordSpinBox->value() < maximumY - 1) {
+ emit scopeCoordsChanged(lastScopeX, ui->yCoordSpinBox->value() + 1);
}
}
-void OscilloscopeDialog::on_scanLineSpinBox_valueChanged(int arg1)
+void OscilloscopeDialog::on_xCoordSpinBox_valueChanged(int arg1)
+{
+ (void)arg1;
+ if (ui->xCoordSpinBox->value() != lastScopeX)
+ emit scopeCoordsChanged(ui->xCoordSpinBox->value(), lastScopeY);
+}
+
+void OscilloscopeDialog::on_yCoordSpinBox_valueChanged(int arg1)
{
(void)arg1;
- if (ui->scanLineSpinBox->value() != lastScopeLine)
- emit scanLineChanged(ui->scanLineSpinBox->value(), lastScopeDot);
+ if (ui->yCoordSpinBox->value() != lastScopeY)
+ emit scopeCoordsChanged(lastScopeX, ui->yCoordSpinBox->value() );
}
void OscilloscopeDialog::on_YCcheckBox_clicked()
{
- emit scanLineChanged(ui->scanLineSpinBox->value(), lastScopeDot);
+ emit scopeCoordsChanged(lastScopeX, lastScopeY);
}
void OscilloscopeDialog::on_YcheckBox_clicked()
{
- emit scanLineChanged(ui->scanLineSpinBox->value(), lastScopeDot);
+ emit scopeCoordsChanged(lastScopeX, lastScopeY);
}
void OscilloscopeDialog::on_CcheckBox_clicked()
{
- emit scanLineChanged(ui->scanLineSpinBox->value(), lastScopeDot);
+ emit scopeCoordsChanged(lastScopeX, lastScopeY);
}
void OscilloscopeDialog::on_dropoutsCheckBox_clicked()
{
- emit scanLineChanged(ui->scanLineSpinBox->value(), lastScopeDot);
+ emit scopeCoordsChanged(lastScopeX, lastScopeY);
}
// Mouse press event handler
@@ -322,7 +341,7 @@ void OscilloscopeDialog::mousePictureDotSelect(qint32 oX)
if (unscaledX < 0) unscaledX = 0;
// Remember the last dot selected
- lastScopeDot = unscaledX;
+ lastScopeX = unscaledX;
- emit scanLineChanged(ui->scanLineSpinBox->value(), lastScopeDot);
+ emit scopeCoordsChanged(lastScopeX, lastScopeY);
}
diff --git a/tools/ld-analyse/oscilloscopedialog.h b/tools/ld-analyse/oscilloscopedialog.h
index c8170e280..ec63c5c43 100644
--- a/tools/ld-analyse/oscilloscopedialog.h
+++ b/tools/ld-analyse/oscilloscopedialog.h
@@ -47,15 +47,16 @@ class OscilloscopeDialog : public QDialog
explicit OscilloscopeDialog(QWidget *parent = nullptr);
~OscilloscopeDialog();
- void showTraceImage(TbcSource::ScanLineData scanLineData, qint32 scanLine, qint32 pictureDot, qint32 frameHeight);
+ void showTraceImage(TbcSource::ScanLineData scanLineData, qint32 xCoord, qint32 yCoord, qint32 frameWidth, qint32 frameHeight);
signals:
- void scanLineChanged(qint32 scanLine, qint32 lastScopeDot);
+ void scopeCoordsChanged(qint32 xCoord, qint32 yCoord);
private slots:
void on_previousPushButton_clicked();
void on_nextPushButton_clicked();
- void on_scanLineSpinBox_valueChanged(int arg1);
+ void on_xCoordSpinBox_valueChanged(int arg1);
+ void on_yCoordSpinBox_valueChanged(int arg1);
void on_YCcheckBox_clicked();
void on_YcheckBox_clicked();
void on_CcheckBox_clicked();
@@ -66,10 +67,11 @@ private slots:
private:
Ui::OscilloscopeDialog *ui;
- qint32 maximumScanLines;
+ qint32 maximumX;
+ qint32 maximumY;
qint32 scopeWidth;
- qint32 lastScopeLine;
- qint32 lastScopeDot;
+ qint32 lastScopeX;
+ qint32 lastScopeY;
QImage getFieldLineTraceImage(TbcSource::ScanLineData scanLineData, qint32 pictureDot);
void mousePictureDotSelect(qint32 oX);
diff --git a/tools/ld-analyse/oscilloscopedialog.ui b/tools/ld-analyse/oscilloscopedialog.ui
index 9e5591183..2f87d1532 100644
--- a/tools/ld-analyse/oscilloscopedialog.ui
+++ b/tools/ld-analyse/oscilloscopedialog.ui
@@ -7,13 +7,13 @@
0
0
480
- 250
+ 300
480
- 250
+ 300
@@ -37,13 +37,13 @@
- 120
+ 180
130
- 100
+ 180
16777215
@@ -64,7 +64,7 @@
- 100
+ 32767
16777215
@@ -86,7 +86,7 @@
- 100
+ 32767
16777215
@@ -99,20 +99,116 @@
-
-
-
-
- 50
- 0
-
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Raised
+
+
+
+ 6
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ X:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 50
+ 28
+
+
+
+
+ 100
+ 16777215
+
+
+
+
+ -
+
+
+ Y:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 50
+ 28
+
+
+
+
+ 100
+ 16777215
+
+
+
+
+
+
+
+ -
+
+
+ SECAM line 888
-
+
+
+ -
+
+
+ Field 8 line 888
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
- 100
- 16777215
+ 20
+ 40
-
+
-
@@ -148,19 +244,6 @@
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
diff --git a/tools/ld-analyse/tbcsource.cpp b/tools/ld-analyse/tbcsource.cpp
index 2f62613a8..ac33e2ccd 100644
--- a/tools/ld-analyse/tbcsource.cpp
+++ b/tools/ld-analyse/tbcsource.cpp
@@ -335,18 +335,10 @@ TbcSource::ScanLineData TbcSource::getScanLineData(qint32 scanLine)
ScanLineData scanLineData;
LdDecodeMetaData::VideoParameters videoParameters = ldDecodeMetaData.getVideoParameters();
- // Convert the scan line into field and field line
- bool isFieldTop = true;
- qint32 fieldLine = 0;
-
- if (scanLine % 2 == 0) isFieldTop = false;
- else isFieldTop = true;
-
- if (isFieldTop) {
- fieldLine = (scanLine / 2) + 1;
- } else {
- fieldLine = (scanLine / 2);
- }
+ // Set the system and line number
+ scanLineData.systemDescription = ldDecodeMetaData.getVideoSystemDescription();
+ scanLineData.lineNumber = LineNumber::fromFrame1(scanLine, videoParameters.system);
+ const LineNumber &lineNumber = scanLineData.lineNumber;
// Set the video parameters
scanLineData.blackIre = videoParameters.black16bIre;
@@ -366,11 +358,11 @@ TbcSource::ScanLineData TbcSource::getScanLineData(qint32 scanLine)
decodeFrame();
// Get the field video and dropout data
- const SourceVideo::Data &fieldData = isFieldTop ? inputFields[inputStartIndex].data
- : inputFields[inputStartIndex + 1].data;
+ const SourceVideo::Data &fieldData = lineNumber.isFirstField() ? inputFields[inputStartIndex].data
+ : inputFields[inputStartIndex + 1].data;
const ComponentFrame &componentFrame = componentFrames[0];
- DropOuts &dropouts = isFieldTop ? firstField.dropOuts
- : secondField.dropOuts;
+ DropOuts &dropouts = lineNumber.isFirstField() ? firstField.dropOuts
+ : secondField.dropOuts;
scanLineData.composite.resize(videoParameters.fieldWidth);
scanLineData.luma.resize(videoParameters.fieldWidth);
@@ -378,14 +370,14 @@ TbcSource::ScanLineData TbcSource::getScanLineData(qint32 scanLine)
for (qint32 xPosition = 0; xPosition < videoParameters.fieldWidth; xPosition++) {
// Get the 16-bit composite value for the current pixel (frame data is numbered 0-624 or 0-524)
- scanLineData.composite[xPosition] = fieldData[((fieldLine - 1) * videoParameters.fieldWidth) + xPosition];
+ scanLineData.composite[xPosition] = fieldData[(lineNumber.field0() * videoParameters.fieldWidth) + xPosition];
// Get the decoded luma value for the current pixel (only computed in the active region)
scanLineData.luma[xPosition] = static_cast(componentFrame.y(scanLine - 1)[xPosition]);
scanLineData.isDropout[xPosition] = false;
for (qint32 doCount = 0; doCount < dropouts.size(); doCount++) {
- if (dropouts.fieldLine(doCount) == fieldLine) {
+ if (dropouts.fieldLine(doCount) == lineNumber.field1()) {
if (xPosition >= dropouts.startx(doCount) && xPosition <= dropouts.endx(doCount)) scanLineData.isDropout[xPosition] = true;
}
}
diff --git a/tools/ld-analyse/tbcsource.h b/tools/ld-analyse/tbcsource.h
index 316687e1b..c38600961 100644
--- a/tools/ld-analyse/tbcsource.h
+++ b/tools/ld-analyse/tbcsource.h
@@ -35,6 +35,7 @@
// TBC library includes
#include "sourcevideo.h"
#include "lddecodemetadata.h"
+#include "linenumber.h"
#include "vbidecoder.h"
#include "filters.h"
@@ -50,6 +51,8 @@ class TbcSource : public QObject
explicit TbcSource(QObject *parent = nullptr);
struct ScanLineData {
+ QString systemDescription;
+ LineNumber lineNumber;
QVector composite;
QVector luma;
QVector isDropout;