Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only 50% CPU usage #1

Open
Infiziert90 opened this issue Mar 26, 2017 · 3 comments
Open

Only 50% CPU usage #1

Infiziert90 opened this issue Mar 26, 2017 · 3 comments

Comments

@Infiziert90
Copy link

Hiho,

when i'm using wwxd for keyframe generation, i only got 50% on every core ... i tested it on an i5 4690k, Xeon 1245v3 and on new Ryzen 1700.
Is there any chance that you can fix that problem?

For the test i used a 1080p Episode(24min) and this script:

    core = vs.get_core(accept_lowercase=True)
    clip = core.resize.Bilinear(clip, 640, 360)  # speed up the analysis by resizing first
    clip = core.wwxd.WWXD(clip)
    outtxt = ""
    for i in range(clip.num_frames):
        if clip.get_frame(i).props.Scenechange == 1:
            outtxt += "%d I -1\\n" % i
@dubhater
Copy link
Owner

To be honest, this filter is rather shitty. You'll get better results with xvid.

The low CPU usage is due to get_frame. It's synchronous, so WWXD will only process one frame at a time. Try get_frame_async, though don't ask me how to use it. I don't understand that "Future" stuff.

@Infiziert90
Copy link
Author

Infiziert90 commented Mar 27, 2017

I already use get_frame_async in one of my other scripts ... but i got the same problem

def get_frame(clip, frameno):
    with _cache_lock:
        if frameno in _frame_cache:
            return _frame_cache[frameno]

        fut = clip.get_frame_async(frameno)
        _frame_cache[frameno] = fut
    return fut


def find_keyframes(clip, frame, epsilon=7):
    """Output frames when scenechange == True"""
    _waiting = {}
    for frameno in range(frame - epsilon, frame + epsilon):
        if not (0 <= frameno < len(clip)):
            continue
        with _cache_lock:
            if frameno in _keyframe_cache:
                if _keyframe_cache[frameno]:
                    yield frameno
                    continue

        future = get_frame(clip, frameno)
        _waiting[future] = frameno

    for future in as_completed(_waiting):
        frameno = _waiting[future]
        frame = future.result()
        with _cache_lock:
            change = _keyframe_cache[frameno] = frame.props.Scenechange
            del _frame_cache[frameno]

        if change:
            yield frameno


def get_nearest_scenechange(clip, start, end, epsilon=7):
    """Resize frame and start check the frame with wwxd for scenechanges

    A resized clip is faster ... but with a resolution under 640x360 wwxd cant work really good and will give you a lot
    of bullshit.
    """
    core = vs.get_core(accept_lowercase=True)
    clip = core.resize.Bilinear(clip, 640, 360)  # speed up the analysis by resizing first
    clip = core.wwxd.WWXD(clip)

    start = tuple(find_keyframes(clip, start, epsilon))
    end = tuple(find_keyframes(clip, end, epsilon))

    return TimeFrame(start, end)

But still the same problem ... only 50% Usage

I will try your xvid Vapoursynth Port ...
The normal scxvid for arch linux is 20-30s slower for the ~same result.

@dubhater
Copy link
Owner

I just checked the code and... I remembered wrong. This filter will run in a single thread no matter what.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants