Skip to content

Commit 8d36039

Browse files
committed
output_format -> hw.is_hw_owned
1 parent 38616d4 commit 8d36039

File tree

14 files changed

+84
-186
lines changed

14 files changed

+84
-186
lines changed

av/codec/hwaccel.pxd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ cdef class HWAccel:
1616
cdef readonly Codec codec
1717
cdef readonly HWConfig config
1818
cdef lib.AVBufferRef *ptr
19+
cdef readonly int device_id
20+
cdef readonly bint is_hw_owned
1921
cdef public bint allow_software_fallback
2022
cdef public dict options
2123
cdef public int flags
22-
cdef str _output_format
23-
cdef int _device_id

av/codec/hwaccel.py

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,8 @@ def __init__(
110110
allow_software_fallback=True,
111111
options=None,
112112
flags=None,
113-
output_format=None,
113+
is_hw_owned=False,
114114
):
115-
if isinstance(device, int):
116-
device = str(device)
117-
118115
if isinstance(device_type, HWDeviceType):
119116
self._device_type = device_type
120117
elif isinstance(device_type, str):
@@ -124,27 +121,16 @@ def __init__(
124121
else:
125122
raise ValueError("Unknown type for device_type")
126123

127-
if output_format is None:
128-
output_format = "sw"
129-
if isinstance(output_format, str):
130-
output_format = output_format.lower()
131-
if output_format not in {"sw", "hw"}:
132-
raise ValueError("output_format must be 'sw' or 'hw'")
133-
self._output_format = output_format
134-
135-
self._device_id = 0
136-
if self._device_type == HWDeviceType.cuda:
137-
if device:
138-
try:
139-
self._device_id = int(device)
140-
except ValueError:
141-
self._device_id = 0
142-
143-
self._device = device
124+
self.is_hw_owned = is_hw_owned
125+
self.device_id = 0
126+
if self._device_type == HWDeviceType.cuda and device:
127+
self.device_id = int(device)
128+
129+
self._device = None if device is None else f"{device}"
144130
self.allow_software_fallback = allow_software_fallback
145131

146132
self.options = {} if not options else dict(options)
147-
if self._device_type == HWDeviceType.cuda and self.output_format == "hw":
133+
if self._device_type == HWDeviceType.cuda and self.is_hw_owned == True:
148134
self.options.setdefault("primary_ctx", "1")
149135
self.flags = 0 if not flags else flags
150136
self.ptr = cython.NULL
@@ -158,7 +144,7 @@ def _initialize_hw_context(self, codec: Codec):
158144
if self._device_type and config.device_type != self._device_type:
159145
continue
160146
break
161-
else:
147+
else: # nobreak
162148
raise NotImplementedError(f"No supported hardware config for {codec}")
163149

164150
self.config = config
@@ -178,15 +164,7 @@ def _initialize_hw_context(self, codec: Codec):
178164
)
179165
)
180166

181-
@property
182-
def device_id(self) -> int:
183-
return self._device_id
184-
185-
@property
186-
def output_format(self) -> str:
187-
return self._output_format
188-
189-
def create(self, codec: Codec):
167+
def create(self, codec: Codec) -> HWAccel:
190168
"""Create a new hardware accelerator context with the given codec"""
191169
if self.ptr:
192170
raise RuntimeError("Hardware context already initialized")

av/codec/hwaccel.pyi

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from enum import IntEnum
2-
from typing import Literal, cast
2+
from typing import cast
33

44
from av.codec.codec import Codec
55
from av.video.format import VideoFormat
@@ -40,7 +40,7 @@ class HWAccel:
4040
options: dict[str, object]
4141

4242
@property
43-
def output_format(self) -> Literal["sw", "hw"]: ...
43+
def is_hw_owned(self) -> bool: ...
4444
@property
4545
def device_id(self) -> int: ...
4646
def __init__(
@@ -50,7 +50,7 @@ class HWAccel:
5050
allow_software_fallback: bool = False,
5151
options: dict[str, object] | None = None,
5252
flags: int | None = None,
53-
output_format: Literal["sw", "hw"] | None = None,
53+
is_hw_owned: bool = False,
5454
) -> None: ...
5555
def create(self, codec: Codec) -> HWAccel: ...
5656

