]> git.mxchange.org Git - flightgear.git/blob - utils/fgviewer/MEncoderCaptureOperation.hxx
fgviewer: Import hla based viewer application.
[flightgear.git] / utils / fgviewer / MEncoderCaptureOperation.hxx
1 // MEncoderCaptureOperation.hxx -- capture video stream into mencoder
2 //
3 // Copyright (C) 2009 - 2012  Mathias Froehlich
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License as
7 // published by the Free Software Foundation; either version 2 of the
8 // License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18
19 #ifndef MEncoderCaptureOperation_HXX
20 #define MEncoderCaptureOperation_HXX
21
22 #include <cstdio>
23 #include <sstream>
24 #include <string>
25
26 #include <osgViewer/ViewerEventHandlers>
27
28 /// Class to capture into a pipe driven mencoder.
29 /// To integrate this into a viewer:
30 ///  MEncoderCaptureOperation* mencoderCaptureOperation = new MEncoderCaptureOperation("/tmp/fgviewer.avi", 60);
31 ///  osgViewer::ScreenCaptureHandler* c = new osgViewer::ScreenCaptureHandler(mencoderCaptureOperation, -1);
32 ///  viewer.addEventHandler(c);
33 ///  c->startCapture();
34
35 namespace fgviewer {
36
37 class MEncoderCaptureOperation : public osgViewer::ScreenCaptureHandler::CaptureOperation {
38 public:
39     MEncoderCaptureOperation(const std::string& fileName = "video.avi", unsigned fps = 30) :
40         _fps(fps),
41         _fileName(fileName),
42         _options("-ovc lavc"),
43         _file(0),
44         _width(-1),
45         _height(-1)
46     { }
47     virtual ~MEncoderCaptureOperation()
48     { _close(); }
49
50     const std::string& getFileName() const
51     { return _fileName; }
52     void setFileName(const std::string& fileName)
53     { _fileName = fileName; }
54
55     unsigned getFramesPerSecond() const
56     { return _fps; }
57     void setFramesPerSecond(unsigned fps)
58     { _fps = fps; }
59
60     const std::string& getOptions() const
61     { return _options; }
62     void setOptions(const std::string& options)
63     { _options = options; }
64
65     virtual void operator()(const osg::Image& image, const unsigned int)
66     {
67         // Delay any action until we have a valid image
68         if (!image.valid())
69             return;
70
71         // Ensure an open file
72         if (!_file) {
73             // If the video was already opened and we got any error,
74             // do not reopen with the same name.
75             if (0 < _width)
76                 return;
77             _width = image.s();
78             _height = image.t();
79             if (!_open())
80                 return;
81         }
82         // Ensure we did not change dimensions
83         if (image.s() != _width)
84             return;
85         if (image.t() != _height)
86             return;
87
88         // Write upside down flipped image
89         for (int row = _height - 1; 0 <= row; --row) {
90             size_t ret = fwrite(image.data(0, row), 1, image.getRowSizeInBytes(), _file);
91             if (ret != image.getRowSizeInBytes())
92                 return;
93         }
94     }
95
96 private:
97     bool _open()
98     {
99         if (_file)
100             return false;
101         /// FIXME improve: adapt format to the format we get from the image
102         std::stringstream ss;
103         ss << "mencoder - -demuxer rawvideo -rawvideo fps="
104            << _fps << ":w=" << _width << ":h=" << _height
105            << ":format=rgb24 -o " << _fileName << " " << _options;
106 #ifdef _WIN32
107         _file = popen(ss.str().c_str(), "wb");
108 #else
109         _file = popen(ss.str().c_str(), "w");
110 #endif
111         return _file != 0;
112     }
113     void _close()
114     {
115         if (!_file)
116             return;
117         pclose(_file);
118         _file = 0;
119     }
120
121     /// Externally given:
122     unsigned _fps;
123     std::string _fileName;
124     std::string _options;
125
126     /// Internal determined
127     FILE* _file;
128     int _width;
129     int _height;
130 };
131
132 }
133
134 #endif