diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/FSRImageVideoUpscalerFrontend.iml b/.idea/FSRImageVideoUpscalerFrontend.iml
new file mode 100644
index 0000000..d0876a7
--- /dev/null
+++ b/.idea/FSRImageVideoUpscalerFrontend.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..dc9ea49
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..345cc4c
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bin/handler.py b/bin/handler.py
new file mode 100644
index 0000000..985e688
--- /dev/null
+++ b/bin/handler.py
@@ -0,0 +1,217 @@
+###########################################################
+#
+# Handler for FSRImageVideoUpscalerFrontend
+#
+# This code is licensed under the GPL V3 License!
+# Developed 2022 by Janis Hutz
+#
+###########################################################
+
+
+import os
+import sys
+import ffmpeg
+import configparser
+import time
+
+# Loading the config file to get user preferred temp path
+config = configparser.ConfigParser()
+config.read('../config/settings.ini')
+
+
+class Handler:
+ def __init__(self):
+ self.os_type = sys.platform
+ self.command = ""
+ self.tmppath = ""
+ self.videometa = {}
+
+ def handler(self, fsrpath, filepath, quality_mode, quality_setting, output_path, ffmpegpath):
+ # Function to be called when using this class as this function automatically determines if file is video or image
+ if self.os_type == "linux":
+ self.tmppath = "/tmp/fsru/" # config["PathSettings"]["tmpPathLinux"]
+ elif self.os_type == "win32":
+ self.tmppath = config["PathSettings"]["tmpPathWindows"]
+ else:
+ print("OS CURRENTLY UNSUPPORTED!")
+ return False
+ # checking for spaces in filepath (for use with terminal commands)
+ self.filepath = ""
+ for self.letter in filepath:
+ if self.letter == " ":
+ self.filepath += "\ "
+ else:
+ self.filepath += self.letter
+
+ # Determining filetype
+ if str(filepath)[len(filepath) - 4:] == ".mp4" or str(filepath)[len(filepath) - 4:] == ".mkv":
+ print("upscaling video")
+ self.video_scaling(ffmpegpath, fsrpath, filepath, quality_mode, quality_setting, output_path)
+ elif str(filepath)[len(filepath) - 4:] == ".JPG" or str(filepath)[len(filepath) - 4:] == ".png" or str(filepath)[len(filepath) - 4:] == ".jpg":
+ print("upscaling image")
+ self.photo_scaling(fsrpath, filepath, quality_mode, quality_setting, output_path)
+ else:
+ print("not supported")
+
+ def photo_scaling(self, fsrpath, filepath, quality_mode, quality_setting, output_path):
+ # DO NOT CALL THIS! Use Handler().handler() instead!
+ if quality_mode == "default":
+ if self.os_type == "linux":
+ self.command = f"wine {fsrpath} -QualityMode {quality_setting} {self.filepath} {output_path}"
+ elif self.os_type == "win32":
+ self.command = f"{fsrpath} -QualityMode {quality_setting} {self.filepath} {output_path}"
+ else:
+ print("OS CURRENTLY UNSUPPORTED!")
+ return False
+
+ os.system(self.command)
+ print("photo upscaled")
+ else:
+ if self.os_type == "linux":
+ self.command = f"wine {fsrpath} -Scale {quality_setting} {self.filepath} {output_path}"
+ elif self.os_type == "win32":
+ self.command = f"{fsrpath} -Scale {quality_setting} {self.filepath} {output_path}"
+ else:
+ print("OS CURRENTLY UNSUPPORTED!")
+ return False
+ os.system(self.command)
+ print("photo upscaled")
+
+ def video_scaling(self, ffmpegpath, fsrpath, filepath, quality_mode, quality_setting, output_path):
+ # DO NOT CALL THIS! Use Handler().handler() instead!
+ self.videometa = ffmpeg.probe(str(filepath))["streams"].pop(0)
+ # Retrieving Video metadata
+ self.duration = self.videometa.get("duration")
+ self.frames = self.videometa.get("nb_frames")
+ self.framerate = round(float(self.frames) / float(self.duration), 1)
+
+ # Splitting video into frames
+ try:
+ os.mkdir(self.tmppath)
+ except FileExistsError:
+ pass
+
+ if self.os_type == "linux":
+ print("linux")
+ self.command = f"ffmpeg -i {str(self.filepath)} {self.tmppath}thumb%04d.jpg -hide_banner"
+ elif self.os_type == "win32":
+ self.command = f"{ffmpegpath} -i {str(self.filepath)} {self.tmppath}thumb%04d.jpg -hide_banner"
+ else:
+ print("OS CURRENTLY UNSUPPORTED!")
+ return False
+ os.system(self.command)
+ print("video split")
+
+ # Locate Images and assemble FSR-Command
+ self.files = ""
+ self.filelist = os.listdir(self.tmppath)
+ self.filelist.pop(0)
+ self.filelist.reverse()
+ self.number = 0
+ for self.file in self.filelist:
+ self.number += 1
+ self.files += f"{self.tmppath}{self.file} {self.tmppath}upscaled/USImage{str(self.number).zfill(4)}.jpg "
+ self.maxlength = 32000
+ self.pos = 1
+
+ # Refactoring of commands that are longer than 32K characters
+ if len(self.files) > self.maxlength:
+ print("shrinking command length")
+ self.fileout = []
+
+ while self.files[self.maxlength - self.pos:self.maxlength - self.pos + 1] != " ":
+ self.pos += 1
+ self.file_processing = self.files[:self.maxlength - self.pos]
+ if self.file_processing[len(self.file_processing) - 13:len(self.file_processing) - 8] == "thumb":
+ self.pos += 5
+ else:
+ pass
+ while self.files[self.maxlength - self.pos:self.maxlength - self.pos + 1] != " ":
+ self.pos += 1
+ self.fileout.append(self.files[:self.maxlength - self.pos])
+ self.filesopt = self.files[self.maxlength - self.pos:]
+ self.posx = 0
+ self.posy = self.maxlength
+
+ # Command refactoring for commands that are longer than 64K characters
+ if len(self.filesopt) > self.maxlength:
+ while len(self.filesopt) > self.maxlength:
+ self.posx += self.maxlength - self.pos
+ self.posy += self.maxlength - self.pos
+ self.pos = 1
+ while self.files[self.posy - self.pos:self.posy - self.pos + 1] != " ":
+ self.pos += 1
+ self.file_processing = self.files[self.posx:self.posy - self.pos]
+ if self.file_processing[len(self.file_processing) - 13:len(self.file_processing) - 8] == "thumb":
+ self.pos += 5
+ else:
+ pass
+ while self.files[self.posy - self.pos:self.posy - self.pos + 1] != " ":
+ self.pos += 1
+
+ self.file_processing = self.files[self.posx:self.posy - self.pos]
+ self.fileout.append(self.file_processing)
+ self.filesopt = self.files[self.posy - self.pos:]
+ self.fileout.append(self.filesopt)
+ else:
+ self.fileout.append(self.files[self.maxlength - self.pos:])
+ else:
+ self.fileout.append(self.files)
+ print("filepath assembled")
+
+ try:
+ os.mkdir(f"{self.tmppath}upscaled/")
+ except FileExistsError:
+ pass
+
+ # Upscaling images
+ print("\n\n\nUpscaling images... \n\n\n")
+ while self.fileout != []:
+ self.files_handle = self.fileout.pop(0)
+ if quality_mode == "default":
+ if self.os_type == "linux":
+ self.command = f"wine {fsrpath} -QualityMode {quality_setting} {self.files_handle}"
+ elif self.os_type == "win32":
+ self.command = f"{fsrpath} -QualityMode {quality_setting} {self.files_handle}"
+ else:
+ print("OS CURRENTLY UNSUPPORTED!")
+ return False
+ else:
+ if quality_mode == "default":
+ if self.os_type == "linux":
+ self.command = f"wine {fsrpath} -Scale {quality_setting} {self.files_handle} {self.tmppath}"
+ elif self.os_type == "win32":
+ self.command = f"{fsrpath} -Scale {quality_setting} {self.files_handle} {self.tmppath}"
+ else:
+ print("OS CURRENTLY UNSUPPORTED!")
+ return False
+ print(self.command, "\n\n\nCOMMAND to EXECUTE\n\n\n")
+ os.system(self.command)
+ print("Finished upscaling this section.")
+ time.sleep(3)
+
+ # get Video's audio
+ print("Retrieving Video's audio to append")
+ os.remove(f"{self.tmppath}audio.aac")
+ os.remove(f"{output_path}")
+ if self.os_type == "linux":
+ self.command = f"ffmpeg -i {self.filepath} -vn -acodec copy {self.tmppath}audio.aac"
+ elif self.os_type == "win32":
+ self.command = f"{ffmpegpath} -i {self.filepath} -vn -acodec copy {self.tmppath}audio.aac"
+ else:
+ print("OS CURRENTLY UNSUPPORTED!")
+ return False
+ os.system(self.command)
+
+ # reassemble Video
+ print("Reassembling Video... with framerate @", self.framerate)
+ if self.os_type == "linux":
+ self.command = f"ffmpeg -framerate {self.framerate} -i {self.tmppath}upscaled/USImage%04d.jpg {output_path} -i {self.tmppath}audio.aac"
+ elif self.os_type == "win32":
+ self.command = f"{ffmpegpath} -framerate {self.framerate} -i {self.tmppath}upscaled/USImage%04d.jpg {output_path} -i {self.tmppath}audio.aac"
+ else:
+ print("OS CURRENTLY UNSUPPORTED!")
+ return False
+ os.system(self.command)
+
+ print("\n\n\n DONE \n\n\n\n")
diff --git a/bin/lib/FidelityFX_CLI.exe b/bin/lib/FidelityFX_CLI.exe
new file mode 100644
index 0000000..166bd2e
Binary files /dev/null and b/bin/lib/FidelityFX_CLI.exe differ
diff --git a/config/settings.ini b/config/settings.ini
new file mode 100644
index 0000000..a59de6b
--- /dev/null
+++ b/config/settings.ini
@@ -0,0 +1,7 @@
+[PathSettings]
+defaultOutputPath = $HOME/FSRImageVideoUpscaler/
+tmpPathLinux = /tmp/
+tmpPathWindows = %TEMP%
+
+[DevSettings]
+loggerReqLevel = DEBUG
\ No newline at end of file
diff --git a/dev/get_metadata.py b/dev/get_metadata.py
new file mode 100644
index 0000000..e1acb45
--- /dev/null
+++ b/dev/get_metadata.py
@@ -0,0 +1,17 @@
+import ffmpeg
+
+
+class MetaDataParser:
+ def __init__(self):
+ pass
+
+ def get_metadata(self, filepath):
+ return ffmpeg.probe(str(filepath))["streams"]
+
+
+videometa = MetaDataParser().get_metadata("/mnt/storage/SORTED/Videos/OBS_Rec/Behalten/2019-12-19 18-21-36.mp4").pop(0)
+duration = videometa.get("duration")
+frames = videometa.get("nb_frames")
+framerate = float(frames) / float(duration)
+print(framerate)
+print(videometa)
diff --git a/dev/test.py b/dev/test.py
new file mode 100644
index 0000000..2b8ced8
--- /dev/null
+++ b/dev/test.py
@@ -0,0 +1,4 @@
+import os
+
+test = f"ffmpeg"
+os.system(test)
diff --git a/fsrimagevideoupscaler.py b/fsrimagevideoupscaler.py
new file mode 100644
index 0000000..ad673c0
--- /dev/null
+++ b/fsrimagevideoupscaler.py
@@ -0,0 +1,103 @@
+###########################################################
+#
+# FSRImageVideoUpscalerFrontend written in GTK+
+#
+# This code is licensed under the GPL V3 License!
+# Developed 2022 by Janis Hutz
+#
+###########################################################
+
+import gi
+import bin.handler
+import multiprocessing
+
+gi.require_version("Gtk", "3.0")
+from gi.repository import Gtk
+
+
+handler = bin.handler.Handler()
+
+
+class HomeWindow(Gtk.Window):
+ def __init__(self):
+ super().__init__(title="Test")
+ self.save_file = ""
+ self.open_file = ""
+
+ # Spawn box
+ self.box = Gtk.Box(spacing=6)
+ self.add(self.box)
+
+ # Create filechooser button
+ self.filechoosebutton = Gtk.Button(label="Choose Input File")
+ self.filechoosebutton.connect("clicked", self.filechooser_clicked)
+ self.box.pack_start(self.filechoosebutton, True, True, 10)
+
+ # Create output filechooser button
+ self.opfchooserbutton = Gtk.Button(label="Choose Output File")
+ self.opfchooserbutton.connect("clicked", self.opfilechooser_clicked)
+ self.box.pack_start(self.opfchooserbutton, True, True, 10)
+
+ # Create start button
+ self.start_button = Gtk.Button(label="Start upscaling")
+ self.start_button.connect("clicked", self.start_clicked)
+ self.box.pack_start(self.start_button, True, True, 10)
+
+ def filechooser_clicked(self, widget):
+ self.filechooserdialog = Gtk.FileChooserDialog(title="Choose input file", action=Gtk.FileChooserAction.OPEN)
+ self.filechooserdialog.add_buttons(
+ Gtk.STOCK_CANCEL,
+ Gtk.ResponseType.CANCEL,
+ Gtk.STOCK_OPEN,
+ Gtk.ResponseType.OK,
+ )
+ self.response = self.filechooserdialog.run()
+ if self.response == Gtk.ResponseType.OK:
+ print("ok, selected file:", self.filechooserdialog.get_filename())
+ self.open_file = self.filechooserdialog.get_filename()
+ elif self.response == Gtk.ResponseType.CANCEL:
+ print("cancel")
+ self.filechooserdialog.destroy()
+
+ def opfilechooser_clicked(self, widget):
+ self.filechooserdialog_save = Gtk.FileChooserDialog(title="Choose output file", action=Gtk.FileChooserAction.SAVE)
+ Gtk.FileChooser.set_do_overwrite_confirmation(self.filechooserdialog_save, True)
+ Gtk.FileChooser.set_current_name(self.filechooserdialog_save, "video.mp4")
+ self.filechooserdialog_save.add_buttons(
+ Gtk.STOCK_CANCEL,
+ Gtk.ResponseType.CANCEL,
+ Gtk.STOCK_SAVE,
+ Gtk.ResponseType.OK,
+ )
+ self.response = self.filechooserdialog_save.run()
+ if self.response == Gtk.ResponseType.OK:
+ print("ok, selected file:", self.filechooserdialog_save.get_filename())
+ self.save_file = self.filechooserdialog_save.get_filename()
+ elif self.response == Gtk.ResponseType.CANCEL:
+ print("cancel")
+ self.filechooserdialog_save.destroy()
+
+ def start_clicked(self, widget):
+ if str(self.open_file) != "" and str(self.save_file) != "":
+ print("ok")
+ self.go = True
+ if self.go:
+ self.scaler = multiprocessing.Process(name="scaler",
+ target=handler.handler,
+ args=("./bin/lib/FidelityFX_CLI.exe",
+ self.open_file,
+ "default",
+ "Quality",
+ self.save_file,
+ "./bin/lib/ffmpeg.exe")
+ )
+ self.scaler.start()
+ else:
+ print("no file specified")
+
+
+win = HomeWindow()
+win.set_default_size(800, 600)
+win.connect("destroy", Gtk.main_quit)
+win.show_all()
+Gtk.main()