mpv/libvo/vo_matrixview.c

325 lines
8.0 KiB
C

/*
* MatrixView video output driver for MPlayer
*
* by Pigeon <pigeon at pigeond.net>
*
* Based on MatrixView the screensaver from http://rss-glx.sf.net/
*
* This file is part of MPlayer.
*
* MPlayer is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* MPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include <stdint.h>
#include "mp_msg.h"
#include "subopt-helper.h"
#include "video_out.h"
#include "video_out_internal.h"
#include "gl_common.h"
#include "libswscale/swscale.h"
#include "libmpcodecs/vf_scale.h"
#include "osdep/timer.h"
#include "matrixview.h"
static const vo_info_t info = {
"MatrixView (OpenGL)",
"matrixview",
"Pigeon <pigeon@pigeond.net>",
"Based on MatrixView from rss-glx.sf.net"
};
const LIBVO_EXTERN(matrixview)
static MPGLContext glctx;
#ifdef CONFIG_GL_X11
static int wsGLXAttrib[] = {
GLX_RGBA,
GLX_RED_SIZE,1,
GLX_GREEN_SIZE,1,
GLX_BLUE_SIZE,1,
GLX_DEPTH_SIZE,1,
GLX_DOUBLEBUFFER,
None
};
#endif
static int int_pause;
static int eq_contrast;
static int eq_brightness;
static uint32_t image_width;
static uint32_t image_height;
static uint32_t image_format;
static struct SwsContext *sws;
static uint8_t *map_image[MP_MAX_PLANES];
static int map_stride[MP_MAX_PLANES];
#define DEFAULT_MATRIX_ROWS 96
#define DEFAULT_MATRIX_COLS 128
static int matrix_rows;
static int matrix_cols;
#define DEFAULT_CONTRAST 0.90f
#define CONTRAST_MULTIPLIER 0.02f
#define DEFAULT_BRIGHTNESS 1.0f
#define BRIGHTNESS_MULTIPLIER 0.02f
static void contrast_set(int value)
{
float contrast = value * CONTRAST_MULTIPLIER + DEFAULT_CONTRAST;
eq_contrast = value;
if (contrast < 0)
contrast = 0;
matrixview_contrast_set(contrast);
}
static void brightness_set(int value)
{
float brightness = value * BRIGHTNESS_MULTIPLIER + DEFAULT_BRIGHTNESS;
eq_brightness = value;
if (brightness < 0)
brightness = 0;
matrixview_brightness_set(brightness);
}
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)
{
image_height = height;
image_width = width;
image_format = format;
int_pause = 0;
#ifdef CONFIG_GL_WIN32
if (glctx.type == GLTYPE_W32 && !vo_w32_config(d_width, d_height, flags))
return -1;
#endif
#ifdef CONFIG_GL_X11
if (glctx.type == GLTYPE_X11) {
XVisualInfo *vinfo=glXChooseVisual( mDisplay,mScreen,wsGLXAttrib );
if (vinfo == NULL) {
mp_msg(MSGT_VO, MSGL_ERR, "[matrixview] no GLX support present\n");
return -1;
}
mp_msg(MSGT_VO, MSGL_V, "[matrixview] GLX chose visual with ID 0x%x\n",
(int)vinfo->visualid);
vo_x11_create_vo_window(vinfo, vo_dx, vo_dy, d_width, d_height, flags,
XCreateColormap(mDisplay, mRootWin,
vinfo->visual, AllocNone),
"matrixview", title);
}
#endif /* CONFIG_GL_WIN32 */
if (glctx.setGlWindow(&glctx) == SET_WINDOW_FAILED)
return -1;
if (sws)
sws_freeContext(sws);
sws = sws_getContextFromCmdLine(image_width, image_height, image_format,
matrix_cols, matrix_rows, IMGFMT_Y8);
if (!sws) {
mp_msg(MSGT_VO, MSGL_ERR, "[matrixview] Cannot create SwsContext context\n");
return -1;
}
if (!map_image[0])
map_image[0] = calloc(matrix_cols, matrix_rows);
map_stride[0] = matrix_cols;
matrixview_init(vo_dwidth, vo_dheight);
matrixview_matrix_resize(matrix_cols, matrix_rows);
contrast_set(eq_contrast);
brightness_set(eq_brightness);
matrixview_reshape(vo_dwidth, vo_dheight);
return 0;
}
static void check_events(void)
{
int e = glctx.check_events();
if (e & VO_EVENT_RESIZE) {
matrixview_reshape(vo_dwidth, vo_dheight);
}
if (e & VO_EVENT_EXPOSE && int_pause)
flip_page();
}
static void draw_osd(void)
{
return;
}
static void flip_page(void)
{
matrixview_draw(vo_dwidth, vo_dheight, GetTimer(), 0.0, map_image[0]);
glctx.swapGlBuffers(&glctx);
}
static int draw_slice(uint8_t *src[], int stride[], int w, int h, int x, int y)
{
sws_scale(sws, src, stride, y, h, map_image, map_stride);
return 0;
}
static int draw_frame(uint8_t *src[])
{
return 0;
}
static int query_format(uint32_t format)
{
int caps = VFCAP_CSP_SUPPORTED | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN | VFCAP_ACCEPT_STRIDE;
switch (format) {
case IMGFMT_YV12:
case IMGFMT_BGR32:
case IMGFMT_BGR24:
case IMGFMT_BGR16:
case IMGFMT_BGR15:
case IMGFMT_RGB32:
case IMGFMT_RGB24:
return caps;
default:
break;
}
return 0;
}
static void uninit(void)
{
if (!vo_config_count)
return;
uninit_mpglcontext(&glctx);
free(map_image[0]);
map_image[0] = NULL;
sws_freeContext(sws);
sws = NULL;
}
static const opt_t subopts[] =
{
{ "rows", OPT_ARG_INT, &matrix_rows, int_pos },
{ "cols", OPT_ARG_INT, &matrix_cols, int_pos },
{ NULL }
};
static int preinit(const char *arg)
{
enum MPGLType gltype = GLTYPE_X11;
#ifdef CONFIG_GL_WIN32
gltype = GLTYPE_W32;
#endif
if (!init_mpglcontext(&glctx, gltype))
return -1;
matrix_rows = DEFAULT_MATRIX_ROWS;
matrix_cols = DEFAULT_MATRIX_COLS;
if (subopt_parse(arg, subopts) != 0) {
mp_msg(MSGT_VO, MSGL_FATAL,
"\n-vo matrixview command line help:\n"
"Example: mplayer -vo matrixview:cols=320:rows=240\n"
"\n"
"Options:\n"
"\n"
" cols=<12-320>\n"
" Specify the number of columns of the matrix view, default %d\n"
"\n"
" rows=<12-240>\n"
" Specify the number of rows of the matrix view, default %d\n"
"\n"
,
DEFAULT_MATRIX_COLS, DEFAULT_MATRIX_ROWS
);
return -1;
}
return 0;
}
static int control(uint32_t request, void *data)
{
switch (request) {
case VOCTRL_PAUSE:
case VOCTRL_RESUME:
int_pause = (request == VOCTRL_PAUSE);
return VO_TRUE;
case VOCTRL_QUERY_FORMAT:
return query_format(*(uint32_t*)data);
case VOCTRL_ONTOP:
glctx.ontop();
return VO_TRUE;
case VOCTRL_FULLSCREEN:
glctx.fullscreen();
matrixview_reshape(vo_dwidth, vo_dheight);
return VO_TRUE;
case VOCTRL_BORDER:
glctx.border();
return VO_TRUE;
case VOCTRL_GET_EQUALIZER:
{
struct voctrl_get_equalizer_args *args = data;
if (strcasecmp(args->name, "contrast") == 0) {
*args->valueptr = eq_contrast;
}
else if (strcasecmp(args->name, "brightness") == 0) {
*args->valueptr = eq_brightness;
}
}
return VO_TRUE;
case VOCTRL_SET_EQUALIZER:
{
struct voctrl_set_equalizer_args *args = data;
if (strcasecmp(args->name, "contrast") == 0) {
contrast_set(args->value);
}
else if (strcasecmp(args->name, "brightness") == 0) {
brightness_set(args->value);
}
}
return VO_TRUE;
case VOCTRL_UPDATE_SCREENINFO:
glctx.update_xinerama_info();
return VO_TRUE;
}
return VO_NOTIMPL;
}