diff --git a/scripts/ld-compress b/scripts/ld-compress index 0adeedb1c..fde8284e8 100755 --- a/scripts/ld-compress +++ b/scripts/ld-compress @@ -4,20 +4,24 @@ modeselection=0 comp=true uncomp=false verify=false +gpu=false +setup=false fileinput_method=cat level=11 ext=ldf help_msg () { - echo "Usage: $0 [-c] [-u] [-v] [-p] [-h] [-l <1-12>] [-g] file(s)"; printf -- "\nModes:\n-c Compress (default): Takes one or more .lds files and compresses them to .ldf files in the current directory.\n-u Uncompress: Takes one or more .ldf/.raw.oga files and uncompresses them to .lds files in the current directory.\n-v Verify: Returns md5 checksums of the given .ldf/.raw.oga files and their contained .lds files for verification purposes.\n\nOptions\n-p Progress: displays progress bars - requires pv to be installed.\n-h Help: This dialog.\n-l Compression level 1 - 12. Default is 11. 6 is recommended for faster but fair compression.\n-g Use .raw.oga extension instead of .ldf when compressing.\n\n" + echo "Usage: $0 [-c] [-a] [-u] [-v] [-s] [-p] [-h] [-l <1-12>] [-g] file(s)"; printf -- "\nModes:\n-c Compress (default): Takes one or more .lds files and compresses them to .ldf files in the current directory.\n-u Uncompress: Takes one or more .ldf/.raw.oga files and uncompresses them to .lds files in the current directory.\n-a GPU Acceleration. Uses OpenCL or CUDA to accelerate encoding.\n-v Verify: Returns md5 checksums of the given .ldf/.raw.oga files and their contained .lds files for verification purposes.\n-s Setup: Set up GPU acceleration requirements. Modifies mono for OpenCL support and installs FLACCL.\nOptions\n-p Progress: displays progress bars - requires pv to be installed.\n-h Help: This dialog.\n-l Compression level 1 - 12. Default is 11. 6 is recommended for faster but fair compression.\n-g Use .raw.oga extension instead of .ldf when compressing.\n\n" } -while getopts ":hcuvpl:g" option; do +while getopts ":hcauvspl:g" option; do case $option in h) help_msg ; exit ;; c) comp=true ; modeselection=$((modeselection+1)) ;; u) uncomp=true ; comp=false ; modeselection=$((modeselection+1)) ;; + a) gpu=true ; comp=false ; modeselection=$((modeselection+1)) ;; v) verify=true ; comp=false ; modeselection=$((modeselection+1)) ;; + s) setup=true ; comp=false ; modeselection=$((modeselection+1)) ;; p) fileinput_method="pv" ;; l) level=${OPTARG} @@ -40,7 +44,7 @@ done shift $(( OPTIND - 1 )) # Check if input files have been entered, and if so, process according to the selected mode. -if [[ $# < 1 ]] +if [[ $# < 1 ]] && [[ "$setup" == false ]] then help_msg ; exit else @@ -61,6 +65,20 @@ else fi done fi + if [[ "$gpu" == true ]] # Perform GPU accelerated compression + then + # Increment compression level down by one to compensate for FLACCL's 0-11 compression levels, vs ffmpeg's 1-12 + ((level=level-1)) + for f in "$@" ; do + if [[ "$f" == *.lds ]] + then + echo $level + >&2 echo Compressing \'"$f"\' to \'"$(basename "$f" .lds).$ext"\' && ${fileinput_method} "$f" | ld-lds-converter -r -u | mono /opt/flaccl/CUETools.FLACCL.cmd.exe - --ignore-chunk-sizes -q -"$level" --lax -o "$(basename "$f" .lds).$ext" && >&2 echo \'"$(basename "$f" .lds).$ext"\' written. + else + >&2 echo Error: \'"$f"\' does not appear to be a .lds file. Skipping. + fi + done + fi if [[ "$uncomp" == true ]] # Perfom uncompression then for f in "$@" ; do @@ -86,6 +104,24 @@ else fi done fi + if [[ "$setup" == true ]] # Setup GPU acceleration support + then + # Check if /opt/flaccl is present + FLADIR=/opt/flaccl + if [ ! -d "$FLADIR" ] + then + mkdir /opt/flaccl + fi + # Download FLACCL 2.2.1 and install + wget -q https://github.com/gchudov/cuetools.net/releases/download/v2.2.1/CUETools_2.2.1.zip -P /tmp/ + unzip -qq -o /tmp/CUETools_2.2.1.zip -d /opt/flaccl + rm /tmp/CUETools_2.2.1.zip + # Check if mono is configured for OpenCL + if ! grep -e '' /etc/mono/config > /dev/null + then + sudo sed -i '$i\ ' /etc/mono/config + fi + fi sleep 1 >&2 echo "Task complete." fi diff --git a/tools/ld-lds-converter/dataconverter.cpp b/tools/ld-lds-converter/dataconverter.cpp index c502d3894..76b801c07 100644 --- a/tools/ld-lds-converter/dataconverter.cpp +++ b/tools/ld-lds-converter/dataconverter.cpp @@ -24,12 +24,13 @@ #include "dataconverter.h" -DataConverter::DataConverter(QString inputFileNameParam, QString outputFileNameParam, bool isPackingParam, QObject *parent) : QObject(parent) +DataConverter::DataConverter(QString inputFileNameParam, QString outputFileNameParam, bool isPackingParam, bool isRIFFParam, QObject *parent) : QObject(parent) { // Store the configuration parameters inputFileName = inputFileNameParam; outputFileName = outputFileNameParam; isPacking = isPackingParam; + isRIFF = isRIFFParam; } // Method to process the conversion of the file @@ -117,9 +118,11 @@ bool DataConverter::openOutputFile(void) return false; } qDebug() << "Writing output data to stdout"; + } else { // Open the output file for writing outputFileHandle = new QFile(outputFileName); + if (!outputFileHandle->open(QIODevice::WriteOnly)) { // Failed to open output file qDebug() << "DataConverter::openOutputFile(): Could not open" << outputFileName << "as output file"; @@ -225,6 +228,15 @@ void DataConverter::unpackFile(void) QByteArray outputBuffer; bool isComplete = false; + // Are we writing a RIFF header? + if (isRIFF) { + // Writes a WAV RIFF header, 44.1k, mono, 16-bit signed + QString riffHex = "52494646FFFFFFFF57415645666D7420100000000100010044AC000088580100020010004C4953541A000000494E464F495346540E0000004C61766635382E32392E3130300064617461FFFFFFFF"; + QByteArray riffArray = QByteArray::fromHex(riffHex.toLatin1()); + outputFileHandle->write(riffArray); + } + + while(!isComplete) { // Input buffer must be divisible by 5 bytes due to 10-bit data format qint32 bufferSizeInBytes = (5 * 1024 * 1024) * 4; // 5MiB * 4 = 20MiBytes diff --git a/tools/ld-lds-converter/dataconverter.h b/tools/ld-lds-converter/dataconverter.h index 2cbc4ec3f..61bc83de4 100644 --- a/tools/ld-lds-converter/dataconverter.h +++ b/tools/ld-lds-converter/dataconverter.h @@ -33,7 +33,7 @@ class DataConverter : public QObject { Q_OBJECT public: - explicit DataConverter(QString inputFileNameParam, QString outputFileNameParam, bool isPackingParam, QObject *parent = nullptr); + explicit DataConverter(QString inputFileNameParam, QString outputFileNameParam, bool isPackingParam, bool isRIFFParam, QObject *parent = nullptr); bool process(void); signals: @@ -44,6 +44,7 @@ public slots: QString inputFileName; QString outputFileName; bool isPacking; + bool isRIFF; QFile *inputFileHandle; QFile *outputFileHandle; diff --git a/tools/ld-lds-converter/main.cpp b/tools/ld-lds-converter/main.cpp index 6b50bd8e7..f418bd436 100644 --- a/tools/ld-lds-converter/main.cpp +++ b/tools/ld-lds-converter/main.cpp @@ -78,6 +78,11 @@ int main(int argc, char *argv[]) QCoreApplication::translate("main", "Pack 16-bit data into 10-bit")); parser.addOption(showPackOption); + // 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")); + parser.addOption(showRIFFOption); + // Process the command line arguments given by the user parser.process(a); @@ -87,12 +92,16 @@ int main(int argc, char *argv[]) // Get the configured settings from the parser bool isUnpacking = parser.isSet(showUnpackOption); bool isPacking = parser.isSet(showPackOption); + bool isRIFF = parser.isSet(showRIFFOption); QString inputFileName = parser.value(sourceVideoFileOption); QString outputFileName = parser.value(targetVideoFileOption); bool modeUnpack = true; if (isPacking) modeUnpack = false; + bool modeRIFF = false; + if (isRIFF) modeRIFF = true; + // Check that both pack and unpack are not set if (isUnpacking && isPacking) { // Quit with error @@ -100,8 +109,15 @@ int main(int argc, char *argv[]) return -1; } + // Check that RIFF option is not set with pack (only unpack) + if (isRIFF && ! isUnpacking) { + // Quit with error + qCritical("You can only write RIFF headers with --unpack (-u)"); + return -1; + } + // Initialise the data conversion object - DataConverter dataConverter(inputFileName, outputFileName, !modeUnpack); + DataConverter dataConverter(inputFileName, outputFileName, !modeUnpack, modeRIFF); // Process the data conversion dataConverter.process();