Generate thumbnails on CPU and with high niceness
This commit is contained in:
parent
fd4e46791c
commit
6016db128c
1 changed files with 27 additions and 20 deletions
|
@ -1,9 +1,11 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import multiprocessing
|
||||
import os
|
||||
import sys
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from typing import TYPE_CHECKING
|
||||
from queue import LifoQueue
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
from gi.repository import GLib, Gst
|
||||
|
||||
|
@ -32,8 +34,10 @@ class Thumbnailer(ThreadPoolExecutor):
|
|||
max_workers=MAX_WORKERS,
|
||||
)
|
||||
|
||||
self._work_queue = cast(Any, LifoQueue())
|
||||
|
||||
def generate_thumbnail(self, file_item: FileItem):
|
||||
"""Schedule thumbnail generation"""
|
||||
"""Schedule thumbnail generation."""
|
||||
|
||||
if not file_item.full_path.is_file():
|
||||
return
|
||||
|
@ -41,39 +45,41 @@ class Thumbnailer(ThreadPoolExecutor):
|
|||
if file_item.attempted_thumbnail:
|
||||
return
|
||||
|
||||
if self._work_queue.qsize() >= MAX_WORKERS:
|
||||
# print("[thumbnail] Ignoring:", file_item.full_path.name)
|
||||
return
|
||||
|
||||
self.submit(generate_thumbnail_sync, file_item)
|
||||
self.submit(generate_thumbnail_sync_nicely, file_item)
|
||||
file_item.attempted_thumbnail = True
|
||||
|
||||
|
||||
def generate_thumbnail_sync_nicely(file_item: FileItem):
|
||||
os.nice(19)
|
||||
return generate_thumbnail_sync(file_item)
|
||||
|
||||
|
||||
def generate_thumbnail_sync(file_item: FileItem):
|
||||
"""Generate thumbnail for a single file"""
|
||||
|
||||
# print("[thumbnailer] Generate:", file_item.full_path.name)
|
||||
|
||||
pipeline_str = (
|
||||
"uridecodebin name=uridecodebin ! "
|
||||
"uridecodebin name=uridecodebin force-sw-decoders=true ! "
|
||||
"videoconvert ! "
|
||||
"jpegenc quality=85 ! "
|
||||
"appsink sync=false name=sink"
|
||||
)
|
||||
|
||||
pipeline = Gst.parse_launch(pipeline_str)
|
||||
assert isinstance(pipeline, Gst.Pipeline)
|
||||
|
||||
sink = pipeline.get_by_name("sink")
|
||||
assert isinstance(sink, Gst.Element)
|
||||
|
||||
uridecodebin = pipeline.get_by_name("uridecodebin")
|
||||
assert isinstance(uridecodebin, Gst.Element)
|
||||
|
||||
# Set file URI
|
||||
uridecodebin.set_property("uri", Gst.filename_to_uri(str(file_item.full_path)))
|
||||
pipeline: Gst.Pipeline | None = None
|
||||
|
||||
try:
|
||||
pipeline = cast(Gst.Pipeline, Gst.parse_launch(pipeline_str))
|
||||
|
||||
sink = pipeline.get_by_name("sink")
|
||||
assert isinstance(sink, Gst.Element)
|
||||
|
||||
uridecodebin = pipeline.get_by_name("uridecodebin")
|
||||
assert isinstance(uridecodebin, Gst.Element)
|
||||
|
||||
# Set file URI
|
||||
uridecodebin.set_property("uri", Gst.filename_to_uri(str(file_item.full_path)))
|
||||
|
||||
# Set pipeline to PAUSED to get duration
|
||||
pipeline.set_state(Gst.State.PAUSED)
|
||||
pipeline.get_state(Gst.CLOCK_TIME_NONE)
|
||||
|
@ -119,4 +125,5 @@ def generate_thumbnail_sync(file_item: FileItem):
|
|||
print("[thumbnailer]", err, file=sys.stderr)
|
||||
|
||||
finally:
|
||||
pipeline.set_state(Gst.State.NULL)
|
||||
if pipeline:
|
||||
pipeline.set_state(Gst.State.NULL)
|
||||
|
|
Loading…
Reference in a new issue