Skip to content

Osc shader #223

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,14 @@ EGL, mmal, GLESv2, vcos, openmaxil, vchiq_arm, bcm_host, WFC, OpenVG.
Use buildme to build. It requires cmake to be installed and an arm cross compiler. It is set up to use this one:
https://github.com/raspberrypi/tools/tree/master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian

Raspistill shader parameters can be controlled through OpenSoundControl.
To enable that, you need liblo-dev package.
`sudo apt-get install liblo7 liblo-dev`
Install it and run ./buildme to build raspistill with OSC support.
Then you can control each shader parameters with OSC message.

To cross-compile with liblo support, you can download deb package on your pi with this command :
`apt-get download liblo7 liblo-dev`
Then extract them in the folder returned by : `arm-linux-gnueabihf-gcc -print-sysroot`.

Note that this repository does not contain the source for the edid_parser and vcdbg binaries due to licensing restrictions.
9 changes: 9 additions & 0 deletions host_applications/linux/apps/raspicam/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ set (GL_SCENE_SOURCES
gl_scenes/sobel.c
gl_scenes/square.c
gl_scenes/teapot.c
gl_scenes/shader.c
gl_scenes/vcsm_square.c)

set (COMMON_SOURCES
Expand All @@ -54,6 +55,14 @@ add_executable(raspividyuv ${COMMON_SOURCES} RaspiVidYUV.c)

set (MMAL_LIBS mmal_core mmal_util mmal_vc_client)

FIND_PACKAGE(liblo)
if(LIBLO_FOUND)
message( STATUS "Building with OSC support !")
add_definitions(-DHAVE_LIBLO)
include_directories(${LIBLO_INCLUDE_DIRS})
target_link_libraries(raspistill ${LIBLO_LIBRARIES})
endif()

target_link_libraries(raspistill ${MMAL_LIBS} vcos bcm_host brcmGLESv2 brcmEGL m dl)
target_link_libraries(raspiyuv ${MMAL_LIBS} vcos bcm_host)
target_link_libraries(raspivid ${MMAL_LIBS} vcos bcm_host)
Expand Down
125 changes: 125 additions & 0 deletions host_applications/linux/apps/raspicam/RaspiStill.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <pthread.h>
#include <time.h>

#include "gl_scenes/shader.h"

#ifdef HAVE_LIBLO
#include <lo/lo.h>
#endif

// Standard port setting for the camera component
#define MMAL_CAMERA_PREVIEW_PORT 0
#define MMAL_CAMERA_VIDEO_PORT 1
Expand Down Expand Up @@ -158,6 +164,12 @@ typedef struct
MMAL_POOL_T *encoder_pool; /// Pointer to the pool of buffers used by encoder output port

RASPITEX_STATE raspitex_state; /// GL renderer state and parameters

#ifdef HAVE_LIBLO
lo_server_thread osc_server;
char* osc_inport;
#endif
int useOSC;

} RASPISTILL_STATE;

Expand Down Expand Up @@ -194,6 +206,9 @@ enum
CommandTimeStamp,
CommandFrameStart,
CommandRestartInterval,
CommandOSCport,
CommandFragmentShader,
CommandVertexShader,
};

static COMMAND_LIST cmdline_commands[] =
Expand All @@ -217,6 +232,9 @@ static COMMAND_LIST cmdline_commands[] =
{ CommandTimeStamp, "-timestamp", "ts", "Replace output pattern (%d) with unix timestamp (seconds since 1970)", 0},
{ CommandFrameStart,"-framestart","fs", "Starting frame number in output pattern(%d)", 1},
{ CommandRestartInterval, "-restart","rs","JPEG Restart interval (default of 0 for none)", 1},
{ CommandOSCport, "-oscport", "oscp", "OSC input port", 1 },
{ CommandFragmentShader, "-fragmentshader", "frag", "fragment shader program file", 1 },
{ CommandVertexShader, "-fragmentshader", "vert", "vertex shader program file", 1 },
};

