xpra icon
Bug tracker and wiki

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


Ticket #94: xpra-x264.patch

File xpra-x264.patch, 10.8 KB (added by Antoine Martin, 10 years ago)

adds an x264 encoder/decoder library, cython glue and makes distutils build it

  • setup.py

     
    6464                ["xpra/wait_for_x_server.pyx"],
    6565                **pkgconfig("x11")
    6666                ),
     67      Extension("xpra.x264.codec",
     68                ["xpra/x264/codec.pyx", "xpra/x264/x264lib.c"],
     69                **pkgconfig("x264", "libswscale", "libavcodec")
     70                ),
    6771      ]
    6872
    6973    cmdclass = {'build_ext': build_ext}
     
    161165              "parti", "parti.trays", "parti.addons", "parti.scripts",
    162166              "xpra", "xpra.scripts", "xpra.platform",
    163167              "xpra.xposix", "xpra.win32", "xpra.darwin",
     168              "xpra.x264"
    164169              ]
    165170    scripts=["scripts/parti", "scripts/parti-repl",
    166171             "scripts/xpra",
  • xpra/x264/x264lib.c

    Property changes on: xpra/x264
    ___________________________________________________________________
    Added: svn:ignore
       + codec.c
    
    
     
     1/* This file is part of Parti.
     2 * Copyright (C) 2012 Serviware (Arthur Huillet, <ahuillet@serviware.com>)
     3 * Copyright (C) 2012 Antoine Martin <antoine@devloop.org.uk>
     4 * Parti is released under the terms of the GNU GPL v2, or, at your option, any
     5 * later version. See the file COPYING for details.
     6 */
     7
     8#include <stdint.h>
     9#include <stdio.h>
     10#include <stdlib.h>
     11#include <string.h>
     12#include <unistd.h>
     13#include <sys/types.h>
     14#include <sys/stat.h>
     15#include <fcntl.h>
     16#include <x264.h>
     17#include <libswscale/swscale.h>
     18#include <libavcodec/avcodec.h>
     19
     20static struct x264lib_ctx {
     21        // Encoding
     22        x264_t *encoder;
     23        struct SwsContext *rgb2yuv;
     24
     25        // Decoding
     26        AVCodec *codec;
     27    AVCodecContext *codec_ctx;
     28        struct SwsContext *yuv2rgb;
     29
     30        // Both
     31        int width;
     32        int height;
     33
     34} ctx;
     35
     36int init_encoder(int width, int height)
     37{
     38        x264_param_t param;
     39        x264_param_default_preset(&param, "veryfast", "zerolatency");
     40        param.i_threads = 1;
     41        param.i_width = width;
     42        param.i_height = height;
     43        param.i_csp = X264_CSP_I420;
     44        x264_param_apply_profile(&param, "baseline");
     45        ctx.encoder = x264_encoder_open(&param);
     46        ctx.width = width;
     47        ctx.height = height;
     48        ctx.rgb2yuv = sws_getContext(ctx.width, ctx.height, PIX_FMT_RGB24, ctx.width, ctx.height, PIX_FMT_YUV420P, SWS_FAST_BILINEAR, NULL, NULL, NULL);
     49
     50        return 0;
     51}
     52
     53int clean_encoder(void)
     54{
     55        sws_freeContext(ctx.rgb2yuv);
     56}
     57
     58int init_decoder(int width, int height)
     59{
     60        ctx.width = width;
     61        ctx.height = height;
     62        ctx.yuv2rgb = sws_getContext(ctx.width, ctx.height, PIX_FMT_YUV420P, ctx.width, ctx.height, PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL);
     63
     64    avcodec_register_all();
     65
     66    ctx.codec = avcodec_find_decoder(CODEC_ID_H264);
     67    if (!ctx.codec) {
     68        fprintf(stderr, "codec not found\n");
     69        return 1;
     70    }
     71        ctx.codec_ctx = avcodec_alloc_context3(ctx.codec);
     72        ctx.codec_ctx->width = ctx.width;
     73        ctx.codec_ctx->height = ctx.height;
     74        ctx.codec_ctx->pix_fmt = PIX_FMT_YUV420P;
     75        if (avcodec_open(ctx.codec_ctx, ctx.codec) < 0) {
     76        fprintf(stderr, "could not open codec\n");
     77        return 2;
     78    }
     79        return 0;
     80}
     81
     82int clean_decoder(void)
     83{
     84    avcodec_close(ctx.codec_ctx);
     85    av_free(ctx.codec_ctx);
     86        sws_freeContext(ctx.yuv2rgb);
     87}
     88
     89int compress_image(const uint8_t *in, int stride, uint8_t **out, int *outsz)
     90{
     91        if (!ctx.encoder || !ctx.rgb2yuv)
     92                return 1;
     93
     94        x264_picture_t pic_in, pic_out;
     95        x264_picture_alloc(&pic_in, X264_CSP_I420, ctx.width, ctx.height);
     96
     97        /* Colorspace conversion (RGB -> I420) */
     98        sws_scale(ctx.rgb2yuv, &in, &stride, 0, ctx.height, pic_in.img.plane, pic_in.img.i_stride);
     99
     100        /* Encoding */
     101        pic_in.i_pts = 1;
     102
     103        x264_nal_t* nals;
     104        int i_nals;
     105        int frame_size = x264_encoder_encode(ctx.encoder, &nals, &i_nals, &pic_in, &pic_out);
     106        printf("Frame size is %d, %d nals\n", frame_size, i_nals);
     107        if (frame_size >= 0) {
     108                *out = malloc(frame_size);
     109                *outsz = frame_size;
     110                memcpy(*out, nals[0].p_payload, frame_size);
     111        } else {
     112                fprintf(stderr, "Problem\n");
     113                return 2;
     114        }
     115        return 0;
     116}
     117
     118int decompress_image(uint8_t *in, int size, uint8_t **out, int *outsz)
     119{
     120        if (!ctx.yuv2rgb)
     121                return 1;
     122
     123    int got_picture, len;
     124    AVFrame *picture;
     125    AVPacket avpkt;
     126    av_init_packet(&avpkt);
     127
     128        if (!ctx.codec_ctx || !ctx.codec)
     129                return 1;
     130
     131    printf("Video decoding\n");
     132
     133    picture = avcodec_alloc_frame();
     134
     135        avpkt.data = in;
     136        avpkt.size = size;
     137       
     138        len = avcodec_decode_video2(ctx.codec_ctx, picture, &got_picture, &avpkt);
     139        if (len < 0) {
     140                fprintf(stderr, "Error while decoding frame\n");
     141                *out = NULL;
     142                *outsz = 0;
     143                return 2;
     144        }
     145
     146        AVPicture pic;
     147        avpicture_fill(&pic, malloc(ctx.height * ctx.width * 3), PIX_FMT_RGB24, 800, 600);
     148
     149        /* Colorspace conversion (I420 -> RGB) */
     150        sws_scale(ctx.yuv2rgb, picture->data, picture->linesize, 0, ctx.height, pic.data, pic.linesize);
     151   
     152        av_free(picture);
     153
     154        /* Output */
     155        *out = pic.data[0];
     156        *outsz = pic.linesize[0] * ctx.height;
     157
     158        printf("Got %p, stride %d, size %d\n", pic.data[0], pic.linesize[0], *outsz);
     159        return 0;
     160}
  • xpra/x264/main.py

     
     1# This file is part of Parti.
     2# Copyright (C) 2012 Serviware (Arthur Huillet, <ahuillet@serviware.com>)
     3# Copyright (C) 2012 Antoine Martin <antoine@devloop.org.uk>
     4# Parti is released under the terms of the GNU GPL v2, or, at your option, any
     5# later version. See the file COPYING for details.
     6
     7def main():
     8    from xpra.x264.codec import init_x264_encoder, clean_x264_encoder, x264_compress_image
     9    w = 640
     10    h = 480
     11    i = init_x264_encoder(w, h)
     12    print("init_x264_encoder(%s,%s)=%s" % (w, h, i))
     13    f = None
     14    try:
     15        f = open("x264test.rgb", mode='rb')
     16        data = f.read()
     17    finally:
     18        if f:
     19            f.close()
     20    stride = 800*3
     21    size, compressed = x264_compress_image(data, stride)
     22    print("x264_compress_image(%s bytes, %s)=%s,%s" % (len(data), stride, size, len(compressed)))
     23    i = clean_x264_encoder()
     24    print("clean_x264_encoder()=%s" % i)
     25
     26
     27if __name__ == "__main__":
     28    main()
  • xpra/x264/codec.pyx

    Cannot display: file marked as a binary type.
    svn:mime-type = application/octet-stream
    
    Property changes on: xpra/x264/x264test.rgb
    ___________________________________________________________________
    Added: svn:mime-type
       + application/octet-stream
    
     
     1# This file is part of Parti.
     2# Copyright (C) 2008 Nathaniel Smith <njs@pobox.com>
     3# Parti is released under the terms of the GNU GPL v2, or, at your option, any
     4# later version. See the file COPYING for details.
     5
     6#gcc -pthread -shared -O0 build/temp.linux-x86_64-2.7/xpra/x264/codec.o xpra/x264/x264lib.o -L/usr/lib64 -lx264 -lavcodec -lswscale -lpthread -lpython2.7 -o build/lib.linux-x86_64-2.7/xpra/x264/codec.so
     7
     8ctypedef unsigned int uint8_t
     9cdef extern from "x264lib.h":
     10    int init_encoder(int width, int height)
     11    int init_decoder(int width, int height)
     12    int clean_encoder()
     13    int clean_decoder()
     14    int compress_image(uint8_t *input, int stride, uint8_t **out, int *outsz)
     15    int decompress_image(uint8_t *input, int size, uint8_t **out, int *outsz)
     16
     17cdef extern from "Python.h":
     18    ctypedef int Py_ssize_t
     19    ctypedef object PyObject
     20    int PyObject_AsReadBuffer(object obj,
     21                              void ** buffer,
     22                              Py_ssize_t * buffer_len) except -1
     23
     24
     25def init_x264_encoder(width, height):
     26    return init_encoder(width, height)
     27
     28def init_x264_decoder(width, height):
     29    return init_decoder(width, height)
     30
     31def clean_x264_encoder():
     32    return clean_encoder()
     33
     34def clean_x264_decoder():
     35    return clean_decoder()
     36
     37def x264_compress_image(input, rowstride):
     38    cdef uint8_t *cout
     39    cdef int coutsz
     40    cdef unsigned int * c_cbuf = <uint8_t *> 0
     41    cdef Py_ssize_t c_cbuf_len = 0
     42    PyObject_AsReadBuffer(input, <void **>&c_cbuf, &c_cbuf_len)
     43    i = compress_image(c_cbuf, rowstride, &cout, &coutsz)
     44    print("x264_compress_image(..,%s) out size=%s" % (rowstride, coutsz))
     45    coutv = (<char *>cout)[:coutsz]
     46    return  coutsz, coutv
     47
     48def x264_decompress_image(input, size):
     49    cdef uint8_t *dout
     50    cdef int doutsz
     51    cdef unsigned int * d_cbuf = <uint8_t *> 0
     52    cdef Py_ssize_t d_cbuf_len = 0
     53    PyObject_AsReadBuffer(input, <void **>&d_cbuf, &d_cbuf_len)
     54    i = decompress_image(d_cbuf, size, &dout, &doutsz)
     55    doutv = (<char *>dout)[:doutsz]
     56    return  doutsz, doutv
  • xpra/x264/Makefile

     
     1# This file is part of Parti.
     2# Copyright (C) 2012 Serviware (Arthur Huillet, <ahuillet@serviware.com>)
     3# Copyright (C) 2012 Antoine Martin <antoine@devloop.org.uk>
     4# Parti is released under the terms of the GNU GPL v2, or, at your option, any
     5# later version. See the file COPYING for details.
     6
     7# This makefile is only used for experimenting/testing
     8# The library and python bindings are built using the standard setup.py file
     9
     10CFLAGS+=$(shell pkg-config  --cflags $(FFMPEG_LIBS))
     11LDFLAGS+=$(shell pkg-config --libs $(FFMPEG_LIBS)) -lm
     12
     13CFLAGS+=-fPIC -W -g3 -O1
     14
     15all: x264lib.so testlib
     16
     17x264lib.so: x264lib.o
     18        $(CC) -shared -Wl,-soname,x264lib.so -o $@ $(LDFLAGS) $< -l x264 -lswscale -lavcodec
     19
     20x264lib.o: x264lib.c x264lib.h
     21        $(CC) $(CFLAGS) x264lib.c -c -o $@
     22
     23testlib: x264lib.so testlib.c
     24        $(CC) $(CFLAGS) testlib.c -o $@ ./x264lib.so -l x264 -lswscale -lavcodec
     25
     26OBJS=$(addsuffix .o,$(EXAMPLES))
     27
     28.phony: all clean
     29
     30
     31clean:
     32        rm -rf x264lib.so x264lib.o
  • xpra/x264/x264lib.h

     
     1int init_encoder(int width, int height);
     2int init_decoder(int width, int height);
     3int clean_encoder(void);
     4int clean_decoder(void);
     5int compress_image(uint8_t *in, int stride, uint8_t **out, int *outsz);
     6int decompress_image(uint8_t *in, int size, uint8_t **out, int *outsz);
  • xpra/x264/__init__.py

     
     1# This file is part of Parti.
     2# Copyright (C) 2012 Antoine Martin <antoine@devloop.org.uk>
     3# Parti is released under the terms of the GNU GPL v2, or, at your option, any
     4# later version. See the file COPYING for details.