Author: tack
Date: Tue May 29 02:22:19 2007
New Revision: 2695

Modified:
   trunk/xine/src/drivers/kaa.c
   trunk/xine/src/drivers/video_out_kaa.c
   trunk/xine/src/drivers/video_out_kaa.h
   trunk/xine/src/xine.c

Log:
Completely revamp frame notification feature of kaa driver: no longer
does colorspace conversion or scaling (which sucked anyway), notifies frame
delivery via fifo; creates new shmem buffers on demand; support for multiple
frame buffers.


Modified: trunk/xine/src/drivers/kaa.c
==============================================================================
--- trunk/xine/src/drivers/kaa.c        (original)
+++ trunk/xine/src/drivers/kaa.c        Tue May 29 02:22:19 2007
@@ -1,5 +1,8 @@
+
 #include "kaa.h"
 #include "video_out_kaa.h"
+#include <sys/shm.h>
+#include <sys/ipc.h>
 #include <malloc.h>
 #include "../config.h"
 
@@ -9,9 +12,14 @@
     #define YUY2_SIZE_THRESHOLD   2000*2000
 #endif
 
+#define NUM_FRAME_BUFFERS 3
 
 typedef struct _kaa_vo_user_data {
     driver_info_common common;
+
+    driver_info_common *passthrough_driver_info;
+
+    // OSD
     PyObject *osd_configure_cb,
              *passthrough_pyobject;
     void *passthrough_visual;
@@ -20,19 +28,36 @@
     uint8_t *yv12_planes[3];
     int yv12_strides[3];
 
-    yuv2rgb_factory_t *yuv2rgb_factory;
-    uint8_t *frame_buffer;
-    int do_notify_frame, notify_frame_width, notify_frame_height;
-    driver_info_common *passthrough_driver_info;
+    // Frame notification
+    //yuv2rgb_factory_t *yuv2rgb_factory;
+    uint8_t *shmem, *buffers[NUM_FRAME_BUFFERS];
+    int do_notify_frame, notify_fd, shm_id, cur_buffer_idx, buffer_size;
+
+    // Not used right now.
+    int notify_frame_width, notify_frame_height;
 
 } kaa_vo_user_data;
 
 typedef struct _kaa_frame_user_data {
-
-    yuv2rgb_t *yuv2rgb;
+    //yuv2rgb_t *yuv2rgb;
 } kaa_frame_user_data;
 
 
+typedef struct {
+    uint8_t lock;
+    uint16_t width, height, stride;
+    double aspect;
+} buffer_header_t;
+
+typedef struct {
+    uint32_t shm_id;
+    uint32_t offset;
+    char padding[8];
+} notify_packet_t;
+
+
+#if 0
+
 static void
 _alloc_yv12(kaa_vo_user_data *user_data, int width, int height)
 {
@@ -114,14 +139,129 @@
         }
     }
 }
+#endif 
+
+static int
+setup_shmem(kaa_vo_user_data *user_data, int stride, int height)
+{   
+    int i;
+
+    if (user_data->shm_id) {
+        struct shmid_ds shmemds; 
+        shmctl(user_data->shm_id, IPC_RMID, &shmemds);
+        shmdt(user_data->shmem);
+    }
+    user_data->buffer_size = 32 + stride*height*2;
+    user_data->shm_id = shmget(IPC_PRIVATE, user_data->buffer_size * 
NUM_FRAME_BUFFERS, IPC_CREAT | 0600);
+    if (user_data->shm_id == -1) 
+        // TODO: get this error back into python space
+        return -1;
+
+    user_data->shmem = shmat(user_data->shm_id, NULL, 0);
+    for (i = 0; i < NUM_FRAME_BUFFERS; i++) {
+        user_data->buffers[i] = user_data->shmem + user_data->buffer_size * i;
+        *user_data->buffers[i] = 0;
+    }
+    user_data->cur_buffer_idx = 0;
+    //printf("[buffer] h=%d stride=%d shmid=%d\n", height, stride, 
user_data->shm_id);
+    return 0;
+}
+
+static inline int
+wait_for_buffer(uint8_t *lock, float max_wait)
+{ 
+    struct timeval curtime;
+    double start, now;
+
+    gettimeofday(&curtime, NULL);
+    start = now = curtime.tv_sec + (curtime.tv_usec/(1000.0*1000));
+    while (*lock && now - start < max_wait) {
+        gettimeofday(&curtime, NULL);
+        now = curtime.tv_sec + (curtime.tv_usec/(1000.0*1000));
+        usleep(1);
+    }
+    return *lock == 0;
+} 
+
+
+static long long 
+get_usecs(void)
+{
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    return (long long)((tv.tv_sec * 1000000.0) + tv.tv_usec);
+}
 
 static int
 handle_frame_cb(int cmd, vo_frame_t *frame, void **frame_user_data_gen, void 
*data)
 {
     kaa_vo_user_data *user_data = (kaa_vo_user_data *)data;
-    kaa_frame_user_data *frame_user_data = *(kaa_frame_user_data 
**)frame_user_data_gen;
+    //kaa_frame_user_data *frame_user_data = *(kaa_frame_user_data 
**)frame_user_data_gen;
+
+    if (cmd == KAA_VO_HANDLE_FRAME_DISPLAY_PRE_OSD && 
user_data->do_notify_frame) {
+        uint8_t *lock, *y_dst, *u_dst, *v_dst;
+        int last_idx = user_data->cur_buffer_idx > 0 ? 
user_data->cur_buffer_idx - 1 : NUM_FRAME_BUFFERS - 1,
+            stride = (frame->format == XINE_IMGFMT_YUY2) ? frame->pitches[0] 
>> 1: frame->pitches[0];
+
+        if (32 + stride*frame->height*2 > user_data->buffer_size)
+            setup_shmem(user_data, stride, frame->height);
+
+        notify_packet_t notify = {
+            .shm_id = user_data->shm_id,
+            .offset = user_data->buffers[user_data->cur_buffer_idx] - 
user_data->buffers[0]
+        };
+
+        buffer_header_t header = {
+            .lock = 0,
+            .width = frame->width,
+            .height = frame->height,
+            .stride = stride,
+            .aspect = frame->ratio
+        };
+
+        lock = user_data->buffers[user_data->cur_buffer_idx];
+        y_dst = lock + 32;
+        u_dst = y_dst + (stride * frame->height);
+        v_dst = u_dst + (stride * frame->height >> 2);
+
+        // Wait for the last buffer to be unlocked (i.e. has been rendered) 
+        // before delivering the next one.
+        if (*user_data->buffers[last_idx] && 
!wait_for_buffer(user_data->buffers[last_idx], 0.1))
+            // Buffer locked too long.
+            return 0;
+
+
+        if (frame->format == XINE_IMGFMT_YV12) {
+            //long long t0=get_usecs();
+            yv12_to_yv12(frame->base[0], frame->pitches[0], y_dst, 
frame->pitches[0],
+                         frame->base[1], frame->pitches[1], u_dst, 
frame->pitches[1],
+                         frame->base[2], frame->pitches[2], v_dst, 
frame->pitches[2],
+                         frame->width, frame->height);
+             //printf("YV12 Convert: %d\n", get_usecs()-t0);
+        } else if (frame->format == XINE_IMGFMT_YUY2 ) {
+            //long long t0=get_usecs();
+            yuy2_to_yv12(frame->base[0], frame->pitches[0], 
+                         y_dst, stride, u_dst, stride >> 1, v_dst, stride >> 1,
+                         frame->width, frame->height);
+            //printf("YUY2 Convert: %d\n", get_usecs()-t0);
+        } else {
+            printf("Unknown frame format!\n");
+            return 0;
+        }
+
+        memcpy(user_data->buffers[user_data->cur_buffer_idx], &header, 
sizeof(header));
+        *lock = 1;
+        write(user_data->notify_fd, &notify, sizeof(notify));
+        fsync(user_data->notify_fd);
+        user_data->cur_buffer_idx++;
+        if (user_data->cur_buffer_idx == NUM_FRAME_BUFFERS)
+            user_data->cur_buffer_idx = 0;
+    }
 
+#if 0
     switch (cmd) {
+        case KAA_VO_HANDLE_FRAME_DISPLAY_PRE_OSD:
+        {
         case KAA_VO_HANDLE_FRAME_ALLOC:
             *frame_user_data_gen = malloc(sizeof(kaa_frame_user_data));
             frame_user_data = *(kaa_frame_user_data **)frame_user_data_gen;
@@ -135,7 +275,6 @@
             free(*frame_user_data_gen);
             break;
 
-
         case KAA_VO_HANDLE_FRAME_DISPLAY_PRE_OSD: {
             struct { short lock, width, height; double aspect; } header = { 
.lock = 0x10 };
             struct timeval curtime;
@@ -176,6 +315,7 @@
             break;
         }
     }
+#endif
     return 0;
 }
 
@@ -217,7 +357,6 @@
     result = PyEval_CallObject(user_data->osd_configure_cb, args);
     if (result) {
         PyObject *py_osd_buffer, *py_frame_buffer = 0;
-        uint8_t *frame_buffer;
         int buflen = -1;
 
         if (!PyArg_ParseTuple(result, "Oi|O", &py_osd_buffer, 
buffer_stride_return, &py_frame_buffer))
@@ -229,10 +368,9 @@
             PyErr_Format(PyExc_ValueError, "OSD buffer is not big enough");
             goto bail;
         }
-
+/*
         if (py_frame_buffer && (frame_buffer = 
_get_ptr_from_pyobject(py_frame_buffer, &buflen)))
             user_data->frame_buffer = frame_buffer;
-/*
         if (buflen != -1 && buflen < width * height * 4) {
             PyErr_Format(PyExc_ValueError, "Frame buffer is not big enough");
             goto bail;
@@ -353,12 +491,17 @@
     if (user_data->passthrough_visual)
         free(user_data->passthrough_visual);
 
-    user_data->yuv2rgb_factory->dispose(user_data->yuv2rgb_factory);
+    //user_data->yuv2rgb_factory->dispose(user_data->yuv2rgb_factory);
      for (i = 0; i < 3; i++) {
          if (user_data->yv12_planes[i])
              free(user_data->yv12_planes[i]);
      }
 
+    if (user_data->shm_id) {
+        struct shmid_ds shmemds; 
+        shmctl(user_data->shm_id, IPC_RMID, &shmemds);
+        shmdt(user_data->shmem);
+    }
 
     free(user_data);
 }
@@ -371,11 +514,10 @@
     kaa_visual_t vis;
     vo_driver_t *passthrough_driver;
     kaa_vo_user_data *user_data;
-    PyObject *o, *passthrough = NULL, *control_return = NULL, 
-             *osd_configure_cb_pyobject = NULL;
+    PyObject *o, *passthrough = NULL, *control_return = NULL, 
*osd_configure_cb_pyobject = NULL;
     void *passthrough_visual;
     driver_info_common *passthrough_driver_info;
-    int passthrough_visual_type;
+    int passthrough_visual_type, notify_fd = -1;
 
     passthrough = PyDict_GetItemString(kwargs, "passthrough");
     if (!passthrough || !PyString_Check(passthrough)) {
@@ -400,7 +542,6 @@
     }
 
     memset(&vis, 0, sizeof(vis));
-    vis.osd_configure_cb        = osd_configure_cb;
     vis.passthrough_driver      = PyString_AsString(passthrough);
     vis.passthrough_visual_type = passthrough_visual_type;
     vis.passthrough_visual      = passthrough_visual;
@@ -414,6 +555,7 @@
     }
 
     if (PyMapping_HasKeyString(kwargs, "osd_configure_cb")) {
+        vis.osd_configure_cb = osd_configure_cb;
         o = PyDict_GetItemString(kwargs, "osd_configure_cb");
         if (!PyCallable_Check(o)) {
             PyErr_Format(PyExc_ValueError, "osd_configure_cb must be 
callable");
@@ -423,6 +565,15 @@
         Py_INCREF(o);
     }
 
+    if (PyMapping_HasKeyString(kwargs, "notify_fd")) {
+        o = PyDict_GetItemString(kwargs, "notify_fd");
+        if (!PyNumber_Check(o)) {
+            PyErr_Format(PyExc_ValueError, "notify_fd must be an integer (file 
descriptor)");
+            return 0;
+        }
+        notify_fd = PyLong_AsLong(o);
+    }
+
     Py_INCREF(passthrough);
 
     user_data = malloc(sizeof(kaa_vo_user_data));
@@ -435,7 +586,8 @@
     user_data->notify_frame_width      = -1;
     user_data->notify_frame_height     = -1;
     user_data->do_notify_frame         = 0;
-    user_data->yuv2rgb_factory         = yuv2rgb_factory_init(MODE_32_RGB, 0, 
NULL);
+    user_data->notify_fd               = notify_fd;
+    //user_data->yuv2rgb_factory         = yuv2rgb_factory_init(MODE_32_RGB, 
0, NULL);
 
     vis.osd_configure_cb_data = user_data;
     vis.handle_frame_cb_data  = user_data;

Modified: trunk/xine/src/drivers/video_out_kaa.c
==============================================================================
--- trunk/xine/src/drivers/video_out_kaa.c      (original)
+++ trunk/xine/src/drivers/video_out_kaa.c      Tue May 29 02:22:19 2007
@@ -51,7 +51,7 @@
 extern int (*glXGetVideoSyncSGI)(unsigned int *);
 #endif
 
-static long long get_usecs()
+static long long get_usecs(void)
 {
     struct timeval tv;
     gettimeofday(&tv, NULL);
@@ -110,7 +110,7 @@
            V_R[256], V_G[256], V_B[256];
 
 static void
-init_rgb2yuv_tables()
+init_rgb2yuv_tables(void)
 {
     int i;
     #define myround(n) (n >= 0) ? (int)(n + 0.5) : (int)(n - 0.5);
@@ -943,14 +943,17 @@
                 } else if (glXGetVideoSyncSGI(&count) == 0) {
                     // We know display refresh rate and current retrace 
counter.
                     float multiple = frame_gen->duration / 
(float)this->vsync_duration;
+                    int n_multiple = (int)roundf(multiple);
                     unsigned int dummy;
-                    if (fabs(roundf(multiple) - multiple) < 0.02 && count - 
this->last_vsync_count == 1) {
+                    //fprintf(stderr, "vsync: %f (%d / %d) tolerance = %f 
%d\n", fabs(roundf(multiple) - multiple), frame_gen->duration, 
this->vsync_duration, 0.02 * n_multiple, this->last_vsync_count);
+                    if (fabs(roundf(multiple) - multiple) < 0.02 * n_multiple 
&& count - this->last_vsync_count == n_multiple) {
                         /* Frame duration looks pretty damn close to a multiple
                          * of the display refresh rate, and our last frame was
                          * exactly 1 refresh ago, so let's wait for next 
                          * refresh.
                          */
                         ret = glXWaitVideoSyncSGI(2, (count+1)%2, &dummy);
+                        //fprintf(stderr, "Waiting\n");
                     }
                     this->last_vsync_count = count;
                 }
@@ -1092,7 +1095,6 @@
     kaa_driver_t *this = (kaa_driver_t *)this_gen;
 
     //printf("kaa_dispose\n");
-    //this->yuv2rgb_factory->dispose(this->yuv2rgb_factory);
     free_overlay_data(this);
     pthread_mutex_destroy(&this->lock);
     pthread_mutex_destroy(&this->osd_buffer_lock);

Modified: trunk/xine/src/drivers/video_out_kaa.h
==============================================================================
--- trunk/xine/src/drivers/video_out_kaa.h      (original)
+++ trunk/xine/src/drivers/video_out_kaa.h      Tue May 29 02:22:19 2007
@@ -33,9 +33,6 @@
 #include <xine/video_out.h>
 #include <xine/xine_internal.h>
 #include <xine/alphablend.h>
-#include "yuv2rgb.h"
-
-
 
 #ifdef HAVE_OPENGL_VSYNC
 #include <X11/Xlib.h>

Modified: trunk/xine/src/xine.c
==============================================================================
--- trunk/xine/src/xine.c       (original)
+++ trunk/xine/src/xine.c       Tue May 29 02:22:19 2007
@@ -715,7 +715,7 @@
 
 
 void
-init_xine()
+init_xine(void)
 {
     PyObject *m;
 #ifdef HAVE_X11

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to