nvidia-codec 0.0.23__tar.gz → 0.0.24__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. {nvidia_codec-0.0.23/src/nvidia_codec.egg-info → nvidia_codec-0.0.24}/PKG-INFO +1 -1
  2. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/setup.cfg +1 -1
  3. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/utils/decode.py +16 -8
  4. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/utils/demux.py +6 -1
  5. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24/src/nvidia_codec.egg-info}/PKG-INFO +1 -1
  6. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/tests/test_smoke.py +23 -0
  7. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/LICENSE +0 -0
  8. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/README.md +0 -0
  9. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/pyproject.toml +0 -0
  10. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/__init__.py +0 -0
  11. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/common.py +0 -0
  12. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/core/__init__.py +0 -0
  13. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/core/common.py +0 -0
  14. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/core/cuda.py +0 -0
  15. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/core/cuviddec.py +0 -0
  16. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/core/decode.py +0 -0
  17. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/core/nvcuvid.py +0 -0
  18. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/ffmpeg/__init__.py +0 -0
  19. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/ffmpeg/adapt.py +0 -0
  20. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/ffmpeg/common.py +0 -0
  21. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/ffmpeg/include/__init__.py +0 -0
  22. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/ffmpeg/include/libavcodec.py +0 -0
  23. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/ffmpeg/include/libavformat.py +0 -0
  24. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/ffmpeg/include/libavutil.py +0 -0
  25. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/ffmpeg/libavcodec.py +0 -0
  26. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/ffmpeg/libavformat.py +0 -0
  27. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/ffmpeg/libavutil.py +0 -0
  28. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/ffmpeg/test.py +0 -0
  29. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/utils/__init__.py +0 -0
  30. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/utils/color.py +0 -0
  31. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/utils/compat.py +0 -0
  32. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec/utils/player.py +0 -0
  33. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec.egg-info/SOURCES.txt +0 -0
  34. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec.egg-info/dependency_links.txt +0 -0
  35. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec.egg-info/requires.txt +0 -0
  36. {nvidia_codec-0.0.23 → nvidia_codec-0.0.24}/src/nvidia_codec.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nvidia-codec
3
- Version: 0.0.23
3
+ Version: 0.0.24
4
4
  Summary: Pythonic interface to Nvidia Codec
5
5
  Home-page: https://github.com/riaqn/python-nvidia-codec
6
6
  Author: Zesen Qian
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = nvidia-codec
3
- version = 0.0.23
3
+ version = 0.0.24
4
4
  author = Zesen Qian
5
5
  author_email = nvidia-codec@riaqn.org
6
6
  description = Pythonic interface to Nvidia Codec
@@ -273,12 +273,17 @@ class Decoder(BaseDecoder):
273
273
  frame we hand back is up to a GOP late. (ffmpeg's CLI papers over this
274
274
  with a fixed 3/23 s dts heuristic.)
275
275
 
276
- Peek at the landing packet; if it isn't a keyframe, back off by a
277
- growing number of frame-durations and retry. Landing on an earlier
278
- keyframe than strictly needed only costs decode-forward time, so
279
- overshooting backwards is safe. The peek consumes a packet, so the
280
- final seek re-runs to restore the position. Raises AVException if the
281
- container can't seek at all (caller falls back to the in-memory index).
276
+ Peek at the landing packet; if it isn't a keyframe — OR it is one but
277
+ its PTS is past the target (dts-space seek with B-frames: a keyframe's
278
+ dts precedes its pts by video_delay frames, so for a target inside
279
+ that window the seek picks a keyframe whose first displayed frame is
280
+ already too late; the on-screen frame belongs to the previous GOP) —
281
+ back off by a growing number of frame-durations and retry. Landing on
282
+ an earlier keyframe than strictly needed only costs decode-forward
283
+ time, so overshooting backwards is safe. The peek consumes a packet,
284
+ so the final seek re-runs to restore the position. Raises AVException
285
+ if the container can't seek at all (caller falls back to the
286
+ in-memory index).
282
287
  """
283
288
  fc, stream = self.track.fc, self.track.stream
284
289
  tb = self.track._time_base
@@ -289,8 +294,11 @@ class Decoder(BaseDecoder):
289
294
  for _ in range(max_tries):
290
295
  fc.seek_file(stream, ts, min_ts=-(2**63), max_ts=ts)
291
296
  first = next(fc.read_packets(stream), None)
292
- if first is None or first.av.flags & AV_PKT_FLAG_KEY:
293
- break # keyframe (or EOF — nothing to fix)
297
+ if first is None:
298
+ break # EOF — nothing to fix
299
+ pts_ok = first.av.pts == AV_NOPTS_VALUE or first.av.pts <= target_pts
300
+ if first.av.flags & AV_PKT_FLAG_KEY and pts_ok:
301
+ break # keyframe that displays at/before target
294
302
  landed = first.av.dts if first.av.dts != AV_NOPTS_VALUE else first.av.pts
295
303
  if landed == AV_NOPTS_VALUE:
296
304
  break # can't reason about position
@@ -246,7 +246,12 @@ class VideoTrack:
246
246
  return default if r == AVColorRange.UNSPECIFIED else r
247
247
 
248
248
  def time2pts(self, time: timedelta):
249
- return int(time.total_seconds() / self._time_base) + self._start_time
249
+ """timedelta -> track pts (floor). Exact rational arithmetic: timedelta has
250
+ microsecond resolution, so 1.16 s is 1160000 us and lands on pts 14848 in a
251
+ 1/12800 base; via float it is 14847.999... and int() would floor to the
252
+ PREVIOUS frame for any target exactly on a frame boundary."""
253
+ us = time // timedelta(microseconds=1)
254
+ return int(Fraction(us, 1_000_000) / self._time_base) + self._start_time
250
255
 
251
256
  def pts2time(self, pts: int):
252
257
  if pts == AV_NOPTS_VALUE:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nvidia-codec
3
- Version: 0.0.23
3
+ Version: 0.0.24
4
4
  Summary: Pythonic interface to Nvidia Codec
5
5
  Home-page: https://github.com/riaqn/python-nvidia-codec
6
6
  Author: Zesen Qian
@@ -133,10 +133,33 @@ def test_mpegts_start_time_and_first_gop(clip):
133
133
  assert abs(t.total_seconds() - 1.0) < 1 / FPS + 1e-3
134
134
  pts0, _ = next(iter(p.frames(torch.uint8, start=timedelta(seconds=1))))
135
135
  assert abs(p.track.pts2time(pts0).total_seconds() - 1.0) < 1 / FPS + 1e-3
136
+ # DTS-vs-PTS window: with B-frames the GOP-2 keyframe (pts 0.96 s) has
137
+ # dts ~0.88 s. A target in between must still yield the previous GOP's
138
+ # frame, not the keyframe (which displays after the target).
139
+ for target in (0.90, 0.94):
140
+ expect = int(target * FPS + 1e-6) / FPS
141
+ t, _ = p.screenshot(timedelta(seconds=target), torch.uint8, accurate=True)
142
+ assert abs(t.total_seconds() - expect) < 1e-3, (target, t)
143
+ pts0, _ = next(iter(p.frames(torch.uint8, start=timedelta(seconds=target))))
144
+ assert abs(p.track.pts2time(pts0).total_seconds() - expect) < 1e-3, (target, pts0)
136
145
  finally:
137
146
  shutil.rmtree(d, ignore_errors=True)
138
147
 
139
148
 
149
+ def test_time2pts_exact_on_frame_boundaries(clip):
150
+ """time2pts must not floor a target that is exactly on a frame boundary to
151
+ the previous frame (float 1.16 * 12800 = 14847.999...)."""
152
+ with Player(clip) as p:
153
+ tb = p.track._time_base
154
+ for i in range(FPS * SECONDS):
155
+ td = timedelta(seconds=i / FPS)
156
+ expect = int(round(float(td.total_seconds() / tb))) + p.track._start_time
157
+ assert p.track.time2pts(td) == expect, i
158
+ # between two frames the pts lands strictly between their pts values
159
+ a, b = p.track.time2pts(timedelta(seconds=1.16)), p.track.time2pts(timedelta(seconds=1.20))
160
+ assert a < p.track.time2pts(timedelta(seconds=1.17)) < b
161
+
162
+
140
163
  def test_pixel_format_enum_values():
141
164
  from nvidia_codec.ffmpeg.include.libavutil import AVPixelFormat
142
165
  assert AVPixelFormat.YUV420P == 0 and AVPixelFormat.RGB24 == 2
File without changes
File without changes