Skip to content
This repository was archived by the owner on Aug 27, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 11 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
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,15 @@ 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 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`.


14 changes: 12 additions & 2 deletions host_applications/linux/apps/raspicam/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

SET(COMPILE_DEFINITIONS -Werror)

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/makefiles/cmake/Modules/")

include_directories(${PROJECT_SOURCE_DIR}/host_applications/linux/libs/bcm_host/include)
include_directories(${PROJECT_SOURCE_DIR}/host_applications/linux/apps/raspicam/)

Expand All @@ -12,7 +14,8 @@ set (GL_SCENE_SOURCES
gl_scenes/yuv.c
gl_scenes/sobel.c
gl_scenes/square.c
gl_scenes/teapot.c)
gl_scenes/teapot.c
gl_scenes/shader.c)

set (COMMON_SOURCES
RaspiCamControl.c
Expand All @@ -26,7 +29,14 @@ add_executable(raspividyuv ${COMMON_SOURCES} RaspiVidYUV.c)

set (MMAL_LIBS mmal_core mmal_util mmal_vc_client)

target_link_libraries(raspistill ${MMAL_LIBS} vcos bcm_host GLESv2 EGL m)
FIND_PACKAGE(liblo)
include_directories(${LIBLO_INCLUDE_DIRS})
if(LIBLO_FOUND)
message( STATUS "Building with OSC support !")
add_definitions(-DHAVE_LIBLO)
endif()

target_link_libraries(raspistill ${MMAL_LIBS} vcos bcm_host GLESv2 EGL m ${LIBLO_LIBRARIES})
target_link_libraries(raspiyuv ${MMAL_LIBS} vcos bcm_host)
target_link_libraries(raspivid ${MMAL_LIBS} vcos bcm_host)
target_link_libraries(raspividyuv ${MMAL_LIBS} vcos bcm_host)
Expand Down
1 change: 1 addition & 0 deletions host_applications/linux/apps/raspicam/RaspiCamControl.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/// Structure to cross reference exposure strings against the MMAL parameter equivalent
static XREF_T exposure_map[] =
{
{"off", MMAL_PARAM_EXPOSUREMODE_OFF},
{"auto", MMAL_PARAM_EXPOSUREMODE_AUTO},
{"night", MMAL_PARAM_EXPOSUREMODE_NIGHT},
{"nightpreview", MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW},
Expand Down
131 changes: 129 additions & 2 deletions host_applications/linux/apps/raspicam/RaspiStill.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include <semaphore.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 @@ -150,6 +156,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 @@ -189,6 +201,9 @@ static void store_exif_tag(RASPISTILL_STATE *state, const char *exif_tag);
#define CommandCamSelect 20
#define CommandBurstMode 21
#define CommandSensorMode 22
#define CommandOSCport 23
#define CommandFragmentShader 24
#define CommandVertexShader 25

static COMMAND_LIST cmdline_commands[] =
{
Expand All @@ -215,6 +230,9 @@ static COMMAND_LIST cmdline_commands[] =
{ CommandCamSelect, "-camselect","cs", "Select camera <number>. Default 0", 1 },
{ CommandBurstMode, "-burst", "bm", "Enable 'burst capture mode'", 0},
{ CommandSensorMode,"-mode", "md", "Force sensor mode. 0=auto. See docs for other modes available", 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 @@ -294,6 +312,8 @@ static void default_status(RASPISTILL_STATE *state)
state->cameraNum = 0;
state->burstCaptureMode=0;
state->sensor_mode = 0;

state->useOSC = 0;

// Setup preview window defaults
raspipreview_set_defaults(&state->preview_parameters);
Expand All @@ -303,6 +323,7 @@ static void default_status(RASPISTILL_STATE *state)

// Set initial GL preview state
raspitex_set_defaults(&state->raspitex_state);

}

/**
Expand Down Expand Up @@ -636,8 +657,61 @@ static int parse_cmdline(int argc, const char **argv, RASPISTILL_STATE *state)
valid = 0;
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 @@ -1611,6 +1685,54 @@ 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 @@ -1665,6 +1787,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 @@ -49,6 +49,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "gl_scenes/square.h"
#include "gl_scenes/teapot.h"
#include "gl_scenes/yuv.h"
#include "gl_scenes/shader.h"

/**
* \file RaspiTex.c
Expand Down Expand Up @@ -97,7 +98,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

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

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

Expand Down Expand Up @@ -585,6 +588,9 @@ int raspitex_init(RASPITEX_STATE *state)
case RASPITEX_SCENE_SOBEL:
rc = sobel_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 @@ -46,6 +46,7 @@ typedef enum {
RASPITEX_SCENE_TEAPOT,
RASPITEX_SCENE_YUV,
RASPITEX_SCENE_SOBEL,
RASPITEX_SCENE_SHADER,

} RASPITEX_SCENE_T;

Expand Down Expand Up @@ -173,7 +174,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
55 changes: 54 additions & 1 deletion host_applications/linux/apps/raspicam/RaspiTexUtil.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,25 @@ int raspitexutil_build_shader_program(RASPITEXUTIL_SHADER_PROGRAM_T *p)
}
}

return 0;
/// 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:
vcos_log_error("%s: Failed to build shader program", VCOS_FUNCTION);
Expand All @@ -595,3 +613,38 @@ 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;
// uniform_array[i].param = (float*) malloc(sizeof(float)*16);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove commented out code

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

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;
// attribute_array[i].param = (float*) malloc(sizeof(float)*16);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove commented out code

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

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;
}
}
Loading