Skip to content

Commit

Permalink
vpx: OpenGL output (including CSC) is now available for vpx
Browse files Browse the repository at this point in the history
git-svn-id: https://xpra.org/svn/Xpra/trunk@931 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
Arthur Huillet committed Jun 18, 2012
1 parent 444d4f9 commit b606094
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 26 deletions.
34 changes: 29 additions & 5 deletions src/xpra/vpx/codec.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ ctypedef void vpx_image_t
cdef extern from "vpxlib.h":
vpx_codec_ctx_t* init_encoder(int width, int height)
void clean_encoder(vpx_codec_ctx_t *context)
vpx_image_t* csc_image(vpx_codec_ctx_t *ctx, uint8_t *input, int stride)
vpx_image_t* csc_image_rgb2yuv(vpx_codec_ctx_t *ctx, uint8_t *input, int stride)
int csc_image_yuv2rgb(vpx_codec_ctx_t *ctx, uint8_t *input[3], int stride[3], uint8_t **out, int *outsz, int *outstride)
int compress_image(vpx_codec_ctx_t *ctx, vpx_image_t *image, uint8_t **out, int *outsz) nogil

vpx_codec_ctx_t* init_decoder(int width, int height)
void clean_decoder(vpx_codec_ctx_t *context)
int decompress_image(vpx_codec_ctx_t *context, uint8_t *input, int size, uint8_t **out, int *outsize, int *outstride)
int decompress_image(vpx_codec_ctx_t *context, uint8_t *input, int size, uint8_t *(*out)[3], int *outsize, int (*outstride)[3])


ENCODERS = {}
Expand Down Expand Up @@ -64,19 +65,42 @@ cdef class Decoder(xcoder):
clean_decoder(self.context)
self.context = NULL

def decompress_image_to_yuv(self, input):
cdef uint8_t *dout[3]
cdef int outsize
cdef int outstrides[3]
cdef unsigned char * buf = <uint8_t *> 0
cdef Py_ssize_t buf_len = 0
assert self.context!=NULL
PyObject_AsReadBuffer(input, <void **>&buf, &buf_len)
i = decompress_image(self.context, buf, buf_len, &dout, &outsize, &outstrides)
if i!=0:
return i, [0, 0, 0], ["", "", ""]
doutvY = (<char *>dout[0])[:self.height * outstrides[0]]
doutvU = (<char *>dout[1])[:self.height * outstrides[1]]
doutvV = (<char *>dout[2])[:self.height * outstrides[2]]
out = [doutvY, doutvU, doutvV]
strides = [outstrides[0], outstrides[1], outstrides[2]]
return i, strides, out

def decompress_image_to_rgb(self, input):
cdef uint8_t *yuvplanes[3]
cdef uint8_t *dout
cdef int outsize
cdef int yuvstrides[3]
cdef int outstride
cdef unsigned char * buf = <uint8_t *> 0
cdef Py_ssize_t buf_len = 0
assert self.context!=NULL
assert self.last_image==NULL
PyObject_AsReadBuffer(input, <void **>&buf, &buf_len)
i = decompress_image(self.context, buf, buf_len, &dout, &outsize, &outstride)
self.last_image = dout
i = decompress_image(self.context, buf, buf_len, &yuvplanes, &outsize, &yuvstrides)
if i!=0:
return i, 0, ""
i = csc_image_yuv2rgb(self.context, yuvplanes, yuvstrides, &dout, &outsize, &outstride)
if i!=0:
return i, 0, ""
self.last_image = dout
doutv = (<char *>dout)[:outsize]
return i, outstride, doutv

Expand Down Expand Up @@ -105,7 +129,7 @@ cdef class Encoder(xcoder):
assert self.context!=NULL
#colourspace conversion with gil held:
PyObject_AsReadBuffer(input, <void **>&buf, &buf_len)
pic_in = csc_image(self.context, buf, rowstride)
pic_in = csc_image_rgb2yuv(self.context, buf, rowstride)
assert pic_in!=NULL, "colourspace conversion failed"
#actual compression (no gil):
with nogil:
Expand Down
44 changes: 28 additions & 16 deletions src/xpra/vpx/vpxlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ void clean_decoder(struct vpx_context *ctx)
free(ctx);
}

