Skip to content

Commit

Permalink
Combine hwaccel and hwaccel ctx
Browse files Browse the repository at this point in the history
  • Loading branch information
WyattBlue committed Dec 17, 2024
1 parent d5121a1 commit 2b9e3cf
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 30 deletions.
4 changes: 2 additions & 2 deletions av/codec/context.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ from libc.stdint cimport int64_t

from av.bytesource cimport ByteSource
from av.codec.codec cimport Codec
from av.codec.hwaccel cimport HWAccel, HWAccelContext
from av.codec.hwaccel cimport HWAccel
from av.frame cimport Frame
from av.packet cimport Packet

Expand Down Expand Up @@ -34,7 +34,7 @@ cdef class CodecContext:
cpdef flush_buffers(self)

# Used by hardware-accelerated decode.
cdef HWAccelContext hwaccel_ctx
cdef HWAccel hwaccel_ctx

# Used by both transcode APIs to setup user-land objects.
# TODO: Remove the `Packet` from `_setup_decoded_frame` (because flushing packets
Expand Down
1 change: 1 addition & 0 deletions av/codec/context.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ from typing import ClassVar, Literal
from av.packet import Packet

from .codec import Codec
from .hwaccel import HWAccel

class ThreadType(Flag):
NONE: ClassVar[ThreadType]
Expand Down
10 changes: 4 additions & 6 deletions av/codec/hwaccel.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,18 @@ cimport libav as lib
from av.codec.codec cimport Codec


cdef class HWConfig(object):
cdef class HWConfig:
cdef object __weakref__
cdef lib.AVCodecHWConfig *ptr
cdef void _init(self, lib.AVCodecHWConfig *ptr)

cdef HWConfig wrap_hwconfig(lib.AVCodecHWConfig *ptr)

cdef class HWAccel(object):
cdef class HWAccel:
cdef int _device_type
cdef str _device
cdef public bint allow_software_fallback
cdef public dict options

cdef class HWAccelContext(HWAccel):
cdef readonly Codec codec
cdef readonly HWConfig config
cdef lib.AVBufferRef *ptr
cdef public bint allow_software_fallback
cdef public dict options
2 changes: 1 addition & 1 deletion av/codec/hwaccel.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ class HWAccel:
allow_software_fallback: bool = False,
options: dict[str, object] | None = None,
) -> None: ...
def create(self, codec: Codec): ...
def create(self, codec: Codec) -> HWAccel: ...

def hwdevices_available() -> list[str]: ...
40 changes: 19 additions & 21 deletions av/codec/hwaccel.pyx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from __future__ import print_function

import weakref
from enum import IntEnum

Expand All @@ -9,7 +7,6 @@ from av.codec.codec cimport Codec
from av.dictionary cimport _Dictionary
from av.error cimport err_check
from av.video.format cimport get_video_format

from av.dictionary import Dictionary


Expand Down Expand Up @@ -97,7 +94,7 @@ cpdef hwdevices_available():


cdef class HWAccel:
def __init__(self, device_type, device=None, allow_software_fallback=True, options=None):
def __init__(self, device_type, device=None, codec=None, allow_software_fallback=True, options=None):
if isinstance(device_type, HWDeviceType):
self._device_type = device_type
elif isinstance(device_type, str):
Expand All @@ -108,34 +105,26 @@ cdef class HWAccel:
self._device = device
self.allow_software_fallback = allow_software_fallback
self.options = {} if not options else dict(options)
self.ptr = NULL
self.codec = codec
self.config = None

def create(self, Codec codec not None):
return HWAccelContext(
HWDeviceType(self._device_type),
self._device,
self.options,
self.allow_software_fallback,
codec,
)
if codec:
self._initialize_hw_context()

cdef class HWAccelContext(HWAccel):
def __init__(self, device_type, device, allow_software_fallback, options, codec):
super().__init__(device_type, device, options)
if not codec:
raise ValueError("`codec` is required")
self.codec = codec
def _initialize_hw_context(self):
cdef HWConfig config

for config in codec.hardware_configs:
for config in self.codec.hardware_configs:
if not (config.ptr.methods & lib.AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX):
continue
if self._device_type and config.device_type != self._device_type:
continue
break
else:
raise NotImplementedError(f"No supported hardware config for {codec}")
raise NotImplementedError(f"No supported hardware config for {self.codec}")

self.config = config

cdef char *c_device = NULL
if self._device:
device_bytes = self._device.encode()
Expand All @@ -148,6 +137,15 @@ cdef class HWAccelContext(HWAccel):
)
)

def create(self, Codec codec not None):
"""Create a new hardware accelerator context with the given codec"""
if self.ptr:
raise RuntimeError("Hardware context already initialized")

self.codec = codec
self._initialize_hw_context()
return self

def __dealloc__(self):
if self.ptr:
lib.av_buffer_unref(&self.ptr)

0 comments on commit 2b9e3cf

Please sign in to comment.