root/OpenSceneGraph/trunk/src/osgPlugins/ffmpeg/FFmpegImageStream.cpp @ 9861

Revision 9861, 5.5 kB (checked in by robert, 5 years ago)

Removed boost reference and cleaned up debug output

RevLine 
[9816]1
2#include "FFmpegImageStream.hpp"
[9847]3#include "FFmpegAudioStream.hpp"
[9816]4
5#include <OpenThreads/ScopedLock>
6#include <osg/Notify>
7
8#include <memory>
9
10
11
12namespace osgFFmpeg {
13
14
15
16FFmpegImageStream::FFmpegImageStream() :
17    m_decoder(0),
18    m_commands(0),
19    m_frame_published_flag(false)
20{
21    setOrigin(osg::Image::BOTTOM_LEFT);
22
23    std::auto_ptr<FFmpegDecoder> decoder(new FFmpegDecoder);
24    std::auto_ptr<CommandQueue> commands(new CommandQueue);
25
26    m_decoder = decoder.release();
27    m_commands = commands.release();
28}
29
30
31
32FFmpegImageStream::FFmpegImageStream(const FFmpegImageStream & image, const osg::CopyOp & copyop) :
33    osg::ImageStream(image, copyop)
34{
35    // TODO: probably incorrect or incomplete
36}
37
38
39
40FFmpegImageStream::~FFmpegImageStream()
41{
[9861]42    osg::notify(osg::NOTICE)<<"Destructing FFMpegImageStream..."<<std::endl;
43
[9816]44    quit(true);
45
[9861]46    // destroy the decoder and associated threads
47    m_decoder = 0;
48
49
[9816]50    delete m_commands;
[9861]51
52    osg::notify(osg::NOTICE)<<"Destructed FFMpegImageStream."<<std::endl;
[9816]53}
54
55
56
57bool FFmpegImageStream::open(const std::string & filename)
58{
59    setFileName(filename);
60
61    if (! m_decoder->open(filename))
62        return false;
63
64    setImage(
65        m_decoder->video_decoder().width(), m_decoder->video_decoder().height(), 1, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE,
66        const_cast<unsigned char *>(m_decoder->video_decoder().image()), NO_DELETE
67    );
[9860]68   
69    setOrigin(osg::Image::TOP_LEFT);
[9816]70
71    m_decoder->video_decoder().setUserData(this);
72    m_decoder->video_decoder().setPublishCallback(publishNewFrame);
[9847]73   
74    if (m_decoder->audio_decoder().validContext())
75    {
76        osg::notify(osg::NOTICE)<<"Attaching FFmpegAudioStream"<<std::endl;
77   
78        getAudioStreams().push_back(new FFmpegAudioStream(m_decoder.get()));
79    }
[9816]80
81    _status = PAUSED;
82    applyLoopingMode();
83
84    start(); // start thread
85
86    return true;
87}
88
89
90
91void FFmpegImageStream::play()
92{
93    m_commands->push(CMD_PLAY);
94
95#if 0
96    // Wait for at least one frame to be published before returning the call
97    OpenThreads::ScopedLock<Mutex> lock(m_mutex);
98
99    while (duration() > 0 && ! m_frame_published_flag)
100        m_frame_published_cond.wait(&m_mutex);
101
102#endif
103}
104
105
106
107void FFmpegImageStream::pause()
108{
109    m_commands->push(CMD_PAUSE);
110}
111
112
113
114void FFmpegImageStream::rewind()
115{
116    m_commands->push(CMD_REWIND);
117}
118
119
120
121void FFmpegImageStream::quit(bool waitForThreadToExit)
122{
123    // Stop the packet producer thread
124    if (isRunning())
125    {
126        m_commands->push(CMD_STOP);
127
128        if (waitForThreadToExit)
129            join();
130    }
131
132    // Close the decoder (i.e. flush the decoder packet queues)
133    m_decoder->close();
134}
135
136
137double FFmpegImageStream::duration() const
138{
139    return m_decoder->duration();
140}
141
142
143
144bool FFmpegImageStream::videoAlphaChannel() const 
145{
146    return m_decoder->video_decoder().alphaChannel();
147}
148
149
150
151double FFmpegImageStream::videoAspectRatio() const
152{
153    return m_decoder->video_decoder().aspectRatio();
154}
155
156
157
158double FFmpegImageStream::videoFrameRate() const
159{
160    return m_decoder->video_decoder().frameRate();
161}
162
163
164void FFmpegImageStream::run()
165{
166    try
167    {
168        bool done = false;
169
170        while (! done)
171        {
172            if (_status == PLAYING)
173            {
174                bool no_cmd;
175                const Command cmd = m_commands->timedPop(no_cmd, 1);
176
177                if (no_cmd)
178                {
179                    m_decoder->readNextPacket();
180                }
181                else
182                    done = ! handleCommand(cmd);
183            }
184            else
185            {
186                done = ! handleCommand(m_commands->pop());
187            }
188        }
189    }
190
191    catch (const std::exception & error)
192    {
193        osg::notify(osg::WARN) << "FFmpegImageStream::run : " << error.what() << std::endl;
194    }
195
196    catch (...)
197    {
198        osg::notify(osg::WARN) << "FFmpegImageStream::run : unhandled exception" << std::endl;
199    }
200}
201
202
203
204void FFmpegImageStream::applyLoopingMode()
205{
206    m_decoder->loop(getLoopingMode() == LOOPING);
207}
208
209
210
211bool FFmpegImageStream::handleCommand(const Command cmd)
212{
213    switch (cmd)
214    {
215    case CMD_PLAY:
216        cmdPlay();
217        return true;
218
219    case CMD_PAUSE:
220        cmdPause();
221        return true;
222
223    case CMD_REWIND:
224        cmdRewind();
225        return true;
226
227    case CMD_STOP:
228        return false;
229
230    default:
231        assert(false);
232        return false;
233    }
234}
235
236
237
238void FFmpegImageStream::cmdPlay()
239{
240    if (_status == PAUSED)
241    {
242        if (! m_decoder->audio_decoder().isRunning())
243            m_decoder->audio_decoder().start();
244
245        if (! m_decoder->video_decoder().isRunning())
246            m_decoder->video_decoder().start();
247    }
248
249    _status = PLAYING;
250}
251
252
253
254void FFmpegImageStream::cmdPause()
255{
256    if (_status == PLAYING)
257    {
258
259    }
260
261    _status = PAUSED;
262}
263
264
265
266void FFmpegImageStream::cmdRewind()
267{
268    m_decoder->rewind();
269}
270
271
272
273void FFmpegImageStream::publishNewFrame(const FFmpegDecoderVideo &, void * user_data)
274{
275    FFmpegImageStream * const this_ = reinterpret_cast<FFmpegImageStream*>(user_data);
276
[9860]277#if 1
278    this_->setImage(
279        this_->m_decoder->video_decoder().width(), this_->m_decoder->video_decoder().height(), 1, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE,
280        const_cast<unsigned char *>(this_->m_decoder->video_decoder().image()), NO_DELETE
281    );
282#else
[9816]283    /** \bug If viewer.realize() hasn't been already called, this doesn't work? */
284    this_->dirty();
[9860]285#endif
[9816]286
287    OpenThreads::ScopedLock<Mutex> lock(this_->m_mutex);
288
289    if (! this_->m_frame_published_flag)
290    {
291        this_->m_frame_published_flag = true;
292        this_->m_frame_published_cond.signal();
293    }
294}
295
296
297
298} // namespace osgFFmpeg
Note: See TracBrowser for help on using the browser.