mirror of
https://github.com/unshackle-dl/unshackle.git
synced 2026-11-12 12:05:07 +00:00
Builds per-scene L1 in unshackle (PQ mean, letterbox-aware) with a generate_dv_mode config (v29/v40/legacy); a failed hybrid no longer exits 0 with no video.
87 lines
3.2 KiB
Python
87 lines
3.2 KiB
Python
"""Unit tests for the path from the DV fixup to the hybrid step, which must read the
|
|
container file and not the raw stream."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
from types import SimpleNamespace
|
|
from typing import Any
|
|
|
|
import pytest
|
|
|
|
from unshackle.commands.dl import hybrid_source_tracks, select_hybrid_bases
|
|
from unshackle.core.tracks import Video
|
|
from unshackle.core.tracks import dv_fixup as dv_fixup_mod
|
|
from unshackle.core.tracks.dv_fixup import apply_dv_fixup
|
|
|
|
pytestmark = pytest.mark.unit
|
|
|
|
|
|
def fake_video(tmp_path: Path, track_id: str, range_: Video.Range, height: int = 2160) -> Any:
|
|
path = tmp_path / f"{track_id}.mp4"
|
|
path.write_bytes(b"x")
|
|
return SimpleNamespace(
|
|
id=track_id, path=path, height=height, range=range_, codec=Video.Codec.HEVC, dv_compatible_bitstream=True
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def fake_demux(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
monkeypatch.setattr(dv_fixup_mod, "FFMPEG", "ffmpeg")
|
|
monkeypatch.setattr(dv_fixup_mod, "log_event", lambda *a, **k: None)
|
|
monkeypatch.setattr(dv_fixup_mod, "run_step", lambda args, **k: Path(args[-1]).write_bytes(b"y"))
|
|
|
|
|
|
@pytest.mark.parametrize("keep_source", [False, True])
|
|
def test_dv_fixup_keeps_the_source_on_request(fake_demux: None, tmp_path: Path, keep_source: bool) -> None:
|
|
video = fake_video(tmp_path, "abc", Video.Range.HDR10P)
|
|
source = video.path
|
|
|
|
kept = apply_dv_fixup(video, keep_source=keep_source)
|
|
|
|
assert video.path == tmp_path / "abc.dv.hevc"
|
|
assert source.exists() is keep_source
|
|
assert kept == (source if keep_source else None)
|
|
|
|
|
|
def test_dv_fixup_that_falls_back_keeps_nothing(
|
|
fake_demux: None, monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
|
) -> None:
|
|
"""A failed fixup leaves the track on its source, so there is no second file to clean up."""
|
|
|
|
def failed_demux(args: list[Any], **kwargs: Any) -> None:
|
|
raise RuntimeError("ffmpeg failed")
|
|
|
|
monkeypatch.setattr(dv_fixup_mod, "run_step", failed_demux)
|
|
video = fake_video(tmp_path, "abc", Video.Range.HDR10P)
|
|
source = video.path
|
|
|
|
assert apply_dv_fixup(video, keep_source=True) is None
|
|
assert video.path == source and source.exists()
|
|
|
|
|
|
def test_hybrid_step_reads_the_container_after_the_fixup(fake_demux: None, tmp_path: Path) -> None:
|
|
base = fake_video(tmp_path, "base", Video.Range.HDR10P)
|
|
dv = fake_video(tmp_path, "dv", Video.Range.DV)
|
|
container = apply_dv_fixup(base, keep_source=True)
|
|
assert container is not None
|
|
|
|
hybrid_base, hybrid_dv = hybrid_source_tracks(base, dv, container)
|
|
|
|
assert base.path == tmp_path / "base.dv.hevc"
|
|
assert hybrid_base.path == tmp_path / "base.mp4"
|
|
assert hybrid_dv.path == dv.path
|
|
assert hybrid_base.needs_duration_fix and hybrid_dv.needs_duration_fix
|
|
|
|
|
|
def test_one_hybrid_base_for_each_height(tmp_path: Path) -> None:
|
|
videos = [
|
|
fake_video(tmp_path, "sdr", Video.Range.SDR, 1080),
|
|
fake_video(tmp_path, "low", Video.Range.HDR10, 1080),
|
|
fake_video(tmp_path, "high", Video.Range.HDR10P, 2160),
|
|
fake_video(tmp_path, "high2", Video.Range.HDR10, 2160),
|
|
fake_video(tmp_path, "dv", Video.Range.DV, 2160),
|
|
]
|
|
|
|
assert [v.id for v in select_hybrid_bases(videos)] == ["high", "low"]
|