Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-gpu
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-gpu
Commits
989cefff
Commit
989cefff
authored
Sep 06, 2006
by
Damien Fouilleul
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
- OpenCV video filter module by Dugal Harris
parent
8dde0ccc
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
961 additions
and
0 deletions
+961
-0
AUTHORS
AUTHORS
+5
-0
THANKS
THANKS
+1
-0
configure.ac
configure.ac
+40
-0
modules/video_filter/Modules.am
modules/video_filter/Modules.am
+2
-0
modules/video_filter/filter_event_info.h
modules/video_filter/filter_event_info.h
+59
-0
modules/video_filter/opencv_example.cpp
modules/video_filter/opencv_example.cpp
+235
-0
modules/video_filter/opencv_wrapper.c
modules/video_filter/opencv_wrapper.c
+619
-0
No files found.
AUTHORS
View file @
989cefff
...
...
@@ -200,6 +200,11 @@ D: XVideo video output
D: Gnome and Gtk+ interface enhancements
S: United Kingdom
N: Dugal Harris
E: dugalh (at) protoclea .dot co dot. za
D: OpenCV video filter
S: South Africa
N: Derk-Jan Hartman
E: hartman@videolan.org
C: hartman
...
...
THANKS
View file @
989cefff
...
...
@@ -77,6 +77,7 @@ Jean-Alexis Montignies <ja at sente.ch> - coreaudio multiple streams fix
Jean-Baptiste Kempf <jb at via dot ecp.fr> - Contrib system upgrade
Jean-Baptiste Le Stang <jp.lestand at lestang.org> - Equalizer-GUI-fixes (OSX)
Jean-Philippe Grimaldi <jeanphi at via.ecp.fr> - bug fixes
Dugal Harris <dugalh at protoclea dot. co dot za > - ActiveX bug fixes
Jean-Pierre Kuypers <Kuypers at sri.ucl.ac.be> - French translation
Jeffrey Baker <jwbaker at acm.org> - port of the ALSA plugin to the ALSA 1.0 API
Jeroen Massar <jeroen at unfix dot org> - IPv6 hostname resolution fix
...
...
configure.ac
View file @
989cefff
...
...
@@ -1143,6 +1143,7 @@ VLC_ADD_PLUGINS([access_http access_mms access_ftp ipv4])
VLC_ADD_PLUGINS([packetizer_mpegvideo packetizer_h264])
VLC_ADD_PLUGINS([packetizer_mpeg4video packetizer_mpeg4audio])
if test "${SYS}" != "mingwce"; then
dnl VLC_ADD_PLUGINS([externrun])
VLC_ADD_PLUGINS([access_fake access_filter_timeshift access_filter_record])
...
...
@@ -1873,6 +1874,45 @@ then
fi
fi
dnl
dnl OpenCV wrapper and example filters
dnl
AC_ARG_ENABLE(opencv,
[ --enable-opencv OpenCV (computer vision) filter (default disabled)])
if test "${enable_opencv}" = "yes" -a "${CXX}" != "";
then
AC_ARG_WITH(opencv-tree,
[ --with-opencv-tree=PATH opencv tree for linking])
if test -n "${with_opencv_tree}"
then
if test "${SYS}" = "mingw32" -o "${SYS}" = "cygwin"
then
AC_MSG_CHECKING(for opencv in ${with_opencv_tree})
if test -f ${with_opencv_tree}/cv/include/cv.h -a -f ${with_opencv_tree}/cxcore/include/cxcore.h \
-a -f ${with_opencv_tree}/cvaux/include/cvaux.h -a -f ${with_opencv_tree}/otherlibs/highgui/highgui.h
then
AC_MSG_RESULT(yes)
VLC_ADD_PLUGINS([opencv_wrapper])
VLC_ADD_LDFLAGS([opencv_wrapper],[-L${with_opencv_tree}/lib -lcv -lcxcore -lcvaux -lhighgui])
VLC_ADD_CFLAGS([opencv_wrapper],[-I${with_opencv_tree}/cv/include -I${with_opencv_tree}/cxcore/include -I${with_opencv_tree}/cvaux/include -I${with_opencv_tree}/otherlibs/highgui])
AC_LANG_PUSH(C++)
VLC_ADD_PLUGINS([opencv_example])
VLC_ADD_LDFLAGS([opencv_example],[-L${with_opencv_tree}/lib -lcv -lcxcore -lcvaux -lhighgui])
VLC_ADD_CXXFLAGS([opencv_example],[-I${with_opencv_tree}/cv/include -I${with_opencv_tree}/cxcore/include -I${with_opencv_tree}/cvaux/include -I${with_opencv_tree}/otherlibs/highgui])
AC_LANG_POP(C++)
else
dnl No opencv could be found, sorry
AC_MSG_RESULT(no)
AC_MSG_ERROR([cannot find opencv in ${with_opencv_tree}])
fi
else
AC_MSG_WARN([--enable-opencv currently only works on windows])
fi
fi
fi
dnl
dnl libsmbclient plugin
dnl
...
...
modules/video_filter/Modules.am
View file @
989cefff
...
...
@@ -21,4 +21,6 @@ SOURCES_wave = wave.c
SOURCES_ripple = ripple.c
SOURCES_psychedelic = psychedelic.c
SOURCES_gradient = gradient.c
SOURCES_opencv_wrapper = opencv_wrapper.c
SOURCES_opencv_example = opencv_example.cpp
noinst_HEADERS = filter_common.h
modules/video_filter/filter_event_info.h
0 → 100644
View file @
989cefff
/*****************************************************************************
* opencv_event_info.h:
*****************************************************************************
* Copyright (C) 2004-2005 the VideoLAN team
* $Id: ???
*
* Authors: Dugal Harris
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef FILTER_EVENT_INFO_H_
#define FILTER_EVENT_INFO_H_
#define VIDEO_FILTER_EVENT_VARIABLE N_("video-filter-event")
typedef
struct
video_filter_region_info_t
{
int
i_x
;
/* x-coordinate of the left-most rectangle corner[s] */
int
i_y
;
/* y-coordinate of the top-most or bottom-most
rectangle corner[s] */
int
i_width
;
/* width of the rectangle */
int
i_height
;
/* height of the rectangle */
int
i_id
;
int
i_type
;
char
*
p_description
;
float
*
pf_param
;
int
i_param_size
;
}
video_filter_region_info_t
;
typedef
struct
video_filter_event_info_t
{
video_filter_region_info_t
*
p_region
;
int
i_region_size
;
}
video_filter_event_info_t
;
/*class CTest
{
public:
CTest(){i=0;};
void Method(){i=0;};
int i;
};*/
#endif
/*FILTER_EVENT_INFO_H_*/
modules/video_filter/opencv_example.cpp
0 → 100644
View file @
989cefff
/*****************************************************************************
* opencv_example.cpp : Example OpenCV internal video filter
* (performs face identification). Mostly taken from the facedetect.c
* OpenCV sample.
*****************************************************************************
* Copyright (C) 2006 the VideoLAN team
*
* Authors: Dugal Harris <dugalh@protoclea.co.za>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <cxcore.h>
#include <cv.h>
#include <highgui.h>
#include <vlc/vlc.h>
#include <vlc/decoder.h>
#include "vlc_filter.h"
#include "filter_common.h"
#include "vlc_image.h"
#include "filter_event_info.h"
/*****************************************************************************
* filter_sys_t : filter descriptor
*****************************************************************************/
struct
filter_sys_t
{
CvMemStorage
*
p_storage
;
CvHaarClassifierCascade
*
p_cascade
;
video_filter_event_info_t
event_info
;
int
i_id
;
};
/****************************************************************************
* Local prototypes
****************************************************************************/
static
int
OpenFilter
(
vlc_object_t
*
);
static
void
CloseFilter
(
vlc_object_t
*
);
static
picture_t
*
Filter
(
filter_t
*
,
picture_t
*
);
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin
();
set_description
(
_
(
"OpenCV face detection example filter"
)
);
set_shortname
(
N_
(
"OpenCV example"
));
set_capability
(
"opencv example"
,
1
);
add_shortcut
(
"opencv_example"
);
set_category
(
CAT_VIDEO
);
set_subcategory
(
SUBCAT_VIDEO_VFILTER2
);
set_callbacks
(
OpenFilter
,
CloseFilter
);
add_string
(
"opencv-haarcascade-file"
,
"c:
\\
haarcascade_frontalface_alt.xml"
,
NULL
,
N_
(
"Haar cascade filename"
),
N_
(
"Name of XML file containing Haar cascade description"
),
VLC_FALSE
);
vlc_module_end
();
/*****************************************************************************
* OpenFilter: probe the filter and return score
*****************************************************************************/
static
int
OpenFilter
(
vlc_object_t
*
p_this
)
{
filter_t
*
p_filter
=
(
filter_t
*
)
p_this
;
filter_sys_t
*
p_sys
;
/* Allocate the memory needed to store the decoder's structure */
if
(
(
p_filter
->
p_sys
=
p_sys
=
(
filter_sys_t
*
)
malloc
(
sizeof
(
filter_sys_t
))
)
==
NULL
)
{
msg_Err
(
p_filter
,
"out of memory"
);
return
VLC_EGENERIC
;
}
//init the video_filter_event_info_t struct
p_sys
->
event_info
.
i_region_size
=
0
;
p_sys
->
event_info
.
p_region
=
NULL
;
p_sys
->
i_id
=
0
;
p_filter
->
pf_video_filter
=
Filter
;
//create the VIDEO_FILTER_EVENT_VARIABLE
vlc_value_t
val
;
if
(
var_Create
(
p_filter
->
p_libvlc
,
VIDEO_FILTER_EVENT_VARIABLE
,
VLC_VAR_ADDRESS
|
VLC_VAR_DOINHERIT
)
!=
VLC_SUCCESS
)
msg_Err
(
p_filter
,
"Could not create %s
\n
"
,
VIDEO_FILTER_EVENT_VARIABLE
);
val
.
p_address
=
&
(
p_sys
->
event_info
);
if
(
var_Set
(
p_filter
->
p_libvlc
,
VIDEO_FILTER_EVENT_VARIABLE
,
val
)
!=
VLC_SUCCESS
)
msg_Err
(
p_filter
,
"Could not set %s
\n
"
,
VIDEO_FILTER_EVENT_VARIABLE
);
//OpenCV init specific to this example
char
*
filename
=
config_GetPsz
(
p_filter
,
"opencv-haarcascade-file"
);
p_filter
->
p_sys
->
p_cascade
=
(
CvHaarClassifierCascade
*
)
cvLoad
(
filename
,
0
,
0
,
0
);
p_filter
->
p_sys
->
p_storage
=
cvCreateMemStorage
(
0
);
return
VLC_SUCCESS
;
}
/*****************************************************************************
* CloseFilter: clean up the filter
*****************************************************************************/
static
void
CloseFilter
(
vlc_object_t
*
p_this
)
{
filter_t
*
p_filter
=
(
filter_t
*
)
p_this
;
filter_sys_t
*
p_sys
=
p_filter
->
p_sys
;
if
(
p_filter
->
p_sys
->
p_cascade
)
cvReleaseHaarClassifierCascade
(
&
p_filter
->
p_sys
->
p_cascade
);
if
(
p_filter
->
p_sys
->
p_storage
)
cvReleaseMemStorage
(
&
p_filter
->
p_sys
->
p_storage
);
if
(
NULL
!=
p_filter
->
p_sys
->
event_info
.
p_region
)
free
(
p_filter
->
p_sys
->
event_info
.
p_region
);
free
(
p_sys
);
var_Destroy
(
p_filter
->
p_libvlc
,
VIDEO_FILTER_EVENT_VARIABLE
);
}
/****************************************************************************
* Filter: Check for faces and raises an event when one is found.
****************************************************************************
* p_pic: A picture_t with its p_data_orig member set to an array of
* IplImages (one image for each picture_t plane).
****************************************************************************/
static
picture_t
*
Filter
(
filter_t
*
p_filter
,
picture_t
*
p_pic
)
{
IplImage
**
p_img
=
NULL
;
int
i_planes
=
0
;
CvPoint
pt1
,
pt2
;
int
i
,
scale
=
1
;
if
((
!
p_pic
)
)
{
msg_Err
(
p_filter
,
"no image array"
);
return
NULL
;
}
if
(
!
(
p_pic
->
p_data_orig
))
{
msg_Err
(
p_filter
,
"no image array"
);
return
NULL
;
}
//(hack) cast the picture_t to array of IplImage*
p_img
=
(
IplImage
**
)
p_pic
->
p_data_orig
;
i_planes
=
p_pic
->
i_planes
;
//check the image array for validity
if
((
!
p_img
[
0
]))
//1st plane is 'I' i.e. greyscale
{
msg_Err
(
p_filter
,
"no image"
);
return
NULL
;
}
if
((
p_pic
->
format
.
i_chroma
!=
VLC_FOURCC
(
'I'
,
'4'
,
'2'
,
'0'
)))
{
msg_Err
(
p_filter
,
"wrong chroma - use I420"
);
return
NULL
;
}
if
(
i_planes
<
1
)
{
msg_Err
(
p_filter
,
"no image planes"
);
return
NULL
;
}
//perform face detection
cvClearMemStorage
(
p_filter
->
p_sys
->
p_storage
);
CvSeq
*
faces
=
NULL
;
if
(
p_filter
->
p_sys
->
p_cascade
)
{
//we should make some of these params config variables
faces
=
cvHaarDetectObjects
(
p_img
[
0
],
p_filter
->
p_sys
->
p_cascade
,
p_filter
->
p_sys
->
p_storage
,
1.15
,
5
,
CV_HAAR_DO_CANNY_PRUNING
,
cvSize
(
20
,
20
)
);
//create the video_filter_region_info_t struct
CvRect
*
r
;
if
(
faces
&&
(
faces
->
total
>
0
))
{
//msg_Dbg( p_filter, "Found %d face(s)\n", faces->total );
if
(
NULL
!=
p_filter
->
p_sys
->
event_info
.
p_region
)
{
free
(
p_filter
->
p_sys
->
event_info
.
p_region
);
p_filter
->
p_sys
->
event_info
.
p_region
=
NULL
;
}
if
(
NULL
==
(
p_filter
->
p_sys
->
event_info
.
p_region
=
(
video_filter_region_info_t
*
)
malloc
(
faces
->
total
*
sizeof
(
video_filter_region_info_t
))))
{
msg_Err
(
p_filter
,
"out of memory"
);
return
NULL
;
}
memset
(
p_filter
->
p_sys
->
event_info
.
p_region
,
0
,
faces
->
total
*
sizeof
(
video_filter_region_info_t
));
p_filter
->
p_sys
->
event_info
.
i_region_size
=
faces
->
total
;
}
//populate the video_filter_region_info_t struct
for
(
i
=
0
;
i
<
(
faces
?
faces
->
total
:
0
);
i
++
)
{
r
=
(
CvRect
*
)
cvGetSeqElem
(
faces
,
i
);
pt1
.
x
=
r
->
x
*
scale
;
pt2
.
x
=
(
r
->
x
+
r
->
width
)
*
scale
;
pt1
.
y
=
r
->
y
*
scale
;
pt2
.
y
=
(
r
->
y
+
r
->
height
)
*
scale
;
cvRectangle
(
p_img
[
0
],
pt1
,
pt2
,
CV_RGB
(
0
,
0
,
0
),
3
,
8
,
0
);
*
(
CvRect
*
)(
&
(
p_filter
->
p_sys
->
event_info
.
p_region
[
i
]))
=
*
r
;
p_filter
->
p_sys
->
event_info
.
p_region
[
i
].
i_id
=
p_filter
->
p_sys
->
i_id
++
;
p_filter
->
p_sys
->
event_info
.
p_region
[
i
].
p_description
=
"Face Detected"
;
}
if
(
faces
&&
(
faces
->
total
>
0
))
//raise the video filter event
var_Change
(
p_filter
->
p_libvlc
,
VIDEO_FILTER_EVENT_VARIABLE
,
VLC_VAR_TRIGGER_CALLBACKS
,
NULL
,
NULL
);
}
else
msg_Err
(
p_filter
,
"No cascade - is opencv-haarcascade-file valid?"
);
return
p_pic
;
}
modules/video_filter/opencv_wrapper.c
0 → 100644
View file @
989cefff
/*****************************************************************************
* opencv_wrapper.c : OpenCV wrapper video filter
*****************************************************************************
* Copyright (C) 2006 the VideoLAN team
*
* Authors: Dugal Harris <dugalh@protoclea.co.za>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h>
/* malloc(), free() */
#include <string.h>
#include <cxcore.h>
#include <cv.h>
#include <highgui.h>
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <math.h>
#include <time.h>
#include "vlc_filter.h"
#include "filter_common.h"
#include "charset.h"
#include "vlc_image.h"
#include "vlc_input.h"
#include "vlc_playlist.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static
int
Create
(
vlc_object_t
*
);
static
void
Destroy
(
vlc_object_t
*
);
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
);
/*****************************************************************************
* Module descriptor
*****************************************************************************/
static
char
*
chroma_list
[]
=
{
"input"
,
"I420"
,
"RGB32"
};
static
char
*
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"
),
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"
),
N_
(
"Show errors and warnings"
),
N_
(
"Show everything including debug messages"
)};
vlc_module_begin
();
set_description
(
_
(
"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
);
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
);
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
);
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
);
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
();
/*****************************************************************************
* wrapper_output_t: what video is output
*****************************************************************************/
enum
wrapper_output_t
{
NONE
,
//not working yet
VINPUT
,
PROCESSED
};
/*****************************************************************************
* internal_chroma_t: what chroma is sent to the internal opencv filter
*****************************************************************************/
enum
internal_chroma_t
{
CINPUT
,
GREY
,
RGB
};
/*****************************************************************************
* verbosity_t:
*****************************************************************************/
enum
verbosity_t
{
VERB_ERROR
,
VERB_WARN
,
VERB_DEBUG
};
/*****************************************************************************
* vout_sys_t: opencv_wrapper video output method descriptor
*****************************************************************************
* This structure is part of the video output thread descriptor.
* It describes the opencv_wrapper specific properties of an output thread.
*****************************************************************************/
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
;
};
/*****************************************************************************
* Control: control facility for the vout (forwards to child vout)
*****************************************************************************/
static
int
Control
(
vout_thread_t
*
p_vout
,
int
i_query
,
va_list
args
)
{
return
vout_vaControl
(
p_vout
->
p_sys
->
p_vout
,
i_query
,
args
);
}
/*****************************************************************************
* Create: allocates opencv_wrapper video thread output method
*****************************************************************************
* This function allocates and initializes a opencv_wrapper vout method.
*****************************************************************************/
static
int
Create
(
vlc_object_t
*
p_this
)
{
vout_thread_t
*
p_vout
=
(
vout_thread_t
*
)
p_this
;
char
*
psz_chroma
,
*
psz_output
,
*
psz_verbosity
;
int
i
=
0
;
/* 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
);
for
(
i
=
0
;
i
<
VOUT_MAX_PLANES
;
i
++
)
p_vout
->
p_sys
->
p_cv_image
[
i
]
=
NULL
;
p_vout
->
p_sys
->
p_proc_image
=
NULL
;
p_vout
->
p_sys
->
p_to_be_freed
=
NULL
;
p_vout
->
p_sys
->
i_cv_image_size
=
0
;
p_vout
->
pf_init
=
Init
;
p_vout
->
pf_end
=
End
;
p_vout
->
pf_manage
=
NULL
;
p_vout
->
pf_render
=
Render
;
p_vout
->
pf_display
=
NULL
;
p_vout
->
pf_control
=
Control
;
/* Retrieve and apply config */
if
(
!
(
psz_chroma
=
config_GetPsz
(
p_vout
,
"opencv-chroma"
))
)
{
msg_Err
(
p_vout
,
"configuration variable %s empty, using 'grey'"
,
"opencv-chroma"
);
p_vout
->
p_sys
->
i_internal_chroma
=
GREY
;
}
else
{
if
(
!
strcmp
(
psz_chroma
,
"input"
)
)
p_vout
->
p_sys
->
i_internal_chroma
=
CINPUT
;
else
if
(
!
strcmp
(
psz_chroma
,
"I420"
)
)
p_vout
->
p_sys
->
i_internal_chroma
=
GREY
;
else
if
(
!
strcmp
(
psz_chroma
,
"RGB32"
)
)
p_vout
->
p_sys
->
i_internal_chroma
=
RGB
;
else
{
msg_Err
(
p_vout
,
"no valid opencv-chroma provided, using 'grey'"
);
p_vout
->
p_sys
->
i_internal_chroma
=
GREY
;
}
}
free
(
psz_chroma
);
if
(
!
(
psz_output
=
config_GetPsz
(
p_vout
,
"opencv-output"
))
)
{
msg_Err
(
p_vout
,
"configuration variable %s empty, using 'input'"
,
"opencv-output"
);
p_vout
->
p_sys
->
i_wrapper_output
=
VINPUT
;
}
else
{
if
(
!
strcmp
(
psz_output
,
"none"
)
)
p_vout
->
p_sys
->
i_wrapper_output
=
NONE
;
else
if
(
!
strcmp
(
psz_output
,
"input"
)
)
p_vout
->
p_sys
->
i_wrapper_output
=
VINPUT
;
else
if
(
!
strcmp
(
psz_output
,
"processed"
)
)
p_vout
->
p_sys
->
i_wrapper_output
=
PROCESSED
;
else
{
msg_Err
(
p_vout
,
"no valid opencv-output provided, using 'input'"
);
p_vout
->
p_sys
->
i_wrapper_output
=
VINPUT
;
}
}
free
(
psz_output
);
if
(
!
(
psz_verbosity
=
config_GetPsz
(
p_vout
,
"opencv-verbosity"
))
)
{
msg_Err
(
p_vout
,
"configuration variable %s empty, using 'input'"
,
"opencv-verbosity"
);
p_vout
->
p_sys
->
i_verbosity
=
VERB_ERROR
;
}
else
{
if
(
!
strcmp
(
psz_verbosity
,
"error"
)
)
p_vout
->
p_sys
->
i_verbosity
=
VERB_ERROR
;
else
if
(
!
strcmp
(
psz_verbosity
,
"warning"
)
)
p_vout
->
p_sys
->
i_verbosity
=
VERB_WARN
;
else
if
(
!
strcmp
(
psz_verbosity
,
"debug"
)
)
p_vout
->
p_sys
->
i_verbosity
=
VERB_DEBUG
;
else
{
msg_Err
(
p_vout
,
"no valid opencv-verbosity provided, using 'error'"
);
p_vout
->
p_sys
->
i_verbosity
=
VERB_ERROR
;
}
}
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"
);
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"
,
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
;
}
/*****************************************************************************
* Init: initialize opencv_wrapper video thread output method
*****************************************************************************/
static
int
Init
(
vout_thread_t
*
p_vout
)
{
int
i_index
;
picture_t
*
p_pic
;
video_format_t
fmt
=
{
0
};
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
I_OUTPUTPICTURES
=
0
;
/* Initialize the output video format */
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
{
fmt
.
i_width
=
fmt
.
i_width
*
p_sys
->
f_scale
;
fmt
.
i_height
=
fmt
.
i_height
*
p_sys
->
f_scale
;
fmt
.
i_visible_width
=
fmt
.
i_visible_width
*
p_sys
->
f_scale
;
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'
);
else
if
(
p_sys
->
i_internal_chroma
==
RGB
)
fmt
.
i_chroma
=
VLC_FOURCC
(
'R'
,
'V'
,
'3'
,
'2'
);
}
/* 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
);
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
);
p_sys
->
p_opencv
=
NULL
;
}
/* Try to open the real video output */
if
(
p_sys
->
i_verbosity
>
VERB_WARN
)
msg_Dbg
(
p_vout
,
"spawning the real video output"
);
p_vout
->
p_sys
->
p_vout
=
vout_Create
(
p_vout
,
&
fmt
);
/* Everything failed */
if
(
p_vout
->
p_sys
->
p_vout
==
NULL
)
{
msg_Err
(
p_vout
,
"can't open vout, aborting"
);
return
VLC_EGENERIC
;
}
ALLOCATE_DIRECTBUFFERS
(
VOUT_MAX_PICTURES
);
ADD_CALLBACKS
(
p_vout
->
p_sys
->
p_vout
,
SendEvents
);
ADD_PARENT_CALLBACKS
(
SendEventsToChild
);
return
VLC_SUCCESS
;
}
/*****************************************************************************
* End: terminate opencv_wrapper video thread output method
*****************************************************************************/
static
void
End
(
vout_thread_t
*
p_vout
)
{
int
i_index
;
/* 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
)
{
//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
;
}
}
/*****************************************************************************
* Destroy: destroy opencv_wrapper video thread output method
*****************************************************************************
* Terminate an output method created by opencv_wrapperCreateOutputMethod
*****************************************************************************/
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
);
}
/*****************************************************************************
* ReleaseImages: Release OpenCV images in vout_sys_t.
*****************************************************************************/
static
void
ReleaseImages
(
vout_thread_t
*
p_vout
)
{
int
i
=
0
;
if
(
p_vout
->
p_sys
->
p_cv_image
)
{
for
(
i
=
0
;
i
<
VOUT_MAX_PLANES
;
i
++
)
{
if
(
p_vout
->
p_sys
->
p_cv_image
[
i
])
cvReleaseImageHeader
(
&
(
p_vout
->
p_sys
->
p_cv_image
[
i
]));
p_vout
->
p_sys
->
p_cv_image
[
i
]
=
NULL
;
}
}
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
);
p_vout
->
p_sys
->
p_to_be_freed
=
NULL
;
}
if
(
p_vout
->
p_sys
->
i_verbosity
>
VERB_WARN
)
msg_Dbg
(
p_vout
,
"images released"
);
}
/*****************************************************************************
* VlcPictureToIplImage: Convert picture_t to IplImage
*****************************************************************************
* Converts given picture_t into IplImage(s) according to module config.
* IplImage(s) are stored in vout_sys_t.
*****************************************************************************/
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
CvSize
sz
=
cvSize
(
abs
(
p_in
->
format
.
i_width
),
abs
(
p_in
->
format
.
i_height
));
video_format_t
fmt_out
=
{
0
};
clock_t
start
,
finish
;
//performance measures
double
duration
;
int
i
=
0
;
vout_sys_t
*
p_sys
=
p_vout
->
p_sys
;
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
;
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
//and I cant think of an easy way to fix this
fmt_out
.
i_chroma
=
VLC_FOURCC
(
'R'
,
'V'
,
'3'
,
'2'
);
}
else
if
(
p_sys
->
i_internal_chroma
==
GREY
)
{
//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'
);
}
//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))
{
//use the input image without conversion
p_sys
->
p_proc_image
=
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
;
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
),
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_proc_image
->
p
[
i
].
i_pixel_pitch
);
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
//another video filter
p_sys
->
hacked_pic
.
p_data_orig
=
p_sys
->
p_cv_image
;
p_sys
->
hacked_pic
.
i_planes
=
planes
;
p_sys
->
hacked_pic
.
format
.
i_chroma
=
fmt_out
.
i_chroma
;
//calculate duration of conversion
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
);
}
/*****************************************************************************
* Render: displays previously rendered output
*****************************************************************************
* This function send the currently rendered image to the internal opencv
* filter for processing.
*****************************************************************************/
static
void
Render
(
vout_thread_t
*
p_vout
,
picture_t
*
p_pic
)
{
picture_t
*
p_outpic
=
NULL
;
clock_t
start
,
finish
;
double
duration
;
while
(
(
p_outpic
=
vout_CreatePicture
(
p_vout
->
p_sys
->
p_vout
,
0
,
0
,
0
)
)
==
NULL
)
{
if
(
p_vout
->
b_die
||
p_vout
->
b_error
)
{
return
;
}
msleep
(
VOUT_OUTMEM_SLEEP
);
}
vout_LinkPicture
(
p_vout
->
p_sys
->
p_vout
,
p_outpic
);
start
=
clock
();
if
(
p_vout
->
p_sys
->
i_wrapper_output
==
VINPUT
)
//output = input video
{
//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
);
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
))
p_vout
->
p_sys
->
p_opencv
->
pf_video_filter
(
p_vout
->
p_sys
->
p_opencv
,
&
(
p_vout
->
p_sys
->
hacked_pic
));
}
else
//output = processed video (NONE option not working yet)
{
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
))
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
);
}
//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
);
ReleaseImages
(
p_vout
);
vout_DatePicture
(
p_vout
->
p_sys
->
p_vout
,
p_outpic
,
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
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment