示例#1
0
def is_any_title_uhd(bdmv_root, titles):
    '''
    determines if the disc is a UHD
    :return: true if UHD, false if not.
    '''
    from madmeasurer.loggers import main_logger
    is_uhd = False
    error = ''
    for t in titles:
        if t.NumberOfClips > 0:
            clip = t.GetClip(0)
            if clip is not None:
                if clip.NumberOfVideosPrimary > 0:
                    video = clip.GetVideo(0)
                    if video is not None:
                        is_uhd |= video.Format == '2160p'
                    else:
                        error = 'main title clip 0 video 0 = None'
                else:
                    error = 'main title clip 0 has no videos'
            else:
                error = 'main title clip 0 is None'
        else:
            error = 'main title has no clips'

        if error != '':
            main_logger.error(f"Unable to determine if {bdmv_root} - {t.Playlist} is a UHD; {error}")
    return is_uhd
示例#2
0
def mount_if_necessary(bd_path, args):
    '''
    A context manager that can mount and iso and return the mounted path then dismounts afterwards.
    '''
    target = bd_path
    mounted = False
    main_requires_mount = args.main_by_mpc_be is True \
                          or args.analyse_main_algos is True \
                          or args.main_by_jriver is True \
                          or args.main_by_jriver_minute_resolution is True
    if args.measure is True or args.copy is True or main_requires_mount is True or args.describe_bd is True:
        mounted = target[-4:] == '.iso'
        if mounted is True:
            if platform.system() == "Windows":
                target = mount_iso_on_windows(bd_path)
                if target is not None:
                    if not os.path.exists(f"{target}BDMV/index.bdmv"):
                        main_logger.error(
                            f"{bd_path} does not contain a BD folder")
                        target = None
            elif platform.system() == "Linux":
                pass
    try:
        yield target
    finally:
        if mounted:
            if platform.system() == "Windows":
                dismount_iso_on_windows(bd_path)
            elif platform.system() == "Linux":
                pass
示例#3
0
def dismount_iso_on_windows(iso):
    '''
    Dismounts the ISO.
    :param iso: the iso.
    '''
    iso_to_dismount = os.path.abspath(iso)
    command = f"PowerShell Dismount-DiskImage {iso_to_dismount}"
    main_logger.debug(f"Triggering : {command}")
    result = subprocess.run(command, capture_output=True)
    if result is not None and result.returncode == 0:
        main_logger.info(f"Dismounted {iso_to_dismount}")
    else:
        main_logger.error(
            f"Unable to dismount {iso_to_dismount} , stdout: {result.stdout.decode('utf-8')}, stderr: {result.stderr.decode('utf-8')}"
        )
示例#4
0
def mount_iso_on_windows(iso):
    '''
    Mounts ISO and returns the mounted drive path.
    :param iso: the iso.
    :return: the mounted path.
    '''
    iso_to_mount = os.path.abspath(iso)
    command = f"PowerShell ((Mount-DiskImage {iso_to_mount} -PassThru) | Get-Volume).DriveLetter"
    main_logger.debug(f"Triggering : {command}")
    result = subprocess.run(command, capture_output=True)
    if result is not None and result.returncode == 0:
        target = f"{result.stdout.decode('utf-8').rstrip()}:{os.path.sep}"
        main_logger.info(f"Mounted {iso_to_mount} on {target}")
    else:
        main_logger.error(
            f"Unable to mount {iso_to_mount} , stdout: {result.stdout.decode('utf-8')}, stderr: {result.stderr.decode('utf-8')}"
        )
        target = None
    return target
