xpra icon
Bug tracker and wiki

This bug tracker and wiki are being discontinued
please use https://github.com/Xpra-org/xpra instead.


Ticket #229: gl-yuv-cython-fix.patch

File gl-yuv-cython-fix.patch, 8.4 KB (added by Antoine Martin, 9 years ago)

use a wrapper class for returning pixel data and copy the data when we get it

  • xpra/gl/gl_window_backing.py

     
    128128            glFlush()
    129129        drawable.gl_end()
    130130
     131    def cairo_draw(self, context):
     132        drawable = self.gl_init()
     133        if drawable:
     134            try:
     135                self.do_cairo_draw(context, drawable)
     136            finally:
     137                self.gl_end(drawable)
     138
    131139    def gl_expose_event(self, glarea, event):
    132140        debug("gl_expose_event(%s, %s)", glarea, event)
    133141        area = event.area
     
    146154
    147155    def do_video_paint(self, coding, img_data, x, y, w, h, options, callbacks):
    148156        debug("do_video_paint: options=%s, decoder=%s", options, type(self._video_decoder))
    149         err, rowstrides, img_data = self._video_decoder.decompress_image_to_yuv(img_data, options)
     157        YUVImage = self._video_decoder.decompress_image_to_yuv(img_data, options)
    150158        csc_pixel_format = options.get("csc_pixel_format", -1)
    151159        #this needs to be done here so we still hold the video_decoder lock:
    152160        pixel_format = self._video_decoder.get_pixel_format(csc_pixel_format)
    153         success = err==0 and img_data and len(img_data)==3
    154         if not success:
    155             log.error("do_video_paint: %s decompression error %s on %s bytes of picture data for %sx%s pixels, options=%s",
    156                       coding, err, len(img_data), w, h, options)
     161        if YUVImage is None:
     162            log.error("do_video_paint: %s decompression error on %s bytes of picture data for %sx%s pixels, options=%s",
     163                      coding, len(img_data), w, h, options)
    157164            gobject.idle_add(fire_paint_callbacks, callbacks, False)
    158165            return
    159         gobject.idle_add(self.do_gl_paint, x, y, w, h, img_data, rowstrides, pixel_format, callbacks)
     166        gobject.idle_add(self.do_gl_paint, x, y, w, h, YUVImage, pixel_format, callbacks)
    160167
    161     def do_gl_paint(self, x, y, w, h, img_data, rowstrides, pixel_format, callbacks):
     168    def do_gl_paint(self, x, y, w, h, YUVImage, pixel_format, callbacks):
    162169        #this function runs in the UI thread, no video_decoder lock held
    163170        drawable = self.gl_init()
    164171        if not drawable:
     
    167174            return
    168175        try:
    169176            try:
    170                 self.update_texture_yuv(img_data, x, y, w, h, rowstrides, pixel_format)
     177                self.update_texture_yuv(YUVImage, x, y, w, h, pixel_format)
    171178                if self.paint_screen:
    172179                    self.render_image(x, y, x+w, y+h)
    173180                fire_paint_callbacks(callbacks, True)
     
    189196            return (1, 1), (1, 1), (1, 1)
    190197        raise Exception("invalid pixel format: %s" % pixel_format)
    191198
    192     def update_texture_yuv(self, img_data, x, y, width, height, rowstrides, pixel_format):
     199    def update_texture_yuv(self, YUVImage, x, y, width, height, pixel_format):
    193200        window_width, window_height = self.size
    194201        assert self.textures is not None, "no OpenGL textures!"
    195202
     
    238245            (div_w, div_h) = divs[index]
    239246            glActiveTexture(texture)
    240247            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index])
    241             glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[index])
    242             glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width/div_w, height/div_h, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[index])
     248            rowstride = YUVImage.get_rowstride(index)
     249            glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstride)
     250            pixel_data = YUVImage.get_component(index)
     251            glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width/div_w, height/div_h, GL_LUMINANCE, GL_UNSIGNED_BYTE, pixel_data)
    243252            if index == 1:
    244253                U_width = width/div_w
    245254                U_height = height/div_h
     
    248257                    log.error("Width of V plane is %d, differs from width of corresponding U plane (%d), pixel_format is %d", width/div_w, U_width, pixel_format)
    249258                if height/div_h != U_height:
    250259                    log.error("Height of V plane is %d, differs from height of corresponding U plane (%d)", height/div_h, U_height)
     260        del YUVImage
    251261
    252262    def render_image(self, rx, ry, rw, rh):
    253263        debug("render_image %sx%s at %sx%s pixel_format=%s", rw, rh, rx, ry, self.pixel_format)
  • xpra/vpx/codec.pyx

     
    66import os
    77from libc.stdlib cimport free
    88
     9cdef extern from "string.h":
     10    void * memcpy ( void * destination, void * source, size_t num )
     11    void * memset ( void * ptr, int value, size_t num )
     12
    913cdef extern from "Python.h":
    1014    ctypedef int Py_ssize_t
    1115    ctypedef object PyObject
     
    8185    def __dealloc__(self):                  #@DuplicatedSignature
    8286        self.free()
    8387
     88cdef class YUVImage:
     89    cdef uint8_t *y
     90    cdef uint8_t *u
     91    cdef uint8_t *v
     92    cdef int ystride
     93    cdef int ustride
     94    cdef int vstride
     95    cdef int height
    8496
     97    cdef uint8_t* copy(self, uint8_t *src, long size):
     98        cdef uint8_t *dst
     99        dst = <uint8_t*> xmemalign(size+1024)
     100        memcpy(dst, src, size)
     101        return dst
     102
     103    cdef init(self, uint8_t *y, int ystride, uint8_t *u, int ustride, uint8_t *v, int vstride, int height):
     104        print("new YUVImage(%s, %s, %s, %s)" % (ystride, ustride, vstride, height))
     105        self.height = height
     106        self.ystride = ystride
     107        self.ustride = ustride
     108        self.vstride = vstride
     109        self.y = self.copy(y, height * ystride)
     110        self.u = self.copy(u, height * ustride)
     111        self.v = self.copy(v, height * vstride)
     112        print("new YUVImage(%s, %s, %s, %s) done" % (ystride, ustride, vstride, height))
     113
     114    cdef free(self):                        #@DuplicatedSignature
     115        print("YUVImage.free()")
     116        xmemfree(self.y)
     117        xmemfree(self.u)
     118        xmemfree(self.v)
     119        self.y = NULL
     120        self.u = NULL
     121        self.v = NULL
     122
     123    def get_component(self, index):
     124        #doutvY = (<char *>dout[0])[:self.height * outstrides[0]]
     125        if index==0:
     126            return (<char *> self.y)[:self.height * self.ystride]
     127        elif index==1:
     128            return (<char *> self.u)[:self.height * self.ustride]
     129        elif index==2:
     130            return (<char *> self.v)[:self.height * self.vstride]
     131        else:
     132            raise Exception("invalid component index %s" % index)
     133
     134    def get_rowstride(self, index):         #@DuplicatedSignature
     135        if index==0:
     136            return self.ystride
     137        elif index==1:
     138            return self.ustride
     139        elif index==2:
     140            return self.vstride
     141        else:
     142            raise Exception("invalid component index %s" % index)
     143
     144    def __dealloc__(self):                  #@DuplicatedSignature
     145        self.free()
     146
     147
    85148cdef class Decoder(xcoder):
    86149
    87150    def init_context(self, width, height, use_swscale, options):
     
    104167        PyObject_AsReadBuffer(input, <const_void_pp> &buf, &buf_len)
    105168        i = decompress_image(self.context, buf, buf_len, &dout, &outsize, &outstrides)
    106169        if i!=0:
    107             return i, [0, 0, 0], ["", "", ""]
    108         doutvY = (<char *>dout[0])[:self.height * outstrides[0]]
    109         doutvU = (<char *>dout[1])[:self.height * outstrides[1]]
    110         doutvV = (<char *>dout[2])[:self.height * outstrides[2]]
    111         out = [doutvY, doutvU, doutvV]
    112         strides = [outstrides[0], outstrides[1], outstrides[2]]
    113         return  i, strides, out
     170            return None
     171        yuv = YUVImage()
     172        yuv.init(dout[0], outstrides[0], dout[1], outstrides[1], dout[2], outstrides[2], self.height)
     173        return yuv
    114174
    115175    def get_pixel_format(self, csc_pixel_format):
    116176        #we only support 420 at present
  • xpra/window_backing.py

     
    174174
    175175
    176176    def cairo_draw(self, context):
     177        self.do_cairo_draw(context, self._backing)
     178
     179    def do_cairo_draw(self, context, drawable):
    177180        try:
    178             context.set_source_pixmap(self._backing, 0, 0)
     181            context.set_source_pixmap(drawable, 0, 0)
    179182            context.set_operator(cairo.OPERATOR_SOURCE)
    180183            context.paint()
    181184            return True