From: Dan Dennedy Date: Tue, 31 Dec 2013 04:05:20 +0000 (-0800) Subject: Refactor movit.convert, movit.mix, and movit.overlay. X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=a615b9e1275a17404b5fe3a4f00c475c19f7ce5c;p=mlt Refactor movit.convert, movit.mix, and movit.overlay. 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). --- diff --git a/src/modules/opengl/filter_glsl_manager.cpp b/src/modules/opengl/filter_glsl_manager.cpp index a09f8099..cd479b74 100644 --- a/src/modules/opengl/filter_glsl_manager.cpp +++ b/src/modules/opengl/filter_glsl_manager.cpp @@ -22,6 +22,7 @@ #include #include "glsl_manager.h" #include +#include #include #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 ) ) ); diff --git a/src/modules/opengl/filter_movit_convert.cpp b/src/modules/opengl/filter_movit_convert.cpp index 4d102db7..124cb34f 100644 --- a/src/modules/opengl/filter_movit_convert.cpp +++ b/src/modules/opengl/filter_movit_convert.cpp @@ -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 ); diff --git a/src/modules/opengl/glsl_manager.h b/src/modules/opengl/glsl_manager.h index 88431a16..fe968dc8 100644 --- a/src/modules/opengl/glsl_manager.h +++ b/src/modules/opengl/glsl_manager.h @@ -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); diff --git a/src/modules/opengl/transition_movit_mix.cpp b/src/modules/opengl/transition_movit_mix.cpp index e05c7eab..ec02752f 100644 --- a/src/modules/opengl/transition_movit_mix.cpp +++ b/src/modules/opengl/transition_movit_mix.cpp @@ -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; diff --git a/src/modules/opengl/transition_movit_overlay.cpp b/src/modules/opengl/transition_movit_overlay.cpp index d3f4b5a8..5273ab83 100644 --- a/src/modules/opengl/transition_movit_overlay.cpp +++ b/src/modules/opengl/transition_movit_overlay.cpp @@ -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),