av/video/codeccontext.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,7 @@ def _transfer_hwframe(self, frame: Frame):
127127
# need to transfer.
128128
return frame
129129

130-
if self.hwaccel_ctx.output_format == "hw":
131-
vframe = cython.cast(VideoFrame, frame)
132-
vframe._device_id = int(getattr(self.hwaccel_ctx, "device_id", 0))
130+
if self.hwaccel_ctx.is_hw_owned:
133131
return frame
134132

135133
frame_sw: Frame = self._alloc_next_frame()

av/video/frame.pxd

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ from av.video.reformatter cimport VideoReformatter
77

88

99
cdef class CudaContext:
10-
cdef int _device_id
11-
cdef bool _primary_ctx
10+
cdef readonly int device_id
11+
cdef readonly bint primary_ctx
1212
cdef lib.AVBufferRef* _device_ref
1313
cdef dict _frames_cache
14-
1514
cdef lib.AVBufferRef* _get_device_ref(self)
1615
cdef public lib.AVBufferRef* get_frames_ctx(
1716
self,
@@ -26,7 +25,6 @@ cdef class VideoFrame(Frame):
2625
cdef uint8_t *_buffer
2726
cdef object _np_buffer
2827

29-
cdef int _device_id
3028
cdef VideoReformatter reformatter
3129
cdef readonly VideoFormat format
3230

av/video/frame.py

Lines changed: 17 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,22 @@
88
from cython.cimports.av.sidedata.sidedata import get_display_rotation
99
from cython.cimports.av.utils import check_ndarray
1010
from cython.cimports.av.video.format import get_pix_fmt, get_video_format
11-
from cython.cimports.av.video.plane import VideoPlane
11+
from cython.cimports.av.video.plane import DLManagedTensor, VideoPlane, kCPU, kCuda
1212
from cython.cimports.cpython.exc import PyErr_Clear
1313
from cython.cimports.cpython.pycapsule import (
1414
PyCapsule_GetPointer,
1515
PyCapsule_IsValid,
1616
PyCapsule_SetName,
1717
)
1818
from cython.cimports.cpython.ref import Py_DECREF, Py_INCREF
19-
from cython.cimports.dlpack import DLManagedTensor, kDLCPU, kDLCUDA, kDLUInt
2019
from cython.cimports.libc.stdint import int64_t, uint8_t
2120

2221

2322
@cython.cclass
2423
class CudaContext:
25-
def __cinit__(self, device_id=0, primary_ctx=True):
26-
self._device_id = int(device_id)
27-
self._primary_ctx = bool(primary_ctx)
24+
def __cinit__(self, device_id: cython.int = 0, primary_ctx: cython.bint = True):
25+
self.device_id = device_id
26+
self.primary_ctx = primary_ctx
2827
self._device_ref = cython.NULL
2928
self._frames_cache = {}
3029

@@ -44,27 +43,18 @@ def __dealloc__(self):
4443
lib.av_buffer_unref(cython.address(ref))
4544
self._device_ref = cython.NULL
4645

47-
@property
48-
def device_id(self) -> int:
49-
return self._device_id
50-
51-
@property
52-
def primary_ctx(self) -> bool:
53-
return self._primary_ctx
54-
5546
@cython.cfunc
5647
def _get_device_ref(self) -> cython.pointer[lib.AVBufferRef]:
5748
device_ref: cython.pointer[lib.AVBufferRef] = self._device_ref
5849
if device_ref != cython.NULL:
5950
return device_ref
6051

6152
device_ref = cython.NULL
62-
device_bytes = str(int(self.device_id)).encode()
53+
device_bytes = f"{self.device_id}".encode()
6354
c_device: cython.p_char = device_bytes
6455
options: Dictionary = Dictionary(
6556
{"primary_ctx": "1" if self.primary_ctx else "0"}
6657
)
67-
6858
err_check(
6959
lib.av_hwdevice_ctx_create(
7060
cython.address(device_ref),
@@ -74,7 +64,6 @@ def _get_device_ref(self) -> cython.pointer[lib.AVBufferRef]:
7464
0,
7565
)
7666
)
77-
7867
self._device_ref = device_ref
7968
return device_ref
8069

@@ -426,10 +415,6 @@ def __repr__(self):
426415
f"{self.width}x{self.height} at 0x{id(self):x}>"
427416
)
428417

