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, ¬ify, 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