示例#5
0
def run_mad_measure_hdr(measure_target, args):
    '''
    triggers madMeasureHDR and bridges the stdout back to this process stdout live
    :param args: the cli args.
    :param measure_target: file to measure.
    '''
    from madmeasurer.loggers import main_logger, output_logger
    exe = "" if args.mad_measure_path is None else f"{args.mad_measure_path}{os.path.sep}"
    command = [os.path.abspath(f"{exe}madMeasureHDR.exe"), os.path.abspath(measure_target)]
    if args.dry_run is True:
        main_logger.error(f"DRY RUN! Triggering : {command}")
    else:
        if not os.path.isfile(command[0]):
            main_logger.error(f"FAILED! madMeasureHDR.exe not found at {command[0]}")
        else:
            main_logger.info(f"Triggering : {command}")
            txt_output = os.path.abspath(f"{measure_target}-madvr.txt")
            with open(txt_output, 'w') as details:
                process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=4)
                line_num = 0
                output = None
                tmp_output = None
                while True:
                    if line_num == 0:
                        output = process.stdout.readline().decode('utf-8')
                        line_num = 1
                    elif line_num == 1:
                        tmp = process.stdout.read(1)
                        if tmp == b'\x08':
                            output = tmp_output
                            tmp_output = ''
                        elif tmp == b'':
                            output = tmp_output
                            tmp_output = ''
                        else:
                            tmp_output = tmp_output + tmp.decode('utf-8')
                    if output is not None:
                        if output == '' and process.poll() is not None:
                            break
                        if output:
                            txt = output.strip()
                            output_logger.error(txt)
                            details.write(txt + '\n')
                            details.flush()
                    output = None
                rc = process.poll()
                if rc == 0:
                    main_logger.error(f"Completed OK {command}")
                else:
                    main_logger.error(f"FAILED {command}")
示例#6
0
def get_main_title_by_jriver(bd, bd_folder_path, resolution='seconds'):
    '''
    Locates the main title using JRiver's algorithm which compares entries one by one by duration, audio stream count
    and then playlist name albeit allowing a slightly (within 10%) shorter track with more audio streams to still win.
    :param bd: the pybluread BD.
    :param bd_folder_path: the folder path.
    :param resolution: the resolution to use when comparison durations.
    :return: the main title.
    '''
    candidate_titles = __read_playlists_from_disc_inf(bd, bd_folder_path)
    if len(candidate_titles) == 0:
        candidate_titles = {x: bd.GetTitle(x) for x in range(bd.NumberOfTitles)}

    max_audio_titles = 0
    main_title = None
    main_title_num = 0

    for title_num, title in candidate_titles.items():
        new_main = False
        reason = ''
        if main_title is None:
            new_main = True
        else:
            audio_titles = __get_max_audio(title)
            cmp = 0
            if title.Length >= (main_title.Length*0.9):
                cmp = audio_titles - max_audio_titles

            if cmp == 0:
                this_len = TicksToTuple(title.Length)
                main_len = TicksToTuple(main_title.Length)
                if resolution == 'minutes':
                    cmp = ((this_len[0] * 60) + this_len[1]) - ((main_len[0] * 60) + main_len[1])
                elif resolution == 'seconds':
                    cmp = ((this_len[0] * 60 * 60) + (this_len[1] * 60) + this_len[2]) \
                          - ((main_len[0] * 60 * 60) + (main_len[1] * 60) + main_len[2])
                else:
                    cmp = title.Length - main_title.Length
                if cmp == 0:
                    cmp = audio_titles - max_audio_titles
                    if cmp == 0:
                        if title.Playlist < main_title.Playlist:
                            cmp = 1
                            reason = 'playlist name order'
                    else:
                        reason = 'audio stream count'
                else:
                    reason = 'duration'
            elif cmp > 0:
                reason = 'audio stream count, duration within 10%'

            if cmp > 0:
                new_main = True

        if new_main is True:
            if main_title is not None:
                main_logger.debug(f"New main title found {title.Playlist} vs {main_title.Playlist} : {reason}")
            else:
                main_logger.debug(f"Initialising main title search with {title.Playlist}")
            main_title = title
            main_title_num = title_num
            max_audio_titles = __get_max_audio(title)
        else:
            main_logger.debug(f"Main title remains {main_title.Playlist}, discarding {title.Playlist}")

    if main_title is None:
        main_logger.error(f"No main title found in {bd.Path}")

    return main_title_num