xpra icon
Bug tracker and wiki

Changeset 877 in xpra


Ignore:
Timestamp:
05/27/12 20:55:32 (12 months ago)
Author:
antoine
Message:

#110: split the colourspace conversion and actual x264/vpx compression phases so we can call the former with the gil held (needed because it uses python object as buffer) and the latter without the lock held (only uses pure C objects)

Location:
trunk/src/xpra
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/xpra/vpx/codec.pyx

    r720 r877  
    99    ctypedef int Py_ssize_t 
    1010    ctypedef object PyObject 
    11     int PyObject_AsReadBuffer(object obj, 
    12                               void ** buffer, 
    13                               Py_ssize_t * buffer_len) except -1 
     11    int PyObject_AsReadBuffer(object obj, void ** buffer, Py_ssize_t * buffer_len) except -1 
    1412 
    1513ctypedef unsigned char uint8_t 
    1614ctypedef void vpx_codec_ctx_t 
     15ctypedef void vpx_image_t 
    1716cdef extern from "vpxlib.h": 
    1817    vpx_codec_ctx_t* init_encoder(int width, int height) 
    1918    void clean_encoder(vpx_codec_ctx_t *context) 
    20     int compress_image(vpx_codec_ctx_t *ctx, uint8_t *input, int w, int h, int stride, uint8_t **out, int *outsz) 
     19    vpx_image_t* csc_image(vpx_codec_ctx_t *ctx, uint8_t *input, int stride) 
     20    int compress_image(vpx_codec_ctx_t *ctx, vpx_image_t *image, uint8_t **out, int *outsz) nogil 
     21 
    2122    vpx_codec_ctx_t* init_decoder(int width, int height) 
    2223    void clean_decoder(vpx_codec_ctx_t *context) 
     
    9798 
    9899    def compress_image(self, input, rowstride): 
     100        cdef vpx_image_t *pic_in = NULL 
    99101        cdef uint8_t *cout 
    100102        cdef int coutsz 
     
    102104        cdef Py_ssize_t buf_len = 0 
    103105        assert self.context!=NULL 
     106        #colourspace conversion with gil held: 
    104107        PyObject_AsReadBuffer(input, <void **>&buf, &buf_len) 
    105         i = compress_image(self.context, buf, self.width, self.height, rowstride, &cout, &coutsz) 
     108        pic_in = csc_image(self.context, buf, rowstride) 
     109        assert pic_in!=NULL, "colourspace conversion failed" 
     110        #actual compression (no gil): 
     111        with nogil: 
     112            i = compress_image(self.context, pic_in, &cout, &coutsz) 
    106113        if i!=0: 
    107114            return i, 0, "" 
    108115        coutv = (<char *>cout)[:coutsz] 
    109116        return  i, coutsz, coutv 
    110      
     117 
    111118    def increase_encoding_speed(self): 
    112119        return 
    113      
     120 
    114121    def decrease_encoding_speed(self): 
    115122        return 
  • trunk/src/xpra/vpx/vpxlib.c

    r823 r877  
    2525#include "vpx/vp8dx.h" 
    2626#include "vpxlib.h" 
     27#include "vpx/vpx_image.h" 
    2728#define enc_interface (vpx_codec_vp8_cx()) 
    2829#define dec_interface (vpx_codec_vp8_dx()) 
     
    3536        struct SwsContext *rgb2yuv; 
    3637        struct SwsContext *yuv2rgb; 
     38        int width; 
     39        int height; 
    3740} vpx_context; 
    3841 
     
    6164                return NULL; 
    6265        } 
     66        ctx->width = width; 
     67        ctx->height = height; 
    6368        ctx->rgb2yuv = sws_getContext(width, height, PIX_FMT_RGB24, width, height, PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL); 
    6469        return ctx; 
     
    8388                return NULL; 
    8489        } 
     90        ctx->width = width; 
     91        ctx->height = height; 
    8592        ctx->yuv2rgb = sws_getContext(width, height, PIX_FMT_YUV420P, width, height, PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL); 
    8693        return  ctx; 
     
    93100} 
    94101 
    95 int compress_image(struct vpx_context *ctx, uint8_t *in, int w, int h, int stride, uint8_t **out, int *outsz) 
     102vpx_image_t* csc_image(struct vpx_context *ctx, const uint8_t *in, int stride) 
    96103{ 
    97         vpx_image_t image; 
     104        vpx_image_t *image = malloc(sizeof(vpx_image_t)); 
     105        if (!vpx_img_alloc(image, VPX_IMG_FMT_I420, ctx->width, ctx->height, 1)) { 
     106                printf("Failed to allocate image %dx%d", ctx->width, ctx->height); 
     107                return NULL; 
     108        } 
     109        /* Colorspace conversion (RGB -> I420) */ 
     110        sws_scale(ctx->rgb2yuv, &in, &stride, 0, ctx->height, image->planes, image->stride); 
     111        image->w = ctx->width; 
     112        image->h = ctx->height; 
     113        image->d_w = ctx->width; 
     114        image->d_h = ctx->height; 
     115        return image; 
     116} 
     117 
     118int compress_image(struct vpx_context *ctx, vpx_image_t *image, uint8_t **out, int *outsz) 
     119{ 
    98120        const vpx_codec_cx_pkt_t *pkt; 
    99121        vpx_codec_iter_t iter = NULL; 
     
    101123        int flags = 0; 
    102124        int i = 0; 
    103         if (!vpx_img_alloc(&image, VPX_IMG_FMT_I420, w, h, 1)) { 
    104                 printf("Failed to allocate image %dx%d", w, h); 
    105                 return -1; 
    106         } 
    107         image.w = w; 
    108         image.h = h; 
    109         image.d_w = w; 
    110         image.d_h = h; 
    111         image.x_chroma_shift = 0; 
    112         image.y_chroma_shift = 0; 
    113         image.bps = 8; 
    114125 
    115         /* Colorspace conversion (RGB -> I420) */ 
    116         sws_scale(ctx->rgb2yuv, &in, &stride, 0, h, image.planes, image.stride); 
    117126        /* Encoding */ 
    118         i = vpx_codec_encode(&ctx->codec, &image, frame_cnt, 1, flags, VPX_DL_REALTIME); 
     127        image->x_chroma_shift = 0; 
     128        image->y_chroma_shift = 0; 
     129        image->bps = 8; 
     130        i = vpx_codec_encode(&ctx->codec, image, frame_cnt, 1, flags, VPX_DL_REALTIME); 
    119131        if (i) { 
    120132                codec_error(&ctx->codec, "vpx_codec_encode"); 
    121                 vpx_img_free(&image); 
     133                vpx_img_free(image); 
    122134                return i; 
    123135        } 
    124136        pkt = vpx_codec_get_cx_data(&ctx->codec, &iter); 
    125137        if (pkt->kind!=VPX_CODEC_CX_FRAME_PKT) { 
    126                 vpx_img_free(&image); 
     138                vpx_img_free(image); 
    127139                return 1; 
    128140        } 
    129141        *out = pkt->data.frame.buf; 
    130142        *outsz = pkt->data.frame.sz; 
    131         vpx_img_free(&image); 
     143        vpx_img_free(image); 
    132144        return 0; 
    133145} 
  • trunk/src/xpra/vpx/vpxlib.h

    r735 r877  
    55#include "stdint.h" 
    66#endif 
     7#include "vpx/vpx_image.h" 
    78 
    89/** Opaque structure - "context". You must have a context to encode images of a given size */ 
     
    2122void clean_decoder(struct vpx_context *ctx); 
    2223 
    23 /** Compress an image using the given context.  
     24/** Colourspace conversion. 
     25 * Note: you must call compress_image to free the image buffer. 
    2426 @param in: Input buffer, format is packed RGB24. 
    2527 @param stride: Input stride (size is taken from context). 
    26  @param out: Will be set to point to the output data. This output buffer MUST NOT BE FREED and will be erased on the  
     28 @return: the converted picture. 
     29*/ 
     30vpx_image_t* csc_image(struct vpx_context *ctx, const uint8_t *in, int stride); 
     31 
     32/** Compress an image using the given context. 
     33 @param pic_in: the input image, as returned by csc_image 
     34 @param out: Will be set to point to the output data. This output buffer MUST NOT BE FREED and will be erased on the 
    2735 next call to compress_image. 
    2836 @param outsz: Output size 
    2937*/ 
    30 int compress_image(struct vpx_context *ctx, uint8_t *in, int w, int h, int stride, uint8_t **out, int *outsz); 
     38int compress_image(struct vpx_context *ctx, vpx_image_t *image, uint8_t **out, int *outsz); 
    3139 
    32 /** Decompress an image using the given context.  
     40/** Decompress an image using the given context. 
    3341 @param in: Input buffer, format is H264. 
    3442 @param size: Input size. 
  • trunk/src/xpra/x264/codec.pyx

    r718 r877  
    1111    ctypedef int Py_ssize_t 
    1212    ctypedef object PyObject 
    13     int PyObject_AsReadBuffer(object obj, 
    14                               void ** buffer, 
    15                               Py_ssize_t * buffer_len) except -1 
     13    int PyObject_AsReadBuffer(object obj, void ** buffer, Py_ssize_t * buffer_len) except -1 
    1614 
    1715ctypedef unsigned char uint8_t 
    1816ctypedef void x264lib_ctx 
     17ctypedef void x264_picture_t 
    1918cdef extern from "x264lib.h": 
    2019    x264lib_ctx* init_encoder(int width, int height) 
    2120    void clean_encoder(x264lib_ctx *context) 
    22     int compress_image(x264lib_ctx *context, uint8_t *input, int stride, uint8_t **out, int *outsz) 
     21    x264_picture_t* csc_image(x264lib_ctx *ctx, uint8_t *input, int stride) 
     22    int compress_image(x264lib_ctx *ctx, x264_picture_t *pic_in, uint8_t **out, int *outsz) nogil 
     23 
    2324    x264lib_ctx* init_decoder(int width, int height) 
    2425    void clean_decoder(x264lib_ctx *context) 
     
    6162    def init_context(self, width, height): 
    6263        self.context = init_decoder(width, height) 
    63      
     64 
    6465    def clean(self): 
    6566        if self.context!=NULL: 
     
    9394    def init_context(self, width, height): 
    9495        self.context = init_encoder(width, height) 
    95      
     96 
    9697    def clean(self): 
    9798        if self.context!=NULL: 
     
    100101 
    101102    def compress_image(self, input, rowstride): 
     103        cdef x264_picture_t *pic_in = NULL 
    102104        cdef uint8_t *cout 
    103105        cdef int coutsz 
     
    105107        cdef Py_ssize_t buf_len = 0 
    106108        assert self.context!=NULL 
     109        #colourspace conversion with gil held: 
    107110        PyObject_AsReadBuffer(input, <void **>&buf, &buf_len) 
    108         i = compress_image(self.context, buf, rowstride, &cout, &coutsz) 
     111        pic_in = csc_image(self.context, buf, rowstride) 
     112        assert pic_in!=NULL, "colourspace conversion failed" 
     113        #actual compression (no gil): 
     114        with nogil: 
     115            i = compress_image(self.context, pic_in, &cout, &coutsz) 
    109116        if i!=0: 
    110117            return i, 0, "" 
     
    114121    def increase_encoding_speed(self): 
    115122        change_encoding_speed(self.context, 1) 
    116      
     123 
    117124    def decrease_encoding_speed(self): 
    118125        change_encoding_speed(self.context, -1) 
  • trunk/src/xpra/x264/x264lib.c

    r721 r877  
    112112 
    113113#ifndef _WIN32 
    114 int compress_image(struct x264lib_ctx *ctx, const uint8_t *in, int stride, uint8_t **out, int *outsz) 
     114x264_picture_t* csc_image(struct x264lib_ctx *ctx, const uint8_t *in, int stride) 
    115115{ 
    116116        if (!ctx->encoder || !ctx->rgb2yuv) 
     117                return NULL; 
     118 
     119        x264_picture_t *pic_in = malloc(sizeof(x264_picture_t)); 
     120        x264_picture_alloc(pic_in, X264_CSP_I420, ctx->width, ctx->height); 
     121 
     122        /* Colorspace conversion (RGB -> I420) */ 
     123        sws_scale(ctx->rgb2yuv, &in, &stride, 0, ctx->height, pic_in->img.plane, pic_in->img.i_stride); 
     124        return pic_in; 
     125} 
     126 
     127void free_csc_image(x264_picture_t *image) 
     128{ 
     129        x264_picture_clean(image); 
     130        free(image); 
     131} 
     132 
     133int compress_image(struct x264lib_ctx *ctx, x264_picture_t *pic_in, uint8_t **out, int *outsz) 
     134{ 
     135        if (!ctx->encoder || !ctx->rgb2yuv) { 
     136                free_csc_image(pic_in); 
    117137                return 1; 
    118  
    119         x264_picture_t pic_in, pic_out; 
    120         x264_picture_alloc(&pic_in, X264_CSP_I420, ctx->width, ctx->height); 
    121  
    122         /* Colorspace conversion (RGB -> I420) */ 
    123         sws_scale(ctx->rgb2yuv, &in, &stride, 0, ctx->height, pic_in.img.plane, pic_in.img.i_stride); 
     138        } 
     139        x264_picture_t pic_out; 
    124140 
    125141        /* Encoding */ 
    126         pic_in.i_pts = 1; 
     142        pic_in->i_pts = 1; 
    127143 
    128144        x264_nal_t* nals; 
    129145        int i_nals; 
    130         int frame_size = x264_encoder_encode(ctx->encoder, &nals, &i_nals, &pic_in, &pic_out); 
    131         if (frame_size >= 0) { 
    132                 /* Do not free that! */ 
    133                 *out = nals[0].p_payload; 
    134                 *outsz = frame_size; 
    135         } else { 
    136                 fprintf(stderr, "Problem\n"); 
    137                 x264_picture_clean(&pic_in); 
     146        int frame_size = x264_encoder_encode(ctx->encoder, &nals, &i_nals, pic_in, &pic_out); 
     147        if (frame_size < 0) { 
     148                fprintf(stderr, "Problem during x264_encoder_encode: frame_size is invalid!\n"); 
     149                free_csc_image(pic_in); 
     150                *out = NULL; 
     151                *outsz = 0; 
    138152                return 2; 
    139153        } 
    140    
    141         x264_picture_clean(&pic_in); 
     154        /* Do not clean that! */ 
     155        *out = nals[0].p_payload; 
     156        *outsz = frame_size; 
     157        free_csc_image(pic_in); 
    142158        return 0; 
    143159} 
    144160#else 
    145 int compress_image(struct x264lib_ctx *ctx, const uint8_t *in, int stride, uint8_t **out, int *outsz) 
     161x264_picture_t* csc_image(struct x264lib_ctx *ctx, const uint8_t *in, int stride) { 
     162        return  NULL; 
     163} 
     164int compress_image(struct x264lib_ctx *ctx, x264_picture_t *pic_in, uint8_t **out, int *outsz) 
    146165{ 
    147166        return 1; 
  • trunk/src/xpra/x264/x264lib.h

    r777 r877  
    44#else 
    55#include "stdint.h" 
     6#endif 
     7 
     8#ifndef _WIN32 
     9#include <x264.h> 
     10#else 
     11typedef void x264_t; 
     12#define inline __inline 
    613#endif 
    714 
     
    2128void clean_decoder(struct x264lib_ctx *); 
    2229 
    23 /** Compress an image using the given context.  
     30/** Colourspace conversion. 
     31 * Note: you must call compress_image to free the image buffer. 
    2432 @param in: Input buffer, format is packed RGB24. 
    2533 @param stride: Input stride (size is taken from context). 
    26  @param out: Will be set to point to the output data. This output buffer MUST NOT BE FREED and will be erased on the  
     34 @return: the converted picture. 
     35*/ 
     36x264_picture_t* csc_image(struct x264lib_ctx *ctx, const uint8_t *in, int stride); 
     37 
     38/** Compress an image using the given context. 
     39 @param pic_in: the input image, as returned by csc_image 
     40 @param out: Will be set to point to the output data. This output buffer MUST NOT BE FREED and will be erased on the 
    2741 next call to compress_image. 
    2842 @param outsz: Output size 
    2943*/ 
    30 int compress_image(struct x264lib_ctx *, const uint8_t *in, int stride, uint8_t **out, int *outsz); 
     44int compress_image(struct x264lib_ctx *ctx, x264_picture_t *pic_in, uint8_t **out, int *outsz); 
    3145 
    32 /** Decompress an image using the given context.  
     46/** Decompress an image using the given context. 
    3347 @param in: Input buffer, format is H264. 
    3448 @param size: Input size. 
Note: See TracChangeset for help on using the changeset viewer.