spice 圖像壓縮算法相關代碼邏輯流程

下面是轉載http://blog.csdn.net/zhoujiaxq/article/details/11201893 內容,是對圖像算法的簡單介紹接流程

目前的spice圖像壓縮主要採用了quic,glz和jpeg。quic和glz是無損壓縮算法,quic主要用於照片,glz用於人工圖像,jpeg也主要用於照片壓縮但是是有損的。jpeg能節省50%的帶寬,glz只能節省20%,但是jpeg會帶來更大的開銷,所以不能都使用jpeg進行壓縮。

spice官網對於廣域網支持的介紹:http://spice-space.org/page/Features/WanSupport

spice圖像壓縮的流程:

qxl首先通過gdi接口獲取到刷新的區域圖像,然後傳送給spice-server,spice-server獲取到圖像後通過

    static inline void marshall_qxl_drawable(RedChannelClient *rcc,SpiceMarshaller *m, DrawablePipeItem *dpi)

 

  1. static inline void marshall_qxl_drawable(RedChannelClient *rcc,SpiceMarshaller *m, DrawablePipeItem *dpi)  
函數先判斷圖像是應該當做視頻處理還是圖像處理,如果是視頻就調用
    red_marshall_stream_data(rcc, m, item)

 

  1. red_marshall_stream_data(rcc, m, item)  
如果是圖像先判斷是否採用jpeg壓縮,是否採用jpeg壓縮是在
    static void red_init(RedWorker *worker, WorkerInitData *init_data)
 
  1. static void red_init(RedWorker *worker, WorkerInitData *init_data)  
裏設置,worker->jpeg_state = init_data->jpeg_state;

如果想採用jpeg壓縮可以直接更改爲worker->jpeg_state =SPICE_WAN_COMPRESSION_ALWAYS;或者在Reds.c裏把

spice_wan_compression_t jpeg_state = SPICE_WAN_COMPRESSION_AUTO;更改爲

        spice_wan_compression_t jpeg_state = SPICE_WAN_COMPRESSION_ALWAYS;

spice-server中圖像的最終壓縮都是在

    static inline int red_compress_image(DisplayChannelClient *dcc,SpiceImage *dest, SpiceBitmap *src, Drawable *drawable,int can_lossy,compress_send_data_t* o_comp_data)

 

  1. static inline int red_compress_image(DisplayChannelClient *dcc,SpiceImage *dest, SpiceBitmap *src, Drawable *drawable,int can_lossy,compress_send_data_t* o_comp_data)  
在這個函數裏會根據image_compression,圖像的大小,圖像的格式來選擇相應的壓縮算法。

spice-server通過tcp傳輸給spice-gtk客戶端,客戶端會通過數據流來判斷出是採用何種壓縮算法並採用相應的算法進行decode。

*************************************************************華麗分割線****************************************************************

     一種觸發quic解碼的路徑,服務器發SPICE_MSG_DISPLAY_DRAW_COPY消息
display_handle_draw_copy進行處理
->surface->canvas->ops->draw_copy
->canvas_draw_copy
->canvas_get_image
->canvas_get_image_internal
->canvas_get_quic

1、quic算法的函數入口
   canvas_get_quic這個函數最終返回的是一個surface,原始位圖寫到
             dest = (uint8_t *)pixman_image_get_data(surface);  

typedef struct display_surface {
    guint32                     surface_id;
    bool                        primary;
    enum SpiceSurfaceFmt        format;
    int                         width, height, stride, size;
    int                         shmid;
    uint8_t                     *data;
    SpiceCanvas                 *canvas;
    SpiceGlzDecoder             *glz_decoder;
    SpiceZlibDecoder            *zlib_decoder;
    SpiceJpegDecoder            *jpeg_decoder;
} display_surface;


struct _SpiceCanvas {
  SpiceCanvasOps *ops; //所有操作函數的函數指針的封裝
};


客戶端增加打印語句
在 canvas_base.c 文件函數中canvas_draw_copy增加下面的輸出:
 pixman_image_t *canvas_image = spice_canvas->ops->get_image(spice_canvas, FALSE); 
int width = pixman_image_get_width (canvas_image); 
int height = pixman_image_get_height (canvas_image); 


SPICE_DEBUG("canvas_draw_copy: %x:%d:%d, [bbox]:%d,%d,%d,%d, [type]%d, [src_area]:%d,%d,%d,%d", 
canvas_image, width, height, bbox->left, bbox->top, 
bbox->right - bbox->left, bbox->bottom - bbox->top, 
copy->src_bitmap->descriptor.type, 
copy->src_area.left, copy->src_area.top, 
copy->src_area.right - copy->src_area.left, copy->src_area.bottom - 
copy->src_area.top 
);


服務器端圖像採集及壓縮:
以下函數在red_worker.c 文件中。
display_channel_send_item 函數從QXL驅動中讀取到當前圖像的更新,然後發到客戶端
->marshall_qxl_drawable 判斷當前圖像時視頻還是圖片的刷新,如果是視頻的刷新回退出,再判斷是無損還是有損壓縮,調用相關的
函數接口。jpeg是有損壓縮,根據設置這裏使用無損壓縮。
->red_marshall_qxl_drawable
->red_marshall_qxl_draw_copy
->fill_bits,fill_mask
->red_compress_image 進入圖像壓縮算法的選擇,目前在quic 和glz lz算法之間進行,默認是glz,根據圖像源的x,y,和stripe等等決定,是否
使用quic算法
->red_quic_compress_image quic算法 。。


http://lists.freedesktop.org/archives/spice-devel/2013-October/015156.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章