Update of /cvsroot/freevo/kaa/xine/src/drivers
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10159/src/drivers

Modified Files:
        buffer.c x11.c x11.h 
Log Message:
New VODriver class; add load_video_output_plugin (requires patch to xine-lib);
reimplement open_video_driver() to use load_video_output_plugin() and
VODriver.get_port(); refactor type initialization in xine.c; reimplement
buffer driver to use a video driver instead of video port; implement RLE
overlay blending in buffer driver (code ripped from xine-lib); buffer driver
seems to actually work now.  kaaplayer.py is a mess. :)


Index: x11.h
===================================================================
RCS file: /cvsroot/freevo/kaa/xine/src/drivers/x11.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** x11.h       19 Jul 2005 02:07:25 -0000      1.2
--- x11.h       30 Jul 2005 20:55:15 -0000      1.3
***************
*** 7,16 ****
  #include <X11/Xutil.h>
  #include "../xine.h"
! #include "../video_port.h"
  
  extern PyTypeObject *X11Window_PyObject_Type;
  extern int (*x11window_object_decompose)(PyObject *, Window *, Display **);
! xine_video_port_t *x11_open_video_driver(Xine_PyObject *, char *, PyObject 
*kwargs, void **);
! void x11_open_video_driver_finalize(Xine_Video_Port_PyObject *, void *);
  
  #endif
--- 7,16 ----
  #include <X11/Xutil.h>
  #include "../xine.h"
! #include "../vo_driver.h"
  
  extern PyTypeObject *X11Window_PyObject_Type;
  extern int (*x11window_object_decompose)(PyObject *, Window *, Display **);
! vo_driver_t *x11_open_video_driver(Xine_PyObject *, char *, PyObject *kwargs, 
void **);
! void x11_open_video_driver_finalize(Xine_VO_Driver_PyObject *, void *);
  
  #endif

Index: x11.c
===================================================================
RCS file: /cvsroot/freevo/kaa/xine/src/drivers/x11.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** x11.c       21 Jul 2005 18:48:19 -0000      1.5
--- x11.c       30 Jul 2005 20:55:15 -0000      1.6
***************
*** 8,11 ****
--- 8,12 ----
               *dest_size_callback;
      Display *display;
+     PyObject *window_pyobject;
  } x11_callback_user_data;
  
***************
*** 30,35 ****
          return;
      }
- 
- 
      gstate = PyGILState_Ensure();
      args = Py_BuildValue("(iid)", video_width, video_height, 
video_pixel_aspect);
--- 31,34 ----
***************
*** 116,125 ****
  
  
! xine_video_port_t *
! x11_open_video_driver(Xine_PyObject *xine, char *driver, PyObject *kwargs, 
                        void **driver_data)
  {
      x11_visual_t vis;
!     xine_video_port_t *vo;
      x11_callback_user_data *user_data;
      x11_driver_finalize_data *finalize_data;
--- 115,124 ----
  
  
! vo_driver_t *
! x11_open_video_driver(Xine_PyObject *xine, char *id, PyObject *kwargs, 
                        void **driver_data)
  {
      x11_visual_t vis;
!     vo_driver_t *driver;
      x11_callback_user_data *user_data;
      x11_driver_finalize_data *finalize_data;
***************
*** 140,143 ****
--- 139,143 ----
      }
  
+ 
      user_data = malloc(sizeof(x11_callback_user_data));
      finalize_data = malloc(sizeof(x11_driver_finalize_data));
***************
*** 146,149 ****
--- 146,151 ----
      user_data->dest_size_callback = dest_size_callback;
      user_data->display = vis.display;
+     user_data->window_pyobject = window;
+     Py_INCREF(window);
      if (frame_output_callback)
          Py_INCREF(frame_output_callback);
***************
*** 156,164 ****
      vis.dest_size_cb = x11_dest_size_cb;
  
!     vo = xine_open_video_driver(xine->xine, driver, XINE_VISUAL_TYPE_X11, 
(void *)&vis);
  
      finalize_data->user_data = user_data;
      *(x11_driver_finalize_data **)driver_data = finalize_data;      
!     return vo;
  }
  
--- 158,167 ----
      vis.dest_size_cb = x11_dest_size_cb;
  
! //    vo = xine_open_video_driver(xine->xine, id, XINE_VISUAL_TYPE_X11, (void 
*)&vis);
!     driver = _x_load_video_output_plugin(xine->xine, id, 
XINE_VISUAL_TYPE_X11, (void *)&vis);
  
      finalize_data->user_data = user_data;
      *(x11_driver_finalize_data **)driver_data = finalize_data;      
!     return driver;
  }
  
***************
*** 166,179 ****
  x11_driver_dealloc(void *data)
  {
      x11_callback_user_data *user_data = (x11_callback_user_data *)data;
      if (user_data->frame_output_callback)
          Py_DECREF(user_data->frame_output_callback);
      if (user_data->dest_size_callback)
          Py_DECREF(user_data->dest_size_callback);
      free(user_data);
  }
  
  void 
