mirror of
https://github.com/game-stop/veejay.git
synced 2025-12-24 00:30:01 +01:00
3452 lines
74 KiB
C
3452 lines
74 KiB
C
/*
|
|
* Linux VeeJay
|
|
*
|
|
* Copyright(C)2002-2008 Niels Elburg <nwelburg@gmail.com>
|
|
*
|
|
* This program 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.
|
|
*
|
|
* This program 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 this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 , USA.
|
|
*
|
|
* Viewport with Perspective Transform Estimation for Veejay
|
|
*
|
|
* Resources:
|
|
* Gimp 1.0,2.0 (Perspective transformation (C) Spencer Kimball & Peter Mattis)
|
|
* Cinelerra (Motion plugin, no author in any file present. GPL2).
|
|
* Xine (bresenham line drawing routine)
|
|
*
|
|
*/
|
|
#include <config.h>
|
|
#include <math.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <libvjmem/vjmem.h>
|
|
#include <libvjmsg/vj-msg.h>
|
|
#include <libvje/vje.h>
|
|
#include <veejay/vj-viewport.h>
|
|
#include <libvje/effects/opacity.h>
|
|
#include <libyuv/yuvconv.h>
|
|
#include <libavutil/pixfmt.h>
|
|
#include <libvjmem/vjmem.h>
|
|
#include <veejay/vj-viewport-cfg.h>
|
|
#include <veejay/vj-viewport.h>
|
|
#include <math.h>
|
|
#include <libel/avcommon.h>
|
|
|
|
#define X0 0
|
|
#define Y0 1
|
|
#define X1 2
|
|
#define Y1 3
|
|
#define X2 4
|
|
#define Y2 5
|
|
#define X3 6
|
|
#define Y3 7
|
|
#ifndef MIN
|
|
#define MIN(a,b) ( (a)>(b) ? (b) : (a) )
|
|
#endif
|
|
#ifndef MAX
|
|
#define MAX(a,b) ( (a)>(b) ? (a) : (b) )
|
|
#endif
|
|
|
|
#define RUP8(num)(((num)+8)&~8)
|
|
|
|
#define clamp1(x, y, z) ((x) = ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x))))
|
|
#define distance1(x1,y1,x2,y2) ( sqrt( (x1 - x2) * (x1 - x2) + ( y1 - y2 ) * (y1 -y2 ) ) )
|
|
|
|
#define round1(x) ( (int32_t)( (x>0) ? (x) + 0.5 : (x) - 0.5 ))
|
|
#define min4(a,b,c,d) MIN(MIN(MIN(a,b),c),d)
|
|
#define max4(a,b,c,d) MAX(MAX(MAX(a,b),c),d)
|
|
#if defined(ARCH_X86) || defined(ARCH_X86_64)
|
|
#include <xmmintrin.h>
|
|
#endif
|
|
|
|
#define GRID_STEP 1
|
|
#define GRID_START 44
|
|
typedef struct
|
|
{
|
|
float m[4][4];
|
|
} matrix_t;
|
|
|
|
typedef struct
|
|
{
|
|
void *scaler;
|
|
uint8_t *buf[3];
|
|
float scale;
|
|
float sx;
|
|
float sy;
|
|
int sw;
|
|
int sh;
|
|
} ui_t;
|
|
|
|
typedef struct
|
|
{
|
|
int x;
|
|
int y;
|
|
} grid_t;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
int32_t x,y;
|
|
int32_t h,w;
|
|
int32_t x0,y0,w0,h0;
|
|
float points[9];
|
|
int users[4];
|
|
float usermouse[6];
|
|
int userm;
|
|
int user;
|
|
int save;
|
|
int user_ui;
|
|
int user_reverse;
|
|
int user_mode;
|
|
int grid_resolution;
|
|
int grid_width;
|
|
int grid_height;
|
|
int renew;
|
|
int disable;
|
|
int snap_marker;
|
|
int marker_size;
|
|
float x1;
|
|
float x2;
|
|
float x3;
|
|
float x4;
|
|
float y1;
|
|
float y2;
|
|
float y3;
|
|
float y4;
|
|
int32_t *map;
|
|
uint8_t *img[4];
|
|
matrix_t *M;
|
|
matrix_t *m;
|
|
matrix_t *T;
|
|
char *help;
|
|
uint8_t grid_val;
|
|
int parameters[8];
|
|
int32_t tx1,tx2,ty1,ty2;
|
|
int32_t ttx1,ttx2,tty1,tty2;
|
|
int mode;
|
|
// int32_t *buf;
|
|
void *sender;
|
|
uint32_t seq_id;
|
|
ui_t *ui;
|
|
int saved_w;
|
|
int saved_h;
|
|
grid_t *grid;
|
|
int grid_mode;
|
|
int initial_active;
|
|
} viewport_t;
|
|
|
|
|
|
static float msx(viewport_t *v, float x);
|
|
static float msy(viewport_t *v, float y);
|
|
|
|
static float vsx(viewport_t *v, float x);
|
|
static float vsy(viewport_t *v, float y);
|
|
|
|
static void viewport_draw_col( void *data, uint8_t *img, uint8_t *u, uint8_t *v );
|
|
static int viewport_update_perspective( viewport_t *v, float *values );
|
|
static void viewport_process( viewport_t *p );
|
|
static int viewport_configure(
|
|
viewport_t *v,
|
|
float x1, float y1,
|
|
float x2, float y2,
|
|
float x3, float y3,
|
|
float x4, float y4,
|
|
int32_t x0, int32_t y0,
|
|
int32_t w0, int32_t h0,
|
|
int32_t w, int32_t h,
|
|
uint32_t reverse,
|
|
uint8_t color,
|
|
int size);
|
|
|
|
static matrix_t *viewport_transform(float x1,float y1,float x2,float y2,float *coord );
|
|
static inline void point_map( matrix_t *M, float x, float y, float *nx, float *ny);
|
|
static matrix_t * viewport_invert_matrix( matrix_t *M, matrix_t *D );
|
|
static matrix_t *viewport_adjoint_matrix(matrix_t *M);
|
|
static double viewport_matrix_determinant( matrix_t *M );
|
|
static matrix_t *viewport_multiply_matrix( matrix_t *A, matrix_t *B );
|
|
static void viewport_copy_from( matrix_t *A, matrix_t *B );
|
|
static void viewport_scale_matrix( matrix_t *M, float sx, float sy );
|
|
static void viewport_translate_matrix( matrix_t *M, float x, float y );
|
|
static matrix_t *viewport_identity_matrix(void);
|
|
static matrix_t *viewport_matrix(void);
|
|
static void viewport_find_transform( float *coord, matrix_t *M );
|
|
void viewport_line (uint8_t *plane,int x1, int y1, int x2, int y2, int w, int h, uint8_t col);
|
|
static void draw_point( uint8_t *plane, int x, int y, int w, int h, int size, int col );
|
|
static viewport_config_t *viewport_load_settings( char *dir );
|
|
static void viewport_prepare_process( viewport_t *v );
|
|
static void viewport_compute_grid( viewport_t *v );
|
|
|
|
#ifdef HAVE_X86CPU
|
|
static inline int int_max( int a, int b )
|
|
{
|
|
b = a-b;
|
|
a -= b & (b>>31);
|
|
return a;
|
|
}
|
|
static inline int int_min( int a, int b )
|
|
{
|
|
b = b- a;
|
|
a += b & (b>>31); // if(a < b) then a = b
|
|
return a;
|
|
}
|
|
#else
|
|
static inline int int_max(int a, int b )
|
|
{
|
|
return MAX(a,b);
|
|
}
|
|
static inline int int_min(int a, int b )
|
|
{
|
|
return MIN(a,b);
|
|
}
|
|
#endif
|
|
/*
|
|
static void viewport_print_matrix( matrix_t *M )
|
|
{
|
|
veejay_msg(0, "|%f\t%f\t%f", M->m[0][0], M->m[0][1], M->m[0][2] );
|
|
veejay_msg(0, "|%f\t%f\t%f", M->m[1][0], M->m[1][1], M->m[1][2] );
|
|
veejay_msg(0, "|%f\t%f\t%f", M->m[2][0], M->m[2][1], M->m[2][2] );
|
|
}
|
|
*/
|
|
extern unsigned char *UTF8toLAT1(unsigned char*);
|
|
|
|
/*
|
|
* Bresenham line implementation from Xine
|
|
*/
|
|
|
|
void viewport_line (uint8_t *plane,
|
|
int x1, int y1, int x2, int y2, int w, int h, uint8_t col) {
|
|
|
|
uint8_t *c;
|
|
int dx, dy, t, inc, d, inc1, inc2;
|
|
int swap_x = 0;
|
|
int swap_y = 0;
|
|
|
|
if( x1 < 0 ) x1 = 0; else if (x1 > w ) x1 = w;
|
|
if( y1 < 0 ) y1 = 0; else if (y1 > h ) y1 = h;
|
|
if( x2 < 0 ) x2 = 0; else if (x2 > w ) x2 = w;
|
|
if( y2 < 0 ) y2 = 0; else if (y2 > h ) y2 = h;
|
|
|
|
/* sort line */
|
|
if (x2 < x1) {
|
|
t = x1;
|
|
x1 = x2;
|
|
x2 = t;
|
|
swap_x = 1;
|
|
}
|
|
if (y2 < y1) {
|
|
t = y1;
|
|
y1 = y2;
|
|
y2 = t;
|
|
swap_y = 1;
|
|
}
|
|
|
|
/* clip line */
|
|
if (x1 < 0) {
|
|
y1 = y1 + (y2-y1) * -x1 / (x2-x1);
|
|
x1 = 0;
|
|
}
|
|
if (y1 < 0) {
|
|
x1 = x1 + (x2-x1) * -y1 / (y2-y1);
|
|
y1 = 0;
|
|
}
|
|
if (x2 > w) {
|
|
y2 = y1 + (y2-y1) * (w-x1) / (x2-x1);
|
|
x2 = w;
|
|
}
|
|
if (y2 > h) {
|
|
x2 = x1 + (x2-x1) * (h-y1) / (y2-y1);
|
|
y2 = h;
|
|
}
|
|
|
|
if (x1 >= w || y1 >= h)
|
|
return;
|
|
|
|
dx = x2 - x1;
|
|
dy = y2 - y1;
|
|
|
|
/* unsort line */
|
|
if (swap_x) {
|
|
t = x1;
|
|
x1 = x2;
|
|
x2 = t;
|
|
}
|
|
if (swap_y) {
|
|
t = y1;
|
|
y1 = y2;
|
|
y2 = t;
|
|
}
|
|
|
|
if( dx>=dy ) {
|
|
if( x1>x2 )
|
|
{
|
|
t = x2; x2 = x1; x1 = t;
|
|
t = y2; y2 = y1; y1 = t;
|
|
}
|
|
|
|
if( y2 > y1 ) inc = 1; else inc = -1;
|
|
|
|
inc1 = 2*dy;
|
|
d = inc1 - dx;
|
|
inc2 = 2*(dy-dx);
|
|
|
|
c = plane + y1 * w + x1;
|
|
|
|
while(x1<x2)
|
|
{
|
|
*c++ = col;
|
|
|
|
x1++;
|
|
if( d<0 ) {
|
|
d+=inc1;
|
|
} else {
|
|
y1+=inc;
|
|
d+=inc2;
|
|
c = plane + y1 * w + x1;
|
|
}
|
|
}
|
|
} else {
|
|
if( y1>y2 ) {
|
|
t = x2; x2 = x1; x1 = t;
|
|
t = y2; y2 = y1; y1 = t;
|
|
}
|
|
|
|
if( x2 > x1 ) inc = 1; else inc = -1;
|
|
|
|
inc1 = 2*dx;
|
|
d = inc1-dy;
|
|
inc2 = 2*(dx-dy);
|
|
|
|
c = plane + y1 * w + x1;
|
|
|
|
while(y1<y2) {
|
|
*c = col;
|
|
|
|
c += w;
|
|
y1++;
|
|
if( d<0 ) {
|
|
d+=inc1;
|
|
} else {
|
|
x1+=inc;
|
|
d+=inc2;
|
|
c = plane + y1 * w + x1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*static void draw_dot( uint8_t *plane, int x, int y, int w, int h, int size, int col )
|
|
{
|
|
int x1 = x - size *2;
|
|
int y1 = y - size*2;
|
|
int x2 = x + size*2;
|
|
int y2 = y + size*2;
|
|
|
|
if( x1 < 0 ) x1 = 0; else if ( x1 > w ) x1 = w;
|
|
if( y1 < 0 ) y1 = 0; else if ( y1 > h ) y1 = h;
|
|
if( x2 < 0 ) x2 = 0; else if ( x2 > w ) x2 = w;
|
|
if( y2 < 0 ) y2 = 0; else if ( y2 > h ) y2 = h;
|
|
|
|
unsigned int i,j;
|
|
for( i = y; i < y2; i ++ )
|
|
{
|
|
for( j = x1; j < x2 ; j ++ )
|
|
plane[ y * w + x ] = col;
|
|
}
|
|
}*/
|
|
|
|
static void draw_point( uint8_t *plane, int x, int y, int w, int h, int size, int col )
|
|
{
|
|
int x1 = x - size *2;
|
|
int y1 = y - size*2;
|
|
int x2 = x + size*2;
|
|
int y2 = y + size*2;
|
|
|
|
if( x1 < 0 ) x1 = 0; else if ( x1 > w ) x1 = w;
|
|
if( y1 < 0 ) y1 = 0; else if ( y1 > h ) y1 = h;
|
|
if( x2 < 0 ) x2 = 0; else if ( x2 > w ) x2 = w;
|
|
if( y2 < 0 ) y2 = 0; else if ( y2 > h ) y2 = h;
|
|
|
|
unsigned int i,j;
|
|
for( i = y1; i < y2; i ++ )
|
|
{
|
|
for( j = x1; j < x2 ; j ++ )
|
|
plane[ i * w + j ] = col;
|
|
}
|
|
}
|
|
|
|
static void viewport_find_transform( float *coord, matrix_t *M )
|
|
{
|
|
double dx1,dx2,dx3,dy1,dy2,dy3;
|
|
double det1,det2;
|
|
|
|
dx1 = coord[X1] - coord[X3];
|
|
dx2 = coord[X2] - coord[X3];
|
|
dx3 = coord[X0] - coord[X1] + coord[X3] - coord[X2];
|
|
|
|
dy1 = coord[Y1] - coord[Y3];
|
|
dy2 = coord[Y2] - coord[Y3];
|
|
dy3 = coord[Y0] - coord[Y1] + coord[Y3] - coord[Y2];
|
|
|
|
/* is the mapping affine? */
|
|
if( ((dx3 == 0.0) && (dy3==0.0)) )
|
|
{
|
|
M->m[0][0] = coord[X1] - coord[X0];
|
|
M->m[0][1] = coord[X3] - coord[X1];
|
|
M->m[0][2] = coord[X0];
|
|
|
|
M->m[1][0] = coord[Y1] - coord[Y0];
|
|
M->m[1][1] = coord[Y3] - coord[Y1];
|
|
M->m[1][2] = coord[Y0];
|
|
|
|
M->m[2][0] = 0.0;
|
|
M->m[2][1] = 0.0;
|
|
}
|
|
else
|
|
{
|
|
det1 = dx3 * dy2 - dy3 * dx2;
|
|
det2 = dx1 * dy2 - dy1 * dx2;
|
|
M->m[2][0] = det1/det2;
|
|
|
|
det1 = dx1 * dy3 - dy1 * dx3;
|
|
det2 = dx1 * dy2 - dy1 * dx2;
|
|
M->m[2][1] = det1/det2;
|
|
|
|
M->m[0][0] = coord[X1] - coord[X0] + M->m[2][0] * coord[X1];
|
|
M->m[0][1] = coord[X2] - coord[X0] + M->m[2][1] * coord[X2];
|
|
M->m[0][2] = coord[X0];
|
|
|
|
M->m[1][0] = coord[Y1] - coord[Y0] + M->m[2][0] * coord[Y1];
|
|
M->m[1][1] = coord[Y2] - coord[Y0] + M->m[2][1] * coord[Y2];
|
|
M->m[1][2] = coord[Y0];
|
|
}
|
|
|
|
M->m[2][2] = 1.0;
|
|
}
|
|
|
|
void viewport_set_ui(void *vv, int i)
|
|
{
|
|
viewport_t *v = (viewport_t*) vv;
|
|
v->user_ui = i;
|
|
}
|
|
|
|
|
|
char *viewport_get_my_help(void *vv)
|
|
{
|
|
viewport_t *v = (viewport_t*) vv;
|
|
if(!v->user_ui )
|
|
return NULL;
|
|
|
|
char reverse_mode[32];
|
|
veejay_memset(reverse_mode,0,sizeof(reverse_mode));
|
|
sprintf(reverse_mode, "%s", ( v->user_reverse ? "Forward" : "Reverse" ) );
|
|
|
|
char scroll_mode[64];
|
|
|
|
switch(v->grid_mode) {
|
|
case 0:
|
|
snprintf(scroll_mode,sizeof(scroll_mode),
|
|
"CTRL + Mousewheel: Marker %2dx%2d up=Grid down=Dots",v->marker_size,v->marker_size);
|
|
break;
|
|
case 1:
|
|
snprintf(scroll_mode,sizeof(scroll_mode),
|
|
"CTRL + Mousewheel: Dots %2dx%2d up=Marker down=Grid",v->grid_resolution,v->grid_resolution);
|
|
break;
|
|
case 2:
|
|
snprintf(scroll_mode,sizeof(scroll_mode),
|
|
"CTRL + Mousewheel: Grid %2dx%2d up=Grid down=Marker",v->grid_resolution,v->grid_resolution);
|
|
break;
|
|
}
|
|
|
|
|
|
char tmp[1500];
|
|
char startup_mode[16];
|
|
snprintf(startup_mode,sizeof(startup_mode), "%s", (v->initial_active==1 ? "Active" :"Inactive" ));
|
|
snprintf(tmp,sizeof(tmp), "Interactive Input/Projection calibration\nMouse Left: Set point\nCTRL + Cursor Keys: Finetune point\nMouse Left + RSHIFT: Set projection quad \nMouse Right: %s\nMouse Middle: Exit without saving\nMouse Middle + LSHIFT: Line Color\nCTRL + h:Hide/Show this Help\nCTRL + p:Enable/disable transform\nCTRL + a: %s on startup.\nCTRL + s: Exit this screen.\n%s\n\n",
|
|
reverse_mode,
|
|
startup_mode,
|
|
scroll_mode
|
|
);
|
|
|
|
|
|
return strdup( tmp );
|
|
}
|
|
char *viewport_get_my_status(void *vv)
|
|
{
|
|
viewport_t *v = (viewport_t*) vv;
|
|
if(!v->user_ui )
|
|
return NULL;
|
|
|
|
// float x = v->usermouse[2] / ( v->w / 100.0f );
|
|
// float y = v->usermouse[3] / ( v->h / 100.0f );
|
|
|
|
float tx = vsx(v,v->usermouse[4]);
|
|
float ty = vsy(v,v->usermouse[5]);
|
|
|
|
char status[1024];
|
|
snprintf(status,1024, "Projection Quad: %dx%d + %dx%d\nPoints: 1=%2.2fx%2.2f 2=%2.2fx%2.2f 3=%2.2fx%2.2f 4=%2.2fx%2.2f\nCurrent Position: %2.1fx%2.1f\n",
|
|
v->x0,v->y0,
|
|
v->w0,v->h0,
|
|
v->x1,v->y1,
|
|
v->x2,v->y2,
|
|
v->x3,v->y3,
|
|
v->x4,v->y4,
|
|
tx,ty
|
|
);
|
|
|
|
return strdup( status );
|
|
}
|
|
|
|
|
|
static matrix_t *viewport_matrix(void)
|
|
{
|
|
matrix_t *M = (matrix_t*) vj_malloc(sizeof(matrix_t));
|
|
uint32_t i,j;
|
|
for( i = 0;i < 3 ; i ++ )
|
|
{
|
|
for( j = 0; j < 3 ; j++ )
|
|
M->m[i][j] = 0.0;
|
|
}
|
|
return M;
|
|
}
|
|
|
|
static matrix_t *viewport_identity_matrix(void)
|
|
{
|
|
matrix_t *M = viewport_matrix();
|
|
M->m[0][0] = 1.0;
|
|
M->m[1][1] = 1.0;
|
|
M->m[2][2] = 1.0;
|
|
return M;
|
|
}
|
|
|
|
static void viewport_translate_matrix( matrix_t *M, float x, float y )
|
|
{
|
|
float g = M->m[2][0];
|
|
float h = M->m[2][1];
|
|
float i = M->m[2][2];
|
|
|
|
M->m[0][0] += x * g;
|
|
M->m[0][1] += x * h;
|
|
M->m[0][2] += x * i;
|
|
|
|
M->m[1][0] += y * g;
|
|
M->m[1][1] += y * h;
|
|
M->m[1][2] += y * i;
|
|
}
|
|
|
|
static void viewport_scale_matrix( matrix_t *M, float sx, float sy )
|
|
{
|
|
M->m[0][0] *= sx;
|
|
M->m[0][1] *= sx;
|
|
M->m[0][2] *= sx;
|
|
|
|
M->m[1][0] *= sy;
|
|
M->m[1][1] *= sy;
|
|
M->m[1][2] *= sy;
|
|
}
|
|
|
|
static void viewport_copy_from( matrix_t *A, matrix_t *B )
|
|
{
|
|
uint32_t i,j;
|
|
for( i =0 ; i < 3; i ++ )
|
|
for( j = 0; j < 3 ; j ++ )
|
|
A->m[i][j] = B->m[i][j];
|
|
}
|
|
|
|
static matrix_t *viewport_multiply_matrix( matrix_t *A, matrix_t *B )
|
|
{
|
|
matrix_t *R = viewport_matrix();
|
|
|
|
R->m[0][0] = A->m[0][0] * B->m[0][0] + A->m[0][1] * B->m[1][0] + A->m[0][2] * B->m[2][0];
|
|
R->m[0][1] = A->m[0][0] * B->m[0][1] + A->m[0][1] * B->m[1][1] + A->m[0][2] * B->m[2][1];
|
|
R->m[0][2] = A->m[0][0] * B->m[0][2] + A->m[0][1] * B->m[1][2] + A->m[0][2] * B->m[2][2];
|
|
|
|
R->m[1][0] = A->m[1][0] * B->m[0][0] + A->m[1][1] * B->m[1][0] + A->m[1][2] * B->m[2][0];
|
|
R->m[1][1] = A->m[1][0] * B->m[0][1] + A->m[1][1] * B->m[1][1] + A->m[1][2] * B->m[2][1];
|
|
R->m[1][2] = A->m[1][0] * B->m[0][2] + A->m[1][1] * B->m[1][2] + A->m[1][2] * B->m[2][2];
|
|
|
|
R->m[2][0] = A->m[2][0] * B->m[0][0] + A->m[2][1] * B->m[0][1] + A->m[2][2] * B->m[2][0];
|
|
R->m[2][1] = A->m[2][0] * B->m[0][1] + A->m[2][1] * B->m[1][1] + A->m[2][2] * B->m[2][1];
|
|
R->m[2][2] = A->m[2][0] * B->m[0][2] + A->m[2][1] * B->m[1][2] + A->m[2][2] * B->m[2][2];
|
|
|
|
|
|
return R;
|
|
}
|
|
|
|
static double viewport_matrix_determinant( matrix_t *M )
|
|
{
|
|
double D = M->m[0][0] * M->m[1][1] * M->m[2][2] +
|
|
M->m[0][1] * M->m[1][2] * M->m[2][0] +
|
|
M->m[2][0] * M->m[1][1] * M->m[0][2] -
|
|
M->m[1][0] * M->m[0][1] * M->m[2][2] -
|
|
M->m[2][1] * M->m[1][2] * M->m[0][0];
|
|
|
|
return D;
|
|
}
|
|
|
|
static matrix_t *viewport_adjoint_matrix(matrix_t *M)
|
|
{
|
|
matrix_t *A = viewport_matrix();
|
|
A->m[0][0] = M->m[0][0];
|
|
A->m[0][1] = -M->m[0][1];
|
|
A->m[0][2] = M->m[0][2];
|
|
A->m[1][0] = -M->m[1][0];
|
|
A->m[1][1] = M->m[1][1];
|
|
A->m[1][2] = -M->m[1][2];
|
|
A->m[2][0] = M->m[2][0];
|
|
A->m[2][1] = -M->m[2][1];
|
|
A->m[2][2] = M->m[2][2];
|
|
return A;
|
|
}
|
|
|
|
static matrix_t * viewport_invert_matrix( matrix_t *M, matrix_t *D )
|
|
{
|
|
double det = viewport_matrix_determinant( M );
|
|
if( det == 0.0 )
|
|
{
|
|
veejay_msg(0, "det = %f, inverse of matrix not possible");
|
|
return NULL;
|
|
}
|
|
det = 1.0 / det;
|
|
|
|
D->m[0][0] = (M->m[1][1] * M->m[2][2] - M->m[1][2] * M->m[2][1] ) * det;
|
|
D->m[1][0] = (M->m[1][0] * M->m[2][2] - M->m[1][2] * M->m[2][0] ) * det;
|
|
D->m[2][0] = (M->m[1][0] * M->m[2][1] - M->m[1][1] * M->m[2][0] ) * det;
|
|
D->m[0][1] = (M->m[0][1] * M->m[2][2] - M->m[0][2] * M->m[2][1] ) * det;
|
|
D->m[1][1] = (M->m[0][0] * M->m[2][2] - M->m[0][2] * M->m[2][0] ) * det;
|
|
D->m[2][1] = (M->m[0][0] * M->m[2][1] - M->m[0][1] * M->m[2][0] ) * det;
|
|
D->m[0][2] = (M->m[0][1] * M->m[1][2] - M->m[0][2] * M->m[1][1] ) * det;
|
|
D->m[1][2] = (M->m[0][0] * M->m[1][2] - M->m[0][2] * M->m[1][0] ) * det;
|
|
D->m[2][2] = (M->m[0][0] * M->m[1][1] - M->m[0][1] * M->m[1][0] ) * det;
|
|
|
|
matrix_t *A = viewport_adjoint_matrix( D );
|
|
|
|
return A;
|
|
}
|
|
|
|
static inline void point_map( matrix_t *M, float x, float y, float *nx, float *ny)
|
|
{
|
|
float w = M->m[2][0] * x + M->m[2][1] * y + M->m[2][2];
|
|
|
|
if( w == 0.0 )
|
|
w = 1.0;
|
|
else
|
|
w = 1.0 / w;
|
|
|
|
*nx = (M->m[0][0] * x + M->m[0][1] * y + M->m[0][2] ) * w;
|
|
*ny = (M->m[1][0] * x + M->m[1][1] * y + M->m[1][2] ) * w;
|
|
|
|
}
|
|
|
|
static inline void point_map_int( matrix_t *M, float x, float y, int *nx, int *ny)
|
|
{
|
|
float w = M->m[2][0] * x + M->m[2][1] * y + M->m[2][2];
|
|
|
|
if( w == 0.0 )
|
|
w = 1.0;
|
|
else
|
|
w = 1.0 / w;
|
|
|
|
*nx = ceilf( (M->m[0][0] * x + M->m[0][1] * y + M->m[0][2] ) * w);
|
|
*ny = ceilf( (M->m[1][0] * x + M->m[1][1] * y + M->m[1][2] ) * w);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static matrix_t *viewport_transform(
|
|
float x1,
|
|
float y1,
|
|
float x2,
|
|
float y2,
|
|
float *coord )
|
|
{
|
|
float sx=1.0,sy=1.0;
|
|
|
|
if( (x2-x1) > 0.0 )
|
|
sx = 1.0 / (x2-x1);
|
|
if( (y2-y1) > 0.0 )
|
|
sy = 1.0 / (y2-y1);
|
|
|
|
matrix_t *H = viewport_matrix();
|
|
viewport_find_transform( coord, H );
|
|
|
|
matrix_t *I = viewport_identity_matrix();
|
|
viewport_translate_matrix( I, -x1, -y1 );
|
|
viewport_scale_matrix( I, sx,sy );
|
|
matrix_t *R = viewport_multiply_matrix( H,I );
|
|
free(I);
|
|
free(H);
|
|
return R;
|
|
}
|
|
|
|
|
|
/*
|
|
void viewport_get_projection_coords(
|
|
void *data, int32_t *x0, int32_t *y0, int32_t *w0, int32_t *h0 )
|
|
{
|
|
viewport_t *v = (viewport_t*) data;
|
|
|
|
*x0 = v->x0;
|
|
*y0 = v->y0;
|
|
*w0 = v->w0;
|
|
*h0 = v->h0;
|
|
}
|
|
|
|
float *viewport_get_projection_points( void *data )
|
|
{
|
|
viewport_t *v = (viewport_t*) data;
|
|
float *res = vj_malloc( sizeof(float) * 8 );
|
|
|
|
res[0] = v->x0;
|
|
res[1] = v->y0;
|
|
res[2] = v->x0 + v->w0;
|
|
res[3] = v->y0;
|
|
res[4] = v->x0;
|
|
res[5] = v->y0 + v->h0;
|
|
res[6] = v->x0 + v->w0;
|
|
res[7] = v->y0 + v->h0;
|
|
|
|
return res;
|
|
}
|
|
|
|
void viewport_set_projection( void *data, float *res )
|
|
{
|
|
viewport_t *v = (viewport_t*) data;
|
|
v->x1 = res[0];
|
|
v->y1 = res[1];
|
|
v->x2 = res[2];
|
|
v->y2 = res[3];
|
|
v->x3 = res[4];
|
|
v->y3 = res[5];
|
|
v->x4 = res[6];
|
|
v->y4 = res[7];
|
|
|
|
}*/
|
|
static float msy(viewport_t *v, float y)
|
|
{
|
|
if( v->ui->scale == 1.0f ) {
|
|
return y;
|
|
}
|
|
ui_t *u = v->ui;
|
|
int cy = v->h / 2;
|
|
int dy = cy - ( u->sh / 2 );
|
|
|
|
float a = (float) dy / ( v->h / 100.0f );
|
|
float s = (float) v->h / (float) v->ui->sh;
|
|
|
|
return (y/s) + a;
|
|
}
|
|
|
|
static float msx(viewport_t *v, float x)
|
|
{
|
|
if( v->ui->scale == 1.0f ) {
|
|
return x;
|
|
}
|
|
ui_t *u = v->ui;
|
|
int cx = v->w / 2;
|
|
int dx = cx - ( u->sw / 2 );
|
|
|
|
float a = (float) dx / ( v->w / 100.0f );
|
|
float s = (float) v->w / (float) v->ui->sw;
|
|
|
|
return (x/s) + a;
|
|
}
|
|
|
|
static float vsx(viewport_t *v, float x)
|
|
{
|
|
if( v->ui->scale == 1.0f ) {
|
|
return x;
|
|
}
|
|
ui_t *u = v->ui;
|
|
int cx = v->w / 2;
|
|
int dx = cx - ( u->sw / 2 );
|
|
|
|
float a = (float) dx / ( v->w / 100.0f );
|
|
float s = (float) v->w / (float) v->ui->sw;
|
|
return (x-a)*s;
|
|
}
|
|
static float vsy(viewport_t *v, float x)
|
|
{
|
|
if( v->ui->scale == 1.0f )
|
|
return x;
|
|
|
|
ui_t *u = v->ui;
|
|
int cy = v->h / 2;
|
|
int dy = cy - ( u->sh / 2 );
|
|
|
|
float a = (float) dy / ( v->h / 100.0f );
|
|
|
|
float s = (float) v->h / (float) v->ui->sh;
|
|
return (x-a)*s;
|
|
}
|
|
|
|
|
|
|
|
static int viewport_configure(
|
|
viewport_t *v,
|
|
float x1, float y1, /* output */
|
|
float x2, float y2,
|
|
float x3, float y3,
|
|
float x4, float y4,
|
|
int32_t x0, int32_t y0, /* input */
|
|
int32_t w0, int32_t h0,
|
|
int32_t wid, int32_t hei,
|
|
uint32_t reverse,
|
|
uint8_t color,
|
|
int grid_resolution)
|
|
{
|
|
int w = wid, h = hei;
|
|
if( grid_resolution <= 8 )
|
|
grid_resolution = GRID_START;
|
|
float rat = (h/(float)w);
|
|
|
|
v->grid_width = grid_resolution;
|
|
v->grid_height = grid_resolution * rat;
|
|
|
|
v->points[X0] = (float) x1 * (float) w / 100.0;
|
|
v->points[Y0] = (float) y1 * (float) h / 100.0;
|
|
|
|
v->points[X1] = (float) x2 * (float) w / 100.0;
|
|
v->points[Y1] = (float) y2 * (float) h / 100.0;
|
|
|
|
v->points[X2] = (float) x3 * (float) w / 100.0;
|
|
v->points[Y2] = (float) y3 * (float) h / 100.0;
|
|
|
|
v->points[X3] = (float) x4 * (float) w / 100.0;
|
|
v->points[Y3] = (float) y4 * (float) h / 100.0;
|
|
|
|
|
|
v->w = wid; /* image plane boundaries */
|
|
v->x = 0;
|
|
v->h = hei;
|
|
v->y = 0;
|
|
|
|
v->x0 = x0;
|
|
v->y0 = y0;
|
|
v->w0 = w0;
|
|
v->h0 = h0;
|
|
|
|
v->grid_val = color;
|
|
|
|
v->x1 = x1;
|
|
v->x2 = x2;
|
|
v->x3 = x3;
|
|
v->x4 = x4;
|
|
v->y1 = y1;
|
|
v->y2 = y2;
|
|
v->y3 = y3;
|
|
v->y4 = y4;
|
|
v->user_reverse = reverse;
|
|
|
|
float tmp = v->points[X3];
|
|
v->points[X3] = v->points[X2];
|
|
v->points[X2] = tmp;
|
|
tmp = v->points[Y3];
|
|
v->points[Y3] = v->points[Y2];
|
|
v->points[Y2] = tmp;
|
|
|
|
matrix_t *m = viewport_transform( x0, y0, x0 + w0, y0 + h0, v->points );
|
|
|
|
if(v->m) {
|
|
free(v->m);
|
|
v->m = NULL;
|
|
}
|
|
if(v->M) {
|
|
free(v->M);
|
|
v->M = NULL;
|
|
}
|
|
|
|
if ( reverse )
|
|
{
|
|
v->m = viewport_matrix();
|
|
viewport_copy_from( v->m, m );
|
|
matrix_t *im = viewport_matrix();
|
|
v->M = viewport_invert_matrix( v->m, im );
|
|
if(!v->M)
|
|
{
|
|
free(m);
|
|
free(im);
|
|
free(v->m);
|
|
v->m = NULL;
|
|
return 0;
|
|
}
|
|
free(im);
|
|
free(m);
|
|
viewport_prepare_process( v );
|
|
return 1;
|
|
|
|
}
|
|
else
|
|
{
|
|
matrix_t *mtmp = viewport_matrix();
|
|
matrix_t *im = viewport_invert_matrix( m, mtmp );
|
|
free(mtmp);
|
|
if(!im)
|
|
{
|
|
free(m);
|
|
return 0;
|
|
}
|
|
v->M = m;
|
|
v->m = im;
|
|
viewport_prepare_process( v );
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void viewport_process( viewport_t *p )
|
|
{
|
|
const int32_t w = p->w;
|
|
const int32_t h = p->h;
|
|
const int32_t X = p->x0;
|
|
const int32_t Y = p->y0;
|
|
|
|
matrix_t *m = p->m;
|
|
|
|
const int len = w * h;
|
|
const float xinc = m->m[0][0];
|
|
const float yinc = m->m[1][0];
|
|
const float winc = m->m[2][0];
|
|
|
|
const int32_t tx1 = p->ttx1;
|
|
const int32_t tx2 = p->ttx2;
|
|
const int32_t ty1 = p->tty1;
|
|
const int32_t ty2 = p->tty2;
|
|
|
|
const float m01 = m->m[0][1];
|
|
const float m11 = m->m[1][1];
|
|
const float m21 = m->m[2][1];
|
|
const float m02 = m->m[0][2];
|
|
const float m12 = m->m[1][2];
|
|
const float m22 = m->m[2][2];
|
|
|
|
float tx,ty,tw;
|
|
float ttx,tty;
|
|
int32_t x,y;
|
|
int32_t itx,ity;
|
|
|
|
int32_t *map = p->map;
|
|
|
|
for( y = ty1; y < ty2; y ++ )
|
|
{
|
|
tx = xinc * ( tx1 + 0.5 ) + m01 * ( y + 0.5) + m02;
|
|
ty = yinc * ( tx1 + 0.5 ) + m11 * ( y + 0.5) + m12;
|
|
tw = winc * ( tx1 + 0.5 ) + m21 * ( y + 0.5) + m22;
|
|
|
|
for( x = tx1; x < tx2 ; x ++ )
|
|
{
|
|
if( tw == 0.0 ) {
|
|
ttx = 0.0;
|
|
tty = 0.0;
|
|
} else if ( tw != 1.0 ) {
|
|
ttx = tx / tw;
|
|
tty = ty / tw;
|
|
} else {
|
|
ttx = tx;
|
|
tty = ty;
|
|
}
|
|
|
|
itx = (int32_t) ttx;
|
|
ity = (int32_t) tty;
|
|
|
|
if( itx >= X && itx <= w && ity >= Y && ity < h )
|
|
map[ (y * w + x) ] = (ity * w + itx);
|
|
else
|
|
map[ (y * w + x) ] = (len+1);
|
|
|
|
tx += xinc;
|
|
ty += yinc;
|
|
tw += winc;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
static void viewport_prepare_process( viewport_t *v )
|
|
{
|
|
const int32_t X = v->x0;
|
|
const int32_t Y = v->y0;
|
|
|
|
float dx1,dx2,dx3,dx4,dy1,dy2,dy3,dy4;
|
|
matrix_t *M = v->M;
|
|
|
|
point_map( M, v->x, v->y, &dx1, &dy1);
|
|
point_map( M, v->x + v->w, v->y, &dx2, &dy2 );
|
|
point_map( M, v->x, v->y + v->h, &dx4, &dy4 );
|
|
point_map( M, v->x + v->w, v->y + v->h, &dx3, &dy3 );
|
|
|
|
v->tx1 = round1( min4( dx1, dx2, dx3, dx4 ) );
|
|
v->ty1 = round1( min4( dy1, dy2, dy3, dy4 ) );
|
|
v->tx2 = round1( max4( dx1, dx2, dx3, dx4 ) );
|
|
v->ty2 = round1( max4( dy1, dy2, dy3, dy4 ) );
|
|
|
|
clamp1( v->ty1 , Y, Y + v->h0 );
|
|
clamp1( v->ty2 ,Y,Y + v->h0 );
|
|
clamp1( v->tx1, X, X + v->w0 );
|
|
clamp1( v->tx2, X, X + v->w0 );
|
|
|
|
v->ttx2 = v->tx2;
|
|
v->tty2 = v->ty2;
|
|
v->ttx1 = v->tx1;
|
|
v->tty1 = v->ty1;
|
|
|
|
clamp1( v->ttx2,0, v->w );
|
|
clamp1( v->tty2,0, v->h );
|
|
clamp1( v->ttx1,0, v->w );
|
|
clamp1( v->tty1,0, v->h );
|
|
|
|
}
|
|
|
|
|
|
void viewport_process_dynamic_map( void *data, uint8_t *in[3], uint8_t *out[3], uint32_t *map, int feather )
|
|
{
|
|
viewport_t *v = (viewport_t*) data;
|
|
const int32_t w = v->w;
|
|
const int32_t h = v->h;
|
|
const int32_t X = v->x0;
|
|
const int32_t Y = v->y0;
|
|
matrix_t *m = v->m;
|
|
|
|
const float xinc = m->m[0][0];
|
|
const float yinc = m->m[1][0];
|
|
const float winc = m->m[2][0];
|
|
const int32_t tx1 = v->ttx1;
|
|
const int32_t tx2 = v->ttx2;
|
|
const int32_t ty1 = v->tty1;
|
|
const int32_t ty2 = v->tty2;
|
|
|
|
const float m01 = m->m[0][1];
|
|
const float m11 = m->m[1][1];
|
|
const float m21 = m->m[2][1];
|
|
const float m02 = m->m[0][2];
|
|
const float m12 = m->m[1][2];
|
|
const float m22 = m->m[2][2];
|
|
|
|
const uint8_t *inY = in[0];
|
|
const uint8_t *inU = in[1];
|
|
const uint8_t *inV = in[2];
|
|
|
|
uint8_t *outY = out[0];
|
|
uint8_t *outU = out[1];
|
|
uint8_t *outV = out[2];
|
|
|
|
float tx,ty,tw;
|
|
float ttx,tty;
|
|
int32_t x,y;
|
|
int32_t itx,ity;
|
|
|
|
outY[ w * h + 1 ] = 0;
|
|
outU[ w * h + 1 ] = 128;
|
|
outV[ w * h + 1 ] = 128;
|
|
|
|
/*
|
|
#if defined (HAVE_ASM_MMX) || defined (HAVE_AMS_SSE )
|
|
|
|
fast_memset_dirty( outY , 0, ty1 * v->w );
|
|
fast_memset_dirty( outU , 128, ty1 * v->w );
|
|
fast_memset_dirty( outV , 128, ty1 * v->w );
|
|
fast_memset_finish();
|
|
#else
|
|
|
|
for( y =0 ; y < ty1; y ++ )
|
|
{
|
|
for( x = 0 ; x < w ; x ++ )
|
|
{
|
|
outY[ (y * w +x ) ] = 0;
|
|
outU[ (y * w +x ) ] = 128;
|
|
outV[ (y * w +x ) ] = 128;
|
|
}
|
|
}
|
|
#endif
|
|
*/
|
|
for( y = ty1; y < ty2; y ++ )
|
|
{
|
|
tx = xinc * ( tx1 + 0.5 ) + m01 * ( y + 0.5) + m02;
|
|
ty = yinc * ( tx1 + 0.5 ) + m11 * ( y + 0.5) + m12;
|
|
tw = winc * ( tx1 + 0.5 ) + m21 * ( y + 0.5) + m22;
|
|
/* for( x = 0; x < tx1; x ++ )
|
|
{
|
|
outY[(y*w+x)] = 0;
|
|
outU[(y*w+x)] = 128;
|
|
outV[(y*w+x)] = 128;
|
|
}*/
|
|
|
|
for( x = tx1; x < tx2 ; x ++ )
|
|
{
|
|
if( tw == 0.0 ) {
|
|
ttx = 0.0;
|
|
tty = 0.0;
|
|
} else if ( tw != 1.0 ) {
|
|
ttx = tx / tw;
|
|
tty = ty / tw;
|
|
} else {
|
|
ttx = tx;
|
|
tty = ty;
|
|
}
|
|
|
|
itx = (int32_t) ttx;
|
|
ity = (int32_t) tty;
|
|
|
|
if( itx >= X && itx <= w && ity >= Y && ity < h
|
|
&&
|
|
map[( y * w + x)] >= feather )
|
|
{
|
|
outY[(y*w+x)] = inY[(ity*w+itx)];
|
|
outU[(y*w+x)] = inU[(ity*w+itx)];
|
|
outV[(y*w+x)] = inV[(ity*w+itx)];
|
|
}
|
|
/*else
|
|
{
|
|
outY[(y*w+x)] = 0;
|
|
outU[(y*w+x)] = 128;
|
|
outV[(y*w+x)] = 128;
|
|
|
|
}*/
|
|
|
|
tx += xinc;
|
|
ty += yinc;
|
|
tw += winc;
|
|
}
|
|
/*
|
|
for( x = tx2; x < w; x ++ )
|
|
{
|
|
outY[(y*w+x)] = 0;
|
|
outU[(y*w+x)] = 128;
|
|
outV[(y*w+x)] = 128;
|
|
}*/
|
|
|
|
}
|
|
/*
|
|
#if defined (HAVE_ASM_MMX) || defined (HAVE_AMS_SSE )
|
|
int rest = h - ty2;
|
|
fast_memset_dirty( outY + (ty2 * v->w),0, rest * v->w );
|
|
fast_memset_dirty( outU + (ty2 * v->w), 128, rest * v->w );
|
|
fast_memset_dirty( outV + (ty2 * v->w), 128, rest * v->w );
|
|
fast_memset_finish();
|
|
#else
|
|
for( y = ty2 ; y < h; y ++ )
|
|
{
|
|
for( x = 0; x < w; x ++ )
|
|
{
|
|
outY[(y*w+x)] = 0;
|
|
outU[(y*w+x)] = 128;
|
|
outV[(y*w+x)] = 128;
|
|
}
|
|
}
|
|
#endif
|
|
*/
|
|
|
|
}
|
|
void viewport_process_dynamic( void *data, uint8_t *in[3], uint8_t *out[3] )
|
|
{
|
|
viewport_t *v = (viewport_t*) data;
|
|
const int32_t w = v->w;
|
|
const int32_t h = v->h;
|
|
const int32_t X = v->x0;
|
|
const int32_t Y = v->y0;
|
|
matrix_t *m = v->m;
|
|
|
|
const float xinc = m->m[0][0];
|
|
const float yinc = m->m[1][0];
|
|
const float winc = m->m[2][0];
|
|
const int32_t tx1 = v->ttx1;
|
|
const int32_t tx2 = v->ttx2;
|
|
const int32_t ty1 = v->tty1;
|
|
const int32_t ty2 = v->tty2;
|
|
|
|
const float m01 = m->m[0][1];
|
|
const float m11 = m->m[1][1];
|
|
const float m21 = m->m[2][1];
|
|
const float m02 = m->m[0][2];
|
|
const float m12 = m->m[1][2];
|
|
const float m22 = m->m[2][2];
|
|
|
|
const uint8_t *inY = in[0];
|
|
const uint8_t *inU = in[1];
|
|
const uint8_t *inV = in[2];
|
|
|
|
uint8_t *outY = out[0];
|
|
uint8_t *outU = out[1];
|
|
uint8_t *outV = out[2];
|
|
|
|
float tx,ty,tw;
|
|
float ttx,tty;
|
|
int32_t x,y;
|
|
int32_t itx,ity;
|
|
|
|
#if defined (HAVE_ASM_MMX) || defined (HAVE_AMS_SSE )
|
|
|
|
fast_memset_dirty( outY , 0, ty1 * v->w );
|
|
fast_memset_dirty( outU , 128, ty1 * v->w );
|
|
fast_memset_dirty( outV , 128, ty1 * v->w );
|
|
fast_memset_finish();
|
|
#else
|
|
|
|
for( y =0 ; y < ty1; y ++ )
|
|
{
|
|
for( x = 0 ; x < w ; x ++ )
|
|
{
|
|
outY[ (y * w +x ) ] = 0;
|
|
outU[ (y * w +x ) ] = 128;
|
|
outV[ (y * w +x ) ] = 128;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
for( y = ty1; y < ty2; y ++ )
|
|
{
|
|
tx = xinc * ( tx1 + 0.5 ) + m01 * ( y + 0.5) + m02;
|
|
ty = yinc * ( tx1 + 0.5 ) + m11 * ( y + 0.5) + m12;
|
|
tw = winc * ( tx1 + 0.5 ) + m21 * ( y + 0.5) + m22;
|
|
for( x = 0; x < tx1; x ++ )
|
|
{
|
|
outY[(y*w+x)] = 0;
|
|
outU[(y*w+x)] = 128;
|
|
outV[(y*w+x)] = 128;
|
|
}
|
|
|
|
for( x = tx1; x < tx2 ; x ++ )
|
|
{
|
|
if( tw == 0.0 ) {
|
|
ttx = 0.0;
|
|
tty = 0.0;
|
|
} else if ( tw != 1.0 ) {
|
|
ttx = tx / tw;
|
|
tty = ty / tw;
|
|
} else {
|
|
ttx = tx;
|
|
tty = ty;
|
|
}
|
|
|
|
itx = (int32_t) ttx;
|
|
ity = (int32_t) tty;
|
|
|
|
if( itx >= X && itx <= w && ity >= Y && ity < h )
|
|
{
|
|
outY[(y*w+x)] = inY[(ity*w+itx)];
|
|
outU[(y*w+x)] = inU[(ity*w+itx)];
|
|
outV[(y*w+x)] = inV[(ity*w+itx)];
|
|
}
|
|
else
|
|
{
|
|
outY[(y*w+x)] = 0;
|
|
outU[(y*w+x)] = 128;
|
|
outV[(y*w+x)] = 128;
|
|
|
|
}
|
|
|
|
tx += xinc;
|
|
ty += yinc;
|
|
tw += winc;
|
|
}
|
|
for( x = tx2; x < w; x ++ )
|
|
{
|
|
outY[(y*w+x)] = 0;
|
|
outU[(y*w+x)] = 128;
|
|
outV[(y*w+x)] = 128;
|
|
}
|
|
|
|
}
|
|
|
|
#if defined (HAVE_ASM_MMX) || defined (HAVE_AMS_SSE )
|
|
int rest = h - ty2;
|
|
fast_memset_dirty( outY + (ty2 * v->w),0, rest * v->w );
|
|
fast_memset_dirty( outU + (ty2 * v->w), 128, rest * v->w );
|
|
fast_memset_dirty( outV + (ty2 * v->w), 128, rest * v->w );
|
|
fast_memset_finish();
|
|
#else
|
|
for( y = ty2 ; y < h; y ++ )
|
|
{
|
|
for( x = 0; x < w; x ++ )
|
|
{
|
|
outY[(y*w+x)] = 0;
|
|
outU[(y*w+x)] = 128;
|
|
outV[(y*w+x)] = 128;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void viewport_process_dynamic_alpha( void *data, uint8_t *in[4], uint8_t *out[4] )
|
|
{
|
|
viewport_t *v = (viewport_t*) data;
|
|
const int32_t w = v->w;
|
|
const int32_t h = v->h;
|
|
const int32_t X = v->x0;
|
|
const int32_t Y = v->y0;
|
|
matrix_t *m = v->m;
|
|
|
|
const float xinc = m->m[0][0];
|
|
const float yinc = m->m[1][0];
|
|
const float winc = m->m[2][0];
|
|
const int32_t tx1 = v->ttx1;
|
|
const int32_t tx2 = v->ttx2;
|
|
const int32_t ty1 = v->tty1;
|
|
const int32_t ty2 = v->tty2;
|
|
|
|
const float m01 = m->m[0][1];
|
|
const float m11 = m->m[1][1];
|
|
const float m21 = m->m[2][1];
|
|
const float m02 = m->m[0][2];
|
|
const float m12 = m->m[1][2];
|
|
const float m22 = m->m[2][2];
|
|
|
|
const uint8_t *inY = in[0];
|
|
const uint8_t *inU = in[1];
|
|
const uint8_t *inV = in[2];
|
|
const uint8_t *inA = in[3];
|
|
|
|
uint8_t *outY = out[0];
|
|
uint8_t *outU = out[1];
|
|
uint8_t *outV = out[2];
|
|
uint8_t *outA = out[3];
|
|
|
|
float tx,ty,tw;
|
|
float ttx,tty;
|
|
int32_t x,y;
|
|
int32_t itx,ity;
|
|
|
|
#if defined (HAVE_ASM_MMX) || defined (HAVE_AMS_SSE )
|
|
|
|
fast_memset_dirty( outY , 0, ty1 * v->w );
|
|
fast_memset_dirty( outU , 128, ty1 * v->w );
|
|
fast_memset_dirty( outV , 128, ty1 * v->w );
|
|
fast_memset_dirty( outA,0, ty1*v->w);
|
|
fast_memset_finish();
|
|
#else
|
|
|
|
for( y =0 ; y < ty1; y ++ )
|
|
{
|
|
for( x = 0 ; x < w ; x ++ )
|
|
{
|
|
outY[ (y * w +x ) ] = 0;
|
|
outU[ (y * w +x ) ] = 128;
|
|
outV[ (y * w +x ) ] = 128;
|
|
outA[ (y*w +x) ] = 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
for( y = ty1; y < ty2; y ++ )
|
|
{
|
|
tx = xinc * ( tx1 + 0.5 ) + m01 * ( y + 0.5) + m02;
|
|
ty = yinc * ( tx1 + 0.5 ) + m11 * ( y + 0.5) + m12;
|
|
tw = winc * ( tx1 + 0.5 ) + m21 * ( y + 0.5) + m22;
|
|
for( x = 0; x < tx1; x ++ )
|
|
{
|
|
outY[(y*w+x)] = 0;
|
|
outU[(y*w+x)] = 128;
|
|
outV[(y*w+x)] = 128;
|
|
outA[(y*w+x)] = 0;
|
|
|
|
}
|
|
|
|
for( x = tx1; x < tx2 ; x ++ )
|
|
{
|
|
if( tw == 0.0 ) {
|
|
ttx = 0.0;
|
|
tty = 0.0;
|
|
} else if ( tw != 1.0 ) {
|
|
ttx = tx / tw;
|
|
tty = ty / tw;
|
|
} else {
|
|
ttx = tx;
|
|
tty = ty;
|
|
}
|
|
|
|
itx = (int32_t) ttx;
|
|
ity = (int32_t) tty;
|
|
|
|
if( itx >= X && itx <= w && ity >= Y && ity < h )
|
|
{
|
|
outY[(y*w+x)] = inY[(ity*w+itx)];
|
|
outU[(y*w+x)] = inU[(ity*w+itx)];
|
|
outV[(y*w+x)] = inV[(ity*w+itx)];
|
|
outA[(y*w+x)] = inA[(ity*w+itx)];
|
|
}
|
|
else
|
|
{
|
|
outY[(y*w+x)] = 0;
|
|
outU[(y*w+x)] = 128;
|
|
outV[(y*w+x)] = 128;
|
|
outA[(y*w+x)] = 0;
|
|
}
|
|
|
|
tx += xinc;
|
|
ty += yinc;
|
|
tw += winc;
|
|
}
|
|
for( x = tx2; x < w; x ++ )
|
|
{
|
|
outY[(y*w+x)] = 0;
|
|
outU[(y*w+x)] = 128;
|
|
outV[(y*w+x)] = 128;
|
|
outA[(y*w+x)] = 0;
|
|
}
|
|
|
|
}
|
|
|
|
#if defined (HAVE_ASM_MMX) || defined (HAVE_AMS_SSE )
|
|
int rest = h - ty2;
|
|
fast_memset_dirty( outY + (ty2 * v->w),0, rest * v->w );
|
|
fast_memset_dirty( outU + (ty2 * v->w), 128, rest * v->w );
|
|
fast_memset_dirty( outV + (ty2 * v->w), 128, rest * v->w );
|
|
fast_memset_dirty( outA + (ty2 * v->w), 0, rest * v->w );
|
|
fast_memset_finish();
|
|
#else
|
|
for( y = ty2 ; y < h; y ++ )
|
|
{
|
|
for( x = 0; x < w; x ++ )
|
|
{
|
|
outY[(y*w+x)] = 0;
|
|
outU[(y*w+x)] = 128;
|
|
outV[(y*w+x)] = 128;
|
|
outA[(y*w+x)] = 0;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void viewport_destroy( void *data )
|
|
{
|
|
viewport_t *v = (viewport_t*)data;
|
|
if( v )
|
|
{
|
|
if( v->M ) free( v->M );
|
|
if( v->m ) free( v->m );
|
|
if( v->T ) free( v->T );
|
|
if( v->map ) free( v->map );
|
|
if( v->help ) free( v->help );
|
|
if( v->ui ) {
|
|
if( v->ui->scaler )
|
|
yuv_free_swscaler(v->ui->scaler);
|
|
if( v->ui->buf )
|
|
free(v->ui->buf[0]);
|
|
free(v->ui);
|
|
}
|
|
if(v->grid) free(v->grid);
|
|
free(v);
|
|
}
|
|
v = NULL;
|
|
}
|
|
|
|
static int viewport_update_perspective( viewport_t *v, float *values )
|
|
{
|
|
v->disable = 0;
|
|
|
|
int res = viewport_configure (v, v->x1, v->y1,
|
|
v->x2, v->y2,
|
|
v->x3, v->y3,
|
|
v->x4, v->y4,
|
|
v->x0, v->y0,
|
|
v->w0, v->h0,
|
|
v->w, v->h,
|
|
v->user_reverse,
|
|
v->grid_val,
|
|
v->grid_resolution );
|
|
|
|
|
|
if(! res )
|
|
{
|
|
veejay_msg(VEEJAY_MSG_ERROR, "Viewport: Invalid quadrilateral. Trying to fallback");
|
|
|
|
v->x1 = values[0]; v->x2 = values[2]; v->x3 = values[4]; v->x4 = values[6];
|
|
v->y1 = values[1]; v->y2 = values[3]; v->y3 = values[5]; v->y4 = values[7];
|
|
|
|
if(!viewport_configure( v, v->x1, v->y1, v->x2, v->y2, v->x3, v->y3,v->x4,v->y4,
|
|
v->x0, v->y0, v->w0, v->h0,v->w,v->h, v->user_reverse, v->grid_val,v->grid_resolution ));
|
|
{
|
|
veejay_msg(VEEJAY_MSG_ERROR, "Unable to configure the viewport");
|
|
veejay_msg(VEEJAY_MSG_ERROR, "If you are using a preset-configuration, remove or fix ~/.veejay/viewport.cfg");
|
|
v->disable = 1;
|
|
return res;
|
|
}
|
|
}
|
|
|
|
// Clear map
|
|
const int len = v->w * v->h;
|
|
int k;
|
|
for( k = 0 ; k < len ; k ++ )
|
|
v->map[k] = len+1;
|
|
|
|
|
|
// Update map
|
|
viewport_process( v );
|
|
|
|
return res;
|
|
}
|
|
static int nearest_div(int val )
|
|
{
|
|
int r = val % 8;
|
|
while(r--)
|
|
val--;
|
|
return val;
|
|
}
|
|
/*static int nearest_div4(int val )
|
|
{
|
|
int r = val % 4;
|
|
while(r--)
|
|
val--;
|
|
return val;
|
|
}
|
|
static int nearest_div16(int val )
|
|
{
|
|
int r = val % 16;
|
|
while(r--)
|
|
val--;
|
|
return val;
|
|
}
|
|
*/
|
|
static void *viewport_init_swscaler(ui_t *u, int w, int h)
|
|
{
|
|
uint8_t *dummy[3] = { NULL,NULL,NULL };
|
|
int nw = w * u->scale;
|
|
int nh = h * u->scale;
|
|
u->sw = nearest_div(nw);
|
|
u->sh = nearest_div(nh);
|
|
VJFrame *srci = yuv_yuv_template( dummy[0],dummy[1],dummy[2],w,h,PIX_FMT_GRAY8);
|
|
VJFrame *dsti = yuv_yuv_template( dummy[0],dummy[1],dummy[2],u->sw,u->sh,PIX_FMT_GRAY8);
|
|
sws_template t;
|
|
memset(&t,0,sizeof(sws_template));
|
|
t.flags = yuv_which_scaler();
|
|
u->sx = (float)w / (float) u->sw;
|
|
u->sy = (float)h / (float) u->sh;
|
|
void *scaler = yuv_init_swscaler( srci,dsti,&t,yuv_sws_get_cpu_flags());
|
|
|
|
free(srci);
|
|
free(dsti);
|
|
|
|
return scaler;
|
|
}
|
|
|
|
|
|
void viewport_reconfigure(void *vv)
|
|
{
|
|
viewport_t *v = (viewport_t*) vv;
|
|
float p[9];
|
|
|
|
p[0] = v->x1;
|
|
p[2] = v->x2;
|
|
p[4] = v->x3;
|
|
p[6] = v->x4;
|
|
p[1] = v->y1;
|
|
p[3] = v->y2;
|
|
p[5] = v->y3;
|
|
p[7] = v->y4;
|
|
|
|
viewport_update_perspective(v,p);
|
|
|
|
}
|
|
|
|
void viewport_set_composite(void *vc, int mode, int colormode)
|
|
{
|
|
viewport_config_t *c = (viewport_config_t*) vc;
|
|
c->composite_mode = mode;
|
|
c->colormode = colormode;
|
|
}
|
|
int viewport_get_color_mode_from_config(void *vc)
|
|
{
|
|
viewport_config_t *c = (viewport_config_t*) vc;
|
|
return c->colormode;
|
|
}
|
|
|
|
int viewport_get_composite_mode_from_config(void *vc)
|
|
{
|
|
viewport_config_t *c = (viewport_config_t*) vc;
|
|
return c->composite_mode;
|
|
}
|
|
|
|
int viewport_get_initial_active( void *vv )
|
|
{
|
|
viewport_t *v = (viewport_t*) vv;
|
|
return v->initial_active;
|
|
}
|
|
|
|
void viewport_set_initial_active( void *vv, int status )
|
|
{
|
|
viewport_t *v = (viewport_t*) vv;
|
|
v->initial_active = status;
|
|
}
|
|
|
|
void *viewport_get_configuration(void *vv, char *filename )
|
|
{
|
|
viewport_config_t *vc = viewport_load_settings( filename );
|
|
if(vc) {
|
|
return vc;
|
|
}
|
|
|
|
viewport_t *v = (viewport_t*) vv;
|
|
viewport_config_t *o = (viewport_config_t*) vj_calloc(sizeof(viewport_config_t)); //FIXME not always freed?
|
|
o->saved_w = v->saved_w;
|
|
o->saved_h = v->saved_h;
|
|
o->reverse = v->user_reverse;
|
|
o->grid_resolution = v->grid_resolution;
|
|
o->grid_color = v->grid_val;
|
|
o->frontback = 0;
|
|
o->x0 = v->x0;
|
|
o->y0 = v->y0;
|
|
o->w0 = v->w0;
|
|
o->h0 = v->h0;
|
|
o->x1 = v->x1;
|
|
o->x2 = v->x2;
|
|
o->x3 = v->x3;
|
|
o->x4 = v->x4;
|
|
o->y1 = v->y1;
|
|
o->y2 = v->y2;
|
|
o->y3 = v->y3;
|
|
o->y4 = v->y4;
|
|
o->scale = v->ui->scale;
|
|
o->initial_active = v->initial_active;
|
|
|
|
return o;
|
|
}
|
|
|
|
int viewport_reconfigure_from_config(void *vv, void *config, char *filename)
|
|
{
|
|
viewport_t *v = (viewport_t*) vv;
|
|
viewport_config_t *c = (viewport_config_t*) config;
|
|
viewport_config_t *o = viewport_get_configuration(vv, filename);
|
|
|
|
veejay_msg(0,"Configuration saved %dx%d, have %dx%d",
|
|
c->saved_w, c->saved_h,v->saved_w,v->saved_h );
|
|
/*
|
|
if( c->saved_w != v->saved_w || c->saved_h != v->saved_h ) {
|
|
float sx=1.0f;
|
|
float sy=1.0f;
|
|
if( c->saved_w > 0 && c->saved_h > 0 ) {
|
|
sx = (float) c->saved_w / (float) v->saved_w;
|
|
sy = (float) c->saved_h / (float) v->saved_h;
|
|
}
|
|
o->x0 = c->x0 * sx;
|
|
o->y0 = c->y0 * sy;
|
|
o->w0 = c->w0 * sx;
|
|
o->h0 = c->h0 * sy;
|
|
|
|
veejay_msg(VEEJAY_MSG_WARNING, "Correcting geometry for current setup");
|
|
}
|
|
*/
|
|
|
|
// Clear map
|
|
const int len = v->w * v->h;
|
|
int k;
|
|
for( k = 0 ; k < len ; k ++ )
|
|
v->map[k] = len+1;
|
|
|
|
v->disable = 0;
|
|
|
|
// try to initialize the new settings
|
|
int res = viewport_configure( v, c->x1,c->y1,
|
|
c->x2,c->y2,
|
|
c->x3,c->y3,
|
|
c->x4,c->y4,
|
|
c->x0,c->y0,
|
|
c->w0,c->h0,
|
|
v->w,v->h,
|
|
c->reverse,
|
|
c->grid_color,
|
|
c->grid_resolution );
|
|
|
|
if(!res) {
|
|
veejay_msg(VEEJAY_MSG_ERROR, "Cannot load calibration settings, restoring defaults.");
|
|
res = viewport_configure( v, o->x1,o->y1,
|
|
o->x2,o->y2,
|
|
o->x3,o->y3,
|
|
o->x4,o->y4,
|
|
o->x0,o->y0,
|
|
o->w0,o->h0,
|
|
v->w,v->h,
|
|
o->reverse,
|
|
o->grid_color,
|
|
o->grid_resolution );
|
|
|
|
|
|
}
|
|
|
|
if(!res) {
|
|
veejay_msg(VEEJAY_MSG_ERROR, "Unable to revert to old configuration.");
|
|
v->disable = 1;
|
|
free(o);
|
|
return 0;
|
|
}
|
|
|
|
|
|
if( res ) {
|
|
v->user_ui = 0;
|
|
viewport_process( v );
|
|
veejay_msg(VEEJAY_MSG_DEBUG,
|
|
"Reconfigured calibration for %dx%d to (1)=%fx%f\t(2)=%fx%f\t(3)=%fx%f\t(4)=%fx%f\t%fx%f+%fx%f",
|
|
v->w,v->h,v->x1,v->y1,v->x2,v->y2,v->x3,v->y3,v->x4,v->y4,v->x0,v->y0,v->w0,v->h0);
|
|
|
|
}
|
|
free(o);
|
|
return 1;
|
|
}
|
|
void viewport_update_from(void *vv, void *bb)
|
|
{
|
|
if( vv == NULL || bb == NULL )
|
|
return;
|
|
|
|
viewport_t *v = (viewport_t*) vv;
|
|
viewport_t *b = (viewport_t*) bb;
|
|
|
|
float p[9];
|
|
|
|
p[0] = b->x1;
|
|
p[2] = b->x2;
|
|
p[4] = b->x3;
|
|
p[6] = b->x4;
|
|
p[1] = b->y1;
|
|
p[3] = b->y2;
|
|
p[5] = b->y3;
|
|
p[7] = b->y4;
|
|
|
|
|
|
float sx = (float) b->w / (float) v->w;
|
|
float sy = (float) b->h / (float) v->h;
|
|
|
|
b->x0 = v->x0 * sx;
|
|
b->y0 = v->y0 * sy;
|
|
b->w0 = v->w0 * sx;
|
|
b->h0 = v->h0 * sy;
|
|
b->x = v->x * sx;
|
|
b->y = v->y * sy;
|
|
|
|
b->x1 = v->x1;
|
|
b->y1 = v->y1;
|
|
b->x2 = v->x2;
|
|
b->y2 = v->y2;
|
|
b->x3 = v->x3;
|
|
b->y3 = v->y3;
|
|
b->x4 = v->x4;
|
|
b->y4 = v->y4;
|
|
|
|
b->user_reverse = v->user_reverse;
|
|
|
|
|
|
if(viewport_update_perspective(b,p)) {
|
|
veejay_msg(VEEJAY_MSG_DEBUG, "Configured input %dx%d to (1)=%fx%f\t(2)=%fx%f\t(3)=%fx%f\t(4)=%fx%f\t%dx%d+%dx%d",
|
|
b->w,b->h,b->x1,b->y1,b->x2,b->y2,b->x3,b->y3,b->x4,b->y4,b->x0,b->y0,b->w0,b->h0);
|
|
}
|
|
else {
|
|
veejay_msg(VEEJAY_MSG_DEBUG,"Failed to apply projection calibration. Press CTRL-s to configure this sample or press CTRL-p to disable.");
|
|
b->disable = 1;
|
|
}
|
|
|
|
}
|
|
|
|
void *viewport_init(int x0, int y0, int w0, int h0, int w, int h, int iw, int ih,char *filename, int *enable, int *frontback, int mode )
|
|
{
|
|
//@ try to load last saved settings
|
|
viewport_config_t *vc = viewport_load_settings( filename );
|
|
if(vc) {
|
|
float sx = (float) w / (float) vc->saved_w;
|
|
float sy = (float) h / (float) vc->saved_h;
|
|
|
|
vc->x0 = vc->x0 * sx;
|
|
vc->y0 = vc->y0 * sy;
|
|
vc->w0 = vc->w0 * sx;
|
|
vc->h0 = vc->h0 * sy;
|
|
veejay_msg(VEEJAY_MSG_DEBUG,"\tQuad : %dx%d+%dx%d",vc->x0,vc->y0,vc->w0,vc->h0 );
|
|
}
|
|
veejay_msg(VEEJAY_MSG_DEBUG,"\tBacking : %dx%d",w,h);
|
|
veejay_msg(VEEJAY_MSG_DEBUG,"\tRectangle: %dx%d+%dx%d",x0,y0,w0,h0);
|
|
|
|
viewport_t *v = (viewport_t*) vj_calloc(sizeof(viewport_t));
|
|
v->usermouse[0] = 0.0;
|
|
v->usermouse[1] = 0.0;
|
|
v->usermouse[2] = 0.0;
|
|
v->usermouse[3] = 0.0;
|
|
v->M = NULL;
|
|
v->m = NULL;
|
|
v->grid = NULL;
|
|
v->ui = vj_calloc( sizeof(ui_t));
|
|
v->ui->buf[0] = vj_calloc(sizeof(uint8_t) * RUP8(w * h) );
|
|
v->ui->scale = 0.5f;
|
|
v->ui->scaler = viewport_init_swscaler(v->ui,iw,ih);
|
|
v->saved_w = w;
|
|
v->saved_h = h;
|
|
v->w = w;
|
|
v->h = h;
|
|
v->marker_size = 4;
|
|
v->disable = 0;
|
|
|
|
int res;
|
|
|
|
if( vc == NULL )
|
|
{
|
|
res = viewport_configure (v, 29.0, 28.0,
|
|
70.0, 30.0,
|
|
70.0, 66.0,
|
|
30.0, 69.0,
|
|
|
|
x0,y0,w0,h0,
|
|
w,h,
|
|
1,
|
|
0xff,
|
|
w/32 );
|
|
|
|
*enable = 0;
|
|
*frontback = 1;
|
|
v->user_ui = 0;
|
|
|
|
}
|
|
else
|
|
{
|
|
v->marker_size = vc->marker_size;
|
|
v->grid_resolution = vc->grid_resolution;
|
|
v->grid_mode = vc->grid_mode;
|
|
v->initial_active = vc->initial_active;
|
|
|
|
res = viewport_configure( v, vc->x1, vc->y1,
|
|
vc->x2, vc->y2,
|
|
vc->x3, vc->y3,
|
|
vc->x4, vc->y4,
|
|
vc->x0, vc->y0,
|
|
vc->w0, vc->h0,
|
|
w,h,
|
|
vc->reverse,
|
|
vc->grid_color,
|
|
vc->grid_resolution );
|
|
|
|
*enable = vc->initial_active;
|
|
*frontback = vc->frontback;
|
|
v->user_ui = 0;
|
|
|
|
}
|
|
|
|
|
|
if(! res )
|
|
{
|
|
veejay_msg(VEEJAY_MSG_ERROR, "Invalid point locations");
|
|
free(v->ui->buf[0]);
|
|
free(v->ui);
|
|
free(v);
|
|
free(vc);
|
|
return NULL;
|
|
}
|
|
|
|
// Allocate memory for map
|
|
v->map = (int32_t*) vj_calloc(sizeof(int32_t) * RUP8(v->w * v->h + (v->w*2)) );
|
|
if(!v->map) {
|
|
free(v->ui->buf[0]);
|
|
free(v->ui);
|
|
free(v);
|
|
free(vc);
|
|
veejay_msg(VEEJAY_MSG_ERROR, "Memory allocation error");
|
|
return NULL;
|
|
}
|
|
|
|
const int len = v->w * v->h;
|
|
const int eln = len + ( v->w * 2 );
|
|
|
|
veejay_memset( v->map, len+1, eln );
|
|
|
|
// calculate initial view
|
|
viewport_process( v );
|
|
|
|
// v->buf = vj_calloc( sizeof(int32_t) * 50000 );
|
|
free(vc);
|
|
|
|
if(v->grid_resolution > 0)
|
|
viewport_compute_grid(v);
|
|
|
|
return (void*)v;
|
|
}
|
|
|
|
void *viewport_clone(void *vv, int new_w, int new_h )
|
|
{
|
|
viewport_t *v = (viewport_t*) vv;
|
|
if(!v) return NULL;
|
|
viewport_t *q = (viewport_t*) vj_malloc(sizeof(viewport_t));
|
|
veejay_memcpy(q,v,sizeof(viewport_t));
|
|
|
|
float sx = (float) new_w / (float) v->w;
|
|
float sy = (float) new_h / (float) v->h;
|
|
q->M = NULL;
|
|
q->m = NULL;
|
|
q->grid = NULL;
|
|
q->initial_active = v->initial_active;
|
|
q->x0 = v->x0 * sx;
|
|
q->y0 = v->y0 * sy;
|
|
q->w0 = v->w0 * sx;
|
|
q->h0 = v->h0 * sy;
|
|
q->x = v->x * sx;
|
|
q->y = v->y * sy;
|
|
q->w = new_w;
|
|
q->h = new_h;
|
|
q->usermouse[0] = 0.0;
|
|
q->usermouse[1] = 0.0;
|
|
q->usermouse[2] = 0.0;
|
|
q->usermouse[3] = 0.0;
|
|
q->ui = vj_calloc( sizeof(ui_t));
|
|
q->ui->buf[0] = vj_calloc(sizeof(uint8_t) * RUP8(new_w * new_h) );
|
|
q->ui->scale = 1.0f;
|
|
q->ui->scaler = viewport_init_swscaler(q->ui,new_w,new_h);
|
|
q->disable = 0;
|
|
|
|
int res = viewport_configure( q, q->x1, q->y1,
|
|
q->x2, q->y2,
|
|
q->x3, q->y3,
|
|
q->x4, q->y4,
|
|
q->x0, q->y0,
|
|
q->w0, q->h0,
|
|
new_w,new_h,
|
|
q->user_reverse,
|
|
q->grid_val,
|
|
q->grid_resolution );
|
|
|
|
q->user_ui = 0;
|
|
|
|
if(! res )
|
|
{
|
|
veejay_msg(VEEJAY_MSG_ERROR, "Invalid point locations");
|
|
free(q->ui->buf[0]);
|
|
free(q->ui);
|
|
free(q);
|
|
return NULL;
|
|
}
|
|
|
|
// Allocate memory for map
|
|
q->map = (int32_t*) vj_malloc(sizeof(int32_t) * RUP8(q->w * q->h + (q->w*2)) );
|
|
|
|
const int len = q->w * q->h;
|
|
const int eln = len + ( q->w * 2 );
|
|
int k;
|
|
for( k = len ; k < eln ; k ++ )
|
|
q->map[k] = len+1;
|
|
|
|
viewport_process( q );
|
|
|
|
// q->buf = vj_calloc( sizeof(int32_t) * 50000 );
|
|
veejay_msg(VEEJAY_MSG_INFO,"\tConfiguring input:");
|
|
veejay_msg(VEEJAY_MSG_INFO, "\tPoints :\t(1) %fx%f (2) %fx%f", q->x1,q->y1,q->x2,q->y2);
|
|
veejay_msg(VEEJAY_MSG_INFO, "\t :\t(3) %fx%f (4) %fx%f", q->x2,q->y2,q->x3,q->y3);
|
|
veejay_msg(VEEJAY_MSG_INFO, "\tQuad :\t%dx%d+%dx%d", q->x0,q->y0,q->w0,q->h0 );
|
|
veejay_msg(VEEJAY_MSG_INFO, "\tDimension:\t%dx%d",q->w,q->h);
|
|
|
|
return (void*) q;
|
|
}
|
|
|
|
|
|
int viewport_active( void *data )
|
|
{
|
|
viewport_t *v = (viewport_t*) data;
|
|
return v->user_ui;
|
|
}
|
|
|
|
char *viewport_get_help(void *data)
|
|
{
|
|
viewport_t *v = (viewport_t*)data;
|
|
return v->help;
|
|
}
|
|
|
|
|
|
|
|
static viewport_config_t *viewport_load_settings( char *path )
|
|
{
|
|
viewport_config_t *vc = vj_calloc(sizeof(viewport_config_t));
|
|
|
|
FILE *fd = fopen( path, "r" );
|
|
if(!fd)
|
|
{
|
|
free(vc);
|
|
veejay_msg(VEEJAY_MSG_WARNING, "No such file %s", path);
|
|
return NULL;
|
|
}
|
|
|
|
fseek(fd,0,SEEK_END );
|
|
unsigned int len = ftell( fd );
|
|
|
|
if( len <= 0 )
|
|
{
|
|
veejay_msg(VEEJAY_MSG_WARNING, "File %s is empty",path);
|
|
free(vc);
|
|
return NULL;
|
|
}
|
|
|
|
char *buf = vj_calloc( (len+1) );
|
|
|
|
rewind( fd );
|
|
fread( buf, len, 1 , fd);
|
|
|
|
fclose(fd );
|
|
|
|
int n = sscanf(buf, "%f %f %f %f %f %f %f %f %d %d %d %d %d %d %d %d %d %d %d %d %d",
|
|
&vc->x1, &vc->y1,
|
|
&vc->x2, &vc->y2,
|
|
&vc->x3, &vc->y3,
|
|
&vc->x4, &vc->y4,
|
|
&vc->reverse,
|
|
&vc->grid_resolution,
|
|
&vc->grid_color,
|
|
&vc->x0,
|
|
&vc->y0,
|
|
&vc->w0,
|
|
&vc->h0,
|
|
&vc->frontback,
|
|
&vc->saved_w,
|
|
&vc->saved_h,
|
|
&vc->marker_size,
|
|
&vc->grid_mode,
|
|
&vc->initial_active);
|
|
|
|
//@ pre 1.4.10
|
|
if( n == 20 ) {
|
|
vc->initial_active = 1;
|
|
n++;
|
|
}
|
|
|
|
if( n != 21 )
|
|
{
|
|
veejay_msg(VEEJAY_MSG_ERROR, "Parse error in %s",path );
|
|
free(vc);
|
|
free(buf);
|
|
return NULL;
|
|
}
|
|
|
|
free(buf);
|
|
veejay_msg(VEEJAY_MSG_INFO, "Projection mapping configuration [%s]", path);
|
|
veejay_msg(VEEJAY_MSG_INFO, "\tBehaviour:\t%s", (vc->reverse ? "Forward" : "Projection") );
|
|
veejay_msg(VEEJAY_MSG_INFO, "\tPoints :\t(1) %fx%f (2) %fx%f", vc->x1,vc->y1,vc->x2,vc->y2);
|
|
veejay_msg(VEEJAY_MSG_INFO, "\t :\t(3) %fx%f (4) %fx%f", vc->x2,vc->y2,vc->x3,vc->y3);
|
|
veejay_msg(VEEJAY_MSG_INFO, "\tPencil :\t%s", (vc->grid_color == 0xff ? "white" : "black" ) );
|
|
veejay_msg(VEEJAY_MSG_INFO, "\tEnabled :\t%s",
|
|
(vc->initial_active == 0 ? "No" : "Yes"));
|
|
|
|
return vc;
|
|
}
|
|
|
|
void viewport_save_settings( void *ptr, int frontback, char *path )
|
|
{
|
|
viewport_t *v = (viewport_t *) ptr;
|
|
|
|
FILE *fd = fopen( path, "wb" );
|
|
|
|
if(!fd)
|
|
{
|
|
veejay_msg(0, "Unable to open '%s' for writing. Cannot save viewport settings",
|
|
path );
|
|
return;
|
|
}
|
|
|
|
char content[512];
|
|
|
|
sprintf( content, "%f %f %f %f %f %f %f %f %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
|
|
v->x1,v->y1,v->x2,v->y2,
|
|
v->x3,v->y3,v->x4,v->y4,
|
|
v->user_reverse,
|
|
0,
|
|
v->grid_val,
|
|
v->x0,
|
|
v->y0,
|
|
v->w0,
|
|
v->h0,
|
|
frontback,
|
|
v->saved_w,
|
|
v->saved_h,
|
|
v->marker_size,
|
|
v->grid_mode,
|
|
v->initial_active );
|
|
|
|
int res = fwrite( content, strlen(content), 1, fd );
|
|
|
|
if( res <= 0 )
|
|
veejay_msg(VEEJAY_MSG_ERROR, "Unable to save viewport settings to %s", path );
|
|
|
|
fclose( fd );
|
|
|
|
veejay_msg(VEEJAY_MSG_INFO, "Saved viewport settings to %s. Press CTRL-p to enable/disable", path);
|
|
}
|
|
/*
|
|
static int viewport_locate_marker( viewport_t *v, uint8_t *img, float fx, float fy , float *dx, float *dy )
|
|
{
|
|
uint32_t x = fx / 100.0f * v->w;
|
|
uint32_t y = fy / 100.0f * v->h;
|
|
|
|
uint32_t x1 = x - v->marker_size;
|
|
uint32_t y1 = y - v->marker_size;
|
|
uint32_t x2 = x + v->marker_size;
|
|
uint32_t y2 = y + v->marker_size;
|
|
|
|
if( x1 < 0 ) x1 = 0; else if ( x1 > v->w ) x1 = v->w;
|
|
if( y1 < 0 ) y1 = 0; else if ( y1 > v->h ) y1 = v->h;
|
|
if( x2 < 0 ) x2 = 0; else if ( x2 > v->w ) x2 = v->w;
|
|
if( y2 < 0 ) y2 = 0; else if ( y2 > v->h ) y2 = v->h;
|
|
|
|
unsigned int i,j;
|
|
uint32_t product_row = 0;
|
|
uint32_t pixels_row = 0;
|
|
uint32_t product_col = 0;
|
|
uint32_t pixels_col = 0;
|
|
uint32_t pixels_row_c = 0;
|
|
uint32_t product_col_c = 0;
|
|
|
|
unsigned long nc = 0, it =0;
|
|
uint8_t hist[256];
|
|
uint8_t p0 = 0;
|
|
int32_t ii=0,ji=0;
|
|
veejay_memset(hist,0,sizeof(hist));
|
|
|
|
// find average and most occuring pixel
|
|
for( i = y1; i < y2; i ++ )
|
|
{
|
|
for( j = x1; j < x2 ; j ++ )
|
|
{
|
|
p0 = (img[i*v->w+j] >= 255 ? 0: img[i * v->w + j]);
|
|
nc += p0;
|
|
hist[ p0 ] ++;
|
|
it ++;
|
|
}
|
|
}
|
|
|
|
for( i =0 ;i < 256; i ++ )
|
|
{
|
|
if( hist[i] > ji )
|
|
{
|
|
ii = i;
|
|
ji = hist[i];
|
|
}
|
|
}
|
|
|
|
unsigned int avg = 0;
|
|
if( nc > 0 )
|
|
avg = (nc / it);
|
|
|
|
int diff = abs( ii - avg );
|
|
for( i = y1; i < y2; i ++ )
|
|
{
|
|
pixels_row = 0;
|
|
for( j = x1; j < x2 ; j ++ )
|
|
{
|
|
if (abs(img[i * v->w + j] - diff)>= avg)
|
|
{
|
|
pixels_row++;
|
|
}
|
|
}
|
|
product_row += (i * pixels_row);
|
|
pixels_row_c += pixels_row;
|
|
}
|
|
|
|
for( i = x1; i < x2; i ++ )
|
|
{
|
|
pixels_col = 0;
|
|
for( j = y1; j < y2; j ++ )
|
|
{
|
|
if (abs(img[i * v->w + j] - diff)>= avg)
|
|
{
|
|
pixels_col ++;
|
|
}
|
|
}
|
|
product_col += (i * pixels_col);
|
|
product_col_c += pixels_col;
|
|
}
|
|
|
|
if( pixels_row_c == 0 || product_col_c == 0 )
|
|
return 0;
|
|
|
|
|
|
uint32_t cy = ( product_row / pixels_row_c );
|
|
uint32_t cx = ( product_col / product_col_c );
|
|
|
|
*dx = (float) cx / (v->w / 100.0f);
|
|
*dy = (float) cy / (v->h / 100.0f);
|
|
|
|
return 1;
|
|
}*/
|
|
|
|
void viewport_projection_inc( void *data, int incr, int screen_width, int screen_height )
|
|
{
|
|
}
|
|
/*
|
|
#define ANIMAX
|
|
|
|
#ifdef ANIMAX
|
|
#include <libvjnet/mcastsender.h>
|
|
#define GROUP "227.0.0.17"
|
|
#define PORT_NUM 1234
|
|
#endif
|
|
|
|
typedef struct
|
|
{
|
|
int x;
|
|
int y;
|
|
} point_t;
|
|
|
|
inline int is_left( point_t *p0, point_t *p1, point_t *p2 )
|
|
{
|
|
return (
|
|
(p1->x - p0->x) * (p2->y - p0->y) -
|
|
(p2->x - p0->x) * (p1->y - p0->y)
|
|
);
|
|
}
|
|
|
|
//@ chainhull 2D (C) 2001 softSurfer (www.softsurfer.com)
|
|
//@ http://geometryalgorithms.com/Archive/algorithm_0109/algorithm_0109.htm
|
|
point_t **chainhull_2d( point_t **p , int n, int *res )
|
|
{
|
|
point_t **H = (point_t**) vj_malloc( n * sizeof(point_t));
|
|
int i;
|
|
|
|
int bot=0, top=-1;
|
|
|
|
int xmin = p[0]->x;
|
|
for( i = 1; i < n; i++)
|
|
if( p[i]->x != xmin ) break;
|
|
int minmax = i-1;
|
|
int minmin = 0;
|
|
if( minmax == (n-1)) {
|
|
H[++top] = p[minmin];
|
|
if( p[minmax]->y != p[minmin]->y )
|
|
H[++top] = p[minmax];
|
|
H[++top] = p[minmin];
|
|
*res = top + 1;
|
|
}
|
|
|
|
int maxmin,maxmax = n-1;
|
|
int xmax = p[n-1]->x;
|
|
for( i = n-2; i >= 0; i -- )
|
|
if( p[i]->x != xmax ) break;
|
|
maxmin = i+1;
|
|
|
|
H[++top] = p[minmin];
|
|
i= minmax;
|
|
while( ++i <= maxmin )
|
|
{
|
|
if ( is_left( p[minmin], p[maxmin], p[i]) >= 0 && i < maxmin )
|
|
continue;
|
|
while( top > 0 )
|
|
{
|
|
if ( is_left( H[top-1], H[top], p[i] ) > 0 )
|
|
break;
|
|
else
|
|
top--;
|
|
}
|
|
H[++top] = p[i];
|
|
}
|
|
|
|
|
|
if( maxmax != maxmin )
|
|
H[++top] = p[maxmax];
|
|
bot = top;
|
|
i = maxmin;
|
|
while( --i >= minmax )
|
|
{
|
|
if( is_left( p[maxmax], p[minmax], p[i] ) >= 0 && i > minmax )
|
|
continue;
|
|
while( top > bot )
|
|
{
|
|
if( is_left( H[top-1], H[top], p[i] ) > 0 )
|
|
break;
|
|
else
|
|
top--;
|
|
}
|
|
H[++top] = p[i];
|
|
}
|
|
if( minmax != minmin )
|
|
H[++top] = p[minmin];
|
|
|
|
*res = top + 1;
|
|
|
|
return H;
|
|
}
|
|
|
|
static void shell_sort_points_by_degree( double *a , point_t **p, int n )
|
|
{
|
|
int i,j,increment=3;
|
|
double temp;
|
|
int dx,dy;
|
|
while( increment > 0 )
|
|
{
|
|
for( i = 0; i < n; i ++ )
|
|
{
|
|
j=i;
|
|
temp = a[i];
|
|
dx = p[i]->x;
|
|
dy = p[i]->y;
|
|
while(( j>= increment) && (a[j-increment] > temp ))
|
|
{
|
|
a[j] = a[j-increment];
|
|
p[j]->x = p[j-increment]->x;
|
|
p[j]->y = p[j-increment]->y;
|
|
j = j - increment;
|
|
}
|
|
a[j] = temp;
|
|
p[j]->x = dx;
|
|
p[j]->y = dy;
|
|
}
|
|
if( increment / 2 != 0 )
|
|
increment = increment / 2;
|
|
else if (increment ==1 )
|
|
increment = 0;
|
|
else
|
|
increment = 1;
|
|
}
|
|
|
|
}
|
|
|
|
static void sort_points_by_degree( double *a, point_t **p, int n )
|
|
{
|
|
int i;
|
|
for( i = 2; i <= n; i ++ )
|
|
{
|
|
float sentinel = a[i];
|
|
point_t point;
|
|
point.x = p[i]->x;
|
|
point.y = p[i]->y;
|
|
int k = i;
|
|
while( sentinel < a[k-1] && k > 0)
|
|
{
|
|
int j = k;
|
|
a[k] = a[--k];
|
|
p[j]->x = p[k]->x;
|
|
p[j]->y = p[k]->y;
|
|
}
|
|
a[k] = sentinel;
|
|
p[k]->x = point.x;
|
|
p[k]->y = point.y;
|
|
}
|
|
}
|
|
|
|
#define VEEJAY_PACKET_SIZE 16384
|
|
|
|
void viewport_dummy_send( void *data )
|
|
{
|
|
viewport_t *v = (viewport_t*) data;
|
|
#ifdef ANIMAX
|
|
unsigned char empty_buf[VEEJAY_PACKET_SIZE];
|
|
veejay_memset( empty_buf, 0, VEEJAY_PACKET_SIZE );
|
|
|
|
if(! v->sender )
|
|
{
|
|
v->sender = mcast_new_sender( GROUP );
|
|
v->seq_id = 0;
|
|
}
|
|
if(!v->sender)
|
|
return;
|
|
|
|
int result = mcast_send( v->sender, empty_buf,VEEJAY_PACKET_SIZE, PORT_NUM );
|
|
if(result<=0)
|
|
{
|
|
veejay_msg(0, "Cannot send empty packet over mcast %s:%d", GROUP,PORT_NUM );
|
|
mcast_close_sender( v->sender );
|
|
v->sender = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void viewport_transform_coords(
|
|
void *data,
|
|
void *input,
|
|
int n,
|
|
int blob_id,
|
|
int center_x,
|
|
int center_y,
|
|
int wid,
|
|
int hei,
|
|
int num_objects,
|
|
uint8_t *plane )
|
|
{
|
|
int i, res = 0;
|
|
viewport_t *v = (viewport_t*) data;
|
|
#ifdef ANIMAX
|
|
if(! v->sender )
|
|
{
|
|
v->sender = mcast_new_sender( GROUP );
|
|
v->seq_id = 0;
|
|
veejay_memset( v->buf, 0, VEEJAY_PACKET_SIZE );
|
|
}
|
|
if(!v->sender)
|
|
return;
|
|
#endif
|
|
|
|
if( n <= 0 )
|
|
{
|
|
viewport_dummy_send( data );
|
|
return;
|
|
}
|
|
|
|
if( !v->T )
|
|
{
|
|
matrix_t *tmp = viewport_matrix();
|
|
v->T = viewport_invert_matrix( v->M, tmp );
|
|
free(tmp);
|
|
}
|
|
|
|
point_t **points = (point_t**) input;
|
|
double *array = (double*) vj_malloc( (n+3) * sizeof(double));
|
|
|
|
for( i = 0; i < n; i ++ )
|
|
array[i] = atan2( (points[i]->x - center_x), (points[i]->y - center_y) ) * (180.0/M_PI );
|
|
|
|
//@ convex hull
|
|
point_t **contour = chainhull_2d( points, n, &res );
|
|
|
|
if( res > 256 )
|
|
{
|
|
veejay_msg(1, "Convex Hull has %d points, Maximum allowed is 256", res );
|
|
res = 256;
|
|
}
|
|
|
|
if ( plane )
|
|
{
|
|
for( i = 0; i < (res-1); i ++ )
|
|
{
|
|
//@ draw polygon
|
|
viewport_line( plane,
|
|
contour[i]->x,
|
|
contour[i]->y,
|
|
contour[i+1]->x,
|
|
contour[i+1]->y,
|
|
wid,
|
|
hei,
|
|
200 );
|
|
}
|
|
|
|
plane[ center_y * wid + center_x ] = 0xff; //@ display centroid
|
|
}
|
|
|
|
shell_sort_points_by_degree( array, points, n );
|
|
|
|
//@ Protocol:
|
|
//@ bytes 0 ... 4 : blob id
|
|
// 4 ... 8 : number of points in convex hull
|
|
// 8 ... 12 : header symbol
|
|
// 12 ... 16 : sequence number
|
|
// 16 ... 20 : total number of blobs
|
|
// 20 ... 24 : number of points in contour
|
|
// 24 ... N1 : convex hull points
|
|
// N1 ... N2 : contour hull points
|
|
//
|
|
// packet size: 16 Kbytes
|
|
|
|
v->buf[0] = blob_id;
|
|
v->buf[1] = res*2;
|
|
v->buf[2] = -1;
|
|
v->buf[3] = v->seq_id ++;
|
|
v->buf[4] = num_objects;
|
|
v->buf[5] = n*2;
|
|
int j = 6;
|
|
for( i = 0; i < res; i ++ )
|
|
{
|
|
float dx1,dy1;
|
|
point_map( v->T, contour[i]->x, contour[i]->y, &dx1, &dy1 );
|
|
v->buf[j + 0] = (int)((dx1/ (float) v->w) * 1000.0f );
|
|
v->buf[j + 1] = (int)((dy1/ (float) v->h) * 1000.0f );
|
|
j+=2;
|
|
}
|
|
|
|
for( i = 0; i < n; i ++ )
|
|
{
|
|
float dx1,dy1;
|
|
point_map( v->T, points[i]->x, points[i]->y, &dx1,&dy1 );
|
|
v->buf[j + 0] = (int) ( ( dx1/(float) v->w) * 1000.0f );
|
|
v->buf[j + 1] = (int) ( ( dy1/(float) v->h) * 1000.0f );
|
|
j += 2;
|
|
}
|
|
int payload = ((n*2)+(res * 2) + 6) * sizeof(int);
|
|
int left = VEEJAY_PACKET_SIZE - payload;
|
|
|
|
int *ptr = &(v->buf[j]);
|
|
|
|
if(left > 0)
|
|
veejay_memset( ptr,0, left );
|
|
|
|
if( payload > VEEJAY_PACKET_SIZE )
|
|
veejay_msg(1, "Contours and convex hull too large for packet");
|
|
|
|
#ifdef ANIMAX
|
|
int result = mcast_send( v->sender, v->buf,VEEJAY_PACKET_SIZE, PORT_NUM );
|
|
if(result<=0)
|
|
{
|
|
veejay_msg(0, "Cannot send contour/convex hull over mcast %s:%d", GROUP,PORT_NUM );
|
|
mcast_close_sender( v->sender );
|
|
v->sender = NULL;
|
|
}
|
|
#endif
|
|
|
|
free(contour);
|
|
free(array);
|
|
|
|
}
|
|
|
|
int *viewport_event_get_projection(void *data, int scale) {
|
|
viewport_t *v = (viewport_t*) data;
|
|
float fscale = 1.0f;
|
|
float set[9];
|
|
if( scale == 100 ) {
|
|
set[0] = v->x1;// * sw;
|
|
set[1] = v->y1;// * sh;
|
|
set[2] = v->x2;// * sw;
|
|
set[3] = v->y2;// * sh;
|
|
set[4] = v->x3;// * sw;
|
|
set[5] = v->y3;// * sh;
|
|
set[6] = v->x4;// * sw;
|
|
set[7] = v->y4;// * sh;
|
|
} else {
|
|
float sw = (float) scale / 100.0;
|
|
float sh = (float) scale / 100.0;
|
|
fscale = sw;
|
|
set[0] = v->x1 * sw;
|
|
set[1] = v->y1 * sh;
|
|
set[2] = v->x2 * sw;
|
|
set[3] = v->y2 * sh;
|
|
set[4] = v->x3 * sw;
|
|
set[5] = v->y3 * sh;
|
|
set[6] = v->x4 * sw;
|
|
set[7] = v->y4 * sh;
|
|
}
|
|
|
|
int *res = (int*) vj_malloc(sizeof(int) * 8 );
|
|
int i;
|
|
|
|
for( i = 0; i < 8 ; i ++ ) {
|
|
res[i] = (int) ( set[i]);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
int viewport_event_set_projection(void *data, float x, float y, int num, int frontback) {
|
|
|
|
|
|
viewport_t *v = (viewport_t*) data;
|
|
switch(num) {
|
|
case 1:
|
|
v->x1 = x;
|
|
v->y1 = y;
|
|
break;
|
|
case 2:
|
|
v->x2 = x;
|
|
v->y2 = y;
|
|
break;
|
|
case 3:
|
|
v->x3 = x;
|
|
v->y3 = y;
|
|
break;
|
|
case 4:
|
|
v->x4 = x;
|
|
v->y4 = y;
|
|
break;
|
|
}
|
|
float p[8];
|
|
p[0] = v->x1;
|
|
p[2] = v->x2;
|
|
p[4] = v->x3;
|
|
p[6] = v->x4;
|
|
p[1] = v->y1;
|
|
p[3] = v->y2;
|
|
p[5] = v->y3;
|
|
p[7] = v->y4;
|
|
|
|
if( viewport_update_perspective( v, p ) ) {
|
|
veejay_msg(VEEJAY_MSG_INFO, "Accepted viewport configuration from remote.");
|
|
} else {
|
|
veejay_msg(0, "Error updating points");
|
|
}
|
|
|
|
return 1;
|
|
}*/
|
|
|
|
|
|
int viewport_finetune_coord(void *data, int screen_width, int screen_height,int inc_x, int inc_y)
|
|
{
|
|
viewport_t *v = (viewport_t*) data;
|
|
if(!v->user_ui)
|
|
return 0;
|
|
|
|
int point = -1;
|
|
int i;
|
|
|
|
//@ use screen width/height
|
|
double dist = 100.0;
|
|
int x = v->usermouse[4];
|
|
int y = v->usermouse[5];
|
|
float p_cpy[9];
|
|
float p[9];
|
|
|
|
p[0] = v->x1;
|
|
p[2] = v->x2;
|
|
p[4] = v->x3;
|
|
p[6] = v->x4;
|
|
p[1] = v->y1;
|
|
p[3] = v->y2;
|
|
p[5] = v->y3;
|
|
p[7] = v->y4;
|
|
|
|
int j;
|
|
|
|
float ix = (float) inc_x * 0.1f;
|
|
float iy = (float) inc_y * 0.1f;
|
|
|
|
for ( j = 0 ; j < 8 ; j += 2 ) {
|
|
p_cpy[j] = p[j];
|
|
p_cpy[j+1]=p[j+1];
|
|
p[j] = msx(v, p[j] );
|
|
p[j+1]= msy(v, p[j+1] );
|
|
}
|
|
|
|
if( v->user_ui )
|
|
{
|
|
double dt[4];
|
|
dt[0] = sqrt( (p[0] - x) * (p[0] - x) + ( p[1] - y ) * (p[1] -y ) );
|
|
dt[1] = sqrt( (p[2] - x) * (p[2] - x) + ( p[3] - y ) * (p[3] -y ) );
|
|
dt[2] = sqrt( (p[4] - x) * (p[4] - x) + ( p[5] - y ) * (p[5] -y ) );
|
|
dt[3] = sqrt( (p[6] - x) * (p[6] - x) + ( p[7] - y ) * (p[7] -y ) );
|
|
|
|
for ( i = 0; i < 4; i ++ )
|
|
{
|
|
if( dt[i] < dist )
|
|
{
|
|
dist = dt[i];
|
|
point = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( point < 0 )
|
|
return 0;
|
|
|
|
switch( point )
|
|
{
|
|
case 0:
|
|
v->x1 = vsx(v, p[0] + ix);
|
|
v->y1 = vsy(v, p[1] + iy);
|
|
break;
|
|
case 1:
|
|
v->x2 = vsx(v, p[2] + ix);
|
|
v->y2 = vsy(v, p[3] + iy);
|
|
break;
|
|
case 2:
|
|
v->x3 = vsx(v,p[4] + ix);
|
|
v->y3 = vsy(v,p[5] + iy);
|
|
break;
|
|
case 3:
|
|
v->x4 = vsx(v,p[6] + ix);
|
|
v->y4 = vsy(v,p[7] + iy);
|
|
break;
|
|
}
|
|
viewport_update_perspective( v, p_cpy );
|
|
if(v->grid)
|
|
viewport_compute_grid(v);
|
|
return 1;
|
|
}
|
|
|
|
int viewport_external_mouse( void *data, uint8_t *img[3], int sx, int sy, int button, int frontback, int screen_width, int screen_height, char *homedir, int mode, int id )
|
|
{
|
|
viewport_t *v = (viewport_t*) data;
|
|
if( sx == 0 && sy == 0 && button == 0 )
|
|
return 0;
|
|
if( button == 3 && v->user_ui == 0 )
|
|
return 0;
|
|
|
|
int ch = 0;
|
|
int point = -1;
|
|
int i;
|
|
|
|
//@ use screen width/height
|
|
float x = (float)sx / ( screen_width / 100.0f );
|
|
float y = (float)sy / ( screen_height / 100.0f );
|
|
double dist = 100.0;
|
|
int cx = v->w / 2;
|
|
int cy = v->h / 2;
|
|
int dx = cx - ( v->ui->sw / 2 );
|
|
int dy = cy - ( v->ui->sh / 2 );
|
|
float scx = (float) v->w / (float) v->ui->sw;
|
|
float scy = (float) v->h / (float) v->ui->sh;
|
|
int nsx = (sx - dx) * scx;
|
|
int nsy = (sy - dy) * scy;
|
|
|
|
v->usermouse[2] = (float) nsx;
|
|
v->usermouse[3] = (float) nsy;
|
|
v->usermouse[4] = x;
|
|
v->usermouse[5] = y;
|
|
|
|
float p_cpy[9];
|
|
float p[9];
|
|
// make a copy of the parameters
|
|
|
|
p[0] = v->x1;
|
|
p[2] = v->x2;
|
|
p[4] = v->x3;
|
|
p[6] = v->x4;
|
|
p[1] = v->y1;
|
|
p[3] = v->y2;
|
|
p[5] = v->y3;
|
|
p[7] = v->y4;
|
|
|
|
int j;
|
|
for ( j = 0 ; j < 8 ; j += 2 ) {
|
|
p_cpy[j] = p[j];
|
|
p_cpy[j+1]=p[j+1];
|
|
p[j] = msx(v, p[j] );
|
|
p[j+1]= msy(v, p[j+1] );
|
|
}
|
|
|
|
float tx = vsx(v,v->usermouse[4]);
|
|
float ty = vsy(v,v->usermouse[5]);
|
|
|
|
for( i = 0; i < 4 ; i ++ )
|
|
v->users[ i ] = 1;
|
|
|
|
if( v->user_ui )
|
|
{
|
|
double dt[4];
|
|
dt[0] = sqrt( (p[0] - x) * (p[0] - x) + ( p[1] - y ) * (p[1] -y ) );
|
|
dt[1] = sqrt( (p[2] - x) * (p[2] - x) + ( p[3] - y ) * (p[3] -y ) );
|
|
dt[2] = sqrt( (p[4] - x) * (p[4] - x) + ( p[5] - y ) * (p[5] -y ) );
|
|
dt[3] = sqrt( (p[6] - x) * (p[6] - x) + ( p[7] - y ) * (p[7] -y ) );
|
|
|
|
for ( i = 0; i < 4; i ++ )
|
|
{
|
|
if( dt[i] < dist )
|
|
{
|
|
dist = dt[i];
|
|
point = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
v->save = 0;
|
|
|
|
if( ( button == 6 || button == 1 || button == 12) && point >= 0 )
|
|
v->save = 1;
|
|
|
|
if( button == 0 && point >= 0)
|
|
v->users[ point ] = 2;
|
|
|
|
if( button == 0 )
|
|
{
|
|
v->usermouse[0] = x;
|
|
v->usermouse[1] = y;
|
|
}
|
|
|
|
if( button == 2 )
|
|
{
|
|
if(v->user_reverse) v->user_reverse = 0; else v->user_reverse = 1;
|
|
ch = 1;
|
|
}
|
|
|
|
if( button == 3 )
|
|
{
|
|
if(v->user_ui) v->user_ui = 0; else v->user_ui = 1;
|
|
|
|
if( v->user_ui == 0 )
|
|
{
|
|
char filename[1024];
|
|
switch(mode) {
|
|
case 1:
|
|
snprintf(filename,sizeof(filename), "%s/viewport-stream-%d.cfg", homedir,id );
|
|
break;
|
|
case 0:
|
|
snprintf(filename,sizeof(filename), "%s/viewport-sample-%d.cfg", homedir,id );
|
|
break;
|
|
default:
|
|
snprintf(filename,sizeof(filename),"%s/viewport.cfg", homedir);
|
|
break;
|
|
}
|
|
|
|
viewport_save_settings(v, frontback, filename);
|
|
}
|
|
}
|
|
|
|
|
|
if( button == 6 && point >= 0)
|
|
{
|
|
switch( point )
|
|
{
|
|
case 0:
|
|
v->x0 = (int32_t)nsx;
|
|
v->y0 = (int32_t)nsy;
|
|
clamp1(v->x0, 0, v->w );
|
|
clamp1(v->y0, 0, v->h );
|
|
break;
|
|
case 1:
|
|
v->w0 = nsx - v->x0;
|
|
v->y0 = nsy;
|
|
clamp1(v->w0, 0,v->w );
|
|
clamp1(v->y0, 0,v->h );
|
|
break;
|
|
case 2:
|
|
v->w0 = nsx - v->x0;
|
|
v->h0 = nsy - v->y0;
|
|
clamp1(v->w0, 0,v->w );
|
|
clamp1(v->h0, 0,v->h );
|
|
break;
|
|
case 3:
|
|
v->w0 = ( v->x0 - nsx ) + v->w0;
|
|
v->x0 = nsx;
|
|
v->h0 = nsy - v->y0;
|
|
clamp1(v->x0, 0,v->w );
|
|
clamp1(v->h0, 0,v->h );
|
|
clamp1(v->w0, 0,v->w );
|
|
break;
|
|
}
|
|
ch = 1;
|
|
}
|
|
|
|
if( button == 15 ) {
|
|
v->grid_mode --;
|
|
if(v->grid_mode < 0 )
|
|
v->grid_mode = 2;
|
|
}
|
|
|
|
if( button == 5 ) // wheel up
|
|
{
|
|
if(v->grid_mode == 0 ) {
|
|
v->marker_size --;
|
|
if(v->marker_size < 2 )
|
|
v->marker_size = 4;
|
|
} else {
|
|
v->grid_resolution -= GRID_STEP;
|
|
if(v->grid_resolution < 2 )
|
|
v->grid_resolution = 2;
|
|
viewport_compute_grid(v);
|
|
}
|
|
}
|
|
|
|
if( button == 16 )
|
|
{
|
|
v->grid_mode ++;
|
|
if(v->grid_mode > 2 )
|
|
v->grid_mode = 0;
|
|
}
|
|
|
|
if (button == 4 ) // wheel down
|
|
{
|
|
if(v->grid_mode == 0 ) {
|
|
v->marker_size ++;
|
|
if(v->marker_size > v->w/16)
|
|
v->marker_size = 4;
|
|
} else {
|
|
v->grid_resolution += GRID_STEP;
|
|
if(v->grid_resolution > v->w )
|
|
v->grid_resolution = v->w;
|
|
viewport_compute_grid(v);
|
|
}
|
|
}
|
|
if( button == 7 )
|
|
{
|
|
if( v->grid_val == 0xff )
|
|
v->grid_val = 0;
|
|
else
|
|
v->grid_val = 0xff;
|
|
}
|
|
|
|
|
|
if(v->save)
|
|
{
|
|
if( button == 12 )
|
|
{
|
|
}
|
|
else if( button == 1 )
|
|
{
|
|
switch( point )
|
|
{
|
|
case 0:
|
|
v->x1 = tx;
|
|
v->y1 = ty;
|
|
break;
|
|
case 1:
|
|
v->x2 = tx;
|
|
v->y2 = ty;
|
|
break;
|
|
case 2:
|
|
v->x3 = tx;
|
|
v->y3 = ty;
|
|
break;
|
|
case 3:
|
|
v->x4 = tx;
|
|
v->y4 = ty;
|
|
break;
|
|
|
|
}
|
|
}
|
|
ch = 1;
|
|
|
|
}
|
|
|
|
if( ch )
|
|
{
|
|
viewport_update_perspective( v, p_cpy );
|
|
if(v->grid)
|
|
viewport_compute_grid(v);
|
|
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
void viewport_push_frame(void *data, int w, int h, uint8_t *Y, uint8_t *U, uint8_t *V )
|
|
{
|
|
viewport_t *v = (viewport_t*) data;
|
|
ui_t *u = v->ui;
|
|
VJFrame *srci = yuv_yuv_template( Y, U,V, w,h, PIX_FMT_GRAY8 );
|
|
VJFrame *dsti = yuv_yuv_template( u->buf[0],NULL,NULL,u->sw, u->sh, PIX_FMT_GRAY8);
|
|
|
|
yuv_convert_and_scale( u->scaler, srci,dsti );
|
|
free(srci);
|
|
free(dsti);
|
|
}
|
|
|
|
static void viewport_translate_frame(void *data, uint8_t *plane )
|
|
{
|
|
viewport_t *v = (viewport_t*) data;
|
|
ui_t *u = v->ui;
|
|
int cx = v->w / 2;
|
|
int cy = v->h / 2;
|
|
int w = v->w;
|
|
int dx = cx - ( u->sw / 2 );
|
|
int dy = cy - ( u->sh / 2 );
|
|
|
|
int x,y;
|
|
|
|
uint8_t *img = u->buf[0];
|
|
for( y = 0; y < u->sh; y ++ ) {
|
|
for( x = 0; x < u->sw; x ++ ) {
|
|
plane[ (dy + y ) * w + dx + x ] = img[ y * u->sw + x ];
|
|
}
|
|
}
|
|
}
|
|
|
|
static void viewport_draw_marker(viewport_t *v, int x, int y, int w, int h, uint8_t *plane )
|
|
{
|
|
int x1 = x - v->marker_size;
|
|
int y1 = y - v->marker_size;
|
|
int x2 = x + v->marker_size;
|
|
int y2 = y + v->marker_size;
|
|
|
|
if( x1 < 0 ) x1 = 0; else if ( x1 > w ) x1 = w;
|
|
if( y1 < 0 ) y1 = 0; else if ( y1 > h ) y1 = h;
|
|
if( x2 < 0 ) x2 = 0; else if ( x2 > w ) x2 = w;
|
|
if( y2 < 0 ) y2 = 0; else if ( y2 > h ) y2 = h;
|
|
|
|
unsigned int i,j;
|
|
for( j = x1; j < x2 ; j ++ )
|
|
plane[ y1 * w + j ] = v->grid_val;
|
|
|
|
for( i = y1; i < y2; i ++ )
|
|
{
|
|
plane[ i * w + x1 ] = v->grid_val;
|
|
plane[ i * w + x2 ] = v->grid_val;
|
|
}
|
|
|
|
for( j = x1; j < x2 ; j ++ )
|
|
plane[ y2 * w + j ] = v->grid_val;
|
|
|
|
}
|
|
|
|
static void viewport_draw_grid(viewport_t *v, int width, int height, uint8_t *plane )
|
|
{
|
|
int x,y;
|
|
grid_t *grid = v->grid;
|
|
int k = 0;
|
|
int n = v->grid_width * v->grid_height;
|
|
int j = 0;
|
|
for( y = 0; y < v->grid_height; y ++) {
|
|
k = y * v->grid_width;
|
|
j = k + v->grid_width-1;
|
|
viewport_line( plane, grid[k].x, grid[k].y,
|
|
grid[j].x, grid[j].y,
|
|
width,height,
|
|
170);
|
|
}
|
|
|
|
k = 0;
|
|
n = (v->grid_height-1) * v->grid_width;
|
|
for( x = 0; x < v->grid_width; x ++ )
|
|
{
|
|
k = x;
|
|
j = n + x;
|
|
viewport_line( plane, grid[k].x, grid[k].y,
|
|
grid[j].x, grid[j].y,
|
|
width,height,
|
|
170);
|
|
}
|
|
}
|
|
|
|
static void viewport_draw_points(viewport_t *v, int width, int height, uint8_t *plane )
|
|
{
|
|
int k;
|
|
for(k = 0; k < (v->grid_width*v->grid_height); k ++ )
|
|
{
|
|
int x=v->grid[k].x;
|
|
int y=v->grid[k].y;
|
|
if( x >= 0 && y >= 0 && x < width && y < height )
|
|
plane[y * width + x] = v->grid_val;
|
|
}
|
|
}
|
|
static void viewport_compute_grid( viewport_t *v )
|
|
{
|
|
int k = 0;
|
|
int gw = v->w/ v->grid_resolution;
|
|
int gh = v->h/v->grid_resolution;
|
|
v->grid_width = gw;
|
|
v->grid_height = gh;
|
|
|
|
int x,y;
|
|
if(v->grid) {
|
|
free(v->grid);
|
|
v->grid = NULL;
|
|
}
|
|
if(!v->grid) {
|
|
v->grid = (grid_t*) vj_malloc(sizeof(grid_t) * gw *gh);
|
|
}
|
|
grid_t *grid = v->grid;
|
|
|
|
for(y = 0; y < gh; y ++ )
|
|
for( x = 0; x < gw; x ++ ) {
|
|
point_map_int( v->M, x * v->grid_resolution,
|
|
y * v->grid_resolution,&(grid[k].x), &(grid[k].y));
|
|
k++;
|
|
}
|
|
}
|
|
|
|
|
|
void viewport_set_marker( void *data, int status )
|
|
{
|
|
viewport_t *v = (viewport_t*) data;
|
|
v->snap_marker = status;
|
|
//v->marker_size = 1;
|
|
}
|
|
|
|
static void viewport_draw_col( void *data, uint8_t *plane, uint8_t *u, uint8_t *V )
|
|
{
|
|
viewport_t *v = (viewport_t*) data;
|
|
int width = v->w;
|
|
int height = v->h;
|
|
|
|
float wx =(float) v->w / 100.0f;
|
|
float wy =(float) v->h / 100.0f;
|
|
|
|
int fx1 = (int)( msx(v,v->x1) *wx );
|
|
int fy1 = (int)( msy(v,v->y1) *wy );
|
|
int fx2 = (int)( msx(v,v->x2) *wx );
|
|
int fy2 = (int)( msy(v,v->y2) *wy );
|
|
int fx3 = (int)( msx(v,v->x3) *wx );
|
|
int fy3 = (int)( msy(v,v->y3) *wy );
|
|
int fx4 = (int)( msx(v,v->x4) *wx );
|
|
int fy4 = (int)( msy(v,v->y4) *wy );
|
|
|
|
const uint8_t p = v->grid_val;
|
|
|
|
if(v->grid)
|
|
switch(v->grid_mode)
|
|
{
|
|
case 2:
|
|
viewport_draw_grid(v,width,height,plane);
|
|
break;
|
|
case 1:
|
|
viewport_draw_points(v,width,height,plane);
|
|
break;
|
|
}
|
|
|
|
|
|
viewport_line( plane, fx1, fy1, fx2,fy2,width,height, p);
|
|
viewport_line( plane, fx1, fy1, fx4,fy4,width,height, p );
|
|
viewport_line( plane, fx4, fy4, fx3,fy3,width,height, p );
|
|
viewport_line( plane, fx2, fy2, fx3,fy3,width,height, p );
|
|
|
|
//@ Project rectangle in v->w * v->h , but scaled to size of >sw >sh
|
|
ui_t *ui = v->ui;
|
|
int cx = v->w / 2;
|
|
int cy = v->h / 2;
|
|
int dx = cx - ( ui->sw / 2 );
|
|
int dy = cy - ( ui->sh / 2 );
|
|
float s = (float) v->w / (float) v->ui->sw;
|
|
float sy = (float) v->h / (float) v->ui->sh;
|
|
int vx0 = (v->x0 / s) + dx;
|
|
int vy0 = (v->y0 / sy) + dy;
|
|
int vw0 = v->w0 / s;
|
|
int vh0 = v->h0 / sy;
|
|
|
|
viewport_line( plane, v->x0, v->y0, v->x0 + v->w0, v->y0, width,height, 110);
|
|
viewport_line( plane, v->x0+v->w0, v->y0, v->x0 + v->w0, v->y0 + v->h0, width,height, 110 );
|
|
viewport_line( plane, v->x0 + v->w0, v->y0 + v->h0, v->x0, v->y0 + v->h0, width,height, 110 );
|
|
viewport_line( plane, v->x0, v->y0 +v->h0, v->x0, v->y0, width,height, 110);
|
|
|
|
|
|
//* Projection quad
|
|
viewport_line( plane, vx0, vy0, vx0 + vw0, vy0, width,height, 65);
|
|
viewport_line( plane, vx0+vw0, vy0, vx0 + vw0, vy0 + vh0, width,height, 65 );
|
|
viewport_line( plane, vx0 + vw0, vy0 + vh0, vx0, vy0 + vh0, width,height, 65 );
|
|
viewport_line( plane, vx0, vy0 +vh0, vx0, vy0, width,height, 65);
|
|
|
|
|
|
draw_point( plane, fx1,fy1, width,height, v->users[0],p );
|
|
draw_point( plane, fx2,fy2, width,height, v->users[1],p );
|
|
draw_point( plane, fx3,fy3, width,height, v->users[2],p );
|
|
draw_point( plane, fx4,fy4, width,height, v->users[3],p );
|
|
|
|
int mx = v->usermouse[0] * wx;
|
|
int my = v->usermouse[1] * wy;
|
|
|
|
viewport_draw_marker(v, mx,my,width,height,plane );
|
|
|
|
|
|
if( mx >= 0 && my >= 0 && mx <= width && my < height )
|
|
{
|
|
if( mx >= 0 && my >= 0 && mx < width && my < height )
|
|
{
|
|
if( abs(v->grid_val - plane[my*width+mx]) < 32 )
|
|
plane[my*width+mx] = 0xff - plane[my*width+mx];
|
|
else
|
|
plane[my * width + mx] = v->grid_val;
|
|
}
|
|
}
|
|
}
|
|
|
|
int viewport_render_ssm(void *vdata )
|
|
{
|
|
viewport_t *v = (viewport_t*) vdata;
|
|
|
|
if( v->disable || v->user_ui)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void viewport_draw_interface_color( void *vdata, uint8_t *img[3] )
|
|
{
|
|
viewport_t *v = (viewport_t*) vdata;
|
|
viewport_translate_frame( v, img[0] );
|
|
viewport_draw_col( v, img[0],img[1],img[2] );
|
|
}
|
|
|
|
void viewport_produce_full_img( void *vdata, uint8_t *img[3], uint8_t *out_img[3] )
|
|
{
|
|
viewport_t *v = (viewport_t*) vdata;
|
|
const int w = v->w;
|
|
uint32_t i,n;
|
|
const int32_t *map = v->map;
|
|
const uint8_t *inY = (const uint8_t*) img[0];
|
|
const uint8_t *inU = (const uint8_t*)img[1];
|
|
const uint8_t *inV = (const uint8_t*)img[2];
|
|
uint8_t *outY = out_img[0];
|
|
uint8_t *outU = out_img[1];
|
|
uint8_t *outV = out_img[2];
|
|
|
|
const int32_t tx1 = v->ttx1;
|
|
const int32_t tx2 = v->ttx2;
|
|
const int32_t ty1 = v->tty1;
|
|
const int32_t ty2 = v->tty2;
|
|
|
|
int x;
|
|
int y = ty1 * w;
|
|
|
|
vj_frame_clear1( out_img[0], 0, v->w * v->h );
|
|
vj_frame_clear1( out_img[1], 128, v->w * v->h * 2 );
|
|
|
|
for( y = ty1; y < ty2; y ++ )
|
|
{
|
|
for( x = tx1; x < tx2 ; x ++ )
|
|
{
|
|
i = y * w + x;
|
|
n = map[i];
|
|
outY[i] = inY[n];
|
|
outU[i] = inU[n];
|
|
outV[i] = inV[n];
|
|
}
|
|
}
|
|
}
|
|
|
|
void viewport_produce_bw_img( void *vdata, uint8_t *img[3], uint8_t *out_img[3], int Yonly)
|
|
{
|
|
if( !Yonly ) {
|
|
viewport_produce_full_img( vdata, img, out_img );
|
|
return;
|
|
}
|
|
|
|
viewport_t *v = (viewport_t*) vdata;
|
|
const int len = v->w * v->h;
|
|
register const int w = v->w;
|
|
register uint32_t i,n;
|
|
const int32_t *map = v->map;
|
|
uint8_t *inY = img[0];
|
|
uint8_t *outY = out_img[0];
|
|
inY[len+1] = 0;
|
|
|
|
register const int32_t tx1 = v->ttx1;
|
|
register const int32_t tx2 = v->ttx2;
|
|
register const int32_t ty1 = v->tty1;
|
|
register const int32_t ty2 = v->tty2;
|
|
|
|
int x,y;
|
|
y = ty1 * w;
|
|
|
|
vj_frame_clear1( outY,0,len);
|
|
|
|
for( y = ty1; y < ty2; y ++ )
|
|
{
|
|
for( x = tx1; x < tx2 ; x ++ )
|
|
{
|
|
i = y * w + x;
|
|
n = map[i];
|
|
outY[i] = inY[n];
|
|
}
|
|
}
|
|
y = (v->h - ty2 ) * w;
|
|
x = ty2 * w;
|
|
}
|
|
|
|
#define pack_yuyv_pixel( y0,u0,u1,y1,v0,v1 )\
|
|
( y0 ) +\
|
|
( ((u0+u1)>>1)<< 8) +\
|
|
( (y1 << 16 )) +\
|
|
( ((v0+v1)>>1)<< 24 )
|
|
|
|
void viewport_produce_full_img_yuyv( void *vdata, uint8_t *img[3], uint8_t *out_img )
|
|
{
|
|
viewport_t *v = (viewport_t*) vdata;
|
|
const int32_t *map = v->map;
|
|
const uint8_t *inY = (const uint8_t*) img[0];
|
|
const uint8_t *inU = (const uint8_t*) img[1];
|
|
const uint8_t *inV = (const uint8_t*) img[2];
|
|
const int32_t tx1 = v->ttx1;
|
|
const int32_t tx2 = v->ttx2;
|
|
const int32_t ty1 = v->tty1;
|
|
const int32_t ty2 = v->tty2;
|
|
const int w = v->w;
|
|
const int uw = v->w >> 1;
|
|
|
|
uint32_t *plane_yuyv = (uint32_t*)out_img;
|
|
uint32_t i,x,y;
|
|
int32_t n,m;
|
|
|
|
img[0][v->w * v->h +1] = 0; // "out of range" pixel value
|
|
img[1][v->w * v->h +1] = 128;
|
|
img[2][v->w * v->h+1] = 128;
|
|
|
|
yuyv_plane_clear( v->w * v->h * 2, plane_yuyv);
|
|
|
|
for( y = ty1 ; y < ty2; y ++ )
|
|
{
|
|
for( x = tx1; x < tx2; x += 2 )
|
|
{ // 2 YUYV pixels out, 2 Y in, 4 UV in
|
|
i = y * w ;
|
|
n = map[ i + x ];
|
|
m = map[ i + x + 1];
|
|
|
|
plane_yuyv[y * uw + ( (x+1)>>1)] = pack_yuyv_pixel( inY[n],inU[n],inU[m],inY[m],inV[n],inV[m] );
|
|
}
|
|
}
|
|
}
|
|
|
|
void viewport_produce_full_img_packed( void *vdata, uint8_t *img[3], uint8_t *out_img )
|
|
{
|
|
viewport_t *v = (viewport_t*) vdata;
|
|
const int len = v->w * v->h;
|
|
const int32_t *map = v->map;
|
|
uint8_t *inY = img[0];
|
|
uint8_t *inU = img[1];
|
|
uint8_t *inV = img[2];
|
|
uint8_t *outYUYV = out_img;
|
|
|
|
inY[len+1] = 0;
|
|
inU[len+1] = 128;
|
|
inV[len+1] = 128;
|
|
|
|
register const int32_t tx1 = v->ttx1;
|
|
register const int32_t tx2 = v->ttx2;
|
|
register const int32_t ty1 = v->tty1;
|
|
register const int32_t ty2 = v->tty2;
|
|
register const int w = v->w;
|
|
register uint32_t n,i,x,y;
|
|
|
|
// clear the yuyv plane (black)
|
|
y = ty1 * w;
|
|
yuyv_plane_clear( len*2, out_img);
|
|
|
|
for( y = ty1 ; y < ty2; y ++ )
|
|
{
|
|
for( x = tx1; x < tx2; x ++ )
|
|
{
|
|
i = y * w + x;
|
|
n = map[ i ];
|
|
outYUYV[3 * i ] = inY[n];
|
|
outYUYV[3 * i + 1 ] = inV[n];
|
|
outYUYV[3 * i + 3 ] = inU[n];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void viewport_render( void *vdata, uint8_t *in[3], uint8_t *out[3],int width, int height, int uv_len )
|
|
{
|
|
viewport_t *v = (viewport_t*) vdata;
|
|
|
|
if( v->disable )
|
|
return;
|
|
|
|
if(! v->user_ui )
|
|
{
|
|
const int len = v->w * v->h;
|
|
const int w = v->w;
|
|
register uint32_t i,j,n;
|
|
const int32_t *map = v->map;
|
|
uint8_t *inY = in[0];
|
|
uint8_t *inU = in[1];
|
|
uint8_t *inV = in[2];
|
|
uint8_t *outY = out[0];
|
|
uint8_t *outU = out[1];
|
|
uint8_t *outV = out[2];
|
|
|
|
inY[len+1] = 0;
|
|
inU[len+1] = 128;
|
|
inV[len+1] = 128;
|
|
|
|
for( i = 0; i < len ; i += v->w )
|
|
{
|
|
for( j = 0; j < w; j += 4 )
|
|
{
|
|
n = map[i + j];
|
|
outY[i + j ] = inY[n];
|
|
outU[i + j ] = inU[n];
|
|
outV[i + j ] = inV[n];
|
|
n = map[ i + j + 1 ];
|
|
outY[ i + 1 + j ] = inY[n];
|
|
outU[ i + 1 + j ] = inU[n];
|
|
outV[ i + 1 + j ] = inV[n];
|
|
n = map[ i + j + 2 ];
|
|
outY[ i + 2 + j ] = inY[n];
|
|
outU[ i + 2 + j ] = inU[n];
|
|
outV[ i + 2 + j ] = inV[n];
|
|
n = map[ i + j + 3 ];
|
|
outY[ i + 3 + j ] = inY[n];
|
|
outU[ i + 3 + j ] = inU[n];
|
|
outV[ i + 3 + j ] = inV[n];
|
|
}
|
|
for( ; j < w; j ++ )
|
|
{
|
|
n = map[i+j];
|
|
outY[i+j] = inY[n];
|
|
outU[i+j] = inU[n];
|
|
outV[i+j] = inV[n];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void viewport_render_dynamic( void *vdata, uint8_t *in[3], uint8_t *out[3],int width, int height )
|
|
{
|
|
viewport_t *v = (viewport_t*) vdata;
|
|
|
|
viewport_process_dynamic( v, in,out );
|
|
|
|
}
|
|
|
|
void *viewport_fx_init_map( int wid, int hei, int x1, int y1,
|
|
int x2, int y2, int x3, int y3, int x4, int y4, int reverse)
|
|
{
|
|
viewport_t *v = (viewport_t*) vj_calloc(sizeof(viewport_t));
|
|
|
|
v->x1 = x1;
|
|
v->y1 = y1;
|
|
v->x2 = x2;
|
|
v->y2 = y2;
|
|
v->x3 = x3;
|
|
v->y3 = y3;
|
|
v->x4 = x4;
|
|
v->y4 = y4;
|
|
|
|
int res = viewport_configure (v,
|
|
v->x1, v->y1,
|
|
v->x2, v->y2,
|
|
v->x3, v->y3,
|
|
v->x4, v->y4,
|
|
0,0,
|
|
wid,hei,
|
|
wid,hei,
|
|
reverse,
|
|
0xff,
|
|
32 );
|
|
|
|
v->user_ui = 0;
|
|
|
|
if(! res )
|
|
{
|
|
veejay_msg(VEEJAY_MSG_ERROR, "Invalid point locations");
|
|
viewport_destroy( v );
|
|
return NULL;
|
|
}
|
|
|
|
return (void*)v;
|
|
}
|
|
|
|
int viewport_get_mode( void *vv ) {
|
|
viewport_t *v = (viewport_t*) vv;
|
|
return v->user_ui;
|
|
}
|
|
|
|
void *viewport_fx_zoom_init(int type, int wid, int hei, int x, int y, int zoom, int dir)
|
|
{
|
|
viewport_t *v = (viewport_t*) vj_calloc(sizeof(viewport_t));
|
|
float fracx = (float) wid;
|
|
float fracy = (float) hei;
|
|
|
|
fracx *= 0.01f;
|
|
fracy *= 0.01f;
|
|
|
|
if( type == VP_QUADZOOM )
|
|
{
|
|
float cx = (float) x;
|
|
float cy = (float) y;
|
|
|
|
cx = cx / fracx;
|
|
cy = cy / fracy;
|
|
|
|
float w = 1.0 * zoom * 0.5;
|
|
float h = 1.0 * zoom * 0.5;
|
|
|
|
v->x1 = cx - w;
|
|
v->y1 = cy - h;
|
|
v->x2 = cx + w;
|
|
v->y2 = cy - h;
|
|
v->x3 = cx + w;
|
|
v->y3 = cy + h;
|
|
v->x4 = cx - w;
|
|
v->y4 = cy + h;
|
|
}
|
|
|
|
int res = viewport_configure (v,
|
|
v->x1, v->y1,
|
|
v->x2, v->y2,
|
|
v->x3, v->y3,
|
|
v->x4, v->y4,
|
|
0,0,
|
|
wid,hei,
|
|
wid,hei,
|
|
dir,
|
|
0xff,
|
|
wid/32 );
|
|
|
|
v->user_ui = 0;
|
|
|
|
if(! res )
|
|
{
|
|
veejay_msg(VEEJAY_MSG_ERROR, "Invalid point locations");
|
|
viewport_destroy( v );
|
|
return NULL;
|
|
}
|
|
|
|
|
|
return (void*)v;
|
|
}
|
|
|
|
|
|
|