Skip to content

Commit 84bea57

Browse files
committed
use h264_NVENC codec in CLI test, skip cuda when no nvenc available
1 parent 289e4ee commit 84bea57

File tree

3 files changed

+55
-27
lines changed

3 files changed

+55
-27
lines changed

src/torchcodec/_core/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ function(make_torchcodec_libraries
116116
find_library(NVCUVID_LIBRARY NAMES nvcuvid.1 PATHS /usr/lib64 /usr/lib)
117117
endif()
118118
if(NOT NVCUVID_LIBRARY)
119-
set(NVCUVID_LIBRARY "/usr/lib64/libnvcuvid.so.1")
119+
# set(NVCUVID_LIBRARY "/usr/lib64/libnvcuvid.so.1")
120+
set(NVCUVID_LIBRARY "/usr/lib/x86_64-linux-gnu/libnvcuvid.so")
120121
endif()
121122

122123
if(NVCUVID_LIBRARY)

test/test_encoders.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515
from torchcodec.encoders import AudioEncoder, VideoEncoder
1616

1717
from .utils import (
18-
TEST_SRC_2_720P,
1918
assert_tensor_close_on_at_least,
2019
get_ffmpeg_major_version,
2120
get_ffmpeg_minor_version,
2221
in_fbcode,
2322
IS_WINDOWS,
2423
NASA_AUDIO_MP3,
2524
SINE_MONO_S32,
25+
TEST_SRC_2_720P,
2626
TestContainerFile,
2727
)
2828

@@ -671,7 +671,9 @@ def encode_to_tensor(frames):
671671
with open(dest, "rb") as f:
672672
return torch.frombuffer(f.read(), dtype=torch.uint8).clone()
673673
elif method == "to_tensor":
674-
return VideoEncoder(frames, frame_rate=30, device=device).to_tensor(format="mp4")
674+
return VideoEncoder(frames, frame_rate=30, device=device).to_tensor(
675+
format="mp4"
676+
)
675677
elif method == "to_file_like":
676678
file_like = io.BytesIO()
677679
VideoEncoder(frames, frame_rate=30, device=device).to_file_like(

test/test_ops.py

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,20 +1167,23 @@ def test_video_encoder_round_trip(self, tmp_path, format, method, device):
11671167
ffmpeg_version = get_ffmpeg_major_version()
11681168
# In FFmpeg6, the default codec's best pixel format is lossy for all container formats but webm.
11691169
# As a result, we skip the round trip test.
1170-
if ffmpeg_version == 6 and format != "webm":
1170+
if ffmpeg_version == 6 and format != "webm" and device == "cpu":
11711171
pytest.skip(
11721172
f"FFmpeg6 defaults to lossy encoding for {format}, skipping round-trip test."
11731173
)
11741174
if format == "webm" and (
11751175
ffmpeg_version == 4 or (IS_WINDOWS and ffmpeg_version in (6, 7))
11761176
):
11771177
pytest.skip("Codec for webm is not available in this FFmpeg installation.")
1178+
if device == "cuda" and format not in ("mp4", "mov", "mkv"):
1179+
pytest.skip(
1180+
f"No NVENC encoder available for format {format}, skipping test."
1181+
)
1182+
11781183
source_frames = self.decode(TEST_SRC_2_720P.path).data
11791184

11801185
# Frame rate is fixed with num frames decoded
1181-
params = dict(
1182-
frame_rate=30, crf=0, device=device
1183-
)
1186+
params = dict(frame_rate=30, crf=0, device=device)
11841187
if method == "to_file":
11851188
encoded_path = str(tmp_path / f"encoder_output.{format}")
11861189
encode_video_to_file(
@@ -1214,7 +1217,9 @@ def test_video_encoder_round_trip(self, tmp_path, format, method, device):
12141217
if ffmpeg_version == 6 or device == "cuda":
12151218
atol = 15
12161219
percentage = 98
1217-
assert_close = partial(assert_tensor_close_on_at_least, percentage=percentage)
1220+
assert_close = partial(
1221+
assert_tensor_close_on_at_least, percentage=percentage
1222+
)
12181223
else:
12191224
assert_close = torch.testing.assert_close
12201225
atol = 2
@@ -1296,6 +1301,16 @@ def test_video_encoder_against_ffmpeg_cli(self, tmp_path, format, device):
12961301
):
12971302
pytest.skip("Codec for webm is not available in this FFmpeg installation.")
12981303

1304+
# Pass flag to FFmpeg CLI to NVENC encoder when device is CUDA and format has a compatible NVENC codec
1305+
codec_str = ""
1306+
if device == "cuda":
1307+
if format in ("mp4", "mov", "mkv"):
1308+
codec_str = "-c:v h264_nvenc"
1309+
else:
1310+
pytest.skip(
1311+
f"No NVENC encoder available for format {format}, skipping test."
1312+
)
1313+
12991314
source_frames = self.decode(TEST_SRC_2_720P.path).data
13001315

13011316
# Encode with FFmpeg CLI
@@ -1306,7 +1321,7 @@ def test_video_encoder_against_ffmpeg_cli(self, tmp_path, format, device):
13061321
ffmpeg_encoded_path = str(tmp_path / f"ffmpeg_output.{format}")
13071322
frame_rate = 30
13081323
crf = 0
1309-
# Some codecs (ex. MPEG4) do not support CRF.
1324+
# Some codecs (ex. MPEG4) and CUDA backend codecs do not support CRF.
13101325
# Flags not supported by the selected codec will be ignored.
13111326
ffmpeg_cmd = [
13121327
"ffmpeg",
@@ -1323,20 +1338,16 @@ def test_video_encoder_against_ffmpeg_cli(self, tmp_path, format, device):
13231338
temp_raw_path,
13241339
]
13251340

1326-
# Use NVENC encoder when device is CUDA and format has an NVENC codec
1327-
if device == "cuda":
1328-
if format in ("mp4", "mov", "mkv"):
1329-
ffmpeg_cmd.extend(["-c:v", "h264_nvenc"])
1330-
elif format == "webm":
1331-
ffmpeg_cmd.extend(["-c:v", "vp9_nvenc"]) # Use NVENC for VP9
1332-
# TODO-VideoEncoder: formats "flv", "avi" should also use respective NVENC codecs,
1333-
# but do not auto select them.
1334-
1335-
ffmpeg_cmd.extend([
1336-
"-crf",
1337-
str(crf),
1338-
ffmpeg_encoded_path,
1339-
])
1341+
if codec_str:
1342+
ffmpeg_cmd.extend(codec_str.split())
1343+
1344+
ffmpeg_cmd.extend(
1345+
[
1346+
"-crf",
1347+
str(crf),
1348+
ffmpeg_encoded_path,
1349+
]
1350+
)
13401351
subprocess.run(ffmpeg_cmd, check=True)
13411352

13421353
# Encode with our video encoder
@@ -1389,14 +1400,21 @@ def get_encoded_data(self):
13891400
source_frames = self.decode(TEST_SRC_2_720P.path).data
13901401
file_like = CustomFileObject()
13911402
encode_video_to_file_like(
1392-
source_frames, frame_rate=30, crf=0, format="mp4", file_like=file_like, device=device
1403+
source_frames,
1404+
frame_rate=30,
1405+
crf=0,
1406+
format="mp4",
1407+
file_like=file_like,
1408+
device=device,
13931409
)
13941410
decoded_samples = self.decode(file_like.get_encoded_data())
13951411

13961412
if device == "cuda":
13971413
atol = 15
13981414
percentage = 98
1399-
assert_close = partial(assert_tensor_close_on_at_least, percentage=percentage)
1415+
assert_close = partial(
1416+
assert_tensor_close_on_at_least, percentage=percentage
1417+
)
14001418
else:
14011419
assert_close = torch.testing.assert_close
14021420
atol = 2
@@ -1418,14 +1436,21 @@ def test_to_file_like_real_file(self, tmp_path, device):
14181436

14191437
with open(file_path, "wb") as file_like:
14201438
encode_video_to_file_like(
1421-
source_frames, frame_rate=30, crf=0, format="mp4", file_like=file_like, device=device
1439+
source_frames,
1440+
frame_rate=30,
1441+
crf=0,
1442+
format="mp4",
1443+
file_like=file_like,
1444+
device=device,
14221445
)
14231446
decoded_samples = self.decode(str(file_path))
14241447

14251448
if device == "cuda":
14261449
atol = 15
14271450
percentage = 98
1428-
assert_close = partial(assert_tensor_close_on_at_least, percentage=percentage)
1451+
assert_close = partial(
1452+
assert_tensor_close_on_at_least, percentage=percentage
1453+
)
14291454
else:
14301455
assert_close = torch.testing.assert_close
14311456
atol = 2

0 commit comments

Comments
 (0)