From 49c40d62dcc649a0b9eb3def3c7d2232727eed74 Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 21 Jan 2025 14:51:58 +0700 Subject: [PATCH] #511 add more diagnostics --- xpra/codecs/amf/amf.pxd | 119 +++++++++++++++++++++++++++++++++--- xpra/codecs/amf/encoder.pyx | 70 +++++++++++++-------- 2 files changed, 156 insertions(+), 33 deletions(-) diff --git a/xpra/codecs/amf/amf.pxd b/xpra/codecs/amf/amf.pxd index 0a2ffb0f5e..795ccedc23 100644 --- a/xpra/codecs/amf/amf.pxd +++ b/xpra/codecs/amf/amf.pxd @@ -139,7 +139,6 @@ cdef extern from "core/Data.h": ctypedef AMF_MEMORY_TYPE (*DATA_GETMEMORYTYPE)(AMFData* pThis); ctypedef AMF_DATA_TYPE (*DATA_GETDATATYPE)(AMFData* pThis); - ctypedef struct AMFDataVtbl: DATA_ACQUIRE Acquire DATA_RELEASE Release @@ -267,6 +266,17 @@ cdef extern from "core/Buffer.h": const AMFBufferVtbl *pVtbl +cdef inline AMF_PLANE_TYPE_STR(AMF_PLANE_TYPE ptype): + return { + AMF_PLANE_UNKNOWN: "UNKNOWN", + AMF_PLANE_PACKED: "PACKED", + AMF_PLANE_Y: "Y", + AMF_PLANE_UV: "UV", + AMF_PLANE_U: "U", + AMF_PLANE_V: "V", + }.get(ptype, "unknown") + + cdef extern from "core/Trace.h": ctypedef void (*TRACEW)(AMFTrace* pThis, const wchar_t* src_path, amf_int32 line, amf_int32 level, const wchar_t* scope,amf_int32 countArgs, const wchar_t* format, ...) @@ -289,6 +299,37 @@ cdef extern from "core/Trace.h": cdef extern from "core/Surface.h": + ctypedef enum AMF_FRAME_TYPE: + AMF_FRAME_STEREO_FLAG + AMF_FRAME_LEFT_FLAG + AMF_FRAME_RIGHT_FLAG + AMF_FRAME_BOTH_FLAG + AMF_FRAME_INTERLEAVED_FLAG + AMF_FRAME_FIELD_FLAG + AMF_FRAME_EVEN_FLAG + AMF_FRAME_ODD_FLAG + + # values + AMF_FRAME_UNKNOWN + AMF_FRAME_PROGRESSIVE + + AMF_FRAME_INTERLEAVED_EVEN_FIRST + AMF_FRAME_INTERLEAVED_ODD_FIRST + AMF_FRAME_FIELD_SINGLE_EVEN + AMF_FRAME_FIELD_SINGLE_ODD + + AMF_FRAME_STEREO_LEFT + AMF_FRAME_STEREO_RIGHT + AMF_FRAME_STEREO_BOTH + + AMF_FRAME_INTERLEAVED_EVEN_FIRST_STEREO_LEFT + AMF_FRAME_INTERLEAVED_EVEN_FIRST_STEREO_RIGHT + AMF_FRAME_INTERLEAVED_EVEN_FIRST_STEREO_BOTH + + AMF_FRAME_INTERLEAVED_ODD_FIRST_STEREO_LEFT + AMF_FRAME_INTERLEAVED_ODD_FIRST_STEREO_RIGHT + AMF_FRAME_INTERLEAVED_ODD_FIRST_STEREO_BOTH + ctypedef enum AMF_SURFACE_FORMAT: AMF_SURFACE_NV12 # 1 - planar 4:2:0 Y width x height + packed UV width/2 x height/2 - 8 bit per component AMF_SURFACE_YV12 # 2 - planar 4:2:0 Y width x height + V width/2 x height/2 + U width/2 x height/2 - 8 bit per component @@ -314,22 +355,85 @@ cdef extern from "core/Surface.h": ctypedef AMF_RESULT (*SURFACE_SETPROPERTY)(AMFSurface* pThis, const wchar_t* name, AMFVariantStruct value) ctypedef amf_long (*SURFACE_ACQUIRE)(AMFSurface* pThis) ctypedef amf_long (*SURFACE_RELEASE)(AMFSurface* pThis) + ctypedef AMF_SURFACE_FORMAT (*SURFACE_GETFORMAT)(AMFSurface* pThis) ctypedef amf_size (*SURFACE_GETPLANESCOUNT)(AMFSurface* pThis) ctypedef AMFPlane* (*SURFACE_GETPLANEAT)(AMFSurface* pThis, amf_size index) ctypedef AMFPlane* (*SURFACE_GETPLANE)(AMFSurface* pThis, AMF_PLANE_TYPE type) + ctypedef AMF_FRAME_TYPE (*SURFACE_GETFRAMETYPE)(AMFSurface* pThis) ctypedef struct AMFSurfaceVtbl: SURFACE_SETPROPERTY SetProperty SURFACE_ACQUIRE Acquire SURFACE_RELEASE Release + SURFACE_GETFORMAT GetFormat SURFACE_GETPLANESCOUNT GetPlanesCount SURFACE_GETPLANEAT GetPlaneAt SURFACE_GETPLANE GetPlane + SURFACE_GETFRAMETYPE GetFrameType ctypedef struct AMFSurface: const AMFSurfaceVtbl *pVtbl +cdef inline AMF_SURFACE_FORMAT_STR(AMF_SURFACE_FORMAT fmt): + return { + AMF_SURFACE_NV12: "NV12", + AMF_SURFACE_YV12: "YV12", + AMF_SURFACE_BGRA: "BGRA", + AMF_SURFACE_ARGB: "ARGB", + AMF_SURFACE_RGBA: "RGBA", + AMF_SURFACE_GRAY8: "GRAY8", + AMF_SURFACE_YUV420P: "YUV420P", + AMF_SURFACE_U8V8: "U8V8", + AMF_SURFACE_YUY2: "YUY2", + AMF_SURFACE_P010: "P010", + AMF_SURFACE_RGBA_F16: "RGBA_F16", + AMF_SURFACE_UYVY: "UYVY", + AMF_SURFACE_R10G10B10A2: "R10G10B10A2", + AMF_SURFACE_Y210: "Y210", + AMF_SURFACE_AYUV: "AYUV", + AMF_SURFACE_Y410: "Y410", + AMF_SURFACE_Y416: "Y416", + AMF_SURFACE_GRAY32: "GRAY32", + AMF_SURFACE_P012: "P012", + AMF_SURFACE_P016: "P016", + }.get(fmt, "unknown") + + +cdef inline AMF_FRAME_TYPE_STR(AMF_FRAME_TYPE ftype): + return { + AMF_FRAME_STEREO_FLAG: "STEREO_FLAG", + AMF_FRAME_LEFT_FLAG: "LEFT_FLAG", + AMF_FRAME_RIGHT_FLAG: "RIGHT_FLAG", + AMF_FRAME_BOTH_FLAG: "BOTH_FLAG", + AMF_FRAME_INTERLEAVED_FLAG: "INTERLEAVED_FLAG", + AMF_FRAME_FIELD_FLAG: "FIELD_FLAG", + AMF_FRAME_EVEN_FLAG: "EVEN_FLAG", + AMF_FRAME_ODD_FLAG: "ODD_FLAG", + + # values + AMF_FRAME_UNKNOWN: "UNKNOWN", + AMF_FRAME_PROGRESSIVE: "PROGRESSIVE", + + AMF_FRAME_INTERLEAVED_EVEN_FIRST: "INTERLEAVED_EVEN_FIRST", + AMF_FRAME_INTERLEAVED_ODD_FIRST: "INTERLEAVED_ODD_FIRST", + AMF_FRAME_FIELD_SINGLE_EVEN: "FIELD_SINGLE_EVEN", + AMF_FRAME_FIELD_SINGLE_ODD: "FIELD_SINGLE_ODD", + + AMF_FRAME_STEREO_LEFT: "STEREO_LEFT", + AMF_FRAME_STEREO_RIGHT: "STEREO_RIGHT", + AMF_FRAME_STEREO_BOTH: "STEREO_BOTH", + + AMF_FRAME_INTERLEAVED_EVEN_FIRST_STEREO_LEFT: "INTERLEAVED_EVEN_FIRST_STEREO_LEFT", + AMF_FRAME_INTERLEAVED_EVEN_FIRST_STEREO_RIGHT: "INTERLEAVED_EVEN_FIRST_STEREO_RIGHT", + AMF_FRAME_INTERLEAVED_EVEN_FIRST_STEREO_BOTH: "INTERLEAVED_EVEN_FIRST_STEREO_BOTH", + + AMF_FRAME_INTERLEAVED_ODD_FIRST_STEREO_LEFT: "INTERLEAVED_ODD_FIRST_STEREO_LEFT", + AMF_FRAME_INTERLEAVED_ODD_FIRST_STEREO_RIGHT: "INTERLEAVED_ODD_FIRST_STEREO_RIGHT", + AMF_FRAME_INTERLEAVED_ODD_FIRST_STEREO_BOTH: "INTERLEAVED_ODD_FIRST_STEREO_BOTH", + }.get(ftype, "unknown") + + cdef extern from "core/Context.h": ctypedef enum AMF_DX_VERSION: AMF_DX9 # 90 @@ -538,12 +642,13 @@ cdef extern from "components/VideoEncoderVCE.h": AMF_VIDEO_ENCODER_PICTURE_TYPE_B -OUTPUT_DATA_TYPES: Dict[int, str] = { - AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR: "IDR", - AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_I: "I", - AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_P: "P", - AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_B: "B", -} +cdef inline AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_STR(AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_ENUM dtype): + return { + AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR: "IDR", + AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_I: "I", + AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_P: "P", + AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_B: "B", + }.get(dtype, "unknown") cdef extern from "components/VideoEncoderHEVC.h": diff --git a/xpra/codecs/amf/encoder.pyx b/xpra/codecs/amf/encoder.pyx index 3b9f49c9c9..697857b965 100644 --- a/xpra/codecs/amf/encoder.pyx +++ b/xpra/codecs/amf/encoder.pyx @@ -21,11 +21,12 @@ from xpra.util.env import envbool from xpra.util.objects import typedict from libc.stddef cimport wchar_t -from libc.stdint cimport uint8_t, uint64_t, uintptr_t +from libc.stdint cimport uint8_t, uint64_t, int64_t, uintptr_t from libc.string cimport memset from xpra.codecs.amf.amf cimport ( set_guid, + AMF_PLANE_TYPE_STR, AMF_SURFACE_FORMAT_STR, AMF_FRAME_TYPE_STR, AMF_RESULT, AMF_EOF, AMF_REPEAT, AMF_DX11_0, AMF_MEMORY_TYPE, @@ -51,12 +52,12 @@ from xpra.codecs.amf.amf cimport ( AMFGuid, AMFBuffer, AMFComponentOptimizationCallback, - AMFPlane, - AMFData, + AMFPlane, AMFPlaneVtbl, + AMFData, AMFDataVtbl, AMFTrace, AMFVariantStruct, AMFVariantAssignInt64, - AMFSurface, + AMFSurface, AMFSurfaceVtbl, AMFContext, AMFComponent, AMFFactory, @@ -264,7 +265,7 @@ cdef class Encoder: self.amf_surface_init() self.amf_encoder_init(options) - if SAVE_TO_FILE is not None: + if SAVE_TO_FILE: filename = SAVE_TO_FILE+f"amf-{self.generation}.{encoding}" self.file = open(filename, "wb") log.info(f"saving {encoding} stream to {filename!r}") @@ -458,7 +459,6 @@ cdef class Encoder: def compress_image(self, image: ImageWrapper, options: typedict) -> Tuple[bytes, Dict]: cdef uint8_t *pic_in[2] cdef int strides[2] - cdef int sizes[2] assert self.context!=NULL pixels = image.get_pixels() istrides = image.get_rowstride() @@ -493,8 +493,7 @@ cdef class Encoder: py_buf[i].len, "YUV"[i], istrides[i]*(self.height//ydiv)) pic_in[i] = py_buf[i].buf strides[i] = istrides[i] - sizes[i] = istrides[i] * (self.height // ydiv) - return self.do_compress_image(pic_in, strides, sizes), { + return self.do_compress_image(pic_in, strides), { "csc" : self.src_format, "frame" : int(self.frames), "full-range" : bool(full_range), @@ -513,7 +512,7 @@ cdef class Encoder: self.surface.pVtbl.SetProperty(self.surface, prop, var) PyMem_Free(prop) - cdef bytes do_compress_image(self, uint8_t *pic_in[2], int strides[2], int sizes[2]): + cdef bytes do_compress_image(self, uint8_t *pic_in[2], int strides[2]): cdef unsigned long start_time = 0 # nanoseconds! cdef AMFPlane *plane cdef uintptr_t dst_texture @@ -527,6 +526,7 @@ cdef class Encoder: with device.get_device_context() as dc: log("device: %s", device.get_info()) log("device context: %s", dc.get_info()) + log("surface: %s", self.get_surface_info(self.surface)) for plane_index in range(2): # get the D3D11 destination surface pointer for this plane: plane = self.surface.pVtbl.GetPlaneAt(self.surface, plane_index) @@ -536,9 +536,8 @@ cdef class Encoder: dst_texture = plane.pVtbl.GetNative(plane) log("texture=%#x, source=%#x", dst_texture, pic_in[plane_index]) assert dst_texture - box = () - #dc.update_subresource(dst_texture, 0, box, - # pic_in[plane_index], strides[plane_index], sizes[plane_index]) + #dc.update_2dtexture(dst_texture, self.width, self.height, + # pic_in[plane_index], strides[plane_index]) dc.flush() ns = round(1000 * 1000 * monotonic()) @@ -577,12 +576,14 @@ cdef class Encoder: size = buffer.pVtbl.GetSize(buffer) log(f"output=%#x, size=%i", output, size) assert output and size - return output[:size] + bdata = output[:size] + if self.file: + self.file.write(bdata) + return bdata finally: if buffer != NULL: buffer.pVtbl.Release(buffer) data.pVtbl.Release(data) - return b"" def flush(self, unsigned long frame_no) -> None: cdef AMF_RESULT res = self.encoder.pVtbl.Drain(self.encoder) @@ -593,23 +594,40 @@ cdef class Encoder: self.check(res, "AMF encoder flush") cdef get_data_info(self, AMFData *data): + assert data + cdef const AMFDataVtbl *dfn = data.pVtbl return { - "property-count": data.pVtbl.GetPropertyCount(data), - "memory-type": data.pVtbl.GetMemoryType(data), - "data-type": data.pVtbl.GetDataType(data), + "property-count": dfn.GetPropertyCount(data), + "memory-type": dfn.GetMemoryType(data), + "data-type": dfn.GetDataType(data), } cdef get_plane_info(self, AMFPlane *plane): + assert plane + ptype = plane.pVtbl.GetType(plane) + cdef const AMFPlaneVtbl *pfn = plane.pVtbl + return { + "type": AMF_PLANE_TYPE_STR(ptype), + "native": pfn.GetNative(plane), + "size": pfn.GetPixelSizeInBytes(plane), + "offset-x": pfn.GetOffsetX(plane), + "offset-y": pfn.GetOffsetY(plane), + "width": pfn.GetWidth(plane), + "height": pfn.GetHeight(plane), + "h-pitch": pfn.GetHPitch(plane), + "v-pitch": pfn.GetVPitch(plane), + "is-tiled": pfn.IsTiled(plane), + } + + cdef get_surface_info(self, AMFSurface *surface): + assert surface + cdef const AMFSurfaceVtbl *sfn = surface.pVtbl + fmt = sfn.GetFormat(surface) + ftype = sfn.GetFrameType(surface) return { - "native": plane.pVtbl.GetNative(plane), - "size": plane.pVtbl.GetPixelSizeInBytes(plane), - "offset-x": plane.pVtbl.GetOffsetX(plane), - "offset-y": plane.pVtbl.GetOffsetY(plane), - "width": plane.pVtbl.GetWidth(plane), - "height": plane.pVtbl.GetHeight(plane), - "h-pitch": plane.pVtbl.GetHPitch(plane), - "v-pitch": plane.pVtbl.GetVPitch(plane), - "is-tiled": plane.pVtbl.IsTiled(plane), + "format": AMF_SURFACE_FORMAT_STR(fmt), + "planes": sfn.GetPlanesCount(surface), + "frame-type": AMF_FRAME_TYPE_STR(ftype), } def set_encoding_speed(self, int pct) -> None: