def native_format(self) -> RawFormat: if not self.acquired: return FORMAT_COMPATBGR32 ff: Format = self._raw_frame.format if ff.color_family == vs.COMPAT: if int(ff) == vs.COMPATBGR32: return FORMAT_COMPATBGR32 else: return FORMAT_COMPATYUY2 else: fam = { vs.RGB: ColorFamily.RGB, vs.GRAY: ColorFamily.GREY, vs.YUV: ColorFamily.YUV, vs.YCOCG: ColorFamily.YUV }[ff.color_family] samples = SampleType.INTEGER if ff.sample_type == vs.INTEGER else SampleType.FLOAT return RawFormat(sample_type=samples, family=fam, num_fields=ff.num_planes, subsampling_w=ff.subsampling_w, subsampling_h=ff.subsampling_h, bits_per_sample=ff.bits_per_sample, packed=False, planar=True)
async def on_render( self, frame: int, format: Optional[list] = None, planes: Optional[Union[List[int], int]] = None) -> Message: frame_inst = self.clip[frame] async with frame_inst: if planes is None: return Message({'size': list(frame_inst.size)}, []) format: RawFormat = RawFormat.from_json(format) if not (await frame_inst.can_render(format)): return Message({'size': None}) if not isinstance(planes, (list, tuple)): planes: List[int] = [planes] buffers = [ bytearray(format.get_plane_size(p, frame_inst.size)) for p in planes ] used_buffers = await gather( *(frame_inst.render_into(buf, p, format, 0) for p, buf in enumerate(buffers))) return Message( {'size': list(frame_inst.size)}, [buf[:sz] for buf, sz in zip(buffers, used_buffers)])
async def can_render(self, format: RawFormat) -> bool: await self.ensure_acquired() if format == self.main.native_format: return True if not format.planar: return False if format.num_planes not in (2, 4): return (await self.main.can_render(format)) main_f = format._replace(num_fields=format.num_fields - 1) alpha_f = format._replace(num_fields=1, family=ColorFamily.GREY) return all(await gather(self.main.can_render(main_f), self.alpha.can_render(alpha_f)))
async def can_render(self, format: RawFormat) -> bool: await self.ensure_acquired() f_json = format.to_json() response: Message = await self.client.render(frame=self.frame, format=f_json, planes=[]) return response.values['size'] is not None
async def render_into(self, buffer: Buffer, plane: int, format: RawFormat, offset: int = 0) -> int: await self.ensure_acquired() if not (await self.can_render(format)): raise ValueError("Unsupported format.") if format.num_planes not in (2, 4): return (await self.main.render_into(buffer, plane, format, offset)) main_f = format._replace(num_fields=format.num_fields - 1) alpha_f = format._replace(num_fields=1, family=ColorFamily.GREY) if format.num_planes - 1 == plane: return (await self.alpha.render_into(buffer, 0, alpha_f, offset)) else: return (await self.main.render_into(buffer, plane, main_f, offset))
async def _acquire(self) -> NoReturn: await self.remote_clip.acquire() await self.client.acquire() register(self.remote_clip, self) register(self.client, self) msg_sz, msg_format = await gather(self.client.size(frame=self.frame), self.client.format(frame=self.frame)) self._size = Size(*msg_sz.values) self._native_format = RawFormat.from_json(msg_format.values)
async def render_into(self, buffer: Buffer, plane: int, format: RawFormat, offset: int = 0) -> int: await self.ensure_acquired() f_json = format.to_json() response: Message = await self.client.render(frame=self.frame, format=f_json, planes=[plane]) if response.values['size'] is None: raise ValueError("Unsupported format.") buf_sz = len(response.blobs[0]) buffer[:buf_sz] = response.blobs[0] return buf_sz
""" arr = frame.get_read_array(planeno) length = len(arr) if length + offset > len(buffer): raise BufferError("Buffer too short.") buffer[offset:offset + length] = arr return len(arr) FORMAT_COMPATBGR32 = RawFormat(sample_type=SampleType.INTEGER, family=ColorFamily.RGB, bits_per_sample=8, subsampling_h=0, subsampling_w=0, num_fields=4, packed=True, planar=False) FORMAT_COMPATYUY2 = RawFormat(sample_type=SampleType.INTEGER, family=ColorFamily.YUV, bits_per_sample=8, subsampling_h=0, subsampling_w=1, num_fields=3, packed=True, planar=False) class VapourSynthFrame(Frame): def __init__(self, script: Script, clip: 'VapourSynthClip', frameno: int):