]> git.sesse.net Git - mlt/commitdiff
Refactor movit.convert, movit.mix, and movit.overlay.
authorDan Dennedy <dan@dennedy.org>
Tue, 31 Dec 2013 04:05:20 +0000 (20:05 -0800)
committerDan Dennedy <dan@dennedy.org>
Tue, 31 Dec 2013 04:05:20 +0000 (20:05 -0800)
To use new methods on GlslManager: render_frame_texture() and
render_frame_rgba(). The latter routine was changed to use GL_BGRA in
glReadPixels() to improve performance on more OpenGL implementation (per
Steinar Gunderson's recommendation).

src/modules/opengl/filter_glsl_manager.cpp
src/modules/opengl/filter_movit_convert.cpp
src/modules/opengl/glsl_manager.h
src/modules/opengl/transition_movit_mix.cpp
src/modules/opengl/transition_movit_overlay.cpp

index a09f8099cb4be13aa7600e3af9f777dded4af253..cd479b74a492b5c0ca2aec39fc62fd95ec225710 100644 (file)
@@ -22,6 +22,7 @@
 #include <string>
 #include "glsl_manager.h"
 #include <movit/init.h>
+#include <movit/util.h>
 #include <movit/effect_chain.h>
 #include "mlt_movit_input.h"
 #include "mlt_flip_effect.h"
@@ -340,7 +341,7 @@ Effect* GlslManager::add_effect( mlt_filter filter, mlt_frame frame, Effect* eff
        return effect;
 }
 
-void GlslManager::render( mlt_service service, void* chain, GLuint fbo, int width, int height )
+void GlslManager::render_fbo( mlt_service service, void* chain, GLuint fbo, int width, int height )
 {
        EffectChain* effect_chain = (EffectChain*) chain;
        mlt_properties properties = MLT_SERVICE_PROPERTIES( service );
@@ -352,6 +353,114 @@ void GlslManager::render( mlt_service service, void* chain, GLuint fbo, int widt
        effect_chain->render_to_fbo( fbo, width, height );
 }
 
+int GlslManager::render_frame_texture(mlt_service service, mlt_frame frame, int width, int height, uint8_t **image)
+{
+       EffectChain* chain = get_chain( service );
+       if (!chain) return 1;
+       glsl_fbo fbo = get_fbo( width, height );
+       if (!fbo) return 1;
+       glsl_texture texture = get_texture( width, height, GL_RGBA );
+       if (!texture) {
+               release_fbo( fbo );
+               return 1;
+       }
+
+       glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
+       check_error();
+       glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
+       check_error();
+       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+       check_error();
+
+       render_fbo( service, chain, fbo->fbo, width, height );
+
+       glFinish();
+       check_error();
+       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+       check_error();
+       release_fbo( fbo );
+
+       *image = (uint8_t*) &texture->texture;
+       mlt_frame_set_image( frame, *image, 0, NULL );
+       mlt_properties_set_data( MLT_FRAME_PROPERTIES(frame), "movit.convert.texture", texture, 0,
+               (mlt_destructor) GlslManager::release_texture, NULL );
+
+       return 0;
+}
+
+int GlslManager::render_frame_rgba(mlt_service service, mlt_frame frame, int width, int height, uint8_t **image)
+{
+       EffectChain* chain = get_chain( service );
+       if (!chain) return 1;
+       glsl_fbo fbo = get_fbo( width, height );
+       if (!fbo) return 1;
+       glsl_texture texture = get_texture( width, height, GL_RGBA );
+       if (!texture) {
+               release_fbo( fbo );
+               return 1;
+       }
+
+       // Use a PBO to hold the data we read back with glReadPixels().
+       // (Intel/DRI goes into a slow path if we don't read to PBO.)
+       int img_size = width * height * 4;
+       glsl_pbo pbo = get_pbo( img_size );
+       if (!pbo) {
+               release_fbo( fbo );
+               release_texture(texture);
+               return 1;
+       }
+
+       // Set the FBO
+       check_error();
+       glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
+       check_error();
+       glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
+       check_error();
+       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+       check_error();
+
+       render_fbo( service, chain, fbo->fbo, width, height );
+
+       // Read FBO into PBO
+       glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, pbo->pbo );
+       check_error();
+       glBufferData( GL_PIXEL_PACK_BUFFER_ARB, img_size, NULL, GL_STREAM_READ );
+       check_error();
+       glReadPixels( 0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0) );
+       check_error();
+
+       // Copy from PBO
+       uint8_t* buf = (uint8_t*) glMapBuffer( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY );
+       check_error();
+       *image = (uint8_t*) mlt_pool_alloc( img_size );
+       mlt_frame_set_image( frame, *image, img_size, mlt_pool_release );
+       memcpy( *image, buf, img_size );
+
+       // Convert BGRA to RGBA
+       register uint8_t *p = *image;
+       register int n = width * height + 1;
+       while ( --n ) {
+               uint8_t b = p[0];
+               *p = p[2]; p += 2;
+               *p = b; p += 2;
+       }
+
+       // Release PBO and FBO
+       glUnmapBuffer( GL_PIXEL_PACK_BUFFER_ARB );
+       check_error();
+       glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, 0 );
+       check_error();
+       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+       check_error();
+       glBindTexture( GL_TEXTURE_2D, 0 );
+       check_error();
+       mlt_properties_set_data( MLT_FRAME_PROPERTIES(frame), "movit.convert.texture", texture, 0,
+               (mlt_destructor) GlslManager::release_texture, NULL);
+       release_fbo( fbo );
+
+       return 0;
+}
+
 void GlslManager::lock_service( mlt_frame frame )
 {
        Mlt::Producer producer( mlt_producer_cut_parent( mlt_frame_get_original_producer( frame ) ) );
index 4d102db73eb6d0eb7b5f34f95bb9d4058b61b046..124cb34f79d45bd9f90419f76c981d8e5d354114 100644 (file)
@@ -73,8 +73,9 @@ static int convert_image( mlt_frame frame, uint8_t **image, mlt_image_format *fo
 
        mlt_properties properties = MLT_FRAME_PROPERTIES( frame );
 
-       mlt_log_debug( NULL, "filter_movit_convert: %s -> %s\n",
-               mlt_image_format_name( *format ), mlt_image_format_name( output_format ) );
+       mlt_log_debug( NULL, "filter_movit_convert: %s -> %s (%d)\n",
+               mlt_image_format_name( *format ), mlt_image_format_name( output_format ),
+               mlt_frame_get_position( frame ) );
 
        // Use CPU if glsl not initialized or not supported.
        GlslManager* glsl = GlslManager::get_instance();
@@ -206,92 +207,19 @@ static int convert_image( mlt_frame frame, uint8_t **image, mlt_image_format *fo
        }
 
        if ( output_format != mlt_image_glsl ) {
-               glsl_fbo fbo = glsl->get_fbo( width, height );
 
                if ( output_format == mlt_image_glsl_texture ) {
-                       glsl_texture texture = glsl->get_texture( width, height, GL_RGBA );
-
-                       glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
-                       check_error();
-                       glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
-                       check_error();
-                       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-                       check_error();
-
-                       GlslManager::render( service, chain, fbo->fbo, width, height );
-
-                       glFinish();
-                       check_error();
-                       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-                       check_error();
-
-                       *image = (uint8_t*) &texture->texture;
-                       mlt_frame_set_image( frame, *image, 0, NULL );
-                       mlt_properties_set_data( properties, "movit.convert.texture", texture, 0,
-                               (mlt_destructor) GlslManager::release_texture, NULL );
-                       mlt_properties_set_int( properties, "format", output_format );
-                       *format = output_format;
+                       error = glsl->render_frame_texture( service, frame, width, height, image );
                }
                else {
-                       // Use a PBO to hold the data we read back with glReadPixels()
-                       // (Intel/DRI goes into a slow path if we don't read to PBO)
-                       GLenum gl_format = ( output_format == mlt_image_rgb24a || output_format == mlt_image_opengl )?
-                               GL_RGBA : GL_RGB;
-                       img_size = width * height * ( gl_format == GL_RGB? 3 : 4 );
-                       glsl_pbo pbo = glsl->get_pbo( img_size );
-                       glsl_texture texture = glsl->get_texture( width, height, gl_format );
-
-                       if ( fbo && pbo && texture ) {
-                               // Set the FBO
-                               glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
-                               check_error();
-                               glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
-                               check_error();
-                               glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-                               check_error();
-
-                               GlslManager::render( service, chain, fbo->fbo, width, height );
-       
-                               // Read FBO into PBO
-                               glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, pbo->pbo );
-                               check_error();
-                               glBufferData( GL_PIXEL_PACK_BUFFER_ARB, img_size, NULL, GL_STREAM_READ );
-                               check_error();
-                               glReadPixels( 0, 0, width, height, gl_format, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0) );
-                               check_error();
-       
-                               // Copy from PBO
-                               uint8_t* buf = (uint8_t*) glMapBuffer( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY );
-                               check_error();
-                               *image = (uint8_t*) mlt_pool_alloc( img_size );
-                               mlt_frame_set_image( frame, *image, img_size, mlt_pool_release );
-                               memcpy( *image, buf, img_size );
-
-                               if ( output_format == mlt_image_yuv422 || output_format == mlt_image_yuv420p ) {
-                                       *format = mlt_image_rgb24;
-                                       error = convert_on_cpu( frame, image, format, output_format );
-                               }
-       
-                               // Release PBO and FBO
-                               glUnmapBuffer( GL_PIXEL_PACK_BUFFER_ARB );
-                               check_error();
-                               glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, 0 );
-                               check_error();
-                               glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-                               check_error();
-                               glBindTexture( GL_TEXTURE_2D, 0 );
-                               check_error();
-                               mlt_properties_set_data( properties, "movit.convert.texture", texture, 0,
-                                       (mlt_destructor) GlslManager::release_texture, NULL);
-       
-                               mlt_properties_set_int( properties, "format", output_format );
-                               *format = output_format;
-                       }
-                       else {
-                               error = 1;
+                       error = glsl->render_frame_rgba( service, frame, width, height, image );
+                       if ( !error && output_format != mlt_image_rgb24a ) {
+                               *format = mlt_image_rgb24a;
+                               error = convert_on_cpu( frame, image, format, output_format );
                        }
                }
-               if ( fbo ) GlslManager::release_fbo( fbo );
+               mlt_properties_set_int( properties, "format", output_format );
+               *format = output_format;
        }
        else {
                mlt_properties_set_int( properties, "format", output_format );
@@ -321,7 +249,7 @@ static mlt_frame process( mlt_filter filter, mlt_frame frame )
        return frame;
 }
 
