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