429-
@property
430-
def device_id(self) -> int:
431-
return self._device_id
432-
433418
@property
434419
def planes(self):
435420
"""
@@ -1059,10 +1044,6 @@ def from_numpy_buffer(array, format="rgb24", width=0):
10591044
return frame
10601045

10611046
def _image_fill_pointers_numpy(self, buffer, width, height, linesizes, format):
1062-
c_data: cython.size_t = buffer.ctypes.data
1063-
c_ptr: cython.pointer[uint8_t] = cython.cast(cython.pointer[uint8_t], c_data)
1064-
c_format: lib.AVPixelFormat = get_pix_fmt(format)
1065-
10661047
# If you want to use the numpy notation, then you need to include the following lines at the top of the file:
10671048
# cimport numpy as cnp
10681049
# cnp.import_array()
@@ -1079,9 +1060,9 @@ def _image_fill_pointers_numpy(self, buffer, width, height, linesizes, format):
10791060
# Using buffer.ctypes.data helps avoid any kind of usage of the c-api from
10801061
# numpy, which avoid the need to add numpy as a compile time dependency.
10811062

1082-
c_data = buffer.ctypes.data
1083-
c_ptr = cython.cast(cython.pointer[uint8_t], c_data)
1084-
c_format = get_pix_fmt(format)
1063+
c_data: cython.Py_ssize_t = buffer.ctypes.data
1064+
c_ptr: cython.pointer[uint8_t] = cython.cast(cython.pointer[uint8_t], c_data)
1065+
c_format: lib.AVPixelFormat = get_pix_fmt(format)
10851066
lib.av_frame_unref(self.ptr)
10861067
self._np_buffer = None
10871068

@@ -1419,7 +1400,7 @@ def from_dlpack(
14191400
p010le = get_pix_fmt(b"p010le")
14201401
p016le = get_pix_fmt(b"p016le")
14211402

1422-
if sw_fmt not in {nv12, p010le, p016le}:
1403+
if sw_fmt not in (nv12, p010le, p016le):
14231404
raise NotImplementedError("from_dlpack supports nv12, p010le, p016le only")
14241405

14251406
expected_bits = 8 if sw_fmt == nv12 else 16
@@ -1437,7 +1418,7 @@ def from_dlpack(
14371418
dev_type1 = m1.dl_tensor.device_type
14381419
if dev_type0 != dev_type1:
14391420
raise ValueError("plane tensors must have the same device_type")
1440-
if dev_type0 not in {kDLCUDA, kDLCPU}:
1421+
if dev_type0 not in (kCuda, kCPU):
14411422
raise NotImplementedError(
14421423
"only CPU and CUDA DLPack tensors are supported"
14431424
)
@@ -1446,7 +1427,7 @@ def from_dlpack(
14461427
dev1 = m1.dl_tensor.device_id
14471428
if dev0 != dev1:
14481429
raise ValueError("plane tensors must be on the same CUDA device")
1449-
if dev_type0 == kDLCUDA:
1430+
if dev_type0 == kCuda:
14501431
if device_id is None:
14511432
device_id = dev0
14521433
elif device_id != dev0:
@@ -1457,18 +1438,17 @@ def from_dlpack(
14571438
if device_id not in (None, 0):
14581439
raise ValueError("device_id must be 0 for CPU tensors")
14591440
device_id = 0
1460-
if dev_type0 == kDLCPU and (dev0 != 0 or dev1 != 0):
1441+
if dev_type0 == kCPU and (dev0 != 0 or dev1 != 0):
14611442
raise ValueError("CPU DLPack tensors must have device_id == 0")
14621443

14631444
if (
1464-
m0.dl_tensor.dtype.code != kDLUInt
1445+
m0.dl_tensor.dtype.code != 1
14651446
or m0.dl_tensor.dtype.bits != expected_bits
14661447
or m0.dl_tensor.dtype.lanes != 1
14671448
):
14681449
raise TypeError("unexpected dtype for plane 0")
1469-
14701450
if (
1471-
m1.dl_tensor.dtype.code != kDLUInt
1451+
m1.dl_tensor.dtype.code != 1
14721452
or m1.dl_tensor.dtype.bits != expected_bits
14731453
or m1.dl_tensor.dtype.lanes != 1
14741454
):
@@ -1541,13 +1521,9 @@ def from_dlpack(
15411521
frame = alloc_video_frame()
15421522
frame.ptr.width = width
15431523
frame.ptr.height = height
1544-
if dev_type0 == kDLCUDA:
1545-
ctx = cython.declare(CudaContext)
1546-
frames_ref = cython.declare(cython.pointer[lib.AVBufferRef])
1547-
if not isinstance(primary_ctx, (bool, int)):
1548-
raise TypeError("primary_ctx must be a bool")
1549-
primary_ctx = bool(primary_ctx)
1550-
1524+
if dev_type0 == kCuda:
1525+
ctx: CudaContext
1526+
frames_ref: cython.pointer[lib.AVBufferRef]
15511527
if cuda_context is None:
15521528
ctx = CudaContext(device_id=device_id, primary_ctx=primary_ctx)
15531529
else:
@@ -1564,7 +1540,6 @@ def from_dlpack(
15641540
ctx = cython.cast(CudaContext, cuda_context)
15651541

15661542
frames_ref = ctx.get_frames_ctx(sw_fmt, width, height)
1567-
15681543
frame.ptr.format = get_pix_fmt(b"cuda")
15691544
frame.ptr.hw_frames_ctx = frames_ref
15701545
else:
@@ -1600,7 +1575,6 @@ def from_dlpack(
16001575
m1 = cython.NULL
16011576

16021577
frame._init_user_attributes()
1603-
frame._device_id = device_id
16041578
return frame
16051579

16061580
except Exception:

av/video/frame.pyi

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,6 @@ class VideoFrame(Frame):
5252
def interlaced_frame(self) -> bool: ...
5353
@property
5454
def rotation(self) -> int: ...
55-
@property
56-
def device_id(self) -> int: ...
5755
def __init__(
5856
self, width: int = 0, height: int = 0, format: str = "yuv420p"
5957
) -> None: ...

av/video/plane.pxd

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,38 @@
1+
from libc.stdint cimport int64_t, uint8_t, uint16_t, uint64_t
2+
13
from av.plane cimport Plane
24
from av.video.format cimport VideoFormatComponent
35

46

57
cdef class VideoPlane(Plane):
6-
78
cdef readonly size_t buffer_size
89
cdef readonly unsigned int width, height
10+
11+
12+
cdef enum DeviceType:
13+
kCPU = 1
14+
kCuda = 2
15+
16+
cdef struct DLDataType:
17+
uint8_t code
18+
uint8_t bits
19+
uint16_t lanes
20+
21+
cdef struct DLTensor:
22+
void* data
23+
int device_type
24+
int device_id
25+
int ndim
26+
DLDataType dtype
27+
int64_t* shape
28+
int64_t* strides
29+
uint64_t byte_offset
30+
31+
cdef struct DLManagedTensor
32+
33+
ctypedef void (*DLManagedTensorDeleter)(DLManagedTensor*) noexcept nogil
34+
35+
cdef struct DLManagedTensor:
36+
DLTensor dl_tensor
37+
void* manager_ctx
38+
DLManagedTensorDeleter deleter

0 commit comments

Comments
 (0)