OpenWalnut  1.5.0dev
WGEScreenCapture.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <osg/BufferObject>
26 
27 #include "animation/WGEAnimationFrameTimer.h"
28 
29 #include "WGEScreenCapture.h"
30 
32  m_timer( new WGEAnimationFrameTimer() )
33 {
34  // initialize
36  w->get().m_frames = 0;
37  w->get().m_framesLeft = 0;
38 }
39 
41 {
42  // cleanup
43 }
44 
46 {
47  return m_timer;
48 }
49 
51 {
52  record();
53 }
54 
56 {
57  record( 0 );
58 }
59 
61 {
62  record( 1 );
63 }
64 
65 void WGEScreenCapture::record( size_t frames )
66 {
68  w->get().m_framesLeft = frames;
69 }
70 
72 {
74  return r->get().m_framesLeft;
75 }
76 
77 void WGEScreenCapture::operator()( osg::RenderInfo& renderInfo ) const // NOLINT - osg wants this to be a non-const reference
78 {
79  SharedRecordingInformation::WriteTicket w = m_recordingInformation.getWriteTicket();
80  RecordingInformation& frameCounter = w->get();
81 
82  // is there something to record?
83  if( !frameCounter.m_framesLeft )
84  {
85  return;
86  }
87 
88  // we need the graphics context here.
89  osg::GraphicsContext* gc = renderInfo.getState()->getGraphicsContext();
90 
91  // get size and color mode
92  size_t width = 0;
93  size_t height = 0;
94  GLenum pixelFormat = GL_RGB;
95  if( gc->getTraits() )
96  {
97  width = gc->getTraits()->width;
98  height = gc->getTraits()->height;
99  pixelFormat = gc->getTraits()->alpha ? GL_RGBA : GL_RGB;
100  }
101 
102  // count frames
103  frameCounter.m_frames++;
104  frameCounter.m_framesLeft--;
105 
106  // read back buffer
107 #ifndef GL_ES_VERSION_2_0
108  glReadBuffer( GL_BACK );
109 #endif
110 
111  // The following code uses PBO to grab the framebuffer. This sometimes causes errors. I am not sure why. glReadPixels
112  // osg::ref_ptr< osg::Image > imagePBO = new osg::Image();
113  // osg::BufferObject::Extensions* ext = osg::BufferObject::getExtensions( gc->getState()->getContextID(), true );
114  // imagePBO->allocateImage( width, height, 1, pixelFormat, GL_UNSIGNED_BYTE );
115  // if( m_pbo == 0 )
116  // {
117  // std::cout << "CREATE" << std::endl;
118  // ext->glGenBuffers( 1, &m_pbo );
119  // ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, m_pbo );
120  // ext->glBufferData( GL_PIXEL_PACK_BUFFER_ARB, imagePBO->getTotalSizeInBytes(), 0, GL_STREAM_READ );
121  // }
122  // else
123  // {
124  // std::cout << "BIND" << std::endl;
125  // ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, m_pbo );
126  // }
127  // std::cout << "READ" << std::endl;
128  // glReadPixels( 0, 0, width, height, pixelFormat, GL_UNSIGNED_BYTE, 0 );
129  // std::cout << "MAP" << std::endl;
130  // GLubyte* src = static_cast< GLubyte* >( ext->glMapBuffer( GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB ) );
131  // if(src)
132  // {
133  // std::cout << "COPY" << std::endl;
134  // memcpy( imagePBO->data(), src, imagePBO->getTotalSizeInBytes() );
135  // ext->glUnmapBuffer( GL_PIXEL_PACK_BUFFER_ARB );
136  //}
137  //
138  // std::cout << "RESTORE" << std::endl;
139  // ext->glBindBuffer( GL_PIXEL_PACK_BUFFER_ARB, 0 );
140 
141  // create image and read pixels into it
142  osg::ref_ptr< osg::Image > image = new osg::Image();
143  image->readPixels( 0, 0, width, height, pixelFormat, GL_UNSIGNED_BYTE );
144 
145  // another frame.
146  m_timer->tick();
147 
148  // someone wants this image
149  handleImage( frameCounter.m_framesLeft, frameCounter.m_frames, image );
150 }
151 
153 {
155 }
156 
158 {
160 }
161 
163 {
165  w->get().m_frames = 0;
166  m_timer->reset();
167 }
168 
169 void WGEScreenCapture::handleImage( size_t framesLeft, size_t totalFrames, osg::ref_ptr< osg::Image > image ) const
170 {
171  m_signalHandleImage( framesLeft, totalFrames, image );
172 }
173 
174 boost::signals2::connection WGEScreenCapture::subscribeSignal( HandleImageCallbackType callback )
175 {
176  return m_signalHandleImage.connect( callback );
177 }
178 
std::shared_ptr< const WCondition > ConstSPtr
Const shared pointer type for WCondition.
Definition: WCondition.h:53
Frame-based animation timing.
std::shared_ptr< const WGEAnimationFrameTimer > ConstSPtr
Convenience typedef for a const shared_ptr.
void recordStop()
Stops recording.
void record(size_t frames=std::numeric_limits< size_t >::max())
Starts recording.
virtual ~WGEScreenCapture()
Destructor.
SharedRecordingInformation m_recordingInformation
Counts the frames to take.
boost::function< void(size_t, size_t, osg::ref_ptr< osg::Image >) > HandleImageCallbackType
This callback signature is needed to subscribe to the handleImage signal.
WGEAnimationFrameTimer::ConstSPtr getFrameTimer() const
Returns a timer getting ticked on each recorded frame.
WCondition::ConstSPtr getRecordCondition() const
The condition returned here is actually the change condition of the frame counter.
void recordStart()
Starts recording.
SharedRecordingInformation::ReadTicket getRecordingInformation() const
Returns the current recording information.
virtual void operator()(osg::RenderInfo &renderInfo) const
The draw callback operator.
WGEAnimationFrameTimer::SPtr m_timer
The frame timer.
void screenshot()
Makes a screenshot with the next frame.
WGEScreenCapture()
Creates a screen capture callback.
HandleImageSignalType m_signalHandleImage
The signal emitted on every new grabbed image.
virtual void handleImage(size_t framesLeft, size_t totalFrames, osg::ref_ptr< osg::Image > image) const
The function handles new images.
void resetFrameCounter()
Resets the frame-counter to 0.
boost::signals2::connection subscribeSignal(HandleImageCallbackType callback)
Subscribes a specified function to the new-image-signal.
bool isRecording()
Checks if there are frames left for recording.
std::shared_ptr< WSharedObjectTicketRead< RecordingInformation > > ReadTicket
Type for read tickets.
Definition: WSharedObject.h:65
ReadTicket getReadTicket() const
Returns a ticket to get read access to the contained data.
std::shared_ptr< WSharedObjectTicketWrite< RecordingInformation > > WriteTicket
Type for write tickets.
Definition: WSharedObject.h:70
WriteTicket getWriteTicket(bool suppressNotify=false) const
Returns a ticket to get write access to the contained data.
std::shared_ptr< WCondition > getChangeCondition() const
This condition fires whenever the encapsulated object changed.
Keeps track of several frame-counts.
size_t m_framesLeft
the frames to take until stop.
size_t m_frames
current number of frames.