static int cmdline_commands_size = sizeof(cmdline_commands) / sizeof(cmdline_commands[0]);
Expand Down Expand Up @@ -300,6 +318,7 @@ static void default_status(RASPISTILL_STATE *state)
state->datetime = 0;
state->timestamp = 0;
state->restart_interval = 0;
state->useOSC = 0;

// Setup preview window defaults
raspipreview_set_defaults(&state->preview_parameters);
Expand Down Expand Up @@ -636,6 +655,60 @@ static int parse_cmdline(int argc, const char **argv, RASPISTILL_STATE *state)
break;
}

case CommandOSCport: // Set OSC port (only valid with shader scene)
{
#ifdef HAVE_LIBLO
int len = strlen(argv[i + 1]);
if (len)
{
state->osc_inport = malloc(len+1); // leave enough space for any timelapse generated changes to filename
vcos_assert(state->osc_inport);
if (state->osc_inport)
strncpy(state->osc_inport, argv[i + 1], len+1);
i++;
state->useOSC=1;
}
else
valid = 0;
break;
#else
fprintf(stderr, "OSC port passed as argument put Raspistill have been build without liblo !");
fprintf(stderr, "OSC is disable.");
#endif /* HAVE_LIBLO */
}

case CommandFragmentShader: // Set fragment shader file to load
{
int len = strlen(argv[i + 1]);
if (len)
{
state->raspitex_state.fragment_shader_filename = malloc(len+1); // leave enough space for any timelapse generated changes to filename
vcos_assert(state->raspitex_state->fragment_shader_filename);
if (state->raspitex_state.fragment_shader_filename)
strncpy(state->raspitex_state.fragment_shader_filename, argv[i + 1], len+1);
i++;
}
else
valid = 0;
break;
}

case CommandVertexShader: // Set vertex shader file to load
{
int len = strlen(argv[i + 1]);
if (len)
{
state->raspitex_state.vertex_shader_filename = malloc(len+1); // leave enough space for any timelapse generated changes to filename
vcos_assert(state->raspitex_state->vertex_shader_filename);
if (state->raspitex_state.vertex_shader_filename)
strncpy(state->raspitex_state.vertex_shader_filename, argv[i + 1], len+1);
i++;
}
else
valid = 0;
break;
}

default:
{
// Try parsing for any image specific parameters
Expand Down Expand Up @@ -1629,6 +1702,53 @@ static void rename_file(RASPISTILL_STATE *state, FILE *output_file,
}
}

#ifdef HAVE_LIBLO
void osc_error(int num, const char *msg, const char *path)
{
printf("liblo server error %d in path %s: %s\n", num, path, msg);
fflush(stdout);
}

void osc_generic_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data)
{
int i;

RASPISTILL_STATE *state = user_data;
RASPITEXUTIL_SHADER_PROGRAM_T *shader = shader_get_shader();

if (state->verbose)
{
fprintf(stderr, "Receive OSC message : %s with %d values\n", path, argc);
}

for (i=0;i<shader->uniform_count;i++){
if ( strcmp(shader->uniform_array[i].name, path+1) == 0 ){
int j;
for (j=0;j<argc;j++){
if ( types[j] == 'f') {
shader->uniform_array[i].param[j]= (GLfloat) argv[j]->f;
} else if ( types[j] == 'i' ){
shader->uniform_array[i].param[j]= (GLfloat) argv[j]->i;
} else {
printf("%s parameter #%d wrong type (%c)! only float or int are allowed !\n",path,j,types[j]);
}
}
shader->uniform_array[i].flag = 1;
break;
}
}
}

static void init_osc(RASPISTILL_STATE *state)
{
printf("initialize OSC server on port %s\n", state->osc_inport);
state->osc_server = lo_server_thread_new(state->osc_inport, osc_error);
/* add method that will match any path and args */
lo_server_thread_add_method(state->osc_server , NULL, NULL, (lo_method_handler) osc_generic_handler, state);
lo_server_thread_start(state->osc_server);
}
#endif /* HAVE_LIBLO */

