Ticket #832: vp9-yuv444p.patch
File vp9-yuv444p.patch, 18.4 KB (added by , 7 years ago) |
---|
-
tests/xpra/codecs/test_encoder.py
46 46 log("input colorspaces=%s", ics) 47 47 for ic in ics: 48 48 for encoding in encoder_module.get_encodings(): 49 ocs = encoder_module.get_output_colorspaces( ic)49 ocs = encoder_module.get_output_colorspaces(encoding, ic) 50 50 for c in ocs: 51 51 log("spec(%s)=%s" % (c, encoder_module.get_spec(encoding, ic))) 52 52 log("version=%s" % str(encoder_module.get_version())) -
tests/xpra/codecs/test_nvenc.py
103 103 for w,h in TEST_DIMENSIONS: 104 104 log("test_context_limits() %s @ %sx%s" % (encoding, w, h)) 105 105 src_format = encoder_module.get_input_colorspaces()[0] 106 dst_formats = encoder_module.get_output_colorspaces( src_format)106 dst_formats = encoder_module.get_output_colorspaces(encoding, src_format) 107 107 for device_id in cuda_devices: 108 108 device_info = get_device_info(device_id) 109 109 options = {"cuda_device" : device_id} … … 134 134 IMAGE_COUNT = 40 135 135 ENCODER_CONTEXTS_PER_DEVICE = 10 136 136 src_format = encoder_module.get_input_colorspaces()[0] 137 dst_formats = encoder_module.get_output_colorspaces( src_format)137 dst_formats = encoder_module.get_output_colorspaces(encoding, src_format) 138 138 log("generating %s images..." % IMAGE_COUNT) 139 139 images = [] 140 140 for _ in range(IMAGE_COUNT): -
tests/xpra/codecs/test_video_codec.py
11 11 from tests.xpra.codecs.test_codec import make_rgb_input, make_planar_input 12 12 13 13 14 def do_test_codec_roundtrip(encoder_class, decoder_class, encoding, src_format, w, h, populate):14 def do_test_codec_roundtrip(encoder_class, decoder_class, encoding, src_format, dst_formats, w, h, populate): 15 15 if src_format.find("RGB")>=0 or src_format.find("BGR")>=0: 16 16 pixels = make_rgb_input(src_format, w, h, populate=populate) 17 17 isize = len(pixels) … … 31 31 32 32 start = time.time() 33 33 encoder = encoder_class() 34 encoder.init_context(w, h, src_format, encoding, quality, speed, scaling, options) 34 #print("%s%s" % (encoder.init_context, (w, h, src_format, dst_formats, encoding, quality, speed, scaling, options))) 35 encoder.init_context(w, h, src_format, dst_formats, encoding, quality, speed, scaling, options) 35 36 end = time.time() 36 37 print("encoder %s initialized in %.1fms" % (encoder, 1000.0*(end-start))) 37 38 … … 43 44 44 45 print("using %s to compress %s" % (encoder, image)) 45 46 start = time.time() 46 data, options = encoder.compress_image(image , {})47 data, options = encoder.compress_image(image) 47 48 end = time.time() 48 49 assert data is not None, "compression failed" 49 50 print("compressed %s bytes down to %s (%.1f%%) in %.1fms" % (isize, len(data), 100.0*len(data)/isize, 1000.0*(end-start))) -
tests/xpra/codecs/test_vpx.py
5 5 # later version. See the file COPYING for details. 6 6 7 7 from tests.xpra.codecs.test_video_codec import do_test_codec_roundtrip 8 from xpra.codecs.vpx import encoder as vpx_encoder #@UnresolvedImport 8 9 from xpra.codecs.vpx.decoder import Decoder #@UnresolvedImport 9 10 from xpra.codecs.vpx.encoder import Encoder #@UnresolvedImport 10 11 … … 13 14 print("") 14 15 print("test_roundtrip() %s" % encoding) 15 16 for populate in (True, False): 16 do_test_codec_roundtrip(Encoder, Decoder, encoding, "YUV420P", 640, 480, populate) 17 src_formats = vpx_encoder.get_input_colorspaces(encoding) 18 for src_format in src_formats: 19 do_test_codec_roundtrip(Encoder, Decoder, encoding, src_format, [src_format], 640, 480, populate) 17 20 18 21 19 22 def main(): -
xpra/codecs/enc_x264/encoder.pyx
258 258 def get_encodings(): 259 259 return ["h264"] 260 260 261 def get_input_colorspaces( ):262 global COLORSPACES261 def get_input_colorspaces(encoding): 262 assert encoding in get_encodings() 263 263 return COLORSPACES.keys() 264 264 265 def get_output_colorspaces(input_colorspace): 265 def get_output_colorspaces(encoding, input_colorspace): 266 assert encoding in get_encodings() 266 267 assert input_colorspace in COLORSPACES 267 268 return COLORSPACE_FORMATS[input_colorspace] 268 269 -
xpra/codecs/enc_x265/encoder.pyx
220 220 def get_encodings(): 221 221 return ["h265"] 222 222 223 def get_input_colorspaces(): 223 def get_input_colorspaces(encoding): 224 assert encoding in get_encodings() 224 225 return COLORSPACES 225 226 226 def get_output_colorspaces(input_colorspace): 227 def get_output_colorspaces(encoding, input_colorspace): 228 assert encoding in get_encodings() 227 229 assert input_colorspace in COLORSPACES 228 230 return (input_colorspace, ) 229 231 -
xpra/codecs/nvenc3/encoder.pyx
1129 1129 COLORSPACES = {"BGRX" : ("YUV420P",)} 1130 1130 return COLORSPACES 1131 1131 1132 def get_input_colorspaces( ):1132 def get_input_colorspaces(encoding): 1133 1133 return get_COLORSPACES().keys() 1134 1134 1135 def get_output_colorspaces(input_colorspace): 1135 def get_output_colorspaces(encoding, input_colorspace): 1136 assert encoding in get_encodings() 1136 1137 assert input_colorspace in get_COLORSPACES(), "invalid input colorspace: %s (must be one of: %s)" % (input_colorspace, get_COLORSPACES()) 1137 1138 #the output will actually be in one of those two formats once decoded 1138 1139 #because internally that's what we convert to before encoding … … 2176 2177 #load the library / DLL: 2177 2178 init_nvencode_library() 2178 2179 2179 colorspaces = get_input_colorspaces()2180 assert colorspaces, "cannot use NVENC: no colorspaces available"2181 2182 2180 success = False 2183 2181 valid_keys = [] 2184 2182 failed_keys = [] … … 2192 2190 2193 2191 test_encoder = Encoder() 2194 2192 for encoding in get_encodings(): 2193 colorspaces = get_input_colorspaces(encoding) 2194 assert colorspaces, "cannot use NVENC: no colorspaces available" 2195 2195 src_format = colorspaces[0] 2196 2196 dst_formats = get_output_colorspaces(src_format) 2197 2197 try: -
xpra/codecs/nvenc4/encoder.pyx
1007 1007 COLORSPACES = {"BGRX" : ("YUV420P",)} 1008 1008 return COLORSPACES 1009 1009 1010 def get_input_colorspaces(): 1010 def get_input_colorspaces(encoding): 1011 assert encoding in get_encodings() 1011 1012 return get_COLORSPACES().keys() 1012 1013 1013 def get_output_colorspaces(input_colorspace): 1014 def get_output_colorspaces(encoding, input_colorspace): 1015 assert encoding in get_encodings() 1014 1016 assert input_colorspace in get_COLORSPACES(), "invalid input colorspace: %s (must be one of: %s)" % (input_colorspace, get_COLORSPACES()) 1015 1017 #the output will actually be in one of those two formats once decoded 1016 1018 #because internally that's what we convert to before encoding … … 2225 2227 #load the library / DLL: 2226 2228 init_nvencode_library() 2227 2229 2228 colorspaces = get_input_colorspaces()2229 assert colorspaces, "cannot use NVENC: no colorspaces available"2230 2231 2230 global YUV444_ENABLED, LOSSLESS_ENABLED 2232 2231 YUV444_ENABLED, LOSSLESS_ENABLED = True, True 2233 2232 success = False … … 2243 2242 2244 2243 test_encoder = Encoder() 2245 2244 for encoding in get_encodings(): 2245 colorspaces = get_input_colorspaces(encoding) 2246 assert colorspaces, "cannot use NVENC: no colorspaces available" 2246 2247 src_format = colorspaces[0] 2247 2248 dst_formats = get_output_colorspaces(src_format) 2248 2249 try: -
xpra/codecs/nvenc5/encoder.pyx
990 990 COLORSPACES = {"BGRX" : ("YUV420P",)} 991 991 return COLORSPACES 992 992 993 def get_input_colorspaces(): 993 def get_input_colorspaces(encoding): 994 assert encoding in get_encodings() 994 995 return get_COLORSPACES().keys() 995 996 996 def get_output_colorspaces(input_colorspace): 997 def get_output_colorspaces(encoding, input_colorspace): 998 assert encoding in get_encodings() 997 999 assert input_colorspace in get_COLORSPACES(), "invalid input colorspace: %s (must be one of: %s)" % (input_colorspace, get_COLORSPACES()) 998 1000 #the output will actually be in one of those two formats once decoded 999 1001 #because internally that's what we convert to before encoding … … 2207 2209 #load the library / DLL: 2208 2210 init_nvencode_library() 2209 2211 2210 colorspaces = get_input_colorspaces()2211 assert colorspaces, "cannot use NVENC: no colorspaces available"2212 2213 2212 global YUV444_ENABLED, LOSSLESS_ENABLED 2214 2213 YUV444_ENABLED, LOSSLESS_ENABLED = True, True 2215 2214 2216 2215 test_encoder = Encoder() 2217 2216 for encoding in get_encodings(): 2217 colorspaces = get_input_colorspaces(encoding) 2218 assert colorspaces, "cannot use NVENC: no colorspaces available for %s" % encoding 2218 2219 src_format = colorspaces[0] 2219 2220 dst_formats = get_output_colorspaces(src_format) 2220 2221 try: -
xpra/codecs/video_helper.py
276 276 log("exception in %s module %s initialization %s: %s", encoder_type, encoder_module.__name__, encoder_module.init_module, e, exc_info=True) 277 277 log.warn("Warning: %s video encoder failed: %s", encoder_type, e) 278 278 raise e 279 colorspaces = encoder_module.get_input_colorspaces()280 log("init_video_encoder_option(%s) %s input colorspaces=%s", encoder_module, encoder_type, colorspaces)281 279 encodings = encoder_module.get_encodings() 282 280 log("init_video_encoder_option(%s) %s encodings=%s", encoder_module, encoder_type, encodings) 283 281 for encoding in encodings: 284 #we assume that all encodings support all colorspaces here...285 #which may not be the case in the future!282 colorspaces = encoder_module.get_input_colorspaces(encoding) 283 log("init_video_encoder_option(%s) %s input colorspaces(%s)=%s", encoder_module, encoder_type, encoding, colorspaces) 286 284 for colorspace in colorspaces: 287 285 spec = encoder_module.get_spec(encoding, colorspace) 288 286 self.add_encoder_spec(encoding, colorspace, spec) -
xpra/codecs/vpx/decoder.pyx
13 13 VPX_THREADS = os.environ.get("XPRA_VPX_THREADS", "2") 14 14 15 15 DEF ENABLE_VP8 = True 16 DEF ENABLE_VP9 = False16 DEF ENABLE_VP9 = True 17 17 18 18 19 19 from libc.stdint cimport int64_t … … 91 91 vpx_image_t *vpx_codec_get_frame(vpx_codec_ctx_t *ctx, vpx_codec_iter_t *iter) nogil 92 92 93 93 94 #https://groups.google.com/a/webmproject.org/forum/?fromgroups#!msg/webm-discuss/f5Rmi-Cu63k/IXIzwVoXt_wJ 95 #"RGB is not supported. You need to convert your source to YUV, and then compress that." 96 COLORSPACES = {} 94 97 CODECS = [] 95 98 IF ENABLE_VP8 == True: 96 99 CODECS.append("vp8") 100 COLORSPACES["vp8"] = [b"YUV420P"] 97 101 IF ENABLE_VP9 == True: 98 102 CODECS.append("vp9") 103 vp9_cs = [b"YUV420P"] 104 #this is the ABI version with libvpx 1.4.0: 105 if VPX_DECODER_ABI_VERSION>=9: 106 vp9_cs.append(b"YUV444P") 107 COLORSPACES["vp9"] = vp9_cs 99 108 100 #https://groups.google.com/a/webmproject.org/forum/?fromgroups#!msg/webm-discuss/f5Rmi-Cu63k/IXIzwVoXt_wJ101 #"RGB is not supported. You need to convert your source to YUV, and then compress that."102 COLORSPACES = ["YUV420P"]103 109 104 105 110 def init_module(): 106 111 log("vpx.decoder.init_module()") 107 112 assert len(CODECS)>0, "no supported encodings!" … … 123 128 return CODECS 124 129 125 130 def get_input_colorspaces(encoding): 126 assert encoding in ("vp8", "vp9")127 return COLORSPACES 131 assert encoding in CODECS 132 return COLORSPACES.get(encoding) 128 133 129 134 def get_output_colorspace(encoding, csc): 130 135 #same as input … … 140 145 "build_config" : vpx_codec_build_config()} 141 146 142 147 143 def get_spec(colorspace):144 assert colorspace in COLORSPACES, "invalid colorspace: %s (must be one of %s)" % (colorspace, COLORSPACES)145 #quality: we only handle YUV420P but this is already accounted for by get_colorspaces() based score calculations146 #setup cost is reasonable (usually about 5ms)147 return codec_spec(Decoder, codec_type="vpx", setup_cost=40)148 149 150 148 cdef const vpx_codec_iface_t *make_codec_dx(encoding): 151 149 IF ENABLE_VP8 == True: 152 150 if encoding=="vp8": … … 201 199 202 200 def init_context(self, encoding, width, height, colorspace): 203 201 assert encoding in CODECS 204 assert colorspace=="YUV420P" 205 assert colorspace in COLORSPACES 202 assert colorspace in get_input_colorspaces(encoding) 206 203 cdef int flags = 0 207 204 cdef const vpx_codec_iface_t *codec_iface = make_codec_dx(encoding) 208 205 self.encoding = encoding 209 self.dst_format = "YUV420P"206 self.dst_format = colorspace 210 207 self.pixfmt = get_vpx_colorspace(self.dst_format) 211 208 self.width = width 212 209 self.height = height -
xpra/codecs/vpx/encoder.pyx
10 10 from xpra.log import Logger 11 11 log = Logger("encoder", "vpx") 12 12 13 VPX_THREADS = os.environ.get("XPRA_VPX_THREADS", "2")14 13 14 #sensible default: 15 cpus = 2 16 try: 17 cpus = os.cpu_count() 18 except: 19 try: 20 import multiprocessing 21 multiprocessing.cpu_count() 22 except: 23 pass 24 VPX_THREADS = os.environ.get("XPRA_VPX_THREADS", cpus) 25 15 26 DEF ENABLE_VP8 = True 16 27 DEF ENABLE_VP9 = True 17 28 … … 52 63 53 64 cdef extern from "vpx/vpx_image.h": 54 65 cdef int VPX_IMG_FMT_I420 66 cdef int VPX_IMG_FMT_I444 55 67 ctypedef struct vpx_image_t: 56 68 unsigned int w 57 69 unsigned int h … … 169 181 170 182 #https://groups.google.com/a/webmproject.org/forum/?fromgroups#!msg/webm-discuss/f5Rmi-Cu63k/IXIzwVoXt_wJ 171 183 #"RGB is not supported. You need to convert your source to YUV, and then compress that." 172 COLORSPACES = { b"YUV420P" : [b"YUV420P"]}184 COLORSPACES = {} 173 185 174 186 CODECS = [] 175 187 IF ENABLE_VP8 == True: 176 188 CODECS.append("vp8") 189 COLORSPACES["vp8"] = [b"YUV420P"] 177 190 IF ENABLE_VP9 == True: 178 191 CODECS.append("vp9") 192 vp9_cs = [b"YUV420P"] 193 #this is the ABI version with libvpx 1.4.0: 194 if VPX_ENCODER_ABI_VERSION>=10: 195 vp9_cs.append(b"YUV444P") 196 COLORSPACES["vp9"] = vp9_cs 179 197 180 198 181 199 def init_module(): … … 198 216 def get_encodings(): 199 217 return CODECS 200 218 201 def get_input_colorspaces(): 202 return COLORSPACES.keys() 219 def get_input_colorspaces(encoding): 220 assert encoding in get_encodings(), "invalid encoding: %s" % encoding 221 return COLORSPACES[encoding] 203 222 204 def get_output_colorspaces(input_colorspace): 205 return COLORSPACES[input_colorspace] 223 def get_output_colorspaces(encoding, input_colorspace): 224 assert encoding in get_encodings(), "invalid encoding: %s" % encoding 225 csdict = COLORSPACES[input_colorspace] 226 assert input_colorspace in csdict, "invalid input colorspace: %s" % input_colorspace 227 #always unchanged in output: 228 return input_colorspace 206 229 207 230 208 231 def get_info(): … … 225 248 226 249 def get_spec(encoding, colorspace): 227 250 assert encoding in CODECS, "invalid encoding: %s (must be one of %s" % (encoding, get_encodings()) 228 assert colorspace in COLORSPACES, "invalid colorspace: %s (must be one of %s)" % (colorspace, COLORSPACES)251 assert colorspace in get_input_colorspaces(encoding), "invalid colorspace: %s (must be one of %s)" % (colorspace, get_input_colorspaces(encoding)) 229 252 #quality: we only handle YUV420P but this is already accounted for by the subsampling factor 230 253 #setup cost is reasonable (usually about 5ms) 231 return video_codec_spec(encoding=encoding, output_colorspaces= COLORSPACES[colorspace],254 return video_codec_spec(encoding=encoding, output_colorspaces=colorspace, 232 255 codec_class=Encoder, codec_type=get_type(), setup_cost=40) 233 256 234 257 235 258 cdef vpx_img_fmt_t get_vpx_colorspace(colorspace): 236 259 assert colorspace in COLORSPACES 237 return VPX_IMG_FMT_I420 260 if colorspace=="YUV420P": 261 return VPX_IMG_FMT_I420 262 elif colorspace=="YUV444P": 263 return VPX_IMG_FMT_I444 264 raise Exception("invalid colorspace %s" % colorspace) 238 265 239 266 240 267 cdef class Encoder: … … 253 280 254 281 cdef object __weakref__ 255 282 283 #init_context(w, h, src_format, encoding, quality, speed, scaling, options) 256 284 def init_context(self, int width, int height, src_format, dst_formats, encoding, int quality, int speed, scaling, options): #@DuplicatedSignature 257 285 assert encoding in CODECS, "invalid encoding: %s" % encoding 258 286 assert scaling==(1,1), "vpx does not handle scaling" 287 assert encoding in get_encodings() 288 assert src_format in get_input_colorspaces(encoding) 289 self.src_format = src_format 290 259 291 cdef const vpx_codec_iface_t *codec_iface = make_codec_cx(encoding) 260 292 self.encoding = encoding 261 293 self.width = width … … 263 295 self.speed = speed 264 296 self.quality = quality 265 297 self.frames = 0 266 assert src_format=="YUV420P" and "YUV420P" in dst_formats267 self.src_format = "YUV420P"268 298 self.pixfmt = get_vpx_colorspace(self.src_format) 269 299 try: 270 300 self.max_threads = max(0, min(32, int(options.get("threads", VPX_THREADS))))