1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//! Shared fixtures for this crate's own tests.
/// Path to a real video file for tests that need one, from
/// `MEDIA_PP_TEST_VIDEO`. Returns `None` — after printing why — when the
/// variable is unset or names something that is not a readable file, the same
/// way a hardware test's `try_device()` skips on a machine without the device.
///
/// No media is checked into this repository, so there is no default to fall
/// back to:
///
/// ```text
/// MEDIA_PP_TEST_VIDEO=/path/to/video.mp4 cargo test -p media-pp
/// ```
///
/// Any container `FileDemuxer` can open works, as long as it holds a video
/// stream and runs for at least a few seconds — the seek tests pace playback
/// and then reposition, so a clip shorter than that finishes before they get
/// to it. Nothing depends on a particular codec, resolution, or keyframe
/// spacing; a test that would need one must assert the contract instead (see
/// `pipeline::tests::seek_reports_where_it_actually_landed_when_target_is_not_a_keyframe`).
///
/// Tests using this must still assert real behavior when it does return a
/// path — skipping is for the machine that has no fixture, not a way to make
/// a failing assertion optional.
pub
/// A CUDA device for a hardware test, together with the lock that keeps
/// CUDA tests from overlapping. `None` — after printing why — on a machine
/// without a usable device, the same way [`try_test_video`] skips without a
/// fixture.
///
/// The two are returned together because they are not separable in practice.
/// Creating or destroying a `CudaDevice` retains/releases the *process-wide*
/// CUDA primary context (see [`crate::elements::CudaDevice`]'s own docs on
/// why it uses that context), and doing so on one thread while another
/// thread has NVDEC or NVENC work in flight segfaults inside `libnvcuvid` —
/// on a thread the driver itself owns, so nothing in this crate can catch or
/// recover it.
///
/// Running the whole suite hid that, because cheap tests were interleaved
/// between the CUDA ones often enough to keep them from overlapping; a run
/// filtered down to CUDA tests alone (`cargo test --features cuda cuda_`)
/// crashed reliably. Bind the guard for the body of the test:
///
/// ```ignore
/// let Some((device, _cuda_lock)) = try_cuda_device() else {
/// return;
/// };
/// ```
///
/// A test needing a *second* device — to check that a frame from a foreign
/// context is rejected — calls `CudaDevice::new()` directly rather than this
/// again: the lock is already held, and it does not nest.
pub