xpra icon
Bug tracker and wiki

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


Ticket #304: small-regions-as-yuv-paint.patch

File small-regions-as-yuv-paint.patch, 23.4 KB (added by Antoine Martin, 9 years ago)

attempts to implement rgb2yuv for small regions

  • xpra/client_window.py

     
    209209        self._metadata = {}
    210210        self._override_redirect = override_redirect
    211211        self._client_properties = client_properties
     212        self._source_properties = {}
    212213        self._auto_refresh_delay = auto_refresh_delay
    213214        self._refresh_timer = None
    214215        self._refresh_min_pixels = -1
     
    491492
    492493
    493494    def do_map_event(self, event):
    494         log("Got map event: %s", event)
     495        log.info("Got map event: %s, OR=%s", event, self._override_redirect)
    495496        gtk.Window.do_map_event(self, event)
    496497        if self.group_leader:
    497498            self.window.set_group(self.group_leader)
     
    508509            if workspace>=0:
    509510                self._client_properties["workspace"] = workspace
    510511            log("map-window for wid=%s with client props=%s", self._id, self._client_properties)
    511             self._client.send("map-window", self._id, x, y, w, h, self._client_properties)
     512            self._client.send("map-window", self._id, x, y, w, h, self._client_properties, self._source_properties)
    512513            self._pos = (x, y)
    513514            self._size = (w, h)
    514515        self._been_mapped = True
     
    538539                if workspace>=0:
    539540                    self._client_properties["workspace"] = workspace
    540541            log("configure-window for wid=%s with client props=%s", self._id, self._client_properties)
    541             self._client.send("configure-window", self._id, x, y, w, h, self._client_properties)
     542            self._client.send("configure-window", self._id, x, y, w, h, self._client_properties, self._source_properties)
    542543        if dx!=0 or dy!=0:
    543544            #window has moved
    544545            if not self._client.window_configure:
  • xpra/gl/gl_client_window.py

     
    2020        ClientWindow.__init__(self, client, group_leader, wid, x, y, w, h, metadata, override_redirect, client_properties, auto_refresh_delay)
    2121        self.set_reallocate_redraws(True)
    2222        self.add(self._backing.glarea)
     23        self._source_properties["encoding.prefer_yuv"] = True
    2324
    2425    def is_GL(self):
    2526        return True
  • xpra/gl/gl_window_backing.py

     
    142142            finally:
    143143                self.gl_end(drawable)
    144144
     145    def paint_YUV(self, img_data, x, y, width, height, rowstride, options, callbacks):
     146        log.info("paint_YUV(%s bytes, %s, %s, %s, %s, %s, %s, %s)", len(img_data), x, y, width, height, rowstride, options, callbacks)
     147        rowstrides = options.get("strides")
     148        csc_pixel_format = options.get("csc_pixel_format")
     149        pixel_format = self._video_decoder.get_pixel_format_for_csc(csc_pixel_format)
     150        gobject.idle_add(self.do_gl_paint, x, y, width, height, img_data, rowstrides, pixel_format, callbacks)
    145151
    146152    def _do_paint_rgb24(self, img_data, x, y, width, height, rowstride, options, callbacks):
    147153        debug("_do_paint_rgb24: %sx%s at %sx%s", width, height, x, y)
     
    149155        self.glarea.window.draw_rgb_image(gc, x, y, width, height, gdk.RGB_DITHER_NONE, img_data, rowstride)
    150156
    151157    def do_video_paint(self, coding, img_data, x, y, w, h, options, callbacks):
    152         debug("do_video_paint: options=%s, decoder=%s", options, type(self._video_decoder))
     158        log.info("do_video_paint: options=%s, decoder=%s", options, type(self._video_decoder))
     159        assert x==0 and y==0
    153160        err, rowstrides, data = self._video_decoder.decompress_image_to_yuv(img_data, options)
    154161        csc_pixel_format = options.get("csc_pixel_format", -1)
    155162        #this needs to be done here so we still hold the video_decoder lock:
    156         pixel_format = self._video_decoder.get_pixel_format(csc_pixel_format)
     163        pixel_format = self._video_decoder.get_pixel_format_for_csc(csc_pixel_format)
    157164        success = err==0 and data and len(data)==3
    158165        if not success:
    159166            log.error("do_video_paint: %s decompression error %s on %s bytes of compressed picture data for %sx%s pixels, options=%s",
     
    183190
    184191
    185192    def update_texture_yuv(self, img_data, x, y, width, height, rowstrides, pixel_format):
    186         assert x==0 and y==0
    187193        assert self.textures is not None, "no OpenGL textures!"
    188194
     195        divs = get_subsampling_divs(pixel_format)
    189196        if self.pixel_format is None or self.pixel_format!=pixel_format or self.texture_size!=(width, height):
    190197            self.pixel_format = pixel_format
    191198            self.texture_size = (width, height)
    192             divs = get_subsampling_divs(pixel_format)
     199           
    193200            debug("GL creating new YUV textures for pixel format %s using divs=%s", pixel_format, divs)
    194201            # Create textures of the same size as the window's
    195202            glEnable(GL_TEXTURE_RECTANGLE_ARB)
     
    219226                    #FIXME: maybe we should do something else here?
    220227                    log.error(err)
    221228
    222         divs = get_subsampling_divs(pixel_format)
    223229        U_width = 0
    224230        U_height = 0
    225231        for texture, index in ((GL_TEXTURE0, 0), (GL_TEXTURE1, 1), (GL_TEXTURE2, 2)):
    226232            (div_w, div_h) = divs[index]
     233            rowstride = rowstrides[index]
     234            size = rowstride * height/div_h
     235            plane_data = img_data[index]
     236            if size!=len(plane_data):
     237                log.error("invalid plane %s: expected %s bytes but we only have %s", index, size, len(plane_data))
     238                continue
     239
    227240            glActiveTexture(texture)
    228241            glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textures[index])
    229             glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstrides[index])
    230             glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width/div_w, height/div_h, GL_LUMINANCE, GL_UNSIGNED_BYTE, img_data[index])
     242            glPixelStorei(GL_UNPACK_ROW_LENGTH, rowstride)
     243            glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, width/div_w, height/div_h, GL_LUMINANCE, GL_UNSIGNED_BYTE, plane_data)
    231244            if index == 1:
    232245                U_width = width/div_w
    233246                U_height = height/div_h
  • xpra/server.py

     
    469469            self._damage(window, event.x, event.y, event.width, event.height)
    470470
    471471    def _process_map_window(self, proto, packet):
     472        log.info("process_map_window(%s, %s)", proto, packet)
    472473        wid, x, y, width, height = packet[1:6]
    473474        window = self._id_to_window.get(wid)
    474475        if not window:
     
    479480        self._desktop_manager.show_window(window)
    480481        self._damage(window, 0, 0, width, height)
    481482        if len(packet)>=7:
     483            #this records things like workspace mapping:
    482484            self._set_client_properties(proto, wid, packet[6])
     485        if len(packet)>=8:
     486            self._set_source_properties(proto, wid, packet[7])
    483487
     488    def _set_source_properties(self, proto, wid, source_properties):
     489        #this is used by the client to pass info to the encoder:
     490        if len(source_properties)>0:
     491            ss = self._server_sources.get(proto)
     492            ss.set_source_properties(wid, source_properties)
    484493
    485494    def _process_unmap_window(self, proto, packet):
    486495        wid = packet[1]
     
    493502        self._desktop_manager.hide_window(window)
    494503
    495504    def _process_configure_window(self, proto, packet):
     505        log.info("process_configure_window(%s, %s)", proto, packet)
    496506        wid, x, y, w, h = packet[1:6]
    497507        window = self._id_to_window.get(wid)
    498508        if not window:
     
    510520            self._damage(window, 0, 0, w, h)
    511521        if len(packet)>=7:
    512522            self._set_client_properties(proto, wid, packet[6])
     523        if len(packet)>=8:
     524            self._set_source_properties(proto, wid, packet[7])
    513525
    514526    def _process_move_window(self, proto, packet):
    515527        wid, x, y = packet[1:4]
  • xpra/server_source.py

     
    805805# Functions used by the server to request something
    806806# (window events, stats, user requests, etc)
    807807#
     808    def set_source_properties(self, wid, props):
     809        #used by the client to request features:
     810        #(only encoding is supported at present)
     811        log.info("set_source_properties(%s, %s)", wid, props)
     812        enc_props = {}
     813        for k,v in props.items():
     814            if k.startswith("encoding."):
     815                k = k[len("encoding."):]
     816                enc_props[k] = v
     817        if len(enc_props)>0:
     818            ws = self.window_sources.get(wid)
     819            if ws:
     820                ws.set_encoder_options(enc_props)
     821
    808822    def set_encoding(self, encoding, window_ids):
    809823        """ Changes the encoder for the given 'window_ids',
    810824            or for all windows if 'window_ids' is None.
     
    11731187            batch_config.wid = wid
    11741188            ws = WindowSource(self.queue_damage, self.queue_packet, self.statistics,
    11751189                              wid, batch_config, self.auto_refresh_delay,
    1176                               self.encoding, self.encodings, self.encoding_options,
     1190                              self.encoding, self.encodings, self.encoding_options.copy(),
    11771191                              self.default_encoding_options,
    11781192                              self.mmap, self.mmap_size)
    11791193            self.window_sources[wid] = ws
  • xpra/vpx/codec.pyx

     
    5454    def get_height(self):
    5555        return self.height
    5656
     57    def get_pixel_format_for_csc(self, csc_pixel_format):
     58        #we only support 420 at present
     59        assert csc_pixel_format==-1
     60        #see xpra.codec_constants: YUV420P
     61        return 420
    5762
     63
    5864cdef class Decoder(xcoder):
    5965
    6066    def init_context(self, width, height, use_swscale, options):
     
    8591        strides = [outstrides[0], outstrides[1], outstrides[2]]
    8692        return  i, strides, out
    8793
    88     def get_pixel_format(self, csc_pixel_format):
    89         #we only support 420 at present
    90         assert csc_pixel_format==-1
    91         #see xpra.codec_constants: YUV420P
    92         return 420
    93 
    9494    def decompress_image_to_rgb(self, input, options):
    9595        cdef uint8_t *yuvplanes[3]
    9696        cdef uint8_t *dout
  • xpra/window_backing.py

     
    233233        Backing.close(self)
    234234        self._backing.finish()
    235235
     236    def paint_YUV(self, img_data, x, y, width, height, rowstride, options, callbacks):
     237        raise Exception("not implemented in %s" % type(self))
     238
    236239    def paint_png(self, img_data, x, y, width, height, rowstride, options, callbacks):
    237240        """ must be called from UI thread """
    238241        try:
     
    454457            if rowstride==0:
    455458                rowstride = width * 3
    456459            self.paint_rgb24(img_data, x, y, width, height, rowstride, options, callbacks)
     460        elif coding == "yuv":
     461            self.paint_YUV(img_data, x, y, width, height, rowstride, options, callbacks)
    457462        elif coding == "x264":
    458463            assert "x264" in ENCODINGS
    459464            self.paint_with_video_decoder(x264_Decoder, "x264", img_data, x, y, width, height, rowstride, options, callbacks)
  • xpra/window_source.py

     
    425425        self._video_encoder_speed = maxdeque(NRECS)
    426426        self._video_encoder_quality = maxdeque(NRECS)
    427427
     428    def set_encoder_options(self, props):
     429        self.encoding_options.update(props)
     430        log.info("set_encoder_options(%s) encoding_options=%s", props, self.encoding_options)
     431
    428432    def set_new_encoding(self, encoding):
    429433        """ Changes the encoder for the given 'window_ids',
    430434            or for all windows if 'window_ids' is None.
     
    703707            x, y, w, h = region
    704708            self.process_damage_region(damage_time, window, x, y, w, h, actual_encoding, options)
    705709
     710
    706711    def get_best_encoding(self, batching, window, pixel_count, ww, wh, current_encoding):
    707712        return self.do_get_best_encoding(batching, window.is_tray(), window.is_OR(), pixel_count, ww, wh, current_encoding)
    708713
     
    748753        return switch()
    749754
    750755    def find_common_lossless_encoder(self, fallback, pixel_count):
     756        if self._video_encoder is not None and self.encoding_options.get("prefer_yuv", False):
     757            return "yuv"
    751758        if pixel_count<512:
    752759            encs = "rgb24", "png"
    753760        else:
     
    944951
    945952        if coding in ("jpeg", "png"):
    946953            data, client_options = self.PIL_encode(w, h, coding, data, rowstride, options)
     954        elif coding=="yuv":
     955            assert self._video_encoder is not None, "cannot do yuv without a video encoder!"
     956            data, client_options = self.YUV_encode(w, h, data, rowstride, options)
    947957        elif coding=="x264":
    948958            #x264 needs sizes divisible by 2:
    949959            w = w & 0xFFFE
     
    10281038        buf.close()
    10291039        return Compressed(coding, data), client_options
    10301040
     1041    def YUV_encode(self, w, h, data, rowstride, options):
     1042        log.info("YUV_encode(%s, %s, %s bytes, %s, %s", w, h, len(data), rowstride, options)
     1043        assert self._video_encoder
     1044        try:
     1045            self._video_encoder_lock.acquire()
     1046            yuv_data, strides = self._video_encoder.rgb2yuv(data, w, h, rowstride)
     1047            assert yuv_data, "rgb2yuv failed!"
     1048            client_options = {"strides" : strides, "csc_pixel_format" : self._video_encoder.get_pixel_format()}
     1049            log.info("YUV_encode(%s, %s, %s bytes, %s, %s)=%s bytes, client_options=%s", w, h, len(data), rowstride, options, len(yuv_data), client_options)
     1050            zlib = zlib_compress("rgb24", yuv_data)
     1051            return zlib, client_options
     1052        finally:
     1053            self._video_encoder_lock.release()
     1054
    10311055    def make_video_encoder(self, coding):
    10321056        assert coding in ENCODINGS
    10331057        if coding=="x264":
  • xpra/x264/codec.pyx

     
    4949                              int I422_min, int I444_min,
    5050                              char *i420_profile, char *i422_profile, char *i444_profile)
    5151    void clean_encoder(x264lib_ctx *context)
     52    int csc_rgb2yuv(x264lib_ctx *ctx, const uint8_t *input, int width, int height, int stride, uint8_t **out, int *outsize, int *outstride) nogil
    5253    x264_picture_t* csc_image_rgb2yuv(x264lib_ctx *ctx, uint8_t *input, int stride)
    5354    int compress_image(x264lib_ctx *ctx, x264_picture_t *pic_in, uint8_t **out, int *outsz) nogil
    54     int get_encoder_pixel_format(x264lib_ctx *ctx)
     55    int get_pixel_format(x264lib_ctx *ctx)
    5556    int get_encoder_quality(x264lib_ctx *ctx)
    5657    int get_encoder_speed(x264lib_ctx *ctx)
    57     int get_pixel_format(int csc_format)
     58    int get_pixel_format_for_csc(int csc_format)
    5859
    5960    x264lib_ctx* init_decoder(int width, int height, int use_swscale, int csc_fmt)
    6061    void set_decoder_csc_format(x264lib_ctx *context, int csc_fmt)
     
    9091    def get_type(self):
    9192        return  "x264"
    9293
     94    def rgb2yuv(self, data, w, h, rowstride):
     95        cdef unsigned char * padded_buf = NULL  #@DuplicatedSignature
     96        cdef unsigned char * buf = NULL         #@DuplicatedSignature
     97        cdef Py_ssize_t buf_len = 0             #@DuplicatedSignature
     98        cdef int i = 0                          #@DuplicatedSignature
     99        cdef uint8_t *dout = NULL
     100        cdef int outstride[3]
     101        cdef int outsize = 0
     102        cdef int width = w
     103        cdef int height = h
     104        cdef int stride = rowstride
     105        PyObject_AsReadBuffer(data, <const_void_pp> &buf, &buf_len)
     106        padded_buf = <unsigned char *> xmemalign(buf_len+32)
     107        if padded_buf==NULL:
     108            return None, (0, 0, 0)
     109        memcpy(padded_buf, buf, buf_len)
     110        memset(padded_buf+buf_len, 0, 32)
     111        with nogil:
     112            i = csc_rgb2yuv(self.context, padded_buf, width, height, stride, &dout, &outsize, outstride)
     113        xmemfree(padded_buf)
     114        if i!=0 or dout==NULL:
     115            return None, (0, 0, 0)
     116        outstr = (<char *>dout)[:outsize]
     117        xmemfree(dout)
     118        return  outstr, (outstride[0], outstride[1], outstride[2])
    93119
     120    def get_pixel_format(self):
     121        return get_pixel_format(self.context)
     122
     123    def get_pixel_format_for_csc(self, csc_pixel_format):
     124        return get_pixel_format_for_csc(csc_pixel_format)
     125
     126
    94127cdef class Decoder(xcoder):
    95128
    96129    def init_context(self, width, height, use_swscale, options):
     
    126159            return i, [0, 0, 0], ["", "", ""]
    127160        out = []
    128161        strides = []
    129         pixel_format = self.get_pixel_format(csc_pixel_format)
     162        pixel_format = get_pixel_format_for_csc(csc_pixel_format)
    130163        divs = get_subsampling_divs(pixel_format)
    131164        for i in (0, 1, 2):
    132165            _, dy = divs[i]
     
    142175            strides.append(outstrides[i])
    143176        return  0, strides, out
    144177
    145     def get_pixel_format(self, csc_pixel_format):
    146         return get_pixel_format(csc_pixel_format)
    147 
    148178    def decompress_image_to_rgb(self, input, options):
    149179        cdef uint8_t *yuvplanes[3]
    150180        cdef uint8_t *dout
     
    236266            self.context = NULL
    237267
    238268    def get_client_options(self, options):
    239         csc_pf = get_encoder_pixel_format(self.context)
     269        csc_pf = self.get_pixel_format()
    240270        client_options = {
    241271                "csc_pixel_format" : csc_pf,
    242272                "frame" : self.frames
  • xpra/x264/x264lib.c

     
    9494         */
    9595};
    9696
    97 int get_encoder_pixel_format(struct x264lib_ctx *ctx) {
     97int get_pixel_format(struct x264lib_ctx *ctx) {
    9898        return ctx->csc_format;
    9999}
    100100int get_encoder_quality(struct x264lib_ctx *ctx) {
     
    167167
    168168//Given a csc colour sampling constant,
    169169//return our own generic csc constant (see codec_constants.py)
    170 int get_pixel_format(int csc)
     170int get_pixel_format_for_csc(int csc)
    171171{
    172172        if (csc == PIX_FMT_YUV420P || csc < 0)
    173173                return 420;
     
    446446        free(ctx);
    447447}
    448448
     449int csc_rgb2yuv(struct x264lib_ctx *ctx, const uint8_t *rgb, int width, int height, int stride, uint8_t **out, int* outsize, int outstride[3])
     450{
     451        uint8_t *dst[3];
     452        int uxdiv=1, uydiv=1, vxdiv=1, vydiv=1;
     453        int ysize=0, usize=0, vsize=0;
     454        int h = 0;
     455        if (ctx->csc_format==PIX_FMT_YUV420P) {
     456                uxdiv = 2; uydiv = 2;
     457                vxdiv = 2; vydiv = 2;
     458        }
     459        else if (ctx->csc_format==PIX_FMT_YUV422P) {
     460                uxdiv = 2; vxdiv = 2;
     461        }
     462        else if (ctx->csc_format!=PIX_FMT_YUV444P) {
     463                fprintf(stderr, "csc_rgb2yuv invalid csc format: %i", ctx->csc_format);
     464                return 1;
     465        }
     466        fprintf(stderr, "csc_rgb2yuv csc_format=%i width=%i, height=%i, divs: Y(1, 1) U(%i, %i) V(%i, %i)\n", ctx->csc_format, width, height, uxdiv, uydiv, vxdiv, vydiv);
     467        //(Y plane is always in full)
     468        //round stride to next 8
     469        outstride[0] = (width+0x7) & ~0x7;
     470        outstride[1] = ((width/uxdiv+0x7) & ~0x7);
     471        outstride[2] = ((width/vxdiv+0x7) & ~0x7);
     472        ysize = outstride[0] * height;
     473        usize = outstride[1] * (height/uydiv) & ~0x1;
     474        vsize = outstride[2] * (height/vydiv) & ~0x1;
     475        *outsize = ysize + usize + vsize + 1024;
     476        if (*outsize==0) {
     477                fprintf(stderr, "csc_rgb2yuv invalid size: %i", *outsize);
     478                return 2;
     479        }
     480        *out = xmemalign(*outsize);
     481        if (*out==NULL) {
     482                fprintf(stderr, "csc_rgb2yuv failed to allocate %s bytes of memory", *outsize);
     483                return 3;
     484        }
     485        memset(*out, 0, *outsize);
     486        dst[0] = *out;
     487        dst[1] = *out+ysize;
     488        dst[2] = *out+ysize+usize;
     489        fprintf(stderr, "csc_rgb2yuv outstrides: %i, %i, %i\n", outstride[0], outstride[1], outstride[2]);
     490        fprintf(stderr, "csc_rgb2yuv sizes: %i, %i, %i\n", ysize, usize, vsize);
     491        h = sws_scale(ctx->rgb2yuv, &rgb, &stride, 0, height & ~0x1, dst, outstride);
     492        fprintf(stderr, "csc_rgb2yuv %ix%i, rounded height=%i, output height=%i\n", width, height, height & ~0x1, h);
     493        return 0;
     494}
    449495
    450 x264_picture_t *csc_image_rgb2yuv(struct x264lib_ctx *ctx, const uint8_t *in, int stride)
     496x264_picture_t *csc_image_rgb2yuv(struct x264lib_ctx *ctx, const uint8_t *rgb, int stride)
    451497{
     498        int h = 0;
    452499        x264_picture_t *pic_in = NULL;
    453500        if (!ctx->encoder || !ctx->rgb2yuv)
    454501                return NULL;
     
    459506        x264_picture_alloc(pic_in, ctx->colour_sampling, ctx->width, ctx->height);
    460507
    461508        /* Colorspace conversion (RGB -> I4??) */
    462         sws_scale(ctx->rgb2yuv, &in, &stride, 0, ctx->height, pic_in->img.plane, pic_in->img.i_stride);
     509        fprintf(stderr, "csc_image_rgb2yuv planes: @%p: 0, %i, %i, strides: %i, %i, %i\n",
     510                        pic_in->img.plane[0], (int) (pic_in->img.plane[1]-pic_in->img.plane[0]), (int) (pic_in->img.plane[2]-pic_in->img.plane[0]),
     511                        pic_in->img.i_stride[0], pic_in->img.i_stride[1], pic_in->img.i_stride[2]);
     512        h = sws_scale(ctx->rgb2yuv, &rgb, &stride, 0, ctx->height, pic_in->img.plane, pic_in->img.i_stride);
     513        fprintf(stderr, "csc_image_rgb2yuv %ix%i, returned height=%i\n", ctx->width, ctx->height, h);
    463514        return pic_in;
    464515}
    465516
     
    500551        return 0;
    501552}
    502553
    503 
    504554int csc_image_yuv2rgb(struct x264lib_ctx *ctx, uint8_t *in[3], const int stride[3], uint8_t **out, int *outsz, int *outstride)
    505555{
    506556        AVPicture pic;
     
    616666                                ctx->quality = pct;
    617667                                ctx->x264_quality = new_quality;
    618668                                do_init_encoder(ctx);
    619                                 //printf("new pixel format: %i / %i\n", get_encoder_pixel_format(ctx), get_pixel_format(get_encoder_pixel_format(ctx)));
    620669                                return;
    621670                        }
    622671                }
  • xpra/x264/x264lib.h

     
    1818/** Opaque structure - "context". You must have a context to encode images of a given size */
    1919struct x264lib_ctx;
    2020
    21 /** Expose the encoder pixel format so the decoder can use the same setting */
    22 int get_encoder_pixel_format(struct x264lib_ctx *ctx);
     21/** Expose the pixel format (ie: so the decoder can use the same setting) */
     22int get_pixel_format(struct x264lib_ctx *ctx);
    2323
    2424/** Expose current quality setting */
    2525int get_encoder_quality(struct x264lib_ctx *ctx);
     
    2828int get_encoder_speed(struct x264lib_ctx *ctx);
    2929
    3030/** Returns the pixel format using our own generic codec_constants */
    31 int get_pixel_format(int csc);
     31int get_pixel_format_for_csc(int csc);
    3232
    3333/** Create an encoding context for images of a given size.  */
    3434struct x264lib_ctx *init_encoder(int width, int height,
     
    5656/** Cleanup decoding context. Also frees the memory. */
    5757void clean_decoder(struct x264lib_ctx *);
    5858
     59int csc_rgb2yuv(struct x264lib_ctx *ctx, const uint8_t *in, int width, int height, int stride, uint8_t **out, int* outsize, int *outstride);
     60
    5961/** Colorspace conversion.
    6062 * Note: you must call compress_image to free the image buffer.
    6163 @param in: Input buffer, format is packed RGB24.