Author: tack
Date: Tue May 29 02:49:35 2007
New Revision: 2696

Added:
   trunk/popcorn/patches/vo_export-WIP-2007-05-28.patch

Log:
Mplayer patch to export video via shared memory with notification via fifo.
This is the protocol implemented in test/render_manager.py


Added: trunk/popcorn/patches/vo_export-WIP-2007-05-28.patch
==============================================================================
--- (empty file)
+++ trunk/popcorn/patches/vo_export-WIP-2007-05-28.patch        Tue May 29 
02:49:35 2007
@@ -0,0 +1,309 @@
+Index: libvo/Makefile
+===================================================================
+--- libvo/Makefile     (revision 23385)
++++ libvo/Makefile     (working copy)
+@@ -10,6 +10,7 @@
+                vo_mpegpes.c \
+                vo_null.c \
+                vo_yuv4mpeg.c \
++               vo_export.c \
+                $(VO_SRCS) \
+ 
+ SRCS_MPLAYER-$(VIDIX)          +=  vosub_vidix.c
+Index: libvo/video_out.c
+===================================================================
+--- libvo/video_out.c  (revision 23385)
++++ libvo/video_out.c  (working copy)
+@@ -142,6 +142,9 @@
+ #ifdef HAVE_MD5SUM
+ extern vo_functions_t video_out_md5sum;
+ #endif
++#ifdef HAVE_SHM
++extern vo_functions_t video_out_export;
++#endif
+ 
+ vo_functions_t* video_out_drivers[] =
+ {
+@@ -268,6 +271,9 @@
+ #ifdef HAVE_MD5SUM
+     &video_out_md5sum,
+ #endif
++#ifdef HAVE_SHM
++        &video_out_export,
++#endif
+         NULL
+ };
+ 
+Index: libvo/vo_export.c
+===================================================================
+--- libvo/vo_export.c  (revision 0)
++++ libvo/vo_export.c  (revision 0)
+@@ -0,0 +1,268 @@
++/* Why VO:
++ *   1. Delay between draw frame and flip page.
++ *   2. Video codec selection is based on VO support, not VF support.
++ *   3. OSD?
++ */
++
++#include "config.h"
++#ifdef HAVE_SHM
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <errno.h>
++#include <sys/shm.h>
++#include <sys/ipc.h>
++#include <sys/time.h>
++#include <fcntl.h>
++
++#include "mp_msg.h"
++#include "help_mp.h"
++#include "video_out.h"
++#include "video_out_internal.h"
++#include "fastmemcpy.h"
++
++#define NUM_BUFFERS 5
++
++vo_functions_t *vo_passthrough = NULL;
++
++static vo_info_t info = 
++{
++      "Export video to shared memory buffer and notify of frame delivery via 
fifo",
++      "export",
++      "Jason Tackaberry <[EMAIL PROTECTED]>",
++      ""
++};
++
++LIBVO_EXTERN(export)
++
++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;
++
++
++
++static uint32_t mpi_w, mpi_h, mpi_stride;
++static double mpi_aspect;
++static int shm_id = 0, cur_buffer_idx, fd_notify, needs_draw;
++static uint8_t *shmem, *buffers[NUM_BUFFERS];
++
++static int
++setup_shmem(int w, int stride)
++{
++    int i;
++    if (shm_id) {
++        struct shmid_ds shmemds;
++        shmctl(shm_id, IPC_RMID, &shmemds);
++        shmdt(shmem); 
++    }
++      mpi_w = w;
++    mpi_stride = stride;
++    shm_id = shmget(IPC_PRIVATE, (32 + mpi_w*mpi_h*2) * NUM_BUFFERS, 
IPC_CREAT | 0600);
++    if (shm_id == -1) {
++        mp_msg(MSGT_VO, MSGL_FATAL, "Couldn't create shmem segment");
++        return -1;
++    }
++    shmem = shmat(shm_id, NULL, 0);
++    for (i = 0; i < NUM_BUFFERS; i++) {
++        buffers[i] = shmem + (32 + mpi_w*mpi_h*2)*i;
++        *buffers[i] = 0;
++    }
++    cur_buffer_idx = 0;
++    printf("[buffer] w=%d h=%d stride=%d shmid=%d\n", mpi_w, mpi_h, 
mpi_stride, 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));
++        usec_sleep(1);
++    }
++    return *lock == 0;
++}
++
++
++static inline void
++write_buffer(uint8_t *img[], int stride[], int w, int h, int x, int y, int 
n_planes)
++{
++    uint8_t *lock, *buf;
++    int i, shift;
++
++    if (!shm_id)
++        setup_shmem(w, stride[0]);
++
++    lock = buffers[cur_buffer_idx];
++    buf = lock + 32;
++    for (i = 0, shift = 0; i < n_planes; i++, shift = 1) {
++        memcpy_pic(buf + ((y * stride[i]) >> shift) + (x >> shift), img[i], 
++                   w >> shift, h >> shift, stride[i], stride[i]);
++        buf += (stride[i] * mpi_h) >> shift;
++    }
++    needs_draw = 0;
++}
++
++static int draw_slice(uint8_t *image[], int stride[], int w,int h,int x,int y)
++{
++    write_buffer(image, stride, w, h, x, y, 3);
++    vo_passthrough->draw_slice(image, stride, w, h, x, y);
++    return VO_TRUE;
++}
++
++static void draw_alpha_yv12(int x0, int y0, int w, int h,
++                            unsigned char *src, unsigned char *srca,
++                            int stride)
++{
++    uint8_t *buf = buffers[cur_buffer_idx] + 32;
++    buf += y0 * mpi_stride + x0;
++    vo_draw_alpha_yv12(w, h, src, srca, stride, buf, mpi_stride);
++}
++
++static void draw_osd(void)
++{
++    vo_draw_text(mpi_w, mpi_h, draw_alpha_yv12);
++    return vo_passthrough->draw_osd();
++}
++
++static void
++flip_page(void)
++{
++    notify_packet_t notify = {
++        .shm_id = shm_id,
++        .offset = buffers[cur_buffer_idx] - buffers[0]
++    };
++
++    int last_idx = cur_buffer_idx > 0 ? cur_buffer_idx - 1 : NUM_BUFFERS - 1;
++    if (*buffers[last_idx] && !wait_for_buffer(buffers[last_idx], 0.05))
++        printf("[buffer] last buffer locked too long\n");
++    else {
++        *buffers[cur_buffer_idx] = 1;
++        write(fd_notify, &notify, sizeof(notify));
++        fsync(fd_notify);
++    }
++
++    vo_passthrough->flip_page();
++    cur_buffer_idx++;
++    if (cur_buffer_idx == NUM_BUFFERS)
++        cur_buffer_idx = 0;
++
++    needs_draw = 1;
++}
++
++static int
++draw_frame(uint8_t *src[])
++{
++    mp_msg(MSGT_VO,MSGL_INFO, MSGTR_LIBVO_XV_DrawFrameCalled);
++    return -1;
++}
++
++static int
++config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, 
uint32_t flags, char *title, uint32_t format)
++{
++    mpi_h = height;
++    mpi_aspect = (double)d_width / d_height;
++
++    needs_draw = 1;
++    vo_passthrough->config(width, height, d_width, d_height, flags, title, 
format);
++      return 0;
++}
++
++static void
++uninit(void)
++{
++    struct shmid_ds shmemds;
++    vo_passthrough->uninit();
++
++    shmctl(shm_id, IPC_RMID, &shmemds);
++    shmdt(shmem); 
++}
++
++
++static void check_events(void)
++{
++    vo_passthrough->check_events();
++}
++
++static int preinit(const char *arg)
++{
++    char *vo_list[2] = {NULL, NULL}, *p;
++    if (!arg || !strstr(arg, ":")) {
++        mp_msg(MSGT_VO, MSGL_FATAL,
++               "\n-vo export command line help:\n"
++               "   -vo export:fifo:subvo[:subvo options]\n"
++               "Example: mplayer -vo export:/tmp/vo_buffer.fifo:xv:port=87\n"
++               "\n");
++        return -1;
++    }
++
++    p = strstr(arg, ":");
++    vo_list[0] = p + 1;
++    *p = 0;
++
++    if ((fd_notify = open(arg, O_RDWR | O_NONBLOCK)) < 0) {
++        mp_msg(MSGT_VO, MSGL_FATAL, "Couldn't open fifo %s\n", arg);
++        return -1;
++    }
++
++    vo_passthrough  = init_best_video_out(vo_list);
++    if (!vo_passthrough) {
++        mp_msg(MSGT_VO,MSGL_WARN, MSGTR_LIBVO_NULL_UnknownSubdevice,arg);
++        return ENOSYS;
++    }
++
++    return 0;
++}
++
++static int control(uint32_t request, void *data, ...)
++{
++    va_list ap;
++    void *arg;
++    // TODO: override getimage for DRI (if mode is buffer only)
++    switch (request) {
++        case VOCTRL_QUERY_FORMAT:
++            if (*((uint32_t *) data) != IMGFMT_YV12)
++                return 0;
++            return vo_passthrough->control(request, data, arg) | VFCAP_OSD | 
VFCAP_FLIP;
++
++        case VOCTRL_DRAW_IMAGE:
++        {
++            mp_image_t *mpi = (mp_image_t *)data;
++            buffer_header_t header = {
++                .lock = 0,
++                .width = mpi->w,
++                .height = mpi->h,
++                .stride = mpi->stride[0],
++                .aspect = mpi_aspect
++            };
++
++            if (!shm_id)
++                setup_shmem(mpi->w, mpi->stride[0]);
++
++            if (needs_draw && (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK) == 0)
++                write_buffer(mpi->planes, mpi->stride, mpi->w, mpi->h, 0, 0, 
mpi->num_planes);
++
++            memcpy(buffers[cur_buffer_idx], &header, sizeof(header));
++            vo_passthrough->control(request, data, arg);
++            return VO_TRUE;
++        }
++    }
++    va_start(ap, data);
++    arg = va_arg(ap, void *);
++    va_end(ap);
++    return vo_passthrough->control(request, data, arg);
++}
++#endif

-------------------------------------------------------------------------
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