X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_filter%2Fopencv_wrapper.c;h=5025c02c23479478007b08318881d254ccfb0fe3;hb=c60652e38ac6afd74bd8225e9dae5406f13aaa4f;hp=36a64ecbfb784e2415dd66c6de571062d1da5bf2;hpb=12efe797994da9153a6c1275f28631888d3d2a80;p=vlc diff --git a/modules/video_filter/opencv_wrapper.c b/modules/video_filter/opencv_wrapper.c index 36a64ecbfb..5025c02c23 100644 --- a/modules/video_filter/opencv_wrapper.c +++ b/modules/video_filter/opencv_wrapper.c @@ -23,25 +23,25 @@ /***************************************************************************** * Preamble *****************************************************************************/ -#include /* malloc(), free() */ -#include -#include -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif -#include -#include +#include +#include +#include +#include #include #include -#include "vlc_filter.h" -#include "filter_common.h" -#include "charset.h" -#include "vlc_image.h" -#include "vlc_input.h" -#include "vlc_playlist.h" +#include +#include +#include + +#include +#include /***************************************************************************** @@ -54,8 +54,6 @@ static int Init ( vout_thread_t * ); static void End ( vout_thread_t * ); static void Render ( vout_thread_t *, picture_t * ); -static int SendEvents( vlc_object_t *, char const *, - vlc_value_t, vlc_value_t, void * ); static void ReleaseImages( vout_thread_t *p_vout ); static void VlcPictureToIplImage( vout_thread_t *p_vout, picture_t *p_in ); @@ -63,46 +61,46 @@ static void VlcPictureToIplImage( vout_thread_t *p_vout, picture_t *p_in ); * Module descriptor *****************************************************************************/ -static char *chroma_list[] = { "input", "I420", "RGB32"}; -static char *chroma_list_text[] = { N_("Use input chroma unaltered"), +static const char *const chroma_list[] = { "input", "I420", "RGB32"}; +static const char *const chroma_list_text[] = { N_("Use input chroma unaltered"), N_("I420 - first plane is greyscale"), N_("RGB32")}; -static char *output_list[] = { "none", "input", "processed"}; -static char *output_list_text[] = { N_("Don't display any video"), +static const char *const output_list[] = { "none", "input", "processed"}; +static const char *const output_list_text[] = { N_("Don't display any video"), N_("Display the input video"), N_("Display the processed video")}; -static char *verbosity_list[] = { "error", "warning", "debug"}; -static char *verbosity_list_text[] = { N_("Show only errors"), +static const char *const verbosity_list[] = { "error", "warning", "debug"}; +static const char *const verbosity_list_text[] = { N_("Show only errors"), N_("Show errors and warnings"), N_("Show everything including debug messages")}; -vlc_module_begin(); - set_description( _("OpenCV video filter wrapper") ); - set_shortname( _("OpenCV" )); - set_category( CAT_VIDEO ); - set_subcategory( SUBCAT_VIDEO_VFILTER ); - set_capability( "video filter", 0 ); - add_shortcut( "opencv_wrapper" ); - set_callbacks( Create, Destroy ); +vlc_module_begin () + set_description( N_("OpenCV video filter wrapper") ) + set_shortname( N_("OpenCV" )) + set_category( CAT_VIDEO ) + set_subcategory( SUBCAT_VIDEO_VFILTER ) + set_capability( "video filter", 0 ) + add_shortcut( "opencv_wrapper" ) + set_callbacks( Create, Destroy ) add_float_with_range( "opencv-scale", 1.0, 0.1, 2.0, NULL, - N_("Scale factor (0.1-2.0)"), - N_("Ammount by which to scale the picture before sending it to the internal OpenCV filter"), - VLC_FALSE ); + N_("Scale factor (0.1-2.0)"), + N_("Ammount by which to scale the picture before sending it to the internal OpenCV filter"), + false ) add_string( "opencv-chroma", "input", NULL, - N_("OpenCV filter chroma"), - N_("Chroma to convert picture to before sending it to the internal OpenCV filter"), VLC_FALSE); + N_("OpenCV filter chroma"), + N_("Chroma to convert picture to before sending it to the internal OpenCV filter"), false); change_string_list( chroma_list, chroma_list_text, 0); add_string( "opencv-output", "input", NULL, - N_("Wrapper filter output"), - N_("Determines what (if any) video is displayed by the wrapper filter"), VLC_FALSE); + N_("Wrapper filter output"), + N_("Determines what (if any) video is displayed by the wrapper filter"), false); change_string_list( output_list, output_list_text, 0); add_string( "opencv-verbosity", "error", NULL, - N_("Wrapper filter verbosity"), - N_("Determines wrapper filter verbosity level"), VLC_FALSE); + N_("Wrapper filter verbosity"), + N_("Determines wrapper filter verbosity level"), false); change_string_list( verbosity_list, verbosity_list_text, 0); add_string( "opencv-filter-name", "none", NULL, - N_("OpenCV internal filter name"), - N_("Name of internal OpenCV plugin filter to use"), VLC_FALSE); -vlc_module_end(); + N_("OpenCV internal filter name"), + N_("Name of internal OpenCV plugin filter to use"), false); +vlc_module_end () /***************************************************************************** @@ -126,7 +124,7 @@ enum internal_chroma_t }; /***************************************************************************** - * verbosity_t: + * verbosity_t: *****************************************************************************/ enum verbosity_t { @@ -134,7 +132,7 @@ enum verbosity_t VERB_WARN, VERB_DEBUG }; - + /***************************************************************************** * vout_sys_t: opencv_wrapper video output method descriptor ***************************************************************************** @@ -146,23 +144,23 @@ struct vout_sys_t vout_thread_t *p_vout; image_handler_t *p_image; - + int i_cv_image_size; - + picture_t *p_proc_image; picture_t *p_to_be_freed; - + float f_scale; - + int i_wrapper_output; int i_internal_chroma; int i_verbosity; IplImage *p_cv_image[VOUT_MAX_PLANES]; - + filter_t *p_opencv; char* psz_inner_name; - + picture_t hacked_pic; }; @@ -188,10 +186,7 @@ static int Create( vlc_object_t *p_this ) /* Allocate structure */ p_vout->p_sys = malloc( sizeof( vout_sys_t ) ); if( p_vout->p_sys == NULL ) - { - msg_Err( p_vout, "out of memory" ); return VLC_ENOMEM; - } /* Init structure */ p_vout->p_sys->p_image = image_HandlerCreate( p_vout ); @@ -209,7 +204,8 @@ static int Create( vlc_object_t *p_this ) p_vout->pf_control = Control; /* Retrieve and apply config */ - if( !(psz_chroma = config_GetPsz( p_vout, "opencv-chroma" )) ) + psz_chroma = var_InheritString( p_vout, "opencv-chroma" ); + if( psz_chroma == NULL ) { msg_Err( p_vout, "configuration variable %s empty, using 'grey'", "opencv-chroma" ); @@ -231,7 +227,8 @@ static int Create( vlc_object_t *p_this ) } free( psz_chroma); - if( !(psz_output = config_GetPsz( p_vout, "opencv-output" )) ) + psz_output = var_InheritString( p_vout, "opencv-output" ); + if( psz_output == NULL ) { msg_Err( p_vout, "configuration variable %s empty, using 'input'", "opencv-output" ); @@ -253,7 +250,8 @@ static int Create( vlc_object_t *p_this ) } free( psz_output); - if( !(psz_verbosity = config_GetPsz( p_vout, "opencv-verbosity" )) ) + psz_verbosity = var_InheritString( p_vout, "opencv-verbosity" ); + if( psz_verbosity == NULL ) { msg_Err( p_vout, "configuration variable %s empty, using 'input'", "opencv-verbosity" ); @@ -275,20 +273,20 @@ static int Create( vlc_object_t *p_this ) } free( psz_verbosity); - p_vout->p_sys->psz_inner_name = config_GetPsz( p_vout, "opencv-filter-name" ); - - p_vout->p_sys->f_scale = - config_GetFloat( p_vout, "opencv-scale" ); + p_vout->p_sys->psz_inner_name = + var_InheritString( p_vout, "opencv-filter-name" ); + p_vout->p_sys->f_scale = + var_InheritFloat( p_vout, "opencv-scale" ); if (p_vout->p_sys->i_verbosity > VERB_WARN) msg_Info(p_vout, "Configuration: opencv-scale: %f, opencv-chroma: %d, " - "opencv-output: %d, opencv-verbosity %d, opencv-filter %s", + "opencv-output: %d, opencv-verbosity %d, opencv-filter %s", p_vout->p_sys->f_scale, p_vout->p_sys->i_internal_chroma, p_vout->p_sys->i_wrapper_output, p_vout->p_sys->i_verbosity, p_vout->p_sys->psz_inner_name); - + return VLC_SUCCESS; } @@ -297,19 +295,18 @@ static int Create( vlc_object_t *p_this ) *****************************************************************************/ static int Init( vout_thread_t *p_vout ) { - int i_index; - picture_t *p_pic; - video_format_t fmt = {0}; + video_format_t fmt; vout_sys_t *p_sys = p_vout->p_sys; I_OUTPUTPICTURES = 0; /* Initialize the output video format */ + memset( &fmt, 0, sizeof(video_format_t) ); p_vout->output.i_chroma = p_vout->render.i_chroma; p_vout->output.i_width = p_vout->render.i_width; p_vout->output.i_height = p_vout->render.i_height; p_vout->output.i_aspect = p_vout->render.i_aspect; p_vout->fmt_out = p_vout->fmt_in; //set to input video format - + fmt = p_vout->fmt_out; if (p_sys->i_wrapper_output == PROCESSED) //set to processed video format { @@ -319,28 +316,27 @@ static int Init( vout_thread_t *p_vout ) fmt.i_visible_height = fmt.i_visible_height * p_sys->f_scale; fmt.i_x_offset = fmt.i_x_offset * p_sys->f_scale; fmt.i_y_offset = fmt.i_y_offset * p_sys->f_scale; - + if (p_sys->i_internal_chroma == GREY) - fmt.i_chroma = VLC_FOURCC('I','4','2','0'); + fmt.i_chroma = VLC_CODEC_I420; else if (p_sys->i_internal_chroma == RGB) - fmt.i_chroma = VLC_FOURCC('R','V','3','2'); + fmt.i_chroma = VLC_CODEC_RGB32; } /* Load the internal opencv filter */ /* We don't need to set up video formats for this filter as it not actually using a picture_t */ p_sys->p_opencv = vlc_object_create( p_vout, sizeof(filter_t) ); vlc_object_attach( p_sys->p_opencv, p_vout ); - + if (p_vout->p_sys->psz_inner_name) p_sys->p_opencv->p_module = - module_Need( p_sys->p_opencv, p_sys->psz_inner_name, 0, 0 ); - + module_need( p_sys->p_opencv, p_sys->psz_inner_name, NULL, false ); + if( !p_sys->p_opencv->p_module ) { msg_Err( p_vout, "can't open internal opencv filter: %s", p_vout->p_sys->psz_inner_name ); p_vout->p_sys->psz_inner_name = NULL; - vlc_object_detach( p_sys->p_opencv ); - vlc_object_destroy( p_sys->p_opencv ); + vlc_object_release( p_sys->p_opencv ); p_sys->p_opencv = NULL; } @@ -357,11 +353,9 @@ static int Init( vout_thread_t *p_vout ) return VLC_EGENERIC; } - ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES ); - - ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents ); + vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES ); - ADD_PARENT_CALLBACKS( SendEventsToChild ); + vout_filter_AddChild( p_vout, p_vout->p_sys->p_vout, NULL ); return VLC_SUCCESS; } @@ -371,25 +365,21 @@ static int Init( vout_thread_t *p_vout ) *****************************************************************************/ static void End( vout_thread_t *p_vout ) { - int i_index; + vout_sys_t *p_sys = p_vout->p_sys; - /* Free the fake output buffers we allocated */ - for( i_index = I_OUTPUTPICTURES ; i_index ; ) - { - i_index--; - free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig ); - } - - if ( p_vout->p_sys->p_opencv ) + vout_filter_DelChild( p_vout, p_sys->p_vout, NULL ); + vout_CloseAndRelease( p_sys->p_vout ); + + vout_filter_ReleaseDirectBuffers( p_vout ); + + if( p_sys->p_opencv ) { //release the internal opencv filter - if( p_vout->p_sys->p_opencv->p_module ) - module_Unneed( p_vout->p_sys->p_opencv, p_vout->p_sys->p_opencv->p_module ); - vlc_object_detach( p_vout->p_sys->p_opencv ); - vlc_object_destroy( p_vout->p_sys->p_opencv ); - p_vout->p_sys->p_opencv = NULL; + if( p_sys->p_opencv->p_module ) + module_unneed( p_sys->p_opencv, p_sys->p_opencv->p_module ); + vlc_object_release( p_sys->p_opencv ); + p_sys->p_opencv = NULL; } - } /***************************************************************************** @@ -401,20 +391,11 @@ static void Destroy( vlc_object_t *p_this ) { vout_thread_t *p_vout = (vout_thread_t *)p_this; - if( p_vout->p_sys->p_vout ) - { - DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents ); - vlc_object_detach( p_vout->p_sys->p_vout ); - vout_Destroy( p_vout->p_sys->p_vout ); - } - - DEL_PARENT_CALLBACKS( SendEventsToChild ); - ReleaseImages(p_vout); if( p_vout->p_sys->p_image ) image_HandlerDelete( p_vout->p_sys->p_image ); - + free( p_vout->p_sys ); } @@ -434,11 +415,11 @@ static void ReleaseImages(vout_thread_t *p_vout) } } p_vout->p_sys->i_cv_image_size = 0; - + /* Release temp picture_t if it exists */ if (p_vout->p_sys->p_to_be_freed) { - p_vout->p_sys->p_to_be_freed->pf_release( p_vout->p_sys->p_to_be_freed ); + picture_Release( p_vout->p_sys->p_to_be_freed ); p_vout->p_sys->p_to_be_freed = NULL; } if (p_vout->p_sys->i_verbosity > VERB_WARN) @@ -454,51 +435,53 @@ static void ReleaseImages(vout_thread_t *p_vout) static void VlcPictureToIplImage( vout_thread_t *p_vout, picture_t *p_in ) { int planes = p_in->i_planes; //num input video planes - // input video size + // input video size CvSize sz = cvSize(abs(p_in->format.i_width), abs(p_in->format.i_height)); - video_format_t fmt_out = {0}; + video_format_t fmt_out; clock_t start, finish; //performance measures double duration; int i = 0; vout_sys_t* p_sys = p_vout->p_sys; - + + memset( &fmt_out, 0, sizeof(video_format_t) ); + start = clock(); //do scale / color conversion according to p_sys config if ((p_sys->f_scale != 1) || (p_sys->i_internal_chroma != CINPUT)) { fmt_out = p_in->format; - + //calc the scaled video size fmt_out.i_width = p_in->format.i_width * p_sys->f_scale; - fmt_out.i_height = p_in->format.i_height * p_sys->f_scale; + fmt_out.i_height = p_in->format.i_height * p_sys->f_scale; if (p_sys->i_internal_chroma == RGB) { //rgb2 gives 3 separate planes, this gives 1 interleaved plane - //rv24 gives is about 20% faster but gives r&b the wrong way round + //rv24 gives is about 20% faster but gives r&b the wrong way round //and I cant think of an easy way to fix this - fmt_out.i_chroma = VLC_FOURCC('R','V','3','2'); + fmt_out.i_chroma = VLC_CODEC_RGB32; } else if (p_sys->i_internal_chroma == GREY) { - //take the I (gray) plane (video seems to commonly be in this fmt so usually the + //take the I (gray) plane (video seems to commonly be in this fmt so usually the //conversion does nothing) - fmt_out.i_chroma = VLC_FOURCC('I','4','2','0'); + fmt_out.i_chroma = VLC_CODEC_I420; } //convert from the input image p_sys->p_proc_image = image_Convert( p_sys->p_image, p_in, &(p_in->format), &fmt_out ); - + if (!p_sys->p_proc_image) { msg_Err(p_vout, "can't convert (unsupported formats?), aborting..."); return; - } + } p_sys->p_to_be_freed = p_sys->p_proc_image; //remember this so we can free it later - + } else //((p_sys->f_scale != 1) || (p_sys->i_internal_chroma != CINPUT)) { @@ -509,22 +492,22 @@ static void VlcPictureToIplImage( vout_thread_t *p_vout, picture_t *p_in ) //Convert to the IplImage array that is to be processed. //If there are multiple planes in p_sys->p_proc_image, then 1 IplImage //is created for each plane. - planes = p_sys->p_proc_image->i_planes; + planes = p_sys->p_proc_image->i_planes; p_sys->i_cv_image_size = planes; for ( i = 0; i < planes; i++ ) { - sz = cvSize(abs(p_sys->p_proc_image->p[i].i_visible_pitch / - p_sys->p_proc_image->p[i].i_pixel_pitch), + sz = cvSize(abs(p_sys->p_proc_image->p[i].i_visible_pitch / + p_sys->p_proc_image->p[i].i_pixel_pitch), abs(p_sys->p_proc_image->p[i].i_visible_lines)); - p_sys->p_cv_image[i] = cvCreateImageHeader(sz, IPL_DEPTH_8U, + p_sys->p_cv_image[i] = cvCreateImageHeader(sz, IPL_DEPTH_8U, p_sys->p_proc_image->p[i].i_pixel_pitch); - cvSetData( p_sys->p_cv_image[i], + cvSetData( p_sys->p_cv_image[i], (char*)(p_sys->p_proc_image->p[i].p_pixels), p_sys->p_proc_image->p[i].i_pitch ); } - //Hack the above opencv image array into a picture_t so that it can be sent to + //Hack the above opencv image array into a picture_t so that it can be sent to //another video filter p_sys->hacked_pic.p_data_orig = p_sys->p_cv_image; p_sys->hacked_pic.i_planes = planes; @@ -534,7 +517,7 @@ static void VlcPictureToIplImage( vout_thread_t *p_vout, picture_t *p_in ) finish = clock(); duration = (double)(finish - start) / CLOCKS_PER_SEC; if (p_sys->i_verbosity > VERB_WARN) - msg_Dbg( p_vout, "VlcPictureToIplImageRgb took %2.4f seconds\n", duration ); + msg_Dbg( p_vout, "VlcPictureToIplImageRgb took %2.4f seconds", duration ); } /***************************************************************************** @@ -552,7 +535,7 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic ) while( ( p_outpic = vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 ) ) == NULL ) { - if( p_vout->b_die || p_vout->b_error ) + if( !vlc_object_alive (p_vout) || p_vout->b_error ) { return; } msleep( VOUT_OUTMEM_SLEEP ); } @@ -566,7 +549,7 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic ) //This copy is a bit unfortunate but image_Convert can't write into an existing image so it is better to copy the //(say) 16bit YUV image here than a 32bit RGB image somehwere else. //It is also not that expensive in time. - vout_CopyPicture( p_vout, p_outpic, p_pic ); + picture_Copy( p_outpic, p_pic ); VlcPictureToIplImage( p_vout, p_pic); //pass the image to the internal opencv filter for processing if ((p_vout->p_sys->p_opencv) && (p_vout->p_sys->p_opencv->p_module)) @@ -579,41 +562,20 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic ) if ((p_vout->p_sys->p_opencv) && (p_vout->p_sys->p_opencv->p_module)) p_vout->p_sys->p_opencv->pf_video_filter( p_vout->p_sys->p_opencv, &(p_vout->p_sys->hacked_pic)); //copy the processed image into the output image - if ((p_vout->p_sys->p_proc_image) && (p_vout->p_sys->p_proc_image->p_data)) - vout_CopyPicture( p_vout, p_outpic, p_vout->p_sys->p_proc_image ); - } + if ((p_vout->p_sys->p_proc_image) && (p_vout->p_sys->p_proc_image->i_planes > 0)) + picture_Copy( p_outpic, p_vout->p_sys->p_proc_image ); + } //calculate duration finish = clock(); duration = (double)(finish - start) / CLOCKS_PER_SEC; if (p_vout->p_sys->i_verbosity > VERB_WARN) - msg_Dbg( p_vout, "Render took %2.4f seconds\n", duration ); + msg_Dbg( p_vout, "Render took %2.4f seconds", duration ); ReleaseImages(p_vout); - vout_DatePicture( p_vout->p_sys->p_vout, p_outpic, p_pic->date ); - + p_outpic->date = p_pic->date; + vout_UnlinkPicture( p_vout->p_sys->p_vout, p_outpic ); vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic ); } -/***************************************************************************** - * SendEvents: forward mouse and keyboard events to the parent p_vout - *****************************************************************************/ -static int SendEvents( vlc_object_t *p_this, char const *psz_var, - vlc_value_t oldval, vlc_value_t newval, void *p_data ) -{ - var_Set( (vlc_object_t *)p_data, psz_var, newval ); - - return VLC_SUCCESS; -} - -/***************************************************************************** - * SendEventsToChild: forward events to the child/children vout - *****************************************************************************/ -static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var, - vlc_value_t oldval, vlc_value_t newval, void *p_data ) -{ - vout_thread_t *p_vout = (vout_thread_t *)p_this; - var_Set( p_vout->p_sys->p_vout, psz_var, newval ); - return VLC_SUCCESS; -}