1 // VideoInput.h: Video input processing using Gstreamer 2 // 3 // Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 4 // Free Software Foundation, Inc. 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 3 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 17 // along with this program; if not, write to the Free Software 18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 20 #ifndef GNASH_VIDEOINPUTGST_H 21 #define GNASH_VIDEOINPUTGST_H 22 23 #include <vector> 24 #include <cstdint> // for C99 int types 25 #include "VideoInput.h" 26 #include "gst/gst.h" 27 28 namespace gnash { 29 namespace media { 30 /// \namespace gst 31 /// 32 /// This namespace is used for the Gstreamer implmentation of the VideoInput 33 /// class. 34 namespace gst { 35 36 class GnashWebcam; 37 class GnashWebcamPrivate; 38 39 /// \class FramerateFraction 40 /// 41 /// Convience wrapper class which allows easily calculating fractions from 42 /// the information returned from probing hardware cameras for supported 43 /// framerates. 44 class FramerateFraction 45 { 46 public: 47 /// \var FramerateFraction::numerator 48 /// \brief contains a gint value for the numerator portion of a fraction. 49 gint numerator; 50 /// \var FramerateFraction::denominator 51 /// \brief contains a gint value for the denominator portion of a fraction. 52 gint denominator; 53 54 /// \brief Constructor which sets the numerator and denominator fields upon construction. 55 /// 56 /// @param num The integer numerator value to initialize the FramerateFraction class with. 57 /// 58 /// @param denom The integer denominator value to initialzie the FramerateFraction class with. 59 FramerateFraction(gint num, gint denom); 60 61 /// Create a new empty FramerateFraction class. 62 FramerateFraction(); 63 }; 64 65 /// \class WebcamVidFormat 66 /// 67 /// Class used to hold enumerated information about usable video formats. 68 /// 69 class WebcamVidFormat 70 { 71 public: 72 /// \var WebcamVidFormat::mimetype 73 /// \brief Contains a gchar* which describes the raw video input stream 74 /// from the camera formated in a Gstreamer video format 75 /// type (e.g. video/x-raw-rgb or video/x-raw-yuv). 76 gchar *mimetype; 77 78 /// \var WebcamVidFormat::width 79 /// \brief Contains a gint value describing the width of the selected 80 /// format. 81 gint width; 82 83 /// \var WebcamVidFormat::height 84 /// \brief Contains a gint value describing the height of the selected 85 /// format. 86 gint height; 87 88 /// \var WebcamVidFormat::numFramerates 89 /// \brief Contains a gint value representing the number of framerate 90 /// values supported by the format described in the mimetype var. 91 gint numFramerates; 92 93 /// \var WebcamVidFormat::framerates 94 /// \brief Pointer to a FramerateFraction class which simply holds a 95 /// temporary framerate variable while trying to determine the 96 /// highest possible supported framerate for the format described 97 /// in the mimetype var. 98 FramerateFraction *framerates; 99 100 /// \var WebcamVidFormat::highestFramerate 101 /// \brief Holds the highest_frame supported by the format described 102 /// in the mimetype var. 103 FramerateFraction highestFramerate; 104 105 /// Constructor for the WebcamVidFormat class 106 WebcamVidFormat(); 107 }; 108 109 110 /// \class VideoInputGst 111 /// 112 /// This class is the main class that interacts with the other classes 113 /// defined in this header file. However, most of the significant information 114 /// is actually stored in a GnashWebcamPrivate class. 115 /// 116 class VideoInputGst : public VideoInput 117 { 118 public: 119 120 /// Constructor for the VideoInputGst class 121 VideoInputGst(); 122 123 /// Destructor for the VideoInputGst class 124 ~VideoInputGst(); 125 126 static void getNames(std::vector<std::string>& names); 127 128 /// Return the current activity level of the webcam 129 // 130 /// @return A double specifying the amount of motion currently 131 /// detected by the camera. activityLevel()132 double activityLevel () const { return _activityLevel; } 133 134 /// The maximum available bandwidth for outgoing connections 135 // 136 /// TODO: see if this should really be here. bandwidth()137 size_t bandwidth() const { return _bandwidth; } 138 setBandwidth(size_t bandwidth)139 void setBandwidth(size_t bandwidth) { 140 _bandwidth = bandwidth; 141 } 142 143 /// The current frame rate of the webcam 144 // 145 /// @return A double specifying the webcam's current FPS currentFPS()146 double currentFPS() const { return _currentFPS; } 147 148 /// The maximum FPS rate of the webcam 149 // 150 /// @return A double specifying the webcam's maximum FPS fps()151 double fps() const { return _fps; } 152 153 /// Return the height of the webcam's frame height()154 size_t height() const { return _height; } 155 156 /// Return the width of the webcam's frame width()157 size_t width() const { return _width; } 158 159 /// The index of the camera index()160 size_t index() const { return _index; } 161 162 /// Request a native mode most closely matching the passed variables. 163 // 164 /// @param width The required width 165 /// @param height The required height 166 /// @param fps The required frame rate 167 /// @param favorArea How to match the requested mode. 168 void requestMode(size_t width, size_t height, double fps, bool favorArea); 169 170 /// Set the amount of motion required before notifying the core setMotionLevel(int m)171 void setMotionLevel(int m) { _motionLevel = m; } 172 173 /// Return the current motionLevel setting motionLevel()174 int motionLevel() const { return _motionLevel; } 175 176 /// Set time without motion in milliseconds before core is notified setMotionTimeout(int m)177 void setMotionTimeout(int m) { _motionTimeout = m; } 178 179 /// Return the current motionTimeout setting. motionTimeout()180 int motionTimeout() const { return _motionTimeout; } 181 mute(bool m)182 void mute(bool m) { _muted = m; } muted()183 bool muted() const { return _muted; } 184 185 /// Return the name of this webcam 186 // 187 /// @return a string specifying the name of the webcam. name()188 const std::string& name() const { return _name; } 189 190 /// Set the quality of the webcam setQuality(int q)191 void setQuality(int q) { _quality = q; } 192 193 /// Return the current quality of the webcam quality()194 int quality() const { return _quality; } 195 196 /// \brief Function starts up the pipeline designed earlier in code 197 /// execution. This puts everything into motion. 198 /// 199 /// @return True if the pipeline was started correctly, false otherwise. 200 bool play(); 201 202 /// \brief Function stops the pipeline designed earlier in code execution. 203 /// 204 /// @return True if the pipeline was stopped correctly, false otherwise. 205 bool stop(); 206 207 208 /// Set this VideoInput's webcam to the device corresponding to an index. 209 // 210 /// Now transfer the 211 /// important information from the GnashWebcam structure to the 212 /// GnashWebcamPrivate structure which is larger because it has 213 /// space to store Gstreamer pipeline, element and bin elements. 214 /// See definition of GnashWebcamPrivate for more info. 215 /// 216 /// @param dev_select The index of the camera the user wants to 217 /// select. 218 /// @return If the device index doesn't exist, return false 219 bool setWebcam(size_t index); 220 221 /// Call all functions necessary for initializing the camera. 222 // 223 /// For gstreamer this includes setting up bins. 224 // 225 /// Return false on failure of any initialization. 226 /// TODO: better throw MediaException. 227 bool init(); 228 229 /// \brief This function is important in the flow of the code. It looks 230 /// in the gnashrc file to see if you have a default camera defined 231 /// and selects that one (if it's defined), otherwise a videotestsrc 232 /// will be used for the remainder of the execution of the code. 233 /// Currently this code also calls other functions to make bins and 234 /// pipelines. It might be abstracted into separate functions later. 235 /// @return The integer value respresenting the selected webcam from the 236 /// gnashrc file. 237 int makeWebcamDeviceSelection(); 238 239 /// ================================== 240 /// Functions that shouldn't be public. 241 /// ================================== 242 243 /// \brief Function links the videoSaveBin to the videoSaveQueue in the 244 /// main bin. 245 /// @param webcam A pointer to the GnashWebcamPrivate webcam structure 246 /// created previously in a call to transferToPrivate() 247 /// 248 /// @return True if the link to the videoSaveQueue was successfully, false 249 /// otherwise. 250 gboolean webcamMakeVideoSaveLink(); 251 252 /// \brief Function breaks link between the videoSaveBin and the videoSaveQueue 253 /// in the main bin. 254 /// @param webcam A pointer to the GnashWebcamPrivate webcam structure 255 /// created previously in a call to transferToPrivate() 256 /// @return True if the link was succesfully broken, false otherwise 257 gboolean webcamBreakVideoSaveLink(); 258 259 /// \brief Function creates the save bin. For more information on pipeline 260 /// implementation and this function in general see the definition of 261 /// the _webcam_save_bin variable in the GnashWebcamPrivate structure 262 /// documentation. 263 /// 264 /// @param webcam A pointer to the GnashWebcamPrivate webcam structure 265 /// created previously in a call to transferToPrivate() 266 /// 267 /// @return True if everything went correctly (making elements, dropping 268 /// into bins and linking elements), false otherwis 269 gboolean webcamCreateSaveBin(); 270 271 /// \brief Function links the video_display_bin to the video_display_queue 272 /// in the main bin. 273 /// 274 /// @param webcam A pointer to the GnashWebcamPrivate webcam structure 275 /// created previously in a call to transferToPrivate() 276 /// 277 /// @return True if the link to the video_display_queue was successful, 278 /// False otherwise. 279 gboolean webcamMakeVideoDisplayLink(); 280 281 /// \brief Function breaks the link between the _videoDisplayBin and the 282 /// _videoDisplayQueue in the main bin 283 /// 284 /// @param webcam A pointer to the GnashWebcamPrivate webcam structure 285 /// created previously in a call to transferToPrivate() 286 /// 287 /// @return True if the link was successfully broken, false otherwise 288 gboolean webcamBreakVideoDisplayLink(); 289 290 private: 291 292 293 /// \brief This function makes a temporary pipeline with the selected device 294 /// to determine its capabilities (Gstreamer calls these caps). This 295 /// information is saved in a GnashWebcamPrivate class and will be 296 /// used when enumerating additional information about the camera and 297 /// in creating the real pipeline to capture video. 298 /// 299 /// @param dev_select The integer value of the camera the user wants to select. 300 /// This might be changed to the name of the camera, but it's 301 /// currently an integer (if it changes, we need to change the 302 /// gnashrc element). If this value is 0, you've selected a 303 /// videotestsrc. 304 /// 305 /// @return Nothing. All pertantent information is stored in a GnashWebcam class. 306 void getSelectedCaps(gint dev_select); 307 308 /// \brief This function is called by get_selected caps to determine what 309 /// formats the input device can handle. It saves all the information 310 /// it finds into an array of WebcamVidFormat pointers. This information 311 /// will then be analyzed and actually added as a supported format in 312 /// a call to addSupportedFormat. 313 /// 314 /// @param cam A pointer to the GnashWebcam structure you want to use as input. 315 /// @param caps A pointer to the capabilities discovered in the getSelectedCaps() function. 316 /// 317 /// @return Nothing. All pertantent information is stored in a GnashWebcam class. 318 void getSupportedFormats(GnashWebcam *cam, GstCaps *caps); 319 320 /// \brief This function is called by getSupportedFormats when it has 321 /// determined that the format being analyzed can be used to capture 322 /// information from the hardware device. 323 /// 324 /// @param cam A pointer to the GnashWebcam structure you want to use as input. 325 /// @param video_format A pointer to a WebcamVidFormat class that has had all 326 /// variables initialize to their respective values. 327 /// 328 /// @return Nothing. All pertantent information is stored in a GnashWebcam class. 329 void addSupportedFormat(GnashWebcam *cam, WebcamVidFormat *video_format, 330 GstStructure *format_structure); 331 332 /// \brief This function is called by addSupportedFormat. Since we have 333 /// found a format that will work with the input device, we now 334 /// need to figure out what framerate the camera can capture at 335 /// that corresponds with the format being analyzed. 336 /// 337 /// @param video_format A pointer to a WebcamVidFormat class that has 338 /// had all variables initialized to their respective values. 339 /// @param structure A pointer to a structure initialized with the 340 /// capabilities of the selected input device. 341 /// 342 /// @return Nothing. All pertintent information is stored in a 343 /// WebcamVidFormat class. 344 void getSupportedFramerates(WebcamVidFormat *video_format, 345 GstStructure *structure); 346 347 /// \brief This function checks to see if the current format selected for the 348 /// webcam supports the framerate passed in as the second argument 349 /// @param webcam A pointer to the selected GnashWebcamPrivate structure to 350 /// check for the supported framerate value 351 /// @param fps An integer value to check for support 352 /// @return True if the framerate is supported, false otherwise 353 gboolean checkForSupportedFramerate (GnashWebcamPrivate *webcam, int fps); 354 355 /// \brief This function runs through the list of framerates determined by 356 /// getSupportedFramerates() and finds the highest supported framerate 357 /// less than 30fps. 358 /// 359 /// @param format A pointer to the chosen format structure. 360 /// 361 /// @return Nothing. All pertantent information is stored in the structure 362 /// passed in (a WebcamVidFormat class). 363 void findHighestFramerate(WebcamVidFormat *format); 364 365 /// \brief Function creates the source bin. For more information on pipeline 366 /// implementation and this function in general see the definition of 367 /// the _webcamSourceBin variable in the GnashWebcamPrivate structure 368 /// documentation. 369 /// 370 /// @param webcam A pointer to the GnashWebcamPrivate webcam structure 371 /// created previously in a call to transferToPrivate() 372 /// 373 /// @return True if everything went correctly (making elements, dropping 374 /// into bins and linking elements), false otherwise. 375 gboolean webcamCreateSourceBin(); 376 377 /// \brief Function is called when changes have been made to certain variables 378 /// that effect the video source's capabilities (specifically resolution 379 /// and fps values) 380 /// @return True if the changes to the source's capabilities happened succesfully 381 /// false otherwise. 382 gboolean webcamChangeSourceBin(); 383 384 /// \brief Function creates the main bin. For more information on pipeline 385 /// implementation and this function in general see the definition of 386 /// the _webcamMainBin variable in the GnashWebcamPrivate structure 387 /// documentation. 388 /// 389 /// @param webcam A pointer to the GnashWebcamPrivate webcam structure 390 /// created previously in a call to transferToPrivate() 391 /// 392 /// @return True if everything went correctly (making elements, dropping 393 /// into bins and linking elements), false otherwise. 394 gboolean webcamCreateMainBin(); 395 396 /// \brief Function creates the display bin. For more information on pipeline 397 /// implementation and this function in general see the definition of 398 /// the _videoDisplayBin variable in the GnashWebcamPrivate structure 399 /// documentation. 400 /// 401 /// @param webcam A pointer to the GnashWebcamPrivate webcam structure 402 /// created previously in a call to transferToPrivate() 403 /// 404 /// @return True if everything went correctly (making elements, dropping 405 /// into bins and linking elements), false otherwise. 406 gboolean webcamCreateDisplayBin(); 407 408 409 410 /// \brief Accessor to return a pointer to the global GnashWebcamPrivate 411 /// variable 412 /// @return A pointer to the global GnashWebcamPrivate pointer getGlobalWebcam()413 GnashWebcamPrivate* getGlobalWebcam() {return _globalWebcam;} 414 415 /// \brief This function interacts with the hardware on the machine 416 /// to enumerate information about devices connected. Currently 417 /// this function only looks for videotestsources (implemented 418 /// in Gstreamer), video4linux and video4linux2 sources. 419 // 420 /// @return Nothing. All pertintent information is stored to the passed 421 /// vector. Note: elements can also be null. 422 static void findVidDevs(std::vector<GnashWebcam*>& cams); 423 424 /// \var VideoInputGst::_vidVect 425 /// \brief A vector containing pointers to GnashWebcam classes. 426 std::vector<GnashWebcam*> _vidVect; 427 428 /// \var VideoInputGst::_devSelection 429 /// \brief An integer value representing the original GnashWebcam data struct 430 /// _vidVect 431 int _devSelection; 432 433 /// \var VideoInputGst::_globalWebcam 434 /// \brief Convienient pointer to the selected device's GnashWebcamPrivate 435 /// class structure. 436 GnashWebcamPrivate *_globalWebcam; 437 438 /// TODO: see which of these need to be retrieved from the camera, 439 /// which of them should be stored like this, and which should 440 /// be stored in the Camera_as relay object. 441 442 /// The currently detected activity level. This should be queried from 443 /// the camera. 444 double _activityLevel; 445 446 /// The available bandwidth. This probably shouldn't be dealt with by 447 /// the camera class. But maybe it should. 448 size_t _bandwidth; 449 450 /// The current FPS of the camera. This should be queried from the 451 /// camera. 452 double _currentFPS; 453 454 /// The maximum FPS allowed. 455 double _fps; 456 457 /// The height of the frame. This should probably be retrieved from 458 /// the camera 459 size_t _height; 460 461 /// The width of the frame. This should probably be retrieved from 462 /// the camera 463 size_t _width; 464 465 /// The index of this Webcam 466 size_t _index; 467 468 /// The motion level required to trigger a notification to the core 469 int _motionLevel; 470 471 /// The length of inactivity required to trigger a notification to the core. 472 int _motionTimeout; 473 474 /// Whether access to the camera is allowed. This depends on the rcfile 475 /// setting 476 bool _muted; 477 478 /// The name of this camera. 479 std::string _name; 480 481 /// The current quality setting. 482 int _quality; 483 484 }; 485 486 487 488 489 } //gst namespace 490 } // gnash.media namespace 491 } // gnash namespace 492 493 #endif 494