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