--- main.current/libmpcodecs/vf_bmovl2.c 1969-12-31 19:00:00.000000000 -0500 +++ main/libmpcodecs/vf_bmovl2.c 2003-10-20 00:30:26.000000000 -0400 @@ -0,0 +1,521 @@ +/* vf_bmovl2.c - BitMap OVerLay videofilter for MPlayer - Take 2 + * + * (C) 2003 Jason Tackaberry + * Large portions of code taken from vf_bmovl.c which is + * (C) 2002 Per Wigren + * Licenced under the GNU General Public License + * + * Use MPlayer as a framebuffer to read bitmaps and commands from a FIFO + * and display them in the window. + * + * + * You can store up to 10 (or NUM_IMAGES) images where each image is + * referenced by an integer id. Then you can perform operations on these + * images, like moving, adjusting alpha, toggling visibility, etc. + * + * This filter takes one argument: the filename of the fifo from which + * to read commands. e.g. -vf bmovl2=/tmp/mplayer.fifo + * + * Commands are: + * + * RAWIMG id format w h reset + * - Stores an image in the given id. format can be any combination of + * either RGBA or RGB. For example, these are all valid formats: RGBA, + * RBGA, ARGB, ABGR, RGB, GBR, etc. w and h are the width and height of + * the image. reset specifies whether or not to reset the other data + * associated with this image id: x, y coordinates, alpha level, + * visibility, and z-index. If reset is 1, these values are reset, + * otherwise they are left alone. + * - This command is followed by w*h*bpp bytes of data. If format is a + * combination of letters RGB, then bpp is 3; if format is a combination + * of RGBA, bpp is 4. + * + * VISIBLE id visibility + * - Sets visibility of the specified image referenced by id. visibility is + * 0 to hide, or 1 to show. + * + * MOVE id x y + * - Move the image with id to coordinates x, y + * + * ALPHA id alpha + * - Sets the transparency of the image to alpha, where 0 <= alpha <= 255, 0 + * being fully transparent and 255 being fully opaque. This value is + * multiplied with the alpha channel of each individual pixel in the + * image. So if a pixel has an alpha of 100 and the image has an alpha + * of 128 (as set by this command), the resulting pixel will have an + * alpha of 50. + * + * ZINDEX id zindex + * - Sets the z-index (layer) of the specified image. The z-index is an + * arbitrary integer. The lower the z-index the closer to the background + * (i.e. movie) the image is displayed. + * + * ATOM + * - Indicate the operations that follow until an ENDATOM command is + * reached are atomic -- that is, they will be all be evaluated before + * the next frame is drawn. This allows you to, for example, movie + * an image to a new position and change its alpha channel in between + * frames. + * + * ENDATOM + * - End the list of operations and render the frame (or more accurately, + * pass control to the next video filter). + * + */ + +#ifndef HAVE_NO_POSIX_SELECT + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mp_image.h" +#include "vf.h" +#include "img_format.h" +#include "../config.h" + +#include "../mp_msg.h" +#include "../libvo/fastmemcpy.h" +#include "../libvo/video_out.h" +#include "../input/input.h" + +#define NUM_IMAGES 10 +#define FALSE 0 +#define TRUE !FALSE + +#define rgb2y(R,G,B) ( (( 263*R + 516*G + 100*B) >> 10) + 16 ) +#define rgb2u(R,G,B) ( ((-152*R - 298*G + 450*B) >> 10) + 128 ) +#define rgb2v(R,G,B) ( (( 450*R - 376*G - 73*B) >> 10) + 128 ) + +#define CMD_RAWIMG 0x100 +#define CMD_ALPHA 0x101 +#define CMD_VISIBLE 0x102 +#define CMD_MOVE 0x103 +#define CMD_ZINDEX 0x104 + +struct vf_priv_s { + struct { + unsigned char *y, *u, *v, *a; + int left, top, w, h, zindex, alpha, visible; + } images[NUM_IMAGES]; + int img_order[NUM_IMAGES]; + int stream_fd; + int mpi_width, mpi_height; +}; + +vf_instance_t* vf_bmovl2 = NULL; +mp_image_t* pause_mpi = NULL; + +static int pause_state; +static struct vf_priv_s *vf_bmovl2_priv; +static int cmd_filter(mp_cmd_t* cmd, int paused, struct vf_priv_s *priv); +static int put_image(struct vf_instance_s* vf, mp_image_t* mpi); + +inline static void copy_mpi(mp_image_t *dmpi, mp_image_t *mpi) +{ + if (mpi->flags&MP_IMGFLAG_PLANAR) { + memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w, mpi->h, dmpi->stride[0],mpi->stride[0]); + memcpy_pic(dmpi->planes[1], mpi->planes[1], mpi->chroma_width, mpi->chroma_height, dmpi->stride[1], mpi->stride[1]); + memcpy_pic(dmpi->planes[2], mpi->planes[2], mpi->chroma_width, mpi->chroma_height, dmpi->stride[2], mpi->stride[2]); + } else { + memcpy_pic(dmpi->planes[0], mpi->planes[0], mpi->w*(dmpi->bpp/8), mpi->h, dmpi->stride[0], mpi->stride[0]); + } +} + +void vf_bmovl2_pause_update(vo_functions_t *video_out) +{ + if (vf_bmovl2 && put_image(vf_bmovl2, pause_mpi)) + video_out->flip_page(); +} + + +static int +query_format(struct vf_instance_s* vf, unsigned int fmt) +{ + if (fmt == IMGFMT_YV12) + return VFCAP_CSP_SUPPORTED; + return 0; +} + + +static int +config(struct vf_instance_s* vf, + int width, int height, int d_width, int d_height, + unsigned int flags, unsigned int outfmt) +{ + if (!vf_bmovl2) { + int i; + // Default image order (all z-indexes are 0) + for (i = 0; i < NUM_IMAGES; i++) + vf->priv->img_order[i] = i; + memset(vf->priv->images, 0, sizeof(vf->priv->images)); + } + vf->priv->mpi_width = width; + vf->priv->mpi_height = height; + vf_bmovl2 = vf; + return vf_next_config(vf, width, height, d_width, d_height, flags, outfmt); +} + +inline static int +check_fifo(int fd) +{ + struct timeval tv; + fd_set fdset; + + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + tv.tv_sec = tv.tv_usec = 0; + return select(fd + 1, &fdset, NULL, NULL, &tv); +} + + +inline static int +read_cmd(int fd, char *cmd, char *args) +{ + char *p = cmd, *start = cmd, maxlen = 20; + *args = 0; + while (read(fd, p, 1)) { + if (*p == ' ' && start == cmd) { + *p = 0; + p = start = args; + maxlen = 100; + } + else if (*p == '\n' || p - start > maxlen) { *p = 0; return TRUE; } + else p++; + } + return FALSE; +} + +inline static int +handle_commands(struct vf_priv_s* priv) +{ + int is_atomic = FALSE, res, command; + char cmd[20], args[100]; + unsigned char *buffer = NULL; + + do { + res = check_fifo(priv->stream_fd); + if (res == 0) { + if (is_atomic) + usleep(10000); + else + return FALSE; + } else if(res < 0) { + mp_msg(MSGT_VFILTER, MSGL_WARN, "\nvf_bmovl2: Error %d in fifo: %s\n\n", errno, strerror(errno)); + return FALSE; + } + + // If we're here it means there's a command in the fifo + if(!read_cmd(priv->stream_fd, cmd, args)) { + mp_msg(MSGT_VFILTER, MSGL_ERR, "\nvf_bmovl: Error reading commands: %s\n\n", strerror(errno)); + return FALSE; + } + + command = 0; + if (strncmp(cmd, "RAWIMG", 6) == 0) command = CMD_RAWIMG; + if (strncmp(cmd, "ALPHA", 5) == 0) command = CMD_ALPHA; + if (strncmp(cmd, "VISIBLE", 7) == 0) command = CMD_VISIBLE; + if (strncmp(cmd, "MOVE", 4) == 0) command = CMD_MOVE; + if (strncmp(cmd, "ZINDEX", 6) == 0) command = CMD_ZINDEX; + if (strncmp(cmd, "ATOM", 4) == 0) is_atomic = TRUE; + if (strncmp(cmd, "ENDATOM", 7) == 0) break; + + switch (command) { + + case CMD_ZINDEX: { // ZINDEX img_id zindex + int id, zindex, i, j; + sscanf(args, "%d %d", &id, &zindex); + if (id < 0 || id > 20) { + mp_msg(MSGT_VFILTER, MSGL_ERR, "\nvf_bmovl2: CMD_ALPHA: image id out of range (%d)\n", id); + break; + } + priv->images[id].zindex = zindex; + + // Figure out which order we blit the images based on zindex + for (i = 0; i < NUM_IMAGES - 1; i++) { + int pos = i; + for (j = i + 1; j < NUM_IMAGES; j++) + if (priv->images[priv->img_order[j]].zindex < + priv->images[priv->img_order[pos]].zindex) + pos = j; + if (pos != i) { + int tmp = priv->img_order[i]; + priv->img_order[i] = priv->img_order[pos]; + priv->img_order[pos] = tmp; + } + } + break; + } + + case CMD_MOVE: { // MOVE img_id x y + int id, x, y; + sscanf(args, "%d %d %d", &id, &x, &y); + if (id < 0 || id > 20) { + mp_msg(MSGT_VFILTER, MSGL_ERR, "\nvf_bmovl2: CMD_ALPHA: image id out of range (%d)\n", id); + break; + } + priv->images[id].left = x; + priv->images[id].top = y; + break; + } + + case CMD_ALPHA: { // ALPHA img_id alpha + int id, alpha; + sscanf(args, "%d %d", &id, &alpha); + if (id < 0 || id > 20) { + mp_msg(MSGT_VFILTER, MSGL_ERR, "\nvf_bmovl2: CMD_ALPHA: image id out of range (%d)\n", id); + break; + } + priv->images[id].alpha = alpha; + break; + } + + case CMD_VISIBLE: { // VISIBLE img_id flag + int id, visible; + sscanf(args, "%d %d", &id, &visible); + if (id < 0 || id > 20) { + mp_msg(MSGT_VFILTER, MSGL_ERR, "\nvf_bmovl2: CMD_VISIBL: image id out of range (%d)\n", id); + break; + } + priv->images[id].visible = visible; + break; + } + + case CMD_RAWIMG: { // RAWIMG img_id format w h reset + char format[5], *imgbuf; + int id, w = 0, h = 0, reset = 0, bpp, i, + r_pos, g_pos, b_pos, a_pos; + + sscanf(args, "%d %s %d %d %d", &id, &format, &w, &h, &reset); + if (id < 0 || id > 20) { + mp_msg(MSGT_VFILTER, MSGL_ERR, "\nvf_bmovl2: CMD_RAWIMG: image id out of range (%d)\n", id); + break; + } + bpp = strlen(format); + if (bpp != 3 && bpp != 4) { + mp_msg(MSGT_VFILTER, MSGL_ERR, "\nvf_bmovl2: CMD_RAWIMG: invalid image format\n"); + break; + } + imgbuf = malloc(w * h * bpp); + if(!imgbuf) { + mp_msg(MSGT_VFILTER, MSGL_WARN, "\nvf_bmovl2: CMD_RAWIMG: couldn't allocate temp buffer (%d bytes)\n", w * h * bpp); + break; + } + int bytes = read(priv->stream_fd, imgbuf, w * h * bpp); + if (bytes != w * h * bpp) { + mp_msg(MSGT_VFILTER, MSGL_WARN, "\nvf_bmovl2: CMD_RAWIMG: image too short\n"); + free(imgbuf); + break; + } + + for (i = 0; i < bpp; i++) { + switch (format[i]) { + case 'R': r_pos = i; break; + case 'G': g_pos = i; break; + case 'B': b_pos = i; break; + case 'A': a_pos = i; break; + } + } + + // Free memory of an existing image + if (priv->images[id].y) { + free(priv->images[id].y); + free(priv->images[id].u); + free(priv->images[id].v); + free(priv->images[id].a); + } + // Allocate memory for new image + priv->images[id].y = malloc(w * h); + priv->images[id].u = malloc(w * h / 4); + priv->images[id].v = malloc(w * h / 4); + priv->images[id].a = malloc(w * h); + priv->images[id].w = w; + priv->images[id].h = h; + + // Convert the image to YUV + int buf_x, buf_y; + for (buf_y = 0; buf_y < h; buf_y++) { + for (buf_x = 0; buf_x < w * bpp; buf_x += bpp) { + int buf_pos = (buf_y * w * bpp) + buf_x, + img_pos = (buf_y * w) + (buf_x / bpp); + unsigned char r = imgbuf[buf_pos + r_pos], + g = imgbuf[buf_pos + g_pos], + b = imgbuf[buf_pos + b_pos], + a = (bpp == 4) ? imgbuf[buf_pos + a_pos] : 0xFF; + + priv->images[id].y[img_pos] = rgb2y(r, g, b); + priv->images[id].a[img_pos] = a; + + if((buf_y % 2) && ((buf_x / bpp) % 2)) { + img_pos = ((buf_y / 2) * (w / 2)) + (buf_x / bpp / 2); + priv->images[id].u[img_pos] = rgb2u(r, g, b); + priv->images[id].v[img_pos] = rgb2v(r, g, b); + } + } + } + if (reset) { + priv->images[id].visible = TRUE; + priv->images[id].alpha = 255; + priv->images[id].left = priv->images[id].top = 0; + priv->images[id].zindex = 0; + } + free(imgbuf); + break; + } + } + } while (is_atomic); +} + + +static int +put_image(struct vf_instance_s* vf, mp_image_t* mpi) +{ + mp_image_t *dmpi; + int img_id, i, ypos, xpos, top, left; + float alpha_mod; + + if (pause_state == 1) { + pause_state = 2; + pause_mpi = vf_get_image(vf, mpi->imgfmt, MP_IMGTYPE_IP, + MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_PREFER_ALIGNED_STRIDE, + mpi->w, mpi->h); + copy_mpi(pause_mpi, mpi); + mpi = pause_mpi; + } + + dmpi = vf_get_image(vf->next, mpi->imgfmt, MP_IMGTYPE_TEMP, + MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_PREFER_ALIGNED_STRIDE, + mpi->w, mpi->h); + + copy_mpi(dmpi, mpi); + if (!handle_commands(vf->priv) && pause_state != 0) + return 0; + + for (i = 0; i < NUM_IMAGES; i++) { + img_id = vf->priv->img_order[i]; + if (vf->priv->images[img_id].visible == FALSE) + continue; + // Don't bother if the image isn't even on screen + if (vf->priv->images[img_id].top >= vf->priv->mpi_height || + vf->priv->images[img_id].left >= vf->priv->mpi_width || + vf->priv->images[img_id].left + vf->priv->images[img_id].w < 0 || + vf->priv->images[img_id].top + vf->priv->images[img_id].h < 0) + continue; + + top = vf->priv->images[img_id].top; + left = vf->priv->images[img_id].left; + alpha_mod = vf->priv->images[img_id].alpha / 255.0; + for(ypos = 0; ypos < vf->priv->images[img_id].h; ypos++) { + if (ypos + top >= vf->priv->mpi_height) break; + if (ypos + top < 0) continue; + for (xpos = 0; xpos < vf->priv->images[img_id].w; xpos++) { + int img_pos, alpha, mpi_pos; + + if (xpos + left >= vf->priv->mpi_width) break; + if (xpos + left < 0) continue; + + if (ypos + top >= vf->priv->mpi_height || xpos + left >= vf->priv->mpi_width || + ypos + top < 0 || xpos + left < 0) + continue; + + img_pos = ypos * (vf->priv->images[img_id].w) + xpos; + alpha = vf->priv->images[img_id].a[img_pos]; + if (vf->priv->images[img_id].alpha != 255) + alpha *= alpha_mod; + + if (alpha == 0) + continue; + mpi_pos = (ypos + top) * dmpi->stride[0] + (xpos + left); + + if (alpha == 255) { + dmpi->planes[0][mpi_pos] = vf->priv->images[img_id].y[img_pos]; + if ((ypos % 2) && (xpos % 2)) { + img_pos = (ypos / 2) * (vf->priv->images[img_id].w/2) + (xpos / 2); + mpi_pos = ((ypos + top) / 2) * dmpi->stride[1] + ((xpos + left) / 2); + dmpi->planes[1][mpi_pos] = vf->priv->images[img_id].u[img_pos]; + dmpi->planes[2][mpi_pos] = vf->priv->images[img_id].v[img_pos]; + } + } else { + dmpi->planes[0][mpi_pos] = + ((255 - alpha) * (int)dmpi->planes[0][mpi_pos] + + alpha * (int)vf->priv->images[img_id].y[img_pos]) >> 8; + + if ((ypos % 2) && (xpos % 2)) { + img_pos = (ypos / 2) * (vf->priv->images[img_id].w / 2) + (xpos / 2); + mpi_pos = ((ypos + top) / 2) * dmpi->stride[1] + ((xpos + left) / 2); + dmpi->planes[1][mpi_pos] = + ((255 - alpha) * (int)dmpi->planes[1][mpi_pos] + + alpha * (int)vf->priv->images[img_id].u[img_pos]) >> 8; + + dmpi->planes[2][mpi_pos] = + ((255 - alpha) * (int)dmpi->planes[2][mpi_pos] + + alpha * (int)vf->priv->images[img_id].v[img_pos]) >> 8; + } + } + } // for xpos + } // for ypos + } + return vf_next_put_image(vf, dmpi); +} + +static int +vf_open(vf_instance_t* vf, char* args) +{ + char filename[1000]; + + vf->config = config; + vf->put_image = put_image; + vf->query_format = query_format; + vf->uninit = NULL; // persistent + + if (vf_bmovl2_priv) { + vf->priv = vf_bmovl2_priv; + } + else { + vf->priv = vf_bmovl2_priv = malloc(sizeof(struct vf_priv_s)); + if(!args || sscanf(args, "%s", filename) < 1 ) { + mp_msg(MSGT_VFILTER, MSGL_ERR, "vf_bmovl2: missing fifo filename argument.\n"); + return FALSE; + } + vf->priv->stream_fd = open(filename, O_RDWR); + if (vf->priv->stream_fd < 0) + mp_msg(MSGT_VFILTER, MSGL_WARN, "vf_bmovl: Error! Couldn't open FIFO %s: %s\n", filename, strerror(errno)); + mp_input_add_cmd_filter((mp_input_cmd_filter)cmd_filter, vf->priv); + } + pause_state = 0; + return TRUE; +} + +static int cmd_filter(mp_cmd_t* cmd, int paused, struct vf_priv_s * priv) { + switch(cmd->id) { + case MP_CMD_PAUSE: + if (pause_state == 2) + pause_state = 0; + else + pause_state = 1; + break; + default: + pause_state = 0; + break; + } + return 0; +} + + + +vf_info_t vf_info_bmovl2 = { + "Read bitmaps from a FIFO and display them in window", + "bmovl2", + "Jason Tackaberry", + "", + vf_open, + NULL +}; + +#endif +// vim: ts=3 --- main.current/mplayer.c 2003-10-19 23:39:48.000000000 -0400 +++ main/mplayer.c 2003-10-20 00:26:57.000000000 -0400 @@ -332,6 +332,9 @@ static char* menu_root = "main"; #endif +#ifndef HAVE_NO_POSIX_SELECT +extern void vf_bmovl2_pause_update(vo_functions_t*); +#endif #ifdef HAVE_RTC static int nortc; @@ -2415,7 +2418,7 @@ if (audio_out && sh_audio) audio_out->pause(); // pause audio, keep data if possible - while( (cmd = mp_input_get_cmd(20,1)) == NULL) { + while( (cmd = mp_input_get_cmd(0,1)) == NULL) { if(sh_video && video_out && vo_config_count) video_out->check_events(); #ifdef HAVE_NEW_GUI if(use_gui){ @@ -2428,7 +2431,10 @@ if(vf_menu) vf_menu_pause_update(vf_menu); #endif - usec_sleep(20000); +#ifndef HAVE_NO_POSIX_SELECT + vf_bmovl2_pause_update(video_out); +#endif + usec_sleep(10000); } mp_cmd_free(cmd); osd_function=OSD_PLAY; --- main.current/libmpcodecs/vf.c 2003-10-19 23:39:51.000000000 -0400 +++ main/libmpcodecs/vf.c 2003-10-19 23:42:04.000000000 -0400 @@ -23,6 +23,7 @@ extern vf_info_t vf_info_rectangle; #ifndef HAVE_NO_POSIX_SELECT extern vf_info_t vf_info_bmovl; +extern vf_info_t vf_info_bmovl2; #endif extern vf_info_t vf_info_crop; extern vf_info_t vf_info_expand; @@ -81,6 +82,7 @@ &vf_info_rectangle, #ifndef HAVE_NO_POSIX_SELECT &vf_info_bmovl, + &vf_info_bmovl2, #endif &vf_info_crop, &vf_info_expand, --- main.current/libmpcodecs/Makefile 2003-10-19 23:39:51.000000000 -0400 +++ main/libmpcodecs/Makefile 2003-10-19 23:42:04.000000000 -0400 @@ -14,7 +14,7 @@ VIDEO_SRCS_OPT=vd_realvid.c vd_ffmpeg.c vd_dshow.c vd_dmo.c vd_vfw.c vd_vfwex.c vd_odivx.c vd_divx4.c vd_xanim.c vd_xvid.c vd_libdv.c vd_qtvideo.c vd_theora.c VIDEO_SRCS=dec_video.c vd.c $(VIDEO_SRCS_NAT) $(VIDEO_SRCS_LIB) $(VIDEO_SRCS_OPT) -VFILTER_SRCS=vf.c vf_vo.c vf_crop.c vf_expand.c vf_pp.c vf_scale.c vf_format.c vf_yuy2.c vf_flip.c vf_rgb2bgr.c vf_rotate.c vf_mirror.c vf_palette.c vf_lavc.c vf_dvbscale.c vf_cropdetect.c vf_test.c vf_noise.c vf_yvu9.c vf_rectangle.c vf_lavcdeint.c vf_eq.c vf_eq2.c vf_halfpack.c vf_dint.c vf_1bpp.c vf_bmovl.c vf_2xsai.c vf_unsharp.c vf_swapuv.c vf_il.c vf_boxblur.c vf_sab.c vf_smartblur.c vf_perspective.c vf_down3dright.c vf_field.c vf_denoise3d.c vf_hqdn3d.c vf_detc.c vf_telecine.c vf_tfields.c vf_ivtc.c vf_ilpack.c vf_dsize.c vf_decimate.c vf_softpulldown.c vf_tinterlace.c vf_pullup.c pullup.c vf_framestep.c vf_tile.c vf_delogo.c +VFILTER_SRCS=vf.c vf_vo.c vf_crop.c vf_expand.c vf_pp.c vf_scale.c vf_format.c vf_yuy2.c vf_flip.c vf_rgb2bgr.c vf_rotate.c vf_mirror.c vf_palette.c vf_lavc.c vf_dvbscale.c vf_cropdetect.c vf_test.c vf_noise.c vf_yvu9.c vf_rectangle.c vf_lavcdeint.c vf_eq.c vf_eq2.c vf_halfpack.c vf_dint.c vf_1bpp.c vf_bmovl.c vf_bmovl2.c vf_2xsai.c vf_unsharp.c vf_swapuv.c vf_il.c vf_boxblur.c vf_sab.c vf_smartblur.c vf_perspective.c vf_down3dright.c vf_field.c vf_denoise3d.c vf_hqdn3d.c vf_detc.c vf_telecine.c vf_tfields.c vf_ivtc.c vf_ilpack.c vf_dsize.c vf_decimate.c vf_softpulldown.c vf_tinterlace.c vf_pullup.c pullup.c vf_framestep.c vf_tile.c vf_delogo.c ENCODER_SRCS=ve.c ve_divx4.c ve_lavc.c ve_vfw.c ve_rawrgb.c ve_libdv.c ve_xvid.c ve_qtvideo.c ve_nuv.c NATIVE_SRCS=native/RTjpegN.c native/cinepak.c native/fli.c native/minilzo.c native/msvidc.c native/nuppelvideo.c native/qtrle.c native/qtrpza.c native/qtsmc.c native/roqav.c native/xa_gsm.c native/decode144.c native/decode288.c