Initialisation du repository de Beta
This commit is contained in:
commit
14985f6dbb
9469 changed files with 1903273 additions and 0 deletions
370
venv/lib/python3.12/site-packages/av/video/codeccontext.pyx
Normal file
370
venv/lib/python3.12/site-packages/av/video/codeccontext.pyx
Normal file
|
|
@ -0,0 +1,370 @@
|
|||
cimport libav as lib
|
||||
from libc.stdint cimport int64_t
|
||||
|
||||
from av.codec.context cimport CodecContext
|
||||
from av.codec.hwaccel cimport HWAccel, HWConfig
|
||||
from av.error cimport err_check
|
||||
from av.frame cimport Frame
|
||||
from av.packet cimport Packet
|
||||
from av.utils cimport avrational_to_fraction, to_avrational
|
||||
from av.video.format cimport VideoFormat, get_pix_fmt, get_video_format
|
||||
from av.video.frame cimport VideoFrame, alloc_video_frame
|
||||
from av.video.reformatter cimport VideoReformatter
|
||||
|
||||
|
||||
cdef lib.AVPixelFormat _get_hw_format(lib.AVCodecContext *ctx, const lib.AVPixelFormat *pix_fmts) noexcept:
|
||||
# In the case where we requested accelerated decoding, the decoder first calls this function
|
||||
# with a list that includes both the hardware format and software formats.
|
||||
# First we try to pick the hardware format if it's in the list.
|
||||
# However, if the decoder fails to initialize the hardware, it will call this function again,
|
||||
# with only software formats in pix_fmts. We return ctx->sw_pix_fmt regardless in this case,
|
||||
# because that should be in the candidate list. If not, we are out of ideas anyways.
|
||||
cdef AVCodecPrivateData* private_data = <AVCodecPrivateData*>ctx.opaque
|
||||
i = 0
|
||||
while pix_fmts[i] != -1:
|
||||
if pix_fmts[i] == private_data.hardware_pix_fmt:
|
||||
return pix_fmts[i]
|
||||
i += 1
|
||||
return ctx.sw_pix_fmt if private_data.allow_software_fallback else lib.AV_PIX_FMT_NONE
|
||||
|
||||
|
||||
cdef class VideoCodecContext(CodecContext):
|
||||
|
||||
def __cinit__(self, *args, **kwargs):
|
||||
self.last_w = 0
|
||||
self.last_h = 0
|
||||
|
||||
cdef _init(self, lib.AVCodecContext *ptr, const lib.AVCodec *codec, HWAccel hwaccel):
|
||||
CodecContext._init(self, ptr, codec, hwaccel) # TODO: Can this be `super`?
|
||||
|
||||
if hwaccel is not None:
|
||||
try:
|
||||
self.hwaccel_ctx = hwaccel.create(self.codec)
|
||||
self.ptr.hw_device_ctx = lib.av_buffer_ref(self.hwaccel_ctx.ptr)
|
||||
self.ptr.pix_fmt = self.hwaccel_ctx.config.ptr.pix_fmt
|
||||
self.ptr.get_format = _get_hw_format
|
||||
self._private_data.hardware_pix_fmt = self.hwaccel_ctx.config.ptr.pix_fmt
|
||||
self._private_data.allow_software_fallback = self.hwaccel.allow_software_fallback
|
||||
self.ptr.opaque = &self._private_data
|
||||
except NotImplementedError:
|
||||
# Some streams may not have a hardware decoder. For example, many action
|
||||
# cam videos have a low resolution mjpeg stream, which is usually not
|
||||
# compatible with hardware decoders.
|
||||
# The user may have passed in a hwaccel because they want to decode the main
|
||||
# stream with it, so we shouldn't abort even if we find a stream that can't
|
||||
# be HW decoded.
|
||||
# If the user wants to make sure hwaccel is actually used, they can check with the
|
||||
# is_hwaccel() function on each stream's codec context.
|
||||
self.hwaccel_ctx = None
|
||||
|
||||
self._build_format()
|
||||
self.encoded_frame_count = 0
|
||||
|
||||
cdef _prepare_frames_for_encode(self, Frame input):
|
||||
if not input:
|
||||
return [None]
|
||||
|
||||
cdef VideoFrame vframe = input
|
||||
|
||||
if self._format is None:
|
||||
raise ValueError("self._format is None, cannot encode")
|
||||
|
||||
# Reformat if it doesn't match.
|
||||
if (
|
||||
vframe.format.pix_fmt != self._format.pix_fmt or
|
||||
vframe.width != self.ptr.width or
|
||||
vframe.height != self.ptr.height
|
||||
):
|
||||
if not self.reformatter:
|
||||
self.reformatter = VideoReformatter()
|
||||
|
||||
vframe = self.reformatter.reformat(
|
||||
vframe, self.ptr.width, self.ptr.height, self._format
|
||||
)
|
||||
|
||||
# There is no pts, so create one.
|
||||
if vframe.ptr.pts == lib.AV_NOPTS_VALUE:
|
||||
vframe.ptr.pts = <int64_t>self.encoded_frame_count
|
||||
|
||||
self.encoded_frame_count += 1
|
||||
|
||||
return [vframe]
|
||||
|
||||
cdef Frame _alloc_next_frame(self):
|
||||
return alloc_video_frame()
|
||||
|
||||
cdef _setup_decoded_frame(self, Frame frame, Packet packet):
|
||||
CodecContext._setup_decoded_frame(self, frame, packet)
|
||||
cdef VideoFrame vframe = frame
|
||||
vframe._init_user_attributes()
|
||||
|
||||
cdef _transfer_hwframe(self, Frame frame):
|
||||
if self.hwaccel_ctx is None:
|
||||
return frame
|
||||
|
||||
if frame.ptr.format != self.hwaccel_ctx.config.ptr.pix_fmt:
|
||||
# If we get a software frame, that means we are in software fallback mode, and don't actually
|
||||
# need to transfer.
|
||||
return frame
|
||||
|
||||
cdef Frame frame_sw
|
||||
|
||||
frame_sw = self._alloc_next_frame()
|
||||
|
||||
err_check(lib.av_hwframe_transfer_data(frame_sw.ptr, frame.ptr, 0))
|
||||
|
||||
# TODO: Is there anything else to transfer?!
|
||||
frame_sw.pts = frame.pts
|
||||
|
||||
return frame_sw
|
||||
|
||||
cdef _build_format(self):
|
||||
self._format = get_video_format(<lib.AVPixelFormat>self.ptr.pix_fmt, self.ptr.width, self.ptr.height)
|
||||
|
||||
@property
|
||||
def format(self):
|
||||
return self._format
|
||||
|
||||
@format.setter
|
||||
def format(self, VideoFormat format):
|
||||
self.ptr.pix_fmt = format.pix_fmt
|
||||
self.ptr.width = format.width
|
||||
self.ptr.height = format.height
|
||||
self._build_format() # Kinda wasteful.
|
||||
|
||||
@property
|
||||
def width(self):
|
||||
if self.ptr is NULL:
|
||||
return 0
|
||||
return self.ptr.width
|
||||
|
||||
@width.setter
|
||||
def width(self, unsigned int value):
|
||||
self.ptr.width = value
|
||||
self._build_format()
|
||||
|
||||
@property
|
||||
def height(self):
|
||||
if self.ptr is NULL:
|
||||
return 0
|
||||
return self.ptr.height
|
||||
|
||||
@height.setter
|
||||
def height(self, unsigned int value):
|
||||
self.ptr.height = value
|
||||
self._build_format()
|
||||
|
||||
@property
|
||||
def bits_per_coded_sample(self):
|
||||
"""
|
||||
The number of bits per sample in the codedwords. It's mandatory for this to be set for some formats to decode properly.
|
||||
|
||||
Wraps :ffmpeg:`AVCodecContext.bits_per_coded_sample`.
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return self.ptr.bits_per_coded_sample
|
||||
|
||||
@bits_per_coded_sample.setter
|
||||
def bits_per_coded_sample(self, int value):
|
||||
if self.is_encoder:
|
||||
raise ValueError("Not supported for encoders")
|
||||
|
||||
self.ptr.bits_per_coded_sample = value
|
||||
self._build_format()
|
||||
|
||||
@property
|
||||
def pix_fmt(self):
|
||||
"""
|
||||
The pixel format's name.
|
||||
|
||||
:type: str | None
|
||||
"""
|
||||
return getattr(self._format, "name", None)
|
||||
|
||||
@pix_fmt.setter
|
||||
def pix_fmt(self, value):
|
||||
self.ptr.pix_fmt = get_pix_fmt(value)
|
||||
self._build_format()
|
||||
|
||||
@property
|
||||
def framerate(self):
|
||||
"""
|
||||
The frame rate, in frames per second.
|
||||
|
||||
:type: fractions.Fraction
|
||||
"""
|
||||
return avrational_to_fraction(&self.ptr.framerate)
|
||||
|
||||
@framerate.setter
|
||||
def framerate(self, value):
|
||||
to_avrational(value, &self.ptr.framerate)
|
||||
|
||||
@property
|
||||
def rate(self):
|
||||
"""Another name for :attr:`framerate`."""
|
||||
return self.framerate
|
||||
|
||||
@rate.setter
|
||||
def rate(self, value):
|
||||
self.framerate = value
|
||||
|
||||
@property
|
||||
def gop_size(self):
|
||||
"""
|
||||
Sets the number of frames between keyframes. Used only for encoding.
|
||||
|
||||
:type: int
|
||||
"""
|
||||
if self.is_decoder:
|
||||
raise RuntimeError("Cannot access 'gop_size' as a decoder")
|
||||
return self.ptr.gop_size
|
||||
|
||||
@gop_size.setter
|
||||
def gop_size(self, int value):
|
||||
if self.is_decoder:
|
||||
raise RuntimeError("Cannot access 'gop_size' as a decoder")
|
||||
self.ptr.gop_size = value
|
||||
|
||||
@property
|
||||
def sample_aspect_ratio(self):
|
||||
return avrational_to_fraction(&self.ptr.sample_aspect_ratio)
|
||||
|
||||
@sample_aspect_ratio.setter
|
||||
def sample_aspect_ratio(self, value):
|
||||
to_avrational(value, &self.ptr.sample_aspect_ratio)
|
||||
|
||||
@property
|
||||
def display_aspect_ratio(self):
|
||||
cdef lib.AVRational dar
|
||||
|
||||
lib.av_reduce(
|
||||
&dar.num, &dar.den,
|
||||
self.ptr.width * self.ptr.sample_aspect_ratio.num,
|
||||
self.ptr.height * self.ptr.sample_aspect_ratio.den, 1024*1024)
|
||||
|
||||
return avrational_to_fraction(&dar)
|
||||
|
||||
@property
|
||||
def has_b_frames(self):
|
||||
"""
|
||||
:type: bool
|
||||
"""
|
||||
return bool(self.ptr.has_b_frames)
|
||||
|
||||
@property
|
||||
def coded_width(self):
|
||||
"""
|
||||
:type: int
|
||||
"""
|
||||
return self.ptr.coded_width
|
||||
|
||||
@property
|
||||
def coded_height(self):
|
||||
"""
|
||||
:type: int
|
||||
"""
|
||||
return self.ptr.coded_height
|
||||
|
||||
@property
|
||||
def color_range(self):
|
||||
"""
|
||||
Describes the signal range of the colorspace.
|
||||
|
||||
Wraps :ffmpeg:`AVFrame.color_range`.
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return self.ptr.color_range
|
||||
|
||||
@color_range.setter
|
||||
def color_range(self, value):
|
||||
self.ptr.color_range = value
|
||||
|
||||
@property
|
||||
def color_primaries(self):
|
||||
"""
|
||||
Describes the RGB/XYZ matrix of the colorspace.
|
||||
|
||||
Wraps :ffmpeg:`AVFrame.color_primaries`.
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return self.ptr.color_primaries
|
||||
|
||||
@color_primaries.setter
|
||||
def color_primaries(self, value):
|
||||
self.ptr.color_primaries = value
|
||||
|
||||
@property
|
||||
def color_trc(self):
|
||||
"""
|
||||
Describes the linearization function (a.k.a. transformation characteristics) of the colorspace.
|
||||
|
||||
Wraps :ffmpeg:`AVFrame.color_trc`.
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return self.ptr.color_trc
|
||||
|
||||
@color_trc.setter
|
||||
def color_trc(self, value):
|
||||
self.ptr.color_trc = value
|
||||
|
||||
@property
|
||||
def colorspace(self):
|
||||
"""
|
||||
Describes the YUV/RGB transformation matrix of the colorspace.
|
||||
|
||||
Wraps :ffmpeg:`AVFrame.colorspace`.
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return self.ptr.colorspace
|
||||
|
||||
@colorspace.setter
|
||||
def colorspace(self, value):
|
||||
self.ptr.colorspace = value
|
||||
|
||||
@property
|
||||
def max_b_frames(self):
|
||||
"""
|
||||
The maximum run of consecutive B frames when encoding a video.
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return self.ptr.max_b_frames
|
||||
|
||||
@max_b_frames.setter
|
||||
def max_b_frames(self, value):
|
||||
self.ptr.max_b_frames = value
|
||||
|
||||
@property
|
||||
def qmin(self):
|
||||
"""
|
||||
The minimum quantiser value of an encoded stream.
|
||||
|
||||
Wraps :ffmpeg:`AVCodecContext.qmin`.
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return self.ptr.qmin
|
||||
|
||||
@qmin.setter
|
||||
def qmin(self, value):
|
||||
self.ptr.qmin = value
|
||||
|
||||
@property
|
||||
def qmax(self):
|
||||
"""
|
||||
The maximum quantiser value of an encoded stream.
|
||||
|
||||
Wraps :ffmpeg:`AVCodecContext.qmax`.
|
||||
|
||||
:type: int
|
||||
"""
|
||||
return self.ptr.qmax
|
||||
|
||||
@qmax.setter
|
||||
def qmax(self, value):
|
||||
self.ptr.qmax = value
|
||||
Loading…
Add table
Add a link
Reference in a new issue