Merge branch 'develop' into enhancement/OP-2956_move-host-install

This commit is contained in:
Jakub Trllo 2022-04-12 18:56:05 +02:00
commit 328a35c166
55 changed files with 2088 additions and 731 deletions

View file

@ -221,11 +221,17 @@ class ExtractBurnin(openpype.api.Extractor):
filled_anatomy = anatomy.format_all(burnin_data)
burnin_data["anatomy"] = filled_anatomy.get_solved()
# Add context data burnin_data.
burnin_data["custom"] = (
custom_data = copy.deepcopy(
instance.data.get("customData") or {}
)
# Backwards compatibility (since 2022/04/07)
custom_data.update(
instance.data.get("custom_burnin_data") or {}
)
# Add context data burnin_data.
burnin_data["custom"] = custom_data
# Add source camera name to burnin data
camera_name = repre.get("camera_name")
if camera_name:

View file

@ -188,8 +188,7 @@ class ExtractReview(pyblish.api.InstancePlugin):
outputs_per_repres = self._get_outputs_per_representations(
instance, profile_outputs
)
fill_data = copy.deepcopy(instance.data["anatomyData"])
for repre, outputs in outputs_per_repres:
for repre, outpu_defs in outputs_per_repres:
# Check if input should be preconverted before processing
# Store original staging dir (it's value may change)
src_repre_staging_dir = repre["stagingDir"]
@ -241,126 +240,143 @@ class ExtractReview(pyblish.api.InstancePlugin):
self.log
)
for _output_def in outputs:
output_def = copy.deepcopy(_output_def)
# Make sure output definition has "tags" key
if "tags" not in output_def:
output_def["tags"] = []
if "burnins" not in output_def:
output_def["burnins"] = []
# Create copy of representation
new_repre = copy.deepcopy(repre)
# Make sure new representation has origin staging dir
# - this is because source representation may change
# it's staging dir because of ffmpeg conversion
new_repre["stagingDir"] = src_repre_staging_dir
# Remove "delete" tag from new repre if there is
if "delete" in new_repre["tags"]:
new_repre["tags"].remove("delete")
# Add additional tags from output definition to representation
for tag in output_def["tags"]:
if tag not in new_repre["tags"]:
new_repre["tags"].append(tag)
# Add burnin link from output definition to representation
for burnin in output_def["burnins"]:
if burnin not in new_repre.get("burnins", []):
if not new_repre.get("burnins"):
new_repre["burnins"] = []
new_repre["burnins"].append(str(burnin))
self.log.debug(
"Linked burnins: `{}`".format(new_repre.get("burnins"))
try:
self._render_output_definitions(
instance, repre, src_repre_staging_dir, outpu_defs
)
self.log.debug(
"New representation tags: `{}`".format(
new_repre.get("tags"))
finally:
# Make sure temporary staging is cleaned up and representation
# has set origin stagingDir
if do_convert:
# Set staging dir of source representation back to previous
# value
repre["stagingDir"] = src_repre_staging_dir
if os.path.exists(new_staging_dir):
shutil.rmtree(new_staging_dir)
def _render_output_definitions(
self, instance, repre, src_repre_staging_dir, outpu_defs
):
fill_data = copy.deepcopy(instance.data["anatomyData"])
for _output_def in outpu_defs:
output_def = copy.deepcopy(_output_def)
# Make sure output definition has "tags" key
if "tags" not in output_def:
output_def["tags"] = []
if "burnins" not in output_def:
output_def["burnins"] = []
# Create copy of representation
new_repre = copy.deepcopy(repre)
# Make sure new representation has origin staging dir
# - this is because source representation may change
# it's staging dir because of ffmpeg conversion
new_repre["stagingDir"] = src_repre_staging_dir
# Remove "delete" tag from new repre if there is
if "delete" in new_repre["tags"]:
new_repre["tags"].remove("delete")
# Add additional tags from output definition to representation
for tag in output_def["tags"]:
if tag not in new_repre["tags"]:
new_repre["tags"].append(tag)
# Add burnin link from output definition to representation
for burnin in output_def["burnins"]:
if burnin not in new_repre.get("burnins", []):
if not new_repre.get("burnins"):
new_repre["burnins"] = []
new_repre["burnins"].append(str(burnin))
self.log.debug(
"Linked burnins: `{}`".format(new_repre.get("burnins"))
)
self.log.debug(
"New representation tags: `{}`".format(
new_repre.get("tags"))
)
temp_data = self.prepare_temp_data(instance, repre, output_def)
files_to_clean = []
if temp_data["input_is_sequence"]:
self.log.info("Filling gaps in sequence.")
files_to_clean = self.fill_sequence_gaps(
temp_data["origin_repre"]["files"],
new_repre["stagingDir"],
temp_data["frame_start"],
temp_data["frame_end"])
# create or update outputName
output_name = new_repre.get("outputName", "")
output_ext = new_repre["ext"]
if output_name:
output_name += "_"
output_name += output_def["filename_suffix"]
if temp_data["without_handles"]:
output_name += "_noHandles"
# add outputName to anatomy format fill_data
fill_data.update({
"output": output_name,
"ext": output_ext
})
try: # temporary until oiiotool is supported cross platform
ffmpeg_args = self._ffmpeg_arguments(
output_def, instance, new_repre, temp_data, fill_data
)
temp_data = self.prepare_temp_data(
instance, repre, output_def)
files_to_clean = []
if temp_data["input_is_sequence"]:
self.log.info("Filling gaps in sequence.")
files_to_clean = self.fill_sequence_gaps(
temp_data["origin_repre"]["files"],
new_repre["stagingDir"],
temp_data["frame_start"],
temp_data["frame_end"])
# create or update outputName
output_name = new_repre.get("outputName", "")
output_ext = new_repre["ext"]
if output_name:
output_name += "_"
output_name += output_def["filename_suffix"]
if temp_data["without_handles"]:
output_name += "_noHandles"
# add outputName to anatomy format fill_data
fill_data.update({
"output": output_name,
"ext": output_ext
})
try: # temporary until oiiotool is supported cross platform
ffmpeg_args = self._ffmpeg_arguments(
output_def, instance, new_repre, temp_data, fill_data
except ZeroDivisionError:
# TODO recalculate width and height using OIIO before
# conversion
if 'exr' in temp_data["origin_repre"]["ext"]:
self.log.warning(
(
"Unsupported compression on input files."
" Skipping!!!"
),
exc_info=True
)
except ZeroDivisionError:
if 'exr' in temp_data["origin_repre"]["ext"]:
self.log.debug("Unsupported compression on input " +
"files. Skipping!!!")
return
raise NotImplementedError
return
raise NotImplementedError
subprcs_cmd = " ".join(ffmpeg_args)
subprcs_cmd = " ".join(ffmpeg_args)
# run subprocess
self.log.debug("Executing: {}".format(subprcs_cmd))
# run subprocess
self.log.debug("Executing: {}".format(subprcs_cmd))
openpype.api.run_subprocess(
subprcs_cmd, shell=True, logger=self.log
)
openpype.api.run_subprocess(
subprcs_cmd, shell=True, logger=self.log
)
# delete files added to fill gaps
if files_to_clean:
for f in files_to_clean:
os.unlink(f)
# delete files added to fill gaps
if files_to_clean:
for f in files_to_clean:
os.unlink(f)
new_repre.update({
"name": "{}_{}".format(output_name, output_ext),
"outputName": output_name,
"outputDef": output_def,
"frameStartFtrack": temp_data["output_frame_start"],
"frameEndFtrack": temp_data["output_frame_end"],
"ffmpeg_cmd": subprcs_cmd
})
new_repre.update({
"name": "{}_{}".format(output_name, output_ext),
"outputName": output_name,
"outputDef": output_def,
"frameStartFtrack": temp_data["output_frame_start"],
"frameEndFtrack": temp_data["output_frame_end"],
"ffmpeg_cmd": subprcs_cmd
})
# Force to pop these key if are in new repre
new_repre.pop("preview", None)
new_repre.pop("thumbnail", None)
if "clean_name" in new_repre.get("tags", []):
new_repre.pop("outputName")
# Force to pop these key if are in new repre
new_repre.pop("preview", None)
new_repre.pop("thumbnail", None)
if "clean_name" in new_repre.get("tags", []):
new_repre.pop("outputName")
# adding representation
self.log.debug(
"Adding new representation: {}".format(new_repre)
)
instance.data["representations"].append(new_repre)
# Cleanup temp staging dir after procesisng of output definitions
if do_convert:
temp_dir = repre["stagingDir"]
shutil.rmtree(temp_dir)
# Set staging dir of source representation back to previous
# value
repre["stagingDir"] = src_repre_staging_dir
# adding representation
self.log.debug(
"Adding new representation: {}".format(new_repre)
)
instance.data["representations"].append(new_repre)
def input_is_sequence(self, repre):
"""Deduce from representation data if input is sequence."""

View file

@ -158,13 +158,15 @@ class ExtractReviewSlate(openpype.api.Extractor):
])
if use_legacy_code:
format_args = []
codec_args = repre["_profile"].get('codec', [])
output_args.extend(codec_args)
# preset's output data
output_args.extend(repre["_profile"].get('output', []))
else:
# Codecs are copied from source for whole input
codec_args = self._get_codec_args(repre)
format_args, codec_args = self._get_format_codec_args(repre)
output_args.extend(format_args)
output_args.extend(codec_args)
# make sure colors are correct
@ -266,8 +268,14 @@ class ExtractReviewSlate(openpype.api.Extractor):
"-safe", "0",
"-i", conc_text_path,
"-c", "copy",
output_path
]
# NOTE: Added because of OP Atom demuxers
# Add format arguments if there are any
# - keep format of output
if format_args:
concat_args.extend(format_args)
# Add final output path
concat_args.append(output_path)
# ffmpeg concat subprocess
self.log.debug(
@ -338,7 +346,7 @@ class ExtractReviewSlate(openpype.api.Extractor):
return vf_back
def _get_codec_args(self, repre):
def _get_format_codec_args(self, repre):
"""Detect possible codec arguments from representation."""
codec_args = []
@ -361,13 +369,9 @@ class ExtractReviewSlate(openpype.api.Extractor):
return codec_args
source_ffmpeg_cmd = repre.get("ffmpeg_cmd")
codec_args.extend(
get_ffmpeg_format_args(ffprobe_data, source_ffmpeg_cmd)
)
codec_args.extend(
get_ffmpeg_codec_args(
ffprobe_data, source_ffmpeg_cmd, logger=self.log
)
format_args = get_ffmpeg_format_args(ffprobe_data, source_ffmpeg_cmd)
codec_args = get_ffmpeg_codec_args(
ffprobe_data, source_ffmpeg_cmd, logger=self.log
)
return codec_args
return format_args, codec_args

View file

@ -8,6 +8,7 @@ import errno
import six
import re
import shutil
from collections import deque, defaultdict
from bson.objectid import ObjectId
from pymongo import DeleteOne, InsertOne
@ -1116,18 +1117,17 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin):
rec["sites"].append(meta)
already_attached_sites[meta["name"]] = None
# add alternative sites
rec, already_attached_sites = self._add_alternative_sites(
system_sync_server_presets, already_attached_sites, rec)
# add skeleton for site where it should be always synced to
for always_on_site in always_accesible:
for always_on_site in set(always_accesible):
if always_on_site not in already_attached_sites.keys():
meta = {"name": always_on_site.strip()}
rec["sites"].append(meta)
already_attached_sites[meta["name"]] = None
# add alternative sites
rec = self._add_alternative_sites(system_sync_server_presets,
already_attached_sites,
rec)
log.debug("final sites:: {}".format(rec["sites"]))
return rec
@ -1158,22 +1158,60 @@ class IntegrateAssetNew(pyblish.api.InstancePlugin):
"""
conf_sites = system_sync_server_presets.get("sites", {})
alt_site_pairs = self._get_alt_site_pairs(conf_sites)
already_attached_keys = list(already_attached_sites.keys())
for added_site in already_attached_keys:
real_created = already_attached_sites[added_site]
for alt_site in alt_site_pairs.get(added_site, []):
if alt_site in already_attached_sites.keys():
continue
meta = {"name": alt_site}
# alt site inherits state of 'created_dt'
if real_created:
meta["created_dt"] = real_created
rec["sites"].append(meta)
already_attached_sites[meta["name"]] = real_created
return rec, already_attached_sites
def _get_alt_site_pairs(self, conf_sites):
"""Returns dict of site and its alternative sites.
If `site` has alternative site, it means that alt_site has 'site' as
alternative site
Args:
conf_sites (dict)
Returns:
(dict): {'site': [alternative sites]...}
"""
alt_site_pairs = defaultdict(list)
for site_name, site_info in conf_sites.items():
alt_sites = set(site_info.get("alternative_sites", []))
already_attached_keys = list(already_attached_sites.keys())
for added_site in already_attached_keys:
if added_site in alt_sites:
if site_name in already_attached_keys:
continue
meta = {"name": site_name}
real_created = already_attached_sites[added_site]
# alt site inherits state of 'created_dt'
if real_created:
meta["created_dt"] = real_created
rec["sites"].append(meta)
already_attached_sites[meta["name"]] = real_created
alt_site_pairs[site_name].extend(alt_sites)
return rec
for alt_site in alt_sites:
alt_site_pairs[alt_site].append(site_name)
for site_name, alt_sites in alt_site_pairs.items():
sites_queue = deque(alt_sites)
while sites_queue:
alt_site = sites_queue.popleft()
# safety against wrong config
# {"SFTP": {"alternative_site": "SFTP"}
if alt_site == site_name or alt_site not in alt_site_pairs:
continue
for alt_alt_site in alt_site_pairs[alt_site]:
if (
alt_alt_site != site_name
and alt_alt_site not in alt_sites
):
alt_sites.append(alt_alt_site)
sites_queue.append(alt_alt_site)
return alt_site_pairs
def handle_destination_files(self, integrated_file_sizes, mode):
""" Clean destination files