Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d0c022e
Adding jpeg2000 codec.
richardssam Nov 10, 2024
30df985
WIP, Had problems running this in a docker container, since the timin…
richardssam Nov 10, 2024
339be36
A bit more docker ffmpeg-7.1 cleanup dont need aces now, since it com…
richardssam Nov 10, 2024
1290b92
Adding the terrific parallel-frames flag, for faster conversion.
richardssam Nov 10, 2024
9006999
Added tests for htj2k, currently relying on ppm files.
richardssam Nov 10, 2024
2e9b7dc
Wrapper script for generating h2k files and then wrapping in mxf (or …
richardssam Nov 10, 2024
d6bfbf2
Frame range fix.
richardssam Nov 10, 2024
561fd05
Lets just use DPX files since they are supported.
richardssam Nov 10, 2024
7847a1a
Update new model location.
richardssam Nov 10, 2024
4d49b02
Update env location so it works on both osx and docker/rockylinux
richardssam Nov 10, 2024
304cf08
This is measuring fps rates, purely using ffmpeg.
richardssam Nov 10, 2024
14d6ab0
Adding a bunch of htj2k tests.
richardssam Feb 19, 2025
16f786a
Adding a dwab test.
richardssam Feb 19, 2025
c0f2863
Wrappers to help map htj2k and dwab into the encoding framework.
richardssam Feb 19, 2025
586110b
Adding some of the 4k media as reference.
richardssam Feb 19, 2025
b4607da
Adding support for cambi.
richardssam Feb 19, 2025
9e3e858
Put each bit of media in a separate folder.
richardssam Feb 19, 2025
ec3ba74
UPgrade to use the vmaf3 code, and do some better comparisons.
richardssam Feb 19, 2025
5630c70
New templates for vmaf3.
richardssam Feb 19, 2025
2aed2d9
Handle the cambi and other parameters into the template better.
richardssam Apr 2, 2025
dba84fb
Special case to handle QFactor= parameters, although this would work …
richardssam Apr 2, 2025
d36613a
comments, and labeling.
richardssam Apr 2, 2025
f7e3f81
Dont need this varient.
richardssam Apr 2, 2025
9a9f163
Adding the vmaf3 test.
richardssam Apr 2, 2025
6d699de
Too extreme, makes graph hard to read.
richardssam Apr 2, 2025
f500d27
Note for getting exr versions of some of the files.
richardssam Apr 2, 2025
8385756
Enable ffplay, so we can do some of the playback testing on the VM.
richardssam Apr 2, 2025
d037067
Improve units here and there.
richardssam Apr 2, 2025
135693d
Merge branch 'main' into htj2k_fixes
richardssam Apr 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 1 addition & 13 deletions docker/ffmpeg-7.1/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -653,18 +653,6 @@ RUN \
make qt-faststart && cp qt-faststart ${PREFIX}/bin/


RUN \
echo "Downloading ACES." && \
DIR=/opt/aces && \
mkdir -p ${DIR} && \
cd ${DIR} && \
curl -sLO https://github.com/colour-science/OpenColorIO-Configs/archive/refs/tags/v1.2.tar.gz && \
tar zxvf v1.2.tar.gz OpenColorIO-Configs-1.2/aces_1.2 && \
rm v1.2.tar.gz && \
mkdir -p /usr/share/ocio/aces_1.2 && \
cp -vr ${DIR}/OpenColorIO-Configs-1.2/aces_1.2 /usr/share/ocio && \
rm -rf ${DIR}

RUN \
ldd ${PREFIX}/bin/ffmpeg | grep opt/ffmpeg | cut -d ' ' -f 3 | xargs -i cp {} /usr/local/lib64/ && \
for lib in /usr/local/lib64/*.so.*; do ln -s "${lib##*/}" "${lib%%.so.*}".so; done && \
Expand All @@ -690,7 +678,7 @@ RUN \
# Need to add /opt/rh/httpd24/root/usr/lib64/ to get git clone to work.

ENV LD_LIBRARY_PATH=/usr/local/lib64:/usr/local/lib:/opt/rh/httpd24/root/usr/lib64/ \
OCIO=/usr/share/ocio/aces_1.2/config.ocio \
OCIO=ocio://studio-config-v1.0.0_aces-v1.3_ocio-v2.1 \
VMAF_MODEL=${VMAF_LIB_DIR}

RUN pip install OpenTimelineIO
Expand Down
2 changes: 1 addition & 1 deletion docker/rocky-ffmpeg-7.0/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ RUN \
--disable-doc \
# --enable-cuda-nvcc \
--enable-libnpp \
--disable-ffplay \
# --disable-ffplay \
--enable-fontconfig \
--enable-cuda-nvcc \
--enable-gpl \
Expand Down
2 changes: 1 addition & 1 deletion enctests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ rm v1.2.tar.gz
export OCIO=$PWD/OpenColorIO-Configs-1.2/aces_1.2/config.ocio
# Set VMAF_Models NOTE, should probably change this.
export VMAF_MODEL=/opt/homebrew/Cellar/libvmaf/2.3.1/share/libvmaf/model/
export VMAF_MODEL_DIR=/opt/homebrew/Cellar/libvmaf/3.0.0/share/libvmaf/model/

