summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosep Torra <n770galaxy@gmail.com>2014-03-26 13:48:22 +0100
committerJosep Torra <n770galaxy@gmail.com>2014-03-26 16:51:45 +0100
commit11a0fccf59774c6d927b6b299e87fee99cbdabac (patch)
tree72479e95eabe136e7bd735970549d6635c0e1d91
parentc269c64c624c5c69e8e977c65df950285966ea32 (diff)
Initial conversion to glib
- Added a main loop and a keyboard handler - Added a dedicated thread for GL stuff - Reindented the code - Some minor random fixes
-rw-r--r--Makefile3
-rw-r--r--triangle.c725
-rw-r--r--triangle.h3
-rw-r--r--video.c409
4 files changed, 655 insertions, 485 deletions
diff --git a/Makefile b/Makefile
index 5a6b8fc..dce6341 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,9 @@ LDFLAGS+=-L$(SDKSTAGE)/opt/vc/lib/ -lGLESv2 -lEGL -lopenmaxil -lbcm_host -lvcos
INCLUDES+=-I$(SDKSTAGE)/opt/vc/include/ -I$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads -I$(SDKSTAGE)/opt/vc/include/interface/vmcs_host/linux -I./
+CFLAGS += $(shell pkg-config --cflags glib-2.0)
+LDFLAGS += $(shell pkg-config --libs glib-2.0)
+
all: $(BIN) $(LIB)
%.o: %.c
diff --git a/triangle.c b/triangle.c
index 420a459..4fd3ffc 100644
--- a/triangle.c
+++ b/triangle.c
@@ -1,6 +1,9 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
Copyright (c) 2012, OtherCrashOverride
+Copyright (C) 2014, Fluendo S.A.
+ @author: Josep Torra <josep@fluendo.com>
+
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -26,7 +29,7 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-// A rotating cube rendered with OpenGL|ES. Three images used as textures on the cube faces.
+/* A rotating cube rendered with OpenGL|ES with a video on it */
#include <stdio.h>
#include <stdlib.h>
@@ -34,6 +37,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <math.h>
#include <assert.h>
#include <unistd.h>
+#include <termios.h>
+
+#include <glib.h>
#include "bcm_host.h"
@@ -44,8 +50,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "cube_texture_and_coords.h"
#include "triangle.h"
-#include <pthread.h>
-
#define PATH "./"
@@ -53,234 +57,268 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define IMAGE_SIZE_HEIGHT 1080
#ifndef M_PI
- #define M_PI 3.141592654
+#define M_PI 3.141592654
#endif
-
typedef struct
{
- uint32_t screen_width;
- uint32_t screen_height;
-// OpenGL|ES objects
- EGLDisplay display;
- EGLSurface surface;
- EGLContext context;
- GLuint tex;
-// model rotation vector and direction
- GLfloat rot_angle_x_inc;
- GLfloat rot_angle_y_inc;
- GLfloat rot_angle_z_inc;
-// current model rotation angles
- GLfloat rot_angle_x;
- GLfloat rot_angle_y;
- GLfloat rot_angle_z;
-// current distance from camera
- GLfloat distance;
- GLfloat distance_inc;
-
- IPC_T ipc;
-} CUBE_STATE_T;
-
-static void init_ogl(CUBE_STATE_T *state);
-static void init_model_proj(CUBE_STATE_T *state);
-static void reset_model(CUBE_STATE_T *state);
-static GLfloat inc_and_wrap_angle(GLfloat angle, GLfloat angle_inc);
-static GLfloat inc_and_clip_distance(GLfloat distance, GLfloat distance_inc);
-static void redraw_scene(CUBE_STATE_T *state);
-static void update_model(CUBE_STATE_T *state);
-static void init_textures(CUBE_STATE_T *state);
-static void exit_func(void);
+ DISPMANX_DISPLAY_HANDLE_T dispman_display;
+ DISPMANX_ELEMENT_HANDLE_T dispman_element;
+
+ uint32_t screen_width;
+ uint32_t screen_height;
+
+ gboolean animate;
+
+ /* OpenGL|ES objects */
+ EGLDisplay display;
+ EGLSurface surface;
+ EGLContext context;
+ GLuint tex;
+ /* model rotation vector and direction */
+ GLfloat rot_angle_x_inc;
+ GLfloat rot_angle_y_inc;
+ GLfloat rot_angle_z_inc;
+ /* current model rotation angles */
+ GLfloat rot_angle_x;
+ GLfloat rot_angle_y;
+ GLfloat rot_angle_z;
+ /* current distance from camera */
+ GLfloat distance;
+ GLfloat distance_inc;
+
+ /* GLib mainloop */
+ GMainLoop *main_loop;
+ /* Rendering thread state */
+ gboolean running;
+
+ IPC_T ipc;
+} AppState;
+
+static void init_ogl (AppState * state);
+static void init_model_proj (AppState * state);
+static void reset_model (AppState * state);
+static GLfloat inc_and_wrap_angle (GLfloat angle, GLfloat angle_inc);
+static GLfloat inc_and_clip_distance (GLfloat distance, GLfloat distance_inc);
+static void redraw_scene (AppState * state);
+static void update_model (AppState * state);
+static void init_textures (AppState * state);
static volatile int terminate;
-static CUBE_STATE_T _state, *state=&_state;
-
-static pthread_t thread1;
-
+static AppState _state, *state = &_state;
/***********************************************************
* Name: init_ogl
*
* Arguments:
- * CUBE_STATE_T *state - holds OGLES model info
+ * AppState *state - holds OGLES model info
*
* Description: Sets the display, OpenGL|ES context and screen stuff
*
* Returns: void
*
***********************************************************/
-static void init_ogl(CUBE_STATE_T *state)
+static void
+init_ogl (AppState * state)
{
- int32_t success = 0;
- EGLBoolean result;
- EGLint num_config;
-
- static EGL_DISPMANX_WINDOW_T nativewindow;
-
- DISPMANX_ELEMENT_HANDLE_T dispman_element;
- DISPMANX_DISPLAY_HANDLE_T dispman_display;
- DISPMANX_UPDATE_HANDLE_T dispman_update;
- VC_RECT_T dst_rect;
- VC_RECT_T src_rect;
-
- static const EGLint attribute_list[] =
- {
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 8,
- EGL_DEPTH_SIZE, 16,
- //EGL_SAMPLES, 4,
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_NONE
- };
-
- EGLConfig config;
-
- // get an EGL display connection
- state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- assert(state->display!=EGL_NO_DISPLAY);
-
- // initialize the EGL display connection
- result = eglInitialize(state->display, NULL, NULL);
- assert(EGL_FALSE != result);
-
- // get an appropriate EGL frame buffer configuration
- // this uses a BRCM extension that gets the closest match, rather than standard which returns anything that matches
- result = eglSaneChooseConfigBRCM(state->display, attribute_list, &config, 1, &num_config);
- assert(EGL_FALSE != result);
-
- // create an EGL rendering context
- state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, NULL);
- assert(state->context!=EGL_NO_CONTEXT);
-
- // create an EGL window surface
- success = graphics_get_display_size(0 /* LCD */, &state->screen_width, &state->screen_height);
- assert( success >= 0 );
-
- dst_rect.x = 0;
- dst_rect.y = 0;
- dst_rect.width = state->screen_width;
- dst_rect.height = state->screen_height;
-
- src_rect.x = 0;
- src_rect.y = 0;
- src_rect.width = state->screen_width << 16;
- src_rect.height = state->screen_height << 16;
-
- dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
- dispman_update = vc_dispmanx_update_start( 0 );
-
- dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display,
- 0/*layer*/, &dst_rect, 0/*src*/,
- &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, 0/*transform*/);
-
- nativewindow.element = dispman_element;
- nativewindow.width = state->screen_width;
- nativewindow.height = state->screen_height;
- vc_dispmanx_update_submit_sync( dispman_update );
-
- state->surface = eglCreateWindowSurface( state->display, config, &nativewindow, NULL );
- assert(state->surface != EGL_NO_SURFACE);
-
- // connect the context to the surface
- result = eglMakeCurrent(state->display, state->surface, state->surface, state->context);
- assert(EGL_FALSE != result);
-
- // Set background color and clear buffers
- glClearColor(0.15f, 0.25f, 0.35f, 1.0f);
-
- // Enable back face culling.
- glEnable(GL_CULL_FACE);
-
- glMatrixMode(GL_MODELVIEW);
+ int32_t success = 0;
+ EGLBoolean result;
+ EGLint num_config;
+
+ static EGL_DISPMANX_WINDOW_T nativewindow;
+
+ DISPMANX_UPDATE_HANDLE_T dispman_update;
+ DISPMANX_MODEINFO_T mode_info;
+ VC_RECT_T dst_rect;
+ VC_RECT_T src_rect;
+
+ static const EGLint attribute_list[] = {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_DEPTH_SIZE, 16,
+ //EGL_SAMPLES, 4,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_NONE
+ };
+
+ EGLConfig config;
+
+ /* get an EGL display connection */
+ state->display = eglGetDisplay (EGL_DEFAULT_DISPLAY);
+ assert (state->display != EGL_NO_DISPLAY);
+
+ /* initialize the EGL display connection */
+ result = eglInitialize (state->display, NULL, NULL);
+ assert (EGL_FALSE != result);
+
+ /* get an appropriate EGL frame buffer configuration
+ * this uses a BRCM extension that gets the closest match, rather
+ * than standard which returns anything that matches. */
+ result =
+ eglSaneChooseConfigBRCM (state->display, attribute_list, &config, 1,
+ &num_config);
+ assert (EGL_FALSE != result);
+
+ /* create an EGL rendering context */
+ state->context =
+ eglCreateContext (state->display, config, EGL_NO_CONTEXT, NULL);
+ assert (state->context != EGL_NO_CONTEXT);
+
+ /* Open display */
+ state->dispman_display = vc_dispmanx_display_open (0 /* LCD */ );
+ assert (state->dispman_display);
+
+ /* Get display dimensions */
+ success = vc_dispmanx_display_get_info(state->dispman_display, &mode_info);
+ assert (success >= 0);
+ state->screen_width = mode_info.width;
+ state->screen_height = mode_info.height;
+
+ /* create an EGL window surface */
+ dst_rect.x = 0;
+ dst_rect.y = 0;
+ dst_rect.width = state->screen_width;
+ dst_rect.height = state->screen_height;
+
+ src_rect.x = 0;
+ src_rect.y = 0;
+ src_rect.width = state->screen_width << 16;
+ src_rect.height = state->screen_height << 16;
+
+ dispman_update = vc_dispmanx_update_start (0);
+
+ state->dispman_element =
+ vc_dispmanx_element_add (dispman_update, state->dispman_display,
+ 0 /*layer */ , &dst_rect, 0 /*src */ ,
+ &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha */ , 0 /*clamp */ ,
+ 0 /*transform */ );
+
+ nativewindow.element = state->dispman_element;
+ nativewindow.width = state->screen_width;
+ nativewindow.height = state->screen_height;
+ vc_dispmanx_update_submit_sync (dispman_update);
+
+ state->surface =
+ eglCreateWindowSurface (state->display, config, &nativewindow, NULL);
+ assert (state->surface != EGL_NO_SURFACE);
+
+ /* connect the context to the surface */
+ result =
+ eglMakeCurrent (state->display, state->surface, state->surface,
+ state->context);
+ assert (EGL_FALSE != result);
+
+ /* Set background color and clear buffers */
+ glClearColor (0.15f, 0.25f, 0.35f, 1.0f);
+
+ /* Enable back face culling. */
+ glEnable (GL_CULL_FACE);
+
+ glMatrixMode (GL_MODELVIEW);
}
/***********************************************************
* Name: init_model_proj
*
* Arguments:
- * CUBE_STATE_T *state - holds OGLES model info
+ * AppState *state - holds OGLES model info
*
* Description: Sets the OpenGL|ES model to default values
*
* Returns: void
*
***********************************************************/
-static void init_model_proj(CUBE_STATE_T *state)
+static void
+init_model_proj (AppState * state)
{
- float nearp = 1.0f;
- float farp = 500.0f;
- float hht;
- float hwd;
+ float nearp = 1.0f;
+ float farp = 500.0f;
+ float hht;
+ float hwd;
+
+ glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
- glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
+ glViewport (0, 0, (GLsizei) state->screen_width,
+ (GLsizei) state->screen_height);
- glViewport(0, 0, (GLsizei)state->screen_width, (GLsizei)state->screen_height);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
+ glMatrixMode (GL_PROJECTION);
+ glLoadIdentity ();
- hht = nearp * (float)tan(45.0 / 2.0 / 180.0 * M_PI);
- hwd = hht * (float)state->screen_width / (float)state->screen_height;
+ hht = nearp * (float) tan (45.0 / 2.0 / 180.0 * M_PI);
+ hwd = hht * (float) state->screen_width / (float) state->screen_height;
- glFrustumf(-hwd, hwd, -hht, hht, nearp, farp);
-
- glEnableClientState( GL_VERTEX_ARRAY );
- glVertexPointer( 3, GL_BYTE, 0, quadx );
+ glFrustumf (-hwd, hwd, -hht, hht, nearp, farp);
- reset_model(state);
+ glEnableClientState (GL_VERTEX_ARRAY);
+ glVertexPointer (3, GL_BYTE, 0, quadx);
+
+ reset_model (state);
}
/***********************************************************
* Name: reset_model
*
* Arguments:
- * CUBE_STATE_T *state - holds OGLES model info
+ * AppState *state - holds OGLES model info
*
* Description: Resets the Model projection and rotation direction
*
* Returns: void
*
***********************************************************/
-static void reset_model(CUBE_STATE_T *state)
+static void
+reset_model (AppState * state)
{
- // reset model position
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(0.f, 0.f, -50.f);
-
- // reset model rotation
- state->rot_angle_x = 45.f; state->rot_angle_y = 30.f; state->rot_angle_z = 0.f;
- state->rot_angle_x_inc = 0.5f; state->rot_angle_y_inc = 0.5f; state->rot_angle_z_inc = 0.f;
- state->distance = 40.f;
+ /* reset model position */
+ glMatrixMode (GL_MODELVIEW);
+ glLoadIdentity ();
+ glTranslatef (0.f, 0.f, -50.f);
+
+ /* reset model rotation */
+ state->rot_angle_x = 45.f;
+ state->rot_angle_y = 30.f;
+ state->rot_angle_z = 0.f;
+ state->rot_angle_x_inc = 0.5f;
+ state->rot_angle_y_inc = 0.5f;
+ state->rot_angle_z_inc = 0.f;
+ state->distance = 40.f;
}
/***********************************************************
* Name: update_model
*
* Arguments:
- * CUBE_STATE_T *state - holds OGLES model info
+ * AppState *state - holds OGLES model info
*
* Description: Updates model projection to current position/rotation
*
* Returns: void
*
***********************************************************/
-static void update_model(CUBE_STATE_T *state)
+static void
+update_model (AppState * state)
{
- // update position
- state->rot_angle_x = inc_and_wrap_angle(state->rot_angle_x, state->rot_angle_x_inc);
- state->rot_angle_y = inc_and_wrap_angle(state->rot_angle_y, state->rot_angle_y_inc);
- state->rot_angle_z = inc_and_wrap_angle(state->rot_angle_z, state->rot_angle_z_inc);
- state->distance = inc_and_clip_distance(state->distance, state->distance_inc);
-
- glLoadIdentity();
- // move camera back to see the cube
- glTranslatef(0.f, 0.f, -state->distance);
-
- // Rotate model to new position
- glRotatef(state->rot_angle_x, 1.f, 0.f, 0.f);
- glRotatef(state->rot_angle_y, 0.f, 1.f, 0.f);
- glRotatef(state->rot_angle_z, 0.f, 0.f, 1.f);
+ if (state->animate) {
+ /* update position */
+ state->rot_angle_x =
+ inc_and_wrap_angle (state->rot_angle_x, state->rot_angle_x_inc);
+ state->rot_angle_y =
+ inc_and_wrap_angle (state->rot_angle_y, state->rot_angle_y_inc);
+ state->rot_angle_z =
+ inc_and_wrap_angle (state->rot_angle_z, state->rot_angle_z_inc);
+ state->distance =
+ inc_and_clip_distance (state->distance, state->distance_inc);
+ }
+
+ glLoadIdentity ();
+ /* move camera back to see the cube */
+ glTranslatef (0.f, 0.f, -state->distance);
+
+ /* Rotate model to new position */
+ glRotatef (state->rot_angle_x, 1.f, 0.f, 0.f);
+ glRotatef (state->rot_angle_y, 0.f, 1.f, 0.f);
+ glRotatef (state->rot_angle_z, 0.f, 0.f, 1.f);
}
/***********************************************************
@@ -296,16 +334,17 @@ static void update_model(CUBE_STATE_T *state)
* Returns: new value of angle
*
***********************************************************/
-static GLfloat inc_and_wrap_angle(GLfloat angle, GLfloat angle_inc)
+static GLfloat
+inc_and_wrap_angle (GLfloat angle, GLfloat angle_inc)
{
- angle += angle_inc;
+ angle += angle_inc;
- if (angle >= 360.0)
- angle -= 360.f;
- else if (angle <=0)
- angle += 360.f;
+ if (angle >= 360.0)
+ angle -= 360.f;
+ else if (angle <= 0)
+ angle += 360.f;
- return angle;
+ return angle;
}
/***********************************************************
@@ -321,23 +360,24 @@ static GLfloat inc_and_wrap_angle(GLfloat angle, GLfloat angle_inc)
* Returns: new value of angle
*
***********************************************************/
-static GLfloat inc_and_clip_distance(GLfloat distance, GLfloat distance_inc)
+static GLfloat
+inc_and_clip_distance (GLfloat distance, GLfloat distance_inc)
{
- distance += distance_inc;
+ distance += distance_inc;
- if (distance >= 120.0f)
- distance = 120.f;
- else if (distance <= 40.0f)
- distance = 40.0f;
+ if (distance >= 120.0f)
+ distance = 120.f;
+ else if (distance <= 40.0f)
+ distance = 40.0f;
- return distance;
+ return distance;
}
/***********************************************************
* Name: redraw_scene
*
* Arguments:
- * CUBE_STATE_T *state - holds OGLES model info
+ * AppState *state - holds OGLES model info
*
* Description: Draws the model and calls eglSwapBuffers
* to render to screen
@@ -345,41 +385,42 @@ static GLfloat inc_and_clip_distance(GLfloat distance, GLfloat distance_inc)
* Returns: void
*
***********************************************************/
-static void redraw_scene(CUBE_STATE_T *state)
+static void
+redraw_scene (AppState * state)
{
- // Start with a clear screen
- glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ /* Start with a clear screen */
+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- // Need to rotate textures - do this by rotating each cube face
- glRotatef(270.f, 0.f, 0.f, 1.f ); // front face normal along z axis
+ /* Need to rotate textures - do this by rotating each cube face */
+ glRotatef (270.f, 0.f, 0.f, 1.f); /* front face normal along z axis */
- // draw first 4 vertices
- glDrawArrays( GL_TRIANGLE_STRIP, 0, 4);
+ /* draw first 4 vertices */
+ glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
- // same pattern for other 5 faces - rotation chosen to make image orientation 'nice'
- glRotatef(90.f, 0.f, 0.f, 1.f ); // back face normal along z axis
- glDrawArrays( GL_TRIANGLE_STRIP, 4, 4);
+ /* same pattern for other 5 faces - rotation chosen to make image orientation 'nice' */
+ glRotatef (90.f, 0.f, 0.f, 1.f); /* back face normal along z axis */
+ glDrawArrays (GL_TRIANGLE_STRIP, 4, 4);
- glRotatef(90.f, 1.f, 0.f, 0.f ); // left face normal along x axis
- glDrawArrays( GL_TRIANGLE_STRIP, 8, 4);
+ glRotatef (90.f, 1.f, 0.f, 0.f); /* left face normal along x axis */
+ glDrawArrays (GL_TRIANGLE_STRIP, 8, 4);
- glRotatef(90.f, 1.f, 0.f, 0.f ); // right face normal along x axis
- glDrawArrays( GL_TRIANGLE_STRIP, 12, 4);
+ glRotatef (90.f, 1.f, 0.f, 0.f); /* right face normal along x axis */
+ glDrawArrays (GL_TRIANGLE_STRIP, 12, 4);
- glRotatef(270.f, 0.f, 1.f, 0.f ); // top face normal along y axis
- glDrawArrays( GL_TRIANGLE_STRIP, 16, 4);
+ glRotatef (270.f, 0.f, 1.f, 0.f); /* top face normal along y axis */
+ glDrawArrays (GL_TRIANGLE_STRIP, 16, 4);
- glRotatef(90.f, 0.f, 1.f, 0.f ); // bottom face normal along y axis
- glDrawArrays( GL_TRIANGLE_STRIP, 20, 4);
+ glRotatef (90.f, 0.f, 1.f, 0.f); /* bottom face normal along y axis */
+ glDrawArrays (GL_TRIANGLE_STRIP, 20, 4);
- eglSwapBuffers(state->display, state->surface);
+ eglSwapBuffers (state->display, state->surface);
}
/***********************************************************
* Name: init_textures
*
* Arguments:
- * CUBE_STATE_T *state - holds OGLES model info
+ * AppState *state - holds OGLES model info
*
* Description: Initialise OGL|ES texture surfaces to use image
* buffers
@@ -387,96 +428,210 @@ static void redraw_scene(CUBE_STATE_T *state)
* Returns: void
*
***********************************************************/
-static void init_textures(CUBE_STATE_T *state)
+static void
+init_textures (AppState * state)
{
- //// load three texture buffers but use them on six OGL|ES texture surfaces
- glGenTextures(1, &state->tex);
-
- glBindTexture(GL_TEXTURE_2D, state->tex);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, IMAGE_SIZE_WIDTH, IMAGE_SIZE_HEIGHT, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
-
- /* Create EGL Image */
- state->ipc.eglImage = eglCreateImageKHR(
- state->display,
- state->context,
- EGL_GL_TEXTURE_2D_KHR,
- (EGLClientBuffer)state->tex,
- 0);
-
- if (state->ipc.eglImage == EGL_NO_IMAGE_KHR)
- {
- printf("eglCreateImageKHR failed.\n");
- exit(1);
- }
-
- // Start rendering
- pthread_create(&thread1, NULL, video_decode_test, &state->ipc);
-
- // setup overall texture environment
- glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
- glEnable(GL_TEXTURE_2D);
-
- // Bind texture surface to current vertices
- glBindTexture(GL_TEXTURE_2D, state->tex);
+ glGenTextures (1, &state->tex);
+
+ glBindTexture (GL_TEXTURE_2D, state->tex);
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, IMAGE_SIZE_WIDTH, IMAGE_SIZE_HEIGHT,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+#if 0
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+#else
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#endif
+
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+
+ /* Create EGL Image */
+ state->ipc.eglImage = eglCreateImageKHR (state->display,
+ state->context, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer) state->tex, 0);
+
+ if (state->ipc.eglImage == EGL_NO_IMAGE_KHR) {
+ g_print ("eglCreateImageKHR failed.\n");
+ exit (1);
+ }
+
+ /* setup overall texture environment */
+ glTexCoordPointer (2, GL_FLOAT, 0, texCoords);
+ glEnableClientState (GL_TEXTURE_COORD_ARRAY);
+
+ glEnable (GL_TEXTURE_2D);
+
+ /* Bind texture surface to current vertices */
+ glBindTexture (GL_TEXTURE_2D, state->tex);
}
+
//------------------------------------------------------------------------------
-static void exit_func(void)
-// Function to be passed to atexit().
+static void
+close_ogl (void)
{
- if (state->ipc.eglImage != 0)
- {
- if (!eglDestroyImageKHR(state->display, (EGLImageKHR) state->ipc.eglImage))
- printf("eglDestroyImageKHR failed.");
- }
+ DISPMANX_UPDATE_HANDLE_T dispman_update;
+
+ if (state->ipc.eglImage != 0) {
+ if (!eglDestroyImageKHR (state->display, (EGLImageKHR) state->ipc.eglImage))
+ g_print ("eglDestroyImageKHR failed.");
+ }
+
+ /* clear screen */
+ glClear (GL_COLOR_BUFFER_BIT);
+ eglSwapBuffers (state->display, state->surface);
+
+ /* Release OpenGL resources */
+ eglMakeCurrent (state->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+ eglDestroySurface (state->display, state->surface);
+ eglDestroyContext (state->display, state->context);
+ eglTerminate (state->display);
+
+ dispman_update = vc_dispmanx_update_start (0);
+ vc_dispmanx_element_remove (dispman_update, state->dispman_element);
+ vc_dispmanx_update_submit_sync (dispman_update);
+ vc_dispmanx_display_close (state->dispman_display);
+}
- // clear screen
- glClear( GL_COLOR_BUFFER_BIT );
- eglSwapBuffers(state->display, state->surface);
+//==============================================================================
- // Release OpenGL resources
- eglMakeCurrent( state->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
- eglDestroySurface( state->display, state->surface );
- eglDestroyContext( state->display, state->context );
- eglTerminate( state->display );
+static void
+open_ogl (void)
+{
- printf("\ncube closed\n");
-} // exit_func()
+ bcm_host_init ();
-//==============================================================================
+ /* Start OpenGLES */
+ init_ogl (state);
-int main ()
+ /* Setup the model world */
+ init_model_proj (state);
+
+ /* initialize the OGLES texture(s) */
+ init_textures (state);
+}
+
+static gpointer
+render_func (gpointer data)
{
- bcm_host_init();
- printf("Note: ensure you have sufficient gpu_mem configured\n");
-
- // Clear application state
- memset( state, 0, sizeof( *state ) );
-
- // Start OGLES
- init_ogl(state);
-
- // Setup the model world
- init_model_proj(state);
-
- // initialise the OGLES texture(s)
- init_textures(state);
-
- while (!terminate)
- {
- update_model(state);
- redraw_scene(state);
- }
- exit_func();
- return 0;
+ open_ogl ();
+ state->running = TRUE;
+
+ do {
+ update_model (state);
+ redraw_scene (state);
+
+ g_usleep (0);
+ } while (state->running == TRUE);
+
+ close_ogl ();
+ return NULL;
}
+/* Process keyboard input */
+static gboolean
+handle_keyboard (GIOChannel * source, GIOCondition cond, AppState * state)
+{
+ gsize bytesread;
+ gchar op;
+
+ if (g_io_channel_read_chars (source, &op, 1, &bytesread,
+ NULL) == G_IO_STATUS_NORMAL) {
+ switch (op) {
+ case 'a':
+ if (state->animate) {
+ state->animate = FALSE;
+ g_print ("Animation disabled\n");
+ } else {
+ state->animate = TRUE;
+ g_print ("Animation enabled\n");
+ }
+ break;
+ case 'q':
+ video_decode_stop ();
+ g_main_loop_quit (state->main_loop);
+ break;
+ default:
+ /* g_print ("%02x ", op); */
+ break;
+ }
+ }
+ return TRUE;
+}
+
+int
+main ()
+{
+ GThread *rthread = NULL, *mthread = NULL;
+ GIOChannel *io_stdin;
+ struct termios cooked, raw;
+
+ /* must initialise the threading system before using any other GLib funtion */
+ if (!g_thread_supported ())
+ g_thread_init (NULL);
+
+ /* Clear application state */
+ memset (state, 0, sizeof (*state));
+ state->animate = TRUE;
+
+ /* Create a GLib Main Loop and set it to run */
+ state->main_loop = g_main_loop_new (NULL, FALSE);
+
+ /* Get the state of the tty */
+ tcgetattr (0, &cooked);
+ /* Make a copy we can mess with */
+ memcpy (&raw, &cooked, sizeof (struct termios));
+ /* Turn off linebuffering, and special-character processing,
+ * but not the SIGINT or SIGQUIT keys. */
+ raw.c_lflag &= ~(ICANON | ECHO);
+ /* Ship the raw control blts */
+ tcsetattr (0, TCSANOW, &raw);
+ /* Add a keyboard watch so we get notified of keystrokes */
+ io_stdin = g_io_channel_unix_new (fileno (stdin));
+ g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc) handle_keyboard, state);
+ g_io_channel_unref (io_stdin);
+
+ /* *INDENT-OFF* */
+ g_print ("Available commands: \n"
+ " a - Toggle animation \n"
+ " q - Quit \n");
+ /* *INDENT-ON* */
+
+ if (!(rthread = g_thread_new ("render", (GThreadFunc) render_func, NULL))) {
+ g_print ("Render thread creation failed\n");
+ goto done;
+ }
+
+ g_usleep(50000);
+ if (!(mthread = g_thread_new ("media", (GThreadFunc) video_decode_test, &state->ipc))) {
+ g_print ("Media thread creation failed\n");
+ goto done;
+ }
+
+ /* Start the mainloop */
+ g_main_loop_run (state->main_loop);
+
+done:
+
+ /* Unref the mainloop */
+ if (state->main_loop) {
+ g_main_loop_unref (state->main_loop);
+ }
+
+ /* Stop media thread */
+ if (mthread)
+ g_thread_join (mthread);
+
+ /* Stop rendering thread */
+ state->running = FALSE;
+ if (rthread)
+ g_thread_join (rthread);
+
+ tcsetattr (0, TCSANOW, &cooked);
+ g_print ("test finished\n");
+ return 0;
+}
diff --git a/triangle.h b/triangle.h
index 8b69c55..1e80909 100644
--- a/triangle.h
+++ b/triangle.h
@@ -31,4 +31,5 @@ typedef struct
void* eglImage;
} IPC_T;
-void* video_decode_test(void* arg);
+void* video_decode_test (void* arg);
+void video_decode_stop ();
diff --git a/video.c b/video.c
index 2bf8795..846227c 100644
--- a/video.c
+++ b/video.c
@@ -1,6 +1,8 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd
Copyright (c) 2012, OtherCrashOverride
+Copyright (C) 2014, Fluendo S.A.
+ @author: Josep Torra <josep@fluendo.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -26,232 +28,241 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-// Video decode demo using OpenMAX IL though the ilcient helper library
+/* Video decode demo using OpenMAX IL though the ilcient helper library */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <glib.h>
+
#include "bcm_host.h"
#include "ilclient.h"
#include "triangle.h"
-static OMX_BUFFERHEADERTYPE* eglBuffer = NULL;
-static COMPONENT_T* egl_render = NULL;
+static OMX_BUFFERHEADERTYPE *eglBuffer = NULL;
+static COMPONENT_T *egl_render = NULL;
-static void* eglImage = 0;
+static void *eglImage = 0;
+static gboolean running = FALSE;
-void my_fill_buffer_done(void* data, COMPONENT_T* comp)
+void
+my_fill_buffer_done (void *data, COMPONENT_T * comp)
{
- if (OMX_FillThisBuffer(ilclient_get_handle(egl_render), eglBuffer) != OMX_ErrorNone)
- {
- printf("WARNING: OMX_FillThisBuffer failed in callback\n");
- //exit(1);
- }
+ if (OMX_FillThisBuffer (ilclient_get_handle (egl_render),
+ eglBuffer) != OMX_ErrorNone) {
+ g_print ("WARNING: OMX_FillThisBuffer failed in callback\n");
+ }
}
-
-// Modified function prototype to work with pthreads
-void *video_decode_test(void* arg)
+void *
+video_decode_test (void *arg)
{
- const char* filename = "/opt/vc/src/hello_pi/hello_video/test.h264";
- IPC_T * ipc = (IPC_T *) arg;
- eglImage = ipc->eglImage;
-
- if (eglImage == 0)
- {
- printf("eglImage is null.\n");
- exit(1);
- }
-
- OMX_VIDEO_PARAM_PORTFORMATTYPE format;
- COMPONENT_T *video_decode = NULL;
- COMPONENT_T *list[5];
- TUNNEL_T tunnel[4];
- ILCLIENT_T *client;
- FILE *in;
- int status = 0;
- unsigned int data_len = 0;
-
- memset(list, 0, sizeof(list));
- memset(tunnel, 0, sizeof(tunnel));
-
- if((in = fopen(filename, "rb")) == NULL)
- return (void *)-2;
-
- if((client = ilclient_init()) == NULL)
- {
- fclose(in);
- return (void *)-3;
- }
-
- if(OMX_Init() != OMX_ErrorNone)
- {
- ilclient_destroy(client);
- fclose(in);
- return (void *)-4;
- }
-
- // callback
- ilclient_set_fill_buffer_done_callback(client, my_fill_buffer_done, 0);
-
- // create video_decode
- if(ilclient_create_component(client, &video_decode, "video_decode", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS) != 0)
- status = -14;
- list[0] = video_decode;
-
- // create egl_render
- if(status == 0 && ilclient_create_component(client, &egl_render, "egl_render", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_OUTPUT_BUFFERS) != 0)
- status = -14;
- list[1] = egl_render;
-
-
- set_tunnel(tunnel, video_decode, 131, egl_render, 220);
-
- if(status == 0)
- ilclient_change_component_state(video_decode, OMX_StateIdle);
-
- memset(&format, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE));
- format.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE);
- format.nVersion.nVersion = OMX_VERSION;
- format.nPortIndex = 130;
- format.eCompressionFormat = OMX_VIDEO_CodingAVC;
-
- if(status == 0 &&
- OMX_SetParameter(ILC_GET_HANDLE(video_decode), OMX_IndexParamVideoPortFormat, &format) == OMX_ErrorNone &&
- ilclient_enable_port_buffers(video_decode, 130, NULL, NULL, NULL) == 0)
- {
- OMX_BUFFERHEADERTYPE *buf;
- int port_settings_changed = 0;
- int first_packet = 1;
-
- ilclient_change_component_state(video_decode, OMX_StateExecuting);
-
- while((buf = ilclient_get_input_buffer(video_decode, 130, 1)) != NULL)
- {
- // feed data and wait until we get port settings changed
- unsigned char *dest = buf->pBuffer;
-
- // loop if at end
- if (feof(in)) {
- printf ("EOS\n");
- break; // rewind(in);
- }
- data_len += fread(dest, 1, buf->nAllocLen-data_len, in);
-
- if(port_settings_changed == 0 &&
- ((data_len > 0 && ilclient_remove_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1) == 0) ||
- (data_len == 0 && ilclient_wait_for_event(video_decode, OMX_EventPortSettingsChanged, 131, 0, 0, 1,
- ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 10000) == 0)))
- {
- port_settings_changed = 1;
-
- {
+ const char *filename = "/opt/vc/src/hello_pi/hello_video/test.h264";
+ IPC_T *ipc = (IPC_T *) arg;
+ eglImage = ipc->eglImage;
+
+ running = TRUE;
+
+ if (eglImage == 0) {
+ g_print ("eglImage is null.\n");
+ exit (1);
+ }
+
+ OMX_VIDEO_PARAM_PORTFORMATTYPE format;
+ COMPONENT_T *video_decode = NULL;
+ COMPONENT_T *list[5];
+ TUNNEL_T tunnel[4];
+ ILCLIENT_T *client;
+ FILE *in;
+ int status = 0;
+ unsigned int data_len = 0;
+
+ memset (list, 0, sizeof (list));
+ memset (tunnel, 0, sizeof (tunnel));
+
+ if ((in = fopen (filename, "rb")) == NULL)
+ return (void *) -2;
+
+ if ((client = ilclient_init ()) == NULL) {
+ fclose (in);
+ return (void *) -3;
+ }
+
+ if (OMX_Init () != OMX_ErrorNone) {
+ ilclient_destroy (client);
+ fclose (in);
+ return (void *) -4;
+ }
+ /* callback */
+ ilclient_set_fill_buffer_done_callback (client, my_fill_buffer_done, 0);
+
+ /* create video_decode */
+ if (ilclient_create_component (client, &video_decode, "video_decode",
+ ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS) != 0)
+ status = -14;
+ list[0] = video_decode;
+
+ /* create egl_render */
+ if (status == 0
+ && ilclient_create_component (client, &egl_render, "egl_render",
+ ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_OUTPUT_BUFFERS) != 0)
+ status = -14;
+ list[1] = egl_render;
+
+
+ set_tunnel (tunnel, video_decode, 131, egl_render, 220);
+
+ if (status == 0)
+ ilclient_change_component_state (video_decode, OMX_StateIdle);
+
+ memset (&format, 0, sizeof (OMX_VIDEO_PARAM_PORTFORMATTYPE));
+ format.nSize = sizeof (OMX_VIDEO_PARAM_PORTFORMATTYPE);
+ format.nVersion.nVersion = OMX_VERSION;
+ format.nPortIndex = 130;
+ format.eCompressionFormat = OMX_VIDEO_CodingAVC;
+
+ if (status == 0 &&
+ OMX_SetParameter (ILC_GET_HANDLE (video_decode),
+ OMX_IndexParamVideoPortFormat, &format) == OMX_ErrorNone
+ && ilclient_enable_port_buffers (video_decode, 130, NULL, NULL,
+ NULL) == 0) {
+ OMX_BUFFERHEADERTYPE *buf;
+ int port_settings_changed = 0;
+ int first_packet = 1;
+
+ ilclient_change_component_state (video_decode, OMX_StateExecuting);
+
+ while ((buf = ilclient_get_input_buffer (video_decode, 130, 1)) != NULL) {
+ /* feed data and wait until we get port settings changed */
+ unsigned char *dest = buf->pBuffer;
+
+ /* loop if at end */
+ if (feof (in) || !running) {
+ g_print ("EOS\n");
+ break;
+ }
+ data_len += fread (dest, 1, buf->nAllocLen - data_len, in);
+
+ if (port_settings_changed == 0 &&
+ ((data_len > 0
+ && ilclient_remove_event (video_decode,
+ OMX_EventPortSettingsChanged, 131, 0, 0, 1) == 0)
+ || (data_len == 0
+ && ilclient_wait_for_event (video_decode,
+ OMX_EventPortSettingsChanged, 131, 0, 0, 1,
+ ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED,
+ 10000) == 0))) {
+ port_settings_changed = 1;
+
+ {
#define OMX_IndexParamBrcmVideoEGLRenderDiscardMode 0x7f0000db
- OMX_CONFIG_PORTBOOLEANTYPE discardMode;
- memset (&discardMode, 0, sizeof (discardMode));
- discardMode.nSize = sizeof (discardMode);
- discardMode.nPortIndex = 220;
- discardMode.nVersion.nVersion = OMX_VERSION;
- discardMode.bEnabled = OMX_FALSE;
- if (OMX_SetParameter(ILC_GET_HANDLE(egl_render), OMX_IndexParamBrcmVideoEGLRenderDiscardMode, &discardMode) != OMX_ErrorNone) {
- status = -7;
- break;
- }
-#undef OMX_IndexParamBrcmVideoEGLRenderDiscardMode
- }
-
- if(ilclient_setup_tunnel(tunnel, 0, 0) != 0)
- {
- status = -7;
- break;
- }
-
- // Set egl_render to idle
- ilclient_change_component_state(egl_render, OMX_StateIdle);
-
- // Enable the output port and tell egl_render to use the texture as a buffer
- //ilclient_enable_port(egl_render, 221); THIS BLOCKS SO CANT BE USED
- if (OMX_SendCommand(ILC_GET_HANDLE(egl_render), OMX_CommandPortEnable, 221, NULL) != OMX_ErrorNone)
- {
- printf("OMX_CommandPortEnable failed.\n");
- exit(1);
- }
-
- if (OMX_UseEGLImage(ILC_GET_HANDLE(egl_render), &eglBuffer, 221, NULL, eglImage) != OMX_ErrorNone)
- {
- printf("OMX_UseEGLImage failed.\n");
- exit(1);
- }
-
- // Set egl_render to executing
- ilclient_change_component_state(egl_render, OMX_StateExecuting);
-
-
- // Request egl_render to write data to the texture buffer
- if(OMX_FillThisBuffer(ILC_GET_HANDLE(egl_render), eglBuffer) != OMX_ErrorNone)
- {
- printf("OMX_FillThisBuffer failed.\n");
- exit(1);
- }
- }
- if(!data_len)
- break;
-
- buf->nFilledLen = data_len;
- data_len = 0;
-
- buf->nOffset = 0;
- if(first_packet)
- {
- buf->nFlags = OMX_BUFFERFLAG_STARTTIME;
- first_packet = 0;
- }
- else
- buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
-
- if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf) != OMX_ErrorNone)
- {
- status = -6;
+ OMX_CONFIG_PORTBOOLEANTYPE discardMode;
+ memset (&discardMode, 0, sizeof (discardMode));
+ discardMode.nSize = sizeof (discardMode);
+ discardMode.nPortIndex = 220;
+ discardMode.nVersion.nVersion = OMX_VERSION;
+ discardMode.bEnabled = OMX_FALSE;
+ if (OMX_SetParameter (ILC_GET_HANDLE (egl_render),
+ OMX_IndexParamBrcmVideoEGLRenderDiscardMode,
+ &discardMode) != OMX_ErrorNone) {
+ status = -7;
break;
- }
+ }
+#undef OMX_IndexParamBrcmVideoEGLRenderDiscardMode
+ }
+
+ if (ilclient_setup_tunnel (tunnel, 0, 0) != 0) {
+ status = -7;
+ break;
+ }
+ /* Set egl_render to idle */
+ ilclient_change_component_state (egl_render, OMX_StateIdle);
+
+ /* Enable the output port and tell egl_render to use the texture as a buffer
+ * ilclient_enable_port(egl_render, 221); THIS BLOCKS SO CANT BE USED */
+ if (OMX_SendCommand (ILC_GET_HANDLE (egl_render), OMX_CommandPortEnable,
+ 221, NULL) != OMX_ErrorNone) {
+ g_print ("OMX_CommandPortEnable failed.\n");
+ exit (1);
+ }
+
+ if (OMX_UseEGLImage (ILC_GET_HANDLE (egl_render), &eglBuffer, 221, NULL,
+ eglImage) != OMX_ErrorNone) {
+ g_print ("OMX_UseEGLImage failed.\n");
+ exit (1);
+ }
+ /* Set egl_render to executing */
+ ilclient_change_component_state (egl_render, OMX_StateExecuting);
+
+
+ /* Request egl_render to write data to the texture buffer */
+ if (OMX_FillThisBuffer (ILC_GET_HANDLE (egl_render),
+ eglBuffer) != OMX_ErrorNone) {
+ g_print ("OMX_FillThisBuffer failed.\n");
+ exit (1);
+ }
+ }
+ if (!data_len)
+ break;
+
+ buf->nFilledLen = data_len;
+ data_len = 0;
+
+ buf->nOffset = 0;
+ if (first_packet) {
+ buf->nFlags = OMX_BUFFERFLAG_STARTTIME;
+ first_packet = 0;
+ } else
+ buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN;
+
+ if (OMX_EmptyThisBuffer (ILC_GET_HANDLE (video_decode),
+ buf) != OMX_ErrorNone) {
+ status = -6;
+ break;
}
+ }
- printf ("Sending EOS buffer\n");
- buf->nFilledLen = 0;
- buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN | OMX_BUFFERFLAG_EOS;
+ g_print ("Sending EOS buffer\n");
+ buf->nFilledLen = 0;
+ buf->nFlags = OMX_BUFFERFLAG_TIME_UNKNOWN | OMX_BUFFERFLAG_EOS;
- if(OMX_EmptyThisBuffer(ILC_GET_HANDLE(video_decode), buf) != OMX_ErrorNone)
- status = -20;
+ if (OMX_EmptyThisBuffer (ILC_GET_HANDLE (video_decode),
+ buf) != OMX_ErrorNone)
+ status = -20;
- printf ("Pause media processing pipeline\n");
- ilclient_state_transition(list, OMX_StatePause);
- printf ("Flushing tunnel\n");
- // need to flush the renderer to allow video_decode to disable its input port
- ilclient_flush_tunnels(tunnel, 0);
- printf ("Disable video decoder input port\n");
- ilclient_disable_port_buffers(video_decode, 130, NULL, NULL, NULL);
- }
+ g_print ("Pause media processing pipeline\n");
+ ilclient_state_transition (list, OMX_StatePause);
+ g_print ("Flushing tunnel\n");
+ /* need to flush the renderer to allow video_decode to disable its input port */
+ ilclient_flush_tunnels (tunnel, 0);
+ g_print ("Disable video decoder input port\n");
+ ilclient_disable_port_buffers (video_decode, 130, NULL, NULL, NULL);
+ }
- fclose(in);
+ fclose (in);
- printf ("change media processing pipeline to idle state\n");
- ilclient_state_transition(list, OMX_StateIdle);
+ g_print ("change media processing pipeline to idle state\n");
+ ilclient_state_transition (list, OMX_StateIdle);
- printf ("Disable tunnels\n");
- ilclient_disable_tunnel(tunnel);
- ilclient_teardown_tunnels(tunnel);
+ g_print ("Disable tunnels\n");
+ ilclient_disable_tunnel (tunnel);
+ ilclient_teardown_tunnels (tunnel);
- printf ("release components\n");
- ilclient_cleanup_components(list);
+ g_print ("release components\n");
+ ilclient_cleanup_components (list);
- printf ("deinit OpenMAX\n");
- OMX_Deinit();
+ g_print ("deinit OpenMAX\n");
+ OMX_Deinit ();
- printf ("destroy IL client\n");
- ilclient_destroy(client);
- exit(1);
- return (void *)status;
+ g_print ("destroy IL client\n");
+ ilclient_destroy (client);
+ return (void *) status;
}
+void
+video_decode_stop ()
+{
+ running = FALSE;
+}