1 2cdef object _cinit_bypass_sentinel = object() 3 4cdef VideoFormat get_video_format(lib.AVPixelFormat c_format, unsigned int width, unsigned int height): 5 if c_format == lib.AV_PIX_FMT_NONE: 6 return None 7 cdef VideoFormat format = VideoFormat.__new__(VideoFormat, _cinit_bypass_sentinel) 8 format._init(c_format, width, height) 9 return format 10 11 12cdef class VideoFormat(object): 13 """ 14 15 >>> format = VideoFormat('rgb24') 16 >>> format.name 17 'rgb24' 18 19 """ 20 21 def __cinit__(self, name, width=0, height=0): 22 23 if name is _cinit_bypass_sentinel: 24 return 25 26 cdef VideoFormat other 27 if isinstance(name, VideoFormat): 28 other = <VideoFormat>name 29 self._init(other.pix_fmt, width or other.width, height or other.height) 30 return 31 32 cdef lib.AVPixelFormat pix_fmt = lib.av_get_pix_fmt(name) 33 if pix_fmt < 0: 34 raise ValueError('not a pixel format: %r' % name) 35 self._init(pix_fmt, width, height) 36 37 cdef _init(self, lib.AVPixelFormat pix_fmt, unsigned int width, unsigned int height): 38 self.pix_fmt = pix_fmt 39 self.ptr = lib.av_pix_fmt_desc_get(pix_fmt) 40 self.width = width 41 self.height = height 42 self.components = tuple( 43 VideoFormatComponent(self, i) 44 for i in range(self.ptr.nb_components) 45 ) 46 47 def __repr__(self): 48 if self.width or self.height: 49 return '<av.%s %s, %dx%d>' % (self.__class__.__name__, self.name, self.width, self.height) 50 else: 51 return '<av.%s %s>' % (self.__class__.__name__, self.name) 52 53 def __int__(self): 54 return int(self.pix_fmt) 55 56 property name: 57 """Canonical name of the pixel format.""" 58 def __get__(self): 59 return <str>self.ptr.name 60 61 property bits_per_pixel: 62 def __get__(self): return lib.av_get_bits_per_pixel(self.ptr) 63 64 property padded_bits_per_pixel: 65 def __get__(self): return lib.av_get_padded_bits_per_pixel(self.ptr) 66 67 property is_big_endian: 68 """Pixel format is big-endian.""" 69 def __get__(self): return bool(self.ptr.flags & lib.AV_PIX_FMT_FLAG_BE) 70 71 property has_palette: 72 """Pixel format has a palette in data[1], values are indexes in this palette.""" 73 def __get__(self): return bool(self.ptr.flags & lib.AV_PIX_FMT_FLAG_PAL) 74 75 property is_bit_stream: 76 """All values of a component are bit-wise packed end to end.""" 77 def __get__(self): return bool(self.ptr.flags & lib.AV_PIX_FMT_FLAG_BITSTREAM) 78 79 # Skipping PIX_FMT_HWACCEL 80 # """Pixel format is an HW accelerated format.""" 81 82 property is_planar: 83 """At least one pixel component is not in the first data plane.""" 84 def __get__(self): return bool(self.ptr.flags & lib.AV_PIX_FMT_FLAG_PLANAR) 85 86 property is_rgb: 87 """The pixel format contains RGB-like data (as opposed to YUV/grayscale).""" 88 def __get__(self): return bool(self.ptr.flags & lib.AV_PIX_FMT_FLAG_RGB) 89 90 cpdef chroma_width(self, int luma_width=0): 91 """chroma_width(luma_width=0) 92 93 Width of a chroma plane relative to a luma plane. 94 95 :param int luma_width: Width of the luma plane; defaults to ``self.width``. 96 97 """ 98 luma_width = luma_width or self.width 99 return -((-luma_width) >> self.ptr.log2_chroma_w) if luma_width else 0 100 101 cpdef chroma_height(self, int luma_height=0): 102 """chroma_height(luma_height=0) 103 104 Height of a chroma plane relative to a luma plane. 105 106 :param int luma_height: Height of the luma plane; defaults to ``self.height``. 107 108 """ 109 luma_height = luma_height or self.height 110 return -((-luma_height) >> self.ptr.log2_chroma_h) if luma_height else 0 111 112 113cdef class VideoFormatComponent(object): 114 115 def __cinit__(self, VideoFormat format, size_t index): 116 self.format = format 117 self.index = index 118 self.ptr = &format.ptr.comp[index] 119 120 property plane: 121 """The index of the plane which contains this component.""" 122 def __get__(self): 123 return self.ptr.plane 124 125 property bits: 126 """Number of bits in the component.""" 127 def __get__(self): 128 return self.ptr.depth 129 130 property is_alpha: 131 """Is this component an alpha channel?""" 132 def __get__(self): 133 return ((self.index == 1 and self.format.ptr.nb_components == 2) or 134 (self.index == 3 and self.format.ptr.nb_components == 4)) 135 136 property is_luma: 137 """Is this compoment a luma channel?""" 138 def __get__(self): 139 return self.index == 0 and ( 140 self.format.ptr.nb_components == 1 or 141 self.format.ptr.nb_components == 2 or 142 not self.format.is_rgb 143 ) 144 145 property is_chroma: 146 """Is this component a chroma channel?""" 147 def __get__(self): 148 return (self.index == 1 or self.index == 2) and (self.format.ptr.log2_chroma_w or self.format.ptr.log2_chroma_h) 149 150 property width: 151 """The width of this component's plane. 152 153 Requires the parent :class:`VideoFormat` to have a width. 154 155 """ 156 def __get__(self): 157 return self.format.chroma_width() if self.is_chroma else self.format.width 158 159 property height: 160 """The height of this component's plane. 161 162 Requires the parent :class:`VideoFormat` to have a height. 163 164 """ 165 def __get__(self): 166 return self.format.chroma_height() if self.is_chroma else self.format.height 167 168 169names = set() 170cdef const lib.AVPixFmtDescriptor *desc = NULL 171while True: 172 desc = lib.av_pix_fmt_desc_next(desc) 173 if not desc: 174 break 175 names.add(desc.name) 176