vpx_image_t* csc_image(struct vpx_context *ctx, const uint8_t *in, int stride)
vpx_image_t* csc_image_rgb2yuv(struct vpx_context *ctx, const uint8_t *in, int stride)
{
vpx_image_t *image = malloc(sizeof(vpx_image_t));
if (!vpx_img_alloc(image, VPX_IMG_FMT_I420, ctx->width, ctx->height, 1)) {
Expand Down Expand Up @@ -144,15 +144,33 @@ int compress_image(struct vpx_context *ctx, vpx_image_t *image, uint8_t **out, i
return 0;
}

int decompress_image(struct vpx_context *ctx, uint8_t *in, int size, uint8_t **out, int *outsize, int *outstride)
int csc_image_yuv2rgb(struct vpx_context *ctx, uint8_t *in[3], const int stride[3], uint8_t **out, int *outsz, int *outstride)
{
int aligned_width;
uint8_t *dst[4] = { malloc(ctx->height * ctx->width * 3), NULL, NULL, NULL };
int dststride[4] = { ctx->width * 3, 0, 0, 0 };

if (!ctx->yuv2rgb)
return 1;

sws_scale(ctx->yuv2rgb, in, stride, 0, ctx->height, dst, dststride);

/* Output (must be freed!) */
*out = dst[0];
*outsz = dststride[0] * ctx->height;
*outstride = dststride[0];

return 0;
}

int decompress_image(struct vpx_context *ctx, uint8_t *in, int size, uint8_t *(*out)[3], int *outsize, int (*outstride)[3])
{
vpx_image_t *img;
int frame_sz = size;
vpx_codec_iter_t iter = NULL;
uint8_t* frame = in;
int outstrides[4];
uint8_t* outs[4];
int stride = 0;
int i = 0;

if (vpx_codec_decode(&ctx->codec, frame, frame_sz, NULL, 0)) {
Expand All @@ -164,19 +182,13 @@ int decompress_image(struct vpx_context *ctx, uint8_t *in, int size, uint8_t **o
codec_error(&ctx->codec, "vpx_codec_get_frame");
return -1;
}
for (i=0; i<4; i++)
stride += img->stride[i];
*outsize = stride * img->h;

*out = malloc(*outsize);
for (i=0; i<4; i++) {
outstrides[i] = img->w*3;
outs[i] = *out;

*outsize = 0;
for (i = 0; i < 3; i++) {
(*out)[i] = img->planes[i];
(*outstride)[i] = img->stride[i];
*outsize += img->stride[i] * img->h;
}
sws_scale(ctx->yuv2rgb, img->planes, img->stride, 0, img->h, outs, outstrides);
stride = 0;
for (i=0; i<4; i++)
stride += img->stride[i];
*outstride = stride;

return 0;
}
19 changes: 15 additions & 4 deletions src/xpra/vpx/vpxlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,17 @@ void clean_decoder(struct vpx_context *ctx);
@param stride: Input stride (size is taken from context).
@return: the converted picture.
*/
vpx_image_t* csc_image(struct vpx_context *ctx, const uint8_t *in, int stride);
vpx_image_t* csc_image_rgb2yuv(struct vpx_context *ctx, const uint8_t *in, int stride);

/** Colorspace conversion.
@param in: Input picture (3 planes).
@param stride: Input strides (3 planes).
@param out: Will be set to point to the output data in packed RGB24 format. Must be freed after use by calling free().
@param outsz: Will be set to the size of the output buffer.
@param outstride: Output stride.
@return non zero on error.
*/
int csc_image_yuv2rgb(struct vpx_context *ctx, uint8_t *in[3], const int stride[3], uint8_t **out, int *outsz, int *outstride);

/** Compress an image using the given context.
@param pic_in: the input image, as returned by csc_image
Expand All @@ -40,7 +50,8 @@ int compress_image(struct vpx_context *ctx, vpx_image_t *image, uint8_t **out, i
/** Decompress an image using the given context.
@param in: Input buffer, format is H264.
@param size: Input size.
@param out: Will be set to point to the output data in RGB24 format.
@param outstride: Output stride.
@param out: Will be filled to point to the output data in planar YUV420 format (3 planes). This data will be freed automatically upon next call to the decoder.
@param outsize: Output size.
@param outstride: Output strides (3 planes).
*/
int decompress_image(struct vpx_context *ctx, uint8_t *in, int size, uint8_t **out, int *outsize, int *outstride);
int decompress_image(struct vpx_context *ctx, uint8_t *in, int size, uint8_t *(*out)[3], int *outsize, int (*outstride)[3]);
1 change: 0 additions & 1 deletion src/xpra/x264/x264lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ void clean_decoder(struct x264lib_ctx *);
x264_picture_t *csc_image_rgb2yuv(struct x264lib_ctx *ctx, const uint8_t *in, int stride);

/** Colorspace conversion.
* Note: you must call compress_image to free the image buffer.
@param in: Input picture (3 planes).
@param stride: Input strides (3 planes).
@param out: Will be set to point to the output data in packed RGB24 format. Must be freed after use by calling free().
Expand Down

0 comments on commit b606094

Please sign in to comment.