-static mlt_filter create_filter( mlt_profile profile, char *effect )
+static mlt_filter create_filter( mlt_profile profile, const char *effect )
 {
        mlt_filter filter;
        char *id = strdup( effect );
index 88431a16f2818fa0e242ce68559053a8ed9fb8ce..fe968dc8370f6fae528e549a8ac65e606ff2499d 100644 (file)
@@ -89,7 +89,9 @@ public:
        static Effect* get_effect(mlt_filter, mlt_frame);
        static Effect* add_effect(mlt_filter, mlt_frame, Effect*);
        static Effect* add_effect(mlt_filter, mlt_frame, Effect*, Effect* input_b);
-       static void render(mlt_service, void *chain, GLuint fbo, int width, int height);
+       static void render_fbo(mlt_service, void *chain, GLuint fbo, int width, int height);
+       int render_frame_texture(mlt_service, mlt_frame, int width, int height, uint8_t **image);
+       int render_frame_rgba(mlt_service, mlt_frame, int width, int height, uint8_t **image);
        static void lock_service(mlt_frame frame);
        static void unlock_service(mlt_frame frame);
 
index e05c7eab829ed07d0c770f5d46a34033bb07d03c..ec02752f2b807af52b99f72920bcf5579bd309ca 100644 (file)
@@ -89,83 +89,14 @@ static int get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *form
 
        // Setup rendering to an FBO
        GlslManager* glsl = GlslManager::get_instance();
-       glsl_fbo fbo = glsl->get_fbo( *width, *height );
        if ( output_format == mlt_image_glsl_texture ) {
-               glsl_texture texture = glsl->get_texture( *width, *height, GL_RGBA );
-
-               glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
-               check_error();
-               glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
-               check_error();
-               glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-               check_error();
-
-               GlslManager::render( service, chain, fbo->fbo, *width, *height );
-
-               glFinish();
-               check_error();
-               glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-               check_error();
-
-               *image = (uint8_t*) &texture->texture;
-               mlt_frame_set_image( a_frame, *image, 0, NULL );
-               mlt_properties_set_data( properties, "movit.convert", texture, 0,
-                       (mlt_destructor) GlslManager::release_texture, NULL );
+               error = glsl->render_frame_texture( service, a_frame, *width, *height, image );
                *format = output_format;
        }
        else {
-               // Use a PBO to hold the data we read back with glReadPixels()
-               // (Intel/DRI goes into a slow path if we don't read to PBO)
-               GLenum gl_format = ( output_format == mlt_image_rgb24a || output_format == mlt_image_opengl )?
-                       GL_RGBA : GL_RGB;
-               int img_size = *width * *height * ( gl_format == GL_RGB? 3 : 4 );
-               glsl_pbo pbo = glsl->get_pbo( img_size );
-               glsl_texture texture = glsl->get_texture( *width, *height, gl_format );
-
-               if ( fbo && pbo && texture ) {
-                       // Set the FBO
-                       glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
-                       check_error();
-                       glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
-                       check_error();
-                       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-                       check_error();
-
-                       GlslManager::render( service, chain, fbo->fbo, *width, *height );
-
-                       // Read FBO into PBO
-                       glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, pbo->pbo );
-                       check_error();
-                       glBufferData( GL_PIXEL_PACK_BUFFER_ARB, img_size, NULL, GL_STREAM_READ );
-                       check_error();
-                       glReadPixels( 0, 0, *width, *height, gl_format, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0) );
-                       check_error();
-
-                       // Copy from PBO
-                       uint8_t* buf = (uint8_t*) glMapBuffer( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY );
-                       check_error();
-
-                       *format = gl_format == GL_RGBA ? mlt_image_rgb24a : mlt_image_rgb24;
-                       *image = (uint8_t*) mlt_pool_alloc( img_size );
-                       mlt_frame_set_image( a_frame, *image, img_size, mlt_pool_release );
-                       memcpy( *image, buf, img_size );
-
-                       // Release PBO and FBO
-                       glUnmapBuffer( GL_PIXEL_PACK_BUFFER_ARB );
-                       check_error();
-                       glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, 0 );
-                       check_error();
-                       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-                       check_error();
-                       glBindTexture( GL_TEXTURE_2D, 0 );
-                       check_error();
-                       GlslManager::release_texture( texture );
-               }
-               else {
-                       error = 1;
-               }
+               error = glsl->render_frame_rgba( service, a_frame, *width, *height, image );
+               *format = mlt_image_rgb24a;
        }
