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

Revision 9912, 5.8 kB (checked in by robert, 5 years ago)

changed debug info to output to INFO instaed of NOTICE.

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{
[9910]21    setOrigin(osg::Image::TOP_LEFT);
[9816]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{
[9912]42    osg::notify(osg::INFO)<<"Destructing FFmpegImageStream..."<<std::endl;
[9861]43
[9816]44    quit(true);
[9869]45   
[9912]46    osg::notify(osg::INFO)<<"Have done quit"<<std::endl;
[9816]47
[9869]48    // release athe audio streams to make sure that the decoder doesn't retain any external
49    // refences.
50    getAudioStreams().clear();
51
[9861]52    // destroy the decoder and associated threads
53    m_decoder = 0;
54
55
[9816]56    delete m_commands;
[9861]57
[9912]58    osg::notify(osg::INFO)<<"Destructed FFMpegImageStream."<<std::endl;
[9816]59}
60
61
62
63bool FFmpegImageStream::open(const std::string & filename)
64{
65    setFileName(filename);
66
67    if (! m_decoder->open(filename))
68        return false;
69
70    setImage(
71        m_decoder->video_decoder().width(), m_decoder->video_decoder().height(), 1, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE,
72        const_cast<unsigned char *>(m_decoder->video_decoder().image()), NO_DELETE
73    );
74
[9910]75    setPixelAspectRatio(m_decoder->video_decoder().pixelAspectRatio());
76   
[9816]77    m_decoder->video_decoder().setUserData(this);
78    m_decoder->video_decoder().setPublishCallback(publishNewFrame);
[9847]79   
80    if (m_decoder->audio_decoder().validContext())
81    {
82        osg::notify(osg::NOTICE)<<"Attaching FFmpegAudioStream"<<std::endl;
83   
84        getAudioStreams().push_back(new FFmpegAudioStream(m_decoder.get()));
85    }
[9816]86
87    _status = PAUSED;
88    applyLoopingMode();
89
90    start(); // start thread
91
92    return true;
93}
94
95
96
97void FFmpegImageStream::play()
98{
99    m_commands->push(CMD_PLAY);
100
101#if 0
102    // Wait for at least one frame to be published before returning the call
103    OpenThreads::ScopedLock<Mutex> lock(m_mutex);
104
105    while (duration() > 0 && ! m_frame_published_flag)
106        m_frame_published_cond.wait(&m_mutex);
107
108#endif
109}
110
111
112
113void FFmpegImageStream::pause()
114{
115    m_commands->push(CMD_PAUSE);
116}
117
118
119
120void FFmpegImageStream::rewind()
121{
122    m_commands->push(CMD_REWIND);
123}
124
125
126
127void FFmpegImageStream::quit(bool waitForThreadToExit)
128{
129    // Stop the packet producer thread
130    if (isRunning())
131    {
132        m_commands->push(CMD_STOP);
133
134        if (waitForThreadToExit)
135            join();
136    }
137
138    // Close the decoder (i.e. flush the decoder packet queues)
[9869]139    m_decoder->close(waitForThreadToExit);
[9816]140}
141
142
[9910]143double FFmpegImageStream::getLength() const
[9816]144{
145    return m_decoder->duration();
146}
147
148
149
[9910]150double FFmpegImageStream::getFrameRate() const
[9816]151{
[9910]152    return m_decoder->video_decoder().frameRate();
[9816]153}
154
155
156
[9910]157bool FFmpegImageStream::isImageTranslucent() const 
[9816]158{
[9910]159    return m_decoder->video_decoder().alphaChannel();
[9816]160}
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    }
[9869]200   
201    osg::notify(osg::NOTICE)<<"Finished FFmpegImageStream::run()"<<std::endl;
[9816]202}
203
204
205
206void FFmpegImageStream::applyLoopingMode()
207{
208    m_decoder->loop(getLoopingMode() == LOOPING);
209}
210
211
212
213bool FFmpegImageStream::handleCommand(const Command cmd)
214{
215    switch (cmd)
216    {
217    case CMD_PLAY:
218        cmdPlay();
219        return true;
220
221    case CMD_PAUSE:
222        cmdPause();
223        return true;
224
225    case CMD_REWIND:
226        cmdRewind();
227        return true;
228
229    case CMD_STOP:
230        return false;
231
232    default:
233        assert(false);
234        return false;
235    }
236}
237
238
239
240void FFmpegImageStream::cmdPlay()
241{
242    if (_status == PAUSED)
243    {
244        if (! m_decoder->audio_decoder().isRunning())
245            m_decoder->audio_decoder().start();
246
247        if (! m_decoder->video_decoder().isRunning())
248            m_decoder->video_decoder().start();
249    }
250
251    _status = PLAYING;
252}
253
254
255
256void FFmpegImageStream::cmdPause()
257{
258    if (_status == PLAYING)
259    {
260
261    }
262
263    _status = PAUSED;
264}
265
266
267
268void FFmpegImageStream::cmdRewind()
269{
270    m_decoder->rewind();
271}
272
273
274
275void FFmpegImageStream::publishNewFrame(const FFmpegDecoderVideo &, void * user_data)
276{
277    FFmpegImageStream * const this_ = reinterpret_cast<FFmpegImageStream*>(user_data);
278
[9860]279#if 1
280    this_->setImage(
281        this_->m_decoder->video_decoder().width(), this_->m_decoder->video_decoder().height(), 1, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE,
282        const_cast<unsigned char *>(this_->m_decoder->video_decoder().image()), NO_DELETE
283    );
284#else
[9816]285    /** \bug If viewer.realize() hasn't been already called, this doesn't work? */
286    this_->dirty();
[9860]287#endif
[9816]288
289    OpenThreads::ScopedLock<Mutex> lock(this_->m_mutex);
290
291    if (! this_->m_frame_published_flag)
292    {
293        this_->m_frame_published_flag = true;
294        this_->m_frame_published_cond.signal();
295    }
296}
297
298
299
300} // namespace osgFFmpeg
Note: See TracBrowser for help on using the browser.