! x11_open_video_driver_finalize(Xine_Video_Port_PyObject *vo, void 
*_finalize_data)
  {
      x11_driver_finalize_data *finalize_data = (x11_driver_finalize_data 
*)_finalize_data;
--- 169,187 ----
  x11_driver_dealloc(void *data)
  {
+     PyGILState_STATE gstate;
      x11_callback_user_data *user_data = (x11_callback_user_data *)data;
+     
+     gstate = PyGILState_Ensure();
      if (user_data->frame_output_callback)
          Py_DECREF(user_data->frame_output_callback);
      if (user_data->dest_size_callback)
          Py_DECREF(user_data->dest_size_callback);
+     Py_DECREF(user_data->window_pyobject);
+     PyGILState_Release(gstate);
      free(user_data);
  }
  
  void 
! x11_open_video_driver_finalize(Xine_VO_Driver_PyObject *vo, void 
*_finalize_data)
  {
      x11_driver_finalize_data *finalize_data = (x11_driver_finalize_data 
*)_finalize_data;
***************
*** 182,187 ****
          return;
  
!     vo->driver_dealloc_cb = x11_driver_dealloc;
!     vo->driver_dealloc_data = finalize_data->user_data;
      free(finalize_data);
  }
--- 190,195 ----
          return;
  
!     vo->dealloc_cb = x11_driver_dealloc;
!     vo->dealloc_data = finalize_data->user_data;
      free(finalize_data);
  }

Index: buffer.c
===================================================================
RCS file: /cvsroot/freevo/kaa/xine/src/drivers/buffer.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** buffer.c    25 Jul 2005 23:23:57 -0000      1.2
--- buffer.c    30 Jul 2005 20:55:15 -0000      1.3
***************
*** 2,6 ****
  #include "buffer.h"
  #include "../xine.h"
! #include "../video_port.h"
  
  typedef struct buffer_frame_s {
--- 2,9 ----
  #include "buffer.h"
  #include "../xine.h"
! #include "../vo_driver.h"
! 
! static void _overlay_blend(vo_driver_t *, vo_frame_t *, vo_overlay_t *);
! 
  
  typedef struct buffer_frame_s {
***************
*** 8,11 ****
--- 11,18 ----
      int width, height, format;
      double ratio;
+     int flags;
+ 
+     unsigned char *yv12_buffer, *yuy2_buffer;
+     vo_frame_t *passthrough_frame;
      // more
  } buffer_frame_t;
***************
*** 17,22 ****
      xine_t *xine;
  
      PyObject *callback;
!     xine_video_port_t *passthrough;
  } buffer_driver_t;
  
--- 24,32 ----
      xine_t *xine;
  
+     int aspect;
+ 
      PyObject *callback;
!     vo_driver_t *passthrough;
!     PyObject *passthrough_pyobject;
  } buffer_driver_t;
  
***************
*** 32,36 ****
  {
      printf("buffer: get_capabilities\n");
!     return VO_CAP_YV12;
  }
  
--- 42,46 ----
  {
      printf("buffer: get_capabilities\n");
!     return VO_CAP_YV12 | VO_CAP_YUY2;
  }
  
***************
*** 45,61 ****
  {
      buffer_frame_t *frame = (buffer_frame_t *)vo_img;
!     printf("buffer_frame_dispose\n");
      pthread_mutex_destroy(&frame->vo_frame.mutex);
!     if (frame->vo_frame.base[0])
!         free(frame->vo_frame.base[0]);
      free(frame);
  }
  
  static vo_frame_t *
  buffer_alloc_frame(vo_driver_t *this_gen)
  {
      buffer_frame_t *frame;
      
!     //printf("buffer_alloc_frame\n");
      frame = (buffer_frame_t *)xine_xmalloc(sizeof(buffer_frame_t));
      if (!frame)
--- 55,84 ----
  {
      buffer_frame_t *frame = (buffer_frame_t *)vo_img;
!     //printf("buffer_frame_dispose\n");
      pthread_mutex_destroy(&frame->vo_frame.mutex);
!     if (frame->yv12_buffer)
!         free(frame->yv12_buffer);
!     if (frame->yuy2_buffer)
!         free(frame->yuy2_buffer);
! 
      free(frame);
  }
  
+ void vo_frame_inc_lock(vo_frame_t *img)
+ {
+ }
+ 
+ void vo_frame_dec_lock(vo_frame_t *img)
+ {
+ }
+ 
+ 
  static vo_frame_t *
  buffer_alloc_frame(vo_driver_t *this_gen)
  {
      buffer_frame_t *frame;
+     buffer_driver_t *this = (buffer_driver_t *)this_gen;
      
!     printf("buffer_alloc_frame: %x\n", this);
      frame = (buffer_frame_t *)xine_xmalloc(sizeof(buffer_frame_t));
      if (!frame)
***************
*** 64,67 ****
--- 87,92 ----
      pthread_mutex_init(&frame->vo_frame.mutex, NULL);
  
+     frame->yv12_buffer = frame->yuy2_buffer = NULL;
+ 
      frame->vo_frame.base[0] = NULL;
      frame->vo_frame.base[1] = NULL;
***************
*** 74,86 ****
      frame->vo_frame.driver = this_gen;
  
      return (vo_frame_t *)frame;
  }
  
- 
  static void 
  buffer_update_frame_format (vo_driver_t *this_gen,
!                     vo_frame_t *frame_gen,
!                     uint32_t width, uint32_t height,
!                     double ratio, int format, int flags) 
  {
      buffer_driver_t *this = (buffer_driver_t *)this_gen;
--- 99,115 ----
      frame->vo_frame.driver = this_gen;
  
+     frame->passthrough_frame = 
this->passthrough->alloc_frame(this->passthrough);
+     frame->passthrough_frame->free = vo_frame_dec_lock;
+     frame->passthrough_frame->lock = vo_frame_inc_lock;
+ 
+ 
      return (vo_frame_t *)frame;
  }
  
  static void 
  buffer_update_frame_format (vo_driver_t *this_gen,
!                 vo_frame_t *frame_gen,
!                 uint32_t width, uint32_t height,
!                 double ratio, int format, int flags) 
  {
      buffer_driver_t *this = (buffer_driver_t *)this_gen;
***************
*** 88,116 ****
      int y_size, uv_size;
  
!     //printf("buffer_update_frame_format: %dx%d ratio=%.3f\n", width, height, 
ratio);
  
-     frame->vo_frame.pitches[0] = width;
-     frame->vo_frame.pitches[1] = width>>1;
-     frame->vo_frame.pitches[2] = width>>1;
  
!     y_size = frame->vo_frame.pitches[0] * height;
!     uv_size = frame->vo_frame.pitches[1] * (height>>1);
  
  
!     if (frame->width != width || frame->height != height) {
!         if (frame->vo_frame.base[0]) {
!             free(frame->vo_frame.base[0]);
          }
-         frame->vo_frame.base[0] = xine_xmalloc(y_size + (2*uv_size));
-         frame->vo_frame.base[1] = frame->vo_frame.base[0] + y_size;
-         frame->vo_frame.base[2] = frame->vo_frame.base[0] + y_size + uv_size;
      }
! 
      frame->width = width;
      frame->height = height;
      frame->format = format;
      frame->ratio = ratio;
! 
! 
  }
  
--- 117,177 ----
      int y_size, uv_size;
  
! //    printf("buffer_update_frame_format: %x format=%d  %dx%d\n", frame, 
format, width, height);
  
  
!     this->passthrough->update_frame_format(this->passthrough,
!         frame->passthrough_frame, width, height, ratio, format, flags);
! 
!     memcpy(&frame->vo_frame.pitches, frame->passthrough_frame->pitches, 
sizeof(int)*3);
!     memcpy(&frame->vo_frame.base, frame->passthrough_frame->base, sizeof(char 
*)*3);
  
  
! #if 0
!     if (frame->width != width || frame->height != height || format != 
frame->format) {
!         if (format == XINE_IMGFMT_YV12) {
!             frame->vo_frame.pitches[0] = 8*((width + 7) / 8);
!             frame->vo_frame.pitches[1] = 8*((width + 15) / 16);
!             frame->vo_frame.pitches[2] = 8*((width + 15) / 16);
!     
!             y_size  = frame->vo_frame.pitches[0] * height;
!             uv_size = frame->vo_frame.pitches[1] * ((height+1)/2);
!     
!             if (frame->yv12_buffer && (width != frame->width || height != 
frame->height)) {
!                 free(frame->yv12_buffer);
!                 frame->yv12_buffer = NULL;
!             }
!             if (!frame->yv12_buffer) {
!                 printf("buffer_update_frame_format: %x format=%d  %dx%d\n", 
frame, format, width, height);
!                 frame->yv12_buffer = xine_xmalloc(y_size + 2*uv_size);
!             }
!             frame->vo_frame.base[0] = frame->yv12_buffer;
!             frame->vo_frame.base[1] = frame->vo_frame.base[0] + 
y_size+uv_size;
!             frame->vo_frame.base[2] = frame->vo_frame.base[0] + y_size;
!         } else if (format == XINE_IMGFMT_YUY2) {
!             frame->vo_frame.pitches[0] = 8*((width + 3) / 4);
!             frame->vo_frame.pitches[1] = 0;
!             frame->vo_frame.pitches[2] = 0;
!             if (frame->yuy2_buffer && (width != frame->width || height != 
frame->height)) {
!                 free(frame->yuy2_buffer);
!                 frame->yuy2_buffer = NULL;
!             }
!             if (!frame->yuy2_buffer) {
!                 printf("buffer_update_frame_format: %x format=%d  %dx%d\n", 
frame, format, width, height);
!                 frame->yuy2_buffer = xine_xmalloc(frame->vo_frame.pitches[0] 
* height);
!             }
!     
!             frame->vo_frame.base[0] = frame->yuy2_buffer;
!             frame->vo_frame.base[1] = NULL;
!             frame->vo_frame.base[2] = NULL;
!         } else {
!             printf("\n\n\nUNSUPPORTED FRAME FORMAT %d\n\n\n", format);
          }
      }
! #endif
      frame->width = width;
      frame->height = height;
      frame->format = format;
      frame->ratio = ratio;
!     frame->flags = flags;
  }
  
***************
*** 118,123 ****
  buffer_redraw_needed(vo_driver_t *vo)
  {
! //    printf("buffer_redraw_needed\n");
!     return 0;
  }
  
--- 179,186 ----
  buffer_redraw_needed(vo_driver_t *vo)
  {
!     buffer_driver_t *this = (buffer_driver_t *)vo;
!     //printf("buffer_redraw_needed: %x\n", vo);
!     return this->passthrough->redraw_needed(this->passthrough);
!     return 1;
  }
  
***************
*** 132,137 ****
      PyGILState_STATE gstate;
  
      pthread_mutex_lock(&this->lock);
- //    printf("buffer_display_frame: fd=%d %d\n", this->callback, 
frame->vo_frame.base[0][2000]);
  
      gstate = PyGILState_Ensure();
--- 195,200 ----
      PyGILState_STATE gstate;
  
+     //printf("buffer_display_frame: %x draw=%x w=%d h=%d ratio=%.3f format=%d 
(yv12=%d yuy=%d)\n", frame, frame_gen->draw, frame->vo_frame.width, 
frame->height, frame->ratio, frame->format, XINE_IMGFMT_YV12, XINE_IMGFMT_YUY2);
      pthread_mutex_lock(&this->lock);
  
      gstate = PyGILState_Ensure();
***************
*** 152,168 ****
  
      if (this->passthrough && do_passthrough) {
!         passthrough_frame = this->passthrough->get_frame(this->passthrough, 
!             frame->vo_frame.width, frame->vo_frame.height, 
frame->vo_frame.ratio, 
!             frame->vo_frame.format, frame->vo_frame.flags);
!         
!         int size = (frame_gen->pitches[0] * frame->height) + 
(frame_gen->pitches[1] * (frame->height>>1))*2;
!         xine_fast_memcpy(passthrough_frame->base[0], frame_gen->base[0], 
frame_gen->pitches[0] * frame->height);
!         xine_fast_memcpy(passthrough_frame->base[1], frame_gen->base[1], 
frame_gen->pitches[1] * (frame->height>>1));
!         xine_fast_memcpy(passthrough_frame->base[2], frame_gen->base[2], 
frame_gen->pitches[2] * (frame->height>>1));
! 
!         _x_post_frame_copy_down(frame, passthrough_frame);
!         passthrough_frame->draw(passthrough_frame, frame_gen->stream);
!         _x_post_frame_copy_up(passthrough_frame, frame);
!         passthrough_frame->free(passthrough_frame);
      }
      frame->vo_frame.free(&frame->vo_frame);
--- 215,219 ----
  
      if (this->passthrough && do_passthrough) {
!         this->passthrough->display_frame(this->passthrough, 
frame->passthrough_frame);
      }
      frame->vo_frame.free(&frame->vo_frame);
***************
*** 173,177 ****
--- 224,234 ----
  buffer_get_property (vo_driver_t *this_gen, int property) 
  {
+     buffer_driver_t *this = (buffer_driver_t *)this_gen;
      printf("buffer_get_property: %d\n", property);
+     switch(property) {
+         case VO_PROP_ASPECT_RATIO:
+             return this->aspect;
+     }
+     return this->passthrough->get_property(this->passthrough, property);
  }
  
***************
*** 180,184 ****
--- 237,250 ----
                  int property, int value) 
  {
+     buffer_driver_t *this = (buffer_driver_t *)this_gen;
      printf("buffer_set_property %d=%d\n", property, value);
+     switch (property) {
+         case VO_PROP_ASPECT_RATIO:
+             if (value >= XINE_VO_ASPECT_NUM_RATIOS)
+                 value = XINE_VO_ASPECT_AUTO;
+             this->aspect = value;
+             return value;
+     }
+     return this->passthrough->set_property(this->passthrough, property, 
value);
  }
  
***************
*** 187,191 ****
--- 253,259 ----
                       int property, int *min, int *max) 
  {
+     buffer_driver_t *this = (buffer_driver_t *)this_gen;
      printf("buffer_get_property_min_max\n");
+     this->passthrough->get_property_min_max(this->passthrough, property, min, 
max);
  }
  
***************
*** 194,199 ****
                   int data_type, void *data) 
  {
      printf("buffer_gui_data_exchange\n");
!     return 0;
  }
  
--- 262,268 ----
                   int data_type, void *data) 
  {
+     buffer_driver_t *this = (buffer_driver_t *)this_gen;
      printf("buffer_gui_data_exchange\n");
!     return this->passthrough->gui_data_exchange(this->passthrough, data_type, 
data);
  }
  
***************
*** 201,208 ****
--- 270,283 ----
  buffer_dispose(vo_driver_t *this_gen)
  {
+     PyGILState_STATE gstate;
      buffer_driver_t *this = (buffer_driver_t *)this_gen;
+ 
      printf("buffer_dispose\n");
+ 
+     gstate = PyGILState_Ensure();
      if (this->callback)
         Py_DECREF(this->callback);
+     Py_DECREF(this->passthrough_pyobject);
+     PyGILState_Release(gstate);
  
      free(this);
***************
*** 225,230 ****
      }
      passthrough = PyDict_GetItemString(kwargs, "passthrough");
!     if (passthrough && !Xine_Video_Port_PyObject_Check(passthrough)) {
!         PyErr_Format(xine_error, "Passthrough must be a video driver");
          return NULL;
      }
--- 300,305 ----
      }
      passthrough = PyDict_GetItemString(kwargs, "passthrough");
!     if (passthrough && !Xine_VO_Driver_PyObject_Check(passthrough)) {
!         PyErr_Format(xine_error, "Passthrough must be a VODriver object");
          return NULL;
      }
***************
*** 243,247 ****
      this->vo_driver.update_frame_format     = buffer_update_frame_format;
      this->vo_driver.overlay_begin           = NULL;
!     this->vo_driver.overlay_blend           = NULL;
      this->vo_driver.overlay_end             = NULL;
      this->vo_driver.display_frame           = buffer_display_frame;
--- 318,322 ----
      this->vo_driver.update_frame_format     = buffer_update_frame_format;
      this->vo_driver.overlay_begin           = NULL;
!     this->vo_driver.overlay_blend           = _overlay_blend;
      this->vo_driver.overlay_end             = NULL;
      this->vo_driver.display_frame           = buffer_display_frame;
***************
*** 255,260 ****
      this->callback = callback;
      Py_INCREF(this->callback);
!     this->passthrough = ((Xine_Video_Port_PyObject *)passthrough)->vo;
  
      return &this->vo_driver;
  }
--- 330,338 ----
      this->callback = callback;
      Py_INCREF(this->callback);
!     this->passthrough = ((Xine_VO_Driver_PyObject *)passthrough)->driver;
!     Py_INCREF(passthrough);
!     this->passthrough_pyobject = passthrough;
  
+ //    memcpy(&this->vo_driver, this->passthrough->driver, 
sizeof(vo_driver_t));
      return &this->vo_driver;
  }
***************
*** 297,300 ****
--- 375,812 ----
  }
  
+ 
+ // These rle blend functions taken from xine (src/video_out/alphablend.c)
+ 
+ #define BLEND_BYTE(dst, src, o) (((src)*o + ((dst)*(0xf-o)))/0xf)
+ 
+ static void mem_blend32(uint8_t *mem, uint8_t *src, uint8_t o, int len) {
+   uint8_t *limit = mem + len*4;
+   while (mem < limit) {
+     *mem = BLEND_BYTE(*mem, src[0], o);
+     mem++;
+     *mem = BLEND_BYTE(*mem, src[1], o);
+     mem++;
+     *mem = BLEND_BYTE(*mem, src[2], o);
+     mem++;
+     *mem = BLEND_BYTE(*mem, src[3], o);
+     mem++;
+   }
+ }
+ 
+ 
+ typedef struct {         /* CLUT == Color LookUp Table */
+   uint8_t cb    : 8;
+   uint8_t cr    : 8;
+   uint8_t y     : 8;
+   uint8_t foo   : 8;
+ } __attribute__ ((packed)) clut_t;
+ 
+ 
+ static void _overlay_mem_blend_8(uint8_t *mem, uint8_t val, uint8_t o, size_t 
sz)
+ {
+    uint8_t *limit = mem + sz;
+    while (mem < limit) {
+       *mem = BLEND_BYTE(*mem, val, o);
+       mem++;
+    }
+ }
+ 
+ static void _overlay_blend_yuv(uint8_t *dst_base[3], vo_overlay_t * 
img_overl, int dst_width, int dst_height, int dst_pitches[3])
+ {
+    clut_t *my_clut;
+    uint8_t *my_trans;
+    int src_width;
+    int src_height;
+    rle_elem_t *rle;
+    rle_elem_t *rle_limit;
+    int x_off;
+    int y_off;
+    int ymask, xmask;
+    int rle_this_bite;
+    int rle_remainder;
+    int rlelen;
+    int x, y;
+    int clip_right;
+    uint8_t clr = 0;
+ 
+    src_width = img_overl->width;
+    src_height = img_overl->height;
+    rle = img_overl->rle;
+    rle_limit = rle + img_overl->num_rle;
+    x_off = img_overl->x;
+    y_off = img_overl->y;
+ 
+    if (!rle) return;
+ 
+    //printf("_overlay_blend_yuv: rle=%x w=%d h=%d x=%d y=%d\n", rle, 
src_width, src_height, x_off, y_off);
+    uint8_t *dst_y = dst_base[0] + dst_pitches[0] * y_off + x_off;
+    uint8_t *dst_cr = dst_base[2] + (y_off / 2) * dst_pitches[1] + (x_off / 2) 
+ 1;
+    uint8_t *dst_cb = dst_base[1] + (y_off / 2) * dst_pitches[2] + (x_off / 2) 
+ 1;
+    my_clut = (clut_t *) img_overl->clip_color;
+    my_trans = img_overl->clip_trans;
+ 
+    /* avoid wraping overlay if drawing to small image */
+    if( (x_off + img_overl->clip_right) < dst_width )
+      clip_right = img_overl->clip_right;
+    else
+      clip_right = dst_width - 1 - x_off;
+ 
+    /* avoid buffer overflow */
+    if( (src_height + y_off) >= dst_height )
+      src_height = dst_height - 1 - y_off;
+ 
+    rlelen=rle_remainder=0;
+    for (y = 0; y < src_height; y++) {
+       ymask = ((img_overl->clip_top > y) || (img_overl->clip_bottom < y));
+       xmask = 0;
+ 
+       for (x = 0; x < src_width;) {
+      uint16_t o;
+ 
+      if (rlelen == 0) {
+         rle_remainder = rlelen = rle->len;
+         clr = rle->color;
+         rle++;
+      }
+      if (rle_remainder == 0) {
+         rle_remainder = rlelen;
+      }
+      if ((rle_remainder + x) > src_width) {
+         /* Do something for long rlelengths */
+         rle_remainder = src_width - x;
+      }
+ 
+      if (ymask == 0) {
+         if (x <= img_overl->clip_left) {
+            /* Starts outside clip area */
+            if ((x + rle_remainder - 1) > img_overl->clip_left ) {
+           /* Cutting needed, starts outside, ends inside */
+           rle_this_bite = (img_overl->clip_left - x + 1);
+           rle_remainder -= rle_this_bite;
+           rlelen -= rle_this_bite;
+           my_clut = (clut_t *) img_overl->color;
+           my_trans = img_overl->trans;
+           xmask = 0;
+            } else {
+           /* no cutting needed, starts outside, ends outside */
+           rle_this_bite = rle_remainder;
+           rle_remainder = 0;
+           rlelen -= rle_this_bite;
+           my_clut = (clut_t *) img_overl->color;
+           my_trans = img_overl->trans;
+           xmask = 0;
+            }
+         } else if (x < clip_right) {
+            /* Starts inside clip area */
+            if ((x + rle_remainder) > clip_right ) {
+           /* Cutting needed, starts inside, ends outside */
+           rle_this_bite = (clip_right - x);
+           rle_remainder -= rle_this_bite;
+           rlelen -= rle_this_bite;
+           my_clut = (clut_t *) img_overl->clip_color;
+           my_trans = img_overl->clip_trans;
+           xmask++;
+            } else {
+           /* no cutting needed, starts inside, ends inside */
+           rle_this_bite = rle_remainder;
+           rle_remainder = 0;
+           rlelen -= rle_this_bite;
+           my_clut = (clut_t *) img_overl->clip_color;
+           my_trans = img_overl->clip_trans;
+           xmask++;
+            }
+         } else if (x >= clip_right) {
+            /* Starts outside clip area, ends outsite clip area */
+            if ((x + rle_remainder ) > src_width ) {
+           /* Cutting needed, starts outside, ends at right edge */
+           /* It should never reach here due to the earlier test of src_width 
*/
+           rle_this_bite = (src_width - x );
+           rle_remainder -= rle_this_bite;
+           rlelen -= rle_this_bite;
+           my_clut = (clut_t *) img_overl->color;
+           my_trans = img_overl->trans;
+           xmask = 0;
+            } else {
+           /* no cutting needed, starts outside, ends outside */
+           rle_this_bite = rle_remainder;
+           rle_remainder = 0;
+           rlelen -= rle_this_bite;
+           my_clut = (clut_t *) img_overl->color;
+           my_trans = img_overl->trans;
+           xmask = 0;
+            }
+         }
+      } else {
+         /* Outside clip are due to y */
+         /* no cutting needed, starts outside, ends outside */
+         rle_this_bite = rle_remainder;
+         rle_remainder = 0;
+         rlelen -= rle_this_bite;
+         my_clut = (clut_t *) img_overl->color;
+         my_trans = img_overl->trans;
+         xmask = 0;
+      }
+      o   = my_trans[clr];
+      if (o) {
+         if(o >= 15) {
+            memset(dst_y + x, my_clut[clr].y, rle_this_bite);
+            if (y & 1) {
+           memset(dst_cr + (x >> 1), my_clut[clr].cr, (rle_this_bite+1) >> 1);
+           memset(dst_cb + (x >> 1), my_clut[clr].cb, (rle_this_bite+1) >> 1);
+            }
+         } else {
+            _overlay_mem_blend_8(dst_y + x, my_clut[clr].y, o, rle_this_bite);
+            if (y & 1) {
+           /* Blending cr and cb should use a different function, with pre 
-128 to each sample */
+           _overlay_mem_blend_8(dst_cr + (x >> 1), my_clut[clr].cr, o, 
(rle_this_bite+1) >> 1);
+           _overlay_mem_blend_8(dst_cb + (x >> 1), my_clut[clr].cb, o, 
(rle_this_bite+1) >> 1);
+            }
+         }
+ 
+      }
+      x += rle_this_bite;
+      if (rle >= rle_limit) {
+         break;
+      }
+       }
+       if (rle >= rle_limit) {
+      break;
+       }
+ 
+       dst_y += dst_pitches[0];
+ 
+       if (y & 1) {
+      dst_cr += dst_pitches[2];
+      dst_cb += dst_pitches[1];
+       }
+    }
+ }
+ 
+ 
+ void _overlay_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl,
+                  int dst_width, int dst_height, int dst_pitch)
+ {
+   clut_t *my_clut;
+   uint8_t *my_trans;
+ 
+   int src_width = img_overl->width;
+   int src_height = img_overl->height;
+   rle_elem_t *rle = img_overl->rle;
+   rle_elem_t *rle_limit = rle + img_overl->num_rle;
+   int x_off = img_overl->x;
+   int y_off = img_overl->y;
+   int x_odd = x_off & 1;
+   int ymask;
+   int rle_this_bite;
+   int rle_remainder;
+   int rlelen;
+   int x, y;
+   int l = 0;
+   int clip_right;
+ 
+   union {
+     uint32_t value;
+     uint8_t  b[4];
+     uint16_t h[2];
+   } yuy2;
+ 
+   uint8_t clr = 0;
+ 
+   int any_line_buffered = 0;
+   uint8_t *(*blend_yuy2_data)[ 3 ] = 0;
+   
+   uint8_t *dst_y = dst_img + dst_pitch * y_off + 2 * x_off;
+   uint8_t *dst;
+ 
+   my_clut = (clut_t*) img_overl->clip_color;
+   my_trans = img_overl->clip_trans;
+ 
+   /* avoid wraping overlay if drawing to small image */
+   if( (x_off + img_overl->clip_right) <= dst_width )
+     clip_right = img_overl->clip_right;
+   else
+     clip_right = dst_width - x_off;
+ 
+   /* avoid buffer overflow */
+   if( (src_height + y_off) > dst_height )
+     src_height = dst_height - y_off;
+ 
+   if (src_height <= 0)
+     return;
+ 
+   rlelen=rle_remainder=0;
+   for (y = 0; y < src_height; y++) {
+     if (rle >= rle_limit)
+       break;
+     
+     ymask = ((y < img_overl->clip_top) || (y >= img_overl->clip_bottom));
+ 
+     dst = dst_y;
+     for (x = 0; x < src_width;) {
+       uint16_t o;
+ 
+       if (rle >= rle_limit)
+         break;
+     
+       if ((rlelen < 0) || (rle_remainder < 0)) {
+       } 
+       if (rlelen == 0) {
+         rle_remainder = rlelen = rle->len;
+         clr = rle->color;
+         rle++;
+       }
+       if (rle_remainder == 0) {
+         rle_remainder = rlelen;
+       }
+       if ((rle_remainder + x) > src_width) {
+         /* Do something for long rlelengths */
+         rle_remainder = src_width - x;
+       }
+ 
+       if (ymask == 0) {
+         if (x < img_overl->clip_left) { 
+           /* Starts outside clip area */
+           if ((x + rle_remainder) > img_overl->clip_left ) {
+             /* Cutting needed, starts outside, ends inside */
+             rle_this_bite = (img_overl->clip_left - x);
+             rle_remainder -= rle_this_bite;
+             rlelen -= rle_this_bite;
+             my_clut = (clut_t*) img_overl->color;
+             my_trans = img_overl->trans;
+           } else {
+           /* no cutting needed, starts outside, ends outside */
+             rle_this_bite = rle_remainder;
+             rle_remainder = 0;
+             rlelen -= rle_this_bite;
+             my_clut = (clut_t*) img_overl->color;
+             my_trans = img_overl->trans;
+           }
+         } else if (x < clip_right) {
+           /* Starts inside clip area */
+           if ((x + rle_remainder) > clip_right ) {
+             /* Cutting needed, starts inside, ends outside */
+             rle_this_bite = (clip_right - x);
+             rle_remainder -= rle_this_bite;
+             rlelen -= rle_this_bite;
+             my_clut = (clut_t*) img_overl->clip_color;
+             my_trans = img_overl->clip_trans;
+           } else {
+           /* no cutting needed, starts inside, ends inside */
+             rle_this_bite = rle_remainder;
+             rle_remainder = 0;
+             rlelen -= rle_this_bite;
+             my_clut = (clut_t*) img_overl->clip_color;
+             my_trans = img_overl->clip_trans;
+           }
+         } else if (x >= clip_right) {
+           /* Starts outside clip area, ends outsite clip area */
+           if ((x + rle_remainder ) > src_width ) { 
+             /* Cutting needed, starts outside, ends at right edge */
+             /* It should never reach here due to the earlier test of 
src_width */
+             rle_this_bite = (src_width - x );
+             rle_remainder -= rle_this_bite;
+             rlelen -= rle_this_bite;
+             my_clut = (clut_t*) img_overl->color;
+             my_trans = img_overl->trans;
+           } else {
+           /* no cutting needed, starts outside, ends outside */
+             rle_this_bite = rle_remainder;
+             rle_remainder = 0;
+             rlelen -= rle_this_bite;
+             my_clut = (clut_t*) img_overl->color;
+             my_trans = img_overl->trans;
+           }
+         }
+       } else {
+         /* Outside clip are due to y */
+         /* no cutting needed, starts outside, ends outside */
+         rle_this_bite = rle_remainder;
+         rle_remainder = 0;
+         rlelen -= rle_this_bite;
+         my_clut = (clut_t*) img_overl->color;
+         my_trans = img_overl->trans;
+       }
+       o   = my_trans[clr];
+ 
+       if (x < (dst_width - x_off)) {
+         /* clip against right edge of destination area */
+         if ((x + rle_this_bite) > (dst_width - x_off)) {
+           int toClip = (x + rle_this_bite) - (dst_width - x_off);
+           
+           rle_this_bite -= toClip;
+           rle_remainder += toClip;
+           rlelen += toClip;
+         }
+ 
+         if (o) {
+             l = rle_this_bite>>1;
+             if( !((x_odd+x) & 1) ) {
+               yuy2.b[0] = my_clut[clr].y;
+               yuy2.b[1] = my_clut[clr].cb;
+               yuy2.b[2] = my_clut[clr].y;
+               yuy2.b[3] = my_clut[clr].cr;
+             } else {
+               yuy2.b[0] = my_clut[clr].y;
+               yuy2.b[1] = my_clut[clr].cr;
+               yuy2.b[2] = my_clut[clr].y;
+               yuy2.b[3] = my_clut[clr].cb;
+             }
+ 
+           if (o >= 15) {
+               while(l--) {
+                 *(uint16_t *)dst = yuy2.h[0];
+                 dst += 2;
+                 *(uint16_t *)dst = yuy2.h[1];
+                 dst += 2;
+               }
+               if(rle_this_bite & 1) {
+                 *(uint16_t *)dst = yuy2.h[0];
+                 dst += 2;
+               }
+           } else {
+               if( l ) {
+                 mem_blend32(dst, &yuy2.b[0], o, l);
+                 dst += 4*l;
+               }
+               
+               if(rle_this_bite & 1) {
+                 *dst = BLEND_BYTE(*dst, yuy2.b[0], o);
+                 dst++;
+                 *dst = BLEND_BYTE(*dst, yuy2.b[1], o);
+                 dst++;
+               }
+           }
+ 
+         } else {
+           dst += rle_this_bite*2;
+         }
+       }
+       
+       x += rle_this_bite;
+     }
+     
+     dst_y += dst_pitch;
+   }
+ }
+ 
+ 
+ static void
+ _overlay_blend(vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t 
*vo_overlay)
+ {
+     buffer_driver_t *this = (buffer_driver_t *)this_gen;
+     buffer_frame_t *frame = (buffer_frame_t *)frame_gen;
+ 
+     printf("buffer_overlay_blend: format=%d overlay=%x\n", frame->format, 
vo_overlay);
+     if (frame->format == XINE_IMGFMT_YV12)
+        _overlay_blend_yuv(frame->vo_frame.base, vo_overlay,
+                       frame->width, frame->height,
+                       frame->vo_frame.pitches);
+     else
+        _overlay_blend_yuy2(frame->vo_frame.base[0], vo_overlay,
+                       frame->width, frame->height,
+                       frame->vo_frame.pitches[0]);
+ }
+ 
+ 
  static vo_info_t buffer_vo_info = {
      1,



-------------------------------------------------------
SF.Net email is sponsored by: Discover Easy Linux Migration Strategies
from IBM. Find simple to follow Roadmaps, straightforward articles,
informative Webcasts and more! Get everything you need to get up to
speed, fast. http://ads.osdn.com/?ad_id=7477&alloc_id=16492&op=click
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to