-       if ( fbo ) GlslManager::release_fbo( fbo );
        mlt_service_unlock( service );
 
        return error;
index d3f4b5a82dda0326ccef8f174c85edbb0a711572..5273ab838edc82d202154031ef182c336b475542 100644 (file)
@@ -74,83 +74,14 @@ static int get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *form
 
        // Setup rendering to an FBO
        GlslManager* glsl = GlslManager::get_instance();
-       glsl_fbo fbo = glsl->get_fbo( *width, *height );
        if ( output_format == mlt_image_glsl_texture ) {
-               glsl_texture texture = glsl->get_texture( *width, *height, GL_RGBA );
-
-               glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
-               check_error();
-               glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
-               check_error();
-               glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-               check_error();
-
-               GlslManager::render( service, chain, fbo->fbo, *width, *height );
-
-               glFinish();
-               check_error();
-               glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-               check_error();
-
-               *image = (uint8_t*) &texture->texture;
-               mlt_frame_set_image( a_frame, *image, 0, NULL );
-               mlt_properties_set_data( properties, "movit.convert", texture, 0,
-                       (mlt_destructor) GlslManager::release_texture, NULL );
+               error = glsl->render_frame_texture( service, a_frame, *width, *height, image );
                *format = output_format;
        }
        else {
-               // Use a PBO to hold the data we read back with glReadPixels()
-               // (Intel/DRI goes into a slow path if we don't read to PBO)
-               GLenum gl_format = ( output_format == mlt_image_rgb24a || output_format == mlt_image_opengl )?
-                       GL_RGBA : GL_RGB;
-               int img_size = *width * *height * ( gl_format == GL_RGB? 3 : 4 );
-               glsl_pbo pbo = glsl->get_pbo( img_size );
-               glsl_texture texture = glsl->get_texture( *width, *height, gl_format );
-
-               if ( fbo && pbo && texture ) {
-                       // Set the FBO
-                       glBindFramebuffer( GL_FRAMEBUFFER, fbo->fbo );
-                       check_error();
-                       glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->texture, 0 );
-                       check_error();
-                       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-                       check_error();
-
-                       GlslManager::render( service, chain, fbo->fbo, *width, *height );
-
-                       // Read FBO into PBO
-                       glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, pbo->pbo );
-                       check_error();
-                       glBufferData( GL_PIXEL_PACK_BUFFER_ARB, img_size, NULL, GL_STREAM_READ );
-                       check_error();
-                       glReadPixels( 0, 0, *width, *height, gl_format, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0) );
-                       check_error();
-
-                       // Copy from PBO
-                       uint8_t* buf = (uint8_t*) glMapBuffer( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY );
-                       check_error();
-
-                       *format = gl_format == GL_RGBA ? mlt_image_rgb24a : mlt_image_rgb24;
-                       *image = (uint8_t*) mlt_pool_alloc( img_size );
-                       mlt_frame_set_image( a_frame, *image, img_size, mlt_pool_release );
-                       memcpy( *image, buf, img_size );
-
-                       // Release PBO and FBO
-                       glUnmapBuffer( GL_PIXEL_PACK_BUFFER_ARB );
-                       check_error();
-                       glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, 0 );
-                       check_error();
-                       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
-                       check_error();
-                       glBindTexture( GL_TEXTURE_2D, 0 );
-                       check_error();
-                       GlslManager::release_texture( texture );
-               }
-               else {
-                       error = 1;
-               }
+               error = glsl->render_frame_rgba( service, a_frame, *width, *height, image );
+               *format = mlt_image_rgb24a;
        }
-       if ( fbo ) GlslManager::release_fbo( fbo );
        mlt_service_unlock( service );
 
        return error;
@@ -172,8 +103,7 @@ static mlt_frame process( mlt_transition transition, mlt_frame a_frame, mlt_fram
                chain->add_output( output_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED );
                chain->set_dither_bits( 8 );
 
-               Effect* effect = chain->add_effect( new OverlayEffect(),
-                       GlslManager::get_input( service ), b_input );
+               chain->add_effect( new OverlayEffect(), GlslManager::get_input( service ), b_input );
 
                // Save these new input on properties for get_image
                mlt_properties_set_data( MLT_TRANSITION_PROPERTIES(transition),