#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"
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 );
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 ) ) );
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();
}
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 );
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 );
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);
// 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;
// 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;
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),