├── 9781484224717.jpg ├── C files.zip ├── Dispmanx └── info.c ├── EGL ├── context.c ├── info.c └── window.c ├── LICENSE.txt ├── OpenGLES ├── Hello_Square.c ├── Hello_Triangle.c ├── Hello_TriangleColour.c ├── Rotate_Image.c └── Simple_Image.c ├── OpenMAX ├── Audio │ ├── api-example.c │ ├── il_ffmpeg_render_audio.c │ ├── il_ffmpeg_render_resample_audio.c │ ├── il_render_audio.c │ └── il_test_audio_encodings.c ├── Buffers │ ├── il_buffer.c │ └── il_decode_image.c ├── Components │ ├── info.c │ ├── listcomponents.c │ └── portinfo.c ├── DeMux │ ├── ffmpeg_demux_decode_audio.c │ ├── il_ffmpeg_demux_render_audio.c │ ├── il_ffmpeg_demux_render_video.c │ └── il_ffmpeg_demux_render_video_full_speed.c ├── EGL │ ├── square.c │ └── video.c ├── ILClient │ └── il_working.c ├── Images │ ├── il_decode_image_redone.c │ ├── il_render_image.c │ └── il_render_image_notunnel.c ├── State │ ├── event.c │ ├── wontwork.c │ └── working.c └── Video │ ├── il_decode_video.c │ └── il_render_video.c ├── OpenVG ├── Basic │ ├── ellipse.c │ ├── image.c │ ├── simple_shape.c │ └── window.c └── Text │ ├── cairo.c │ ├── pango.c │ ├── text-bitmap.c │ ├── text-font.c │ └── text-outline.c ├── Overlays ├── il_render_image_gles_overlay.c ├── il_render_image_vg_overlay.c ├── il_render_video_gles_overlay.c ├── il_render_video_pango_overlay.c └── il_render_video_vg_overlay.c ├── README.md └── contributing.md /9781484224717.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/raspberry-pi-gpu-audio-video-prog/a3a8b1cde03d32e230502277fd0250695e9581cf/9781484224717.jpg -------------------------------------------------------------------------------- /C files.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/raspberry-pi-gpu-audio-video-prog/a3a8b1cde03d32e230502277fd0250695e9581cf/C files.zip -------------------------------------------------------------------------------- /Dispmanx/info.c: -------------------------------------------------------------------------------- 1 | /* 2 | * code stolen from openGL-RPi-tutorial-master/encode_OGL/ 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | typedef struct 11 | { 12 | uint32_t screen_width; 13 | uint32_t screen_height; 14 | DISPMANX_DISPLAY_HANDLE_T dispman_display; 15 | } DISPMANX_STATE_T; 16 | 17 | DISPMANX_STATE_T state, *p_state = &state; 18 | 19 | void init_dispmanx(DISPMANX_STATE_T *state) { 20 | int32_t success = 0; 21 | 22 | bcm_host_init(); 23 | 24 | DISPMANX_ELEMENT_HANDLE_T dispman_element; 25 | 26 | DISPMANX_UPDATE_HANDLE_T dispman_update; 27 | VC_RECT_T dst_rect; 28 | VC_RECT_T src_rect; 29 | 30 | success = graphics_get_display_size(0 /* LCD */, 31 | &state->screen_width, 32 | &state->screen_height); 33 | assert( success >= 0 ); 34 | 35 | printf("Screen height %d, width %d\n", 36 | state->screen_height, state->screen_width); 37 | 38 | dst_rect.x = 0; 39 | dst_rect.y = 0; 40 | dst_rect.width = state->screen_width; 41 | dst_rect.height = state->screen_height; 42 | 43 | src_rect.x = 0; 44 | src_rect.y = 0; 45 | src_rect.width = state->screen_width << 16; 46 | src_rect.height = state->screen_height << 16; 47 | 48 | state->dispman_display = vc_dispmanx_display_open( 0 /* LCD */); 49 | dispman_update = vc_dispmanx_update_start( 0 ); 50 | 51 | dispman_element = 52 | vc_dispmanx_element_add(dispman_update, state->dispman_display, 53 | 0/*layer*/, &dst_rect, 0/*src*/, 54 | &src_rect, DISPMANX_PROTECTION_NONE, 55 | 0 /*alpha*/, 0/*clamp*/, 0/*transform*/); 56 | 57 | /* Now we have created a native Dispmanx window 58 | * Toolkits such as OpenGL ES will use this for 59 | * their own 'native window' type, with code like this: 60 | 61 | static EGL_DISPMANX_WINDOW_T nativewindow; 62 | 63 | nativewindow.element = dispman_element; 64 | nativewindow.width = state->screen_width; 65 | nativewindow.height = state->screen_height; 66 | vc_dispmanx_update_submit_sync( dispman_update ); 67 | assert(vc_dispmanx_element_remove(dispman_update, dispman_element) == 0); 68 | */ 69 | } 70 | 71 | int 72 | main(int argc, char *argv[]) 73 | { 74 | init_dispmanx(p_state); 75 | 76 | assert( vc_dispmanx_display_close(p_state->dispman_display) == 0); 77 | 78 | return 0; 79 | } 80 | 81 | -------------------------------------------------------------------------------- /EGL/context.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * code stolen from openGL-RPi-tutorial-master/encode_OGL/ 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | typedef struct 14 | { 15 | uint32_t screen_width; 16 | uint32_t screen_height; 17 | 18 | EGLDisplay display; 19 | EGLSurface surface; 20 | EGLContext context; 21 | EGLConfig config; 22 | } EGL_STATE_T; 23 | 24 | 25 | EGL_STATE_T state, *p_state = &state; 26 | 27 | void init_egl(EGL_STATE_T *state) 28 | { 29 | EGLBoolean result; 30 | EGLint num_configs; 31 | 32 | static const EGLint attribute_list[] = 33 | { 34 | EGL_RED_SIZE, 8, 35 | EGL_GREEN_SIZE, 8, 36 | EGL_BLUE_SIZE, 8, 37 | EGL_ALPHA_SIZE, 8, 38 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 39 | EGL_NONE 40 | }; 41 | 42 | static const EGLint context_attributes[] = 43 | { 44 | EGL_CONTEXT_CLIENT_VERSION, 2, 45 | EGL_NONE 46 | }; 47 | 48 | EGLConfig *configs; 49 | 50 | // get an EGL display connection 51 | state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 52 | 53 | // initialize the EGL display connection 54 | result = eglInitialize(state->display, NULL, NULL); 55 | 56 | eglGetConfigs(state->display, NULL, 0, &num_configs); 57 | printf("EGL has %d configs\n", num_configs); 58 | 59 | configs = calloc(num_configs, sizeof *configs); 60 | eglGetConfigs(state->display, configs, num_configs, &num_configs); 61 | 62 | // get an appropriate EGL configuration - just use the first available 63 | result = eglChooseConfig(state->display, attribute_list, 64 | &state->config, 1, &num_configs); 65 | assert(EGL_FALSE != result); 66 | 67 | // Choose the OpenGL ES API 68 | result = eglBindAPI(EGL_OPENGL_ES_API); 69 | assert(EGL_FALSE != result); 70 | 71 | // create an EGL rendering context 72 | state->context = eglCreateContext(state->display, 73 | state->config, EGL_NO_CONTEXT, 74 | context_attributes); 75 | assert(state->context!=EGL_NO_CONTEXT); 76 | printf("Got an EGL context\n"); 77 | } 78 | 79 | int 80 | main(int argc, char *argv[]) 81 | { 82 | init_egl(p_state); 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /EGL/info.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * code stolen from openGL-RPi-tutorial-master/encode_OGL/ 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | typedef struct 15 | { 16 | uint32_t screen_width; 17 | uint32_t screen_height; 18 | 19 | EGLDisplay display; 20 | EGLSurface surface; 21 | EGLContext context; 22 | EGLConfig config; 23 | } EGL_STATE_T; 24 | 25 | 26 | EGL_STATE_T state, *p_state = &state; 27 | 28 | void printConfigInfo(int n, EGLDisplay display, EGLConfig *config) { 29 | int size; 30 | 31 | printf("Configuration %d is\n", n); 32 | 33 | eglGetConfigAttrib(display, 34 | *config, EGL_RED_SIZE, &size); 35 | printf(" Red size is %d\n", size); 36 | eglGetConfigAttrib(display, 37 | *config, EGL_BLUE_SIZE, &size); 38 | printf(" Blue size is %d\n", size); 39 | eglGetConfigAttrib(display, 40 | *config, EGL_GREEN_SIZE, &size); 41 | printf(" Green size is %d\n", size); 42 | eglGetConfigAttrib(display, 43 | *config, EGL_BUFFER_SIZE, &size); 44 | printf(" Buffer size is %d\n", size); 45 | 46 | eglGetConfigAttrib(display, 47 | *config, EGL_BIND_TO_TEXTURE_RGB , &size); 48 | if (size == EGL_TRUE) 49 | printf(" Can be bound to RGB texture\n"); 50 | else 51 | printf(" Can't be bound to RGB texture\n"); 52 | 53 | eglGetConfigAttrib(display, 54 | *config, EGL_BIND_TO_TEXTURE_RGBA , &size); 55 | if (size == EGL_TRUE) 56 | printf(" Can be bound to RGBA texture\n"); 57 | else 58 | printf(" Can't be bound to RGBA texture\n"); 59 | } 60 | 61 | void init_egl(EGL_STATE_T *state) 62 | { 63 | EGLBoolean result; 64 | EGLint num_configs; 65 | 66 | EGLConfig *configs; 67 | 68 | // get an EGL display connection 69 | state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 70 | 71 | // initialize the EGL display connection 72 | result = eglInitialize(state->display, NULL, NULL); 73 | if (result == EGL_FALSE) { 74 | fprintf(stderr, "Can't initialise EGL\n"); 75 | exit(1); 76 | } 77 | 78 | eglGetConfigs(state->display, NULL, 0, &num_configs); 79 | printf("EGL has %d configs\n", num_configs); 80 | 81 | configs = calloc(num_configs, sizeof *configs); 82 | eglGetConfigs(state->display, configs, num_configs, &num_configs); 83 | 84 | int i; 85 | for (i = 0; i < num_configs; i++) { 86 | printConfigInfo(i, state->display, &configs[i]); 87 | } 88 | } 89 | 90 | int 91 | main(int argc, char *argv[]) 92 | { 93 | init_egl(p_state); 94 | 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /EGL/window.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * code stolen from openGL-RPi-tutorial-master/encode_OGL/ 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | typedef struct 17 | { 18 | EGLDisplay display; 19 | EGLSurface surface; 20 | EGLContext context; 21 | EGLConfig config; 22 | 23 | EGL_DISPMANX_WINDOW_T nativewindow; 24 | DISPMANX_DISPLAY_HANDLE_T dispman_display; 25 | } EGL_STATE_T; 26 | 27 | EGL_STATE_T state = { 28 | .display = EGL_NO_DISPLAY, 29 | .surface = EGL_NO_SURFACE, 30 | .context = EGL_NO_CONTEXT 31 | }; 32 | EGL_STATE_T *p_state = &state; 33 | 34 | void init_egl(EGL_STATE_T *state) 35 | { 36 | EGLint num_configs; 37 | EGLBoolean result; 38 | 39 | bcm_host_init(); 40 | 41 | static const EGLint attribute_list[] = 42 | { 43 | EGL_RED_SIZE, 8, 44 | EGL_GREEN_SIZE, 8, 45 | EGL_BLUE_SIZE, 8, 46 | EGL_ALPHA_SIZE, 8, 47 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 48 | EGL_NONE 49 | }; 50 | 51 | static const EGLint context_attributes[] = 52 | { 53 | EGL_CONTEXT_CLIENT_VERSION, 2, 54 | EGL_NONE 55 | }; 56 | 57 | // get an EGL display connection 58 | state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 59 | 60 | // initialize the EGL display connection 61 | result = eglInitialize(state->display, NULL, NULL); 62 | 63 | // get an appropriate EGL frame buffer configuration 64 | result = eglChooseConfig(state->display, attribute_list, &state->config, 1, &num_configs); 65 | assert(EGL_FALSE != result); 66 | 67 | // Choose the OpenGL ES API 68 | result = eglBindAPI(EGL_OPENGL_ES_API); 69 | assert(EGL_FALSE != result); 70 | 71 | // create an EGL rendering context 72 | state->context = eglCreateContext(state->display, 73 | state->config, EGL_NO_CONTEXT, 74 | context_attributes); 75 | assert(state->context!=EGL_NO_CONTEXT); 76 | } 77 | 78 | void init_dispmanx(EGL_STATE_T *state) { 79 | EGL_DISPMANX_WINDOW_T *nativewindow = &p_state->nativewindow; 80 | int32_t success = 0; 81 | uint32_t screen_width; 82 | uint32_t screen_height; 83 | 84 | DISPMANX_ELEMENT_HANDLE_T dispman_element; 85 | DISPMANX_DISPLAY_HANDLE_T dispman_display; 86 | DISPMANX_UPDATE_HANDLE_T dispman_update; 87 | VC_RECT_T dst_rect; 88 | VC_RECT_T src_rect; 89 | 90 | bcm_host_init(); 91 | 92 | // create an EGL window surface 93 | success = graphics_get_display_size(0 /* LCD */, 94 | &screen_width, 95 | &screen_height); 96 | assert( success >= 0 ); 97 | 98 | dst_rect.x = 0; 99 | dst_rect.y = 0; 100 | dst_rect.width = screen_width; 101 | dst_rect.height = screen_height; 102 | 103 | src_rect.x = 0; 104 | src_rect.y = 0; 105 | src_rect.width = screen_width << 16; 106 | src_rect.height = screen_height << 16; 107 | 108 | dispman_display = vc_dispmanx_display_open( 0 /* LCD */); 109 | dispman_update = vc_dispmanx_update_start( 0 ); 110 | state->dispman_display = dispman_display; 111 | 112 | dispman_element = 113 | vc_dispmanx_element_add(dispman_update, dispman_display, 114 | 0/*layer*/, &dst_rect, 0/*src*/, 115 | &src_rect, DISPMANX_PROTECTION_NONE, 116 | 0 /*alpha*/, 0/*clamp*/, 0/*transform*/); 117 | 118 | // Build an EGL_DISPMANX_WINDOW_T from the Dispmanx window 119 | nativewindow->element = dispman_element; 120 | nativewindow->width = screen_width; 121 | nativewindow->height = screen_height; 122 | vc_dispmanx_update_submit_sync(dispman_update); 123 | assert(vc_dispmanx_element_remove(dispman_update, dispman_element) == 0); 124 | 125 | printf("Got a Dispmanx window\n"); 126 | } 127 | 128 | void egl_from_dispmanx(EGL_STATE_T *state) { 129 | EGLBoolean result; 130 | 131 | state->surface = eglCreateWindowSurface(state->display, 132 | state->config, 133 | &p_state->nativewindow, NULL ); 134 | assert(state->surface != EGL_NO_SURFACE); 135 | 136 | // connect the context to the surface 137 | result = eglMakeCurrent(state->display, state->surface, state->surface, state->context); 138 | assert(EGL_FALSE != result); 139 | } 140 | 141 | void cleanup(int s) { 142 | if (p_state->surface != EGL_NO_SURFACE && 143 | eglDestroySurface(p_state->display, p_state->surface)) { 144 | printf("Surface destroyed ok\n"); 145 | } 146 | if (p_state->context != EGL_NO_CONTEXT && 147 | eglDestroyContext(p_state->display, p_state->context)) { 148 | printf("Main context destroyed ok\n"); 149 | } 150 | if (p_state->display != EGL_NO_DISPLAY && 151 | eglTerminate(p_state->display)) { 152 | printf("Display terminated ok\n"); 153 | } 154 | if (eglReleaseThread()) { 155 | printf("EGL thread resources released ok\n"); 156 | } 157 | if (vc_dispmanx_display_close(p_state->dispman_display) == 0) { 158 | printf("Dispmanx display rleased ok\n"); 159 | } 160 | bcm_host_deinit(); 161 | exit(s); 162 | } 163 | 164 | int 165 | main(int argc, char *argv[]) 166 | { 167 | signal(SIGINT, cleanup); 168 | 169 | init_egl(p_state); 170 | 171 | init_dispmanx(p_state); 172 | 173 | egl_from_dispmanx(p_state); 174 | 175 | 176 | glClearColor(1.0, 0.0, 0.0, 1.0); 177 | glClear(GL_COLOR_BUFFER_BIT); 178 | glFlush(); 179 | 180 | eglSwapBuffers(p_state->display, p_state->surface); 181 | 182 | sleep(4); 183 | 184 | cleanup(0); 185 | return 0; 186 | } 187 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/raspberry-pi-gpu-audio-video-prog/a3a8b1cde03d32e230502277fd0250695e9581cf/LICENSE.txt -------------------------------------------------------------------------------- /OpenGLES/Hello_Square.c: -------------------------------------------------------------------------------- 1 | // 2 | // Book: OpenGL(R) ES 2.0 Programming Guide 3 | // Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner 4 | // ISBN-10: 0321502795 5 | // ISBN-13: 9780321502797 6 | // Publisher: Addison-Wesley Professional 7 | // URLs: http://safari.informit.com/9780321563835 8 | // http://www.opengles-book.com 9 | // 10 | 11 | // Hello_Triangle.c 12 | // 13 | // This is a simple example that draws a single triangle with 14 | // a minimal vertex/fragment shader. The purpose of this 15 | // example is to demonstrate the basic concepts of 16 | // OpenGL ES 2.0 rendering. 17 | #include 18 | #include "esUtil.h" 19 | 20 | typedef struct 21 | { 22 | // Handle to a program object 23 | GLuint programObject; 24 | 25 | } UserData; 26 | 27 | /// 28 | // Create a shader object, load the shader source, and 29 | // compile the shader. 30 | // 31 | GLuint LoadShader ( GLenum type, const char *shaderSrc ) 32 | { 33 | GLuint shader; 34 | GLint compiled; 35 | 36 | // Create the shader object 37 | shader = glCreateShader ( type ); 38 | 39 | if ( shader == 0 ) 40 | return 0; 41 | 42 | // Load the shader source 43 | glShaderSource ( shader, 1, &shaderSrc, NULL ); 44 | 45 | // Compile the shader 46 | glCompileShader ( shader ); 47 | 48 | // Check the compile status 49 | glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled ); 50 | 51 | if ( !compiled ) 52 | { 53 | GLint infoLen = 0; 54 | 55 | glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen ); 56 | 57 | if ( infoLen > 1 ) 58 | { 59 | char* infoLog = malloc (sizeof(char) * infoLen ); 60 | 61 | glGetShaderInfoLog ( shader, infoLen, NULL, infoLog ); 62 | esLogMessage ( "Error compiling shader:\n%s\n", infoLog ); 63 | 64 | free ( infoLog ); 65 | } 66 | 67 | glDeleteShader ( shader ); 68 | return 0; 69 | } 70 | 71 | return shader; 72 | 73 | } 74 | 75 | /// 76 | // Initialize the shader and program object 77 | // 78 | int Init ( ESContext *esContext ) 79 | { 80 | esContext->userData = malloc(sizeof(UserData)); 81 | 82 | UserData *userData = esContext->userData; 83 | GLbyte vShaderStr[] = 84 | "attribute vec4 vPosition; \n" 85 | "void main() \n" 86 | "{ \n" 87 | " gl_Position = vPosition; \n" 88 | "} \n"; 89 | 90 | GLbyte fShaderStr[] = 91 | "precision mediump float;\n"\ 92 | "void main() \n" 93 | "{ \n" 94 | " gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n" 95 | "} \n"; 96 | 97 | GLuint vertexShader; 98 | GLuint fragmentShader; 99 | GLuint programObject; 100 | GLint linked; 101 | 102 | // Load the vertex/fragment shaders 103 | vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr ); 104 | fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr ); 105 | 106 | // Create the program object 107 | programObject = glCreateProgram ( ); 108 | 109 | if ( programObject == 0 ) 110 | return 0; 111 | 112 | glAttachShader ( programObject, vertexShader ); 113 | glAttachShader ( programObject, fragmentShader ); 114 | 115 | // Bind vPosition to attribute 0 116 | glBindAttribLocation ( programObject, 0, "vPosition" ); 117 | 118 | // Link the program 119 | glLinkProgram ( programObject ); 120 | 121 | // Check the link status 122 | glGetProgramiv ( programObject, GL_LINK_STATUS, &linked ); 123 | 124 | if ( !linked ) 125 | { 126 | GLint infoLen = 0; 127 | 128 | glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen ); 129 | 130 | if ( infoLen > 1 ) 131 | { 132 | char* infoLog = malloc (sizeof(char) * infoLen ); 133 | 134 | glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog ); 135 | esLogMessage ( "Error linking program:\n%s\n", infoLog ); 136 | 137 | free ( infoLog ); 138 | } 139 | 140 | glDeleteProgram ( programObject ); 141 | return GL_FALSE; 142 | } 143 | 144 | // Store the program object 145 | userData->programObject = programObject; 146 | 147 | glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); 148 | return GL_TRUE; 149 | } 150 | 151 | /// 152 | // Draw a triangle using the shader pair created in Init() 153 | // 154 | void Draw ( ESContext *esContext ) 155 | { 156 | #define TRIANGLES 1 157 | #define ELEMENTS 1 158 | 159 | UserData *userData = esContext->userData; 160 | GLfloat vVertices[] = { 161 | 1.0f, -1.0f, 0.0f, 162 | 1.0f, 1.0f, 0.0f, 163 | -1.0f, -1.0f, 0.0f, 164 | -1.0f, 1.0f, 0.0f, 165 | #if TRIANGLES 166 | -1.0f, -1.0f, 0.0f, 167 | 1.0f, 1.0f, 0.0f 168 | #endif 169 | }; 170 | 171 | #if ELEMENTS 172 | GLubyte vIndices[] = { 173 | 0, 1, 2, 174 | 3, 175 | # if TRIANGLES 176 | 4, 5 177 | # endif 178 | }; 179 | #endif 180 | 181 | // Set the viewport 182 | glViewport ( 0, 0, esContext->width, esContext->height ); 183 | 184 | // Clear the color buffer 185 | glClear ( GL_COLOR_BUFFER_BIT ); 186 | 187 | // Use the program object 188 | glUseProgram ( userData->programObject ); 189 | 190 | // Load the vertex data 191 | glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices ); 192 | glEnableVertexAttribArray ( 0 ); 193 | 194 | #if TRIANGLES 195 | # if ELEMENTS 196 | glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, vIndices ); 197 | # else 198 | glDrawArrays ( GL_TRIANGLES, 0, 6 ); 199 | # endif 200 | #else 201 | # if ELEMENTS 202 | glDrawElements ( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, vIndices ); 203 | # else 204 | glDrawArrays ( GL_TRIANGLE_STRIP, 0, 4 ); 205 | # endif 206 | #endif 207 | //glDrawArrays ( GL_TRIANGLES, 3, 3 ); 208 | } 209 | 210 | int main ( int argc, char *argv[] ) 211 | { 212 | ESContext esContext; 213 | UserData userData; 214 | 215 | esInitContext ( &esContext ); 216 | esContext.userData = &userData; 217 | 218 | esCreateWindow ( &esContext, "Hello Triangle", 320, 240, ES_WINDOW_RGB ); 219 | 220 | if ( !Init ( &esContext ) ) 221 | return 0; 222 | 223 | esRegisterDrawFunc ( &esContext, Draw ); 224 | 225 | esMainLoop ( &esContext ); 226 | } 227 | -------------------------------------------------------------------------------- /OpenGLES/Hello_Triangle.c: -------------------------------------------------------------------------------- 1 | // 2 | // Book: OpenGL(R) ES 2.0 Programming Guide 3 | // Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner 4 | // ISBN-10: 0321502795 5 | // ISBN-13: 9780321502797 6 | // Publisher: Addison-Wesley Professional 7 | // URLs: http://safari.informit.com/9780321563835 8 | // http://www.opengles-book.com 9 | // 10 | 11 | // Hello_Triangle.c 12 | // 13 | // This is a simple example that draws a single triangle with 14 | // a minimal vertex/fragment shader. The purpose of this 15 | // example is to demonstrate the basic concepts of 16 | // OpenGL ES 2.0 rendering. 17 | #include 18 | #include "esUtil.h" 19 | 20 | typedef struct 21 | { 22 | // Handle to a program object 23 | GLuint programObject; 24 | 25 | } UserData; 26 | 27 | /// 28 | // Create a shader object, load the shader source, and 29 | // compile the shader. 30 | // 31 | GLuint LoadShader ( GLenum type, const char *shaderSrc ) 32 | { 33 | GLuint shader; 34 | GLint compiled; 35 | 36 | // Create the shader object 37 | shader = glCreateShader ( type ); 38 | 39 | if ( shader == 0 ) 40 | return 0; 41 | 42 | // Load the shader source 43 | glShaderSource ( shader, 1, &shaderSrc, NULL ); 44 | 45 | // Compile the shader 46 | glCompileShader ( shader ); 47 | 48 | // Check the compile status 49 | glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled ); 50 | 51 | if ( !compiled ) 52 | { 53 | GLint infoLen = 0; 54 | 55 | glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen ); 56 | 57 | if ( infoLen > 1 ) 58 | { 59 | char* infoLog = malloc (sizeof(char) * infoLen ); 60 | 61 | glGetShaderInfoLog ( shader, infoLen, NULL, infoLog ); 62 | esLogMessage ( "Error compiling shader:\n%s\n", infoLog ); 63 | 64 | free ( infoLog ); 65 | } 66 | 67 | glDeleteShader ( shader ); 68 | return 0; 69 | } 70 | 71 | return shader; 72 | 73 | } 74 | 75 | /// 76 | // Initialize the shader and program object 77 | // 78 | int Init ( ESContext *esContext ) 79 | { 80 | esContext->userData = malloc(sizeof(UserData)); 81 | 82 | UserData *userData = esContext->userData; 83 | GLbyte vShaderStr[] = 84 | "attribute vec4 vPosition; \n" 85 | "void main() \n" 86 | "{ \n" 87 | " gl_Position = vPosition; \n" 88 | "} \n"; 89 | 90 | GLbyte fShaderStr[] = 91 | "precision mediump float;\n"\ 92 | "void main() \n" 93 | "{ \n" 94 | " gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n" 95 | "} \n"; 96 | 97 | GLuint vertexShader; 98 | GLuint fragmentShader; 99 | GLuint programObject; 100 | GLint linked; 101 | 102 | // Load the vertex/fragment shaders 103 | vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr ); 104 | fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr ); 105 | 106 | // Create the program object 107 | programObject = glCreateProgram ( ); 108 | 109 | if ( programObject == 0 ) 110 | return 0; 111 | 112 | glAttachShader ( programObject, vertexShader ); 113 | glAttachShader ( programObject, fragmentShader ); 114 | 115 | // Bind vPosition to attribute 0 116 | glBindAttribLocation ( programObject, 0, "vPosition" ); 117 | 118 | // Link the program 119 | glLinkProgram ( programObject ); 120 | 121 | // Check the link status 122 | glGetProgramiv ( programObject, GL_LINK_STATUS, &linked ); 123 | 124 | if ( !linked ) 125 | { 126 | GLint infoLen = 0; 127 | 128 | glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen ); 129 | 130 | if ( infoLen > 1 ) 131 | { 132 | char* infoLog = malloc (sizeof(char) * infoLen ); 133 | 134 | glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog ); 135 | esLogMessage ( "Error linking program:\n%s\n", infoLog ); 136 | 137 | free ( infoLog ); 138 | } 139 | 140 | glDeleteProgram ( programObject ); 141 | return GL_FALSE; 142 | } 143 | 144 | // Store the program object 145 | userData->programObject = programObject; 146 | 147 | glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); 148 | return GL_TRUE; 149 | } 150 | 151 | /// 152 | // Draw a triangle using the shader pair created in Init() 153 | // 154 | void Draw ( ESContext *esContext ) 155 | { 156 | UserData *userData = esContext->userData; 157 | GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f, 158 | -0.5f, -0.5f, 0.0f, 159 | 0.5f, -0.5f, 0.0f }; 160 | 161 | // Set the viewport 162 | glViewport ( 0, 0, esContext->width, esContext->height ); 163 | 164 | // Clear the color buffer 165 | glClear ( GL_COLOR_BUFFER_BIT ); 166 | 167 | // Use the program object 168 | glUseProgram ( userData->programObject ); 169 | 170 | // Load the vertex data 171 | glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices ); 172 | glEnableVertexAttribArray ( 0 ); 173 | 174 | glDrawArrays ( GL_TRIANGLES, 0, 3 ); 175 | } 176 | 177 | int main ( int argc, char *argv[] ) 178 | { 179 | ESContext esContext; 180 | UserData userData; 181 | 182 | esInitContext ( &esContext ); 183 | esContext.userData = &userData; 184 | 185 | esCreateWindow ( &esContext, "Hello Triangle", 320, 240, ES_WINDOW_RGB ); 186 | 187 | if ( !Init ( &esContext ) ) 188 | return 0; 189 | 190 | esRegisterDrawFunc ( &esContext, Draw ); 191 | 192 | esMainLoop ( &esContext ); 193 | } 194 | -------------------------------------------------------------------------------- /OpenGLES/Hello_TriangleColour.c: -------------------------------------------------------------------------------- 1 | // 2 | // Book: OpenGL(R) ES 2.0 Programming Guide 3 | // Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner 4 | // ISBN-10: 0321502795 5 | // ISBN-13: 9780321502797 6 | // Publisher: Addison-Wesley Professional 7 | // URLs: http://safari.informit.com/9780321563835 8 | // http://www.opengles-book.com 9 | // 10 | 11 | // Hello_TriangleColour.c 12 | // 13 | // This is a simple example that draws a single triangle with 14 | // a minimal vertex/fragment shader. The purpose of this 15 | // example is to demonstrate the basic concepts of 16 | // OpenGL ES 2.0 rendering. 17 | #include 18 | #include "esUtil.h" 19 | 20 | typedef struct 21 | { 22 | // Handle to a program object 23 | GLuint programObject; 24 | 25 | } UserData; 26 | 27 | /// 28 | // Create a shader object, load the shader source, and 29 | // compile the shader. 30 | // 31 | GLuint LoadShader ( GLenum type, const char *shaderSrc ) 32 | { 33 | GLuint shader; 34 | GLint compiled; 35 | 36 | // Create the shader object 37 | shader = glCreateShader ( type ); 38 | 39 | if ( shader == 0 ) 40 | return 0; 41 | 42 | // Load the shader source 43 | glShaderSource ( shader, 1, &shaderSrc, NULL ); 44 | 45 | // Compile the shader 46 | glCompileShader ( shader ); 47 | 48 | // Check the compile status 49 | glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled ); 50 | 51 | if ( !compiled ) 52 | { 53 | GLint infoLen = 0; 54 | 55 | glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen ); 56 | 57 | if ( infoLen > 1 ) 58 | { 59 | char* infoLog = malloc (sizeof(char) * infoLen ); 60 | 61 | glGetShaderInfoLog ( shader, infoLen, NULL, infoLog ); 62 | esLogMessage ( "Error compiling shader:\n%s\n", infoLog ); 63 | 64 | free ( infoLog ); 65 | } 66 | 67 | glDeleteShader ( shader ); 68 | return 0; 69 | } 70 | 71 | return shader; 72 | 73 | } 74 | 75 | /// 76 | // Initialize the shader and program object 77 | // 78 | int Init ( ESContext *esContext ) 79 | { 80 | esContext->userData = malloc(sizeof(UserData)); 81 | 82 | UserData *userData = esContext->userData; 83 | GLbyte vShaderStr[] = 84 | "attribute vec4 vPosition; \n" 85 | "attribute vec4 vColour; \n" 86 | "varying vec4 vFragmentColour; \n" 87 | "void main() \n" 88 | "{ \n" 89 | " gl_Position = vPosition; \n" 90 | " vFragmentColour = vColour;\n" 91 | "} \n"; 92 | 93 | GLbyte fShaderStr[] = 94 | "precision mediump float;\n"\ 95 | "varying vec4 vFragmentColour; \n" 96 | "void main() \n" 97 | "{ \n" 98 | " gl_FragColor = vFragmentColour;\n" 99 | "} \n"; 100 | 101 | GLuint vertexShader; 102 | GLuint fragmentShader; 103 | GLuint programObject; 104 | GLint linked; 105 | 106 | // Load the vertex/fragment shaders 107 | vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr ); 108 | fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr ); 109 | 110 | // Create the program object 111 | programObject = glCreateProgram ( ); 112 | 113 | if ( programObject == 0 ) 114 | return 0; 115 | 116 | glAttachShader ( programObject, vertexShader ); 117 | glAttachShader ( programObject, fragmentShader ); 118 | 119 | // Bind vPosition to attribute 0 120 | glBindAttribLocation ( programObject, 0, "vPosition" ); 121 | 122 | // Bind vColour to attribute 1 123 | glBindAttribLocation ( programObject, 1, "vColour" ); 124 | 125 | // Link the program 126 | glLinkProgram ( programObject ); 127 | 128 | // Check the link status 129 | glGetProgramiv ( programObject, GL_LINK_STATUS, &linked ); 130 | 131 | if ( !linked ) 132 | { 133 | GLint infoLen = 0; 134 | 135 | glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen ); 136 | 137 | if ( infoLen > 1 ) 138 | { 139 | char* infoLog = malloc (sizeof(char) * infoLen ); 140 | 141 | glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog ); 142 | esLogMessage ( "Error linking program:\n%s\n", infoLog ); 143 | 144 | free ( infoLog ); 145 | } 146 | 147 | glDeleteProgram ( programObject ); 148 | return GL_FALSE; 149 | } 150 | 151 | // Store the program object 152 | userData->programObject = programObject; 153 | 154 | glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); 155 | return GL_TRUE; 156 | } 157 | 158 | /// 159 | // Draw a triangle using the shader pair created in Init() 160 | // 161 | void Draw ( ESContext *esContext ) 162 | { 163 | UserData *userData = esContext->userData; 164 | GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f, 165 | -0.5f, -0.5f, 0.0f, 166 | 0.5f, -0.5f, 0.0f }; 167 | GLfloat vColours[] = {1.0f, 0.0f, 0.0f, 1.0f, 168 | 0.0f, 1.0f, 0.0f, 1.0f, 169 | 0.0f, 0.0f, 1.0f, 1.0f}; 170 | 171 | // Set the viewport 172 | glViewport ( 0, 0, esContext->width, esContext->height ); 173 | 174 | // Clear the color buffer 175 | glClear ( GL_COLOR_BUFFER_BIT ); 176 | 177 | // Use the program object 178 | glUseProgram ( userData->programObject ); 179 | 180 | // Load the vertex data 181 | glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices ); 182 | glEnableVertexAttribArray ( 0 ); 183 | glVertexAttribPointer ( 1, 4, GL_FLOAT, GL_FALSE, 0, vColours ); 184 | glEnableVertexAttribArray ( 1 ); 185 | 186 | glDrawArrays ( GL_TRIANGLES, 0, 3 ); 187 | } 188 | 189 | int main ( int argc, char *argv[] ) 190 | { 191 | ESContext esContext; 192 | UserData userData; 193 | 194 | esInitContext ( &esContext ); 195 | esContext.userData = &userData; 196 | 197 | esCreateWindow ( &esContext, "Hello Triangle", 320, 240, ES_WINDOW_RGB ); 198 | 199 | if ( !Init ( &esContext ) ) 200 | return 0; 201 | 202 | esRegisterDrawFunc ( &esContext, Draw ); 203 | 204 | esMainLoop ( &esContext ); 205 | } 206 | -------------------------------------------------------------------------------- /OpenGLES/Rotate_Image.c: -------------------------------------------------------------------------------- 1 | // 2 | // Book: OpenGL(R) ES 2.0 Programming Guide 3 | // Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner 4 | // ISBN-10: 0321502795 5 | // ISBN-13: 9780321502797 6 | // Publisher: Addison-Wesley Professional 7 | // URLs: http://safari.informit.com/9780321563835 8 | // http://www.opengles-book.com 9 | // 10 | 11 | // Simple_Texture2D.c 12 | // 13 | // This is a simple example that draws a quad with a 2D 14 | // texture image. The purpose of this example is to demonstrate 15 | // the basics of 2D texturing 16 | // 17 | #include 18 | #include 19 | #include "esUtil.h" 20 | 21 | typedef struct 22 | { 23 | // Handle to a program object 24 | GLuint programObject; 25 | 26 | // Attribute locations 27 | GLint positionLoc; 28 | GLint texCoordLoc; 29 | 30 | // Uniform locations 31 | GLint rotateLoc; 32 | 33 | // Sampler location 34 | GLint samplerLoc; 35 | 36 | // Texture handle 37 | GLuint textureId; 38 | 39 | GLubyte *image; 40 | int width, height; 41 | 42 | // Rotation angle 43 | GLfloat angle; 44 | 45 | // rotate matrix 46 | ESMatrix rotateMx; 47 | } UserData; 48 | 49 | /// 50 | // Create a simple 2x2 texture image with four different colors 51 | // 52 | GLuint CreateSimpleTexture2D(ESContext *esContext) 53 | { 54 | // Texture object handle 55 | GLuint textureId; 56 | UserData *userData = esContext->userData; 57 | 58 | #if 0 59 | // 2x2 Image, 3 bytes per pixel (R, G, B) 60 | GLubyte pixels[4 * 3] = 61 | { 62 | 255, 0, 0, // Red 63 | 0, 255, 0, // Green 64 | 0, 0, 255, // Blue 65 | 255, 255, 0 // Yellow 66 | }; 67 | userData->width = 2; 68 | userData->height = 2; 69 | #else 70 | GLubyte *pixels = userData->image; 71 | userData->width = esContext->width; 72 | userData->height = esContext->height; 73 | #endif 74 | // Use tightly packed data 75 | glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ); 76 | 77 | // Generate a texture object 78 | glGenTextures ( 1, &textureId ); 79 | 80 | // Bind the texture object 81 | glBindTexture ( GL_TEXTURE_2D, textureId ); 82 | 83 | // Load the texture 84 | glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 85 | userData->width, userData->height, 86 | 0, GL_RGB, GL_UNSIGNED_BYTE, pixels ); 87 | 88 | // Set the filtering mode 89 | glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); 90 | glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); 91 | 92 | return textureId; 93 | 94 | } 95 | 96 | 97 | /// 98 | // Initialize the shader and program object 99 | // 100 | int Init ( ESContext *esContext ) 101 | { 102 | UserData *userData = esContext->userData; 103 | GLbyte vShaderStr[] = 104 | "uniform mat4 u_rotateMx; \n" 105 | "attribute vec4 a_position; \n" 106 | "attribute vec2 a_texCoord; \n" 107 | "varying vec2 v_texCoord; \n" 108 | "void main() \n" 109 | "{ \n" 110 | " gl_Position = u_rotateMx * a_position; \n" 111 | " v_texCoord = a_texCoord; \n" 112 | "} \n"; 113 | 114 | GLbyte fShaderStr[] = 115 | "precision mediump float; \n" 116 | "varying vec2 v_texCoord; \n" 117 | "uniform sampler2D s_texture; \n" 118 | "void main() \n" 119 | "{ \n" 120 | " gl_FragColor = texture2D( s_texture, v_texCoord );\n" 121 | "} \n"; 122 | 123 | // Load the shaders and get a linked program object 124 | userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); 125 | 126 | // Get the attribute locations 127 | userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); 128 | userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" ); 129 | userData->rotateLoc = glGetUniformLocation( userData->programObject, "u_rotateMx" ); 130 | // Starting rotation angle for the square 131 | userData->angle = 0.0f; 132 | 133 | // Get the sampler location 134 | userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); 135 | 136 | // Load the texture 137 | userData->textureId = CreateSimpleTexture2D (esContext); 138 | 139 | glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); 140 | 141 | return GL_TRUE; 142 | } 143 | 144 | /// 145 | // Update rotate matrix based on time 146 | // 147 | void Update ( ESContext *esContext, float deltaTime ) 148 | { 149 | UserData *userData = (UserData*) esContext->userData; 150 | 151 | // Compute a rotation angle based on time to rotate the cube 152 | userData->angle += ( deltaTime * 40.0f ); 153 | if( userData->angle >= 360.0f ) 154 | userData->angle -= 360.0f; 155 | 156 | // Generate an identity matrix before rotating the square 157 | esMatrixLoadIdentity( &userData->rotateMx ); 158 | 159 | // Rotate the square 160 | esRotate( &userData->rotateMx, userData->angle, 1.0, 0.0, 1.0 ); 161 | } 162 | 163 | /// 164 | // Draw a triangle using the shader pair created in Init() 165 | // 166 | void Draw ( ESContext *esContext ) 167 | { 168 | UserData *userData = esContext->userData; 169 | GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, // Position 0 170 | 0.0f, 1.0f, // TexCoord 0 171 | -0.5f, -0.5f, 0.0f, // Position 1 172 | 0.0f, 0.0f, // TexCoord 1 173 | 0.5f, -0.5f, 0.0f, // Position 2 174 | 1.0f, 0.0f, // TexCoord 2 175 | 0.5f, 0.5f, 0.0f, // Position 3 176 | 1.0f, 1.0f // TexCoord 3 177 | }; 178 | GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; 179 | 180 | // Set the viewport 181 | glViewport ( 0, 0, esContext->width, esContext->height ); 182 | 183 | // Clear the color buffer 184 | glClear ( GL_COLOR_BUFFER_BIT ); 185 | 186 | // Use the program object 187 | glUseProgram ( userData->programObject ); 188 | 189 | // Load the vertex position 190 | glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, 191 | GL_FALSE, 5 * sizeof(GLfloat), vVertices ); 192 | // Load the texture coordinate 193 | glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT, 194 | GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] ); 195 | 196 | glEnableVertexAttribArray ( userData->positionLoc ); 197 | glEnableVertexAttribArray ( userData->texCoordLoc ); 198 | 199 | // Load the rotate matrix 200 | glUniformMatrix4fv( userData->rotateLoc, // userData->mvpLoc, 201 | 1, GL_FALSE, (GLfloat*) &userData->rotateMx.m[0][0] ); 202 | 203 | // Bind the texture 204 | glActiveTexture ( GL_TEXTURE0 ); 205 | glBindTexture ( GL_TEXTURE_2D, userData->textureId ); 206 | 207 | // Set the sampler texture unit to 0 208 | glUniform1i ( userData->samplerLoc, 0 ); 209 | 210 | glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); 211 | 212 | } 213 | 214 | /// 215 | // Cleanup 216 | // 217 | void ShutDown ( ESContext *esContext ) 218 | { 219 | UserData *userData = esContext->userData; 220 | 221 | // Delete texture object 222 | glDeleteTextures ( 1, &userData->textureId ); 223 | 224 | // Delete program object 225 | glDeleteProgram ( userData->programObject ); 226 | 227 | free(esContext->userData); 228 | } 229 | 230 | int main ( int argc, char *argv[] ) 231 | { 232 | ESContext esContext; 233 | UserData userData; 234 | 235 | int width, height; 236 | GLubyte *image; 237 | 238 | image = esLoadTGA("jan.tga", &width, &height); 239 | if (image == NULL) { 240 | fprintf(stderr, "No such image\n"); 241 | exit(1); 242 | } 243 | printf("Width %d height %d\n", width, height); 244 | 245 | userData.image = image; 246 | userData.width = width; 247 | userData.height = height; 248 | 249 | 250 | esInitContext ( &esContext ); 251 | esContext.userData = &userData; 252 | 253 | esCreateWindow ( &esContext, "Simple Texture 2D", width, height, ES_WINDOW_RGB ); 254 | 255 | if ( !Init ( &esContext ) ) 256 | return 0; 257 | 258 | esRegisterDrawFunc ( &esContext, Draw ); 259 | esRegisterUpdateFunc ( &esContext, Update ); 260 | 261 | esMainLoop ( &esContext ); 262 | 263 | ShutDown ( &esContext ); 264 | } 265 | -------------------------------------------------------------------------------- /OpenGLES/Simple_Image.c: -------------------------------------------------------------------------------- 1 | // Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner 2 | // Copyright: the authors and Jan Newmarch 3 | 4 | // Simple_Image.c 5 | // 6 | // This is a simple example that draws an image with a 2D 7 | // texture image. 8 | // 9 | #include 10 | #include 11 | #include "esUtil.h" 12 | 13 | typedef struct 14 | { 15 | // Handle to a program object 16 | GLuint programObject; 17 | 18 | // Attribute locations 19 | GLint positionLoc; 20 | GLint texCoordLoc; 21 | 22 | // Sampler location 23 | GLint samplerLoc; 24 | 25 | // Texture handle 26 | GLuint textureId; 27 | 28 | GLubyte *image; 29 | int width, height; 30 | } UserData; 31 | 32 | /// 33 | // Create a simple 2x2 texture image with four different colors 34 | // 35 | GLuint CreateSimpleTexture2D(ESContext *esContext) 36 | { 37 | // Texture object handle 38 | GLuint textureId; 39 | UserData *userData = esContext->userData; 40 | 41 | GLubyte *pixels = userData->image; 42 | userData->width = esContext->width; 43 | userData->height = esContext->height; 44 | 45 | // Use tightly packed data 46 | glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ); 47 | 48 | // Generate a texture object 49 | glGenTextures ( 1, &textureId ); 50 | 51 | // Bind the texture object 52 | glBindTexture ( GL_TEXTURE_2D, textureId ); 53 | 54 | // Load the texture 55 | glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 56 | userData->width, userData->height, 57 | 0, GL_RGB, GL_UNSIGNED_BYTE, pixels ); 58 | 59 | // Set the filtering mode 60 | glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); 61 | glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); 62 | 63 | return textureId; 64 | 65 | } 66 | 67 | 68 | /// 69 | // Initialize the shader and program object 70 | // 71 | int Init ( ESContext *esContext ) 72 | { 73 | UserData *userData = esContext->userData; 74 | GLbyte vShaderStr[] = 75 | "attribute vec4 a_position; \n" 76 | "attribute vec2 a_texCoord; \n" 77 | "varying vec2 v_texCoord; \n" 78 | "void main() \n" 79 | "{ \n" 80 | " gl_Position = a_position; \n" 81 | " v_texCoord = a_texCoord; \n" 82 | "} \n"; 83 | 84 | GLbyte fShaderStr[] = 85 | "precision mediump float; \n" 86 | "varying vec2 v_texCoord; \n" 87 | "uniform sampler2D s_texture; \n" 88 | "void main() \n" 89 | "{ \n" 90 | " gl_FragColor = texture2D( s_texture, v_texCoord );\n" 91 | "} \n"; 92 | 93 | // Load the shaders and get a linked program object 94 | userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); 95 | 96 | // Get the attribute locations 97 | userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); 98 | userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" ); 99 | 100 | // Get the sampler location 101 | userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); 102 | 103 | // Load the texture 104 | userData->textureId = CreateSimpleTexture2D (esContext); 105 | 106 | glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); 107 | return GL_TRUE; 108 | } 109 | 110 | /// 111 | // Draw a triangle using the shader pair created in Init() 112 | // 113 | void Draw ( ESContext *esContext ) 114 | { 115 | UserData *userData = esContext->userData; 116 | GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, // Position 0 117 | 0.0f, 1.0f, // TexCoord 0 118 | -0.5f, -0.5f, 0.0f, // Position 1 119 | 0.0f, 0.0f, // TexCoord 1 120 | 0.5f, -0.5f, 0.0f, // Position 2 121 | 1.0f, 0.0f, // TexCoord 2 122 | 0.5f, 0.5f, 0.0f, // Position 3 123 | 1.0f, 1.0f // TexCoord 3 124 | }; 125 | GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; 126 | 127 | // Set the viewport 128 | glViewport ( 0, 0, esContext->width, esContext->height ); 129 | 130 | // Clear the color buffer 131 | glClear ( GL_COLOR_BUFFER_BIT ); 132 | 133 | // Use the program object 134 | glUseProgram ( userData->programObject ); 135 | 136 | // Load the vertex position 137 | glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, 138 | GL_FALSE, 5 * sizeof(GLfloat), vVertices ); 139 | // Load the texture coordinate 140 | glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT, 141 | GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] ); 142 | 143 | glEnableVertexAttribArray ( userData->positionLoc ); 144 | glEnableVertexAttribArray ( userData->texCoordLoc ); 145 | 146 | // Bind the texture 147 | glActiveTexture ( GL_TEXTURE0 ); 148 | glBindTexture ( GL_TEXTURE_2D, userData->textureId ); 149 | 150 | // Set the sampler texture unit to 0 151 | glUniform1i ( userData->samplerLoc, 0 ); 152 | 153 | glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); 154 | 155 | } 156 | 157 | /// 158 | // Cleanup 159 | // 160 | void ShutDown ( ESContext *esContext ) 161 | { 162 | UserData *userData = esContext->userData; 163 | 164 | // Delete texture object 165 | glDeleteTextures ( 1, &userData->textureId ); 166 | 167 | // Delete program object 168 | glDeleteProgram ( userData->programObject ); 169 | 170 | free(esContext->userData); 171 | } 172 | 173 | int main ( int argc, char *argv[] ) 174 | { 175 | ESContext esContext; 176 | UserData userData; 177 | 178 | int width, height; 179 | GLubyte *image; 180 | 181 | image = esLoadTGA("jan.tga", &width, &height); 182 | if (image == NULL) { 183 | fprintf(stderr, "No such image\n"); 184 | exit(1); 185 | } 186 | printf("Width %d height %d\n", width, height); 187 | 188 | userData.image = image; 189 | userData.width = width; 190 | userData.height = height; 191 | 192 | 193 | esInitContext ( &esContext ); 194 | esContext.userData = &userData; 195 | 196 | esCreateWindow ( &esContext, "Simple Texture 2D", width, height, ES_WINDOW_RGB ); 197 | 198 | if ( !Init ( &esContext ) ) 199 | return 0; 200 | 201 | esRegisterDrawFunc ( &esContext, Draw ); 202 | 203 | esMainLoop ( &esContext ); 204 | 205 | ShutDown ( &esContext ); 206 | } 207 | -------------------------------------------------------------------------------- /OpenMAX/Audio/api-example.c: -------------------------------------------------------------------------------- 1 | /* 2 | * copyright (c) 2001 Fabrice Bellard 3 | * 4 | * This file is part of Libav. 5 | * 6 | * Libav is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * Libav is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with Libav; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | // From http://code.haskell.org/~thielema/audiovideo-example/cbits/ 22 | 23 | /** 24 | * @file 25 | * libavcodec API use example. 26 | * 27 | * @example libavcodec/api-example.c 28 | * Note that this library only handles codecs (mpeg, mpeg4, etc...), 29 | * not file formats (avi, vob, etc...). See library 'libavformat' for the 30 | * format handling 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | #ifdef HAVE_AV_CONFIG_H 38 | #undef HAVE_AV_CONFIG_H 39 | #endif 40 | 41 | #include "libavcodec/avcodec.h" 42 | #include 43 | #include "libavutil/mathematics.h" 44 | #include "libavutil/samplefmt.h" 45 | 46 | #define INBUF_SIZE 4096 47 | #define AUDIO_INBUF_SIZE 20480 48 | #define AUDIO_REFILL_THRESH 4096 49 | 50 | /* 51 | * Audio decoding. 52 | */ 53 | static void audio_decode_example(const char *outfilename, const char *filename) 54 | { 55 | AVCodec *codec; 56 | AVCodecContext *c = NULL; 57 | int len; 58 | FILE *f, *outfile; 59 | uint8_t inbuf[AUDIO_INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; 60 | AVPacket avpkt; 61 | AVFrame *decoded_frame = NULL; 62 | int num_streams = 0; 63 | int sample_size = 0; 64 | 65 | av_init_packet(&avpkt); 66 | 67 | printf("Audio decoding\n"); 68 | 69 | /* find the mpeg audio decoder */ 70 | codec = avcodec_find_decoder(CODEC_ID_MP3); 71 | if (!codec) { 72 | fprintf(stderr, "codec not found\n"); 73 | exit(1); 74 | } 75 | 76 | c = avcodec_alloc_context3(codec);; 77 | 78 | /* open it */ 79 | if (avcodec_open2(c, codec, NULL) < 0) { 80 | fprintf(stderr, "could not open codec\n"); 81 | exit(1); 82 | } 83 | 84 | f = fopen(filename, "rb"); 85 | if (!f) { 86 | fprintf(stderr, "could not open %s\n", filename); 87 | exit(1); 88 | } 89 | outfile = fopen(outfilename, "wb"); 90 | if (!outfile) { 91 | av_free(c); 92 | exit(1); 93 | } 94 | 95 | /* decode until eof */ 96 | avpkt.data = inbuf; 97 | avpkt.size = fread(inbuf, 1, AUDIO_INBUF_SIZE, f); 98 | 99 | while (avpkt.size > 0) { 100 | int got_frame = 0; 101 | 102 | if (!decoded_frame) { 103 | if (!(decoded_frame = avcodec_alloc_frame())) { 104 | fprintf(stderr, "out of memory\n"); 105 | exit(1); 106 | } 107 | } else 108 | avcodec_get_frame_defaults(decoded_frame); 109 | 110 | len = avcodec_decode_audio4(c, decoded_frame, &got_frame, &avpkt); 111 | if (len < 0) { 112 | fprintf(stderr, "Error while decoding\n"); 113 | exit(1); 114 | } 115 | if (got_frame) { 116 | printf("Decoded frame nb_samples %d, format %d\n", 117 | decoded_frame->nb_samples, 118 | decoded_frame->format); 119 | if (decoded_frame->data[1] != NULL) 120 | printf("Data[1] not null\n"); 121 | else 122 | printf("Data[1] is null\n"); 123 | /* if a frame has been decoded, output it */ 124 | int data_size = av_samples_get_buffer_size(NULL, c->channels, 125 | decoded_frame->nb_samples, 126 | c->sample_fmt, 1); 127 | // first time: count the number of planar streams 128 | if (num_streams == 0) { 129 | while (num_streams < AV_NUM_DATA_POINTERS && 130 | decoded_frame->data[num_streams] != NULL) 131 | num_streams++; 132 | } 133 | 134 | // first time: set sample_size from 0 to e.g 2 for 16-bit data 135 | if (sample_size == 0) { 136 | sample_size = 137 | data_size / (num_streams * decoded_frame->nb_samples); 138 | } 139 | 140 | int m, n; 141 | for (n = 0; n < decoded_frame->nb_samples; n++) { 142 | // interleave the samples from the planar streams 143 | for (m = 0; m < num_streams; m++) { 144 | fwrite(&decoded_frame->data[m][n*sample_size], 145 | 1, sample_size, outfile); 146 | } 147 | } 148 | } 149 | avpkt.size -= len; 150 | avpkt.data += len; 151 | if (avpkt.size < AUDIO_REFILL_THRESH) { 152 | /* Refill the input buffer, to avoid trying to decode 153 | * incomplete frames. Instead of this, one could also use 154 | * a parser, or use a proper container format through 155 | * libavformat. */ 156 | memmove(inbuf, avpkt.data, avpkt.size); 157 | avpkt.data = inbuf; 158 | len = fread(avpkt.data + avpkt.size, 1, 159 | AUDIO_INBUF_SIZE - avpkt.size, f); 160 | if (len > 0) 161 | avpkt.size += len; 162 | } 163 | } 164 | 165 | fclose(outfile); 166 | fclose(f); 167 | 168 | avcodec_close(c); 169 | av_free(c); 170 | av_free(decoded_frame); 171 | } 172 | 173 | int main(int argc, char **argv) 174 | { 175 | const char *filename = "BST.mp3"; 176 | AVFormatContext *pFormatCtx = NULL; 177 | 178 | if (argc == 2) { 179 | filename = argv[1]; 180 | } 181 | 182 | // Register all formats and codecs 183 | av_register_all(); 184 | if(avformat_open_input(&pFormatCtx, filename, NULL, NULL)!=0) { 185 | fprintf(stderr, "Can't get format\n"); 186 | return -1; // Couldn't open file 187 | } 188 | // Retrieve stream information 189 | if(avformat_find_stream_info(pFormatCtx, NULL)<0) 190 | return -1; // Couldn't find stream information 191 | av_dump_format(pFormatCtx, 0, filename, 0); 192 | printf("Num streams %d\n", pFormatCtx->nb_streams); 193 | printf("Bit rate %d\n", pFormatCtx->bit_rate); 194 | audio_decode_example("/tmp/test.sw", filename); 195 | 196 | return 0; 197 | } 198 | -------------------------------------------------------------------------------- /OpenMAX/Audio/il_render_audio.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #define AUDIO "enigma.s16" 12 | 13 | /* For the RPi name can be "hdmi" or "local" */ 14 | void setOutputDevice(OMX_HANDLETYPE handle, const char *name) { 15 | OMX_ERRORTYPE err; 16 | OMX_CONFIG_BRCMAUDIODESTINATIONTYPE arDest; 17 | 18 | if (name && strlen(name) < sizeof(arDest.sName)) { 19 | memset(&arDest, 0, sizeof(OMX_CONFIG_BRCMAUDIODESTINATIONTYPE)); 20 | arDest.nSize = sizeof(OMX_CONFIG_BRCMAUDIODESTINATIONTYPE); 21 | arDest.nVersion.nVersion = OMX_VERSION; 22 | 23 | strcpy((char *)arDest.sName, name); 24 | 25 | err = OMX_SetParameter(handle, OMX_IndexConfigBrcmAudioDestination, &arDest); 26 | if (err != OMX_ErrorNone) { 27 | fprintf(stderr, "Error on setting audio destination\n"); 28 | exit(1); 29 | } 30 | } 31 | } 32 | 33 | void setPCMMode(OMX_HANDLETYPE handle, int startPortNumber) { 34 | OMX_AUDIO_PARAM_PCMMODETYPE sPCMMode; 35 | OMX_ERRORTYPE err; 36 | 37 | memset(&sPCMMode, 0, sizeof(OMX_AUDIO_PARAM_PCMMODETYPE)); 38 | sPCMMode.nSize = sizeof(OMX_AUDIO_PARAM_PCMMODETYPE); 39 | sPCMMode.nVersion.nVersion = OMX_VERSION; 40 | 41 | sPCMMode.nPortIndex = startPortNumber; 42 | 43 | err = OMX_GetParameter(handle, OMX_IndexParamAudioPcm, &sPCMMode); 44 | printf("Sampling rate %d, channels %d\n", 45 | sPCMMode.nSamplingRate, 46 | sPCMMode.nChannels); 47 | 48 | sPCMMode.nSamplingRate = 44100; 49 | sPCMMode.nChannels = 2; 50 | 51 | err = OMX_SetParameter(handle, OMX_IndexParamAudioPcm, &sPCMMode); 52 | if(err != OMX_ErrorNone){ 53 | fprintf(stderr, "PCM mode unsupported\n"); 54 | return; 55 | } else { 56 | fprintf(stderr, "PCM mode supported\n"); 57 | fprintf(stderr, "PCM sampling rate %d\n", sPCMMode.nSamplingRate); 58 | fprintf(stderr, "PCM nChannels %d\n", sPCMMode.nChannels); 59 | } 60 | } 61 | 62 | void printState(OMX_HANDLETYPE handle) { 63 | //elided 64 | } 65 | 66 | char *err2str(int err) { 67 | return "elided"; 68 | } 69 | 70 | void eos_callback(void *userdata, COMPONENT_T *comp, OMX_U32 data) { 71 | fprintf(stderr, "Got eos event\n"); 72 | } 73 | 74 | void error_callback(void *userdata, COMPONENT_T *comp, OMX_U32 data) { 75 | fprintf(stderr, "OMX error %s\n", err2str(data)); 76 | } 77 | 78 | int get_file_size(char *fname) { 79 | struct stat st; 80 | 81 | if (stat(fname, &st) == -1) { 82 | perror("Stat'ing img file"); 83 | return -1; 84 | } 85 | return(st.st_size); 86 | } 87 | 88 | static void set_audio_render_input_format(COMPONENT_T *component) { 89 | // set input audio format 90 | printf("Setting audio render format\n"); 91 | OMX_AUDIO_PARAM_PORTFORMATTYPE audioPortFormat; 92 | //setHeader(&audioPortFormat, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); 93 | memset(&audioPortFormat, 0, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); 94 | audioPortFormat.nSize = sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE); 95 | audioPortFormat.nVersion.nVersion = OMX_VERSION; 96 | 97 | audioPortFormat.nPortIndex = 100; 98 | 99 | 100 | OMX_GetParameter(ilclient_get_handle(component), 101 | OMX_IndexParamAudioPortFormat, &audioPortFormat); 102 | 103 | audioPortFormat.eEncoding = OMX_AUDIO_CodingPCM; 104 | //audioPortFormat.eEncoding = OMX_AUDIO_CodingMP3; 105 | OMX_SetParameter(ilclient_get_handle(component), 106 | OMX_IndexParamAudioPortFormat, &audioPortFormat); 107 | 108 | setPCMMode(ilclient_get_handle(component), 100); 109 | 110 | } 111 | 112 | OMX_ERRORTYPE read_into_buffer_and_empty(FILE *fp, 113 | COMPONENT_T *component, 114 | OMX_BUFFERHEADERTYPE *buff_header, 115 | int *toread) { 116 | OMX_ERRORTYPE r; 117 | 118 | int buff_size = buff_header->nAllocLen; 119 | int nread = fread(buff_header->pBuffer, 1, buff_size, fp); 120 | 121 | printf("Read %d\n", nread); 122 | 123 | buff_header->nFilledLen = nread; 124 | *toread -= nread; 125 | if (*toread <= 0) { 126 | printf("Setting EOS on input\n"); 127 | buff_header->nFlags |= OMX_BUFFERFLAG_EOS; 128 | } 129 | r = OMX_EmptyThisBuffer(ilclient_get_handle(component), 130 | buff_header); 131 | if (r != OMX_ErrorNone) { 132 | fprintf(stderr, "Empty buffer error %s\n", 133 | err2str(r)); 134 | } 135 | return r; 136 | } 137 | 138 | 139 | int main(int argc, char** argv) { 140 | 141 | int i; 142 | char *componentName; 143 | int err; 144 | ILCLIENT_T *handle; 145 | COMPONENT_T *component; 146 | 147 | char *audio_file = AUDIO; 148 | if (argc == 2) { 149 | audio_file = argv[1]; 150 | } 151 | 152 | FILE *fp = fopen(audio_file, "r"); 153 | int toread = get_file_size(audio_file); 154 | 155 | OMX_BUFFERHEADERTYPE *buff_header; 156 | 157 | componentName = "audio_render"; 158 | 159 | 160 | bcm_host_init(); 161 | 162 | handle = ilclient_init(); 163 | if (handle == NULL) { 164 | fprintf(stderr, "IL client init failed\n"); 165 | exit(1); 166 | } 167 | 168 | if (OMX_Init() != OMX_ErrorNone) { 169 | ilclient_destroy(handle); 170 | fprintf(stderr, "OMX init failed\n"); 171 | exit(1); 172 | } 173 | 174 | ilclient_set_error_callback(handle, 175 | error_callback, 176 | NULL); 177 | ilclient_set_eos_callback(handle, 178 | eos_callback, 179 | NULL); 180 | 181 | 182 | err = ilclient_create_component(handle, 183 | &component, 184 | componentName, 185 | ILCLIENT_DISABLE_ALL_PORTS 186 | | 187 | ILCLIENT_ENABLE_INPUT_BUFFERS 188 | ); 189 | if (err == -1) { 190 | fprintf(stderr, "Component create failed\n"); 191 | exit(1); 192 | } 193 | printState(ilclient_get_handle(component)); 194 | 195 | err = ilclient_change_component_state(component, 196 | OMX_StateIdle); 197 | if (err < 0) { 198 | fprintf(stderr, "Couldn't change state to Idle\n"); 199 | exit(1); 200 | } 201 | printState(ilclient_get_handle(component)); 202 | 203 | // must be before we enable buffers 204 | set_audio_render_input_format(component); 205 | 206 | setOutputDevice(ilclient_get_handle(component), "local"); 207 | 208 | // input port 209 | ilclient_enable_port_buffers(component, 100, 210 | NULL, NULL, NULL); 211 | ilclient_enable_port(component, 100); 212 | 213 | 214 | 215 | 216 | err = ilclient_change_component_state(component, 217 | OMX_StateExecuting); 218 | if (err < 0) { 219 | fprintf(stderr, "Couldn't change state to Executing\n"); 220 | exit(1); 221 | } 222 | printState(ilclient_get_handle(component)); 223 | 224 | // now work through the file 225 | while (toread > 0) { 226 | OMX_ERRORTYPE r; 227 | 228 | // do we have an input buffer we can fill and empty? 229 | buff_header = 230 | ilclient_get_input_buffer(component, 231 | 100, 232 | 1 /* block */); 233 | if (buff_header != NULL) { 234 | read_into_buffer_and_empty(fp, 235 | component, 236 | buff_header, 237 | &toread); 238 | } 239 | } 240 | 241 | exit(0); 242 | } 243 | -------------------------------------------------------------------------------- /OpenMAX/Audio/il_test_audio_encodings.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #define AUDIO "enigma.s16" 12 | 13 | #define OUT "out" 14 | FILE *outfp; 15 | 16 | void printState(OMX_HANDLETYPE handle) { 17 | // elided 18 | } 19 | 20 | char *err2str(int err) { 21 | return "elided"; 22 | } 23 | 24 | void eos_callback(void *userdata, COMPONENT_T *comp, OMX_U32 data) { 25 | fprintf(stderr, "Got eos event\n"); 26 | } 27 | 28 | void error_callback(void *userdata, COMPONENT_T *comp, OMX_U32 data) { 29 | //fprintf(stderr, "OMX error %s\n", err2str(data)); 30 | } 31 | 32 | int get_file_size(char *fname) { 33 | struct stat st; 34 | 35 | if (stat(fname, &st) == -1) { 36 | perror("Stat'ing img file"); 37 | return -1; 38 | } 39 | return(st.st_size); 40 | } 41 | 42 | static void set_audio_decoder_input_format(COMPONENT_T *component, 43 | int port, int format) { 44 | // set input audio format 45 | //printf("Setting audio decoder format\n"); 46 | OMX_AUDIO_PARAM_PORTFORMATTYPE audioPortFormat; 47 | //setHeader(&audioPortFormat, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); 48 | memset(&audioPortFormat, 0, sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE)); 49 | audioPortFormat.nSize = sizeof(OMX_AUDIO_PARAM_PORTFORMATTYPE); 50 | audioPortFormat.nVersion.nVersion = OMX_VERSION; 51 | 52 | audioPortFormat.nPortIndex = port; 53 | //audioPortFormat.eEncoding = OMX_AUDIO_CodingPCM; 54 | audioPortFormat.eEncoding = format; 55 | OMX_SetParameter(ilclient_get_handle(component), 56 | OMX_IndexParamAudioPortFormat, &audioPortFormat); 57 | //printf("Format set ok to %d\n", format); 58 | } 59 | 60 | char *format2str(OMX_AUDIO_CODINGTYPE format) { 61 | switch(format) { 62 | case OMX_AUDIO_CodingUnused: return "OMX_AUDIO_CodingUnused"; 63 | case OMX_AUDIO_CodingAutoDetect: return "OMX_AUDIO_CodingAutoDetect"; 64 | case OMX_AUDIO_CodingPCM: return "OMX_AUDIO_CodingPCM"; 65 | case OMX_AUDIO_CodingADPCM: return "OMX_AUDIO_CodingADPCM"; 66 | case OMX_AUDIO_CodingAMR: return "OMX_AUDIO_CodingAMR"; 67 | case OMX_AUDIO_CodingGSMFR: return "OMX_AUDIO_CodingGSMFR"; 68 | case OMX_AUDIO_CodingGSMEFR: return "OMX_AUDIO_CodingGSMEFR"; 69 | case OMX_AUDIO_CodingGSMHR: return "OMX_AUDIO_CodingGSMHR"; 70 | case OMX_AUDIO_CodingPDCFR: return "OMX_AUDIO_CodingPDCFR"; 71 | case OMX_AUDIO_CodingPDCEFR: return "OMX_AUDIO_CodingPDCEFR"; 72 | case OMX_AUDIO_CodingPDCHR: return "OMX_AUDIO_CodingPDCHR"; 73 | case OMX_AUDIO_CodingTDMAFR: return "OMX_AUDIO_CodingTDMAFR"; 74 | case OMX_AUDIO_CodingTDMAEFR: return "OMX_AUDIO_CodingTDMAEFR"; 75 | case OMX_AUDIO_CodingQCELP8: return "OMX_AUDIO_CodingQCELP8"; 76 | case OMX_AUDIO_CodingQCELP13: return "OMX_AUDIO_CodingQCELP13"; 77 | case OMX_AUDIO_CodingEVRC: return "OMX_AUDIO_CodingEVRC"; 78 | case OMX_AUDIO_CodingSMV: return "OMX_AUDIO_CodingSMV"; 79 | case OMX_AUDIO_CodingG711: return "OMX_AUDIO_CodingG711"; 80 | case OMX_AUDIO_CodingG723: return "OMX_AUDIO_CodingG723"; 81 | case OMX_AUDIO_CodingG726: return "OMX_AUDIO_CodingG726"; 82 | case OMX_AUDIO_CodingG729: return "OMX_AUDIO_CodingG729"; 83 | case OMX_AUDIO_CodingAAC: return "OMX_AUDIO_CodingAAC"; 84 | case OMX_AUDIO_CodingMP3: return "OMX_AUDIO_CodingMP3"; 85 | case OMX_AUDIO_CodingSBC: return "OMX_AUDIO_CodingSBC"; 86 | case OMX_AUDIO_CodingVORBIS: return "OMX_AUDIO_CodingVORBIS"; 87 | case OMX_AUDIO_CodingWMA: return "OMX_AUDIO_CodingWMA"; 88 | case OMX_AUDIO_CodingRA: return "OMX_AUDIO_CodingRA"; 89 | case OMX_AUDIO_CodingMIDI: return "OMX_AUDIO_CodingMIDI"; 90 | case OMX_AUDIO_CodingFLAC: return "OMX_AUDIO_CodingFLAC"; 91 | case OMX_AUDIO_CodingDDP: return "OMX_AUDIO_CodingDDP"; 92 | case OMX_AUDIO_CodingDTS: return "OMX_AUDIO_CodingDTS"; 93 | case OMX_AUDIO_CodingWMAPRO: return "OMX_AUDIO_CodingWMAPRO"; 94 | case OMX_AUDIO_CodingATRAC3: return "OMX_AUDIO_CodingATRAC3"; 95 | case OMX_AUDIO_CodingATRACX: return "OMX_AUDIO_CodingATRACX"; 96 | case OMX_AUDIO_CodingATRACAAL: return "OMX_AUDIO_CodingATRACAAL"; 97 | default: return "Unknown format"; 98 | } 99 | } 100 | 101 | void test_audio_port_formats(COMPONENT_T *component, int port) { 102 | int n = 2; 103 | while (n <= OMX_AUDIO_CodingMIDI) { 104 | set_audio_decoder_input_format(component, port, n); 105 | 106 | 107 | // input port 108 | if (ilclient_enable_port_buffers(component, port, 109 | NULL, NULL, NULL) < 0) { 110 | printf(" Unsupported encoding is %s\n", 111 | format2str(n)); 112 | } else { 113 | printf(" Supported encoding is %s\n", 114 | format2str(n)); 115 | ilclient_disable_port_buffers(component, port, 116 | NULL, NULL, NULL); 117 | } 118 | n++; 119 | } 120 | n = OMX_AUDIO_CodingFLAC; 121 | while (n <= OMX_AUDIO_CodingATRACAAL) { 122 | set_audio_decoder_input_format(component, port, n); 123 | 124 | 125 | // input port 126 | if (ilclient_enable_port_buffers(component, port, 127 | NULL, NULL, NULL) < 0) { 128 | printf(" Unsupported encoding is %s\n", 129 | format2str(n)); 130 | } else { 131 | printf(" Supported encoding is %s\n", 132 | format2str(n)); 133 | ilclient_disable_port_buffers(component, port, 134 | NULL, NULL, NULL); 135 | } 136 | n++; 137 | } 138 | } 139 | 140 | void test_all_audio_ports(COMPONENT_T *component) { 141 | OMX_PORT_PARAM_TYPE param; 142 | OMX_PARAM_PORTDEFINITIONTYPE sPortDef; 143 | OMX_ERRORTYPE err; 144 | OMX_HANDLETYPE handle = ilclient_get_handle(component); 145 | 146 | int startPortNumber; 147 | int nPorts; 148 | int n; 149 | 150 | //setHeader(¶m, sizeof(OMX_PORT_PARAM_TYPE)); 151 | memset(¶m, 0, sizeof(OMX_PORT_PARAM_TYPE)); 152 | param.nSize = sizeof(OMX_PORT_PARAM_TYPE); 153 | param.nVersion.nVersion = OMX_VERSION; 154 | 155 | err = OMX_GetParameter(handle, OMX_IndexParamAudioInit, ¶m); 156 | if(err != OMX_ErrorNone){ 157 | fprintf(stderr, "Error in getting audio OMX_PORT_PARAM_TYPE parameter\n"); 158 | return; 159 | } 160 | printf("Audio ports:\n"); 161 | 162 | startPortNumber = param.nStartPortNumber; 163 | nPorts = param.nPorts; 164 | if (nPorts == 0) { 165 | printf("No ports of this type\n"); 166 | return; 167 | } 168 | 169 | printf("Ports start on %d\n", startPortNumber); 170 | printf("There are %d open ports\n", nPorts); 171 | 172 | 173 | for (n = 0; n < nPorts; n++) { 174 | memset(&sPortDef, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); 175 | sPortDef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); 176 | sPortDef.nVersion.nVersion = OMX_VERSION; 177 | 178 | 179 | sPortDef.nPortIndex = startPortNumber + n; 180 | err = OMX_GetParameter(handle, OMX_IndexParamPortDefinition, &sPortDef); 181 | if(err != OMX_ErrorNone){ 182 | fprintf(stderr, "Error in getting OMX_PORT_DEFINITION_TYPE parameter\n"); 183 | exit(1); 184 | } 185 | printf("Port %d has %d buffers of size %d\n", 186 | sPortDef.nPortIndex, 187 | sPortDef.nBufferCountActual, 188 | sPortDef.nBufferSize); 189 | printf("Direction is %s\n", 190 | (sPortDef.eDir == OMX_DirInput ? "input" : "output")); 191 | test_audio_port_formats(component, sPortDef.nPortIndex); 192 | } 193 | } 194 | 195 | int main(int argc, char** argv) { 196 | char *componentName; 197 | int err; 198 | ILCLIENT_T *handle; 199 | COMPONENT_T *component; 200 | 201 | componentName = "audio_decode"; 202 | if (argc == 2) { 203 | componentName = argv[1]; 204 | } 205 | 206 | bcm_host_init(); 207 | 208 | handle = ilclient_init(); 209 | if (handle == NULL) { 210 | fprintf(stderr, "IL client init failed\n"); 211 | exit(1); 212 | } 213 | 214 | if (OMX_Init() != OMX_ErrorNone) { 215 | ilclient_destroy(handle); 216 | fprintf(stderr, "OMX init failed\n"); 217 | exit(1); 218 | } 219 | 220 | ilclient_set_error_callback(handle, 221 | error_callback, 222 | NULL); 223 | ilclient_set_eos_callback(handle, 224 | eos_callback, 225 | NULL); 226 | 227 | 228 | err = ilclient_create_component(handle, 229 | &component, 230 | componentName, 231 | ILCLIENT_DISABLE_ALL_PORTS 232 | | 233 | ILCLIENT_ENABLE_INPUT_BUFFERS 234 | | 235 | ILCLIENT_ENABLE_OUTPUT_BUFFERS 236 | ); 237 | if (err == -1) { 238 | fprintf(stderr, "Component create failed\n"); 239 | exit(1); 240 | } 241 | printState(ilclient_get_handle(component)); 242 | 243 | err = ilclient_change_component_state(component, 244 | OMX_StateIdle); 245 | if (err < 0) { 246 | fprintf(stderr, "Couldn't change state to Idle\n"); 247 | exit(1); 248 | } 249 | printState(ilclient_get_handle(component)); 250 | 251 | test_all_audio_ports(component); 252 | 253 | exit(0); 254 | } 255 | -------------------------------------------------------------------------------- /OpenMAX/Buffers/il_buffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | void printState(OMX_HANDLETYPE handle) { 11 | OMX_STATETYPE state; 12 | OMX_ERRORTYPE err; 13 | 14 | err = OMX_GetState(handle, &state); 15 | if (err != OMX_ErrorNone) { 16 | fprintf(stderr, "Error on getting state\n"); 17 | exit(1); 18 | } 19 | switch (state) { 20 | case OMX_StateLoaded: printf("StateLoaded\n"); break; 21 | case OMX_StateIdle: printf("StateIdle\n"); break; 22 | case OMX_StateExecuting: printf("StateExecuting\n"); break; 23 | case OMX_StatePause: printf("StatePause\n"); break; 24 | case OMX_StateWaitForResources: printf("StateWait\n"); break; 25 | case OMX_StateInvalid: printf("StateInvalid\n"); break; 26 | default: printf("State unknown\n"); break; 27 | } 28 | } 29 | 30 | char *err2str(int err) { 31 | switch (err) { 32 | case OMX_ErrorInsufficientResources: return "OMX_ErrorInsufficientResources"; 33 | case OMX_ErrorUndefined: return "OMX_ErrorUndefined"; 34 | case OMX_ErrorInvalidComponentName: return "OMX_ErrorInvalidComponentName"; 35 | case OMX_ErrorComponentNotFound: return "OMX_ErrorComponentNotFound"; 36 | case OMX_ErrorInvalidComponent: return "OMX_ErrorInvalidComponent"; 37 | case OMX_ErrorBadParameter: return "OMX_ErrorBadParameter"; 38 | case OMX_ErrorNotImplemented: return "OMX_ErrorNotImplemented"; 39 | case OMX_ErrorUnderflow: return "OMX_ErrorUnderflow"; 40 | case OMX_ErrorOverflow: return "OMX_ErrorOverflow"; 41 | case OMX_ErrorHardware: return "OMX_ErrorHardware"; 42 | case OMX_ErrorInvalidState: return "OMX_ErrorInvalidState"; 43 | case OMX_ErrorStreamCorrupt: return "OMX_ErrorStreamCorrupt"; 44 | case OMX_ErrorPortsNotCompatible: return "OMX_ErrorPortsNotCompatible"; 45 | case OMX_ErrorResourcesLost: return "OMX_ErrorResourcesLost"; 46 | case OMX_ErrorNoMore: return "OMX_ErrorNoMore"; 47 | case OMX_ErrorVersionMismatch: return "OMX_ErrorVersionMismatch"; 48 | case OMX_ErrorNotReady: return "OMX_ErrorNotReady"; 49 | case OMX_ErrorTimeout: return "OMX_ErrorTimeout"; 50 | case OMX_ErrorSameState: return "OMX_ErrorSameState"; 51 | case OMX_ErrorResourcesPreempted: return "OMX_ErrorResourcesPreempted"; 52 | case OMX_ErrorPortUnresponsiveDuringAllocation: return "OMX_ErrorPortUnresponsiveDuringAllocation"; 53 | case OMX_ErrorPortUnresponsiveDuringDeallocation: return "OMX_ErrorPortUnresponsiveDuringDeallocation"; 54 | case OMX_ErrorPortUnresponsiveDuringStop: return "OMX_ErrorPortUnresponsiveDuringStop"; 55 | case OMX_ErrorIncorrectStateTransition: return "OMX_ErrorIncorrectStateTransition"; 56 | case OMX_ErrorIncorrectStateOperation: return "OMX_ErrorIncorrectStateOperation"; 57 | case OMX_ErrorUnsupportedSetting: return "OMX_ErrorUnsupportedSetting"; 58 | case OMX_ErrorUnsupportedIndex: return "OMX_ErrorUnsupportedIndex"; 59 | case OMX_ErrorBadPortIndex: return "OMX_ErrorBadPortIndex"; 60 | case OMX_ErrorPortUnpopulated: return "OMX_ErrorPortUnpopulated"; 61 | case OMX_ErrorComponentSuspended: return "OMX_ErrorComponentSuspended"; 62 | case OMX_ErrorDynamicResourcesUnavailable: return "OMX_ErrorDynamicResourcesUnavailable"; 63 | case OMX_ErrorMbErrorsInFrame: return "OMX_ErrorMbErrorsInFrame"; 64 | case OMX_ErrorFormatNotDetected: return "OMX_ErrorFormatNotDetected"; 65 | case OMX_ErrorContentPipeOpenFailed: return "OMX_ErrorContentPipeOpenFailed"; 66 | case OMX_ErrorContentPipeCreationFailed: return "OMX_ErrorContentPipeCreationFailed"; 67 | case OMX_ErrorSeperateTablesUsed: return "OMX_ErrorSeperateTablesUsed"; 68 | case OMX_ErrorTunnelingUnsupported: return "OMX_ErrorTunnelingUnsupported"; 69 | default: return "unknown error"; 70 | } 71 | } 72 | 73 | void error_callback(void *userdata, COMPONENT_T *comp, OMX_U32 data) { 74 | fprintf(stderr, "OMX error %s\n", err2str(data)); 75 | } 76 | 77 | int main(int argc, char** argv) { 78 | 79 | int i; 80 | char *componentName; 81 | int err; 82 | ILCLIENT_T *handle; 83 | COMPONENT_T *component; 84 | 85 | componentName = "image_encode"; 86 | 87 | bcm_host_init(); 88 | 89 | handle = ilclient_init(); 90 | if (handle == NULL) { 91 | fprintf(stderr, "IL client init failed\n"); 92 | exit(1); 93 | } 94 | 95 | if (OMX_Init() != OMX_ErrorNone) { 96 | ilclient_destroy(handle); 97 | fprintf(stderr, "OMX init failed\n"); 98 | exit(1); 99 | } 100 | 101 | ilclient_set_error_callback(handle, 102 | error_callback, 103 | NULL); 104 | 105 | err = ilclient_create_component(handle, 106 | &component, 107 | componentName, 108 | ILCLIENT_DISABLE_ALL_PORTS 109 | | 110 | ILCLIENT_ENABLE_INPUT_BUFFERS 111 | | 112 | ILCLIENT_ENABLE_OUTPUT_BUFFERS 113 | ); 114 | if (err == -1) { 115 | fprintf(stderr, "Component create failed\n"); 116 | exit(1); 117 | } 118 | printState(ilclient_get_handle(component)); 119 | 120 | err = ilclient_change_component_state(component, 121 | OMX_StateIdle); 122 | if (err < 0) { 123 | fprintf(stderr, "Couldn't change state to Idle\n"); 124 | exit(1); 125 | } 126 | printState(ilclient_get_handle(component)); 127 | 128 | // input port 129 | ilclient_enable_port_buffers(component, 340, 130 | NULL, NULL, NULL); 131 | ilclient_enable_port(component, 340); 132 | // the input port is enabled and has input buffers allocated 133 | 134 | // output port 135 | ilclient_enable_port_buffers(component, 341, 136 | NULL, NULL, NULL); 137 | ilclient_enable_port(component, 341); 138 | // the output port is enabled and has output buffers allocated 139 | 140 | err = ilclient_change_component_state(component, 141 | OMX_StateExecuting); 142 | if (err < 0) { 143 | fprintf(stderr, "Couldn't change state to Executing\n"); 144 | exit(1); 145 | } 146 | printState(ilclient_get_handle(component)); 147 | 148 | exit(0); 149 | } 150 | -------------------------------------------------------------------------------- /OpenMAX/Buffers/il_decode_image.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #define IMG "cimg0135.jpg" 12 | //#define IMG "hype.jpg" 13 | 14 | void printState(OMX_HANDLETYPE handle) { 15 | OMX_STATETYPE state; 16 | OMX_ERRORTYPE err; 17 | 18 | err = OMX_GetState(handle, &state); 19 | if (err != OMX_ErrorNone) { 20 | fprintf(stderr, "Error on getting state\n"); 21 | exit(1); 22 | } 23 | switch (state) { 24 | case OMX_StateLoaded: printf("StateLoaded\n"); break; 25 | case OMX_StateIdle: printf("StateIdle\n"); break; 26 | case OMX_StateExecuting: printf("StateExecuting\n"); break; 27 | case OMX_StatePause: printf("StatePause\n"); break; 28 | case OMX_StateWaitForResources: printf("StateWait\n"); break; 29 | case OMX_StateInvalid: printf("StateInvalid\n"); break; 30 | default: printf("State unknown\n"); break; 31 | } 32 | } 33 | 34 | char *err2str(int err) { 35 | return "error deleted"; 36 | } 37 | 38 | void eos_callback(void *userdata, COMPONENT_T *comp, OMX_U32 data) { 39 | fprintf(stderr, "Got eos event\n"); 40 | } 41 | 42 | void error_callback(void *userdata, COMPONENT_T *comp, OMX_U32 data) { 43 | fprintf(stderr, "OMX error %s\n", err2str(data)); 44 | } 45 | 46 | int get_file_size(char *fname) { 47 | struct stat st; 48 | 49 | if (stat(fname, &st) == -1) { 50 | perror("Stat'ing img file"); 51 | return -1; 52 | } 53 | return(st.st_size); 54 | } 55 | 56 | static void set_image_decoder_input_format(COMPONENT_T *component) { 57 | // set input image format 58 | OMX_IMAGE_PARAM_PORTFORMATTYPE imagePortFormat; 59 | 60 | memset(&imagePortFormat, 0, sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE)); 61 | imagePortFormat.nSize = sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE); 62 | imagePortFormat.nVersion.nVersion = OMX_VERSION; 63 | 64 | imagePortFormat.nPortIndex = 320; 65 | imagePortFormat.eCompressionFormat = OMX_IMAGE_CodingJPEG; 66 | OMX_SetParameter(ilclient_get_handle(component), 67 | OMX_IndexParamImagePortFormat, &imagePortFormat); 68 | 69 | } 70 | 71 | OMX_ERRORTYPE read_into_buffer_and_empty(FILE *fp, 72 | COMPONENT_T *component, 73 | OMX_BUFFERHEADERTYPE *buff_header, 74 | int *toread) { 75 | OMX_ERRORTYPE r; 76 | 77 | int buff_size = buff_header->nAllocLen; 78 | int nread = fread(buff_header->pBuffer, 1, buff_size, fp); 79 | 80 | printf("Read %d\n", nread); 81 | 82 | buff_header->nFilledLen = nread; 83 | *toread -= nread; 84 | if (*toread <= 0) { 85 | printf("Setting EOS on input\n"); 86 | buff_header->nFlags |= OMX_BUFFERFLAG_EOS; 87 | } 88 | r = OMX_EmptyThisBuffer(ilclient_get_handle(component), 89 | buff_header); 90 | if (r != OMX_ErrorNone) { 91 | fprintf(stderr, "Empty buffer error %s\n", 92 | err2str(r)); 93 | } 94 | return r; 95 | } 96 | 97 | OMX_ERRORTYPE save_info_from_filled_buffer(COMPONENT_T *component, 98 | OMX_BUFFERHEADERTYPE * buff_header) { 99 | OMX_ERRORTYPE r; 100 | 101 | printf("Got a filled buffer with %d, allocated %d\n", 102 | buff_header->nFilledLen, 103 | buff_header->nAllocLen); 104 | if (buff_header->nFlags & OMX_BUFFERFLAG_EOS) { 105 | printf("Got EOS on output\n"); 106 | exit(0); 107 | } 108 | 109 | // do something here, like save the data - do nothing this time 110 | 111 | // and then refill it 112 | r = OMX_FillThisBuffer(ilclient_get_handle(component), 113 | buff_header); 114 | if (r != OMX_ErrorNone) { 115 | fprintf(stderr, "Fill buffer error %s\n", 116 | err2str(r)); 117 | } 118 | return r; 119 | } 120 | 121 | int main(int argc, char** argv) { 122 | 123 | int i; 124 | char *componentName; 125 | int err; 126 | ILCLIENT_T *handle; 127 | COMPONENT_T *component; 128 | FILE *fp = fopen(IMG, "r"); 129 | int toread = get_file_size(IMG); 130 | OMX_BUFFERHEADERTYPE *buff_header; 131 | 132 | componentName = "image_decode"; 133 | 134 | 135 | bcm_host_init(); 136 | 137 | handle = ilclient_init(); 138 | if (handle == NULL) { 139 | fprintf(stderr, "IL client init failed\n"); 140 | exit(1); 141 | } 142 | 143 | if (OMX_Init() != OMX_ErrorNone) { 144 | ilclient_destroy(handle); 145 | fprintf(stderr, "OMX init failed\n"); 146 | exit(1); 147 | } 148 | 149 | ilclient_set_error_callback(handle, 150 | error_callback, 151 | NULL); 152 | ilclient_set_eos_callback(handle, 153 | eos_callback, 154 | NULL); 155 | 156 | 157 | err = ilclient_create_component(handle, 158 | &component, 159 | componentName, 160 | ILCLIENT_DISABLE_ALL_PORTS 161 | | 162 | ILCLIENT_ENABLE_INPUT_BUFFERS 163 | | 164 | ILCLIENT_ENABLE_OUTPUT_BUFFERS 165 | ); 166 | if (err == -1) { 167 | fprintf(stderr, "Component create failed\n"); 168 | exit(1); 169 | } 170 | printState(ilclient_get_handle(component)); 171 | 172 | err = ilclient_change_component_state(component, 173 | OMX_StateIdle); 174 | if (err < 0) { 175 | fprintf(stderr, "Couldn't change state to Idle\n"); 176 | exit(1); 177 | } 178 | printState(ilclient_get_handle(component)); 179 | 180 | // must be before we enable buffers 181 | set_image_decoder_input_format(component); 182 | 183 | // input port 184 | ilclient_enable_port_buffers(component, 320, 185 | NULL, NULL, NULL); 186 | ilclient_enable_port(component, 320); 187 | 188 | 189 | 190 | 191 | err = ilclient_change_component_state(component, 192 | OMX_StateExecuting); 193 | if (err < 0) { 194 | fprintf(stderr, "Couldn't change state to Executing\n"); 195 | exit(1); 196 | } 197 | printState(ilclient_get_handle(component)); 198 | 199 | 200 | // Read the first block so that the component can get 201 | // the dimensions of the image and call port settings 202 | // changed on the output port to configure it 203 | buff_header = 204 | ilclient_get_input_buffer(component, 205 | 320, 206 | 1 /* block */); 207 | if (buff_header != NULL) { 208 | read_into_buffer_and_empty(fp, 209 | component, 210 | buff_header, 211 | &toread); 212 | 213 | // If all the file has been read in, then 214 | // we have to re-read this first block. 215 | // Broadcom bug? 216 | if (toread <= 0) { 217 | printf("Rewinding\n"); 218 | // wind back to start and repeat 219 | fp = freopen(IMG, "r", fp); 220 | toread = get_file_size(IMG); 221 | } 222 | } 223 | 224 | // wait for first input block to set params for output port 225 | ilclient_wait_for_event(component, 226 | OMX_EventPortSettingsChanged, 227 | 321, 0, 0, 1, 228 | ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 229 | 10000); 230 | 231 | // now enable output port since port params have been set 232 | ilclient_enable_port_buffers(component, 321, 233 | NULL, NULL, NULL); 234 | ilclient_enable_port(component, 321); 235 | 236 | // now work through the file 237 | while (toread > 0) { 238 | OMX_ERRORTYPE r; 239 | 240 | // do we have an input buffer we can fill and empty? 241 | buff_header = 242 | ilclient_get_input_buffer(component, 243 | 320, 244 | 1 /* block */); 245 | if (buff_header != NULL) { 246 | read_into_buffer_and_empty(fp, 247 | component, 248 | buff_header, 249 | &toread); 250 | } 251 | 252 | // do we have an output buffer that has been filled? 253 | buff_header = 254 | ilclient_get_output_buffer(component, 255 | 321, 256 | 0 /* no block */); 257 | if (buff_header != NULL) { 258 | save_info_from_filled_buffer(component, 259 | buff_header); 260 | } 261 | } 262 | 263 | while (1) { 264 | printf("Getting last output buffers\n"); 265 | buff_header = 266 | ilclient_get_output_buffer(component, 267 | 321, 268 | 1 /* block */); 269 | if (buff_header != NULL) { 270 | save_info_from_filled_buffer(component, 271 | buff_header); 272 | } 273 | } 274 | exit(0); 275 | } 276 | -------------------------------------------------------------------------------- /OpenMAX/Components/listcomponents.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | OMX_ERRORTYPE err; 10 | 11 | void listroles(char *name) { 12 | int n; 13 | OMX_U32 numRoles; 14 | OMX_U8 *roles[32]; 15 | 16 | /* get the number of roles by passing in a NULL roles param */ 17 | err = OMX_GetRolesOfComponent(name, &numRoles, NULL); 18 | if (err != OMX_ErrorNone) { 19 | fprintf(stderr, "Getting roles failed\n", 0); 20 | exit(1); 21 | } 22 | printf(" Num roles is %d\n", numRoles); 23 | if (numRoles > 32) { 24 | printf("Too many roles to list\n"); 25 | return; 26 | } 27 | 28 | /* now get the roles */ 29 | for (n = 0; n < numRoles; n++) { 30 | roles[n] = malloc(OMX_MAX_STRINGNAME_SIZE); 31 | } 32 | err = OMX_GetRolesOfComponent(name, &numRoles, roles); 33 | if (err != OMX_ErrorNone) { 34 | fprintf(stderr, "Getting roles failed\n", 0); 35 | exit(1); 36 | } 37 | for (n = 0; n < numRoles; n++) { 38 | printf(" role: %s\n", roles[n]); 39 | free(roles[n]); 40 | } 41 | 42 | /* This is in version 1.2 43 | for (i = 0; OMX_ErrorNoMore != err; i++) { 44 | err = OMX_RoleOfComponentEnum(role, name, i); 45 | if (OMX_ErrorNone == err) { 46 | printf(" Role of omponent is %s\n", role); 47 | } 48 | } 49 | */ 50 | } 51 | 52 | int main(int argc, char** argv) { 53 | 54 | int i; 55 | unsigned char name[OMX_MAX_STRINGNAME_SIZE]; 56 | 57 | bcm_host_init(); 58 | 59 | err = OMX_Init(); 60 | if (err != OMX_ErrorNone) { 61 | fprintf(stderr, "OMX_Init() failed\n", 0); 62 | exit(1); 63 | } 64 | 65 | err = OMX_ErrorNone; 66 | for (i = 0; OMX_ErrorNoMore != err; i++) { 67 | err = OMX_ComponentNameEnum(name, OMX_MAX_STRINGNAME_SIZE, i); 68 | if (OMX_ErrorNone == err) { 69 | printf("Component is %s\n", name); 70 | listroles(name); 71 | } 72 | } 73 | printf("No more components\n"); 74 | 75 | exit(0); 76 | } 77 | -------------------------------------------------------------------------------- /OpenMAX/Components/portinfo.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | // OMX_ERRORTYPE err; 11 | 12 | OMX_ERRORTYPE get_port_info(OMX_HANDLETYPE handle, 13 | OMX_PARAM_PORTDEFINITIONTYPE *portdef) { 14 | return OMX_GetParameter(handle, 15 | OMX_IndexParamPortDefinition, 16 | portdef); 17 | 18 | } 19 | 20 | void print_port_info(OMX_PARAM_PORTDEFINITIONTYPE *portdef) { 21 | char *domain; 22 | 23 | printf("Port %d\n", portdef->nPortIndex); 24 | if (portdef->eDir == OMX_DirInput) { 25 | printf(" is input port\n"); 26 | } else { 27 | printf(" is output port\n"); 28 | } 29 | 30 | switch (portdef->eDomain) { 31 | case OMX_PortDomainAudio: domain = "Audio"; break; 32 | case OMX_PortDomainVideo: domain = "Video"; break; 33 | case OMX_PortDomainImage: domain = "Image"; break; 34 | case OMX_PortDomainOther: domain = "Other"; break; 35 | } 36 | printf(" Domain is %s\n", domain); 37 | 38 | printf(" Buffer count %d\n", portdef->nBufferCountActual); 39 | printf(" Buffer minimum count %d\n", portdef->nBufferCountMin); 40 | printf(" Buffer size %d bytes\n", portdef->nBufferSize); 41 | } 42 | 43 | OMX_CALLBACKTYPE callbacks = { .EventHandler = NULL, 44 | .EmptyBufferDone = NULL, 45 | .FillBufferDone = NULL 46 | }; 47 | 48 | int main(int argc, char** argv) { 49 | 50 | int i; 51 | char componentName[128]; // min space required see /opt/vc/include/IL/OMX_Core.h 52 | // thanks to Peter Maersk-Moller 53 | OMX_ERRORTYPE err; 54 | OMX_HANDLETYPE handle; 55 | OMX_PARAM_PORTDEFINITIONTYPE portdef; 56 | OMX_VERSIONTYPE specVersion, compVersion; 57 | OMX_UUIDTYPE uid; 58 | int portindex; 59 | 60 | if (argc < 3) { 61 | fprintf(stderr, "Usage: %s component-name port-index\n", argv[0]); 62 | exit(1); 63 | } 64 | strncpy(componentName, argv[1], 128); 65 | portindex = atoi(argv[2]); 66 | 67 | bcm_host_init(); 68 | 69 | err = OMX_Init(); 70 | if(err != OMX_ErrorNone) { 71 | fprintf(stderr, "OMX_Init() failed\n", 0); 72 | exit(1); 73 | } 74 | /** Ask the core for a handle to the component 75 | */ 76 | err = OMX_GetHandle(&handle, componentName, 77 | // the next two fields are discussed later 78 | NULL, &callbacks); 79 | if (err != OMX_ErrorNone) { 80 | fprintf(stderr, "OMX_GetHandle failed\n", 0); 81 | exit(1); 82 | } 83 | 84 | // Get some version info 85 | err = OMX_GetComponentVersion(handle, componentName, 86 | &compVersion, &specVersion, 87 | &uid); 88 | if (err != OMX_ErrorNone) { 89 | fprintf(stderr, "OMX_GetComponentVersion failed\n", 0); 90 | exit(1); 91 | } 92 | printf("Component name: %s version %d.%d, Spec version %d.%d\n", 93 | componentName, compVersion.s.nVersionMajor, 94 | compVersion.s.nVersionMinor, 95 | specVersion.s.nVersionMajor, 96 | specVersion.s.nVersionMinor); 97 | 98 | memset(&portdef, 0, sizeof(OMX_PARAM_PORTDEFINITIONTYPE)); 99 | portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); 100 | portdef.nVersion.nVersion = OMX_VERSION; 101 | portdef.nPortIndex = portindex; 102 | 103 | if (get_port_info(handle, &portdef) == OMX_ErrorNone) { 104 | print_port_info(&portdef); 105 | } 106 | 107 | exit(0); 108 | } 109 | -------------------------------------------------------------------------------- /OpenMAX/DeMux/ffmpeg_demux_decode_audio.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "libavcodec/avcodec.h" 6 | #include 7 | #include "libavutil/mathematics.h" 8 | #include "libavutil/samplefmt.h" 9 | #include "libavresample/avresample.h" 10 | 11 | #define INBUF_SIZE 4096 12 | #define AUDIO_INBUF_SIZE 20480 13 | #define AUDIO_REFILL_THRESH 4096 14 | 15 | char *IMG = "taichi.mp4"; 16 | 17 | static AVCodecContext *audio_dec_ctx = NULL; 18 | static AVStream *audio_stream = NULL; 19 | static AVPacket pkt; 20 | AVFormatContext *pFormatCtx = NULL; 21 | 22 | static int audio_stream_idx = -1; 23 | 24 | AVCodec *codec; 25 | 26 | 27 | int get_file_size(char *fname) { 28 | struct stat st; 29 | 30 | if (stat(fname, &st) == -1) { 31 | perror("Stat'ing img file"); 32 | return -1; 33 | } 34 | return(st.st_size); 35 | } 36 | 37 | AVCodecContext* codec_context; 38 | 39 | int setup_demuxer(const char *filename) { 40 | // Register all formats and codecs 41 | av_register_all(); 42 | if(avformat_open_input(&pFormatCtx, filename, NULL, NULL)!=0) { 43 | fprintf(stderr, "Can't get format\n"); 44 | return -1; // Couldn't open file 45 | } 46 | // Retrieve stream information 47 | if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { 48 | return -1; // Couldn't find stream information 49 | } 50 | printf("Format:\n"); 51 | av_dump_format(pFormatCtx, 0, filename, 0); 52 | 53 | int ret; 54 | ret = av_find_best_stream(pFormatCtx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); 55 | if (ret >= 0) { 56 | audio_stream_idx = ret; 57 | 58 | audio_stream = pFormatCtx->streams[audio_stream_idx]; 59 | audio_dec_ctx = audio_stream->codec; 60 | 61 | AVCodec *codec = avcodec_find_decoder(audio_stream->codec->codec_id); 62 | codec_context = avcodec_alloc_context3(codec); 63 | 64 | // copy across info from codec about extradata 65 | codec_context->extradata = audio_stream->codec->extradata; 66 | codec_context->extradata_size = audio_stream->codec->extradata_size; 67 | 68 | 69 | if (codec) { 70 | printf("Codec name %s\n", codec->name); 71 | } 72 | 73 | if (!avcodec_open2(codec_context, codec, NULL) < 0) { 74 | fprintf(stderr, "Could not find open the needed codec"); 75 | exit(1); 76 | } 77 | } 78 | return 0; 79 | } 80 | 81 | int main(int argc, char** argv) { 82 | 83 | int err; 84 | 85 | if (argc > 1) { 86 | IMG = argv[1]; 87 | } 88 | 89 | setup_demuxer(IMG); 90 | 91 | FILE *out = fopen("tmp.s16", "w"); 92 | 93 | // for converting from AV_SAMPLE_FMT_FLTP to AV_SAMPLE_FMT_S16 94 | // Set up SWR context once you've got codec information 95 | AVAudioResampleContext *swr = avresample_alloc_context(); 96 | //av_opt_set_int(swr, "in_channel_layout", audio_dec_ctx->channel_layout, 0); 97 | //av_opt_set_int(swr, "out_channel_layout", audio_dec_ctx->channel_layout, 0); 98 | av_opt_set_int(swr, "in_channel_layout", 99 | av_get_default_channel_layout(audio_dec_ctx->channels) , 0); 100 | av_opt_set_int(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); 101 | av_opt_set_int(swr, "in_sample_rate", audio_dec_ctx->sample_rate, 0); 102 | av_opt_set_int(swr, "out_sample_rate", audio_dec_ctx->sample_rate, 0); 103 | //av_opt_set_int(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0); 104 | av_opt_set_int(swr, "in_sample_fmt", audio_dec_ctx->sample_fmt, 0); 105 | av_opt_set_int(swr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); 106 | avresample_open(swr); 107 | 108 | int buffer_size; 109 | int num_ret; 110 | 111 | /* read frames from the file */ 112 | AVFrame *frame = avcodec_alloc_frame(); // av_frame_alloc 113 | while (av_read_frame(pFormatCtx, &pkt) >= 0) { 114 | // printf("Read pkt %d\n", pkt.size); 115 | 116 | AVPacket orig_pkt = pkt; 117 | if (pkt.stream_index == audio_stream_idx) { 118 | // printf(" read audio pkt %d\n", pkt.size); 119 | // fwrite(pkt.data, 1, pkt.size, out); 120 | 121 | AVPacket avpkt; 122 | int got_frame; 123 | av_init_packet(&avpkt); 124 | avpkt.data = pkt.data; 125 | avpkt.size = pkt.size; 126 | 127 | 128 | uint8_t *buffer; 129 | if (((err = avcodec_decode_audio4(codec_context, 130 | frame, 131 | &got_frame, 132 | &avpkt)) < 0) || !got_frame) { 133 | fprintf(stderr, "Error decoding %d\n", err); 134 | continue; 135 | } 136 | 137 | int out_linesize; 138 | /* 139 | av_samples_get_buffer_size(&out_linesize, 2, frame->nb_samples, 140 | AV_SAMPLE_FMT_S16, 0); 141 | */ 142 | av_samples_alloc(&buffer, &out_linesize, 2, frame->nb_samples, 143 | AV_SAMPLE_FMT_S16, 0); 144 | 145 | avresample_convert(swr, &buffer, 146 | frame->linesize[0], 147 | frame->nb_samples, 148 | frame->data, 149 | // frame->extended_data, 150 | frame->linesize[0], 151 | frame->nb_samples); 152 | /* 153 | printf("Pkt size %d, decoded to %d line size %d\n", 154 | pkt.size, err, out_linesize); 155 | printf("Samples: pkt size %d nb_samples %d\n", 156 | pkt.size, frame->nb_samples); 157 | printf("Buffer is (decoded size %d) %d %d %d %d %d\n", 158 | required_decoded_size, 159 | buffer[0], buffer[1], buffer[2], buffer[3], err); 160 | */ 161 | fwrite(buffer, 1, frame->nb_samples*4, out); 162 | } 163 | av_free_packet(&orig_pkt); 164 | } 165 | 166 | printf("Finished\n"); 167 | exit(0); 168 | } 169 | -------------------------------------------------------------------------------- /OpenMAX/EGL/square.c: -------------------------------------------------------------------------------- 1 | // 2 | // Book: OpenGL(R) ES 2.0 Programming Guide 3 | // Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner 4 | // ISBN-10: 0321502795 5 | // ISBN-13: 9780321502797 6 | // Publisher: Addison-Wesley Professional 7 | // URLs: http://safari.informit.com/9780321563835 8 | // http://www.opengles-book.com 9 | // 10 | 11 | // Simple_Texture2D.c 12 | // 13 | // This is a simple example that draws a quad with a 2D 14 | // texture image. The purpose of this example is to demonstrate 15 | // the basics of 2D texturing 16 | // 17 | #include 18 | #include 19 | #include "esUtil.h" 20 | 21 | #include "EGL/eglext.h" 22 | 23 | #include "triangle.h" 24 | 25 | typedef struct 26 | { 27 | // Handle to a program object 28 | GLuint programObject; 29 | 30 | // Attribute locations 31 | GLint positionLoc; 32 | GLint texCoordLoc; 33 | 34 | // Sampler location 35 | GLint samplerLoc; 36 | 37 | // Texture handle 38 | GLuint textureId; 39 | 40 | GLubyte *image; 41 | int width, height; 42 | } UserData; 43 | 44 | static void* eglImage = 0; 45 | static pthread_t thread1; 46 | 47 | #define IMAGE_SIZE_WIDTH 1920 48 | #define IMAGE_SIZE_HEIGHT 1080 49 | 50 | GLuint CreateSimpleTexture2D(ESContext *esContext) 51 | { 52 | // Texture object handle 53 | GLuint textureId; 54 | UserData *userData = esContext->userData; 55 | 56 | //userData->width = esContext->width; 57 | //userData->height = esContext->height; 58 | 59 | // Generate a texture object 60 | glGenTextures ( 1, &textureId ); 61 | 62 | // Bind the texture object 63 | glBindTexture ( GL_TEXTURE_2D, textureId ); 64 | 65 | // Load the texture 66 | glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA, 67 | IMAGE_SIZE_WIDTH, IMAGE_SIZE_HEIGHT, 68 | 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL ); 69 | 70 | // Set the filtering mode 71 | glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); 72 | glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); 73 | //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 74 | //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 75 | 76 | 77 | /* Create EGL Image */ 78 | eglImage = eglCreateImageKHR( 79 | esContext->eglDisplay, 80 | esContext->eglContext, 81 | EGL_GL_TEXTURE_2D_KHR, 82 | textureId, // (EGLClientBuffer)esContext->texture, 83 | 0); 84 | 85 | if (eglImage == EGL_NO_IMAGE_KHR) 86 | { 87 | printf("eglCreateImageKHR failed.\n"); 88 | exit(1); 89 | } 90 | 91 | // Start rendering 92 | pthread_create(&thread1, NULL, video_decode_test, eglImage); 93 | 94 | return textureId; 95 | } 96 | 97 | 98 | /// 99 | // Initialize the shader and program object 100 | // 101 | int Init ( ESContext *esContext ) 102 | { 103 | UserData *userData = esContext->userData; 104 | GLbyte vShaderStr[] = 105 | "attribute vec4 a_position; \n" 106 | "attribute vec2 a_texCoord; \n" 107 | "varying vec2 v_texCoord; \n" 108 | "void main() \n" 109 | "{ \n" 110 | " gl_Position = a_position; \n" 111 | " v_texCoord = a_texCoord; \n" 112 | "} \n"; 113 | 114 | GLbyte fShaderStr[] = 115 | "precision mediump float; \n" 116 | "varying vec2 v_texCoord; \n" 117 | "uniform sampler2D s_texture; \n" 118 | "void main() \n" 119 | "{ \n" 120 | " gl_FragColor = texture2D( s_texture, v_texCoord );\n" 121 | "} \n"; 122 | 123 | // Load the shaders and get a linked program object 124 | userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); 125 | 126 | // Get the attribute locations 127 | userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); 128 | userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" ); 129 | 130 | // Get the sampler location 131 | userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); 132 | 133 | // Load the texture 134 | userData->textureId = CreateSimpleTexture2D (esContext); 135 | 136 | glClearColor ( 0.5f, 0.5f, 0.5f, 1.0f ); 137 | 138 | return GL_TRUE; 139 | } 140 | 141 | /// 142 | // Draw a triangle using the shader pair created in Init() 143 | // 144 | void Draw ( ESContext *esContext ) 145 | { 146 | UserData *userData = esContext->userData; 147 | GLfloat vVertices[] = { -1.0f, 1.0f, 0.0f, // Position 0 148 | 0.0f, 0.0f, // TexCoord 0 149 | -1.0f, -1.0f, 0.0f, // Position 1 150 | 0.0f, 1.0f, // TexCoord 1 151 | 1.0f, -1.0f, 0.0f, // Position 2 152 | 1.0f, 1.0f, // TexCoord 2 153 | 1.0f, 1.0f, 0.0f, // Position 3 154 | 1.0f, 0.0f // TexCoord 3 155 | }; 156 | GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; 157 | 158 | // Set the viewport 159 | glViewport ( 0, 0, 1920, 1080); //esContext->width, esContext->height ); 160 | 161 | // Clear the color buffer 162 | glClear ( GL_COLOR_BUFFER_BIT ); 163 | 164 | // Use the program object 165 | glUseProgram ( userData->programObject ); 166 | 167 | // Load the vertex position 168 | glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, 169 | GL_FALSE, 5 * sizeof(GLfloat), vVertices ); 170 | // Load the texture coordinate 171 | glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT, 172 | GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] ); 173 | 174 | glEnableVertexAttribArray ( userData->positionLoc ); 175 | glEnableVertexAttribArray ( userData->texCoordLoc ); 176 | 177 | // Bind the texture 178 | glActiveTexture ( GL_TEXTURE0 ); 179 | glBindTexture ( GL_TEXTURE_2D, userData->textureId ); 180 | 181 | // Set the sampler texture unit to 0 182 | glUniform1i ( userData->samplerLoc, 0 ); 183 | 184 | glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); 185 | 186 | } 187 | 188 | /// 189 | // Cleanup 190 | // 191 | void ShutDown ( ESContext *esContext ) 192 | { 193 | UserData *userData = esContext->userData; 194 | 195 | // Delete texture object 196 | glDeleteTextures ( 1, &userData->textureId ); 197 | 198 | // Delete program object 199 | glDeleteProgram ( userData->programObject ); 200 | 201 | free(esContext->userData); 202 | } 203 | 204 | int main ( int argc, char *argv[] ) 205 | { 206 | ESContext esContext; 207 | UserData userData; 208 | 209 | int width = 1920, height = 1080; 210 | GLubyte *image; 211 | 212 | esInitContext ( &esContext ); 213 | esContext.userData = &userData; 214 | 215 | esCreateWindow ( &esContext, "Simple Texture 2D", width, height, ES_WINDOW_RGB ); 216 | 217 | if ( !Init ( &esContext ) ) 218 | return 0; 219 | 220 | esRegisterDrawFunc ( &esContext, Draw ); 221 | 222 | esMainLoop ( &esContext ); 223 | 224 | ShutDown ( &esContext ); 225 | } 226 | -------------------------------------------------------------------------------- /OpenMAX/EGL/video.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012, Broadcom Europe Ltd 3 | Copyright (c) 2012, OtherCrashOverride 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | * Neither the name of the copyright holder nor the 14 | names of its contributors may be used to endorse or promote products 15 | derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | // Video decode demo using OpenMAX IL though the ilcient helper library 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "bcm_host.h" 37 | #include "ilclient.h" 38 | 39 | static OMX_BUFFERHEADERTYPE* eglBuffer = NULL; 40 | static COMPONENT_T* egl_render = NULL; 41 | 42 | static void* eglImage = 0; 43 | 44 | void my_fill_buffer_done(void* data, COMPONENT_T* comp) 45 | { 46 | if (OMX_FillThisBuffer(ilclient_get_handle(egl_render), eglBuffer) != OMX_ErrorNone) 47 | { 48 | printf("OMX_FillThisBuffer failed in callback\n"); 49 | exit(1); 50 | } 51 | } 52 | 53 | int get_file_size(char *fname) { 54 | struct stat st; 55 | 56 | if (stat(fname, &st) == -1) { 57 | perror("Stat'ing img file"); 58 | return -1; 59 | } 60 | return(st.st_size); 61 | } 62 | 63 | #define err2str(x) "" 64 | 65 | OMX_ERRORTYPE read_into_buffer_and_empty(FILE *fp, 66 | COMPONENT_T *component, 67 | OMX_BUFFERHEADERTYPE *buff_header, 68 | int *toread) { 69 | OMX_ERRORTYPE r; 70 | 71 | int buff_size = buff_header->nAllocLen; 72 | int nread = fread(buff_header->pBuffer, 1, buff_size, fp); 73 | 74 | 75 | buff_header->nFilledLen = nread; 76 | *toread -= nread; 77 | 78 | if (*toread <= 0) { 79 | printf("Setting EOS on input\n"); 80 | buff_header->nFlags |= OMX_BUFFERFLAG_EOS; 81 | } 82 | r = OMX_EmptyThisBuffer(ilclient_get_handle(component), 83 | buff_header); 84 | if (r != OMX_ErrorNone) { 85 | fprintf(stderr, "Empty buffer error %s\n", 86 | err2str(r)); 87 | } 88 | return r; 89 | } 90 | 91 | // Modified function prototype to work with pthreads 92 | void *video_decode_test(void* arg) 93 | { 94 | const char* filename = "/opt/vc/src/hello_pi/hello_video/test.h264"; 95 | eglImage = arg; 96 | 97 | if (eglImage == 0) 98 | { 99 | printf("eglImage is null.\n"); 100 | exit(1); 101 | } 102 | 103 | OMX_VIDEO_PARAM_PORTFORMATTYPE format; 104 | OMX_TIME_CONFIG_CLOCKSTATETYPE cstate; 105 | 106 | COMPONENT_T *video_decode = NULL; 107 | COMPONENT_T *list[3]; // last entry should be null 108 | TUNNEL_T tunnel[2]; // last entry should be null 109 | 110 | ILCLIENT_T *client; 111 | FILE *in; 112 | int status = 0; 113 | unsigned int data_len = 0; 114 | 115 | memset(list, 0, sizeof(list)); 116 | memset(tunnel, 0, sizeof(tunnel)); 117 | 118 | if((in = fopen(filename, "rb")) == NULL) 119 | return (void *)-2; 120 | 121 | if((client = ilclient_init()) == NULL) 122 | { 123 | fclose(in); 124 | return (void *)-3; 125 | } 126 | 127 | if(OMX_Init() != OMX_ErrorNone) 128 | { 129 | ilclient_destroy(client); 130 | fclose(in); 131 | return (void *)-4; 132 | } 133 | 134 | // callback 135 | ilclient_set_fill_buffer_done_callback(client, my_fill_buffer_done, 0); 136 | 137 | // create video_decode 138 | if(ilclient_create_component(client, &video_decode, "video_decode", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_INPUT_BUFFERS) != 0) 139 | status = -14; 140 | list[0] = video_decode; 141 | 142 | // create egl_render 143 | if(status == 0 && ilclient_create_component(client, &egl_render, "egl_render", ILCLIENT_DISABLE_ALL_PORTS | ILCLIENT_ENABLE_OUTPUT_BUFFERS) != 0) 144 | status = -14; 145 | list[1] = egl_render; 146 | 147 | set_tunnel(tunnel, video_decode, 131, egl_render, 220); 148 | ilclient_change_component_state(video_decode, OMX_StateIdle); 149 | 150 | memset(&format, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 151 | format.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE); 152 | format.nVersion.nVersion = OMX_VERSION; 153 | format.nPortIndex = 130; 154 | format.eCompressionFormat = OMX_VIDEO_CodingAVC; 155 | 156 | if (status != 0) { 157 | fprintf(stderr, "Error has occurred %d\n", status); 158 | exit(1); 159 | } 160 | 161 | if(OMX_SetParameter(ILC_GET_HANDLE(video_decode), 162 | OMX_IndexParamVideoPortFormat, &format) != OMX_ErrorNone) { 163 | fprintf(stderr, "Error setting port format\n"); 164 | exit(1); 165 | } 166 | 167 | if(ilclient_enable_port_buffers(video_decode, 130, NULL, NULL, NULL) != 0) { 168 | fprintf(stderr, "Error enablng port buffers\n"); 169 | exit(1); 170 | } 171 | 172 | 173 | OMX_BUFFERHEADERTYPE *buf; 174 | int port_settings_changed = 0; 175 | int first_packet = 1; 176 | 177 | ilclient_change_component_state(video_decode, OMX_StateExecuting); 178 | 179 | int toread = get_file_size(filename); 180 | // Read the first block so that the video_decode can get 181 | // the dimensions of the video and call port settings 182 | // changed on the output port to configure it 183 | while (toread > 0) { 184 | buf = 185 | ilclient_get_input_buffer(video_decode, 186 | 130, 187 | 1 /* block */); 188 | if (buf != NULL) { 189 | read_into_buffer_and_empty(in, 190 | video_decode, 191 | buf, 192 | &toread); 193 | 194 | // If all the file has been read in, then 195 | // we have to re-read this first block. 196 | // Broadcom bug? 197 | if (toread <= 0) { 198 | printf("Rewinding\n"); 199 | // wind back to start and repeat 200 | //fp = freopen(IMG, "r", fp); 201 | rewind(in); 202 | toread = get_file_size(filename); 203 | } 204 | } 205 | 206 | if (toread > 0 && ilclient_remove_event(video_decode, 207 | OMX_EventPortSettingsChanged, 208 | 131, 0, 0, 1) == 0) { 209 | printf("Removed port settings event\n"); 210 | break; 211 | } else { 212 | // printf("No portr settting seen yet\n"); 213 | } 214 | // wait for first input block to set params for output port 215 | if (toread == 0) { 216 | int err; 217 | // wait for first input block to set params for output port 218 | err = ilclient_wait_for_event(video_decode, 219 | OMX_EventPortSettingsChanged, 220 | 131, 0, 0, 1, 221 | ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 222 | 2000); 223 | if (err < 0) { 224 | fprintf(stderr, "No port settings change\n"); 225 | //exit(1); 226 | } else { 227 | printf("Port settings changed\n"); 228 | break; 229 | } 230 | } 231 | } 232 | 233 | if(ilclient_setup_tunnel(tunnel, 0, 0) != 0) 234 | { 235 | status = -7; 236 | exit(1); 237 | } 238 | 239 | // Set egl_render to idle 240 | ilclient_change_component_state(egl_render, OMX_StateIdle); 241 | 242 | // Enable the output port and tell egl_render to use the texture as a buffer 243 | //ilclient_enable_port(egl_render, 221); THIS BLOCKS SO CANT BE USED 244 | if (OMX_SendCommand(ILC_GET_HANDLE(egl_render), OMX_CommandPortEnable, 221, NULL) != OMX_ErrorNone) 245 | { 246 | printf("OMX_CommandPortEnable failed.\n"); 247 | exit(1); 248 | } 249 | 250 | if (OMX_UseEGLImage(ILC_GET_HANDLE(egl_render), &eglBuffer, 221, NULL, eglImage) != OMX_ErrorNone) 251 | { 252 | printf("OMX_UseEGLImage failed.\n"); 253 | exit(1); 254 | } 255 | 256 | // Set egl_render to executing 257 | ilclient_change_component_state(egl_render, OMX_StateExecuting); 258 | 259 | 260 | // Request egl_render to write data to the texture buffer 261 | if(OMX_FillThisBuffer(ILC_GET_HANDLE(egl_render), eglBuffer) != OMX_ErrorNone) 262 | { 263 | printf("OMX_FillThisBuffer failed.\n"); 264 | exit(1); 265 | } 266 | 267 | 268 | // now work through the file 269 | while (toread > 0) { 270 | OMX_ERRORTYPE r; 271 | 272 | // do we have a decode input buffer we can fill and empty? 273 | buf = 274 | ilclient_get_input_buffer(video_decode, 275 | 130, 276 | 1 /* block */); 277 | if (buf != NULL) { 278 | read_into_buffer_and_empty(in, 279 | video_decode, 280 | buf, 281 | &toread); 282 | } 283 | } 284 | 285 | sleep(2); 286 | 287 | // need to flush the renderer to allow video_decode to disable its input port 288 | ilclient_flush_tunnels(tunnel, 1); 289 | 290 | ilclient_disable_port_buffers(video_decode, 130, NULL, NULL, NULL); 291 | 292 | fclose(in); 293 | 294 | ilclient_disable_tunnel(tunnel); 295 | ilclient_teardown_tunnels(tunnel); 296 | 297 | ilclient_state_transition(list, OMX_StateIdle); 298 | ilclient_state_transition(list, OMX_StateLoaded); 299 | 300 | ilclient_cleanup_components(list); 301 | 302 | OMX_Deinit(); 303 | 304 | ilclient_destroy(client); 305 | return (void *)status; 306 | } 307 | 308 | -------------------------------------------------------------------------------- /OpenMAX/ILClient/il_working.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | void printState(OMX_HANDLETYPE handle) { 11 | OMX_STATETYPE state; 12 | OMX_ERRORTYPE err; 13 | 14 | err = OMX_GetState(handle, &state); 15 | if (err != OMX_ErrorNone) { 16 | fprintf(stderr, "Error on getting state\n"); 17 | exit(1); 18 | } 19 | switch (state) { 20 | case OMX_StateLoaded: printf("StateLoaded\n"); break; 21 | case OMX_StateIdle: printf("StateIdle\n"); break; 22 | case OMX_StateExecuting: printf("StateExecuting\n"); break; 23 | case OMX_StatePause: printf("StatePause\n"); break; 24 | case OMX_StateWaitForResources: printf("StateWait\n"); break; 25 | case OMX_StateInvalid: printf("StateInvalid\n"); break; 26 | default: printf("State unknown\n"); break; 27 | } 28 | } 29 | 30 | int main(int argc, char** argv) { 31 | 32 | int i; 33 | char *componentName; 34 | int err; 35 | ILCLIENT_T *handle; 36 | COMPONENT_T *component; 37 | 38 | if (argc < 2) { 39 | fprintf(stderr, "Usage: %s component-name\n", argv[0]); 40 | exit(1); 41 | } 42 | componentName = argv[1]; 43 | 44 | bcm_host_init(); 45 | 46 | handle = ilclient_init(); 47 | if (handle == NULL) { 48 | fprintf(stderr, "IL client init failed\n"); 49 | exit(1); 50 | } 51 | 52 | if (OMX_Init() != OMX_ErrorNone) { 53 | ilclient_destroy(handle); 54 | fprintf(stderr, "OMX init failed\n"); 55 | exit(1); 56 | } 57 | 58 | err = ilclient_create_component(handle, 59 | &component, 60 | componentName, 61 | ILCLIENT_DISABLE_ALL_PORTS 62 | ); 63 | if (err == -1) { 64 | fprintf(stderr, "Component create failed\n"); 65 | exit(1); 66 | } 67 | printState(ilclient_get_handle(component)); 68 | 69 | err = ilclient_change_component_state(component, 70 | OMX_StateIdle); 71 | if (err < 0) { 72 | fprintf(stderr, "Couldn't change state to Idle\n"); 73 | exit(1); 74 | } 75 | printState(ilclient_get_handle(component)); 76 | 77 | err = ilclient_change_component_state(component, 78 | OMX_StateExecuting); 79 | if (err < 0) { 80 | fprintf(stderr, "Couldn't change state to Executing\n"); 81 | exit(1); 82 | } 83 | printState(ilclient_get_handle(component)); 84 | 85 | exit(0); 86 | } 87 | -------------------------------------------------------------------------------- /OpenMAX/Images/il_render_image.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #define IMG "cimg0135.jpg" 12 | //#define IMG "hype.jpg" 13 | 14 | void printState(OMX_HANDLETYPE handle) { 15 | // code elided 16 | } 17 | 18 | char *err2str(int err) { 19 | return "error elided"; 20 | } 21 | 22 | void eos_callback(void *userdata, COMPONENT_T *comp, OMX_U32 data) { 23 | fprintf(stderr, "Got eos event\n"); 24 | } 25 | 26 | void error_callback(void *userdata, COMPONENT_T *comp, OMX_U32 data) { 27 | fprintf(stderr, "OMX error %s\n", err2str(data)); 28 | } 29 | 30 | int get_file_size(char *fname) { 31 | struct stat st; 32 | 33 | if (stat(fname, &st) == -1) { 34 | perror("Stat'ing img file"); 35 | return -1; 36 | } 37 | return(st.st_size); 38 | } 39 | 40 | unsigned int uWidth; 41 | unsigned int uHeight; 42 | 43 | OMX_ERRORTYPE read_into_buffer_and_empty(FILE *fp, 44 | COMPONENT_T *component, 45 | OMX_BUFFERHEADERTYPE *buff_header, 46 | int *toread) { 47 | OMX_ERRORTYPE r; 48 | 49 | int buff_size = buff_header->nAllocLen; 50 | int nread = fread(buff_header->pBuffer, 1, buff_size, fp); 51 | 52 | printf("Read %d\n", nread); 53 | 54 | buff_header->nFilledLen = nread; 55 | *toread -= nread; 56 | if (*toread <= 0) { 57 | printf("Setting EOS on input\n"); 58 | buff_header->nFlags |= OMX_BUFFERFLAG_EOS; 59 | } 60 | r = OMX_EmptyThisBuffer(ilclient_get_handle(component), 61 | buff_header); 62 | if (r != OMX_ErrorNone) { 63 | fprintf(stderr, "Empty buffer error %s\n", 64 | err2str(r)); 65 | } 66 | return r; 67 | } 68 | 69 | static void set_image_decoder_input_format(COMPONENT_T *component) { 70 | // set input image format 71 | printf("Setting image decoder format\n"); 72 | OMX_IMAGE_PARAM_PORTFORMATTYPE imagePortFormat; 73 | //setHeader(&imagePortFormat, sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE)); 74 | memset(&imagePortFormat, 0, sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE)); 75 | imagePortFormat.nSize = sizeof(OMX_IMAGE_PARAM_PORTFORMATTYPE); 76 | imagePortFormat.nVersion.nVersion = OMX_VERSION; 77 | 78 | imagePortFormat.nPortIndex = 320; 79 | imagePortFormat.eCompressionFormat = OMX_IMAGE_CodingJPEG; 80 | OMX_SetParameter(ilclient_get_handle(component), 81 | OMX_IndexParamImagePortFormat, &imagePortFormat); 82 | 83 | } 84 | 85 | void setup_decodeComponent(ILCLIENT_T *handle, 86 | char *decodeComponentName, 87 | COMPONENT_T **decodeComponent) { 88 | int err; 89 | 90 | err = ilclient_create_component(handle, 91 | decodeComponent, 92 | decodeComponentName, 93 | ILCLIENT_DISABLE_ALL_PORTS 94 | | 95 | ILCLIENT_ENABLE_INPUT_BUFFERS 96 | /* | 97 | ILCLIENT_ENABLE_OUTPUT_BUFFERS 98 | */ 99 | ); 100 | if (err == -1) { 101 | fprintf(stderr, "DecodeComponent create failed\n"); 102 | exit(1); 103 | } 104 | printState(ilclient_get_handle(*decodeComponent)); 105 | 106 | err = ilclient_change_component_state(*decodeComponent, 107 | OMX_StateIdle); 108 | if (err < 0) { 109 | fprintf(stderr, "Couldn't change state to Idle\n"); 110 | exit(1); 111 | } 112 | printState(ilclient_get_handle(*decodeComponent)); 113 | 114 | // must be before we enable buffers 115 | set_image_decoder_input_format(*decodeComponent); 116 | } 117 | 118 | void setup_renderComponent(ILCLIENT_T *handle, 119 | char *renderComponentName, 120 | COMPONENT_T **renderComponent) { 121 | int err; 122 | 123 | err = ilclient_create_component(handle, 124 | renderComponent, 125 | renderComponentName, 126 | ILCLIENT_DISABLE_ALL_PORTS 127 | /* | 128 | ILCLIENT_ENABLE_INPUT_BUFFERS 129 | */ 130 | ); 131 | if (err == -1) { 132 | fprintf(stderr, "RenderComponent create failed\n"); 133 | exit(1); 134 | } 135 | printState(ilclient_get_handle(*renderComponent)); 136 | 137 | err = ilclient_change_component_state(*renderComponent, 138 | OMX_StateIdle); 139 | if (err < 0) { 140 | fprintf(stderr, "Couldn't change state to Idle\n"); 141 | exit(1); 142 | } 143 | printState(ilclient_get_handle(*renderComponent)); 144 | } 145 | 146 | int main(int argc, char** argv) { 147 | 148 | int i; 149 | char *decodeComponentName; 150 | char *renderComponentName; 151 | int err; 152 | ILCLIENT_T *handle; 153 | COMPONENT_T *decodeComponent; 154 | COMPONENT_T *renderComponent; 155 | FILE *fp = fopen(IMG, "r"); 156 | int toread = get_file_size(IMG); 157 | OMX_BUFFERHEADERTYPE *buff_header; 158 | 159 | decodeComponentName = "image_decode"; 160 | renderComponentName = "video_render"; 161 | 162 | bcm_host_init(); 163 | 164 | handle = ilclient_init(); 165 | if (handle == NULL) { 166 | fprintf(stderr, "IL client init failed\n"); 167 | exit(1); 168 | } 169 | 170 | if (OMX_Init() != OMX_ErrorNone) { 171 | ilclient_destroy(handle); 172 | fprintf(stderr, "OMX init failed\n"); 173 | exit(1); 174 | } 175 | 176 | ilclient_set_error_callback(handle, 177 | error_callback, 178 | NULL); 179 | ilclient_set_eos_callback(handle, 180 | eos_callback, 181 | NULL); 182 | 183 | 184 | setup_decodeComponent(handle, decodeComponentName, &decodeComponent); 185 | setup_renderComponent(handle, renderComponentName, &renderComponent); 186 | // both components now in Idle state, no buffers, ports disabled 187 | 188 | // input port 189 | ilclient_enable_port_buffers(decodeComponent, 320, 190 | NULL, NULL, NULL); 191 | ilclient_enable_port(decodeComponent, 320); 192 | 193 | 194 | err = ilclient_change_component_state(decodeComponent, 195 | OMX_StateExecuting); 196 | if (err < 0) { 197 | fprintf(stderr, "Couldn't change state to Executing\n"); 198 | exit(1); 199 | } 200 | printState(ilclient_get_handle(decodeComponent)); 201 | 202 | 203 | // Read the first block so that the decodeComponent can get 204 | // the dimensions of the image and call port settings 205 | // changed on the output port to configure it 206 | buff_header = 207 | ilclient_get_input_buffer(decodeComponent, 208 | 320, 209 | 1 /* block */); 210 | if (buff_header != NULL) { 211 | read_into_buffer_and_empty(fp, 212 | decodeComponent, 213 | buff_header, 214 | &toread); 215 | 216 | // If all the file has been read in, then 217 | // we have to re-read this first block. 218 | // Broadcom bug? 219 | if (toread <= 0) { 220 | printf("Rewinding\n"); 221 | // wind back to start and repeat 222 | fp = freopen(IMG, "r", fp); 223 | toread = get_file_size(IMG); 224 | } 225 | } 226 | 227 | // wait for first input block to set params for output port 228 | ilclient_wait_for_event(decodeComponent, 229 | OMX_EventPortSettingsChanged, 230 | 321, 0, 0, 1, 231 | ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 232 | 5); 233 | 234 | printf("Port settings changed\n"); 235 | 236 | TUNNEL_T tunnel; 237 | set_tunnel(&tunnel, decodeComponent, 321, renderComponent, 90); 238 | if ((err = ilclient_setup_tunnel(&tunnel, 0, 0)) < 0) { 239 | fprintf(stderr, "Error setting up tunnel %X\n", err); 240 | exit(1); 241 | } else { 242 | printf("Tunnel set up ok\n"); 243 | } 244 | 245 | // Okay to go back to processing data 246 | // enable the decode output ports 247 | 248 | OMX_SendCommand(ilclient_get_handle(decodeComponent), 249 | OMX_CommandPortEnable, 321, NULL); 250 | 251 | ilclient_enable_port(decodeComponent, 321); 252 | 253 | // enable the render output ports 254 | /* 255 | OMX_SendCommand(ilclient_get_handle(renderComponent), 256 | OMX_CommandPortEnable, 90, NULL); 257 | */ 258 | ilclient_enable_port(renderComponent, 90); 259 | 260 | // set both components to executing state 261 | err = ilclient_change_component_state(decodeComponent, 262 | OMX_StateExecuting); 263 | if (err < 0) { 264 | fprintf(stderr, "Couldn't change state to Idle\n"); 265 | exit(1); 266 | } 267 | err = ilclient_change_component_state(renderComponent, 268 | OMX_StateExecuting); 269 | if (err < 0) { 270 | fprintf(stderr, "Couldn't change state to Idle\n"); 271 | exit(1); 272 | } 273 | 274 | // now work through the file 275 | while (toread > 0) { 276 | OMX_ERRORTYPE r; 277 | 278 | // do we have a decode input buffer we can fill and empty? 279 | buff_header = 280 | ilclient_get_input_buffer(decodeComponent, 281 | 320, 282 | 1 /* block */); 283 | if (buff_header != NULL) { 284 | read_into_buffer_and_empty(fp, 285 | decodeComponent, 286 | buff_header, 287 | &toread); 288 | } 289 | } 290 | 291 | ilclient_wait_for_event(renderComponent, 292 | OMX_EventBufferFlag, 293 | 90, 0, OMX_BUFFERFLAG_EOS, 0, 294 | ILCLIENT_BUFFER_FLAG_EOS, 10000); 295 | printf("EOS on render\n"); 296 | 297 | sleep(100); 298 | 299 | exit(0); 300 | } 301 | -------------------------------------------------------------------------------- /OpenMAX/State/event.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | char *err2str(int err) { 10 | return "omitted"; 11 | } 12 | 13 | void printState(OMX_HANDLETYPE handle) { 14 | OMX_STATETYPE state; 15 | OMX_ERRORTYPE err; 16 | 17 | err = OMX_GetState(handle, &state); 18 | if (err != OMX_ErrorNone) { 19 | fprintf(stderr, "Error on getting state\n"); 20 | exit(1); 21 | } 22 | switch (state) { 23 | case OMX_StateLoaded: printf("StateLoaded\n"); break; 24 | case OMX_StateIdle: printf("StateIdle\n"); break; 25 | case OMX_StateExecuting: printf("StateExecuting\n"); break; 26 | case OMX_StatePause: printf("StatePause\n"); break; 27 | case OMX_StateWaitForResources: printf("StateWait\n"); break; 28 | case OMX_StateInvalid: printf("StateInvalid\n"); break; 29 | default: printf("State unknown\n"); break; 30 | } 31 | } 32 | 33 | OMX_ERRORTYPE cEventHandler( 34 | OMX_HANDLETYPE hComponent, 35 | OMX_PTR pAppData, 36 | OMX_EVENTTYPE eEvent, 37 | OMX_U32 Data1, 38 | OMX_U32 Data2, 39 | OMX_PTR pEventData) { 40 | 41 | if(eEvent == OMX_EventCmdComplete) { 42 | if (Data1 == OMX_CommandStateSet) { 43 | printf("Component State changed to "); 44 | switch ((int)Data2) { 45 | case OMX_StateInvalid: 46 | printf("OMX_StateInvalid\n"); 47 | break; 48 | case OMX_StateLoaded: 49 | printf("OMX_StateLoaded\n"); 50 | break; 51 | case OMX_StateIdle: 52 | printf("OMX_StateIdle\n"); 53 | break; 54 | case OMX_StateExecuting: 55 | printf("OMX_StateExecuting\n"); 56 | break; 57 | case OMX_StatePause: 58 | printf("OMX_StatePause\n"); 59 | break; 60 | case OMX_StateWaitForResources: 61 | printf("OMX_StateWaitForResources\n"); 62 | break; 63 | } 64 | } else if (Data1 == OMX_CommandPortEnable){ 65 | printf("OMX State Port enabled %d\n", (int) Data2); 66 | } else if (Data1 == OMX_CommandPortDisable){ 67 | printf("OMX State Port disabled %d\n", (int) Data2); 68 | } 69 | } else if(eEvent == OMX_EventBufferFlag) { 70 | if((int)Data2 == OMX_BUFFERFLAG_EOS) { 71 | printf("Event is buffer end of stream\n"); 72 | } 73 | } else if(eEvent == OMX_EventError) { 74 | if (Data1 == OMX_ErrorSameState) { 75 | printf("Already in requested state\n"); 76 | } else { 77 | printf("Event is Error %X\n", Data1); 78 | } 79 | } else if(eEvent == OMX_EventMark) { 80 | printf("Event is Buffer Mark\n"); 81 | } else if(eEvent == OMX_EventPortSettingsChanged) { 82 | printf("Event is PortSettingsChanged\n"); 83 | } 84 | 85 | return OMX_ErrorNone; 86 | } 87 | 88 | OMX_CALLBACKTYPE callbacks = { .EventHandler = cEventHandler, 89 | .EmptyBufferDone = NULL, 90 | .FillBufferDone = NULL 91 | }; 92 | 93 | void disableSomePorts(OMX_HANDLETYPE handle, OMX_INDEXTYPE indexType) { 94 | OMX_PORT_PARAM_TYPE param; 95 | int startPortNumber, endPortNumber; 96 | int nPorts; 97 | int n; 98 | OMX_ERRORTYPE err; 99 | 100 | //setHeader(¶m, sizeof(OMX_PORT_PARAM_TYPE)); 101 | 102 | memset(¶m, 0, sizeof(OMX_PORT_PARAM_TYPE)); 103 | param.nSize = sizeof(OMX_PORT_PARAM_TYPE); 104 | param.nVersion.nVersion = OMX_VERSION; 105 | 106 | err = OMX_GetParameter(handle, indexType, ¶m); 107 | if(err != OMX_ErrorNone){ 108 | fprintf(stderr, "Error in getting image OMX_PORT_PARAM_TYPE parameter\n" 109 | , 0); 110 | return; 111 | } 112 | 113 | startPortNumber = param.nStartPortNumber; 114 | nPorts = param.nPorts; 115 | endPortNumber = startPortNumber + nPorts; 116 | 117 | for (n = startPortNumber; n < endPortNumber; n++) { 118 | OMX_SendCommand(handle, OMX_CommandPortDisable, 119 | n, NULL); 120 | } 121 | } 122 | 123 | void disableAllPorts(OMX_HANDLETYPE handle) { 124 | disableSomePorts(handle, OMX_IndexParamVideoInit); 125 | disableSomePorts(handle, OMX_IndexParamImageInit); 126 | disableSomePorts(handle, OMX_IndexParamAudioInit); 127 | disableSomePorts(handle, OMX_IndexParamOtherInit); 128 | } 129 | 130 | int main(int argc, char** argv) { 131 | 132 | int i; 133 | char *componentName; 134 | OMX_ERRORTYPE err; 135 | OMX_HANDLETYPE handle; 136 | 137 | if (argc < 2) { 138 | fprintf(stderr, "Usage: %s component-name\n", argv[0]); 139 | exit(1); 140 | } 141 | componentName = argv[1]; 142 | 143 | bcm_host_init(); 144 | 145 | err = OMX_Init(); 146 | if(err != OMX_ErrorNone) { 147 | fprintf(stderr, "OMX_Init() failed %s\n", err2str(err)); 148 | exit(1); 149 | } 150 | /** Ask the core for a handle to the component 151 | */ 152 | err = OMX_GetHandle(&handle, componentName, 153 | // the next two fields are discussed later 154 | NULL, &callbacks); 155 | if (err != OMX_ErrorNone) { 156 | fprintf(stderr, "OMX_GetHandle failed %s\n", err2str(err)); 157 | exit(1); 158 | } 159 | 160 | sleep(1); 161 | // check our current state - should be Loaded 162 | printState(handle); 163 | 164 | disableAllPorts(handle); 165 | 166 | // request a move to idle 167 | OMX_SendCommand(handle, 168 | OMX_CommandStateSet, 169 | OMX_StateIdle, 170 | NULL); 171 | 172 | sleep(2); 173 | printState(handle); 174 | 175 | // and to executing 176 | OMX_SendCommand(handle, 177 | OMX_CommandStateSet, 178 | OMX_StateExecuting, 179 | NULL); 180 | sleep(2); 181 | printState(handle); 182 | 183 | exit(0); 184 | } 185 | -------------------------------------------------------------------------------- /OpenMAX/State/wontwork.c: -------------------------------------------------------------------------------- 1 | /* 2 | * WARNING: THIS PROGRAM DOESN'T WORK 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | char *err2str(int err) { 14 | switch (err) { 15 | case OMX_ErrorInsufficientResources: return "OMX_ErrorInsufficientResources"; 16 | case OMX_ErrorUndefined: return "OMX_ErrorUndefined"; 17 | case OMX_ErrorInvalidComponentName: return "OMX_ErrorInvalidComponentName"; 18 | case OMX_ErrorComponentNotFound: return "OMX_ErrorComponentNotFound"; 19 | case OMX_ErrorInvalidComponent: return "OMX_ErrorInvalidComponent"; 20 | case OMX_ErrorBadParameter: return "OMX_ErrorBadParameter"; 21 | case OMX_ErrorNotImplemented: return "OMX_ErrorNotImplemented"; 22 | case OMX_ErrorUnderflow: return "OMX_ErrorUnderflow"; 23 | case OMX_ErrorOverflow: return "OMX_ErrorOverflow"; 24 | case OMX_ErrorHardware: return "OMX_ErrorHardware"; 25 | case OMX_ErrorInvalidState: return "OMX_ErrorInvalidState"; 26 | case OMX_ErrorStreamCorrupt: return "OMX_ErrorStreamCorrupt"; 27 | case OMX_ErrorPortsNotCompatible: return "OMX_ErrorPortsNotCompatible"; 28 | case OMX_ErrorResourcesLost: return "OMX_ErrorResourcesLost"; 29 | case OMX_ErrorNoMore: return "OMX_ErrorNoMore"; 30 | case OMX_ErrorVersionMismatch: return "OMX_ErrorVersionMismatch"; 31 | case OMX_ErrorNotReady: return "OMX_ErrorNotReady"; 32 | case OMX_ErrorTimeout: return "OMX_ErrorTimeout"; 33 | case OMX_ErrorSameState: return "OMX_ErrorSameState"; 34 | case OMX_ErrorResourcesPreempted: return "OMX_ErrorResourcesPreempted"; 35 | case OMX_ErrorPortUnresponsiveDuringAllocation: return "OMX_ErrorPortUnresponsiveDuringAllocation"; 36 | case OMX_ErrorPortUnresponsiveDuringDeallocation: return "OMX_ErrorPortUnresponsiveDuringDeallocation"; 37 | case OMX_ErrorPortUnresponsiveDuringStop: return "OMX_ErrorPortUnresponsiveDuringStop"; 38 | case OMX_ErrorIncorrectStateTransition: return "OMX_ErrorIncorrectStateTransition"; 39 | case OMX_ErrorIncorrectStateOperation: return "OMX_ErrorIncorrectStateOperation"; 40 | case OMX_ErrorUnsupportedSetting: return "OMX_ErrorUnsupportedSetting"; 41 | case OMX_ErrorUnsupportedIndex: return "OMX_ErrorUnsupportedIndex"; 42 | case OMX_ErrorBadPortIndex: return "OMX_ErrorBadPortIndex"; 43 | case OMX_ErrorPortUnpopulated: return "OMX_ErrorPortUnpopulated"; 44 | case OMX_ErrorComponentSuspended: return "OMX_ErrorComponentSuspended"; 45 | case OMX_ErrorDynamicResourcesUnavailable: return "OMX_ErrorDynamicResourcesUnavailable"; 46 | case OMX_ErrorMbErrorsInFrame: return "OMX_ErrorMbErrorsInFrame"; 47 | case OMX_ErrorFormatNotDetected: return "OMX_ErrorFormatNotDetected"; 48 | case OMX_ErrorContentPipeOpenFailed: return "OMX_ErrorContentPipeOpenFailed"; 49 | case OMX_ErrorContentPipeCreationFailed: return "OMX_ErrorContentPipeCreationFailed"; 50 | case OMX_ErrorSeperateTablesUsed: return "OMX_ErrorSeperateTablesUsed"; 51 | case OMX_ErrorTunnelingUnsupported: return "OMX_ErrorTunnelingUnsupported"; 52 | default: return "unknown error"; 53 | } 54 | } 55 | 56 | void printState(OMX_HANDLETYPE handle) { 57 | OMX_STATETYPE state; 58 | OMX_ERRORTYPE err; 59 | 60 | err = OMX_GetState(handle, &state); 61 | if (err != OMX_ErrorNone) { 62 | fprintf(stderr, "Error on getting state\n"); 63 | exit(1); 64 | } 65 | switch (state) { 66 | case OMX_StateLoaded: printf("StateLoaded\n"); break; 67 | case OMX_StateIdle: printf("StateIdle\n"); break; 68 | case OMX_StateExecuting: printf("StateExecuting\n"); break; 69 | case OMX_StatePause: printf("StatePause\n"); break; 70 | case OMX_StateWaitForResources: printf("StateWait\n"); break; 71 | case OMX_StateInvalid: printf("StateInvalid\n"); break; 72 | default: printf("State unknown\n"); break; 73 | } 74 | } 75 | 76 | OMX_ERRORTYPE cEventHandler( 77 | OMX_HANDLETYPE hComponent, 78 | OMX_PTR pAppData, 79 | OMX_EVENTTYPE eEvent, 80 | OMX_U32 Data1, 81 | OMX_U32 Data2, 82 | OMX_PTR pEventData) { 83 | 84 | printf("Hi there, I am in the %s callback\n", __func__); 85 | printf("Event is %i\n", (int)eEvent); 86 | printf("Param1 is %i\n", (int)Data1); 87 | printf("Param2 is %i\n", (int)Data2); 88 | 89 | return OMX_ErrorNone; 90 | } 91 | 92 | OMX_CALLBACKTYPE callbacks = { .EventHandler = cEventHandler, 93 | .EmptyBufferDone = NULL, 94 | .FillBufferDone = NULL 95 | }; 96 | 97 | 98 | int main(int argc, char** argv) { 99 | 100 | int i; 101 | char *componentName; 102 | OMX_ERRORTYPE err; 103 | OMX_HANDLETYPE handle; 104 | 105 | if (argc < 2) { 106 | fprintf(stderr, "Usage: %s component-name\n", argv[0]); 107 | exit(1); 108 | } 109 | componentName = argv[1]; 110 | 111 | bcm_host_init(); 112 | 113 | err = OMX_Init(); 114 | if(err != OMX_ErrorNone) { 115 | fprintf(stderr, "OMX_Init() failed %s\n", err2str(err)); 116 | exit(1); 117 | } 118 | /** Ask the core for a handle to the component 119 | */ 120 | err = OMX_GetHandle(&handle, componentName, 121 | // the next two fields are discussed later 122 | NULL, &callbacks); 123 | if (err != OMX_ErrorNone) { 124 | fprintf(stderr, "OMX_GetHandle failed %s\n", err2str(err)); 125 | exit(1); 126 | } 127 | 128 | // check our current state - should be Loaded 129 | printState(handle); 130 | 131 | // request a move to idle 132 | OMX_SendCommand(handle, 133 | OMX_CommandStateSet, 134 | OMX_StateIdle, 135 | NULL); 136 | 137 | int n = 0; 138 | while (n++ < 10) { 139 | sleep(1); 140 | // are we there yet? 141 | printState(handle); 142 | } 143 | 144 | exit(0); 145 | } 146 | -------------------------------------------------------------------------------- /OpenMAX/State/working.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | char *err2str(int err) { 10 | return "omitted"; 11 | } 12 | 13 | void printState(OMX_HANDLETYPE handle) { 14 | OMX_STATETYPE state; 15 | OMX_ERRORTYPE err; 16 | 17 | err = OMX_GetState(handle, &state); 18 | if (err != OMX_ErrorNone) { 19 | fprintf(stderr, "Error on getting state\n"); 20 | exit(1); 21 | } 22 | switch (state) { 23 | case OMX_StateLoaded: printf("StateLoaded\n"); break; 24 | case OMX_StateIdle: printf("StateIdle\n"); break; 25 | case OMX_StateExecuting: printf("StateExecuting\n"); break; 26 | case OMX_StatePause: printf("StatePause\n"); break; 27 | case OMX_StateWaitForResources: printf("StateWait\n"); break; 28 | case OMX_StateInvalid: printf("StateInvalid\n"); break; 29 | default: printf("State unknown\n"); break; 30 | } 31 | } 32 | 33 | OMX_ERRORTYPE cEventHandler( 34 | OMX_HANDLETYPE hComponent, 35 | OMX_PTR pAppData, 36 | OMX_EVENTTYPE eEvent, 37 | OMX_U32 Data1, 38 | OMX_U32 Data2, 39 | OMX_PTR pEventData) { 40 | 41 | printf("Hi there, I am in the %s callback\n", __func__); 42 | printf("Event is %i\n", (int)eEvent); 43 | printf("Param1 is %i\n", (int)Data1); 44 | printf("Param2 is %i\n", (int)Data2); 45 | 46 | return OMX_ErrorNone; 47 | } 48 | 49 | OMX_CALLBACKTYPE callbacks = { .EventHandler = cEventHandler, 50 | .EmptyBufferDone = NULL, 51 | .FillBufferDone = NULL 52 | }; 53 | 54 | void disableSomePorts(OMX_HANDLETYPE handle, OMX_INDEXTYPE indexType) { 55 | OMX_PORT_PARAM_TYPE param; 56 | int startPortNumber, endPortNumber; 57 | int nPorts; 58 | int n; 59 | OMX_ERRORTYPE err; 60 | 61 | memset(¶m, 0, sizeof(OMX_PORT_PARAM_TYPE)); 62 | param.nSize = sizeof(OMX_PORT_PARAM_TYPE); 63 | param.nVersion.nVersion = OMX_VERSION; 64 | 65 | err = OMX_GetParameter(handle, indexType, ¶m); 66 | if(err != OMX_ErrorNone){ 67 | fprintf(stderr, "Error in getting image OMX_PORT_PARAM_TYPE parameter\n" 68 | ); 69 | return; 70 | } 71 | 72 | startPortNumber = param.nStartPortNumber; 73 | nPorts = param.nPorts; 74 | endPortNumber = startPortNumber + nPorts; 75 | 76 | for (n = startPortNumber; n < endPortNumber; n++) { 77 | OMX_SendCommand(handle, OMX_CommandPortDisable, 78 | n, NULL); 79 | } 80 | } 81 | 82 | void disableAllPorts(OMX_HANDLETYPE handle) { 83 | disableSomePorts(handle, OMX_IndexParamVideoInit); 84 | disableSomePorts(handle, OMX_IndexParamImageInit); 85 | disableSomePorts(handle, OMX_IndexParamAudioInit); 86 | disableSomePorts(handle, OMX_IndexParamOtherInit); 87 | } 88 | 89 | int main(int argc, char** argv) { 90 | 91 | int i; 92 | char *componentName; 93 | OMX_ERRORTYPE err; 94 | OMX_HANDLETYPE handle; 95 | 96 | if (argc < 2) { 97 | fprintf(stderr, "Usage: %s component-name\n", argv[0]); 98 | exit(1); 99 | } 100 | componentName = argv[1]; 101 | 102 | bcm_host_init(); 103 | 104 | err = OMX_Init(); 105 | if(err != OMX_ErrorNone) { 106 | fprintf(stderr, "OMX_Init() failed %s\n", err2str(err)); 107 | exit(1); 108 | } 109 | /** Ask the core for a handle to the component 110 | */ 111 | err = OMX_GetHandle(&handle, componentName, 112 | // the next two fields are discussed later 113 | NULL, &callbacks); 114 | if (err != OMX_ErrorNone) { 115 | fprintf(stderr, "OMX_GetHandle failed %s\n", err2str(err)); 116 | exit(1); 117 | } 118 | 119 | sleep(1); 120 | // check our current state - should be Loaded 121 | printState(handle); 122 | 123 | disableAllPorts(handle); 124 | 125 | // request a move to idle 126 | OMX_SendCommand(handle, 127 | OMX_CommandStateSet, 128 | OMX_StateIdle, 129 | NULL); 130 | 131 | int n = 0; 132 | while (n++ < 10) { 133 | sleep(1); 134 | // are we there yet? 135 | printState(handle); 136 | } 137 | 138 | exit(0); 139 | } 140 | -------------------------------------------------------------------------------- /OpenMAX/Video/il_decode_video.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #define IMG "/opt/vc/src/hello_pi/hello_video/test.h264" 12 | 13 | void printState(OMX_HANDLETYPE handle) { 14 | // elided 15 | } 16 | 17 | char *err2str(int err) { 18 | return "elided"; 19 | } 20 | 21 | void eos_callback(void *userdata, COMPONENT_T *comp, OMX_U32 data) { 22 | fprintf(stderr, "Got eos event\n"); 23 | } 24 | 25 | void error_callback(void *userdata, COMPONENT_T *comp, OMX_U32 data) { 26 | fprintf(stderr, "OMX error %s\n", err2str(data)); 27 | } 28 | 29 | int get_file_size(char *fname) { 30 | struct stat st; 31 | 32 | if (stat(fname, &st) == -1) { 33 | perror("Stat'ing img file"); 34 | return -1; 35 | } 36 | return(st.st_size); 37 | } 38 | 39 | static void set_video_decoder_input_format(COMPONENT_T *component) { 40 | // set input video format 41 | printf("Setting video decoder format\n"); 42 | OMX_VIDEO_PARAM_PORTFORMATTYPE videoPortFormat; 43 | //setHeader(&videoPortFormat, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 44 | memset(&videoPortFormat, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 45 | videoPortFormat.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE); 46 | videoPortFormat.nVersion.nVersion = OMX_VERSION; 47 | 48 | videoPortFormat.nPortIndex = 130; 49 | videoPortFormat.eCompressionFormat = OMX_VIDEO_CodingAVC; 50 | OMX_SetParameter(ilclient_get_handle(component), 51 | OMX_IndexParamVideoPortFormat, &videoPortFormat); 52 | 53 | } 54 | 55 | OMX_ERRORTYPE read_into_buffer_and_empty(FILE *fp, 56 | COMPONENT_T *component, 57 | OMX_BUFFERHEADERTYPE *buff_header, 58 | int *toread) { 59 | OMX_ERRORTYPE r; 60 | 61 | int buff_size = buff_header->nAllocLen; 62 | int nread = fread(buff_header->pBuffer, 1, buff_size, fp); 63 | 64 | 65 | 66 | buff_header->nFilledLen = nread; 67 | *toread -= nread; 68 | printf("Read %d, %d still left\n", nread, *toread); 69 | 70 | if (*toread <= 0) { 71 | printf("Setting EOS on input\n"); 72 | buff_header->nFlags |= OMX_BUFFERFLAG_EOS; 73 | } 74 | r = OMX_EmptyThisBuffer(ilclient_get_handle(component), 75 | buff_header); 76 | if (r != OMX_ErrorNone) { 77 | fprintf(stderr, "Empty buffer error %s\n", 78 | err2str(r)); 79 | } 80 | return r; 81 | } 82 | 83 | OMX_ERRORTYPE save_info_from_filled_buffer(COMPONENT_T *component, 84 | OMX_BUFFERHEADERTYPE * buff_header) { 85 | OMX_ERRORTYPE r; 86 | 87 | printf("Got a filled buffer with %d, allocated %d\n", 88 | buff_header->nFilledLen, 89 | buff_header->nAllocLen); 90 | if (buff_header->nFlags & OMX_BUFFERFLAG_EOS) { 91 | printf("Got EOS on output\n"); 92 | exit(0); 93 | } 94 | 95 | // and then refill it 96 | r = OMX_FillThisBuffer(ilclient_get_handle(component), 97 | buff_header); 98 | if (r != OMX_ErrorNone) { 99 | fprintf(stderr, "Fill buffer error %s\n", 100 | err2str(r)); 101 | } 102 | return r; 103 | } 104 | 105 | void get_output_port_settings(COMPONENT_T *component) { 106 | OMX_PARAM_PORTDEFINITIONTYPE portdef; 107 | 108 | printf("Port settings changed\n"); 109 | // need to setup the input for the resizer with the output of the 110 | // decoder 111 | portdef.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE); 112 | portdef.nVersion.nVersion = OMX_VERSION; 113 | portdef.nPortIndex = 131; 114 | OMX_GetParameter(ilclient_get_handle(component), 115 | OMX_IndexParamPortDefinition, &portdef); 116 | 117 | unsigned int uWidth = 118 | (unsigned int) portdef.format.video.nFrameWidth; 119 | unsigned int uHeight = 120 | (unsigned int) portdef.format.video.nFrameHeight; 121 | unsigned int uStride = 122 | (unsigned int) portdef.format.video.nStride; 123 | unsigned int uSliceHeight = 124 | (unsigned int) portdef.format.video.nSliceHeight; 125 | printf("Frame width %d, frame height %d, stride %d, slice height %d\n", 126 | uWidth, 127 | uHeight, 128 | uStride, 129 | uSliceHeight); 130 | printf("Getting format Compression 0x%x Color Format: 0x%x\n", 131 | (unsigned int) portdef.format.video.eCompressionFormat, 132 | (unsigned int) portdef.format.video.eColorFormat); 133 | } 134 | 135 | int main(int argc, char** argv) { 136 | 137 | int i; 138 | char *componentName; 139 | int err; 140 | ILCLIENT_T *handle; 141 | COMPONENT_T *component; 142 | FILE *fp = fopen(IMG, "r"); 143 | int toread = get_file_size(IMG); 144 | OMX_BUFFERHEADERTYPE *buff_header; 145 | 146 | componentName = "video_decode"; 147 | 148 | 149 | bcm_host_init(); 150 | 151 | handle = ilclient_init(); 152 | if (handle == NULL) { 153 | fprintf(stderr, "IL client init failed\n"); 154 | exit(1); 155 | } 156 | 157 | if (OMX_Init() != OMX_ErrorNone) { 158 | ilclient_destroy(handle); 159 | fprintf(stderr, "OMX init failed\n"); 160 | exit(1); 161 | } 162 | 163 | ilclient_set_error_callback(handle, 164 | error_callback, 165 | NULL); 166 | ilclient_set_eos_callback(handle, 167 | eos_callback, 168 | NULL); 169 | 170 | 171 | err = ilclient_create_component(handle, 172 | &component, 173 | componentName, 174 | ILCLIENT_DISABLE_ALL_PORTS 175 | | 176 | ILCLIENT_ENABLE_INPUT_BUFFERS 177 | | 178 | ILCLIENT_ENABLE_OUTPUT_BUFFERS 179 | ); 180 | if (err == -1) { 181 | fprintf(stderr, "Component create failed\n"); 182 | exit(1); 183 | } 184 | printState(ilclient_get_handle(component)); 185 | 186 | err = ilclient_change_component_state(component, 187 | OMX_StateIdle); 188 | if (err < 0) { 189 | fprintf(stderr, "Couldn't change state to Idle\n"); 190 | exit(1); 191 | } 192 | printState(ilclient_get_handle(component)); 193 | 194 | // must be before we enable buffers 195 | set_video_decoder_input_format(component); 196 | 197 | // input port 198 | ilclient_enable_port_buffers(component, 130, 199 | NULL, NULL, NULL); 200 | ilclient_enable_port(component, 130); 201 | 202 | 203 | 204 | 205 | err = ilclient_change_component_state(component, 206 | OMX_StateExecuting); 207 | if (err < 0) { 208 | fprintf(stderr, "Couldn't change state to Executing\n"); 209 | exit(1); 210 | } 211 | printState(ilclient_get_handle(component)); 212 | 213 | 214 | // Read the first block so that the component can get 215 | // the dimensions of the video and call port settings 216 | // changed on the output port to configure it 217 | int port_settings_changed = 0; 218 | while (!port_settings_changed) { 219 | buff_header = 220 | ilclient_get_input_buffer(component, 221 | 130, 222 | 1 /* block */); 223 | if (buff_header != NULL) { 224 | read_into_buffer_and_empty(fp, 225 | component, 226 | buff_header, 227 | &toread); 228 | 229 | // If all the file has been read in, then 230 | // we have to re-read this first block. 231 | // Broadcom bug? 232 | if (toread <= 0) { 233 | printf("Rewinding\n"); 234 | // wind back to start and repeat 235 | fp = freopen(IMG, "r", fp); 236 | toread = get_file_size(IMG); 237 | } 238 | } 239 | 240 | // wait for first input block to set params for output port 241 | err = ilclient_wait_for_event(component, 242 | OMX_EventPortSettingsChanged, 243 | 131, 0, 0, 1, 244 | ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 245 | 2000); 246 | if (err < 0) { 247 | printf("Wait for port settings changed timed out\n"); 248 | } else { 249 | port_settings_changed = 1; 250 | } 251 | err = ilclient_remove_event(component, 252 | OMX_EventPortSettingsChanged, 253 | 131, 0, 0, 1); 254 | if (err < 0) { 255 | printf("Wait for remove port settings changed timed out\n"); 256 | } else { 257 | port_settings_changed = 1; 258 | } 259 | } 260 | 261 | get_output_port_settings(component); 262 | 263 | // now enable output port since port params have been set 264 | ilclient_enable_port_buffers(component, 131, 265 | NULL, NULL, NULL); 266 | ilclient_enable_port(component, 131); 267 | 268 | // now work through the file 269 | while (toread > 0) { 270 | OMX_ERRORTYPE r; 271 | 272 | // do we have an input buffer we can fill and empty? 273 | buff_header = 274 | ilclient_get_input_buffer(component, 275 | 130, 276 | 1 /* block */); 277 | if (buff_header != NULL) { 278 | read_into_buffer_and_empty(fp, 279 | component, 280 | buff_header, 281 | &toread); 282 | } 283 | 284 | // do we have an output buffer that has been filled? 285 | buff_header = 286 | ilclient_get_output_buffer(component, 287 | 131, 288 | 0 /* no block */); 289 | if (buff_header != NULL) { 290 | save_info_from_filled_buffer(component, 291 | buff_header); 292 | } else { 293 | printf("No filled buffer\n"); 294 | } 295 | } 296 | 297 | while (1) { 298 | printf("Getting last output buffers\n"); 299 | buff_header = 300 | ilclient_get_output_buffer(component, 301 | 131, 302 | 1 /* block */); 303 | if (buff_header != NULL) { 304 | save_info_from_filled_buffer(component, 305 | buff_header); 306 | } 307 | } 308 | exit(0); 309 | } 310 | -------------------------------------------------------------------------------- /OpenMAX/Video/il_render_video.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #define IMG "/opt/vc/src/hello_pi/hello_video/test.h264" 12 | 13 | void printState(OMX_HANDLETYPE handle) { 14 | // elided 15 | } 16 | 17 | char *err2str(int err) { 18 | return "elided"; 19 | } 20 | 21 | void eos_callback(void *userdata, COMPONENT_T *comp, OMX_U32 data) { 22 | fprintf(stderr, "Got eos event\n"); 23 | } 24 | 25 | void error_callback(void *userdata, COMPONENT_T *comp, OMX_U32 data) { 26 | fprintf(stderr, "OMX error %s\n", err2str(data)); 27 | } 28 | 29 | int get_file_size(char *fname) { 30 | struct stat st; 31 | 32 | if (stat(fname, &st) == -1) { 33 | perror("Stat'ing img file"); 34 | return -1; 35 | } 36 | return(st.st_size); 37 | } 38 | 39 | unsigned int uWidth; 40 | unsigned int uHeight; 41 | 42 | OMX_ERRORTYPE read_into_buffer_and_empty(FILE *fp, 43 | COMPONENT_T *component, 44 | OMX_BUFFERHEADERTYPE *buff_header, 45 | int *toread) { 46 | OMX_ERRORTYPE r; 47 | 48 | int buff_size = buff_header->nAllocLen; 49 | int nread = fread(buff_header->pBuffer, 1, buff_size, fp); 50 | 51 | 52 | buff_header->nFilledLen = nread; 53 | *toread -= nread; 54 | printf("Read %d, %d still left\n", nread, *toread); 55 | 56 | if (*toread <= 0) { 57 | printf("Setting EOS on input\n"); 58 | buff_header->nFlags |= OMX_BUFFERFLAG_EOS; 59 | } 60 | r = OMX_EmptyThisBuffer(ilclient_get_handle(component), 61 | buff_header); 62 | if (r != OMX_ErrorNone) { 63 | fprintf(stderr, "Empty buffer error %s\n", 64 | err2str(r)); 65 | } 66 | return r; 67 | } 68 | 69 | static void set_video_decoder_input_format(COMPONENT_T *component) { 70 | int err; 71 | 72 | // set input video format 73 | printf("Setting video decoder format\n"); 74 | OMX_VIDEO_PARAM_PORTFORMATTYPE videoPortFormat; 75 | //setHeader(&videoPortFormat, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 76 | memset(&videoPortFormat, 0, sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE)); 77 | videoPortFormat.nSize = sizeof(OMX_VIDEO_PARAM_PORTFORMATTYPE); 78 | videoPortFormat.nVersion.nVersion = OMX_VERSION; 79 | 80 | videoPortFormat.nPortIndex = 130; 81 | videoPortFormat.eCompressionFormat = OMX_VIDEO_CodingAVC; 82 | 83 | err = OMX_SetParameter(ilclient_get_handle(component), 84 | OMX_IndexParamVideoPortFormat, &videoPortFormat); 85 | if (err != OMX_ErrorNone) { 86 | fprintf(stderr, "Error setting video decoder format %s\n", err2str(err)); 87 | return err; 88 | } else { 89 | printf("Video decoder format set up ok\n"); 90 | } 91 | 92 | 93 | } 94 | 95 | void setup_decodeComponent(ILCLIENT_T *handle, 96 | char *decodeComponentName, 97 | COMPONENT_T **decodeComponent) { 98 | int err; 99 | 100 | err = ilclient_create_component(handle, 101 | decodeComponent, 102 | decodeComponentName, 103 | ILCLIENT_DISABLE_ALL_PORTS 104 | | 105 | ILCLIENT_ENABLE_INPUT_BUFFERS 106 | | 107 | ILCLIENT_ENABLE_OUTPUT_BUFFERS 108 | ); 109 | if (err == -1) { 110 | fprintf(stderr, "DecodeComponent create failed\n"); 111 | exit(1); 112 | } 113 | printState(ilclient_get_handle(*decodeComponent)); 114 | 115 | err = ilclient_change_component_state(*decodeComponent, 116 | OMX_StateIdle); 117 | if (err < 0) { 118 | fprintf(stderr, "Couldn't change state to Idle\n"); 119 | exit(1); 120 | } 121 | printState(ilclient_get_handle(*decodeComponent)); 122 | 123 | // must be before we enable buffers 124 | set_video_decoder_input_format(*decodeComponent); 125 | } 126 | 127 | void setup_renderComponent(ILCLIENT_T *handle, 128 | char *renderComponentName, 129 | COMPONENT_T **renderComponent) { 130 | int err; 131 | 132 | err = ilclient_create_component(handle, 133 | renderComponent, 134 | renderComponentName, 135 | ILCLIENT_DISABLE_ALL_PORTS 136 | | 137 | ILCLIENT_ENABLE_INPUT_BUFFERS 138 | ); 139 | if (err == -1) { 140 | fprintf(stderr, "RenderComponent create failed\n"); 141 | exit(1); 142 | } 143 | printState(ilclient_get_handle(*renderComponent)); 144 | 145 | err = ilclient_change_component_state(*renderComponent, 146 | OMX_StateIdle); 147 | if (err < 0) { 148 | fprintf(stderr, "Couldn't change state to Idle\n"); 149 | exit(1); 150 | } 151 | printState(ilclient_get_handle(*renderComponent)); 152 | } 153 | 154 | int main(int argc, char** argv) { 155 | 156 | int i; 157 | char *decodeComponentName; 158 | char *renderComponentName; 159 | int err; 160 | ILCLIENT_T *handle; 161 | COMPONENT_T *decodeComponent; 162 | COMPONENT_T *renderComponent; 163 | FILE *fp = fopen(IMG, "r"); 164 | int toread = get_file_size(IMG); 165 | OMX_BUFFERHEADERTYPE *buff_header; 166 | 167 | decodeComponentName = "video_decode"; 168 | renderComponentName = "video_render"; 169 | 170 | bcm_host_init(); 171 | 172 | handle = ilclient_init(); 173 | if (handle == NULL) { 174 | fprintf(stderr, "IL client init failed\n"); 175 | exit(1); 176 | } 177 | 178 | if (OMX_Init() != OMX_ErrorNone) { 179 | ilclient_destroy(handle); 180 | fprintf(stderr, "OMX init failed\n"); 181 | exit(1); 182 | } 183 | 184 | ilclient_set_error_callback(handle, 185 | error_callback, 186 | NULL); 187 | ilclient_set_eos_callback(handle, 188 | eos_callback, 189 | NULL); 190 | 191 | 192 | setup_decodeComponent(handle, decodeComponentName, &decodeComponent); 193 | setup_renderComponent(handle, renderComponentName, &renderComponent); 194 | // both components now in Idle state, no buffers, ports disabled 195 | 196 | // input port 197 | ilclient_enable_port_buffers(decodeComponent, 130, 198 | NULL, NULL, NULL); 199 | ilclient_enable_port(decodeComponent, 130); 200 | 201 | 202 | err = ilclient_change_component_state(decodeComponent, 203 | OMX_StateExecuting); 204 | if (err < 0) { 205 | fprintf(stderr, "Couldn't change state to Executing\n"); 206 | exit(1); 207 | } 208 | printState(ilclient_get_handle(decodeComponent)); 209 | 210 | 211 | // Read the first block so that the decodeComponent can get 212 | // the dimensions of the video and call port settings 213 | // changed on the output port to configure it 214 | while (toread > 0) { 215 | buff_header = 216 | ilclient_get_input_buffer(decodeComponent, 217 | 130, 218 | 1 /* block */); 219 | if (buff_header != NULL) { 220 | read_into_buffer_and_empty(fp, 221 | decodeComponent, 222 | buff_header, 223 | &toread); 224 | 225 | // If all the file has been read in, then 226 | // we have to re-read this first block. 227 | // Broadcom bug? 228 | if (toread <= 0) { 229 | printf("Rewinding\n"); 230 | // wind back to start and repeat 231 | fp = freopen(IMG, "r", fp); 232 | toread = get_file_size(IMG); 233 | } 234 | } 235 | 236 | if (toread > 0 && ilclient_remove_event(decodeComponent, 237 | OMX_EventPortSettingsChanged, 238 | 131, 0, 0, 1) == 0) { 239 | printf("Removed port settings event\n"); 240 | break; 241 | } else { 242 | printf("No portr settting seen yet\n"); 243 | } 244 | // wait for first input block to set params for output port 245 | if (toread == 0) { 246 | // wait for first input block to set params for output port 247 | err = ilclient_wait_for_event(decodeComponent, 248 | OMX_EventPortSettingsChanged, 249 | 131, 0, 0, 1, 250 | ILCLIENT_EVENT_ERROR | ILCLIENT_PARAMETER_CHANGED, 251 | 2000); 252 | if (err < 0) { 253 | fprintf(stderr, "No port settings change\n"); 254 | //exit(1); 255 | } else { 256 | printf("Port settings changed\n"); 257 | break; 258 | } 259 | } 260 | } 261 | 262 | // set the decode component to idle and disable its ports 263 | err = ilclient_change_component_state(decodeComponent, 264 | OMX_StateIdle); 265 | if (err < 0) { 266 | fprintf(stderr, "Couldn't change state to Idle\n"); 267 | exit(1); 268 | } 269 | ilclient_disable_port(decodeComponent, 131); 270 | ilclient_disable_port_buffers(decodeComponent, 131, 271 | NULL, NULL, NULL); 272 | 273 | // set up the tunnel between decode and render ports 274 | err = OMX_SetupTunnel(ilclient_get_handle(decodeComponent), 275 | 131, 276 | ilclient_get_handle(renderComponent), 277 | 90); 278 | if (err != OMX_ErrorNone) { 279 | fprintf(stderr, "Error setting up tunnel %X\n", err); 280 | exit(1); 281 | } else { 282 | printf("Tunnel set up ok\n"); 283 | } 284 | 285 | // Okay to go back to processing data 286 | // enable the decode output ports 287 | 288 | OMX_SendCommand(ilclient_get_handle(decodeComponent), 289 | OMX_CommandPortEnable, 131, NULL); 290 | 291 | ilclient_enable_port(decodeComponent, 131); 292 | 293 | // enable the render output ports 294 | 295 | OMX_SendCommand(ilclient_get_handle(renderComponent), 296 | OMX_CommandPortEnable, 90, NULL); 297 | 298 | ilclient_enable_port(renderComponent, 90); 299 | 300 | // set both components to executing state 301 | err = ilclient_change_component_state(decodeComponent, 302 | OMX_StateExecuting); 303 | if (err < 0) { 304 | fprintf(stderr, "Couldn't change state to Idle\n"); 305 | exit(1); 306 | } 307 | err = ilclient_change_component_state(renderComponent, 308 | OMX_StateExecuting); 309 | if (err < 0) { 310 | fprintf(stderr, "Couldn't change state to Idle\n"); 311 | exit(1); 312 | } 313 | 314 | // now work through the file 315 | while (toread > 0) { 316 | OMX_ERRORTYPE r; 317 | 318 | // do we have a decode input buffer we can fill and empty? 319 | buff_header = 320 | ilclient_get_input_buffer(decodeComponent, 321 | 130, 322 | 1 /* block */); 323 | if (buff_header != NULL) { 324 | read_into_buffer_and_empty(fp, 325 | decodeComponent, 326 | buff_header, 327 | &toread); 328 | } 329 | } 330 | 331 | ilclient_wait_for_event(renderComponent, 332 | OMX_EventBufferFlag, 333 | 90, 0, OMX_BUFFERFLAG_EOS, 0, 334 | ILCLIENT_BUFFER_FLAG_EOS, 10000); 335 | printf("EOS on render\n"); 336 | 337 | sleep(100); 338 | 339 | exit(0); 340 | } 341 | -------------------------------------------------------------------------------- /OpenVG/Basic/ellipse.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | //#include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | typedef struct 16 | { 17 | EGLDisplay display; 18 | EGLSurface surface; 19 | EGLContext context; 20 | EGLConfig config; 21 | } EGL_STATE_T; 22 | 23 | 24 | EGL_STATE_T state, *p_state = &state; 25 | 26 | 27 | void init_egl(EGL_STATE_T *state) 28 | { 29 | EGLint num_configs; 30 | EGLBoolean result; 31 | 32 | //bcm_host_init(); 33 | 34 | static const EGLint attribute_list[] = 35 | { 36 | EGL_RED_SIZE, 8, 37 | EGL_GREEN_SIZE, 8, 38 | EGL_BLUE_SIZE, 8, 39 | EGL_ALPHA_SIZE, 8, 40 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 41 | EGL_SAMPLES, 1, 42 | EGL_NONE 43 | }; 44 | 45 | static const EGLint context_attributes[] = 46 | { 47 | EGL_CONTEXT_CLIENT_VERSION, 2, 48 | EGL_NONE 49 | }; 50 | 51 | // get an EGL display connection 52 | state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 53 | 54 | // initialize the EGL display connection 55 | result = eglInitialize(state->display, NULL, NULL); 56 | 57 | // get an appropriate EGL frame buffer configuration 58 | result = eglChooseConfig(state->display, attribute_list, &state->config, 1, &num_configs); 59 | assert(EGL_FALSE != result); 60 | 61 | // Choose the OpenVG API 62 | result = eglBindAPI(EGL_OPENVG_API); 63 | assert(EGL_FALSE != result); 64 | 65 | // create an EGL rendering context 66 | state->context = eglCreateContext(state->display, 67 | state->config, 68 | NULL, // EGL_NO_CONTEXT, 69 | NULL); 70 | // breaks if we use this: context_attributes); 71 | assert(state->context!=EGL_NO_CONTEXT); 72 | } 73 | 74 | void init_dispmanx(EGL_DISPMANX_WINDOW_T *nativewindow) { 75 | int32_t success = 0; 76 | uint32_t screen_width; 77 | uint32_t screen_height; 78 | 79 | DISPMANX_ELEMENT_HANDLE_T dispman_element; 80 | DISPMANX_DISPLAY_HANDLE_T dispman_display; 81 | DISPMANX_UPDATE_HANDLE_T dispman_update; 82 | VC_RECT_T dst_rect; 83 | VC_RECT_T src_rect; 84 | 85 | bcm_host_init(); 86 | 87 | // create an EGL window surface 88 | success = graphics_get_display_size(0 /* LCD */, 89 | &screen_width, 90 | &screen_height); 91 | assert( success >= 0 ); 92 | 93 | dst_rect.x = 0; 94 | dst_rect.y = 0; 95 | dst_rect.width = screen_width; 96 | dst_rect.height = screen_height; 97 | 98 | src_rect.x = 0; 99 | src_rect.y = 0; 100 | src_rect.width = screen_width << 16; 101 | src_rect.height = screen_height << 16; 102 | 103 | dispman_display = vc_dispmanx_display_open( 0 /* LCD */); 104 | dispman_update = vc_dispmanx_update_start( 0 ); 105 | 106 | dispman_element = 107 | vc_dispmanx_element_add(dispman_update, dispman_display, 108 | 0 /*layer*/, &dst_rect, 0 /*src*/, 109 | &src_rect, DISPMANX_PROTECTION_NONE, 110 | 0 /*alpha*/, 0 /*clamp*/, 0 /*transform*/); 111 | 112 | // Build an EGL_DISPMANX_WINDOW_T from the Dispmanx window 113 | nativewindow->element = dispman_element; 114 | nativewindow->width = screen_width; 115 | nativewindow->height = screen_height; 116 | vc_dispmanx_update_submit_sync(dispman_update); 117 | 118 | printf("Got a Dispmanx window\n"); 119 | } 120 | 121 | void egl_from_dispmanx(EGL_STATE_T *state, 122 | EGL_DISPMANX_WINDOW_T *nativewindow) { 123 | EGLBoolean result; 124 | static const EGLint attribute_list[] = 125 | { 126 | EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER, 127 | EGL_NONE 128 | }; 129 | 130 | state->surface = eglCreateWindowSurface(state->display, 131 | state->config, 132 | nativewindow, 133 | NULL ); 134 | //attribute_list); 135 | assert(state->surface != EGL_NO_SURFACE); 136 | 137 | // connect the context to the surface 138 | result = eglMakeCurrent(state->display, state->surface, state->surface, state->context); 139 | assert(EGL_FALSE != result); 140 | } 141 | 142 | // setfill sets the fill color 143 | void setfill(float color[4]) { 144 | VGPaint fillPaint = vgCreatePaint(); 145 | vgSetParameteri(fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); 146 | vgSetParameterfv(fillPaint, VG_PAINT_COLOR, 4, color); 147 | vgSetPaint(fillPaint, VG_FILL_PATH); 148 | vgDestroyPaint(fillPaint); 149 | } 150 | 151 | 152 | // setstroke sets the stroke color and width 153 | void setstroke(float color[4], float width) { 154 | VGPaint strokePaint = vgCreatePaint(); 155 | vgSetParameteri(strokePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); 156 | vgSetParameterfv(strokePaint, VG_PAINT_COLOR, 4, color); 157 | vgSetPaint(strokePaint, VG_STROKE_PATH); 158 | vgSetf(VG_STROKE_LINE_WIDTH, width); 159 | vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_BUTT); 160 | vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_MITER); 161 | vgDestroyPaint(strokePaint); 162 | } 163 | 164 | // Ellipse makes an ellipse at the specified location and dimensions, applying style 165 | void Ellipse(float x, float y, float w, float h, float sw, float fill[4], float stroke[4]) { 166 | VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL); 167 | vguEllipse(path, x, y, w, h); 168 | setfill(fill); 169 | setstroke(stroke, sw); 170 | vgDrawPath(path, VG_FILL_PATH | VG_STROKE_PATH); 171 | vgDestroyPath(path); 172 | } 173 | 174 | void draw() { 175 | EGL_DISPMANX_WINDOW_T nativewindow; 176 | 177 | init_egl(p_state); 178 | init_dispmanx(&nativewindow); 179 | 180 | egl_from_dispmanx(p_state, &nativewindow); 181 | 182 | vgClear(0, 0, 1920, 1080); 183 | 184 | VGfloat color[4] = {0.4, 0.1, 1.0, 1.0}; // purple 185 | float c = 1.0; 186 | float clearColor[4] = {c, c, c, c}; // white non-transparent 187 | vgSetfv(VG_CLEAR_COLOR, 4, clearColor); 188 | vgClear(0, 0, 1920, 1080); 189 | 190 | vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER); 191 | static float ht = 200; 192 | while (1) { 193 | vgClear(0, 0, 1920, 1080); 194 | Ellipse(1920/2, 1080/2, 400, ht--, 0, color, color); 195 | if (ht <= 0) { 196 | ht = 200; 197 | } 198 | eglSwapBuffers(p_state->display, p_state->surface); 199 | } 200 | assert(vgGetError() == VG_NO_ERROR); 201 | 202 | vgFlush(); 203 | 204 | eglSwapBuffers(p_state->display, p_state->surface); 205 | } 206 | 207 | void sig_handler(int sig) { 208 | eglTerminate(p_state->display); 209 | exit(1); 210 | } 211 | 212 | int main(int argc, char** argv) { 213 | signal(SIGINT, sig_handler); 214 | 215 | draw(); 216 | 217 | exit(0); 218 | } 219 | -------------------------------------------------------------------------------- /OpenVG/Basic/image.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | typedef struct 16 | { 17 | EGLDisplay display; 18 | EGLSurface surface; 19 | EGLContext context; 20 | EGLConfig config; 21 | } EGL_STATE_T; 22 | 23 | struct egl_manager { 24 | EGLNativeDisplayType xdpy; 25 | EGLNativeWindowType xwin; 26 | EGLNativePixmapType xpix; 27 | 28 | EGLDisplay dpy; 29 | EGLConfig conf; 30 | EGLContext ctx; 31 | 32 | EGLSurface win; 33 | EGLSurface pix; 34 | EGLSurface pbuf; 35 | EGLImageKHR image; 36 | 37 | EGLBoolean verbose; 38 | EGLint major, minor; 39 | }; 40 | 41 | EGL_STATE_T state, *p_state = &state; 42 | 43 | 44 | void init_egl(EGL_STATE_T *state) 45 | { 46 | EGLint num_configs; 47 | EGLBoolean result; 48 | 49 | //bcm_host_init(); 50 | 51 | static const EGLint attribute_list[] = 52 | { 53 | EGL_RED_SIZE, 5, 54 | EGL_GREEN_SIZE, 6, 55 | EGL_BLUE_SIZE, 5, 56 | EGL_ALPHA_SIZE, 0, 57 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 58 | EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, 59 | EGL_NONE 60 | }; 61 | 62 | static const EGLint context_attributes[] = 63 | { 64 | EGL_CONTEXT_CLIENT_VERSION, 2, 65 | EGL_NONE 66 | }; 67 | 68 | // get an EGL display connection 69 | state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 70 | 71 | // initialize the EGL display connection 72 | result = eglInitialize(state->display, NULL, NULL); 73 | 74 | // get an appropriate EGL frame buffer configuration 75 | result = eglChooseConfig(state->display, attribute_list, &state->config, 1, &num_configs); 76 | assert(EGL_FALSE != result); 77 | 78 | result = eglBindAPI(EGL_OPENVG_API); 79 | assert(EGL_FALSE != result); 80 | 81 | // create an EGL rendering context 82 | state->context = eglCreateContext(state->display, 83 | state->config, EGL_NO_CONTEXT, 84 | NULL); 85 | // breaks if we use this: context_attributes); 86 | assert(state->context!=EGL_NO_CONTEXT); 87 | } 88 | 89 | void init_dispmanx(EGL_DISPMANX_WINDOW_T *nativewindow) { 90 | int32_t success = 0; 91 | uint32_t screen_width; 92 | uint32_t screen_height; 93 | 94 | DISPMANX_ELEMENT_HANDLE_T dispman_element; 95 | DISPMANX_DISPLAY_HANDLE_T dispman_display; 96 | DISPMANX_UPDATE_HANDLE_T dispman_update; 97 | VC_RECT_T dst_rect; 98 | VC_RECT_T src_rect; 99 | 100 | bcm_host_init(); 101 | 102 | // create an EGL window surface 103 | success = graphics_get_display_size(0 /* LCD */, 104 | &screen_width, 105 | &screen_height); 106 | assert( success >= 0 ); 107 | 108 | dst_rect.x = 0; 109 | dst_rect.y = 0; 110 | dst_rect.width = screen_width; 111 | dst_rect.height = screen_height; 112 | 113 | src_rect.x = 0; 114 | src_rect.y = 0; 115 | src_rect.width = screen_width << 16; 116 | src_rect.height = screen_height << 16; 117 | 118 | dispman_display = vc_dispmanx_display_open( 0 /* LCD */); 119 | dispman_update = vc_dispmanx_update_start( 0 ); 120 | 121 | dispman_element = 122 | vc_dispmanx_element_add(dispman_update, dispman_display, 123 | 0/*layer*/, &dst_rect, 0/*src*/, 124 | &src_rect, DISPMANX_PROTECTION_NONE, 125 | 0 /*alpha*/, 0/*clamp*/, 0/*transform*/); 126 | 127 | // Build an EGL_DISPMANX_WINDOW_T from the Dispmanx window 128 | nativewindow->element = dispman_element; 129 | nativewindow->width = screen_width; 130 | nativewindow->height = screen_height; 131 | vc_dispmanx_update_submit_sync(dispman_update); 132 | 133 | printf("Got a Dispmanx window\n"); 134 | } 135 | 136 | void egl_from_dispmanx(EGL_STATE_T *state, 137 | EGL_DISPMANX_WINDOW_T *nativewindow) { 138 | EGLBoolean result; 139 | 140 | state->surface = eglCreateWindowSurface(state->display, 141 | state->config, 142 | nativewindow, NULL ); 143 | assert(state->surface != EGL_NO_SURFACE); 144 | 145 | // connect the context to the surface 146 | result = eglMakeCurrent(state->display, state->surface, state->surface, state->context); 147 | assert(EGL_FALSE != result); 148 | } 149 | 150 | void simple_image() { 151 | VGImage img; 152 | img = vgCreateImage(VG_sL_8, 153 | 256, 256, 154 | VG_IMAGE_QUALITY_NONANTIALIASED); 155 | if (img == VG_INVALID_HANDLE) { 156 | fprintf(stderr, "Can't create simple image\n"); 157 | fprintf(stderr, "Error code %x\n", vgGetError()); 158 | exit(2); 159 | } 160 | unsigned char val; 161 | unsigned char data[256*256]; 162 | int n; 163 | 164 | for (n = 0; n < 256*256; n++) { 165 | val = (unsigned char) n; 166 | data[n] = val; 167 | } 168 | vgImageSubData(img, data, 169 | 256, VG_sL_8, 170 | 0, 0, 256, 256); 171 | vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); 172 | vgLoadIdentity(); 173 | vgTranslate(200, 30); 174 | 175 | vgDrawImage(img); 176 | 177 | vgDestroyImage(img); 178 | } 179 | 180 | // setfill sets the fill color 181 | void setfill(float color[4]) { 182 | VGPaint fillPaint = vgCreatePaint(); 183 | vgSetParameteri(fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); 184 | vgSetParameterfv(fillPaint, VG_PAINT_COLOR, 4, color); 185 | //vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY); 186 | vgSetPaint(fillPaint, VG_FILL_PATH); 187 | vgDestroyPaint(fillPaint); 188 | } 189 | 190 | VGfloat drawn_color[4] = {0.0, 0.0, 1.0, 1.0}; 191 | 192 | void drawn_image() { 193 | EGLSurface img_surface; 194 | VGImage drawn_image; 195 | EGLContext context; 196 | 197 | static const EGLint attribute_list[] = 198 | { 199 | //EGL_COLOR_BUFFER_TYPE, EGL_LUMINANCE_BUFFER, 200 | // EGL_LUMINANCE_SIZE, 8, 201 | EGL_RED_SIZE, 8, 202 | EGL_GREEN_SIZE, 8, 203 | EGL_BLUE_SIZE, 8, 204 | EGL_ALPHA_SIZE, 8, 205 | EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, 206 | EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, 207 | EGL_NONE 208 | }; 209 | EGLConfig config; 210 | 211 | drawn_image = vgCreateImage(VG_sRGBA_8888, 212 | 256, 256, 213 | VG_IMAGE_QUALITY_NONANTIALIASED); 214 | if (drawn_image == VG_INVALID_HANDLE) { 215 | fprintf(stderr, "Can't create drawn image\n"); 216 | fprintf(stderr, "Error code %x\n", vgGetError()); 217 | exit(2); 218 | } 219 | vgClearImage(drawn_image, 0, 0, 256, 256); 220 | 221 | int result, num_configs; 222 | result = eglChooseConfig(p_state->display, 223 | attribute_list, 224 | &config, 225 | 1, 226 | &num_configs); 227 | assert(EGL_FALSE != result); 228 | context = eglCreateContext(p_state->display, 229 | config, EGL_NO_CONTEXT, 230 | NULL); 231 | 232 | img_surface = eglCreatePbufferFromClientBuffer(p_state->display, 233 | EGL_OPENVG_IMAGE, 234 | (EGLClientBuffer) drawn_image, 235 | config, 236 | NULL); 237 | if (img_surface == EGL_NO_SURFACE) { 238 | fprintf(stderr, "Couldn't create pbuffer\n"); 239 | fprintf(stderr, "Error code %x\n", eglGetError()); 240 | exit(1); 241 | } 242 | eglMakeCurrent(p_state->display, img_surface, img_surface, 243 | context); //p_state->context); 244 | 245 | VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, 246 | VG_PATH_DATATYPE_F, 1.0f, 247 | 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL); 248 | 249 | float height = 40.0; 250 | float arcW = 15.0; 251 | float arcH = 15.0; 252 | 253 | vguRoundRect(path, 28, 10, 254 | 200, 60, arcW, arcH); 255 | vguEllipse(path, 128, 200, 60, 40); 256 | 257 | setfill(drawn_color); 258 | vgDrawPath(path, VG_FILL_PATH); 259 | 260 | eglMakeCurrent(p_state->display, p_state->surface, 261 | p_state->surface, 262 | p_state->context); 263 | 264 | vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); 265 | vgLoadIdentity(); 266 | vgTranslate(800, 300); 267 | 268 | vgDrawImage(drawn_image); 269 | 270 | vgDestroyImage(drawn_image); 271 | } 272 | 273 | void draw(){ 274 | float c = 1.0; 275 | float clearColor[4] = {c, c, c, c}; // white, no transparency 276 | vgSetfv(VG_CLEAR_COLOR, 4, clearColor); 277 | 278 | vgClear(0, 0, 1920, 1080); 279 | 280 | simple_image(); 281 | 282 | drawn_image(); 283 | 284 | vgFlush(); 285 | } 286 | 287 | int 288 | main(int argc, char *argv[]) 289 | { 290 | EGL_DISPMANX_WINDOW_T nativewindow; 291 | 292 | init_egl(p_state); 293 | init_dispmanx(&nativewindow); 294 | egl_from_dispmanx(p_state, &nativewindow); 295 | 296 | draw(); 297 | eglSwapBuffers(p_state->display, p_state->surface); 298 | 299 | sleep(100); 300 | 301 | eglTerminate(p_state->display); 302 | exit(0); 303 | } 304 | -------------------------------------------------------------------------------- /OpenVG/Basic/simple_shape.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * code adapted from openGL-RPi-tutorial-master/encode_OGL/ 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | typedef struct 22 | { 23 | EGLDisplay display; 24 | EGLSurface surface; 25 | EGLContext context; 26 | EGLConfig config; 27 | } EGL_STATE_T; 28 | 29 | struct egl_manager { 30 | EGLNativeDisplayType xdpy; 31 | EGLNativeWindowType xwin; 32 | EGLNativePixmapType xpix; 33 | 34 | EGLDisplay dpy; 35 | EGLConfig conf; 36 | EGLContext ctx; 37 | 38 | EGLSurface win; 39 | EGLSurface pix; 40 | EGLSurface pbuf; 41 | EGLImageKHR image; 42 | 43 | EGLBoolean verbose; 44 | EGLint major, minor; 45 | 46 | GC gc; 47 | GLuint fbo; 48 | }; 49 | 50 | EGL_STATE_T state, *p_state = &state; 51 | 52 | 53 | void init_egl(EGL_STATE_T *state) 54 | { 55 | EGLint num_configs; 56 | EGLBoolean result; 57 | 58 | //bcm_host_init(); 59 | 60 | static const EGLint attribute_list[] = 61 | { 62 | EGL_RED_SIZE, 8, 63 | EGL_GREEN_SIZE, 8, 64 | EGL_BLUE_SIZE, 8, 65 | EGL_ALPHA_SIZE, 8, 66 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 67 | EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, 68 | EGL_NONE 69 | }; 70 | 71 | static const EGLint context_attributes[] = 72 | { 73 | EGL_CONTEXT_CLIENT_VERSION, 2, 74 | EGL_NONE 75 | }; 76 | 77 | // get an EGL display connection 78 | state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 79 | 80 | // initialize the EGL display connection 81 | result = eglInitialize(state->display, NULL, NULL); 82 | 83 | // get an appropriate EGL frame buffer configuration 84 | result = eglChooseConfig(state->display, attribute_list, &state->config, 1, &num_configs); 85 | assert(EGL_FALSE != result); 86 | 87 | //result = eglBindAPI(EGL_OPENGL_ES_API); 88 | result = eglBindAPI(EGL_OPENVG_API); 89 | assert(EGL_FALSE != result); 90 | 91 | // create an EGL rendering context 92 | state->context = eglCreateContext(state->display, 93 | state->config, EGL_NO_CONTEXT, 94 | NULL); 95 | // breaks if we use this: context_attributes); 96 | assert(state->context!=EGL_NO_CONTEXT); 97 | } 98 | 99 | void init_dispmanx(EGL_DISPMANX_WINDOW_T *nativewindow) { 100 | int32_t success = 0; 101 | uint32_t screen_width; 102 | uint32_t screen_height; 103 | 104 | DISPMANX_ELEMENT_HANDLE_T dispman_element; 105 | DISPMANX_DISPLAY_HANDLE_T dispman_display; 106 | DISPMANX_UPDATE_HANDLE_T dispman_update; 107 | VC_RECT_T dst_rect; 108 | VC_RECT_T src_rect; 109 | 110 | bcm_host_init(); 111 | 112 | // create an EGL window surface 113 | success = graphics_get_display_size(0 /* LCD */, 114 | &screen_width, 115 | &screen_height); 116 | assert( success >= 0 ); 117 | 118 | dst_rect.x = 0; 119 | dst_rect.y = 0; 120 | dst_rect.width = screen_width; 121 | dst_rect.height = screen_height; 122 | 123 | src_rect.x = 0; 124 | src_rect.y = 0; 125 | src_rect.width = screen_width << 16; 126 | src_rect.height = screen_height << 16; 127 | 128 | dispman_display = vc_dispmanx_display_open( 0 /* LCD */); 129 | dispman_update = vc_dispmanx_update_start( 0 ); 130 | 131 | dispman_element = 132 | vc_dispmanx_element_add(dispman_update, dispman_display, 133 | 0/*layer*/, &dst_rect, 0/*src*/, 134 | &src_rect, DISPMANX_PROTECTION_NONE, 135 | 0 /*alpha*/, 0/*clamp*/, 0/*transform*/); 136 | 137 | // Build an EGL_DISPMANX_WINDOW_T from the Dispmanx window 138 | nativewindow->element = dispman_element; 139 | nativewindow->width = screen_width; 140 | nativewindow->height = screen_height; 141 | vc_dispmanx_update_submit_sync(dispman_update); 142 | 143 | printf("Got a Dispmanx window\n"); 144 | } 145 | 146 | void egl_from_dispmanx(EGL_STATE_T *state, 147 | EGL_DISPMANX_WINDOW_T *nativewindow) { 148 | EGLBoolean result; 149 | 150 | state->surface = eglCreateWindowSurface(state->display, 151 | state->config, 152 | nativewindow, NULL ); 153 | assert(state->surface != EGL_NO_SURFACE); 154 | 155 | // connect the context to the surface 156 | result = eglMakeCurrent(state->display, state->surface, state->surface, state->context); 157 | assert(EGL_FALSE != result); 158 | } 159 | 160 | void simple_shape() { 161 | VGint cap_style = VG_CAP_BUTT; 162 | VGint join_style = VG_JOIN_MITER; 163 | VGfloat color[4] = {1.0, 0.1, 1.0, 0.2}; 164 | VGfloat white_color[4] = {1.0, 1.0, 1.0, 0.0}; //1.0}; 165 | VGPaint fill; 166 | 167 | static const VGubyte cmds[] = {VG_MOVE_TO_ABS, 168 | VG_LINE_TO_ABS, 169 | VG_LINE_TO_ABS, 170 | VG_CLOSE_PATH 171 | }; 172 | 173 | static const VGfloat coords[] = {630, 630, 174 | 902, 630, 175 | 750, 924 176 | }; 177 | 178 | VGfloat dash_pattern[2] = { 20.f, 20.f }; 179 | VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, 180 | VG_PATH_DATATYPE_F, 1, 0, 0, 0, 181 | VG_PATH_CAPABILITY_APPEND_TO); 182 | vgAppendPathData(path, 4, cmds, coords); 183 | 184 | fill = vgCreatePaint(); 185 | vgSetParameterfv(fill, VG_PAINT_COLOR, 4, color); 186 | vgSetPaint(fill, VG_FILL_PATH); 187 | vgSetPaint(fill, VG_STROKE_PATH); 188 | 189 | vgSetfv(VG_CLEAR_COLOR, 4, white_color); 190 | vgSetf(VG_STROKE_LINE_WIDTH, 20); 191 | vgSeti(VG_STROKE_CAP_STYLE, cap_style); 192 | vgSeti(VG_STROKE_JOIN_STYLE, join_style); 193 | vgSetfv(VG_STROKE_DASH_PATTERN, 2, dash_pattern); 194 | vgSetf(VG_STROKE_DASH_PHASE, 0.0f); 195 | 196 | vgDrawPath(path, VG_STROKE_PATH|VG_FILL_PATH); 197 | } 198 | 199 | void draw(){ 200 | float c = 1.0; 201 | float clearColor[4] = {c, c, c, c}; // white, no transparency 202 | vgSetfv(VG_CLEAR_COLOR, 4, clearColor); 203 | 204 | vgClear(0, 0, 1920, 1080); 205 | 206 | simple_shape(); 207 | 208 | vgFlush(); 209 | } 210 | 211 | int 212 | main(int argc, char *argv[]) 213 | { 214 | EGL_DISPMANX_WINDOW_T nativewindow; 215 | 216 | init_egl(p_state); 217 | init_dispmanx(&nativewindow); 218 | egl_from_dispmanx(p_state, &nativewindow); 219 | 220 | draw(); 221 | eglSwapBuffers(p_state->display, p_state->surface); 222 | 223 | sleep(100); 224 | eglTerminate(p_state->display); 225 | 226 | exit(0); 227 | } 228 | -------------------------------------------------------------------------------- /OpenVG/Basic/window.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * code adapted from openGL-RPi-tutorial-master/encode_OGL/ 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | typedef struct 22 | { 23 | EGLDisplay display; 24 | EGLSurface surface; 25 | EGLContext context; 26 | EGLConfig config; 27 | } EGL_STATE_T; 28 | 29 | struct egl_manager { 30 | EGLNativeDisplayType xdpy; 31 | EGLNativeWindowType xwin; 32 | EGLNativePixmapType xpix; 33 | 34 | EGLDisplay dpy; 35 | EGLConfig conf; 36 | EGLContext ctx; 37 | 38 | EGLSurface win; 39 | EGLSurface pix; 40 | EGLSurface pbuf; 41 | EGLImageKHR image; 42 | 43 | EGLBoolean verbose; 44 | EGLint major, minor; 45 | 46 | GC gc; 47 | GLuint fbo; 48 | }; 49 | 50 | EGL_STATE_T state, *p_state = &state; 51 | 52 | 53 | void init_egl(EGL_STATE_T *state) 54 | { 55 | EGLint num_configs; 56 | EGLBoolean result; 57 | 58 | //bcm_host_init(); 59 | 60 | static const EGLint attribute_list[] = 61 | { 62 | EGL_RED_SIZE, 8, 63 | EGL_GREEN_SIZE, 8, 64 | EGL_BLUE_SIZE, 8, 65 | EGL_ALPHA_SIZE, 8, 66 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 67 | EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, 68 | EGL_NONE 69 | }; 70 | 71 | static const EGLint context_attributes[] = 72 | { 73 | EGL_CONTEXT_CLIENT_VERSION, 2, 74 | EGL_NONE 75 | }; 76 | 77 | // get an EGL display connection 78 | state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 79 | 80 | // initialize the EGL display connection 81 | result = eglInitialize(state->display, NULL, NULL); 82 | 83 | // get an appropriate EGL frame buffer configuration 84 | result = eglChooseConfig(state->display, attribute_list, &state->config, 1, &num_configs); 85 | assert(EGL_FALSE != result); 86 | 87 | //result = eglBindAPI(EGL_OPENGL_ES_API); 88 | result = eglBindAPI(EGL_OPENVG_API); 89 | assert(EGL_FALSE != result); 90 | 91 | // create an EGL rendering context 92 | state->context = eglCreateContext(state->display, 93 | state->config, EGL_NO_CONTEXT, 94 | NULL); 95 | // breaks if we use this: context_attributes); 96 | assert(state->context!=EGL_NO_CONTEXT); 97 | } 98 | 99 | void init_dispmanx(EGL_DISPMANX_WINDOW_T *nativewindow) { 100 | int32_t success = 0; 101 | uint32_t screen_width; 102 | uint32_t screen_height; 103 | 104 | DISPMANX_ELEMENT_HANDLE_T dispman_element; 105 | DISPMANX_DISPLAY_HANDLE_T dispman_display; 106 | DISPMANX_UPDATE_HANDLE_T dispman_update; 107 | VC_RECT_T dst_rect; 108 | VC_RECT_T src_rect; 109 | 110 | bcm_host_init(); 111 | 112 | // create an EGL window surface 113 | success = graphics_get_display_size(0 /* LCD */, 114 | &screen_width, 115 | &screen_height); 116 | assert( success >= 0 ); 117 | 118 | dst_rect.x = 0; 119 | dst_rect.y = 0; 120 | dst_rect.width = screen_width; 121 | dst_rect.height = screen_height; 122 | 123 | src_rect.x = 0; 124 | src_rect.y = 0; 125 | src_rect.width = screen_width << 16; 126 | src_rect.height = screen_height << 16; 127 | 128 | dispman_display = vc_dispmanx_display_open( 0 /* LCD */); 129 | dispman_update = vc_dispmanx_update_start( 0 ); 130 | 131 | dispman_element = 132 | vc_dispmanx_element_add(dispman_update, dispman_display, 133 | 0/*layer*/, &dst_rect, 0/*src*/, 134 | &src_rect, DISPMANX_PROTECTION_NONE, 135 | 0 /*alpha*/, 0/*clamp*/, 0/*transform*/); 136 | 137 | // Build an EGL_DISPMANX_WINDOW_T from the Dispmanx window 138 | nativewindow->element = dispman_element; 139 | nativewindow->width = screen_width; 140 | nativewindow->height = screen_height; 141 | vc_dispmanx_update_submit_sync(dispman_update); 142 | 143 | printf("Got a Dispmanx window\n"); 144 | } 145 | 146 | void egl_from_dispmanx(EGL_STATE_T *state, 147 | EGL_DISPMANX_WINDOW_T *nativewindow) { 148 | EGLBoolean result; 149 | 150 | state->surface = eglCreateWindowSurface(state->display, 151 | state->config, 152 | nativewindow, NULL ); 153 | assert(state->surface != EGL_NO_SURFACE); 154 | 155 | // connect the context to the surface 156 | result = eglMakeCurrent(state->display, state->surface, state->surface, state->context); 157 | assert(EGL_FALSE != result); 158 | } 159 | 160 | void draw(){ 161 | float c = 1.0; 162 | float clearColor[4] = {c, c, c, 0.5}; // white, no transparency 163 | vgSetfv(VG_CLEAR_COLOR, 4, clearColor); 164 | 165 | vgClear(0, 0, 1920, 1080); // window_width(), window_height()); 166 | 167 | // do lots of drawing in here 168 | 169 | vgFlush(); 170 | } 171 | 172 | int 173 | main(int argc, char *argv[]) 174 | { 175 | EGL_DISPMANX_WINDOW_T nativewindow; 176 | 177 | init_egl(p_state); 178 | init_dispmanx(&nativewindow); 179 | egl_from_dispmanx(p_state, &nativewindow); 180 | 181 | draw(); 182 | eglSwapBuffers(p_state->display, p_state->surface); 183 | 184 | sleep(10); 185 | eglTerminate(p_state->display); 186 | 187 | exit(0); 188 | } 189 | -------------------------------------------------------------------------------- /OpenVG/Text/cairo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | char *lines[] = {"hello", "world", "AWAKE"}; 18 | int num_lines = 3; 19 | 20 | typedef struct 21 | { 22 | EGLDisplay display; 23 | EGLSurface surface; 24 | EGLContext context; 25 | EGLConfig config; 26 | } EGL_STATE_T; 27 | 28 | 29 | EGL_STATE_T state, *p_state = &state; 30 | 31 | void init_egl(EGL_STATE_T *state) 32 | { 33 | EGLint num_configs; 34 | EGLBoolean result; 35 | 36 | //bcm_host_init(); 37 | 38 | static const EGLint attribute_list[] = 39 | { 40 | EGL_RED_SIZE, 8, 41 | EGL_GREEN_SIZE, 8, 42 | EGL_BLUE_SIZE, 8, 43 | EGL_ALPHA_SIZE, 8, 44 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 45 | EGL_NONE 46 | }; 47 | 48 | // get an EGL display connection 49 | state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 50 | 51 | // initialize the EGL display connection 52 | result = eglInitialize(state->display, NULL, NULL); 53 | 54 | // get an appropriate EGL frame buffer configuration 55 | result = eglChooseConfig(state->display, attribute_list, &state->config, 1, &num_configs); 56 | assert(EGL_FALSE != result); 57 | 58 | // Choose the OpenVG API 59 | result = eglBindAPI(EGL_OPENVG_API); 60 | assert(EGL_FALSE != result); 61 | 62 | // create an EGL rendering context 63 | state->context = eglCreateContext(state->display, 64 | state->config, EGL_NO_CONTEXT, 65 | NULL); 66 | 67 | assert(state->context!=EGL_NO_CONTEXT); 68 | } 69 | 70 | void init_dispmanx(EGL_DISPMANX_WINDOW_T *nativewindow) { 71 | int32_t success = 0; 72 | uint32_t screen_width; 73 | uint32_t screen_height; 74 | 75 | DISPMANX_ELEMENT_HANDLE_T dispman_element; 76 | DISPMANX_DISPLAY_HANDLE_T dispman_display; 77 | DISPMANX_UPDATE_HANDLE_T dispman_update; 78 | VC_RECT_T dst_rect; 79 | VC_RECT_T src_rect; 80 | 81 | bcm_host_init(); 82 | 83 | // create an EGL window surface 84 | success = graphics_get_display_size(0 /* LCD */, 85 | &screen_width, 86 | &screen_height); 87 | assert( success >= 0 ); 88 | 89 | dst_rect.x = 0; 90 | dst_rect.y = 0; 91 | dst_rect.width = screen_width; 92 | dst_rect.height = screen_height; 93 | 94 | src_rect.x = 0; 95 | src_rect.y = 0; 96 | src_rect.width = screen_width << 16; 97 | src_rect.height = screen_height << 16; 98 | 99 | dispman_display = vc_dispmanx_display_open( 0 /* LCD */); 100 | dispman_update = vc_dispmanx_update_start( 0 ); 101 | 102 | dispman_element = 103 | vc_dispmanx_element_add(dispman_update, dispman_display, 104 | 0 /*layer*/, &dst_rect, 0 /*src*/, 105 | &src_rect, DISPMANX_PROTECTION_NONE, 106 | 0 /*alpha*/, 0 /*clamp*/, 0 /*transform*/); 107 | 108 | // Build an EGL_DISPMANX_WINDOW_T from the Dispmanx window 109 | nativewindow->element = dispman_element; 110 | nativewindow->width = screen_width; 111 | nativewindow->height = screen_height; 112 | vc_dispmanx_update_submit_sync(dispman_update); 113 | 114 | printf("Got a Dispmanx window\n"); 115 | } 116 | 117 | void egl_from_dispmanx(EGL_STATE_T *state, 118 | EGL_DISPMANX_WINDOW_T *nativewindow) { 119 | EGLBoolean result; 120 | 121 | state->surface = eglCreateWindowSurface(state->display, 122 | state->config, 123 | nativewindow, NULL ); 124 | assert(state->surface != EGL_NO_SURFACE); 125 | 126 | // connect the context to the surface 127 | result = eglMakeCurrent(state->display, state->surface, state->surface, state->context); 128 | assert(EGL_FALSE != result); 129 | } 130 | 131 | void cairo(char *text) { 132 | int width = 500; 133 | int height = 200; 134 | 135 | cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 136 | width, height); 137 | cairo_t *cr = cairo_create(surface); 138 | 139 | cairo_rectangle(cr, 0, 0, width, height); 140 | cairo_set_source_rgb(cr, 0.0, 0.0, 0.5); 141 | cairo_fill(cr); 142 | 143 | // draw some white text on top 144 | cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); 145 | // this is a standard font for Cairo 146 | cairo_select_font_face (cr, "cairo:serif", 147 | CAIRO_FONT_SLANT_NORMAL, 148 | CAIRO_FONT_WEIGHT_BOLD); 149 | cairo_set_font_size (cr, 36); 150 | cairo_move_to(cr, 10.0, 50.0); 151 | 152 | cairo_scale(cr, 1.0f, -1.0f); 153 | cairo_translate(cr, 0.0f, -50); 154 | 155 | cairo_text_extents_t extents; 156 | cairo_text_extents(cr, text, &extents); 157 | 158 | cairo_show_text (cr, text); 159 | 160 | int tex_w = cairo_image_surface_get_width(surface); 161 | int tex_h = cairo_image_surface_get_height(surface); 162 | int tex_s = cairo_image_surface_get_stride(surface); 163 | unsigned char* data = cairo_image_surface_get_data(surface); 164 | 165 | int left = 1920/2 - extents.width/2; 166 | vgWritePixels(data, tex_s, 167 | VG_lBGRA_8888, left, 300, tex_w, tex_h ); 168 | } 169 | 170 | void draw() { 171 | EGL_DISPMANX_WINDOW_T nativewindow; 172 | 173 | init_egl(p_state); 174 | init_dispmanx(&nativewindow); 175 | 176 | egl_from_dispmanx(p_state, &nativewindow); 177 | 178 | int n = 0; 179 | while (1) { 180 | cairo(lines[n++]); 181 | n %= num_lines; 182 | 183 | eglSwapBuffers(p_state->display, p_state->surface); 184 | sleep(3); 185 | } 186 | } 187 | 188 | int main(int argc, char** argv) { 189 | 190 | draw(); 191 | 192 | exit(0); 193 | } 194 | -------------------------------------------------------------------------------- /OpenVG/Text/pango.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | //include 17 | 18 | typedef struct 19 | { 20 | EGLDisplay display; 21 | EGLSurface surface; 22 | EGLContext context; 23 | EGLConfig config; 24 | } EGL_STATE_T; 25 | 26 | 27 | EGL_STATE_T state, *p_state = &state; 28 | 29 | void init_egl(EGL_STATE_T *state) 30 | { 31 | EGLint num_configs; 32 | EGLBoolean result; 33 | 34 | //bcm_host_init(); 35 | 36 | static const EGLint attribute_list[] = 37 | { 38 | EGL_RED_SIZE, 8, 39 | EGL_GREEN_SIZE, 8, 40 | EGL_BLUE_SIZE, 8, 41 | EGL_ALPHA_SIZE, 8, 42 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 43 | EGL_NONE 44 | }; 45 | 46 | // get an EGL display connection 47 | state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 48 | 49 | // initialize the EGL display connection 50 | result = eglInitialize(state->display, NULL, NULL); 51 | 52 | // get an appropriate EGL frame buffer configuration 53 | result = eglChooseConfig(state->display, attribute_list, &state->config, 1, &num_configs); 54 | assert(EGL_FALSE != result); 55 | 56 | // Choose the OpenVG API 57 | result = eglBindAPI(EGL_OPENVG_API); 58 | assert(EGL_FALSE != result); 59 | 60 | // create an EGL rendering context 61 | state->context = eglCreateContext(state->display, 62 | state->config, EGL_NO_CONTEXT, 63 | NULL); 64 | 65 | assert(state->context!=EGL_NO_CONTEXT); 66 | } 67 | 68 | void init_dispmanx(EGL_DISPMANX_WINDOW_T *nativewindow) { 69 | int32_t success = 0; 70 | uint32_t screen_width; 71 | uint32_t screen_height; 72 | 73 | DISPMANX_ELEMENT_HANDLE_T dispman_element; 74 | DISPMANX_DISPLAY_HANDLE_T dispman_display; 75 | DISPMANX_UPDATE_HANDLE_T dispman_update; 76 | VC_RECT_T dst_rect; 77 | VC_RECT_T src_rect; 78 | 79 | bcm_host_init(); 80 | 81 | // create an EGL window surface 82 | success = graphics_get_display_size(0 /* LCD */, 83 | &screen_width, 84 | &screen_height); 85 | assert( success >= 0 ); 86 | 87 | dst_rect.x = 0; 88 | dst_rect.y = 0; 89 | dst_rect.width = screen_width; 90 | dst_rect.height = screen_height; 91 | 92 | src_rect.x = 0; 93 | src_rect.y = 0; 94 | src_rect.width = screen_width << 16; 95 | src_rect.height = screen_height << 16; 96 | 97 | dispman_display = vc_dispmanx_display_open( 0 /* LCD */); 98 | dispman_update = vc_dispmanx_update_start( 0 ); 99 | 100 | dispman_element = 101 | vc_dispmanx_element_add(dispman_update, dispman_display, 102 | 0/*layer*/, &dst_rect, 0/*src*/, 103 | &src_rect, DISPMANX_PROTECTION_NONE, 104 | 0 /*alpha*/, 0/*clamp*/, 0/*transform*/); 105 | 106 | // Build an EGL_DISPMANX_WINDOW_T from the Dispmanx window 107 | nativewindow->element = dispman_element; 108 | nativewindow->width = screen_width; 109 | nativewindow->height = screen_height; 110 | vc_dispmanx_update_submit_sync(dispman_update); 111 | 112 | printf("Got a Dispmanx window\n"); 113 | } 114 | 115 | void egl_from_dispmanx(EGL_STATE_T *state, 116 | EGL_DISPMANX_WINDOW_T *nativewindow) { 117 | EGLBoolean result; 118 | 119 | state->surface = eglCreateWindowSurface(state->display, 120 | state->config, 121 | nativewindow, NULL ); 122 | assert(state->surface != EGL_NO_SURFACE); 123 | 124 | // connect the context to the surface 125 | result = eglMakeCurrent(state->display, state->surface, state->surface, state->context); 126 | assert(EGL_FALSE != result); 127 | } 128 | 129 | // setfill sets the fill color 130 | void setfill(float color[4]) { 131 | VGPaint fillPaint = vgCreatePaint(); 132 | vgSetParameteri(fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); 133 | vgSetParameterfv(fillPaint, VG_PAINT_COLOR, 4, color); 134 | vgSetPaint(fillPaint, VG_FILL_PATH); 135 | vgDestroyPaint(fillPaint); 136 | } 137 | 138 | 139 | // setstroke sets the stroke color and width 140 | void setstroke(float color[4], float width) { 141 | VGPaint strokePaint = vgCreatePaint(); 142 | vgSetParameteri(strokePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); 143 | vgSetParameterfv(strokePaint, VG_PAINT_COLOR, 4, color); 144 | vgSetPaint(strokePaint, VG_STROKE_PATH); 145 | vgSetf(VG_STROKE_LINE_WIDTH, width); 146 | vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_BUTT); 147 | vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_MITER); 148 | vgDestroyPaint(strokePaint); 149 | } 150 | 151 | // Ellipse makes an ellipse at the specified location and dimensions, applying style 152 | void Ellipse(float x, float y, float w, float h, float sw, float fill[4], float stroke[4]) { 153 | VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL); 154 | vguEllipse(path, x, y, w, h); 155 | setfill(fill); 156 | setstroke(stroke, sw); 157 | vgDrawPath(path, VG_FILL_PATH | VG_STROKE_PATH); 158 | vgDestroyPath(path); 159 | } 160 | 161 | void pango() { 162 | int width = 500; 163 | int height = 200; 164 | 165 | cairo_surface_t *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 166 | width, height); 167 | cairo_t *cr = cairo_create(surface); 168 | 169 | cairo_rectangle(cr, 0, 0, width, height); 170 | cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); 171 | cairo_fill(cr); 172 | 173 | 174 | // Pango marked up text, half red, half black 175 | gchar *markup_text = "hello\ 176 | AWA㹴犬"; 177 | PangoAttrList *attrs; 178 | gchar *text; 179 | 180 | pango_parse_markup (markup_text, -1, 0, &attrs, &text, NULL, NULL); 181 | 182 | // draw Pango text 183 | PangoLayout *layout; 184 | PangoFontDescription *desc; 185 | 186 | cairo_move_to(cr, 30.0, 150.0); 187 | cairo_scale(cr, 1.0f, -1.0f); 188 | layout = pango_cairo_create_layout (cr); 189 | pango_layout_set_text (layout, text, -1); 190 | pango_layout_set_attributes(layout, attrs); 191 | pango_cairo_update_layout (cr, layout); 192 | pango_cairo_show_layout (cr, layout); 193 | 194 | int tex_w = cairo_image_surface_get_width(surface); 195 | int tex_h = cairo_image_surface_get_height(surface); 196 | int tex_s = cairo_image_surface_get_stride(surface); 197 | cairo_surface_flush(surface); 198 | cairo_format_t type = 199 | cairo_image_surface_get_format (surface); 200 | printf("Format is (0 is ARGB32) %d\n", type); 201 | unsigned char* data = cairo_image_surface_get_data(surface); 202 | 203 | PangoLayoutLine *layout_line = 204 | pango_layout_get_line(layout, 0); 205 | PangoRectangle ink_rect; 206 | PangoRectangle logical_rect; 207 | pango_layout_line_get_pixel_extents (layout_line, 208 | &ink_rect, 209 | &logical_rect); 210 | printf("Layout line rectangle is %d, %d, %d, %d\n", 211 | ink_rect.x, ink_rect.y, ink_rect.width, ink_rect.height); 212 | 213 | int left = 1920/2 - ink_rect.width/2; 214 | vgWritePixels(data, tex_s, 215 | //VG_lBGRA_8888, 216 | VG_sARGB_8888 , 217 | left, 300, tex_w, tex_h ); 218 | } 219 | 220 | 221 | void draw() 222 | { 223 | EGL_DISPMANX_WINDOW_T nativewindow; 224 | 225 | init_egl(p_state); 226 | init_dispmanx(&nativewindow); 227 | 228 | egl_from_dispmanx(p_state, &nativewindow); 229 | //draw(); 230 | pango(); 231 | 232 | eglSwapBuffers(p_state->display, p_state->surface); 233 | 234 | sleep(30); 235 | eglTerminate(p_state->display); 236 | 237 | exit(0); 238 | } 239 | 240 | int main(int argc, char** argv) { 241 | 242 | draw(); 243 | 244 | exit(0); 245 | } 246 | -------------------------------------------------------------------------------- /OpenVG/Text/text-bitmap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | //#include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include FT_FREETYPE_H 17 | #include FT_STROKER_H 18 | 19 | typedef struct 20 | { 21 | EGLDisplay display; 22 | EGLSurface surface; 23 | EGLContext context; 24 | EGLConfig config; 25 | } EGL_STATE_T; 26 | 27 | 28 | EGL_STATE_T state, *p_state = &state; 29 | 30 | 31 | void init_egl(EGL_STATE_T *state) 32 | { 33 | EGLint num_configs; 34 | EGLBoolean result; 35 | 36 | //bcm_host_init(); 37 | 38 | static const EGLint attribute_list[] = 39 | { 40 | EGL_RED_SIZE, 8, 41 | EGL_GREEN_SIZE, 8, 42 | EGL_BLUE_SIZE, 8, 43 | EGL_ALPHA_SIZE, 8, 44 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 45 | EGL_SAMPLES, 1, 46 | EGL_NONE 47 | }; 48 | 49 | static const EGLint context_attributes[] = 50 | { 51 | EGL_CONTEXT_CLIENT_VERSION, 2, 52 | EGL_NONE 53 | }; 54 | 55 | // get an EGL display connection 56 | state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 57 | 58 | // initialize the EGL display connection 59 | result = eglInitialize(state->display, NULL, NULL); 60 | 61 | // get an appropriate EGL frame buffer configuration 62 | result = eglChooseConfig(state->display, attribute_list, &state->config, 1, &num_configs); 63 | assert(EGL_FALSE != result); 64 | 65 | // Choose the OpenVG API 66 | result = eglBindAPI(EGL_OPENVG_API); 67 | assert(EGL_FALSE != result); 68 | 69 | // create an EGL rendering context 70 | state->context = eglCreateContext(state->display, 71 | state->config, 72 | NULL, // EGL_NO_CONTEXT, 73 | NULL); 74 | // breaks if we use this: context_attributes); 75 | assert(state->context!=EGL_NO_CONTEXT); 76 | } 77 | 78 | void init_dispmanx(EGL_DISPMANX_WINDOW_T *nativewindow) { 79 | int32_t success = 0; 80 | uint32_t screen_width; 81 | uint32_t screen_height; 82 | 83 | DISPMANX_ELEMENT_HANDLE_T dispman_element; 84 | DISPMANX_DISPLAY_HANDLE_T dispman_display; 85 | DISPMANX_UPDATE_HANDLE_T dispman_update; 86 | VC_RECT_T dst_rect; 87 | VC_RECT_T src_rect; 88 | 89 | bcm_host_init(); 90 | 91 | // create an EGL window surface 92 | success = graphics_get_display_size(0 /* LCD */, 93 | &screen_width, 94 | &screen_height); 95 | assert( success >= 0 ); 96 | 97 | dst_rect.x = 0; 98 | dst_rect.y = 0; 99 | dst_rect.width = screen_width; 100 | dst_rect.height = screen_height; 101 | 102 | src_rect.x = 0; 103 | src_rect.y = 0; 104 | src_rect.width = screen_width << 16; 105 | src_rect.height = screen_height << 16; 106 | 107 | dispman_display = vc_dispmanx_display_open( 0 /* LCD */); 108 | dispman_update = vc_dispmanx_update_start( 0 ); 109 | 110 | dispman_element = 111 | vc_dispmanx_element_add(dispman_update, dispman_display, 112 | 0 /*layer*/, &dst_rect, 0 /*src*/, 113 | &src_rect, DISPMANX_PROTECTION_NONE, 114 | 0 /*alpha*/, 0 /*clamp*/, 0 /*transform*/); 115 | 116 | // Build an EGL_DISPMANX_WINDOW_T from the Dispmanx window 117 | nativewindow->element = dispman_element; 118 | nativewindow->width = screen_width; 119 | nativewindow->height = screen_height; 120 | vc_dispmanx_update_submit_sync(dispman_update); 121 | 122 | printf("Got a Dispmanx window\n"); 123 | } 124 | 125 | void egl_from_dispmanx(EGL_STATE_T *state, 126 | EGL_DISPMANX_WINDOW_T *nativewindow) { 127 | EGLBoolean result; 128 | static const EGLint attribute_list[] = 129 | { 130 | EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER, 131 | EGL_NONE 132 | }; 133 | 134 | state->surface = eglCreateWindowSurface(state->display, 135 | state->config, 136 | nativewindow, 137 | NULL ); 138 | //attribute_list); 139 | assert(state->surface != EGL_NO_SURFACE); 140 | 141 | // connect the context to the surface 142 | result = eglMakeCurrent(state->display, state->surface, state->surface, state->context); 143 | assert(EGL_FALSE != result); 144 | } 145 | 146 | FT_Library ft_library; /* handle to library */ 147 | FT_Face ft_face; 148 | 149 | void ft_init() { 150 | int err; 151 | 152 | err = FT_Init_FreeType(&ft_library); 153 | assert( !err); 154 | 155 | err = FT_New_Face(ft_library, 156 | "/usr/share/ghostscript/9.05/Resource/CIDFSubst/DroidSansFallback.ttf", 157 | 0, 158 | &ft_face ); 159 | assert( !err); 160 | 161 | int font_size = 256; //128; 162 | err = FT_Set_Pixel_Sizes(ft_face, 0, font_size); 163 | assert( !err); 164 | } 165 | 166 | void draw() { 167 | EGL_DISPMANX_WINDOW_T nativewindow; 168 | 169 | init_egl(p_state); 170 | init_dispmanx(&nativewindow); 171 | 172 | egl_from_dispmanx(p_state, &nativewindow); 173 | 174 | vgClear(0, 0, 1920, 1080); 175 | 176 | VGFont font, font_border; 177 | font = vgCreateFont(0); 178 | font_border = vgCreateFont(0); 179 | 180 | ft_init(); 181 | 182 | int glyph_index = FT_Get_Char_Index(ft_face, 0x597d); // '好' 183 | if (glyph_index == 0) printf("No glyph found\n"); 184 | FT_Load_Glyph(ft_face, glyph_index, FT_LOAD_NO_HINTING); 185 | 186 | FT_Glyph glyph; 187 | FT_Get_Glyph(ft_face->glyph, &glyph); 188 | 189 | FT_Stroker ft_stroker; 190 | FT_Stroker_New(ft_library, &ft_stroker); 191 | FT_Stroker_Set(ft_stroker, 192 | 200, // line_height_*border_thickness*64.0f, 193 | FT_STROKER_LINECAP_ROUND, 194 | FT_STROKER_LINEJOIN_ROUND, 195 | 0); 196 | FT_Glyph_StrokeBorder(&glyph, ft_stroker, 0, 1); 197 | 198 | FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, NULL, 1); 199 | FT_BitmapGlyph bit_glyph = (FT_BitmapGlyph) glyph; 200 | FT_Bitmap bitmap = bit_glyph->bitmap; 201 | printf("Bitmap mode is %d (2 is gray) with %d levels\n", 202 | bitmap.pixel_mode, bitmap.num_grays); 203 | 204 | int tex_s = bitmap.pitch; 205 | int tex_w = bitmap.width; 206 | int tex_h = bitmap.rows; 207 | 208 | VGImage image = vgCreateImage(VG_sL_8, tex_w, tex_h, 209 | VG_IMAGE_QUALITY_NONANTIALIASED); 210 | 211 | // invert bitmap image 212 | vgImageSubData(image, 213 | bitmap.buffer + tex_s*(tex_h-1), 214 | -tex_s, 215 | VG_sL_8, //VG_A_8, VG_sL_8 seem to be okay too 216 | 0, 0, tex_w, tex_h); 217 | 218 | vgSetPixels(600, 600, image, 0, 0, tex_w, tex_h); 219 | 220 | vgFlush(); 221 | 222 | eglSwapBuffers(p_state->display, p_state->surface); 223 | } 224 | 225 | void sig_handler(int sig) { 226 | eglTerminate(p_state->display); 227 | exit(1); 228 | } 229 | 230 | int main(int argc, char** argv) { 231 | signal(SIGINT, sig_handler); 232 | 233 | draw(); 234 | 235 | sleep(100); 236 | exit(0); 237 | } 238 | -------------------------------------------------------------------------------- /OpenVG/Text/text-outline.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | //#include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include FT_FREETYPE_H 17 | #include FT_STROKER_H 18 | 19 | typedef struct 20 | { 21 | EGLDisplay display; 22 | EGLSurface surface; 23 | EGLContext context; 24 | EGLConfig config; 25 | } EGL_STATE_T; 26 | 27 | EGL_STATE_T state, *p_state = &state; 28 | 29 | void init_egl(EGL_STATE_T *state) 30 | { 31 | EGLint num_configs; 32 | EGLBoolean result; 33 | 34 | //bcm_host_init(); 35 | 36 | static const EGLint attribute_list[] = 37 | { 38 | EGL_RED_SIZE, 8, 39 | EGL_GREEN_SIZE, 8, 40 | EGL_BLUE_SIZE, 8, 41 | EGL_ALPHA_SIZE, 8, 42 | EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 43 | EGL_SAMPLES, 1, 44 | EGL_NONE 45 | }; 46 | 47 | static const EGLint context_attributes[] = 48 | { 49 | EGL_CONTEXT_CLIENT_VERSION, 2, 50 | EGL_NONE 51 | }; 52 | 53 | // get an EGL display connection 54 | state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 55 | 56 | // initialize the EGL display connection 57 | result = eglInitialize(state->display, NULL, NULL); 58 | 59 | // get an appropriate EGL frame buffer configuration 60 | result = eglChooseConfig(state->display, attribute_list, &state->config, 1, &num_configs); 61 | assert(EGL_FALSE != result); 62 | 63 | // Choose the OpenVG API 64 | result = eglBindAPI(EGL_OPENVG_API); 65 | assert(EGL_FALSE != result); 66 | 67 | // create an EGL rendering context 68 | state->context = eglCreateContext(state->display, 69 | state->config, 70 | NULL, // EGL_NO_CONTEXT, 71 | NULL); 72 | // breaks if we use this: context_attributes); 73 | assert(state->context!=EGL_NO_CONTEXT); 74 | } 75 | 76 | void init_dispmanx(EGL_DISPMANX_WINDOW_T *nativewindow) { 77 | int32_t success = 0; 78 | uint32_t screen_width; 79 | uint32_t screen_height; 80 | 81 | DISPMANX_ELEMENT_HANDLE_T dispman_element; 82 | DISPMANX_DISPLAY_HANDLE_T dispman_display; 83 | DISPMANX_UPDATE_HANDLE_T dispman_update; 84 | VC_RECT_T dst_rect; 85 | VC_RECT_T src_rect; 86 | 87 | bcm_host_init(); 88 | 89 | // create an EGL window surface 90 | success = graphics_get_display_size(0 /* LCD */, 91 | &screen_width, 92 | &screen_height); 93 | assert( success >= 0 ); 94 | 95 | dst_rect.x = 0; 96 | dst_rect.y = 0; 97 | dst_rect.width = screen_width; 98 | dst_rect.height = screen_height; 99 | 100 | src_rect.x = 0; 101 | src_rect.y = 0; 102 | src_rect.width = screen_width << 16; 103 | src_rect.height = screen_height << 16; 104 | 105 | dispman_display = vc_dispmanx_display_open( 0 /* LCD */); 106 | dispman_update = vc_dispmanx_update_start( 0 ); 107 | 108 | dispman_element = 109 | vc_dispmanx_element_add(dispman_update, dispman_display, 110 | 0 /*layer*/, &dst_rect, 0 /*src*/, 111 | &src_rect, DISPMANX_PROTECTION_NONE, 112 | 0 /*alpha*/, 0 /*clamp*/, 0 /*transform*/); 113 | 114 | // Build an EGL_DISPMANX_WINDOW_T from the Dispmanx window 115 | nativewindow->element = dispman_element; 116 | nativewindow->width = screen_width; 117 | nativewindow->height = screen_height; 118 | vc_dispmanx_update_submit_sync(dispman_update); 119 | 120 | printf("Got a Dispmanx window\n"); 121 | } 122 | 123 | void egl_from_dispmanx(EGL_STATE_T *state, 124 | EGL_DISPMANX_WINDOW_T *nativewindow) { 125 | EGLBoolean result; 126 | static const EGLint attribute_list[] = 127 | { 128 | EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER, 129 | EGL_NONE 130 | }; 131 | 132 | state->surface = eglCreateWindowSurface(state->display, 133 | state->config, 134 | nativewindow, 135 | NULL ); 136 | //attribute_list); 137 | assert(state->surface != EGL_NO_SURFACE); 138 | 139 | // connect the context to the surface 140 | result = eglMakeCurrent(state->display, state->surface, state->surface, state->context); 141 | assert(EGL_FALSE != result); 142 | } 143 | 144 | // setfill sets the fill color 145 | void setfill(float color[4]) { 146 | VGPaint fillPaint = vgCreatePaint(); 147 | vgSetParameteri(fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); 148 | vgSetParameterfv(fillPaint, VG_PAINT_COLOR, 4, color); 149 | vgSetPaint(fillPaint, VG_FILL_PATH); 150 | vgDestroyPaint(fillPaint); 151 | } 152 | 153 | 154 | // setstroke sets the stroke color and width 155 | void setstroke(float color[4], float width) { 156 | VGPaint strokePaint = vgCreatePaint(); 157 | vgSetParameteri(strokePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); 158 | vgSetParameterfv(strokePaint, VG_PAINT_COLOR, 4, color); 159 | vgSetPaint(strokePaint, VG_STROKE_PATH); 160 | vgSetf(VG_STROKE_LINE_WIDTH, width); 161 | vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_BUTT); 162 | vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_MITER); 163 | vgDestroyPaint(strokePaint); 164 | } 165 | 166 | // from /opt/vc/src/hello_pi/libs/vgfont/vgft.c 167 | 168 | #define SEGMENTS_COUNT_MAX 256 169 | #define COORDS_COUNT_MAX 1024 170 | 171 | static VGuint segments_count; 172 | static VGubyte segments[SEGMENTS_COUNT_MAX]; 173 | static VGuint coords_count; 174 | static VGfloat coords[COORDS_COUNT_MAX]; 175 | 176 | static VGfloat float_from_26_6(FT_Pos x) 177 | { 178 | return (VGfloat)x / 64.0f; 179 | } 180 | 181 | 182 | static void convert_contour(const FT_Vector *points, 183 | const char *tags, short points_count) 184 | { 185 | int first_coords = coords_count; 186 | 187 | int first = 1; 188 | char last_tag = 0; 189 | int c = 0; 190 | 191 | for (; points_count != 0; ++points, ++tags, --points_count) { 192 | ++c; 193 | 194 | char tag = *tags; 195 | if (first) { 196 | assert(tag & 0x1); 197 | assert(c==1); c=0; 198 | segments[segments_count++] = VG_MOVE_TO; 199 | first = 0; 200 | } else if (tag & 0x1) { 201 | /* on curve */ 202 | 203 | if (last_tag & 0x1) { 204 | /* last point was also on -- line */ 205 | assert(c==1); c=0; 206 | segments[segments_count++] = VG_LINE_TO; 207 | } else { 208 | /* last point was off -- quad or cubic */ 209 | if (last_tag & 0x2) { 210 | /* cubic */ 211 | assert(c==3); c=0; 212 | segments[segments_count++] = VG_CUBIC_TO; 213 | } else { 214 | /* quad */ 215 | assert(c==2); c=0; 216 | segments[segments_count++] = VG_QUAD_TO; 217 | } 218 | } 219 | } else { 220 | /* off curve */ 221 | 222 | if (tag & 0x2) { 223 | /* cubic */ 224 | 225 | assert((last_tag & 0x1) || (last_tag & 0x2)); /* last either on or off and cubic */ 226 | } else { 227 | /* quad */ 228 | 229 | if (!(last_tag & 0x1)) { 230 | /* last was also off curve */ 231 | 232 | assert(!(last_tag & 0x2)); /* must be quad */ 233 | 234 | /* add on point half-way between */ 235 | assert(c==2); c=1; 236 | segments[segments_count++] = VG_QUAD_TO; 237 | VGfloat x = (coords[coords_count - 2] + float_from_26_6(points->x)) * 0.5f; 238 | VGfloat y = (coords[coords_count - 1] + float_from_26_6(points->y)) * 0.5f; 239 | coords[coords_count++] = x; 240 | coords[coords_count++] = y; 241 | } 242 | } 243 | } 244 | last_tag = tag; 245 | 246 | coords[coords_count++] = float_from_26_6(points->x); 247 | coords[coords_count++] = float_from_26_6(points->y); 248 | } 249 | 250 | if (last_tag & 0x1) { 251 | /* last point was also on -- line (implicit with close path) */ 252 | assert(c==0); 253 | } else { 254 | ++c; 255 | 256 | /* last point was off -- quad or cubic */ 257 | if (last_tag & 0x2) { 258 | /* cubic */ 259 | assert(c==3); c=0; 260 | segments[segments_count++] = VG_CUBIC_TO; 261 | } else { 262 | /* quad */ 263 | assert(c==2); c=0; 264 | segments[segments_count++] = VG_QUAD_TO; 265 | } 266 | coords[coords_count++] = coords[first_coords + 0]; 267 | coords[coords_count++] = coords[first_coords + 1]; 268 | } 269 | 270 | segments[segments_count++] = VG_CLOSE_PATH; 271 | } 272 | 273 | static void convert_outline(const FT_Vector *points, 274 | const char *tags, const short *contours, 275 | short contours_count, short points_count) 276 | { 277 | segments_count = 0; 278 | coords_count = 0; 279 | 280 | short last_contour = 0; 281 | for (; contours_count != 0; ++contours, --contours_count) { 282 | short contour = *contours + 1; 283 | convert_contour(points + last_contour, tags + last_contour, contour - last_contour); 284 | last_contour = contour; 285 | } 286 | assert(last_contour == points_count); 287 | 288 | assert(segments_count <= SEGMENTS_COUNT_MAX); /* oops... we overwrote some me 289 | mory */ 290 | assert(coords_count <= COORDS_COUNT_MAX); 291 | } 292 | 293 | 294 | FT_Library ft_library; /* handle to library */ 295 | FT_Face ft_face; 296 | 297 | void ft_init() { 298 | int err; 299 | 300 | err = FT_Init_FreeType(&ft_library); 301 | assert( !err); 302 | 303 | err = FT_New_Face(ft_library, 304 | "/usr/share/ghostscript/9.05/Resource/CIDFSubst/DroidSansFallback.ttf", 305 | 0, 306 | &ft_face ); 307 | assert( !err); 308 | 309 | int font_size = 256; 310 | err = FT_Set_Pixel_Sizes(ft_face, 0, font_size); 311 | assert( !err); 312 | } 313 | 314 | void draw() { 315 | EGL_DISPMANX_WINDOW_T nativewindow; 316 | 317 | init_egl(p_state); 318 | init_dispmanx(&nativewindow); 319 | 320 | egl_from_dispmanx(p_state, &nativewindow); 321 | 322 | vgClear(0, 0, 1920, 1080); 323 | 324 | VGFont font, font_border; 325 | font = vgCreateFont(0); 326 | font_border = vgCreateFont(0); 327 | 328 | ft_init(); 329 | 330 | int glyph_index = FT_Get_Char_Index(ft_face, 0x597d); // '好' 331 | if (glyph_index == 0) printf("No glyph found\n"); 332 | FT_Load_Glyph(ft_face, glyph_index, FT_LOAD_NO_HINTING); 333 | 334 | VGPath vg_path; 335 | 336 | FT_Outline *outline = &ft_face->glyph->outline; 337 | if (outline->n_contours != 0) { 338 | vg_path = vgCreatePath(VG_PATH_FORMAT_STANDARD, 339 | VG_PATH_DATATYPE_F, 1.0f, 340 | 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL); 341 | assert(vg_path != VG_INVALID_HANDLE); 342 | 343 | convert_outline(outline->points, outline->tags, 344 | outline->contours, outline->n_contours, 345 | outline->n_points); 346 | vgAppendPathData(vg_path, segments_count, segments, coords); 347 | } else { 348 | vg_path = VG_INVALID_HANDLE; 349 | } 350 | 351 | 352 | VGfloat strokeColor[4] = {0.4, 0.1, 1.0, 1.0}; // purple 353 | VGfloat fillColor[4] = {1.0, 1.0, 0.0, 1.0}; // yellowish 354 | float c = 1.0; 355 | float backColor[4] = {c, c, c, c}; // white non-transparent 356 | vgSetfv(VG_CLEAR_COLOR, 4, backColor); 357 | vgClear(0, 0, 1920, 1080); 358 | 359 | //vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER); 360 | 361 | setfill(fillColor); 362 | setstroke(strokeColor, 5); 363 | 364 | //vgDrawPath(vg_path, VG_STROKE_PATH); 365 | vgDrawPath(vg_path, VG_FILL_PATH | VG_STROKE_PATH); 366 | 367 | vgFlush(); 368 | 369 | eglSwapBuffers(p_state->display, p_state->surface); 370 | } 371 | 372 | void sig_handler(int sig) { 373 | eglTerminate(p_state->display); 374 | exit(1); 375 | } 376 | 377 | int main(int argc, char** argv) { 378 | signal(SIGINT, sig_handler); 379 | 380 | draw(); 381 | 382 | sleep(100); 383 | exit(0); 384 | } 385 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Apress Source Code 2 | 3 | This repository accompanies [*Raspberry Pi GPU Audio Video Programming*](http://www.apress.com/9781484224717) by Jan Newmarch (Apress, 2016). 4 | 5 | ![Cover image](9781484224717.jpg) 6 | 7 | Download the files as a zip using the green button, or clone the repository to your machine using Git. 8 | 9 | ## Releases 10 | 11 | Release v1.0 corresponds to the code in the published book, without corrections or updates. 12 | 13 | ## Contributions 14 | 15 | See the file Contributing.md for more information on how you can contribute to this repository. 16 | -------------------------------------------------------------------------------- /contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to Apress Source Code 2 | 3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. 4 | 5 | ## How to Contribute 6 | 7 | 1. Make sure you have a GitHub account. 8 | 2. Fork the repository for the relevant book. 9 | 3. Create a new branch on which to make your change, e.g. 10 | `git checkout -b my_code_contribution` 11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. 12 | 5. Submit a pull request. 13 | 14 | Thank you for your contribution! --------------------------------------------------------------------------------