Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Catch up with parent repo #6

Merged
merged 11 commits into from
Sep 5, 2022
1 change: 1 addition & 0 deletions lddecode/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3982,6 +3982,7 @@ def build_json(self, f):
vp = {}

vp["numberOfSequentialFields"] = len(self.fieldinfo)
vp["osInfo"] = f'{platform.system()}:{platform.release()}:{platform.version()}'

if f is None:
return
Expand Down
2 changes: 1 addition & 1 deletion tools/ld-analyse/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -601,7 +601,7 @@ void MainWindow::on_actionSave_frame_as_PNG_triggered()
else filenameSuggestion += tr("ar43_");
}

filenameSuggestion += QString::number(currentFrameNumber) + tr(".png");
filenameSuggestion += QString::number(currentFrameNumber) + "_" + tbcSource.getCurrentSourceFilename().split("/").last() + tr(".png");

QString pngFilename = QFileDialog::getSaveFileName(this,
tr("Save PNG file"),
Expand Down
5 changes: 2 additions & 3 deletions tools/ld-chroma-decoder/comb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,9 +533,8 @@ namespace {

// Rotate the burst angle to get the correct values.
// We do the 33 degree rotation here to avoid computing it for every pixel.
// TODO: additionally we need to rotate another ~10 degrees to get the correct hue, find out why.
constexpr double ROTATE_SIN = 0.6819983600624985;
constexpr double ROTATE_COS = 0.7313537016191705;
constexpr double ROTATE_SIN = 0.5446390350150271;
constexpr double ROTATE_COS = 0.838670567945424;

BurstInfo detectBurst(const quint16* lineData,
const LdDecodeMetaData::VideoParameters& videoParameters)
Expand Down
40 changes: 19 additions & 21 deletions tools/ld-chroma-decoder/encoder/ntscencoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,14 @@ NTSCEncoder::NTSCEncoder(QFile &_rgbFile, QFile &_tbcFile, QFile &_chromaFile, L
// Each 63.555 usec line is 910 samples long. The values
// in this struct represent the sample numbers *on the first line*.
//
// Each line in the output TBC consists of a series of blanking samples
// followed by a series of active samples [SMPTE p4] -- different from
// ld-decode, which starts each line with the leading edge of the
// horizontal sync pulse (0H).
//
// The first sample in the TBC frame is the first blanking sample of
// field 1 line 1, sample 768 of 910. 0H occurs 33/90 between samples
// 784 and 785. [SMPTE p4]

// Subcarrier is co-incident with 0H, i.e. SCH phase is 0. [Poynton p511]
const double zeroH = 784 + 33.0 / 90.0 - 768;

// Burst gate opens 19 cycles after 0H, and closes 9 cycles later.
Expand Down Expand Up @@ -114,7 +117,7 @@ void NTSCEncoder::getFieldMetadata(qint32 fieldNo, LdDecodeMetaData::Field &fiel
fieldData.isFirstField = (fieldNo % 2) == 0;
fieldData.syncConf = 100;
fieldData.medianBurstIRE = 20;
fieldData.fieldPhaseID = (fieldNo + fieldOffset) % 4;
fieldData.fieldPhaseID = ((fieldNo + fieldOffset) % 4) + 1;
fieldData.audioSamples = 0;
}

Expand Down Expand Up @@ -182,26 +185,21 @@ void NTSCEncoder::encodeLine(qint32 fieldNo, qint32 frameLine, const quint16 *rg
}

// How many complete lines have gone by since the start of the 4-field
// sequence? Subcarrier is positive going at line 10, so adjust for
// that here. [SMPTE p3]
// sequence?
const qint32 fieldID = (fieldNo + fieldOffset) % 4;
qint32 prevLines = ((fieldID / 2) * 525) + ((fieldID % 2) * 263) + (frameLine / 2) - 10;
// XXX The third field shouldn't be special like this. If anything,
// colorframe B needs something, but prevLines seems correct.
if (fieldID == 2)
prevLines--;

// Subcarrier is co-incident with 0H which is 33/90 after sample 784
// [SMPTE p5] [Poynton p511]
const qint32 prevLines = ((fieldID / 2) * 525) + ((fieldID % 2) * 263) + (frameLine / 2);

// Compute the time at which 0H occurs within the line (see above).
const double zeroH = (784 + 33.0 / 90.0 - 768) / videoParameters.sampleRate;

// How many cycles of the subcarrier have gone by at 0H? [Poynton p511]
// There are 227.5 cycles per lines (910/4). 0H is offset 33/90 of one
// sample, which is 33/360 of one 4-sample cycle.
const double prevCycles = prevLines * 227.5 + 33.0 / 360.0;
// How many cycles of the subcarrier have gone by at 0H?
// There are 227.5 cycles per line (910/4). [Poynton p511]
// Subtract 1/4 cycle because the burst is inverted but it should be
// crossing zero and going positive at the start of the field sequence.
const double prevCycles = (prevLines * 227.5) - 0.25;

// The colorburst is inverted from subcarrier [SMPTE p4] [Poynton p512]
const double burstOffset = 227.5 * M_PI / 180.0;
const double burstOffset = 180.0 * M_PI / 180.0;

// Burst peak-to-peak amplitude is 2/5 of black-white range
// [Poynton p516 eq 42.6]
Expand Down Expand Up @@ -303,11 +301,11 @@ void NTSCEncoder::encodeLine(qint32 fieldNo, qint32 frameLine, const quint16 *rg
// Encode the chroma signal
double chroma;
if (chromaMode == WIDEBAND_YUV) {
// Y'UV [Poynton p338], offset 57 degrees
chroma = C1[x] * sin(a + 57.0 * M_PI / 180.0) + C2[x] * cos(a + 57.0 * M_PI / 180.0);
// Y'UV [Poynton p338]
chroma = C1[x] * sin(a) + C2[x] * cos(a);
} else {
// Y'IQ [Poynton p368]
chroma = C2[x] * sin(a + 33.0) + C1[x] * cos(a + 33.0);
chroma = C2[x] * sin(a + 33.0 * M_PI / 180.0) + C1[x] * cos(a + 33.0 * M_PI / 180.0);
}

// Generate C output
Expand Down
5 changes: 5 additions & 0 deletions tools/ld-chroma-decoder/encoder/palencoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ PALEncoder::PALEncoder(QFile &_rgbFile, QFile &_tbcFile, QFile &_chromaFile, LdD
// moves to the right by (4 / 625) samples on each line. The values
// in this struct represent the sample numbers *on the first line*.
//
// Each line in the output TBC consists of a series of blanking samples
// followed by a series of active samples [EBU p9] -- different from
// ld-decode, which starts each line with the leading edge of the
// horizontal sync pulse (0H).
//
// The first sample in the TBC frame is the first blanking sample of
// field 1 line 1, sample 948 of 1135. 0H occurs midway between samples
// 957 and 958. [EBU p7]
Expand Down
45 changes: 32 additions & 13 deletions tools/ld-disc-stacker/stackingpool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,20 @@ bool StackingPool::getInputFrame(qint32& frameNumber,
// Use VBI frame number mapping to get the same frame from the
// current additional source
qint32 currentSourceFrameNumber = convertVbiFrameNumberToSequential(currentVbiFrame, sourceNo);
firstFieldNumber[sourceNo] = ldDecodeMetaData[sourceNo]->getFirstFieldNumber(currentSourceFrameNumber);
secondFieldNumber[sourceNo] = ldDecodeMetaData[sourceNo]->getSecondFieldNumber(currentSourceFrameNumber);

qDebug().nospace() << "Source #" << sourceNo << " has VBI frame number " << currentVbiFrame <<
" and fields " << firstFieldNumber[sourceNo] << "/" << secondFieldNumber[sourceNo];
// Check the current source contains the frame
if (ldDecodeMetaData[sourceNo]->getNumberOfFrames() < currentSourceFrameNumber) {
firstFieldNumber[sourceNo] = -1;
secondFieldNumber[sourceNo] = -1;

qDebug().nospace() << "Source #" << sourceNo << " does not contain VBI frame number " << currentVbiFrame;
} else {
firstFieldNumber[sourceNo] = ldDecodeMetaData[sourceNo]->getFirstFieldNumber(currentSourceFrameNumber);
secondFieldNumber[sourceNo] = ldDecodeMetaData[sourceNo]->getSecondFieldNumber(currentSourceFrameNumber);

qDebug().nospace() << "Source #" << sourceNo << " has VBI frame number " << currentVbiFrame <<
" and fields " << firstFieldNumber[sourceNo] << "/" << secondFieldNumber[sourceNo];
}
} else {
qDebug().nospace() << "Source #" << sourceNo << " does not contain a usable frame";
}
Expand Down Expand Up @@ -397,16 +406,26 @@ QVector<qint32> StackingPool::getAvailableSourcesForFrame(qint32 vbiFrameNumber)
QVector<qint32> availableSourcesForFrame;
for (qint32 sourceNo = 0; sourceNo < sourceVideos.size(); sourceNo++) {
if (vbiFrameNumber >= sourceMinimumVbiFrame[sourceNo] && vbiFrameNumber <= sourceMaximumVbiFrame[sourceNo]) {
// Get the field numbers for the frame
qint32 firstFieldNumber = ldDecodeMetaData[sourceNo]->getFirstFieldNumber(convertVbiFrameNumberToSequential(vbiFrameNumber, sourceNo));
qint32 secondFieldNumber = ldDecodeMetaData[sourceNo]->getSecondFieldNumber(convertVbiFrameNumberToSequential(vbiFrameNumber, sourceNo));

// Ensure the frame is not a padded field (i.e. missing)
if (ldDecodeMetaData[sourceNo]->getField(firstFieldNumber).pad == false && ldDecodeMetaData[sourceNo]->getField(secondFieldNumber).pad == false) {
availableSourcesForFrame.append(sourceNo);
// Get the field numbers for the frame - THIS CRASHES
qint32 sequentialFrameNumber = convertVbiFrameNumberToSequential(vbiFrameNumber, sourceNo);

// Check the source contains enough frames to have the required sequential frame
if (ldDecodeMetaData[sourceNo]->getNumberOfFrames() < sequentialFrameNumber)
{
// Sequential frame is out of bounds
qDebug() << "VBI Frame number" << vbiFrameNumber << "is out of bounds for source " << sourceNo;
} else {
if (ldDecodeMetaData[sourceNo]->getField(firstFieldNumber).pad == true) qDebug() << "First field number" << firstFieldNumber << "of source" << sourceNo << "is padded";
if (ldDecodeMetaData[sourceNo]->getField(secondFieldNumber).pad == true) qDebug() << "Second field number" << firstFieldNumber << "of source" << sourceNo << "is padded";
// Sequential frame is in bounds
qint32 firstFieldNumber = ldDecodeMetaData[sourceNo]->getFirstFieldNumber(sequentialFrameNumber);
qint32 secondFieldNumber = ldDecodeMetaData[sourceNo]->getSecondFieldNumber(sequentialFrameNumber);

// Ensure the frame is not a padded field (i.e. missing)
if (ldDecodeMetaData[sourceNo]->getField(firstFieldNumber).pad == false && ldDecodeMetaData[sourceNo]->getField(secondFieldNumber).pad == false) {
availableSourcesForFrame.append(sourceNo);
} else {
if (ldDecodeMetaData[sourceNo]->getField(firstFieldNumber).pad == true) qDebug() << "First field number" << firstFieldNumber << "of source" << sourceNo << "is padded";
if (ldDecodeMetaData[sourceNo]->getField(secondFieldNumber).pad == true) qDebug() << "Second field number" << firstFieldNumber << "of source" << sourceNo << "is padded";
}
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions tools/ld-lds-converter/dataconverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,8 @@ void DataConverter::unpackFile(void)

// Are we writing a RIFF header?
if (isRIFF) {
// Writes a WAV RIFF header, 44.1k, mono, 16-bit signed
QString riffHex = "52494646FFFFFFFF57415645666D7420100000000100010044AC000088580100020010004C4953541A000000494E464F495346540E0000004C61766635382E32392E3130300064617461FFFFFFFF";
// Writes a WAV RIFF header, 40k, mono, 16-bit signed
QString riffHex = "52494646FFFFFFFF57415645666D74201000000001000100409C000088580100020010004C4953541A000000494E464F495346540E0000004C61766635382E32392E3130300064617461FFFFFFFF";
QByteArray riffArray = QByteArray::fromHex(riffHex.toLatin1());
outputFileHandle->write(riffArray);
}
Expand Down
2 changes: 1 addition & 1 deletion tools/ld-lds-converter/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ int main(int argc, char *argv[])

// Option to unpack 10-bit data with RIFF WAV headers (-r)
QCommandLineOption showRIFFOption(QStringList() << "r" << "riff",
QCoreApplication::translate("main", "Unpack 10-bit data into 16-bit with RIFF WAV headers"));
QCoreApplication::translate("main", "Unpack 10-bit data into 16-bit with RIFF WAV headers (use this ONLY for FlaCCL)"));
parser.addOption(showRIFFOption);

// Process the command line arguments given by the user
Expand Down