# Run tests (for now)
.venv/bin/python main.py
Expand Down
126 changes: 126 additions & 0 deletions enctests/bin/generic_encodewrap.csh
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#!/usr/bin/env python3


import os, sys
import argparse
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
from functools import partial
import subprocess

# This allows you to compress the file with the compressor of your choice, and then wrap the result in a quicktime file
# So we can do the comparison with vmaf.
# We assume that what ever the intermediate compressor is doing that the resulting intermediate file is a png file.

def process_file(args, tmpoutputdir, ext, file_path):
input_path = Path(file_path)
output_path = Path(os.path.join(tmpoutputdir, os.path.basename(str(input_path)))).with_suffix(ext)
if os.path.exists(str(output_path)):
print("Removing file:", output_path)
os.remove(str(output_path))
try:
# Your processing here
# Example: copy file with new extension
cmd = args[:]
cmd.extend(['-i', file_path])

cmd.extend(["-o", str(output_path)])
print("Running:", " ".join(cmd))
subprocess.run(cmd)
return True, input_path, output_path
except Exception as e:
print("ERROR:", e)
return False, input_path, str(e)

def main():
print("Root:", os.path.dirname(os.path.abspath(__file__)))
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + ":" + os.environ['PATH']

parser = argparse.ArgumentParser()

parser.add_argument(
'-i', '--input',
dest="input",
action='store',
default=[""],
help='Provide an input file.'
)
parser.add_argument(
'-start_number',
dest="start_frame",
default="0",
help='Start frame for input file.'
)
parser.add_argument(
'-r',
dest="framerate",
default="25",
help='Frame rate'
)

parser.add_argument(
'--extension',
dest="extension",
default="png",
help='Intermediate extension'
)

args, otherargs = parser.parse_known_args()
ext = args.extension
print("EXT:", ext)
outputfile = otherargs[-1]
otherargs = otherargs[:-1] #Strip of the last argument.

# Configure number of workers
max_workers = 4

outputdir = os.path.dirname(outputfile)
tmpoutputdir = os.path.join(outputdir, "tmppngfiles", os.path.basename(outputfile))
if not os.path.exists(tmpoutputdir):
os.makedirs(tmpoutputdir)

# Get list of files
inputfile = args.input
print("Processing input file spec:", inputfile)
files = []
if "%" in inputfile:
startframe = int(args.start_frame)
infile = inputfile % startframe
while os.path.exists(infile):
files.append(infile)
startframe = startframe + 1
infile = inputfile % startframe
print("Checking:", infile)
else:
files.append(inputfile)
# files = list(Path('directory').glob('*.txt'))

# Process files with progress bar
with ThreadPoolExecutor(max_workers=max_workers) as executor:
results = executor.map(partial(process_file, otherargs, str(tmpoutputdir), "." + ext), files)

# Report results
successes = [r for r in results if r[0]]
failures = [r for r in results if not r[0]]

print(f"\nProcessed {len(successes)} files successfully")
if failures:
print(f"Failed to process {len(failures)} files:")
for _, input_path, error in failures:
print(f" {input_path}: {error}")
else:
intputfilej2k = str(Path(os.path.join(tmpoutputdir, os.path.basename(inputfile))).with_suffix("." + ext))
cmd = ['ffmpeg', '-f', 'image2', '-r', args.framerate,
'-start_number', args.start_frame, '-i', intputfilej2k, '-vcodec', 'copy',
'-color_range', '1', '-colorspace', '1', '-color_primaries', '1',
'-color_trc', '2', '-y', outputfile]
print(" ".join(cmd))
subprocess.run(cmd)
# Now we remove the intermediate files.




if __name__ == '__main__':
main()

122 changes: 122 additions & 0 deletions enctests/bin/htj2k_encodewrap.csh
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#!/usr/bin/env python3


import os
import argparse
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
from functools import partial
import subprocess

# This allows you to do the encoding of a j2h file in a different app, and then wrap the result into a movie file with ffmpeg.

def process_file(args, tmpoutputdir, file_path):
input_path = Path(file_path)
output_path = Path(os.path.join(tmpoutputdir, os.path.basename(str(input_path)))).with_suffix('.j2c')
if os.path.exists(str(output_path)):
print("Removing file:", output_path)
os.remove(str(output_path))
try:
# Your processing here
# Example: copy file with new extension
cmd = [f.replace("--reversible", "-reversible") for f in args[:]]
cmd.extend(['-i', file_path, "-o", str(output_path)])
print("Running:", " ".join(cmd))
subprocess.run(cmd)
return True, input_path, output_path
except Exception as e:
print("ERROR:", e)
return False, input_path, str(e)

def main():
parser = argparse.ArgumentParser()

parser.add_argument(
'-i', '--input',
dest="input",
action='store',
default=[""],
help='Provide an input file.'
)
parser.add_argument(
'-start_number',
dest="start_frame",
default="0",
help='Start frame for input file.'
)
parser.add_argument(
'-r',
dest="framerate",
default="25",
help='Frame rate'
)

