diff --git a/slideshow_ENCODER_legacy.vpy b/slideshow_ENCODER_legacy.vpy index d6bc8ae..c679031 100644 --- a/slideshow_ENCODER_legacy.vpy +++ b/slideshow_ENCODER_legacy.vpy @@ -937,6 +937,172 @@ def boxing(clip, W, H): else: return clip +### +def write_props(clip, **kwargs): + # function borrowed from _AI_ and modified to be API4 only and R62+ only add use json.dumps(value) on type 'list' as well, added _ColorRange + ''' + kwargs are: prop1=value1, prop2=value2, ... this will work for API4 ONLY + Keys are strings only, values can be: int, str, lists or dictionaries. + As for dictionaries, whatever json allows. Not wanting to go into annotations nightmare for it, + if it is a dictionary passed as a value, it can be whatever json module can decode to bytes. + As for lists and tuples, values can be int, float, str, same type for a particular list. + + Note: If complicated values, use a dictionary! json module is used to write to bytes, and that is stored to a prop. + Then it is read from bytes back to a dictionary by json again in read_prop(), so structure can be really complicated one. + Example: + clip = write_props( + clip, + _FieldBased = 1, + any_string = 'dogs', + data = {'clip_name':'Kittens', 'litter_of':3, 'names': {'fluffy':'Anna','ginger':'Bob','mottled':'Jen'}}, + filters = {'denoise':['core','fft3dfilter','FFT3DFilter',{'sigma':1.5}]}, + integer_list = [2, 6], + string_list = ['apples','oranges'] + ) + ''' + TRANSFER = { + ## 0:'reserved', + 1:'709', + 2:'unspec', + ## 3:'reserved', + 4:'470m', + 5:'470bg', + 6:'601', + 7:'240m', + 8:'linear', + 9:'log100', + 10:'log316', + 11:'xvycc', + 13:'srgb', + 14:'2020_10', #use for '2020' + 15:'2020_12', + 16:'st2084', + 18:'std-b67' + } + MATRIX = { + 0:'rgb', + 1:'709', + 2:'unspec', + ## 3:'reserved', + 4:'fcc', + 5:'470bg', + 6:'170m', + 7:'240m', + 8:'ycgco', + 9:'2020ncl', + 10:'2020cl' , + 12:'chromancl', + 13:'chromacl', + 14:'ictcp' + } + PRIMARIES = { + 1 : '709' , + 2 : 'unspec' , + 4 : '470m' , + 5 : '470bg' , + 6 : '170m' , + 7 : '240m' , + 8 : 'film' , + 9 : '2020' , + 10 : 'st428' , #use for 'xyz' + 11 : 'st431-2', #use for 'dci-p3' + 12 : 'st432-1', #use for 'display-p3' + 22 : 'jedec-p22' + } + RANGE = { + 0 : 'full range' , + 1 : 'limited range' + } + + INT_PROPS = { #int values + '_ChromaLocation': {0:'left', 1:'center', 2:'top_left', 3:'top', 4:'bottom_left', 5:'bottom'}, + '_ColorRange': {0:'full', 1:'limited'}, + '_Matrix': MATRIX , + '_Primaries': PRIMARIES , + '_Transfer': TRANSFER , + '_ColorRange': RANGE , + '_FieldBased': {0:'progressive', 1:'bottom field first', 2:'top field first'}, + '_DurationNum': {}, + '_DurationDen': {}, + '_Combed': {}, #or bool + '_Field': {0:'from bottom field, if frame was generated by SeparateFields', + 1:'from top field, if frame was generated by SeparateFields'}, + '_SARNum': {}, + '_SARDen': {}, + '_SceneChangeNext': {0:'nope',1:'LAST FRAME of the current scene'}, #or bool + '_SceneChangePrev': {0:'nope',1:'FRAME STARTS a new scene'}, #or bool + } + # ASSUME API4, ASSUME R62 or later ... so as to remove older logic + for prop, value in kwargs.items(): + if prop in INT_PROPS and not isinstance(value, int): + raise ValueError(f'[viewfunc] prop "{prop}" needs to be an integer') + if prop == '_Alpha' and not isinstance(value, vs.VideoFrame): + raise ValueError(f'[viewfunc] prop "_Alpha" needs to be a vapoursynth.VideoFrame type') + for prop, value in kwargs.items(): + if isinstance(value, dict) or isinstance(value, list): # added 'or isinstance(value, list)' + kwargs[prop] = json.dumps(value) + return clip.std.SetFrameProps(**kwargs) + +### +def read_prop(f, prop): + ''' + Can read int, str, lists or dictionaries from props for API3 and API4 + + for example props were saved like this: + -------------------------------------- + clip = viewfunc.write_props( + clip, + _FieldBased = 1, + any_string = 'dogs', + data = {'clip_name':'Kittens', 'litter_of':3, 'names': {'fluffy':'Anna','ginger':'Bob','mottled':'Jen'}}, + filters = {'denoise':['core','fft3dfilter','FFT3DFilter',{'sigma':1.5}]}, + integer_list = [2, 6], + string_list = ['apples','oranges'] + ) + + then reading those props: + ------------------------ + props_to_read = ['_FieldBased', 'any_string', 'data','filters', 'integer_list', 'string_list'] + for prop in props_to_read: + print(viewfunc.read_prop(clip.get_frame(0), prop)) + + we get correct python objects: + ------------------------------ + 1 + dogs + {'clip_name': 'Kittens', 'litter_of': 3, 'names': {'fluffy': 'Anna', 'ginger': 'Bob', 'mottled': 'Jen'}} + {'denoise':['core','fft3dfilter','FFT3DFilter',{'sigma':1.5}]} + [2, 6] + ['apples', 'oranges'] + ''' + if isinstance(f, vs.VideoNode): + raise ValueError('value passed to read_prop() was a clip instead of a frame') + if prop not in f.props: + return None + v = f.props[prop] + if isinstance(v, bytes): + try: + data = json.loads(v) + except json.decoder.JSONDecodeError: + data = v.decode() + return data + elif isinstance(v, (tuple,list)): + #API3 list reading + items = [] + for item in v: + try: + item = item.decode() + item = int(item) + except AttributeError: + item = 'cannot be decoded from bytes' + except ValueError: + #it is not an integer in API3, str gets passed + pass + finally: + items.append(item) + return items + return v + ### def resize_clip(clip,w,h): # w = calculated interim target width before addborders @@ -944,68 +1110,175 @@ def resize_clip(clip,w,h): W = clip.width # current clip width before resizing H = clip.height # current clip height before resizing resize = None - xyz = None - if w>=W or h>=H: # the clip needs to be increased in size in at least one dimension, or is the same - resize = getattr(clip.resize, objSettings.UPSIZE_KERNEL) # get the resize function object ?handle? with the nominated kernel - xyz = "UPSIZE_KERNEL" - else: # the clip needs to be reduced in size in at least one dimension - resize = getattr(clip.resize, objSettings.DOWNSIZE_KERNEL) # get the resize function object ?handle? with the nominated kernel - xyz = "DOWNSIZE_KERNEL" + #if w>=W or h>=H: # the clip needs to be increased in size in at least one dimension, or is the same + # resize = getattr(clip.resize, objSettings.UPSIZE_KERNEL) # get the resize function object ?handle? with the nominated kernel + #else: # the clip needs to be reduced in size in at least one dimension + # resize = getattr(clip.resize, objSettings.DOWNSIZE_KERNEL) # get the resize function object ?handle? with the nominated kernel + f0 = clip.get_frame(0) # force an previous work on clip to take effect + if A_DEBUG_IS_ON: + print_DEBUG(f'ENTERED resize_clip clip={clip} w={w} h={h}') + c = clip + f0 = c.get_frame(0) # force an previous work on c to take effect if c.format.color_family==vs.RGB: #rgb to YUV, perhaps only for png images, figure out what matrix out is needed ... use the HD one REC.709 - if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: incoming clip properties before RGB resize: c.format.name="{c.format.name}" c.format.color_family="{c.format.color_family}" c.format.sample_type="{c.format.sample_type}" c.format.bits_per_sample="{c.format.bits_per_sample}" c.format.bytes_per_sample="{c.format.bytes_per_sample}" c.format.num_planes="{c.format.num_planes}" c.format.subsampling_w="{c.format.subsampling_w}" c.format.subsampling_h="{c.format.subsampling_h}"') - with c.get_frame(0) as f: - if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: incoming frame properties before RGB resize: w={c.width} h={c.height} fps={c.fps} {objPrettyPrint.pformat(c)} {objPrettyPrint.pformat(f.props)}') - pass - if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: TARGET resize properties: width={w}, height={h}, format={objSettings.WORKING_PIXEL_FORMAT}, objSettings.TARGET_COLOR_RANGE_I_ZIMG={objSettings.TARGET_COLOR_RANGE_I_ZIMG}), primaries={objSettings.TARGET_COLOR_PRIMARIES_I}, transfer={objSettings.TARGET_COLOR_TRANSFER_I}, matrix={objSettings.TARGET_COLORSPACE_MATRIX_I}') + if A_DEBUG_IS_ON: + print_DEBUG(f'resize_clip: incoming clip properties before RGB resize: c.format.name="{c.format.name}" c.format.color_family="{c.format.color_family}" c.format.sample_type="{c.format.sample_type}" c.format.bits_per_sample="{c.format.bits_per_sample}" c.format.bytes_per_sample="{c.format.bytes_per_sample}" c.format.num_planes="{c.format.num_planes}" c.format.subsampling_w="{c.format.subsampling_w}" c.format.subsampling_h="{c.format.subsampling_h}"') + with c.get_frame(0) as f: + if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: incoming frame properties before RGB resize: w={c.width} h={c.height} fps={c.fps} {objPrettyPrint.pformat(c)} {objPrettyPrint.pformat(f.props)}') + pass + print_DEBUG(f'resize_clip: TARGET resize properties: width={w}, height={h}, format={objSettings.WORKING_PIXEL_FORMAT}, objSettings.TARGET_COLOR_RANGE_I_ZIMG={objSettings.TARGET_COLOR_RANGE_I_ZIMG}), primaries={objSettings.TARGET_COLOR_PRIMARIES_I}, transfer={objSettings.TARGET_COLOR_TRANSFER_I}, matrix={objSettings.TARGET_COLORSPACE_MATRIX_I}') + # ********************************************************************************************************************************************************** + # CONVERT RGB TO YUV or it all breaks + if A_DEBUG_IS_ON: + print_DEBUG(f'resize_clip: ABOUT TO CONVERT RGB TO YUV clip properties: c={objPrettyPrint.pformat(c)}') + print_DEBUG(f'resize_clip: ABOUT TO CONVERT RGB TO YUV clip properties: c={c.format}') + print_DEBUG(f'resize_clip: ABOUT TO CONVERT RGB TO YUV clip properties: c.format.name="{c.format.name}" c.format.color_family="{c.format.color_family}" c.format.sample_type="{c.format.sample_type}" c.format.bits_per_sample="{c.format.bits_per_sample}" c.format.bytes_per_sample="{c.format.bytes_per_sample}" c.format.num_planes="{c.format.num_planes}" c.format.subsampling_w="{c.format.subsampling_w}" c.format.subsampling_h="{c.format.subsampling_h}"') + with c.get_frame(0) as f: + print_DEBUG(f'resize_clip: ABOUT TO CONVERT RGB TO YUV - FRAME PROPERTIES before RGB CONVERSION TO YUV: w={c.width} h={c.height} fps={c.fps} {c} FRAME PROPERTIES={objPrettyPrint.pformat(f.props)}') + pass + + # ** BEFORE ** RESIZING, WE MUST CONVERT RGB TO YUV444 WITH THE RIGHT COLOUR PROPERTIES ETC, AS A SINGLE PRIOR STEP + # + # _AI_ for RGB to YUV ... https://forum.videohelp.com/threads/408230-ffmpeg-avc-from-jpgs-of-arbitrary-dimensions-maintaining-aspect-ratio/page4#post2694300 + # + # https://www.vapoursynth.com/doc/pythonreference.html#video + # + # INCOMING: RGB: we have to set defaults since FFMS2 dos not appear to deliver properties for .gif other than RGB family + range_in = vs.ColorRange.RANGE_LIMITED # 1, vs.ColorRange.RANGE_LIMITED # vs: 0=full range, 1=limited range + range_in_s = {0:'full',1:'limited'}[range_in] # 1, limited convert to text ??????????? + matrix_in = vs.MatrixCoefficients.MATRIX_RGB # 0, RGB + transfer_in = vs.TransferCharacteristics.TRANSFER_BT470_BG # 5, 470bg + primaries_in = vs.ColorPrimaries.PRIMARIES_BT470_BG # 5, 470bg + colors_in = dict(range_in_s=range_in_s, matrix_in=matrix_in, transfer_in=transfer_in, primaries_in=primaries_in) + + # OUTGOING: YUV444 WORKING_PIXEL_FORMAT + range_out = vs.ColorRange.RANGE_FULL # 1, vs.ColorRange.RANGE_FULL + range_out_s = {0:'full',1:'limited'}[range_out] # 0, full convert to text ??????????? + range_out_zimg = objSettings.TARGET_COLOR_RANGE_I_ZIMG + matrix_out = objSettings.TARGET_COLORSPACE_MATRIX_I + transfer_out = objSettings.TARGET_COLOR_TRANSFER_I + primaries_out = objSettings.TARGET_COLOR_PRIMARIES_I + #colors_out = dict(range_s=range_out_s, matrix=matrix_out, transfer=transfer_out, primaries=primaries_out) # _AI_ uses this one + #colors_out = dict(range=range_out_zimg, matrix=matrix_out, transfer=transfer_out, primaries=primaries_out) + colors_out = dict(range=range_out, matrix=matrix_out, transfer=transfer_out, primaries=primaries_out) + + if A_DEBUG_IS_ON: + print_DEBUG(f'\n{20*"="} BEFORE write_props RGB properties for the INCOMING RGB clip:') + props_to_read = ['_Matrix', '_Transfer', '_Primaries', '_ColorRange', ] + f0 = c.get_frame(0) + for prop in props_to_read: + print_DEBUG(f' BEFORE write_props RGB properties for the INCOMING RGB clip {prop}\t=\t{read_prop(f0, prop)}') + + # SET RGB properties for the INCOMING RGB clip + # setting prop values for a clip, preventing Resize Error while frame is requested. Technically, just setting props, should be enough without passing colors_in dict for conversion later, but heck doing both, at least it is necessary for range + c = write_props(clip=c, _Matrix=matrix_in, _Transfer=transfer_in, _Primaries=primaries_in, _ColorRange=range_in) # ?? and the range ??? + f0 = c.get_frame(0) # force an previous work on c to take effect + + if A_DEBUG_IS_ON: + print_DEBUG(f'\n{20*"="} AFTER write_props RGB properties for the INCOMING RGB clip:') + f0 = c.get_frame(0) + for prop in props_to_read: + print_DEBUG(f' AFTER write_props RGB properties for the INCOMING RGB clip {prop}\t=\t{read_prop(f0, prop)}') + + # DO THE CLIP CONVERSION RGB -> YUV444 WITHOUT ANY X Y SIZE CHANGE + c = core.resize.Bicubic(clip=c, format=objSettings.WORKING_PIXEL_FORMAT, **colors_in, **colors_out) + f0 = c.get_frame(0) # force an previous work on c to take effect + + if A_DEBUG_IS_ON: + print_DEBUG(f'\n{20*"="} AFTER CLIP CONVERSION RGB -> YUV444 clip:') + f0 = c.get_frame(0) + for prop in props_to_read: + print_DEBUG(f' AFTER CLIP CONVERSION RGB -> YUV444 clip {prop}\t=\t{read_prop(f0, prop)}') + + # SET YUV properties for the CONVERTED YV444 clip + # setting prop values for a clip, preventing Resize Error while frame is requested. Technically, just setting props, should be enough without passing colors_in dict for conversion later, but heck doing both, at least it is necessary for range + c = write_props (clip=c, _Matrix=matrix_out, _Transfer=transfer_out, _Primaries=primaries_out, _ColorRange=range_out) # ?? and the range ??? + f0 = c.get_frame(0) # force an previous work on c to take effect + + if A_DEBUG_IS_ON: + f0 = c.get_frame(0) + print_DEBUG(f'\n{20*"="} AFTER write_props AFTER CLIP CONVERSION RGB -> YUV444 clip:') + for prop in props_to_read: + print_DEBUG(f' AFTER write_props AFTER CLIP CONVERSION RGB -> YUV444 clip {prop}\t=\t{read_prop(f0, prop)}') + print_DEBUG(f'resize_clip: HAVE CONVERTED RGB TO YUV clip properties: c={objPrettyPrint.pformat(c)}') + print_DEBUG(f'resize_clip: HAVE CONVERTED RGB TO YUV clip properties: c={c.format}') + print_DEBUG(f'resize_clip: HAVE CONVERTED RGB TO YUV clip properties: c.format.name="{c.format.name}" c.format.color_family="{c.format.color_family}" c.format.sample_type="{c.format.sample_type}" c.format.bits_per_sample="{c.format.bits_per_sample}" c.format.bytes_per_sample="{c.format.bytes_per_sample}" c.format.num_planes="{c.format.num_planes}" c.format.subsampling_w="{c.format.subsampling_w}" c.format.subsampling_h="{c.format.subsampling_h}"') + with c.get_frame(0) as f: + print_DEBUG(f'resize_clip: HAVE CONVERTED RGB TO YUV - FRAME PROPERTIES after RGB CONVERSION TO YUV: w={c.width} h={c.height} fps={c.fps} {c} FRAME PROPERTIES={objPrettyPrint.pformat(f.props)}') + pass + # ********************************************************************************************************************************************************** + + # SEE https://forum.videohelp.com/threads/408230-ffmpeg-avc-from-jpgs-of-arbitrary-dimensions-maintaining-aspect-ratio/page4#post2694300 # https://www.vapoursynth.com/doc/functions/video/resize.html https://www.itu.int/rec/T-REC-H.265 - c = resize(width=w, height=h, format=objSettings.WORKING_PIXEL_FORMAT, matrix=objSettings.TARGET_COLORSPACE_MATRIX_I, transfer=objSettings.TARGET_COLOR_TRANSFER_I, primaries=objSettings.TARGET_COLOR_PRIMARIES_I, range=objSettings.TARGET_COLOR_RANGE_I_ZIMG) + # c = resize(width=w, height=h, format=objSettings.WORKING_PIXEL_FORMAT, matrix=objSettings.TARGET_COLORSPACE_MATRIX_I, transfer=objSettings.TARGET_COLOR_TRANSFER_I, primaries=objSettings.TARGET_COLOR_PRIMARIES_I, range=objSettings.TARGET_COLOR_RANGE_I_ZIMG) + if w>=W or h>=H: # the clip needs to be increased in size in at least one dimension, or is the same + resize = getattr(c.resize, objSettings.UPSIZE_KERNEL) # get the resize function object ?handle? with the nominated kernel + else: # the clip needs to be reduced in size in at least one dimension + resize = getattr(c.resize, objSettings.DOWNSIZE_KERNEL) # get the resize function object ?handle? with the nominated kernel + c = resize(width=w, height=h) c = core.std.AssumeFPS(clip=c, fpsnum=objSettings.TARGET_FPSNUM, fpsden=objSettings.TARGET_FPSDEN) - if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: incoming clip properties after RGB resize: c.format.name="{c.format.name}" c.format.color_family="{c.format.color_family}" c.format.sample_type="{c.format.sample_type}" c.format.bits_per_sample="{c.format.bits_per_sample}" c.format.bytes_per_sample="{c.format.bytes_per_sample}" c.format.num_planes="{c.format.num_planes}" c.format.subsampling_w="{c.format.subsampling_w}" c.format.subsampling_h="{c.format.subsampling_h}"') - with c.get_frame(0) as f: - if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: outgoing frame properties after RGB resize: w={c.width} h={c.height} fps={c.fps} {c} {objPrettyPrint.pformat(f.props)}') + f0 = c.get_frame(0) + if A_DEBUG_IS_ON: + print_DEBUG(f'\n{20*"="} AFTER RESIZE APPLIED :') + for prop in props_to_read: + print_DEBUG(f' AFTER RESIZE APPLIED clip {prop}\t=\t{read_prop(f0, prop)}') + print_DEBUG(f'resize_clip: incoming clip properties after RGB resize and AssumeFPS: c.format.name="{c.format.name}" c.format.color_family="{c.format.color_family}" c.format.sample_type="{c.format.sample_type}" c.format.bits_per_sample="{c.format.bits_per_sample}" c.format.bytes_per_sample="{c.format.bytes_per_sample}" c.format.num_planes="{c.format.num_planes}" c.format.subsampling_w="{c.format.subsampling_w}" c.format.subsampling_h="{c.format.subsampling_h}"') + with c.get_frame(0) as f: + if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: outgoing frame properties after RGB resize and AssumeFPS: w={c.width} h={c.height} fps={c.fps} {c} {objPrettyPrint.pformat(f.props)}') pass elif c.format.color_family==vs.YUV: - if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: incoming clip properties before YUV resize: c.format.name="{c.format.name}" c.format.color_family="{c.format.color_family}" c.format.sample_type="{c.format.sample_type}" c.format.bits_per_sample="{c.format.bits_per_sample}" c.format.bytes_per_sample="{c.format.bytes_per_sample}" c.format.num_planes="{c.format.num_planes}" c.format.subsampling_w="{c.format.subsampling_w}" c.format.subsampling_h="{c.format.subsampling_h}"') - with c.get_frame(0) as f: - if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: incoming frame properties before YUV resize: w={c.width} h={c.height} fps={c.fps} {objPrettyPrint.pformat(c)} {objPrettyPrint.pformat(f.props)}') - pass - if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: TARGET resize properties: width={w}, height={h}, format={objSettings.WORKING_PIXEL_FORMAT}, objSettings.TARGET_COLOR_RANGE_I_ZIMG={objSettings.TARGET_COLOR_RANGE_I_ZIMG}), primaries={objSettings.TARGET_COLOR_PRIMARIES_I}, transfer={objSettings.TARGET_COLOR_TRANSFER_I}, matrix={objSettings.TARGET_COLORSPACE_MATRIX_I}') + if A_DEBUG_IS_ON: + print_DEBUG(f'resize_clip: incoming clip properties before YUV resize: c.format.name="{c.format.name}" c.format.color_family="{c.format.color_family}" c.format.sample_type="{c.format.sample_type}" c.format.bits_per_sample="{c.format.bits_per_sample}" c.format.bytes_per_sample="{c.format.bytes_per_sample}" c.format.num_planes="{c.format.num_planes}" c.format.subsampling_w="{c.format.subsampling_w}" c.format.subsampling_h="{c.format.subsampling_h}"') + with c.get_frame(0) as f: + if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: incoming frame properties before YUV resize: w={c.width} h={c.height} fps={c.fps} {objPrettyPrint.pformat(c)} {objPrettyPrint.pformat(f.props)}') + print_DEBUG(f'resize_clip: TARGET resize properties: width={w}, height={h}, format={objSettings.WORKING_PIXEL_FORMAT}, objSettings.TARGET_COLOR_RANGE_I_ZIMG={objSettings.TARGET_COLOR_RANGE_I_ZIMG}), primaries={objSettings.TARGET_COLOR_PRIMARIES_I}, transfer={objSettings.TARGET_COLOR_TRANSFER_I}, matrix={objSettings.TARGET_COLORSPACE_MATRIX_I}') # https://www.vapoursynth.com/doc/functions/video/resize.html https://www.itu.int/rec/T-REC-H.265 + if w>=W or h>=H: # the clip needs to be increased in size in at least one dimension, or is the same + resize = getattr(c.resize, objSettings.UPSIZE_KERNEL) # get the resize function object ?handle? with the nominated kernel + else: # the clip needs to be reduced in size in at least one dimension + resize = getattr(c.resize, objSettings.DOWNSIZE_KERNEL) # get the resize function object ?handle? with the nominated kernel c = resize(width=w, height=h, format=objSettings.WORKING_PIXEL_FORMAT, matrix=objSettings.TARGET_COLORSPACE_MATRIX_I, transfer=objSettings.TARGET_COLOR_TRANSFER_I, primaries=objSettings.TARGET_COLOR_PRIMARIES_I, range=objSettings.TARGET_COLOR_RANGE_I_ZIMG) c = core.std.AssumeFPS(clip=c, fpsnum=objSettings.TARGET_FPSNUM, fpsden=objSettings.TARGET_FPSDEN) + f0 = c.get_frame(0) # AH !!! the above line with matrix_s='709' can cause this error: # Resize error 3074: no path between colorspaces (2/2/2 => 1/1/1). May need to specify additional colorspace parameters. # It usually means the matrix/transfer/primaries are unknown # *** and you have to specify the input colorspace parameters yourself. *** Note: 2 means “unspecified” according to the ITU-T recommendation. - if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: incoming clip properties after YUV resize: c.format.name="{c.format.name}" c.format.color_family="{c.format.color_family}" c.format.sample_type="{c.format.sample_type}" c.format.bits_per_sample="{c.format.bits_per_sample}" c.format.bytes_per_sample="{c.format.bytes_per_sample}" c.format.num_planes="{c.format.num_planes}" c.format.subsampling_w="{c.format.subsampling_w}" c.format.subsampling_h="{c.format.subsampling_h}"') - with c.get_frame(0) as f: - if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: outgoing frame properties after YUV resize: w={c.width} h={c.height} fps={c.fps} {c} {objPrettyPrint.pformat(f.props)}') + if A_DEBUG_IS_ON: + print_DEBUG(f'resize_clip: incoming clip properties after YUV resize: c.format.name="{c.format.name}" c.format.color_family="{c.format.color_family}" c.format.sample_type="{c.format.sample_type}" c.format.bits_per_sample="{c.format.bits_per_sample}" c.format.bytes_per_sample="{c.format.bytes_per_sample}" c.format.num_planes="{c.format.num_planes}" c.format.subsampling_w="{c.format.subsampling_w}" c.format.subsampling_h="{c.format.subsampling_h}"') + with c.get_frame(0) as f: + if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: outgoing frame properties after YUV resize: w={c.width} h={c.height} fps={c.fps} {c} {objPrettyPrint.pformat(f.props)}') pass else: #resize.(vnode clip[, int width, int height, int format, enum matrix, enum transfer, enum primaries, enum range, # enum chromaloc, enum matrix_in, enum transfer_in, enum primaries_in, enum range_in, enum chromaloc_in, # float filter_param_a, float filter_param_b, string resample_filter_uv, float filter_param_a_uv, float filter_param_b_uv, # string dither_type="none", string cpu_type, float src_left, float src_top, float src_width, float src_height, float nominal_luminance]) - if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: incoming clip properties before non-vs.RGB,non-vs.YUV resize: c.format.name="{c.format.name}" c.format.color_family="{c.format.color_family}" c.format.sample_type="{c.format.sample_type}" c.format.bits_per_sample="{c.format.bits_per_sample}" c.format.bytes_per_sample="{c.format.bytes_per_sample}" c.format.num_planes="{c.format.num_planes}" c.format.subsampling_w="{c.format.subsampling_w}" c.format.subsampling_h="{c.format.subsampling_h}"') - with c.get_frame(0) as f: - if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: incoming frame properties before non-vs.RGB,non-vs.YUV resize: w={c.width} h={c.height} fps={c.fps} {objPrettyPrint.pformat(c)} {objPrettyPrint.pformat(f.props)}') + if A_DEBUG_IS_ON: + print_DEBUG(f'resize_clip: incoming clip properties before non-vs.RGB,non-vs.YUV resize: c.format.name="{c.format.name}" c.format.color_family="{c.format.color_family}" c.format.sample_type="{c.format.sample_type}" c.format.bits_per_sample="{c.format.bits_per_sample}" c.format.bytes_per_sample="{c.format.bytes_per_sample}" c.format.num_planes="{c.format.num_planes}" c.format.subsampling_w="{c.format.subsampling_w}" c.format.subsampling_h="{c.format.subsampling_h}"') + with c.get_frame(0) as f: + if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: incoming frame properties before non-vs.RGB,non-vs.YUV resize: w={c.width} h={c.height} fps={c.fps} {objPrettyPrint.pformat(c)} {objPrettyPrint.pformat(f.props)}') pass - if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: TARGET resize properties: width={w}, height={h}, format={objSettings.WORKING_PIXEL_FORMAT}, objSettings.TARGET_COLOR_RANGE_I_ZIMG={objSettings.TARGET_COLOR_RANGE_I_ZIMG}), primaries={objSettings.TARGET_COLOR_PRIMARIES_I}, transfer={objSettings.TARGET_COLOR_TRANSFER_I}, matrix={objSettings.TARGET_COLORSPACE_MATRIX_I}') + print_DEBUG(f'resize_clip: TARGET resize properties: width={w}, height={h}, format={objSettings.WORKING_PIXEL_FORMAT}, objSettings.TARGET_COLOR_RANGE_I_ZIMG={objSettings.TARGET_COLOR_RANGE_I_ZIMG}), primaries={objSettings.TARGET_COLOR_PRIMARIES_I}, transfer={objSettings.TARGET_COLOR_TRANSFER_I}, matrix={objSettings.TARGET_COLORSPACE_MATRIX_I}') # https://www.vapoursynth.com/doc/functions/video/resize.html https://www.itu.int/rec/T-REC-H.265 + if w>=W or h>=H: # the clip needs to be increased in size in at least one dimension, or is the same + resize = getattr(c.resize, objSettings.UPSIZE_KERNEL) # get the resize function object ?handle? with the nominated kernel + else: # the clip needs to be reduced in size in at least one dimension + resize = getattr(c.resize, objSettings.DOWNSIZE_KERNEL) # get the resize function object ?handle? with the nominated kernel c = resize(width=w, height=h, format=objSettings.WORKING_PIXEL_FORMAT, matrix=objSettings.TARGET_COLORSPACE_MATRIX_I, transfer=objSettings.TARGET_COLOR_TRANSFER_I, primaries=objSettings.TARGET_COLOR_PRIMARIES_I, range=objSettings.TARGET_COLOR_RANGE_I_ZIMG) # https://www.vapoursynth.com/doc/functions/video/resize.html# https://www.itu.int/rec/T-REC-H.265 c = core.std.AssumeFPS(clip=c, fpsnum=objSettings.TARGET_FPSNUM, fpsden=objSettings.TARGET_FPSDEN) + f0 = c.get_frame(0) # AH !!! the avove line with matrix_s='709' can cause this error: # Resize error 3074: no path between colorspaces (2/2/2 => 1/1/1). May need to specify additional colorspace parameters. # It usually means the matrix/transfer/primaries are unknown # *** and you have to specify the input colorspace parameters yourself. *** Note: 2 means “unspecified” according to the ITU-T recommendation. - if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: incoming clip properties after non-vs.RGB,non-vs.YUV resize: c.format.name="{c.format.name}" c.format.color_family="{c.format.color_family}" c.format.sample_type="{c.format.sample_type}" c.format.bits_per_sample="{c.format.bits_per_sample}" c.format.bytes_per_sample="{c.format.bytes_per_sample}" c.format.num_planes="{c.format.num_planes}" c.format.subsampling_w="{c.format.subsampling_w}" c.format.subsampling_h="{c.format.subsampling_h}"') - with c.get_frame(0) as f: - if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: outgoing frame properties after non-vs.RGB,non-vs.YUV resize: w={c.width} h={c.height} fps={c.fps} {c} {objPrettyPrint.pformat(f.props)}') - pass + if A_DEBUG_IS_ON: + print_DEBUG(f'resize_clip: incoming clip properties after non-vs.RGB,non-vs.YUV resize: c.format.name="{c.format.name}" c.format.color_family="{c.format.color_family}" c.format.sample_type="{c.format.sample_type}" c.format.bits_per_sample="{c.format.bits_per_sample}" c.format.bytes_per_sample="{c.format.bytes_per_sample}" c.format.num_planes="{c.format.num_planes}" c.format.subsampling_w="{c.format.subsampling_w}" c.format.subsampling_h="{c.format.subsampling_h}"') + with c.get_frame(0) as f: + if A_DEBUG_IS_ON: print_DEBUG(f'resize_clip: outgoing frame properties after non-vs.RGB,non-vs.YUV resize: w={c.width} h={c.height} fps={c.fps} {c} {objPrettyPrint.pformat(f.props)}') + pass del resize - del xyz return c ### @@ -1125,7 +1398,7 @@ def get_clip_specs(clip=None, path=None, ext=None, mediainfo_specs:dict=None, ro if A_DEBUG_IS_ON: print_DEBUG(f'get_clip_specs: translation_table mi_standard_list=\n{objPrettyPrint.pformat(mi_standard_list)}') # values of video stream colour_primaries seen returned by mediainfo used to convert mediainfo to "vs" ColorPrimaries mi_color_primaries_dict = { 'BT.2020' : vs.ColorPrimaries.PRIMARIES_BT2020, - 'BT.601 NTSC' : vs.ColorPrimaries.PRIMARIES_ST170_M, # ? newer than ColorPrimaries.PRIMARIES_BT470_M + 'BT.601 NTSC' : vs.ColorPrimaries.PRIMARIES_ST170_M, # NTSC ? newer than ColorPrimaries.PRIMARIES_BT470_M 'BT.601 PAL' : vs.ColorPrimaries.PRIMARIES_BT470_BG, 'BT.709' : vs.ColorPrimaries.PRIMARIES_BT709, #None : None, @@ -1253,18 +1526,6 @@ def get_clip_specs(clip=None, path=None, ext=None, mediainfo_specs:dict=None, ro clip_specs["guessed_ColorRange"] = True clip_specs["proposed_ColorRange"] = mi_colour_range_dict[mediainfo_specs['colour_range']] # translate to "vs." if possible if A_DEBUG_IS_ON: print_DEBUG(f'get_clip_specs: Guess the Specs Pass #1 translated mediainfo colour_range "{mediainfo_specs["colour_range"]}" to "{clip_specs["proposed_ColorRange"]}"') - - - - - - - - - - - - # ********** # Guess the Specs Pass #2 once we've had a god with medinfo values .. # Sometimes, ffms2 delvers content with missing metadata tellng us what the source frame properties are