36 |
40 |
41 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/src/core/XImage.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | cam2web - streaming camera to web
3 |
4 | Copyright (C) 2017-2019, cvsandbox, cvsandbox@gmail.com
5 |
6 | This program is free software; you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation; either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License along
17 | with this program; if not, write to the Free Software Foundation, Inc.,
18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | #ifndef XIMAGE_HPP
22 | #define XIMAGE_HPP
23 |
24 | #include
25 |
26 | #include "XInterfaces.hpp"
27 | #include "XError.hpp"
28 |
29 | enum class XPixelFormat
30 | {
31 | Unknown = 0,
32 | Grayscale8,
33 | RGB24,
34 | RGBA32,
35 |
36 | JPEG,
37 | // Enough for this project
38 | };
39 |
40 | enum
41 | {
42 | RedIndex = 0,
43 | GreenIndex = 1,
44 | BlueIndex = 2
45 | };
46 |
47 | // Definition of ARGB color type
48 | typedef union
49 | {
50 | uint32_t argb;
51 | struct
52 | {
53 | uint8_t b;
54 | uint8_t g;
55 | uint8_t r;
56 | uint8_t a;
57 | }
58 | components;
59 | }
60 | xargb;
61 |
62 | // A very close approximation of the famous BT709 Grayscale coefficients: (0.2125, 0.7154, 0.0721)
63 | // Pre-multiplied by 0x10000, so integer grayscaling could be done
64 | #define GRAY_COEF_RED (0x3666)
65 | #define GRAY_COEF_GREEN (0xB724)
66 | #define GRAY_COEF_BLUE (0x1276)
67 |
68 | // A macro to get gray value (intensity) out of RGB values
69 | #define RGB_TO_GRAY(r, g, b) ((uint32_t) ( GRAY_COEF_RED * (r) + GRAY_COEF_GREEN * (g) + GRAY_COEF_BLUE * (b) ) >> 16 )
70 |
71 |
72 | // Class encapsulating image data
73 | class XImage : private Uncopyable
74 | {
75 | private:
76 | XImage( uint8_t* data, int32_t width, int32_t height, int32_t stride, XPixelFormat format, bool ownMemory );
77 |
78 | public:
79 | ~XImage( );
80 |
81 | // Allocate image of the specified size and format
82 | static std::shared_ptr Allocate( int32_t width, int32_t height, XPixelFormat format, bool zeroInitialize = false );
83 | // Create image by wrapping existing memory buffer
84 | static std::shared_ptr Create( uint8_t* data, int32_t width, int32_t height, int32_t stride, XPixelFormat format );
85 |
86 | // Clone image - make a deep copy of it
87 | std::shared_ptr Clone( ) const;
88 | // Copy content of the image - destination image must have same width/height/format
89 | XError CopyData( const std::shared_ptr& copyTo ) const;
90 | // Copy content of the image into the specified one if its size/format is same or make a clone
91 | XError CopyDataOrClone( std::shared_ptr& copyTo ) const;
92 |
93 | // Image properties
94 | int32_t Width( ) const { return mWidth; }
95 | int32_t Height( ) const { return mHeight; }
96 | int32_t Stride( ) const { return mStride; }
97 | XPixelFormat Format( ) const { return mFormat; }
98 | // Raw data of the image
99 | uint8_t* Data( ) const { return mData; }
100 |
101 | private:
102 | uint8_t* mData;
103 | int32_t mWidth;
104 | int32_t mHeight;
105 | int32_t mStride;
106 | XPixelFormat mFormat;
107 | bool mOwnMemory;
108 | };
109 |
110 | #endif // XIMAGE_HPP
111 |
--------------------------------------------------------------------------------
/src/core/XVideoFrameDecorator.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | cam2web - streaming camera to web
3 |
4 | Copyright (C) 2017-2019, cvsandbox, cvsandbox@gmail.com
5 |
6 | This program is free software; you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation; either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License along
17 | with this program; if not, write to the Free Software Foundation, Inc.,
18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | #include "XVideoFrameDecorator.hpp"
22 | #include "XImageDrawing.hpp"
23 | #include
24 |
25 | using namespace std;
26 |
27 | XVideoFrameDecorator::XVideoFrameDecorator( ) :
28 | cameraTitle( ),
29 | addTimestampOverlay( false ),
30 | addCameraTitleOverlay( false ),
31 | overlayTextColor( { 0xFF000000 } ),
32 | overlayBackgroundColor( { 0xFFFFFFFF } )
33 | {
34 |
35 | }
36 |
37 | // Decorate the video frame coming from video source
38 | void XVideoFrameDecorator::OnNewImage( const shared_ptr& image )
39 | {
40 | string overlay;
41 |
42 | if ( addTimestampOverlay )
43 | {
44 | std::time_t time = std::time( 0 );
45 | std::tm* now = std::localtime( &time );
46 | char buffer[32];
47 |
48 | sprintf( buffer, "%02d/%02d/%02d %02d:%02d:%02d", now->tm_year - 100, now->tm_mon + 1, now->tm_mday,
49 | now->tm_hour, now->tm_min, now->tm_sec );
50 |
51 | overlay = buffer;
52 | }
53 |
54 | if ( ( addCameraTitleOverlay ) && ( !cameraTitle.empty( ) ) )
55 | {
56 | if ( !overlay.empty( ) )
57 | {
58 | overlay += " :: ";
59 | }
60 |
61 | overlay += cameraTitle;
62 | }
63 |
64 | if ( !overlay.empty( ) )
65 | {
66 | XImageDrawing::PutText( image, overlay, 0, 0, overlayTextColor, overlayBackgroundColor );
67 | }
68 | }
69 |
70 | // Get/Set camera title
71 | string XVideoFrameDecorator::CameraTitle( ) const
72 | {
73 | return cameraTitle;
74 | }
75 | void XVideoFrameDecorator::SetCameraTitle( const string& title )
76 | {
77 | cameraTitle = title;
78 | }
79 |
80 | // Get/Set if timestamp should be overlayed on camera images
81 | bool XVideoFrameDecorator::TimestampOverlay( ) const
82 | {
83 | return addTimestampOverlay;
84 | }
85 | void XVideoFrameDecorator::SetTimestampOverlay( bool enabled )
86 | {
87 | addTimestampOverlay = enabled;
88 | }
89 |
90 | // Get/Set if camera's title should be overlayed on its images
91 | bool XVideoFrameDecorator::CameraTitleOverlay( ) const
92 | {
93 | return addCameraTitleOverlay;
94 | }
95 | void XVideoFrameDecorator::SetCameraTitleOverlay( bool enabled )
96 | {
97 | addCameraTitleOverlay = enabled;
98 | }
99 |
100 | // Get/Set overlay text color
101 | xargb XVideoFrameDecorator::OverlayTextColor( ) const
102 | {
103 | return overlayTextColor;
104 | }
105 | void XVideoFrameDecorator::SetOverlayTextColor( xargb color )
106 | {
107 | overlayTextColor = color;
108 | }
109 |
110 | // Get/Set overlay background color
111 | xargb XVideoFrameDecorator::OverlayBackgroundColor( ) const
112 | {
113 | return overlayBackgroundColor;
114 | }
115 | void XVideoFrameDecorator::SetOverlayBackgroundColor( xargb color )
116 | {
117 | overlayBackgroundColor = color;
118 | }
119 |
--------------------------------------------------------------------------------
/src/apps/win/EditAuthDomainDialog.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | cam2web - streaming camera to web
3 |
4 | Copyright (C) 2017, cvsandbox, cvsandbox@gmail.com
5 |
6 | This program is free software; you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation; either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License along
17 | with this program; if not, write to the Free Software Foundation, Inc.,
18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | // Exclude rarely-used stuff from Windows headers
22 | #define WIN32_LEAN_AND_MEAN
23 |
24 | #include
25 | #include
26 |
27 | #include "resource.h"
28 | #include "EditAuthDomainDialog.hpp"
29 | #include "Tools.hpp"
30 | #include "UiTools.hpp"
31 |
32 | using namespace std;
33 |
34 | #define STR_ERROR TEXT( "Error" )
35 |
36 | // Message handler for Edit HTTP auth domain dialog box
37 | INT_PTR CALLBACK EditAuthDomainDialogProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
38 | {
39 | static HICON hIcon = NULL;
40 | static char* strAuthDomain = nullptr;
41 | int wmId;
42 | int wmEvent;
43 |
44 | switch ( message )
45 | {
46 | case WM_INITDIALOG:
47 | {
48 | HWND hwndAuthDomainEdit = GetDlgItem( hDlg, IDC_AUTH_DOMAIN_EDIT );
49 |
50 | CenterWindowTo( hDlg, GetParent( hDlg ) );
51 |
52 | hIcon = (HICON) LoadImage( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDI_PASSWORD ), IMAGE_ICON,
53 | GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), 0 );
54 |
55 | if ( hIcon )
56 | {
57 | SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );
58 | }
59 |
60 | SendMessage( hwndAuthDomainEdit, EM_SETLIMITTEXT, 32, 0 );
61 |
62 | strAuthDomain = (char*) lParam;
63 |
64 | if ( strAuthDomain != nullptr )
65 | {
66 | SetWindowText( hwndAuthDomainEdit, Utf8to16( strAuthDomain ).c_str( ) );
67 | }
68 |
69 | EnableWindow( GetDlgItem( hDlg, IDOK ), ( GetWindowTextLength( hwndAuthDomainEdit ) > 0 ) ? TRUE : FALSE );
70 | }
71 | return (INT_PTR) TRUE;
72 |
73 | case WM_DESTROY:
74 |
75 | if ( hIcon )
76 | {
77 | DestroyIcon( hIcon );
78 | }
79 |
80 | return (INT_PTR) TRUE;
81 |
82 | case WM_COMMAND:
83 | wmId = LOWORD( wParam );
84 | wmEvent = HIWORD( wParam );
85 |
86 | if ( ( wmId == IDOK ) || ( wmId == IDCANCEL ) )
87 | {
88 | if ( ( wmId == IDOK ) && ( strAuthDomain ) )
89 | {
90 | string authDomain = GetWindowString( GetDlgItem( hDlg, IDC_AUTH_DOMAIN_EDIT ), true );
91 |
92 | strcpy( strAuthDomain, authDomain.c_str( ) );
93 | }
94 |
95 | EndDialog( hDlg, wmId );
96 | return (INT_PTR) TRUE;
97 | }
98 | else if ( ( wmEvent == EN_CHANGE ) && ( wmId == IDC_AUTH_DOMAIN_EDIT ) )
99 | {
100 | string authDomain = GetWindowString( GetDlgItem( hDlg, IDC_AUTH_DOMAIN_EDIT ), true );
101 |
102 | EnableWindow( GetDlgItem( hDlg, IDOK ), ( authDomain.empty( ) ) ? FALSE : TRUE );
103 |
104 | return (INT_PTR) TRUE;
105 | }
106 |
107 | break;
108 | }
109 |
110 | return (INT_PTR) FALSE;
111 | }
112 |
--------------------------------------------------------------------------------
/Running.md:
--------------------------------------------------------------------------------
1 | # Running cam2web
2 | cam2web application comes as a single executable, which does not require any installation to run correctly. Once built or extracted from downloaded package, it is ready to run and stream a camera over HTTP. Release builds have all web resources embedded into the executable, so no extra files are needed to access camera from web browsers.
3 |
4 | ## Windows version
5 | Windows version of cam2web provides graphical user interface, which allows to start/stop camera streaming and set different configuration settings. The application’s main window lists all detected cameras and their supported resolutions. Once selection is done, streaming can be started. All other settings are optional and are used to change default behaviour.
6 |
7 | **Note**: The resolution box shows default average frame rate for all resolutions supported by a camera. However, some cameras support a range of frames rates - minimum/maximum rate. For such cameras it is possible to override default frame rate and set the one needed. But, don't expect all frame rate values to work from the provided range. Due to limitations of DirectShow API and badly written drivers of some cameras, many frame rate values may no work.
8 |
9 | 
10 |
11 | When a camera is streamed, it can be accessed from a web browser – http://ip:port/ (or by clicking the link in the main window for a quick start). If camera provides any configuration settings, like brightness, contrast, saturation, etc., those can be changed from the web UI.
12 |
13 | The "Settings" window allows changing different application’s option like HTTP port to listen on, maximum frame rate of MJPEG stream, quality level of JPEG images, etc.:
14 |
15 | 
16 |
17 | The "Access rights" window allows to configure who can view the camera and change its settings. By default, anyone can do everything. However, if there is no desire to keep the camera public, it is possible to limit access only to registered users. Furthermore, changing camera’s settings can be restricted more and allowed to administrators only.
18 |
19 | 
20 |
21 | **Note**: changing any application’s settings requires restarting camera streaming.
22 |
23 | The Windows version of cam2web also provides few command line options:
24 | * /start – Automatically start camera streaming on application start.
25 | * /minimize – Minimize application’s window on its start.
26 | * /fcfg:file_name – Name of configuration file to store application’s settings. By default, the application stores all settings (including last run camera/resolution) in app.cfg stored in cam2web folder within user’s home directory. However, the name of configuration file can be set different, so several instances of the application could run, having different settings and streaming different cameras.
27 |
28 | ## Linux and Raspberry Pi versions
29 | Both Linux and Raspberry Pi versions are implemented as command line applications, which do not provide any graphical user interface. Running them will start streaming of the available camera automatically using default settings. However, if **-?** option is specified, the list of supported command line options is provided, which includes their description.
30 |
31 | Same as with Windows version, once the camera is streamed, it is accessible on http://ip:port/ URL.
32 |
33 | Unlike Windows version, the Linux/Pi version does not provide means for editing users’ list who can access camera. Instead, the [Apache htdigest](https://httpd.apache.org/docs/2.4/programs/htdigest.html) tool is used to manage users’ file, which name can then be specified as one of the cam2web’s command line options. This creates a limitation though – only one user with administrator role can be created, which is **admin**. All other names get user role.
34 |
35 |
--------------------------------------------------------------------------------
/src/core/cameras/V4L2/XV4LCamera.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | cam2web - streaming camera to web
3 |
4 | Copyright (C) 2017, cvsandbox, cvsandbox@gmail.com
5 |
6 | This program is free software; you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation; either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License along
17 | with this program; if not, write to the Free Software Foundation, Inc.,
18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | #ifndef XV4L_CAMERA_HPP
22 | #define XV4L_CAMERA_HPP
23 |
24 | #include
25 |
26 | #include "IVideoSource.hpp"
27 | #include "XInterfaces.hpp"
28 |
29 | namespace Private
30 | {
31 | class XV4LCameraData;
32 | }
33 |
34 | enum class XVideoProperty
35 | {
36 | Brightness = 0,
37 | Contrast,
38 | Saturation,
39 | Hue,
40 | Sharpness,
41 | Gain,
42 | BacklightCompensation,
43 | RedBalance,
44 | BlueBalance,
45 | AutoWhiteBalance,
46 | HorizontalFlip,
47 | VerticalFlip
48 | };
49 |
50 | // Class which provides access to cameras using V4L2 API (Video for Linux, v2)
51 | class XV4LCamera : public IVideoSource, private Uncopyable
52 | {
53 | protected:
54 | XV4LCamera( );
55 |
56 | public:
57 | ~XV4LCamera( );
58 |
59 | static const std::shared_ptr Create( );
60 |
61 | // Start video source so it initializes and begins providing video frames
62 | bool Start( );
63 | // Signal source video to stop, so it could finalize and clean-up
64 | void SignalToStop( );
65 | // Wait till video source (its thread) stops
66 | void WaitForStop( );
67 | // Check if video source is still running
68 | bool IsRunning( );
69 |
70 | // Get number of frames received since the start of the video source
71 | uint32_t FramesReceived( );
72 |
73 | // Set video source listener returning the old one
74 | IVideoSourceListener* SetListener( IVideoSourceListener* listener );
75 |
76 | public: // Set of poperties, which can be set only when device is NOT running.
77 | // If it is running, then setting these properties is silently ignored.
78 |
79 | // Set/get video device
80 | uint32_t VideoDevice( ) const;
81 | void SetVideoDevice( uint32_t videoDevice );
82 |
83 | // Get/Set video size
84 | uint32_t Width( ) const;
85 | uint32_t Height( ) const;
86 | void SetVideoSize( uint32_t width, uint32_t height );
87 |
88 | // Get/Set frame rate
89 | uint32_t FrameRate( ) const;
90 | void SetFrameRate( uint32_t frameRate );
91 |
92 | // Enable/Disable JPEG encoding
93 | bool IsJpegEncodingEnabled( ) const;
94 | void EnableJpegEncoding( bool enable );
95 |
96 | public:
97 |
98 | // Set the specified video property. The device does not have to be running. If it is not,
99 | // the setting will be cached and applied as soon as the device gets running.
100 | XError SetVideoProperty( XVideoProperty property, int32_t value );
101 | // Get current value if the specified video property. The device must be running.
102 | XError GetVideoProperty( XVideoProperty property, int32_t* value ) const;
103 | // Get range of values supported by the specified video property
104 | XError GetVideoPropertyRange( XVideoProperty property, int32_t* min, int32_t* max, int32_t* step, int32_t* def ) const;
105 |
106 | private:
107 | Private::XV4LCameraData* mData;
108 | };
109 |
110 | #endif // XV4L_CAMERA_HPP
111 |
112 |
--------------------------------------------------------------------------------
/WebAPI.md:
--------------------------------------------------------------------------------
1 | # Accessing camera from other applications (WEB API)
2 |
3 | The streamed camera can be accessed not only from web browser, but also from any other application supporting MJPEG streams (like VLC media player, for example, or different applications for IP cameras monitoring). The URL format to access MJPEG stream is:
4 | ```
5 | http://ip:port/camera/mjpeg
6 | ```
7 |
8 | In the case an individual image is required, the next URL provides the latest camera snapshot:
9 | ```
10 | http://ip:port/camera/jpeg
11 | ```
12 |
13 | ### Camera information
14 | To get some camera information, like device name, width, height, etc., an HTTP GET request should be sent the next URL:
15 | ```
16 | http://ip:port/camera/info
17 | ```
18 | It provides reply in JSON format, which may look like the one below:
19 | ```JSON
20 | {
21 | "status":"OK",
22 | "config":
23 | {
24 | "device":"RaspberryPi Camera",
25 | "title":"My home camera",
26 | "width":"640",
27 | "height":"480"
28 | }
29 | }
30 | ````
31 |
32 | ### Changing camera’s settings
33 | ```
34 | http://ip:port/camera/config
35 | ```
36 | To get current camera’ settings, an HTTP GET request is sent to the above URL, which provides all values as JSON reply:
37 | ```JSON
38 | {
39 | "status":"OK",
40 | "config":
41 | {
42 | "awb":"Auto",
43 | "brightness":"50",
44 | "contrast":"15",
45 | "effect":"None",
46 | "expmeteringmode":"Average",
47 | "expmode":"Auto",
48 | "hflip":"1",
49 | "saturation":"25",
50 | "sharpness":"100",
51 | "vflip":"1",
52 | "videostabilisation":"0"
53 | }
54 | }
55 | ```
56 | In the case if only some values are required, their names (separated with coma) can be passed as **vars** variable. For example:
57 | ```
58 | http://ip:port/camera/config?vars=brightness,contrast
59 | ```
60 |
61 | For setting camera’s properties, the same URL is used, but HTTP POST request must be used. The posted data must contain collection of variables to set encoded in JSON format.
62 | ```JSON
63 | {
64 | "brightness":"50",
65 | "contrast":"15"
66 | }
67 | ```
68 | On success, the reply JSON will have **status** variable set to "OK". Or it will contain failure reason otherwise.
69 |
70 | ### Getting description of camera properties
71 | Starting from version 1.1.0, the cam2web application provides description of all properties camera provides. This allows, for example, to have single WebUI code, which queries the list of available properties first and then does unified rendering. The properties description can be optained using the below URL:
72 | ```
73 | http://ip:port/camera/properties
74 | ```
75 |
76 | The JSON response provides name of all available properties, their default value, type, display name and order. For integer type properties, it also includes allowed minimum and maximum values. And for selection type properties, it provides all possible choices for the property.
77 | ```JSON
78 | {
79 | "status":"OK",
80 | "config":
81 | {
82 | "hflip":
83 | {
84 | "def":0,
85 | "type":"bool",
86 | "order":8,
87 | "name":"Horizontal Flip"
88 | },
89 | "brightness":
90 | {
91 | "min":0,
92 | "max":100,
93 | "def":50,
94 | "type":"int",
95 | "order":0,
96 | "name":"Brightness"
97 | },
98 | "awb":
99 | {
100 | "def":"Auto",
101 | "type":"select",
102 | "order":4,
103 | "name":"White Balance",
104 | "choices":
105 | [
106 | ["Off","Off"],
107 | ["Auto","Auto"],
108 | ["Sunlight","Sunlight"],
109 | ...
110 | ]
111 | },
112 | ...
113 | }
114 | }
115 | ```
116 |
117 | ### Getting version information
118 | To get information about version of the cam2web application streaming the camera, the next URL is used
119 | ```
120 | http://ip:port/version
121 | ```
122 | Which provides information in the format below:
123 | ```JSON
124 | {
125 | "status":"OK",
126 | "config":
127 | {
128 | "platform":"RaspberryPi",
129 | "product":"cam2web",
130 | "version":"1.0.0"
131 | }
132 | }
133 | ```
134 |
135 | ### Access rights
136 | Accessing JPEG, MJPEG and camera information URLs is available to those who can view the camera. Access to camera configuration URL is available to those who can configure it. The version URL is accessible to anyone. See [Running cam2web](Running.md) for more information about access rights.
137 |
--------------------------------------------------------------------------------
/src/apps/linux/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # cam2web - streaming camera to web
3 | #
4 | # Copyright (C) 2017, cvsandbox, cvsandbox@gmail.com
5 | #
6 | # This program is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation; either version 2 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License along
17 | # with this program; if not, write to the Free Software Foundation, Inc.,
18 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | #
20 |
21 | # Additional folders to look for source files
22 | VPATH = ../../../externals/mongoose/ \
23 | ../../core \
24 | ../../core/cameras/V4L2
25 |
26 | # C code
27 | SRC_C = mongoose.c
28 | # C++ code
29 | SRC_CPP = cam2web.cpp XImage.cpp XJpegEncoder.cpp XManualResetEvent.cpp \
30 | XV4LCamera.cpp XV4LCameraConfig.cpp XVideoSourceToWeb.cpp XWebServer.cpp \
31 | XSimpleJsonParser.cpp XObjectConfigurationSerializer.cpp \
32 | XObjectConfigurationRequestHandler.cpp XStringTools.cpp \
33 | XError.cpp
34 |
35 | # Output name
36 | OUT = cam2web
37 |
38 | # Compiler to use
39 | COMPILER = g++
40 | # Base compiler flags
41 | CFLAGS = -std=c++0x
42 |
43 | # Object files list
44 | OBJ = $(SRC_CPP:.cpp=.o) $(SRC_C:.c=.o)
45 |
46 | # Additional include folders
47 | INCLUDE = -I../../../externals/mongoose/ \
48 | -I../../core \
49 | -I../../core/cameras/V4L2
50 |
51 | # Libraries to use
52 | LIBS = -ljpeg
53 |
54 | # Enable threads in Mongoose
55 | mongoose.o: CFLAGS += -DMG_ENABLE_THREADS
56 | XWebServer.o: CFLAGS += -DMG_ENABLE_THREADS
57 |
58 | ifneq "$(findstring debug, $(MAKECMDGOALS))" ""
59 | # "Debug" build - no optimization and add debugging symbols
60 | OUT_FOLDER = ../../../build/gcc/debug/
61 | CFLAGS += -O0 -g
62 | else
63 | # "Release" build - optimization and no debug symbols
64 | OUT_FOLDER = ../../../build/gcc/release/
65 | CFLAGS += -O2 -s -DNDEBUG
66 | INCLUDE += -I$(OUT_FOLDER)include
67 | endif
68 |
69 | # Update compiler/linker flags include folders and libraries
70 | CFLAGS += $(INCLUDE)
71 | LDFLAGS = $(LIBS) -pthread
72 |
73 | # Different output folders
74 | OUT_BIN = $(OUT_FOLDER)bin/
75 | OUT_INC = $(OUT_FOLDER)include/
76 | OUT_WEB = $(OUT_BIN)web/
77 |
78 | # web2h tool used to generate header files for web files
79 | WEB2H = $(OUT_BIN)web2h
80 |
81 | # ===================================
82 |
83 | all: release
84 |
85 | release: generateweb build
86 |
87 | debug: build copyweb
88 |
89 | %.o: %.c
90 | $(COMPILER) $(CFLAGS) -c $^ -o $@
91 | %.o: %.cpp
92 | $(COMPILER) $(CFLAGS) -c $^ -o $@
93 |
94 | $(OUT): $(OBJ)
95 | $(COMPILER) -o $@ $(OBJ) $(LDFLAGS)
96 |
97 | build: $(OUT)
98 | mkdir -p $(OUT_BIN)
99 | cp $(OUT) $(OUT_BIN)
100 |
101 | clean:
102 | rm $(OBJ) $(OUT)
103 | rm -rf web
104 |
105 | copyweb:
106 | mkdir -p $(OUT_WEB)
107 | cp ../../web/* $(OUT_WEB)
108 | cp ../../../externals/jquery/*.js $(OUT_WEB)
109 | cp ../../../externals/jquery/*.css $(OUT_WEB)
110 | cp -r $(OUT_WEB) .
111 |
112 | generateweb:
113 | mkdir -p $(OUT_INC)
114 | cp ../../web/* $(OUT_INC)
115 | cp ../../../externals/jquery/*.js $(OUT_INC)
116 | cp ../../../externals/jquery/*.css $(OUT_INC)
117 | $(WEB2H) -i $(OUT_INC)index.html -o $(OUT_INC)index.html.h
118 | $(WEB2H) -i $(OUT_INC)styles.css -o $(OUT_INC)styles.css.h
119 | $(WEB2H) -i $(OUT_INC)cam2web.png -o $(OUT_INC)cam2web.png.h
120 | $(WEB2H) -i $(OUT_INC)cam2web_white.png -o $(OUT_INC)cam2web_white.png.h
121 | $(WEB2H) -i $(OUT_INC)cameraproperties.html -o $(OUT_INC)cameraproperties.html.h
122 | $(WEB2H) -i $(OUT_INC)camera.js -o $(OUT_INC)camera.js.h
123 | $(WEB2H) -i $(OUT_INC)cameraproperties.js -o $(OUT_INC)cameraproperties.js.h
124 | $(WEB2H) -i $(OUT_INC)jquery.js -o $(OUT_INC)jquery.js.h
125 | $(WEB2H) -i $(OUT_INC)jquery.mobile.js -o $(OUT_INC)jquery.mobile.js.h
126 | $(WEB2H) -i $(OUT_INC)jquery.mobile.css -o $(OUT_INC)jquery.mobile.css.h
127 | rm $(OUT_INC)*.html
128 | rm $(OUT_INC)*.css
129 | rm $(OUT_INC)*.js
130 |
--------------------------------------------------------------------------------
/src/tools/web2h/make/msvc/web2h.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 |
15 |
16 |
17 | {FA0B8656-7FBF-439A-995B-60000AFD32F0}
18 | Win32Proj
19 | web2h
20 |
21 |
22 |
23 | Application
24 | true
25 | v140
26 | Unicode
27 |
28 |
29 | Application
30 | false
31 | v140
32 | true
33 | Unicode
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | true
47 |
48 |
49 | false
50 |
51 |
52 |
53 |
54 |
55 | Level4
56 | Disabled
57 | WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
58 |
59 |
60 | Console
61 | true
62 |
63 |
64 | xcopy /Y "$(TargetPath)" "$(ProjectDir)..\..\..\..\..\build\msvc\debug\bin\"
65 |
66 |
67 |
68 |
69 | Level4
70 |
71 |
72 | MaxSpeed
73 | true
74 | true
75 | WIN32;NDEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
76 |
77 |
78 | Console
79 | true
80 | true
81 | true
82 |
83 |
84 | xcopy /Y "$(TargetPath)" "$(ProjectDir)..\..\..\..\..\build\msvc\release\bin\"
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/src/apps/pi/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # cam2web - streaming camera to web
3 | #
4 | # Copyright (C) 2017, cvsandbox, cvsandbox@gmail.com
5 | #
6 | # This program is free software; you can redistribute it and/or modify
7 | # it under the terms of the GNU General Public License as published by
8 | # the Free Software Foundation; either version 2 of the License, or
9 | # (at your option) any later version.
10 | #
11 | # This program is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | # GNU General Public License for more details.
15 | #
16 | # You should have received a copy of the GNU General Public License along
17 | # with this program; if not, write to the Free Software Foundation, Inc.,
18 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | #
20 |
21 | # Additional folders to look for source files
22 | VPATH = ../../../externals/mongoose/ \
23 | ../../core \
24 | ../../core/cameras/RaspiCam
25 |
26 | # C code
27 | SRC_C = mongoose.c
28 | # C++ code
29 | SRC_CPP = cam2web.cpp XImage.cpp XJpegEncoder.cpp XManualResetEvent.cpp \
30 | XRaspiCamera.cpp XRaspiCameraConfig.cpp XVideoSourceToWeb.cpp XWebServer.cpp \
31 | XSimpleJsonParser.cpp XObjectConfigurationSerializer.cpp \
32 | XObjectConfigurationRequestHandler.cpp XStringTools.cpp \
33 | XError.cpp
34 |
35 | # Output name
36 | OUT = cam2web
37 |
38 | # Compiler to use
39 | COMPILER = g++
40 | # Base compiler flags
41 | CFLAGS = -std=c++0x
42 |
43 | # Object files list
44 | OBJ = $(SRC_CPP:.cpp=.o) $(SRC_C:.c=.o)
45 |
46 | # Additional include folders
47 | INCLUDE = -I../../../externals/mongoose/ \
48 | -I../../core \
49 | -I../../core/cameras/RaspiCam \
50 | -I/opt/vc/include \
51 | -I/opt/vc/include/interface/vcos \
52 | -I/opt/vc/include/interface/vcos/pthreads \
53 | -I/opt/vc/include/interface/vmcs_host/linux
54 |
55 | # Libraries to use
56 | LIBS = -lmmal_core -lmmal_util -lmmal_vc_client -lvcos -lbcm_host -ljpeg
57 |
58 | # Folders to look for additional libraries
59 | LIBDIR = -L/opt/vc/lib
60 |
61 | # Enable threads in Mongoose
62 | mongoose.o: CFLAGS += -DMG_ENABLE_THREADS
63 | XWebServer.o: CFLAGS += -DMG_ENABLE_THREADS
64 |
65 | ifneq "$(findstring debug, $(MAKECMDGOALS))" ""
66 | # "Debug" build - no optimization and add debugging symbols
67 | OUT_FOLDER = ../../../build/gcc/debug/
68 | CFLAGS += -O0 -g
69 | else
70 | # "Release" build - optimization and no debug symbols
71 | OUT_FOLDER = ../../../build/gcc/release/
72 | CFLAGS += -O2 -s -DNDEBUG
73 | INCLUDE += -I$(OUT_FOLDER)include
74 | endif
75 |
76 | # Update compiler/linker flags include folders and libraries
77 | CFLAGS += $(INCLUDE)
78 | LDFLAGS = $(LIBDIR) $(LIBS) -pthread
79 |
80 | # Different output folders
81 | OUT_BIN = $(OUT_FOLDER)bin/
82 | OUT_INC = $(OUT_FOLDER)include/
83 | OUT_WEB = $(OUT_BIN)web/
84 |
85 | # web2h tool used to generate header files for web files
86 | WEB2H = $(OUT_BIN)web2h
87 |
88 | # ===================================
89 |
90 | all: release
91 |
92 | release: generateweb build
93 |
94 | debug: build copyweb
95 |
96 | %.o: %.c
97 | $(COMPILER) $(CFLAGS) -c $^ -o $@
98 | %.o: %.cpp
99 | $(COMPILER) $(CFLAGS) -c $^ -o $@
100 |
101 | $(OUT): $(OBJ)
102 | $(COMPILER) -o $@ $(OBJ) $(LDFLAGS)
103 |
104 | build: $(OUT)
105 | mkdir -p $(OUT_BIN)
106 | cp $(OUT) $(OUT_BIN)
107 |
108 | clean:
109 | rm $(OBJ) $(OUT)
110 | rm -rf web
111 |
112 | copyweb:
113 | mkdir -p $(OUT_WEB)
114 | cp ../../web/* $(OUT_WEB)
115 | cp ../../../externals/jquery/*.js $(OUT_WEB)
116 | cp ../../../externals/jquery/*.css $(OUT_WEB)
117 | cp -r $(OUT_WEB) .
118 |
119 | generateweb:
120 | mkdir -p $(OUT_INC)
121 | cp ../../web/* $(OUT_INC)
122 | cp ../../../externals/jquery/*.js $(OUT_INC)
123 | cp ../../../externals/jquery/*.css $(OUT_INC)
124 | $(WEB2H) -i $(OUT_INC)index.html -o $(OUT_INC)index.html.h
125 | $(WEB2H) -i $(OUT_INC)styles.css -o $(OUT_INC)styles.css.h
126 | $(WEB2H) -i $(OUT_INC)cam2web.png -o $(OUT_INC)cam2web.png.h
127 | $(WEB2H) -i $(OUT_INC)cam2web_white.png -o $(OUT_INC)cam2web_white.png.h
128 | $(WEB2H) -i $(OUT_INC)cameraproperties.html -o $(OUT_INC)cameraproperties.html.h
129 | $(WEB2H) -i $(OUT_INC)camera.js -o $(OUT_INC)camera.js.h
130 | $(WEB2H) -i $(OUT_INC)cameraproperties.js -o $(OUT_INC)cameraproperties.js.h
131 | $(WEB2H) -i $(OUT_INC)jquery.js -o $(OUT_INC)jquery.js.h
132 | $(WEB2H) -i $(OUT_INC)jquery.mobile.js -o $(OUT_INC)jquery.mobile.js.h
133 | $(WEB2H) -i $(OUT_INC)jquery.mobile.css -o $(OUT_INC)jquery.mobile.css.h
134 | rm $(OUT_INC)*.html
135 | rm $(OUT_INC)*.css
136 | rm $(OUT_INC)*.js
137 |
--------------------------------------------------------------------------------
/src/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
Remote Camera
25 |
Settings
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
42 |
43 |
44 |
45 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/src/apps/win/AppConfig.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | cam2web - streaming camera to web
3 |
4 | Copyright (C) 2017-2019, cvsandbox, cvsandbox@gmail.com
5 |
6 | This program is free software; you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation; either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License along
17 | with this program; if not, write to the Free Software Foundation, Inc.,
18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | #ifndef APP_CONFIG_HPP
22 | #define APP_CONFIG_HPP
23 |
24 | #include
25 | #include
26 | #include
27 |
28 | class AppConfig : public IObjectConfigurator
29 | {
30 | public:
31 | AppConfig( );
32 |
33 | // Get/Set JPEG quality
34 | uint16_t JpegQuality( ) const;
35 | void SetJpegQuality( uint16_t quality );
36 |
37 | // Get/Set MJPEG frame rate
38 | uint16_t MjpegFrameRate( ) const;
39 | void SetMjpegFrameRate( uint16_t frameRate );
40 |
41 | // Get/Set HTTP port to listen
42 | uint16_t HttpPort( ) const;
43 | void SetHttpPort( uint16_t port );
44 |
45 | // Get/Set viewers group ID
46 | uint16_t ViewersGroup( );
47 | void SetViewersGroup( uint16_t groupId );
48 |
49 | // Get/Set configurators group ID
50 | uint16_t ConfiguratorsGroup( );
51 | void SetConfiguratorsGroup( uint16_t groupId );
52 |
53 | // Get/Set HTTP digest auth domain
54 | std::string AuthDomain( ) const;
55 | void SetAuthDomain( const std::string& authDomain );
56 |
57 | // Get/Set HTTP authentication method
58 | std::string AuthenticationMethod( ) const;
59 | void SetAuthenticationMethod( const std::string& method );
60 |
61 | // Get/Set path to the folder with custom web content
62 | std::string CustomWebContent( ) const;
63 | void SetCustomWebContent( const std::string& path );
64 |
65 | // Get/Set camera moniker string
66 | std::string CameraMoniker( ) const;
67 | void SetCameraMoniker( const std::string& moniker );
68 |
69 | // Get/Set camera title
70 | std::string CameraTitle( ) const;
71 | void SetCameraTitle( const std::string& title );
72 |
73 | // Get/Set if timestamp should be overlayed on camera images
74 | bool TimestampOverlay( ) const;
75 | void SetTimestampOverlay( bool enabled );
76 |
77 | // Get/Set if camera's title should be overlayed on its images
78 | bool CameraTitleOverlay( ) const;
79 | void SetCameraTitleOverlay( bool enabled );
80 |
81 | // Get/Set overlay text color
82 | xargb OverlayTextColor( ) const;
83 | void SetOverlayTextColor( xargb color );
84 |
85 | // Get/Set overlay background color
86 | xargb OverlayBackgroundColor( ) const;
87 | void SetOverlayBackgroundColor( xargb color );
88 |
89 | // Get/Set last used video resolution
90 | void GetLastVideoResolution( uint16_t* width, uint16_t* height, uint16_t* bpp, uint16_t* fps ) const;
91 | void SetLastVideoResolution( uint16_t width, uint16_t height, uint16_t bpp, uint16_t fps );
92 |
93 | // Get/Set last requested frame rate
94 | uint16_t LastRequestedFrameRate( ) const;
95 | void SetLastRequestedFrameRate( uint16_t fps );
96 |
97 | // Get/Set the flag inidicating that application should minimize to system tray
98 | bool MinimizeToSystemTray( ) const;
99 | void SetMinimizeToSystemTray( bool enabled );
100 |
101 | // Get/Set index of the window/tray icon to use
102 | uint16_t WindowIconIndex( ) const;
103 | void SetWindowIconIndex( uint16_t index );
104 |
105 | // Get/Set file name to store users' list in
106 | std::string UsersFileName( ) const;
107 | void SetUsersFileName( const std::string& fileName );
108 |
109 | // Get/Set main window's position
110 | int32_t MainWindowX( ) const;
111 | int32_t MainWindowY( ) const;
112 | void SetMainWindowXY( int32_t x, int32_t y );
113 |
114 | // Get user camaera device preference
115 | std::string DevicePreference( ) const;
116 |
117 | public: // IObjectConfigurator interface
118 |
119 | virtual XError SetProperty( const std::string& propertyName, const std::string& value );
120 | virtual XError GetProperty( const std::string& propertyName, std::string& value ) const;
121 |
122 | virtual std::map GetAllProperties( ) const;
123 |
124 | private:
125 | uint16_t jpegQuality;
126 | uint16_t mjpegFrameRate;
127 | uint16_t httpPort;
128 | uint16_t viewersGroup;
129 | uint16_t configuratorsGroup;
130 | std::string authDomain;
131 | std::string authMethod;
132 | std::string customWebContent;
133 | std::string cameraMoniker;
134 | std::string cameraTitle;
135 | std::string devicePreference;
136 | bool addTimestampOverlay;
137 | bool addCameraTitleOverlay;
138 | xargb overlayTextColor;
139 | xargb overlayBackgroundColor;
140 | uint16_t cameraWidth;
141 | uint16_t cameraHeight;
142 | uint16_t cameraBpp;
143 | uint16_t cameraFps;
144 | uint16_t requestedFps;
145 | uint16_t windowIcon;
146 | bool minimizeToSystemTray;
147 | int32_t mainWindowX;
148 | int32_t mainWindowY;
149 |
150 | std::string usersFileName;
151 | };
152 |
153 | #endif // APP_CONFIG_HPP
154 |
--------------------------------------------------------------------------------
/src/core/cameras/RaspiCam/XRaspiCamera.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | cam2web - streaming camera to web
3 |
4 | Copyright (C) 2017-2019, cvsandbox, cvsandbox@gmail.com
5 |
6 | This program is free software; you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation; either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License along
17 | with this program; if not, write to the Free Software Foundation, Inc.,
18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | #ifndef XRASPI_CAMERA_HPP
22 | #define XRASPI_CAMERA_HPP
23 |
24 | #include
25 |
26 | #include "IVideoSource.hpp"
27 | #include "XInterfaces.hpp"
28 |
29 | namespace Private
30 | {
31 | class XRaspiCameraData;
32 | }
33 |
34 | enum class AwbMode
35 | {
36 | Off = 0,
37 | Auto,
38 | Sunlight,
39 | Cloudy,
40 | Shade,
41 | Tungsten,
42 | Fluorescent,
43 | Incandescent,
44 | Flash,
45 | Horizon
46 | };
47 |
48 | enum class ExposureMode
49 | {
50 | Off = 0,
51 | Auto,
52 | Night,
53 | NightPreview,
54 | Backlight,
55 | Spotlight,
56 | Sports,
57 | Snow,
58 | Beach,
59 | VeryLong,
60 | FixedFps,
61 | AntiShake,
62 | Fireworks
63 | };
64 |
65 | enum class ExposureMeteringMode
66 | {
67 | Average = 0,
68 | Spot,
69 | Backlit,
70 | Matrix
71 | };
72 |
73 | enum class ImageEffect
74 | {
75 | None = 0,
76 | Negative,
77 | Solarize,
78 | Posterize,
79 | WhiteBoard,
80 | BlackBoard,
81 | Sketch,
82 | Denoise,
83 | Emboss,
84 | OilPaint,
85 | Hatch,
86 | Gpen,
87 | Pastel,
88 | WaterColor,
89 | Film,
90 | Blur,
91 | Saturation,
92 | ColorSwap,
93 | WashedOut,
94 | Posterise,
95 | ColorPoint,
96 | ColorBalance,
97 | Cartoon
98 | };
99 |
100 | class XRaspiCamera : public IVideoSource, private Uncopyable
101 | {
102 | protected:
103 | XRaspiCamera( );
104 |
105 | public:
106 | ~XRaspiCamera( );
107 |
108 | static const std::shared_ptr Create( );
109 |
110 | // Start video source so it initializes and begins providing video frames
111 | bool Start( );
112 | // Signal source video to stop, so it could finalize and clean-up
113 | void SignalToStop( );
114 | // Wait till video source (its thread) stops
115 | void WaitForStop( );
116 | // Check if video source is still running
117 | bool IsRunning( );
118 |
119 | // Get number of frames received since the start of the video source
120 | uint32_t FramesReceived( );
121 |
122 | // Set video source listener returning the old one
123 | IVideoSourceListener* SetListener( IVideoSourceListener* listener );
124 |
125 | public: // Camera configuration to be done before starting it
126 |
127 | // Get/Set video size
128 | uint32_t Width( ) const;
129 | uint32_t Height( ) const;
130 | void SetVideoSize( uint32_t width, uint32_t height );
131 |
132 | // Get/Set frame rate
133 | uint32_t FrameRate( ) const;
134 | void SetFrameRate( uint32_t frameRate );
135 |
136 | // Enable/Disable JPEG encoding
137 | bool IsJpegEncodingEnabled( ) const;
138 | void EnableJpegEncoding( bool enable );
139 |
140 | // Get/Set JPEG quality
141 | uint32_t JpegQuality( ) const;
142 | void SetJpegQuality( uint32_t jpegQuality );
143 |
144 | public: // Different settings of the video source (can be changed at run time)
145 |
146 | // Get/Set camera's image rotation, (0, 90, 180, 270)
147 | uint32_t GetImageRotation( ) const;
148 | bool SetImageRotation( uint32_t rotation );
149 |
150 | // Get/Set camera's horizontal/vertical flip
151 | bool GetHorizontalFlip( ) const;
152 | bool GetVerticalFlip( ) const;
153 | bool SetCameraFlip( bool horizontal, bool vertical );
154 |
155 | // Get/Set video stabilisation flag
156 | bool GetVideoStabilisation( ) const;
157 | bool SetVideoStabilisation( bool enabled );
158 |
159 | // Get/Set camera's sharpness value, [-100, 100]
160 | int32_t GetSharpness( ) const;
161 | bool SetSharpness( int32_t sharpness );
162 |
163 | // Get/Set camera's contrast value, [-100, 100]
164 | int32_t GetContrast( ) const;
165 | bool SetContrast( int32_t contrast );
166 |
167 | // Get/Set camera's brightness value, [0, 100]
168 | int32_t GetBrightness( ) const;
169 | bool SetBrightness( int32_t brightness );
170 |
171 | // Get/Set camera's saturation value, [-100, 100]
172 | int32_t GetSaturation( ) const;
173 | bool SetSaturation( int32_t saturation );
174 |
175 | // Get/Set camera's Automatic White Balance mode
176 | AwbMode GetWhiteBalanceMode( ) const;
177 | bool SetWhiteBalanceMode( AwbMode mode );
178 |
179 | // Get/Set camera's exposure mode
180 | ExposureMode GetExposureMode( ) const;
181 | bool SetExposureMode( ExposureMode mode );
182 |
183 | // Get/Set camera's exposure metering mode
184 | ExposureMeteringMode GetExposureMeteringMode( ) const;
185 | bool SetExposureMeteringMode( ExposureMeteringMode mode );
186 |
187 | // Get/Set camera's image effect
188 | ImageEffect GetImageEffect( ) const;
189 | bool SetImageEffect( ImageEffect effect );
190 |
191 | // Get/Set text annotation
192 | std::string TextAnnotation( ) const;
193 | bool SetTextTextAnnotation( const std::string& text, bool blackBackground = true );
194 | bool ClearTextTextAnnotation( );
195 |
196 | private:
197 | Private::XRaspiCameraData* mData;
198 | };
199 |
200 | #endif // XRASPI_CAMERA_HPP
201 |
202 |
--------------------------------------------------------------------------------
/src/core/XObjectConfigurationSerializer.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | cam2web - streaming camera to web
3 |
4 | Copyright (C) 2017, cvsandbox, cvsandbox@gmail.com
5 |
6 | This program is free software; you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation; either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License along
17 | with this program; if not, write to the Free Software Foundation, Inc.,
18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | #include "XObjectConfigurationSerializer.hpp"
22 |
23 | #ifdef WIN32
24 | #include
25 | #endif
26 |
27 | using namespace std;
28 |
29 | XObjectConfigurationSerializer::XObjectConfigurationSerializer( ) :
30 | FileName( ),
31 | ObjectToConfigure( )
32 | {
33 |
34 | }
35 |
36 | XObjectConfigurationSerializer::XObjectConfigurationSerializer( const std::string& fileName,
37 | const std::shared_ptr& objectToConfigure ) :
38 | FileName( fileName ),
39 | ObjectToConfigure( objectToConfigure )
40 | {
41 | }
42 |
43 | // Save properties of the specified object into a file
44 | XError XObjectConfigurationSerializer::SaveConfiguration( ) const
45 | {
46 | XError ret = XError::Success;
47 |
48 | if ( ( FileName.empty( ) ) || ( !ObjectToConfigure ) )
49 | {
50 | ret = XError::Failed;
51 | }
52 | else
53 | {
54 | FILE* file = nullptr;
55 |
56 | #ifdef WIN32
57 | {
58 | int charsRequired = MultiByteToWideChar( CP_UTF8, 0, FileName.c_str( ), -1, NULL, 0 );
59 |
60 | if ( charsRequired > 0 )
61 | {
62 | WCHAR* filenameUtf16 = (WCHAR*) malloc( sizeof( WCHAR ) * charsRequired );
63 |
64 | if ( MultiByteToWideChar( CP_UTF8, 0, FileName.c_str( ), -1, filenameUtf16, charsRequired ) > 0 )
65 | {
66 | file = _wfopen( filenameUtf16, L"w" );
67 | }
68 |
69 | free( filenameUtf16 );
70 | }
71 | }
72 | #else
73 | file = fopen( FileName.c_str( ), "w" );
74 | #endif
75 |
76 | if ( file == nullptr )
77 | {
78 | ret = XError::IOError;
79 | }
80 | else
81 | {
82 | map properties = ObjectToConfigure->GetAllProperties( );
83 | bool first = true;
84 |
85 | // write a simple file, where property name and value go separate lines
86 | for ( auto property : properties )
87 | {
88 | if ( !first )
89 | {
90 | fprintf( file, "\n" );
91 | }
92 |
93 | fprintf( file, "%s\n%s\n", property.first.c_str( ), property.second.c_str( ) );
94 |
95 | first = false;
96 | }
97 |
98 | fclose( file );
99 | }
100 | }
101 |
102 | return ret;
103 | }
104 |
105 | // Load properties of the specified object from a file
106 | XError XObjectConfigurationSerializer::LoadConfiguration( ) const
107 | {
108 | XError ret = XError::Success;
109 |
110 | if ( ( FileName.empty( ) ) || ( !ObjectToConfigure ) )
111 | {
112 | ret = XError::Failed;
113 | }
114 | else
115 | {
116 | FILE* file = nullptr;
117 |
118 | #ifdef WIN32
119 | {
120 | int charsRequired = MultiByteToWideChar( CP_UTF8, 0, FileName.c_str( ), -1, NULL, 0 );
121 |
122 | if ( charsRequired > 0 )
123 | {
124 | WCHAR* filenameUtf16 = (WCHAR*) malloc( sizeof( WCHAR ) * charsRequired );
125 |
126 | if ( MultiByteToWideChar( CP_UTF8, 0, FileName.c_str( ), -1, filenameUtf16, charsRequired ) > 0 )
127 | {
128 | file = _wfopen( filenameUtf16, L"r" );
129 | }
130 |
131 | free( filenameUtf16 );
132 | }
133 | }
134 | #else
135 | file = fopen( FileName.c_str( ), "r" );
136 | #endif
137 |
138 | if ( file == nullptr )
139 | {
140 | ret = XError::IOError;
141 | }
142 | else
143 | {
144 | char buffer[256];
145 | string name;
146 | string line;
147 | bool gotName = false;
148 |
149 | while ( fgets( buffer, sizeof( buffer ) - 1, file ) )
150 | {
151 | line = string( buffer );
152 |
153 | while ( ( !line.empty( ) ) &&
154 | ( ( line.back( ) == ' ' ) || ( line.back( ) == '\t' ) ||
155 | ( line.back( ) == '\n' ) || ( line.back( ) == '\r' ) ) )
156 | {
157 | line.pop_back( );
158 | }
159 |
160 | // allow blank lines between configuration options, but not between option and its value
161 | if ( ( !line.empty( ) ) || ( gotName ) )
162 | {
163 | if ( !gotName )
164 | {
165 | name = line;
166 | gotName = true;
167 | }
168 | else
169 | {
170 | ObjectToConfigure->SetProperty( name, line );
171 | gotName = false;
172 | }
173 | }
174 | }
175 | }
176 | }
177 |
178 | return ret;
179 | }
180 |
--------------------------------------------------------------------------------
/src/core/XImage.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | cam2web - streaming camera to web
3 |
4 | Copyright (C) 2017, cvsandbox, cvsandbox@gmail.com
5 |
6 | This program is free software; you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation; either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License along
17 | with this program; if not, write to the Free Software Foundation, Inc.,
18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | #include
22 | #include
23 |
24 | #include "XImage.hpp"
25 |
26 | using namespace std;
27 |
28 | // Returns number of bits required for pixel in certain format
29 | uint32_t XImageBitsPerPixel( XPixelFormat format )
30 | {
31 | static int sizes[] = { 0, 8, 24, 32, 8 };
32 | int formatIndex = static_cast( format );
33 |
34 | return ( formatIndex >= ( sizeof( sizes ) / sizeof( sizes[0] ) ) ) ? 0 : sizes[formatIndex];
35 | }
36 |
37 | // Returns number of bytes per stride when number of bits per line is known (stride is always 32 bit aligned)
38 | static uint32_t XImageBytesPerStride( uint32_t bitsPerLine )
39 | {
40 | return ( ( bitsPerLine + 31 ) & ~31 ) >> 3;
41 | }
42 |
43 | // Returns number of bytes per line when number of bits per line is known (line is always 8 bit aligned)
44 | static uint32_t XImageBytesPerLine( uint32_t bitsPerLine )
45 | {
46 | return ( bitsPerLine + 7 ) >> 3;
47 | }
48 |
49 | // Create empty image
50 | XImage::XImage( uint8_t* data, int32_t width, int32_t height, int32_t stride, XPixelFormat format, bool ownMemory ) :
51 | mData( data ), mWidth( width ), mHeight( height ), mStride( stride ), mFormat( format ), mOwnMemory( ownMemory )
52 | {
53 | }
54 |
55 | // Destroy image
56 | XImage::~XImage( )
57 | {
58 | if ( ( mOwnMemory ) && ( mData != nullptr ) )
59 | {
60 | free( mData );
61 | }
62 | }
63 |
64 | // Allocate image of the specified size and format
65 | shared_ptr XImage::Allocate( int32_t width, int32_t height, XPixelFormat format, bool zeroInitialize )
66 | {
67 | int32_t stride = (int32_t) XImageBytesPerStride( width * XImageBitsPerPixel( format ) );
68 | XImage* image = nullptr;
69 | uint8_t* data = nullptr;
70 |
71 | if ( zeroInitialize )
72 | {
73 | data = (uint8_t*) calloc( 1, height * stride );
74 | }
75 | else
76 | {
77 | data = (uint8_t*) malloc( height * stride );
78 | }
79 |
80 | if ( data != nullptr )
81 | {
82 | image = new (nothrow) XImage( data, width, height, stride, format, true );
83 | }
84 |
85 | return shared_ptr( image );
86 | }
87 |
88 | // Create image by wrapping existing memory buffer
89 | shared_ptr XImage::Create( uint8_t* data, int32_t width, int32_t height, int32_t stride, XPixelFormat format )
90 | {
91 | return shared_ptr( new (nothrow) XImage( data, width, height, stride, format, false ) );
92 | }
93 |
94 | // Clone image - make a deep copy of it
95 | shared_ptr XImage::Clone( ) const
96 | {
97 | shared_ptr clone;
98 |
99 | if ( mData != nullptr )
100 | {
101 | clone = Allocate( mWidth, mHeight, mFormat );
102 |
103 | if ( clone )
104 | {
105 | if ( CopyData( clone ) != XError::Success )
106 | {
107 | clone.reset( );
108 | }
109 | }
110 | }
111 |
112 | return clone;
113 | }
114 |
115 | // Copy content of the image - destination image must have same width/height/format
116 | XError XImage::CopyData( const shared_ptr& copyTo ) const
117 | {
118 | XError ret = XError::Success;
119 |
120 | if ( ( mData == nullptr ) || ( !copyTo ) || ( copyTo->mData == nullptr ) )
121 | {
122 | ret = XError::NullPointer;
123 | }
124 | // for JPEGs we just make sure there is enough space to copy the image data,
125 | // but for all uncompressed formats we check for exact match of width/height
126 | else if ( ( mHeight != copyTo->mHeight ) || ( mFormat != copyTo->mFormat ) )
127 | {
128 | ret = XError::ImageParametersMismatch;
129 | }
130 | else if ( ( ( mFormat != XPixelFormat::JPEG ) && ( mWidth != copyTo->mWidth ) ) ||
131 | ( ( mFormat == XPixelFormat::JPEG ) && ( mStride > copyTo->mStride ) ) )
132 | {
133 | ret = XError::ImageParametersMismatch;
134 | }
135 | else
136 | {
137 | uint32_t lineSize = XImageBytesPerLine( mWidth * XImageBitsPerPixel( mFormat ) );
138 | uint8_t* srcPtr = mData;
139 | uint8_t* dstPtr = copyTo->mData;
140 | int32_t dstStride = copyTo->mStride;
141 |
142 | for ( int y = 0; y < mHeight; y++ )
143 | {
144 | memcpy( dstPtr, srcPtr, lineSize );
145 | srcPtr += mStride;
146 | dstPtr += dstStride;
147 | }
148 |
149 | if ( mFormat == XPixelFormat::JPEG )
150 | {
151 | // set correct size of destionation JPEG image
152 | copyTo->mWidth = mWidth;
153 | }
154 | }
155 |
156 | return ret;
157 | }
158 |
159 | // Copy content of the image into the specified one if its size/format is same or make a clone
160 | XError XImage::CopyDataOrClone( std::shared_ptr& copyTo ) const
161 | {
162 | XError ret = XError::Success;
163 |
164 | if ( ( !copyTo ) ||
165 | ( copyTo->Height( ) != mHeight ) ||
166 | ( copyTo->Format( ) != mFormat ) ||
167 | ( ( mFormat != XPixelFormat::JPEG ) && ( copyTo->Width( ) != mWidth ) ) ||
168 | ( ( mFormat == XPixelFormat::JPEG ) && ( copyTo->Stride( ) < mStride ) )
169 | )
170 | {
171 | copyTo = Clone( );
172 | if ( !copyTo )
173 | {
174 | ret = XError::OutOfMemory;
175 | }
176 | }
177 | else
178 | {
179 | ret = CopyData( copyTo );
180 | }
181 |
182 | return ret;
183 | }
184 |
--------------------------------------------------------------------------------
/src/core/XJpegEncoder.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | cam2web - streaming camera to web
3 |
4 | Copyright (C) 2017, cvsandbox, cvsandbox@gmail.com
5 |
6 | This program is free software; you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation; either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License along
17 | with this program; if not, write to the Free Software Foundation, Inc.,
18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | #include "XJpegEncoder.hpp"
22 |
23 | #include
24 | #include
25 |
26 | using namespace std;
27 |
28 | namespace Private
29 | {
30 | class JpegException : public exception
31 | {
32 | public:
33 | virtual const char* what( ) const throw( )
34 | {
35 | return "JPEG coding failure";
36 | }
37 | };
38 |
39 | static void my_error_exit( j_common_ptr /* cinfo */ )
40 | {
41 | throw JpegException( );
42 | }
43 |
44 | static void my_output_message( j_common_ptr /* cinfo */ )
45 | {
46 | // do nothing - kill the message
47 | }
48 |
49 | class XJpegEncoderData
50 | {
51 | public:
52 | uint16_t Quality;
53 | bool FasterCompression;
54 | private:
55 | struct jpeg_compress_struct cinfo;
56 | struct jpeg_error_mgr jerr;
57 |
58 | public:
59 | XJpegEncoderData( uint16_t quality, bool fasterCompression) :
60 | Quality( quality ), FasterCompression( fasterCompression )
61 | {
62 | if ( Quality > 100 )
63 | {
64 | Quality = 100;
65 | }
66 |
67 | // allocate and initialize JPEG compression object
68 | cinfo.err = jpeg_std_error( &jerr );
69 | jerr.error_exit = my_error_exit;
70 | jerr.output_message = my_output_message;
71 |
72 | jpeg_create_compress( &cinfo );
73 | }
74 |
75 | ~XJpegEncoderData( )
76 | {
77 | jpeg_destroy_compress( &cinfo );
78 | }
79 |
80 | XError EncodeToMemory( const shared_ptr& image, uint8_t** buffer, uint32_t* bufferSize );
81 | };
82 | }
83 |
84 | XJpegEncoder::XJpegEncoder( uint16_t quality, bool fasterCompression ) :
85 | mData( new Private::XJpegEncoderData( quality, fasterCompression ) )
86 | {
87 |
88 | }
89 |
90 | XJpegEncoder::~XJpegEncoder( )
91 | {
92 | delete mData;
93 | }
94 |
95 | // Set/get compression quality, [0, 100]
96 | uint16_t XJpegEncoder::Quality( ) const
97 | {
98 | return mData->Quality;
99 | }
100 | void XJpegEncoder::SetQuality( uint16_t quality )
101 | {
102 | mData->Quality = quality;
103 | if ( mData->Quality > 100 ) mData->Quality = 100;
104 | if ( mData->Quality < 1 ) mData->Quality = 1;
105 | }
106 |
107 | // Set/get faster compression (but less accurate) flag
108 | bool XJpegEncoder::FasterCompression( ) const
109 | {
110 | return mData->FasterCompression;
111 | }
112 | void XJpegEncoder::SetFasterCompression( bool faster )
113 | {
114 | mData->FasterCompression = faster;
115 | }
116 |
117 | // Compress the specified image into provided buffer
118 | XError XJpegEncoder::EncodeToMemory( const shared_ptr& image, uint8_t** buffer, uint32_t* bufferSize )
119 | {
120 | return mData->EncodeToMemory( image, buffer, bufferSize );
121 | }
122 |
123 | namespace Private
124 | {
125 |
126 | XError XJpegEncoderData::EncodeToMemory( const shared_ptr& image, uint8_t** buffer, uint32_t* bufferSize )
127 | {
128 | JSAMPROW row_pointer[1];
129 | XError ret = XError::Success;
130 |
131 | if ( ( !image ) || ( image->Data( ) == nullptr ) || ( buffer == nullptr ) || ( *buffer == nullptr ) || ( bufferSize == nullptr ) )
132 | {
133 | ret = XError::NullPointer;
134 | }
135 | else if ( ( image->Format( ) != XPixelFormat::RGB24 ) && ( image->Format( ) != XPixelFormat::Grayscale8 ) )
136 | {
137 | ret = XError::UnsupportedPixelFormat;
138 | }
139 | else
140 | {
141 | try
142 | {
143 | // 1 - specify data destination
144 | unsigned long mem_buffer_size = *bufferSize;
145 | jpeg_mem_dest( &cinfo, buffer, &mem_buffer_size );
146 |
147 | // 2 - set parameters for compression
148 | cinfo.image_width = image->Width( );
149 | cinfo.image_height = image->Height( );
150 |
151 | if ( image->Format( ) == XPixelFormat::RGB24 )
152 | {
153 | cinfo.input_components = 3;
154 | cinfo.in_color_space = JCS_RGB;
155 | }
156 | else
157 | {
158 | cinfo.input_components = 1;
159 | cinfo.in_color_space = JCS_GRAYSCALE;
160 | }
161 |
162 | // set default compression parameters
163 | jpeg_set_defaults( &cinfo );
164 | // set quality
165 | jpeg_set_quality( &cinfo, (int) Quality, TRUE /* limit to baseline-JPEG values */ );
166 |
167 | // use faster, but less accurate compressions
168 | cinfo.dct_method = ( FasterCompression ) ? JDCT_FASTEST : JDCT_DEFAULT;
169 |
170 | // 3 - start compressor
171 | jpeg_start_compress( &cinfo, TRUE );
172 |
173 | // 4 - do compression
174 | while ( cinfo.next_scanline < cinfo.image_height )
175 | {
176 | row_pointer[0] = image->Data( ) + image->Stride( ) * cinfo.next_scanline;
177 |
178 | jpeg_write_scanlines( &cinfo, row_pointer, 1 );
179 | }
180 |
181 | // 5 - finish compression
182 | jpeg_finish_compress( &cinfo );
183 |
184 | *bufferSize = (uint32_t) mem_buffer_size;
185 | }
186 | catch ( const JpegException& )
187 | {
188 | ret = XError::FailedImageEncoding;
189 | }
190 | }
191 |
192 | return ret;
193 | }
194 |
195 | } // namespace Private
196 |
--------------------------------------------------------------------------------
/src/core/cameras/DirectShow/XLocalVideoDevice.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | cam2web - streaming camera to web
3 |
4 | Copyright (C) 2017, cvsandbox, cvsandbox@gmail.com
5 |
6 | This program is free software; you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation; either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License along
17 | with this program; if not, write to the Free Software Foundation, Inc.,
18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | #ifndef XLOCAL_VIDEO_DEVICE_HPP
22 | #define XLOCAL_VIDEO_DEVICE_HPP
23 |
24 | #include
25 | #include
26 | #include
27 |
28 | #include "XDeviceName.hpp"
29 | #include "XDeviceCapabilities.hpp"
30 | #include "XDevicePinInfo.hpp"
31 |
32 | namespace Private
33 | {
34 | class XLocalVideoDeviceData;
35 | };
36 |
37 | enum class XVideoProperty
38 | {
39 | Brightness = 0,
40 | Contrast,
41 | Hue,
42 | Saturation,
43 | Sharpness,
44 | Gamma,
45 | ColorEnable,
46 | WhiteBalance,
47 | BacklightCompensation,
48 | Gain
49 | };
50 |
51 | enum class XCameraProperty
52 | {
53 | Pan = 0,
54 | Tilt,
55 | Roll,
56 | Zoom,
57 | Exposure,
58 | Iris,
59 | Focus
60 | };
61 |
62 | // Class which provides access to local video devices available through DirectShow interface
63 | class XLocalVideoDevice : public IVideoSource, private Uncopyable
64 | {
65 | private:
66 | XLocalVideoDevice( const std::string& deviceMoniker );
67 |
68 | public:
69 | ~XLocalVideoDevice( );
70 |
71 | static const std::shared_ptr Create( const std::string& deviceMoniker = std::string( ) );
72 |
73 | // Start video source so it initializes and begins providing video frames
74 | virtual bool Start( );
75 | // Signal video source to stop, so it could finalize and clean-up
76 | virtual void SignalToStop( );
77 | // Wait till video source stops
78 | virtual void WaitForStop( );
79 | // Check if video source (its background thread) is running or not
80 | virtual bool IsRunning( );
81 | // Get number of frames received since the the start of the video source
82 | virtual uint32_t FramesReceived( );
83 |
84 | // Set video source listener returning the old one
85 | virtual IVideoSourceListener* SetListener( IVideoSourceListener* listener );
86 |
87 | // Set device moniker for the video source (video source must not be running)
88 | bool SetDeviceMoniker( const std::string& moniker );
89 | // Set resolution and frame rate of the device (video source must not be running)
90 | bool SetResolution( const XDeviceCapabilities& resolution, uint32_t requestedFps = 0 );
91 | // Set video input of the device
92 | void SetVideoInput( const XDevicePinInfo& input );
93 |
94 | // Get/Set JPEG encoding preference. Not guaranteed as device/driver may not support it.
95 | bool IsJpegEncodingPreferred( ) const;
96 | void PreferJpegEncoding( bool prefer );
97 | // Check if running device was configured to provide JPEG images. Always returns
98 | // false for not running devices. NOTE: provided image pixel format already will indicate
99 | // this, but having extra property may be handy.
100 | bool IsJpegEncodingEnabled( ) const;
101 |
102 | // Get capabilities of the device (resolutions and frame rates)
103 | const std::vector GetCapabilities( );
104 | // Get available video pins of the device if any
105 | const std::vector GetInputVideoPins( );
106 | // Check if device supports crossbar, which would allow setting video input pin
107 | bool IsCrossbarSupported( );
108 |
109 | // Get list of available video devices in the system
110 | static std::vector GetAvailableDevices( );
111 |
112 | // The IsRunning() reports if video source's background thread is running or not. However,
113 | // it does not mean the video device itself is running. When the thread is started, it
114 | // needs to perform certain configuration of the device and start it, which may or may not
115 | // succeed (device can be un-plugged, used by another application, etc). So the
116 | // IsDeviceRunning() reports status of the device itself.
117 |
118 | // Check if device is running
119 | bool IsDeviceRunning( ) const;
120 | // Wait till video configuration becomes available (milliseconds)
121 | bool WaitForDeviceRunning( uint32_t msec );
122 |
123 | // Check if video configuration is supported (device must be running)
124 | bool IsVideoConfigSupported( ) const;
125 |
126 | // Set the specified video property. The device does not have to be running. If it is not,
127 | // the setting will be cached and applied as soon as the device gets running.
128 | XError SetVideoProperty( XVideoProperty property, int32_t value, bool automatic = false );
129 | // Get current value if the specified video property. The device must be running.
130 | XError GetVideoProperty( XVideoProperty property, int32_t* value, bool* automatic = nullptr ) const;
131 | // Get range of values supported by the specified video property
132 | XError GetVideoPropertyRange( XVideoProperty property, int32_t* min, int32_t* max, int32_t* step, int32_t* default, bool* isAutomaticSupported ) const;
133 |
134 | // Check if camera configuration is supported (device must be running)
135 | bool IsCameraConfigSupported( ) const;
136 |
137 | // Set the specified camera property. The device does not have to be running. If it is not,
138 | // the setting will be cached and applied as soon as the device gets running.
139 | XError SetCameraProperty( XCameraProperty property, int32_t value, bool automatic = false );
140 | // Get current value if the specified camera property. The device must be running.
141 | XError GetCameraProperty( XCameraProperty property, int32_t* value, bool* automatic = nullptr ) const;
142 | // Get range of values supported by the specified camera property
143 | XError GetCameraPropertyRange( XCameraProperty property, int32_t* min, int32_t* max, int32_t* step, int32_t* default, bool* isAutomaticSupported ) const;
144 |
145 | private:
146 | Private::XLocalVideoDeviceData* mData;
147 | };
148 |
149 | #endif // XLOCAL_VIDEO_DEVICE_HPP
150 |
--------------------------------------------------------------------------------
/src/web/cameraproperties.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
Reset to Defaults
7 |
8 |
9 |
10 |
194 |
--------------------------------------------------------------------------------
/src/apps/win/Tools.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | cam2web - streaming camera to web
3 |
4 | Copyright (C) 2017-2019, cvsandbox, cvsandbox@gmail.com
5 |
6 | This program is free software; you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation; either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License along
17 | with this program; if not, write to the Free Software Foundation, Inc.,
18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | // Exclude rarely-used stuff from Windows headers
22 | #define WIN32_LEAN_AND_MEAN
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | #include "Tools.hpp"
30 |
31 | using namespace std;
32 |
33 | static const char* STR_ARGB_FORMAT32 = "%08X";
34 | static const char* STR_ARGB_FORMAT24 = "%06X";
35 |
36 | // Convert specfied UTF8 string to wide character string
37 | wstring Utf8to16( const string& utf8string )
38 | {
39 | wstring ret;
40 |
41 | int required = MultiByteToWideChar( CP_UTF8, 0, utf8string.c_str( ), -1, nullptr, 0 );
42 |
43 | if ( required > 0 )
44 | {
45 | wchar_t* utf16string = new wchar_t[required];
46 |
47 | if ( MultiByteToWideChar( CP_UTF8, 0, utf8string.c_str( ), -1, utf16string, required ) > 0 )
48 | {
49 | ret = wstring( utf16string );
50 | }
51 |
52 | delete[] utf16string;
53 | }
54 |
55 | return ret;
56 | }
57 |
58 | // Convert specfied wide character string to UTF8 string
59 | string Utf16to8( const wstring& utf16string )
60 | {
61 | string ret;
62 |
63 | int required = WideCharToMultiByte( CP_UTF8, 0, utf16string.c_str( ), -1, nullptr, 0, nullptr, nullptr );
64 |
65 | if ( required > 0 )
66 | {
67 | char* utf8string = new char[required];
68 |
69 | if ( WideCharToMultiByte( CP_UTF8, 0, utf16string.c_str( ), -1, utf8string, required, nullptr, nullptr ) > 0 )
70 | {
71 | ret = string( utf8string );
72 | }
73 |
74 | delete[] utf8string;
75 | }
76 |
77 | return ret;
78 | }
79 |
80 | // Calculate MD5 hash string for the given buffer
81 | string GetMd5Hash( const uint8_t* buffer, int bufferLength )
82 | {
83 | HCRYPTPROV hCryptProv = NULL;
84 | HCRYPTHASH hHash = NULL;
85 | string md5str;
86 |
87 | if ( CryptAcquireContext( &hCryptProv, NULL, NULL, PROV_RSA_FULL, 0 ) )
88 | {
89 | if ( CryptCreateHash( hCryptProv, CALG_MD5, 0, 0, &hHash ) )
90 | {
91 | if ( CryptHashData( hHash, buffer, bufferLength, 0 ) )
92 | {
93 | DWORD dataLength;
94 | DWORD hashSize;
95 |
96 | dataLength = sizeof( hashSize );
97 | if ( CryptGetHashParam( hHash, HP_HASHSIZE, (BYTE*) &hashSize, &dataLength, 0 ) )
98 | {
99 | BYTE* hashValue = new BYTE[hashSize];
100 |
101 | dataLength = hashSize;
102 | if ( CryptGetHashParam( hHash, HP_HASHVAL, hashValue, &dataLength, 0 ) )
103 | {
104 | char hex[3];
105 |
106 | for ( DWORD i = 0; i < hashSize; i++ )
107 | {
108 | _itoa( hashValue[i], hex, 16 );
109 | md5str += hex;
110 | }
111 | }
112 |
113 | delete [] hashValue;
114 | }
115 | }
116 | }
117 | }
118 |
119 | if ( hHash != NULL )
120 | {
121 | CryptDestroyHash( hHash );
122 | }
123 | if ( hCryptProv != NULL )
124 | {
125 | CryptReleaseContext( hCryptProv, 0 );
126 | }
127 |
128 | return md5str;
129 | }
130 |
131 | // Get local IP address as string (if a single valid IP found). Returns empty string if fails to resolve.
132 | string GetLocalIpAddress( )
133 | {
134 | PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *) malloc( sizeof( IP_ADAPTER_INFO ) );
135 | PIP_ADAPTER_INFO pAdapter = nullptr;
136 | ULONG ulOutBufLen = sizeof( IP_ADAPTER_INFO );
137 | string localIp;
138 |
139 | if ( pAdapterInfo != nullptr )
140 | {
141 | if ( GetAdaptersInfo( pAdapterInfo, &ulOutBufLen ) == ERROR_BUFFER_OVERFLOW )
142 | {
143 | free( pAdapterInfo );
144 | pAdapterInfo = (IP_ADAPTER_INFO *) malloc( ulOutBufLen );
145 | }
146 | }
147 |
148 | if ( pAdapterInfo != nullptr )
149 | {
150 | if ( GetAdaptersInfo( pAdapterInfo, &ulOutBufLen ) == NO_ERROR )
151 | {
152 | pAdapter = pAdapterInfo;
153 |
154 | while ( pAdapter )
155 | {
156 | if ( ( strcmp( pAdapter->IpAddressList.IpAddress.String, "0.0.0.0" ) != 0 ) &&
157 | ( strcmp( pAdapter->GatewayList.IpAddress.String, "0.0.0.0" ) != 0 ) &&
158 | ( pAdapter->IpAddressList.Next == nullptr ) &&
159 | ( pAdapter->GatewayList.Next == nullptr ) )
160 | {
161 | if ( localIp.empty( ) )
162 | {
163 | localIp = string( pAdapter->IpAddressList.IpAddress.String );
164 | }
165 | else
166 | {
167 | // if there is more than one valid IP, assume we've failed
168 | localIp.clear( );
169 | break;
170 | }
171 | }
172 |
173 | pAdapter = pAdapter->Next;
174 | }
175 | }
176 |
177 | free( pAdapterInfo );
178 | }
179 |
180 | return localIp;
181 | }
182 |
183 | // Convert xargb to string
184 | std::string XargbToString( xargb color )
185 | {
186 | char buffer[16];
187 |
188 | if ( color.components.a != 0xFF )
189 | {
190 | sprintf( buffer, STR_ARGB_FORMAT32, color.argb );
191 | }
192 | else
193 | {
194 | color.components.a = 0;
195 | sprintf( buffer, STR_ARGB_FORMAT24, color.argb );
196 | }
197 |
198 | return string( buffer );
199 | }
200 |
201 | // Parse xargb from string
202 | bool StringToXargb( const string& str, xargb* color )
203 | {
204 | size_t len = str.length( );
205 | xargb newColor = { 0xFF000000 };
206 | bool parsed = false;
207 |
208 | if ( len == 8 )
209 | {
210 | parsed = ( sscanf( str.c_str( ), STR_ARGB_FORMAT32, &newColor.argb ) == 1 );
211 | }
212 | else if ( len == 6 )
213 | {
214 | // in the case if only 6 hex numbers present, suppose it is RGB value with alpha set to FF
215 | if ( sscanf( str.c_str( ), STR_ARGB_FORMAT24, &newColor.argb ) == 1 )
216 | {
217 | newColor.components.a = 0xFF;
218 | parsed = true;
219 | }
220 | }
221 |
222 | if ( ( color != nullptr ) && ( parsed ) )
223 | {
224 | *color = newColor;
225 | }
226 |
227 | return parsed;
228 | }
229 |
--------------------------------------------------------------------------------
/src/apps/win/EditUserDialog.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | cam2web - streaming camera to web
3 |
4 | Copyright (C) 2017, cvsandbox, cvsandbox@gmail.com
5 |
6 | This program is free software; you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation; either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License along
17 | with this program; if not, write to the Free Software Foundation, Inc.,
18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | // Exclude rarely-used stuff from Windows headers
22 | #define WIN32_LEAN_AND_MEAN
23 |
24 | #include
25 | #include
26 |
27 | #include "resource.h"
28 | #include "EditUserDialog.hpp"
29 | #include "Tools.hpp"
30 | #include "UiTools.hpp"
31 |
32 | using namespace std;
33 |
34 | #define STR_ERROR TEXT( "Error" )
35 |
36 | // Message handler for Add/Edit User dialog box
37 | INT_PTR CALLBACK EditUserDialogProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
38 | {
39 | static HICON hIcon = NULL;
40 | static UserInfo* pUserInfo = nullptr;
41 | int wmId;
42 | int wmEvent;
43 |
44 | switch ( message )
45 | {
46 | case WM_INITDIALOG:
47 | {
48 | HWND hwndUserNameEdit = GetDlgItem( hDlg, IDC_USER_NAME_EDIT );
49 | HWND hwndUserRoleCombo = GetDlgItem( hDlg, IDC_USER_ROLE_COMBO );
50 | HWND hwndPasswordEdit = GetDlgItem( hDlg, IDC_PASSWORD_EDIT );
51 | HWND hwndRePasswordEdit = GetDlgItem( hDlg, IDC_RE_PASSWORD_EDIT );
52 |
53 | CenterWindowTo( hDlg, GetParent( hDlg ) );
54 |
55 | hIcon = (HICON) LoadImage( GetModuleHandle( NULL ), MAKEINTRESOURCE( IDI_FAMILY ), IMAGE_ICON,
56 | GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), 0 );
57 |
58 | if ( hIcon )
59 | {
60 | SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );
61 | }
62 |
63 | // limit length of user name/password to something sensible
64 | SendMessage( hwndUserNameEdit, EM_SETLIMITTEXT, 32, 0 );
65 | SendMessage( hwndPasswordEdit, EM_SETLIMITTEXT, 32, 0 );
66 | SendMessage( hwndRePasswordEdit, EM_SETLIMITTEXT, 32, 0 );
67 |
68 | SendMessage( hwndUserRoleCombo, CB_ADDSTRING, 0, (LPARAM) L"User" );
69 | SendMessage( hwndUserRoleCombo, CB_ADDSTRING, 0, (LPARAM) L"Admin" );
70 | SendMessage( hwndUserRoleCombo, CB_SETCURSEL, 0, 0 );
71 |
72 | pUserInfo = (UserInfo*) lParam;
73 |
74 | if ( pUserInfo != nullptr )
75 | {
76 | if ( !pUserInfo->Name.empty( ) )
77 | {
78 | wstring password = Utf8to16( pUserInfo->Password );
79 |
80 | SetWindowText( hwndUserNameEdit, Utf8to16( pUserInfo->Name ).c_str( ) );
81 | SetWindowText( hwndPasswordEdit, password.c_str( ) );
82 | SetWindowText( hwndRePasswordEdit, password.c_str( ) );
83 | SendMessage( hwndUserRoleCombo, CB_SETCURSEL, ( pUserInfo->IsAdmin ) ? 1 : 0, 0 );
84 |
85 | // allow editting everything except user name
86 | SendMessage( hwndUserNameEdit, EM_SETREADONLY, 1, 0 );
87 |
88 | SetWindowText( hDlg, L"Edit user" );
89 | }
90 | else
91 | {
92 | // disable OK button, since user name/password are all empty
93 | EnableWindow( GetDlgItem( hDlg, IDOK ), FALSE );
94 | }
95 |
96 | pUserInfo->PasswordChanged = false;
97 | }
98 | }
99 | return (INT_PTR) TRUE;
100 |
101 | case WM_DESTROY:
102 |
103 | if ( hIcon )
104 | {
105 | DestroyIcon( hIcon );
106 | }
107 |
108 | pUserInfo = nullptr;
109 |
110 | return (INT_PTR) TRUE;
111 |
112 | case WM_COMMAND:
113 | wmId = LOWORD( wParam );
114 | wmEvent = HIWORD( wParam );
115 |
116 | if ( ( wmId == IDOK ) || ( wmId == IDCANCEL ) )
117 | {
118 | bool allFine = true;
119 |
120 | if ( ( wmId == IDOK ) && ( pUserInfo ) )
121 | {
122 | string userName = GetWindowString( GetDlgItem( hDlg, IDC_USER_NAME_EDIT ), true );
123 | string password1 = GetWindowString( GetDlgItem( hDlg, IDC_PASSWORD_EDIT ), false );
124 | string password2 = GetWindowString( GetDlgItem( hDlg, IDC_RE_PASSWORD_EDIT ), false );
125 |
126 | allFine = false;
127 |
128 | if ( std::find( pUserInfo->ExistingUserNames.begin( ), pUserInfo->ExistingUserNames.end( ), userName ) != pUserInfo->ExistingUserNames.end( ) )
129 | {
130 | CenteredMessageBox( hDlg, L"A user with the specified name already exists.", STR_ERROR, MB_OK | MB_ICONERROR );
131 | }
132 | else if ( password1 != password2 )
133 | {
134 | CenteredMessageBox( hDlg, L"The two passwords don't match.", STR_ERROR, MB_OK | MB_ICONERROR );
135 | }
136 | else if ( userName.find( ':' ) != string::npos )
137 | {
138 | CenteredMessageBox( hDlg, L"User names are not allowed to contain colon character (':').", STR_ERROR, MB_OK | MB_ICONERROR );
139 | }
140 | else
141 | {
142 | allFine = true;
143 |
144 | pUserInfo->Name = userName;
145 | pUserInfo->Password = password1;
146 | pUserInfo->IsAdmin = ( SendMessage( GetDlgItem( hDlg, IDC_USER_ROLE_COMBO ), CB_GETCURSEL, 0, 0 ) == 1 );
147 | }
148 | }
149 |
150 | if ( allFine )
151 | {
152 | EndDialog( hDlg, wmId );
153 | }
154 | return (INT_PTR) TRUE;
155 | }
156 | else if ( wmEvent == EN_CHANGE )
157 | {
158 | if ( ( wmId == IDC_USER_NAME_EDIT ) || ( wmId == IDC_PASSWORD_EDIT ) || ( wmId == IDC_RE_PASSWORD_EDIT ) )
159 | {
160 | string userName = GetWindowString( GetDlgItem( hDlg, IDC_USER_NAME_EDIT ), true );
161 | string password1 = GetWindowString( GetDlgItem( hDlg, IDC_PASSWORD_EDIT ), false );
162 | string password2 = GetWindowString( GetDlgItem( hDlg, IDC_RE_PASSWORD_EDIT ), false );
163 | bool isEmpty = ( userName.empty( ) || password1.empty( ) || password2.empty( ) );
164 |
165 | EnableWindow( GetDlgItem( hDlg, IDOK ), ( isEmpty ) ? FALSE : TRUE );
166 |
167 | if ( ( pUserInfo != nullptr ) && ( ( wmId == IDC_PASSWORD_EDIT ) || ( wmId == IDC_RE_PASSWORD_EDIT ) ) )
168 | {
169 | pUserInfo->PasswordChanged = true;
170 | }
171 |
172 | return (INT_PTR) TRUE;
173 | }
174 | }
175 |
176 | break;
177 | }
178 |
179 | return (INT_PTR) FALSE;
180 | }
181 |
--------------------------------------------------------------------------------
/src/core/cameras/V4L2/XV4LCameraConfig.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | cam2web - streaming camera to web
3 |
4 | Copyright (C) 2017, cvsandbox, cvsandbox@gmail.com
5 |
6 | This program is free software; you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation; either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License along
17 | with this program; if not, write to the Free Software Foundation, Inc.,
18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | #include
22 | #include
23 | #include
24 |
25 | #include "XV4LCameraConfig.hpp"
26 |
27 | using namespace std;
28 |
29 | #define TYPE_INT (0)
30 | #define TYPE_BOOL (1)
31 |
32 | typedef struct
33 | {
34 | XVideoProperty VideoProperty;
35 | uint16_t Type;
36 | uint16_t Order;
37 | const char* Name;
38 | }
39 | PropertyInformation;
40 |
41 | const static map SupportedProperties =
42 | {
43 | { "brightness", { XVideoProperty::Brightness, TYPE_INT, 0, "Brightness" } },
44 | { "contrast", { XVideoProperty::Contrast, TYPE_INT, 1, "Contrast" } },
45 | { "saturation", { XVideoProperty::Saturation, TYPE_INT, 2, "Saturation" } },
46 | { "hue", { XVideoProperty::Hue, TYPE_INT, 3, "Hue" } },
47 | { "sharpness", { XVideoProperty::Sharpness, TYPE_INT, 4, "Sharpness" } },
48 | { "gain", { XVideoProperty::Gain, TYPE_INT, 5, "Gain" } },
49 | { "blc", { XVideoProperty::BacklightCompensation, TYPE_INT, 6, "Back Light Compensation" } },
50 | { "redBalance", { XVideoProperty::RedBalance, TYPE_INT, 7, "Red Balance" } },
51 | { "blueBalance", { XVideoProperty::BlueBalance, TYPE_INT, 8, "Blue Balance" } },
52 | { "awb", { XVideoProperty::AutoWhiteBalance, TYPE_BOOL, 9, "Automatic White Balance" } },
53 | { "hflip", { XVideoProperty::HorizontalFlip, TYPE_BOOL, 10, "Horizontal Flip" } },
54 | { "vflip", { XVideoProperty::VerticalFlip, TYPE_BOOL, 11, "Vertical Flip" } }
55 | };
56 |
57 | // ------------------------------------------------------------------------------------------
58 |
59 | XV4LCameraConfig::XV4LCameraConfig( const shared_ptr& camera ) :
60 | mCamera( camera )
61 | {
62 |
63 | }
64 |
65 | // Set the specified property of a DirectShow video device
66 | XError XV4LCameraConfig::SetProperty( const string& propertyName, const string& value )
67 | {
68 | XError ret = XError::Success;
69 | int32_t propValue = 0;
70 |
71 | // assume all configuration values are numeric
72 | int scannedCount = sscanf( value.c_str( ), "%d", &propValue );
73 |
74 | if ( scannedCount != 1 )
75 | {
76 | ret = XError::InvalidPropertyValue;
77 | }
78 | else
79 | {
80 | map::const_iterator itSupportedProperty = SupportedProperties.find( propertyName );
81 |
82 | if ( itSupportedProperty == SupportedProperties.end( ) )
83 | {
84 | ret = XError::UnknownProperty;
85 | }
86 | else
87 | {
88 | ret = mCamera->SetVideoProperty( itSupportedProperty->second.VideoProperty, propValue );
89 | }
90 | }
91 |
92 | return ret;
93 | }
94 |
95 | // Get the specified property of a DirectShow video device
96 | XError XV4LCameraConfig::GetProperty( const string& propertyName, string& value ) const
97 | {
98 | XError ret = XError::Success;
99 | int32_t propValue = 0;
100 | char buffer[32];
101 |
102 | // find the property in the list of supported
103 | map::const_iterator itSupportedProperty = SupportedProperties.find( propertyName );
104 |
105 | if ( itSupportedProperty == SupportedProperties.end( ) )
106 | {
107 | ret = XError::UnknownProperty;
108 | }
109 | else
110 | {
111 | // get the property value itself
112 | ret = mCamera->GetVideoProperty( itSupportedProperty->second.VideoProperty, &propValue );
113 | }
114 |
115 | if ( ret )
116 | {
117 | sprintf( buffer, "%d", propValue );
118 | value = buffer;
119 | }
120 |
121 | return ret;
122 | }
123 |
124 | // Get all supported properties of a DirectShow video device
125 | map XV4LCameraConfig::GetAllProperties( ) const
126 | {
127 | map properties;
128 | string value;
129 |
130 | for ( auto property : SupportedProperties )
131 | {
132 | if ( GetProperty( property.first, value ) )
133 | {
134 | properties.insert( pair( property.first, value ) );
135 | }
136 | }
137 |
138 | return properties;
139 | }
140 |
141 | // ------------------------------------------------------------------------------------------
142 |
143 | XV4LCameraPropsInfo::XV4LCameraPropsInfo( const shared_ptr& camera ) :
144 | mCamera( camera )
145 | {
146 | }
147 |
148 | XError XV4LCameraPropsInfo::GetProperty( const std::string& propertyName, std::string& value ) const
149 | {
150 | XError ret = XError::Success;
151 | char buffer[128];
152 |
153 | // find the property in the list of supported
154 | map::const_iterator itSupportedProperty = SupportedProperties.find( propertyName );
155 |
156 | if ( itSupportedProperty == SupportedProperties.end( ) )
157 | {
158 | ret = XError::UnknownProperty;
159 | }
160 | else
161 | {
162 | int32_t min, max, step, def;
163 |
164 | // get property features - min/max/default/etc
165 | ret = mCamera->GetVideoPropertyRange( itSupportedProperty->second.VideoProperty, &min, &max, &step, &def );
166 |
167 | if ( ret )
168 | {
169 | if ( itSupportedProperty->second.Type == TYPE_INT )
170 | {
171 | sprintf( buffer, "{\"min\":%d,\"max\":%d,\"def\":%d,\"type\":\"int\",\"order\":%d,\"name\":\"%s\"}",
172 | min, max, def, itSupportedProperty->second.Order, itSupportedProperty->second.Name );
173 | }
174 | else
175 | {
176 | sprintf( buffer, "{\"def\":%d,\"type\":\"bool\",\"order\":%d,\"name\":\"%s\"}",
177 | def, itSupportedProperty->second.Order, itSupportedProperty->second.Name );
178 | }
179 |
180 | value = buffer;
181 | }
182 | }
183 |
184 | return ret;
185 | }
186 |
187 | // Get information for all supported properties of a DirectShow video device
188 | map XV4LCameraPropsInfo::GetAllProperties( ) const
189 | {
190 | map properties;
191 | string value;
192 |
193 | for ( auto property : SupportedProperties )
194 | {
195 | if ( GetProperty( property.first, value ) )
196 | {
197 | properties.insert( pair( property.first, value ) );
198 | }
199 | }
200 |
201 | return properties;
202 | }
203 |
204 |
--------------------------------------------------------------------------------
/src/core/XWebServer.hpp:
--------------------------------------------------------------------------------
1 | /*
2 | cam2web - streaming camera to web
3 |
4 | Copyright (C) 2017-2019, cvsandbox, cvsandbox@gmail.com
5 |
6 | This program is free software; you can redistribute it and/or modify
7 | it under the terms of the GNU General Public License as published by
8 | the Free Software Foundation; either version 2 of the License, or
9 | (at your option) any later version.
10 |
11 | This program is distributed in the hope that it will be useful,
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | GNU General Public License for more details.
15 |
16 | You should have received a copy of the GNU General Public License along
17 | with this program; if not, write to the Free Software Foundation, Inc.,
18 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 | */
20 |
21 | #ifndef XWEB_SERVER_HPP
22 | #define XWEB_SERVER_HPP
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include "XInterfaces.hpp"
31 |
32 | namespace Private
33 | {
34 | class XWebServerData;
35 | }
36 |
37 | enum class UserGroup
38 | {
39 | Anyone = 0,
40 | User = 1,
41 | Power = 2,
42 | Admin = 3
43 | };
44 |
45 | enum class Authentication
46 | {
47 | Basic = 0,
48 | Digest = 1
49 | };
50 |
51 | /* ================================================================= */
52 | /* Web request data */
53 | /* ================================================================= */
54 | class IWebRequest
55 | {
56 | public:
57 | virtual ~IWebRequest( ) { }
58 |
59 | virtual std::string Uri( ) const = 0;
60 | virtual std::string Method( ) const = 0;
61 | virtual std::string Proto( ) const = 0;
62 | virtual std::string Query( ) const = 0;
63 | virtual std::string Body( ) const = 0;
64 |
65 | virtual std::string GetVariable( const std::string& name ) const = 0;
66 |
67 | virtual std::map Headers( ) const = 0;
68 | };
69 |
70 | /* ================================================================= */
71 | /* Web response methods */
72 | /* ================================================================= */
73 | class IWebResponse
74 | {
75 | public:
76 | virtual ~IWebResponse( ) { }
77 |
78 | // Length of data, which is still enqueued for sending
79 | virtual size_t ToSendDataLength( ) const = 0;
80 |
81 | virtual void Send( const uint8_t* buffer, size_t length ) = 0;
82 | virtual void Printf( const char* fmt, ... ) = 0;
83 |
84 | virtual void SendChunk( const uint8_t* buffer, size_t length ) = 0;
85 | virtual void PrintfChunk( const char* fmt, ... ) = 0;
86 |
87 | virtual void SendError( int errorCode, const char* reason = nullptr ) = 0;
88 |
89 | virtual void CloseConnection( ) = 0;
90 |
91 | // Generate timer event for the connection associated with the response
92 | // after the specified number of milliseconds
93 | virtual void SetTimer( uint32_t msec ) = 0;
94 | };
95 |
96 | /* ================================================================= */
97 | /* Handler of a web request */
98 | /* ================================================================= */
99 | class IWebRequestHandler
100 | {
101 | protected:
102 | IWebRequestHandler( const std::string& uri, bool canHandleSubContent );
103 |
104 | public:
105 | virtual ~IWebRequestHandler( ) { }
106 |
107 | const std::string& Uri( ) const { return mUri; }
108 | bool CanHandleSubContent( ) const { return mCanHandleSubContent; }
109 |
110 | // Handle the specified request
111 | virtual void HandleHttpRequest( const IWebRequest& request, IWebResponse& response ) = 0;
112 |
113 | // Handle timer event
114 | virtual void HandleTimer( IWebResponse& ) { };
115 |
116 | private:
117 | std::string mUri;
118 | bool mCanHandleSubContent;
119 | };
120 |
121 | /* ================================================================= */
122 | /* Definition of embedded content */
123 | /* ================================================================= */
124 | typedef struct
125 | {
126 | uint32_t Length;
127 | const char* Type;
128 | const uint8_t* Body;
129 | }
130 | XEmbeddedContent;
131 |
132 | /* ================================================================= */
133 | /* Web request handler serving embedded content */
134 | /* ================================================================= */
135 | class XEmbeddedContentHandler : public IWebRequestHandler
136 | {
137 | public:
138 | XEmbeddedContentHandler( const std::string& uri, const XEmbeddedContent* content );
139 |
140 | // Handle request providing given embedded content
141 | void HandleHttpRequest( const IWebRequest& request, IWebResponse& response );
142 |
143 | private:
144 | const XEmbeddedContent* mContent;
145 | };
146 |
147 | /* ================================================================= */
148 | /* Web server class */
149 | /* ================================================================= */
150 | class XWebServer : private Uncopyable
151 | {
152 | public:
153 | XWebServer( const std::string& documentRoot = "", uint16_t port = 8000 );
154 | ~XWebServer( );
155 |
156 | /* ================================================================= */
157 | /* All of the below configuration must be done before starting */
158 | /* an instance of a Web server. Setting those while it is running */
159 | /* has no effect until it is restarted. */
160 | /* ================================================================= */
161 |
162 | // Get/Set document root
163 | std::string DocumentRoot( ) const;
164 | XWebServer& SetDocumentRoot( const std::string& documentRoot );
165 |
166 | // Get/Set authentication domain
167 | std::string AuthDomain( ) const;
168 | XWebServer& SetAuthDomain( const std::string& authDomain );
169 |
170 | // Get/Set authentication method (default Digest)
171 | Authentication AuthenticationMethod( ) const;
172 | XWebServer& SetAuthenticationMethod( Authentication authMethod );
173 |
174 | // Get/Set port
175 | uint16_t Port( ) const;
176 | XWebServer& SetPort( uint16_t port );
177 |
178 | // Add/Remove web handler
179 | XWebServer& AddHandler( const std::shared_ptr& handler, UserGroup allowedUserGroup = UserGroup::Anyone );
180 | void RemoveHandler( const std::shared_ptr& handler );
181 |
182 | // Remove all handlers
183 | void ClearHandlers( );
184 |
185 | // ==============================================================
186 |
187 | // Start/Stop the Web server
188 | bool Start( );
189 | void Stop( );
190 |
191 | // Get time of the last access/request to the web server
192 | std::chrono::steady_clock::time_point LastAccessTime( bool* pWasAccessed = nullptr );
193 | // Get time of the last access/request to the specified handler
194 | std::chrono::steady_clock::time_point LastAccessTime( const std::string& handlerUri, bool* pWasAccessed = nullptr );
195 |
196 | // Add/Remove user to access protected request handlers
197 | XWebServer& AddUser( const std::string& name, const std::string& digestHa1, UserGroup group );
198 | void RemoveUser( const std::string& name );
199 |
200 | // Load users from file having "htdigest" format (returns number of loaded users)
201 | uint32_t LoadUsersFromFile( const std::string& fileName );
202 |
203 | // Clear the list of users who can access the web server
204 | void ClearUsers( );
205 |
206 | public:
207 | // Calculate HA1 as defined by Digest authentication algorithm, MD5(user:domain:pass).
208 | static std::string CalculateDigestAuthHa1( const std::string& user, const std::string& domain, const std::string& pass );
209 |
210 | private:
211 | Private::XWebServerData* mData;
212 | };
213 |
214 | #endif // XWEB_SERVER_HPP
215 |
--------------------------------------------------------------------------------