args, otherargs = parser.parse_known_args()
outputfile = otherargs[-1]
otherargs = otherargs[:-1] #Strip of the last argument.

# Need to look for arguments ending in "=" so we know to merge with next arg.
# so ["Qfactor=", "40", "Clevels=", "5"] would become ['Qfactor=40', 'Clevels=5']
newotherargs = []
while otherargs:
print("OTHERARGS:", otherargs)
arg = otherargs.pop(0)
if arg.endswith("="):
nextarg = otherargs.pop(0)
arg = arg[:-1] + "=" + nextarg
newotherargs.append(arg)
otherargs = newotherargs

# Configure number of workers
max_workers = 4

outputdir = os.path.dirname(outputfile)
tmpoutputdir = os.path.join(outputdir, "tmpj2kfiles", os.path.basename(outputfile))
if not os.path.exists(tmpoutputdir):
os.makedirs(tmpoutputdir)

# Get list of files
inputfile = args.input
print("Processing input file spec:", inputfile)
files = []
if "%" in inputfile:
startframe = int(args.start_frame)
infile = inputfile % startframe
while os.path.exists(infile):
files.append(infile)
startframe = startframe + 1
infile = inputfile % startframe
print("Checking:", infile)
else:
files.append(inputfile)
# files = list(Path('directory').glob('*.txt'))

# Process files with progress bar
with ThreadPoolExecutor(max_workers=max_workers) as executor:
results = executor.map(partial(process_file, otherargs, str(tmpoutputdir)), files)

# Report results
successes = [r for r in results if r[0]]
failures = [r for r in results if not r[0]]

print(f"\nProcessed {len(successes)} files successfully")
if failures:
print(f"Failed to process {len(failures)} files:")
for _, input_path, error in failures:
print(f" {input_path}: {error}")
else:
intputfilej2k = str(Path(os.path.join(tmpoutputdir, os.path.basename(inputfile))).with_suffix('.j2c'))
cmd = ['ffmpeg', '-f', 'image2', '-r', args.framerate,
'-start_number', args.start_frame, '-i', intputfilej2k, '-vcodec', 'copy',
'-color_range', '1', '-colorspace', '1', '-color_primaries', '1',
'-color_trc', '2', '-y', outputfile]
print("Running:", " ".join(cmd))
subprocess.run(cmd)
# Now we remove the intermediate files.




if __name__ == '__main__':
main()

95 changes: 95 additions & 0 deletions enctests/bin/htj2k_encodewrap_oiio.csh
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#!/usr/bin/env python3


import os
import argparse
from concurrent.futures import ThreadPoolExecutor
from pathlib import Path
from functools import partial
import subprocess



def main():
parser = argparse.ArgumentParser()

parser.add_argument(
'-i', '--input',
dest="input",
action='store',
default=[""],
help='Provide an input file.'
)
parser.add_argument(
'-start_number',
dest="start_frame",
default="0",
help='Start frame for input file.'
)
parser.add_argument(
'-r',
dest="framerate",
default="25",
help='Frame rate'
)

args, otherargs = parser.parse_known_args()
file_path = args.input
outputfile = otherargs[-1]
otherargs = otherargs[:-1] #Strip of the last argument.

input_path = Path(file_path)

outputdir = os.path.dirname(outputfile)
tmpoutputdir = os.path.join(outputdir, "tmpj2kfiles", os.path.basename(outputfile))
)
output_path = Path(os.path.join(tmpoutputdir, os.path.basename(str(input_path)))).with_suffix('.j2c')

if not os.path.exists(tmpoutputdir):
os.makedirs(tmpoutputdir)

# Get list of files
inputfile = args.input

oiio_args = []
launch_arg = otherargs.pop(0) # Get rid of the app to run.
arg = otherargs.pop(0)
while otherargs:
if arg.startswith("-jph:"):
oiio_args.append("--attrib")
oiio_args.append(arg.replace("-jph:", "jph:"))
arg = otherargs.pop(0)
oiio_args.append(arg)
else:
print("Misc arg:", arg)
oiio_args.append(arg)
if not otherargs:
break
arg = otherargs.pop(0)

endframe = int(args.start_frame)
file = str(input_path) % endframe
print("FILE:", file, " from :", input_path)
while(os.path.exists(str(input_path) % endframe)):
endframe += 1
endframe -= 1

oiio_args = [launch_arg, '-v', '-i', str(input_path), "--parallel-frames", "--frames", "%s-%d" % (args.start_frame, endframe)]+oiio_args+['-o', str(output_path)]
print(" ".join(oiio_args))
subprocess.run(oiio_args)


intputfilej2k = str(Path(os.path.join(tmpoutputdir, os.path.basename(inputfile))).with_suffix('.j2c'))
cmd = ['ffmpeg', '-f', 'image2', '-r', args.framerate,
'-start_number', args.start_frame, '-i', intputfilej2k, '-vcodec', 'copy',
'-color_range', '1', '-colorspace', '1', '-color_primaries', '1',
'-color_trc', '2', '-y', outputfile]
subprocess.run(cmd)
# Now we remove the intermediate files.




if __name__ == '__main__':
main()

Loading