Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,7 @@ Image/Inventory/ExtraNonsenseToKeepForNow/inventory.csv

#wsl files
*.deb
*.deb.1
*.deb.1
*.csv
*.vscode/
*.conda
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
{
"githubPullRequests.ignoredPullRequestBranches": [
"main"
]
],
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
},
"python.formatting.provider": "none"
}
4 changes: 4 additions & 0 deletions Staging/QCScript/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Prevents CSVs from being uploaded to GitHub and wasting space
*.csv
*.conda
*.vscode
Empty file added Staging/QCScript/README.md
Empty file.
36 changes: 36 additions & 0 deletions Staging/QCScript/ReferenceData10Bit.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
10 Bit Data Ranges for Average Videos

Digital Luma Range: 64-940
Digital Chroma Range: 64 - 960
Ideal U & V Range: 340 - 680
Yav: ~512
Yrang: ~516 - 876
Uav: ~512
Vav: ~512
TOUT: 0 - 0.009
TOUTc: <10
SAT Ideal Range: 0 - 88.7
SATb: <1000
SATi: <1000
Hue Ideal Range: 480 - 588 (for skin tones)
BRNGav: <0.02
BRNGc: <1000
MSEf: ~0
MSEfY: <10
VREP Ideal: 0

Y Channel Range: 0-1020 IRE
Y Channel Ideal Range: 64 - 940 IRE
Y LOW : 64 IRE
Y AVG : 512 IRE
Y HIGH : 940 IRE

U Channel Ideal Range: 340 - 680 IRE
V Channel Ideal Range: 340 - 680 IRE


YUV Diff : Closer to 0 the better

SAT Ideal RAnge: 0 - 354.8


37 changes: 37 additions & 0 deletions Staging/QCScript/argparser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env python3

import argparse

parser = argparse.ArgumentParser(
description="Allows input of files and the output of files"
)

parser.add_argument(
"--input",
"-i",
action="store",
dest="input_path",
type=str,
help="full path to input folder",
)

parser.add_argument(
"--output",
"-o",
action="store",
dest="output_path",
type=str,
help="full path to output folder",
)

parser.add_argument(
"--8bit",
"--8",
"--10" "--10bit",
action="store",
default="--10bit",
type=str,
help="Use to specify what bit depth your video is",
)

args = parser.parse_args()
16 changes: 16 additions & 0 deletions Staging/QCScript/csvgeneration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import pandas as pd
import csv

def videostatscsv(videostats):
csv_columns= list(videostats.keys())

try:
with open ('videodata.csv', 'w') as videocsvfile:
writer = csv.DictWriter(videocsvfile, fieldnames=csv_columns)
writer.writeheader()
for data in videostats:
writer.writerow(data)
except IOError:
print ('I/O Error')


29 changes: 29 additions & 0 deletions Staging/QCScript/datalist10bit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
tenBitVideoValues = {
"YMin": [0],
"YLow": [64],
"YAvg": [512],
"YHigh": [940],
"YMax": [1023],
"UMin": [0],
"ULow": [64],
"UAvg": [512],
"UHigh": [940],
"UMax": [1023],
"VMin": [0],
"VLow": [64],
"VAvg": [512],
"VHigh": [940],
"VMax": [1023],
"SATMin": [0],
"SATAvg": [362.04],
"SATHigh": [512],
"SATMax": [724.08],
"TOUTMin": [0],
"TOUTMax": [1],
"VREPMin": [0],
"VREPMax": [1],
"BRNGMin": [0],
"BRNGMax": [1],
}

tenBitAudioValues = {"AudioPhaseMeterOOP": [-1], "AudioPhaseMeterIP": [1]}
58 changes: 58 additions & 0 deletions Staging/QCScript/dataparsing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import pandas as pd
import keycleaner
import overallstatistics
from bs4 import BeautifulSoup
from tabulate import tabulate


def dataparsingandtabulatingaudio(filepath):
audiodata = {}
file = open(filepath)
contents = file.read()
soup = BeautifulSoup(contents, "xml")
contents = file.read()
for frames in soup.find_all("frame"):
taglist = frames.find_all("tag")
frametime = frames.get("pkt_pts_time")
mediatype = frames.get("media_type")
if mediatype == "audio":
audiodata[frametime] = {}
for tag in taglist:
tagkey = tag.get("key")
if tagkey == "lavfi.astats.1.Noise_floor":
pass
elif tagkey == "lavfi.astats.2.Noise_floor":
pass
elif tagkey == "lavfi.astats.Overall.Noise_floor":
pass
else:
cleankey = keycleaner.tagkeycleaning(tagkey)
tagvalue = tag.get("value")
audiodata[frametime][cleankey] = float(tagvalue)
else:
pass
audiodf = pd.DataFrame.from_dict(audiodata, orient="index")
return audiodf


def dataparsingandtabulatingvideo(filepath):
videodata = {}
file = open(filepath)
contents = file.read()
soup = BeautifulSoup(contents, "xml")
contents = file.read()
for frames in soup.find_all("frame"):
taglist = frames.find_all("tag")
frametime = frames.get("pkt_pts_time")
mediatype = frames.get("media_type")
if mediatype == "video":
videodata[frametime] = {}
for tag in taglist:
tagkey = tag.get("key")
cleankey = keycleaner.tagkeycleaning(tagkey)
tagvalue = tag.get("value")
videodata[frametime][cleankey] = float(tagvalue)
else:
pass
videodf = pd.DataFrame.from_dict(videodata, orient="index")
return videodf
9 changes: 9 additions & 0 deletions Staging/QCScript/errortiers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import json

def tier1error (criteria, description, value):
failstier1 = {criteria[value, description]}
return failstier1

def tier2error(criteria, description, value):
failstier2 = {criteria[value, description]}
return failstier2
7 changes: 7 additions & 0 deletions Staging/QCScript/keycleaner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
def tagkeycleaning(tagkey):
tagkeyclean1 = tagkey.replace("lavfi.astats", "")
tagkeyclean2 = tagkeyclean1.replace("lavfi.", "")
tagkeyclean3 = tagkeyclean2.replace("signalstats.", "")
tagkeyclean4 = tagkeyclean3.replace(".", " ")
cleanedtagkey = tagkeyclean4.replace("_", " ")
return cleanedtagkey
16 changes: 16 additions & 0 deletions Staging/QCScript/overallstatistics.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import pandas as pd


# Forms dictionaries of the summary data from Pandas
def videodatastatistics(videodata):
videogeneralstats = {}
videostats = videodata.describe()
videogeneralstats["videostats"] = videostats
return videogeneralstats


def audiodatastatistics(audiodata):
audiogeneralstats = {}
audiostats = audiodata.describe()
audiogeneralstats["audiostats"] = audiostats
return audiogeneralstats
Empty file added Staging/QCScript/passfail.py
Empty file.
18 changes: 18 additions & 0 deletions Staging/QCScript/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import dataparsing
import videoanalysis
import overallstatistics
import csvgeneration

filepath = input("Filepath")


videodata = dataparsing.dataparsingandtabulatingvideo(filepath)
audiodata = dataparsing.dataparsingandtabulatingaudio(filepath)

videostats = overallstatistics.videodatastatistics(videodata)
audiostats = overallstatistics.audiodatastatistics(audiodata)


"""
videoanalysis.videoanalyzer(videodata)
"""
69 changes: 69 additions & 0 deletions Staging/QCScript/videoanalysis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import pandas as pd
import errortiers

tenBitVideoValues = {
"YMin": 0,
"YLow": 64,
"YAvg": 512,
"YHigh": 940,
"YMax": 1023,
"UMin": 0,
"ULow": 64,
"UAvg": 512,
"UHigh": 960,
"UMax": 1023,
"VMin": 0,
"VLow": 64,
"VAvg": 512,
"VHigh": 960,
"VMax": 1023,
"SATMin": 0,
"SATAvg": 362.04,
"SATHigh": 512,
"SATMax": 724.08,
"TOUTMax": 0.009,
"VREPMax": 0.03,
"BRNGMax": 1,
}


def videoanalyzer(videodata):
BRNGcheck(videodata, tenBitVideoValues)
TOUTcheck(videodata, tenBitVideoValues)
VREPcheck(videodata, tenBitVideoValues)


def BRNGcheck(videodata, tenBitVideoValues):
maxBRNG = tenBitVideoValues["BRNGMax"]
videomaxBRNG = videodata.at[8, "BRNG"]
if maxBRNG < videomaxBRNG:
criteria = "BRNG Max"
description = "The video is out of the maximum broadcasting range"
value = videomaxBRNG
errortiers.tier1error(criteria, description, value)
else:
pass


def TOUTcheck(videodata, tenBitVideoValues):
maxTOUT = tenBitVideoValues["TOUTMax"]
videomaxTOUT = videodata.at[8, "TOUT"]
if maxTOUT < videomaxTOUT:
criteria = "TOUTMax"
description = "Your TOUT maximum is higher than the suggested range"
value = videomaxTOUT
errortiers.tier2error(criteria, value, description)
else:
pass


def VREPcheck(videodata, tenBitVideoValues):
maxVREP = tenBitVideoValues["VREPMax"]
videomaxVREP = videodata.at[8, "VREP"]
if maxVREP < videomaxVREP:
criteria = "VREPMax"
value = videomaxVREP
description = "Your VREP maximum is outside of the suggested range"
errortiers.tier2error(criteria, value, description)
else:
pass
Loading