/**
* main
Expand Down Expand Up @@ -1697,6 +1817,11 @@ int main(int argc, const char **argv)
if (state.useGL)
raspitex_init(&state.raspitex_state);

#ifdef HAVE_LIBLO
if (state.useOSC)
init_osc(&state);
#endif

// OK, we have a nice set of parameters. Now set up our components
// We have three components. Camera, Preview and encoder.
// Camera and encoder are different in stills/video, but preview
Expand Down
8 changes: 7 additions & 1 deletion host_applications/linux/apps/raspicam/RaspiTex.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "gl_scenes/teapot.h"
#include "gl_scenes/vcsm_square.h"
#include "gl_scenes/yuv.h"
#include "gl_scenes/shader.h"

/**
* \file RaspiTex.c
Expand Down Expand Up @@ -101,7 +102,7 @@ enum

static COMMAND_LIST cmdline_commands[] =
{
{ CommandGLScene, "-glscene", "gs", "GL scene square,teapot,mirror,yuv,sobel,vcsm_square", 1 },
{ CommandGLScene, "-glscene", "gs", "GL scene square,teapot,mirror,yuv,sobel,vcsm_square,shader", 1 },
{ CommandGLWin, "-glwin", "gw", "GL window settings <'x,y,w,h'>", 1 },
};

Expand Down Expand Up @@ -165,6 +166,8 @@ int raspitex_parse_cmdline(RASPITEX_STATE *state,
state->scene_id = RASPITEX_SCENE_SOBEL;
else if (strcmp(arg2, "vcsm_square") == 0)
state->scene_id = RASPITEX_SCENE_VCSM_SQUARE;
else if (strcmp(arg2, "shader") == 0)
state->scene_id = RASPITEX_SCENE_SHADER;
else
vcos_log_error("Unknown scene %s", arg2);

Expand Down Expand Up @@ -594,6 +597,9 @@ int raspitex_init(RASPITEX_STATE *state)
case RASPITEX_SCENE_VCSM_SQUARE:
rc = vcsm_square_open(state);
break;
case RASPITEX_SCENE_SHADER:
rc = shader_open(state);
break;
default:
rc = -1;
break;
Expand Down
5 changes: 4 additions & 1 deletion host_applications/linux/apps/raspicam/RaspiTex.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ typedef enum
RASPITEX_SCENE_YUV,
RASPITEX_SCENE_SOBEL,
RASPITEX_SCENE_VCSM_SQUARE,
RASPITEX_SCENE_SHADER,

} RASPITEX_SCENE_T;

Expand Down Expand Up @@ -175,7 +176,9 @@ typedef struct RASPITEX_STATE
int verbose; /// Log FPS

RASPITEX_CAPTURE capture; /// Frame-buffer capture state

char* fragment_shader_filename;
char* vertex_shader_filename;

} RASPITEX_STATE;

int raspitex_init(RASPITEX_STATE *state);
Expand Down
51 changes: 51 additions & 0 deletions host_applications/linux/apps/raspicam/RaspiTexUtil.c
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,24 @@ int raspitexutil_build_shader_program(RASPITEXUTIL_SHADER_PROGRAM_T *p)
}
}

/// Automatically find uniform variables
glGetProgramiv( p->program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &p->max_length);
glGetProgramiv( p->program, GL_ACTIVE_UNIFORMS, &p->uniform_count);
printf("found %d uniform variable(s) : \n",p->uniform_count);

raspitexutil_create_param_array(p);

GLchar *name= (GLchar*) malloc(sizeof(GLchar)*p->max_length);
GLsizei length=0;
RASPITEXUTIL_SHADER_PARAMETER_T *array = p->uniform_array;
for(i=0;i<p->uniform_count;i++){
glGetActiveUniform(p->program, i, p->max_length, &length, &array[i].size, &array[i].type, name);
array[i].loc = glGetUniformLocation( p->program, name );
strncpy(array[i].name,name,length+1);
printf("\t%s\n",name);
}
free(name);

return 0;

fail:
Expand All @@ -599,3 +617,36 @@ int raspitexutil_build_shader_program(RASPITEXUTIL_SHADER_PROGRAM_T *p)
return -1;
}

void raspitexutil_create_param_array(RASPITEXUTIL_SHADER_PROGRAM_T *p)
{

int i;

p->uniform_array = (RASPITEXUTIL_SHADER_PARAMETER_T*) malloc(sizeof (RASPITEXUTIL_SHADER_PARAMETER_T) * p->uniform_count);
p->attribute_array = (RASPITEXUTIL_SHADER_PARAMETER_T*) malloc(sizeof (RASPITEXUTIL_SHADER_PARAMETER_T) * p->attribute_count);

RASPITEXUTIL_SHADER_PARAMETER_T* array = p->uniform_array;
// allocate maximum size for a param, which is a 4x4 matrix of floats
// in the future, only allocate for specific type
// also, technically we should handle arrays of matrices, too...sheesh!
for (i = 0; i < p->uniform_count; i++) {
int j=0;
array[i].size = 0;
array[i].type = 0;
array[i].loc = 0;
array[i].name = (GLchar*) malloc(sizeof(GLchar)* p->max_length+1);;
array[i].flag = 0;
for(j=0; j<16; j++)array[i].param[j]=0;
}

array = p->attribute_array;
for (i = 0; i < p->attribute_count; i++) {
int j=0;
array[i].size = 0;
array[i].type = 0;
array[i].loc = 0;
array[i].name = (GLchar*) malloc(sizeof(GLchar)* p->max_length+1);
array[i].flag = 0;
for(j=0; j<16; j++)array[i].param[j]=0;
}
}
25 changes: 25 additions & 0 deletions host_applications/linux/apps/raspicam/RaspiTexUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef RASPITEX_UTIL_H_
#define RASPITEX_UTIL_H_

#ifndef VCOS_LOG_CATEGORY
#define VCOS_LOG_CATEGORY (&raspitex_log_category)
#endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
Expand All @@ -43,6 +45,19 @@ extern VCOS_LOG_CAT_T raspitex_log_category;

#define SHADER_MAX_ATTRIBUTES 16
#define SHADER_MAX_UNIFORMS 16

typedef struct RASPITEXUTIL_SHADER_PARAMETER_T
{
// Variables for the, uh, variables
// stolen from puredata/gem glsl_program.h, thanks guys ;-)
GLint size;
GLenum type;
GLint loc;
GLchar *name;
GLfloat param[16];
int flag;
} RASPITEXUTIL_SHADER_PARAMETER_T;

/**
* Container for a simple shader program. The uniform and attribute locations
* are automatically setup by raspitex_build_shader_program.
Expand All @@ -51,7 +66,16 @@ typedef struct RASPITEXUTIL_SHADER_PROGRAM_T
{
const char *vertex_source; /// Pointer to vertex shader source
const char *fragment_source; /// Pointer to fragment shader source

GLint max_length; /// Maximum length of parameter name;
GLint uniform_count, attribute_count; /// Number of parameters


char* fragment_shader_filename;
char* vertex_shader_filename;
/// Array of shader paramaters (uniform and attributes)
RASPITEXUTIL_SHADER_PARAMETER_T *uniform_array, *attribute_array;

/// Array of uniform names for raspitex_build_shader_program to process
const char *uniform_names[SHADER_MAX_UNIFORMS];
/// Array of attribute names for raspitex_build_shader_program to process
Expand Down Expand Up @@ -112,5 +136,6 @@ void raspitexutil_close(RASPITEX_STATE* raspitex_state);
/* Utility functions */
int raspitexutil_build_shader_program(RASPITEXUTIL_SHADER_PROGRAM_T *p);
void raspitexutil_brga_to_rgba(uint8_t *buffer, size_t size);
void raspitexutil_create_param_array(RASPITEXUTIL_SHADER_PROGRAM_T *p);

#endif /* RASPITEX_UTIL_H_ */
Loading