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

Revision 13041, 6.9 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
1
2#include "FFmpegImageStream.hpp"
3#include "FFmpegAudioStream.hpp"
4#include "FFmpegParameters.hpp"
5
6#include <OpenThreads/ScopedLock>
7#include <osg/Notify>
8
9#include <memory>
10
11
12
13namespace osgFFmpeg {
14
15
16
17FFmpegImageStream::FFmpegImageStream() :
18    m_decoder(0),
19    m_commands(0),
20    m_frame_published_flag(false)
21{
22    setOrigin(osg::Image::TOP_LEFT);
23
24    std::auto_ptr<FFmpegDecoder> decoder(new FFmpegDecoder);
25    std::auto_ptr<CommandQueue> commands(new CommandQueue);
26
27    m_decoder = decoder.release();
28    m_commands = commands.release();
29}
30
31
32
33FFmpegImageStream::FFmpegImageStream(const FFmpegImageStream & image, const osg::CopyOp & copyop) :
34    osg::ImageStream(image, copyop)
35{
36    // TODO: probably incorrect or incomplete
37}
38
39
40
41FFmpegImageStream::~FFmpegImageStream()
42{
43    OSG_INFO<<"Destructing FFmpegImageStream..."<<std::endl;
44
45    quit(true);
46
47    OSG_INFO<<"Have done quit"<<std::endl;
48
49    // release athe audio streams to make sure that the decoder doesn't retain any external
50    // refences.
51    getAudioStreams().clear();
52
53    // destroy the decoder and associated threads
54    m_decoder = 0;
55
56
57    delete m_commands;
58
59    OSG_INFO<<"Destructed FFMpegImageStream."<<std::endl;
60}
61
62
63
64bool FFmpegImageStream::open(const std::string & filename, FFmpegParameters* parameters)
65{
66    setFileName(filename);
67
68    if (! m_decoder->open(filename, parameters))
69        return false;
70
71    setImage(
72        m_decoder->video_decoder().width(), m_decoder->video_decoder().height(), 1, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE,
73        const_cast<unsigned char *>(m_decoder->video_decoder().image()), NO_DELETE
74    );
75
76
77    setPixelAspectRatio(m_decoder->video_decoder().pixelAspectRatio());
78
79    OSG_NOTICE<<"ffmpeg::open("<<filename<<") size("<<s()<<", "<<t()<<") aspect ratio "<<m_decoder->video_decoder().pixelAspectRatio()<<std::endl;
80
81#if 1
82    // swscale is reported errors and then crashing when rescaling video of size less than 10 by 10.
83    if (s()<=10 || t()<=10) return false;
84#endif
85
86    m_decoder->video_decoder().setUserData(this);
87    m_decoder->video_decoder().setPublishCallback(publishNewFrame);
88
89    if (m_decoder->audio_decoder().validContext())
90    {
91        OSG_NOTICE<<"Attaching FFmpegAudioStream"<<std::endl;
92
93        getAudioStreams().push_back(new FFmpegAudioStream(m_decoder.get()));
94    }
95
96    _status = PAUSED;
97    applyLoopingMode();
98
99    start(); // start thread
100
101    return true;
102}
103
104
105
106void FFmpegImageStream::play()
107{
108    m_commands->push(CMD_PLAY);
109
110#if 0
111    // Wait for at least one frame to be published before returning the call
112    OpenThreads::ScopedLock<Mutex> lock(m_mutex);
113
114    while (duration() > 0 && ! m_frame_published_flag)
115        m_frame_published_cond.wait(&m_mutex);
116
117#endif
118}
119
120
121
122void FFmpegImageStream::pause()
123{
124    m_commands->push(CMD_PAUSE);
125}
126
127
128
129void FFmpegImageStream::rewind()
130{
131    m_commands->push(CMD_REWIND);
132}
133
134void FFmpegImageStream::seek(double time) {
135    m_seek_time = time;
136    m_commands->push(CMD_SEEK);
137}
138
139
140
141void FFmpegImageStream::quit(bool waitForThreadToExit)
142{
143    // Stop the packet producer thread
144    if (isRunning())
145    {
146        m_commands->push(CMD_STOP);
147
148        if (waitForThreadToExit)
149            join();
150    }
151
152    // Close the decoder (i.e. flush the decoder packet queues)
153    m_decoder->close(waitForThreadToExit);
154}
155
156void FFmpegImageStream::setVolume(float volume)
157{
158    m_decoder->audio_decoder().setVolume(volume);
159}
160
161float FFmpegImageStream::getVolume() const
162{
163    return m_decoder->audio_decoder().getVolume();
164}
165
166double FFmpegImageStream::getCreationTime() const
167{
168    return m_decoder->creation_time();
169}
170
171double FFmpegImageStream::getLength() const
172{
173    return m_decoder->duration();
174}
175
176
177double FFmpegImageStream::getReferenceTime () const
178{
179    return m_decoder->reference();
180}
181
182double FFmpegImageStream::getCurrentTime() const
183{
184    return m_decoder->reference();
185}
186
187
188
189double FFmpegImageStream::getFrameRate() const
190{
191    return m_decoder->video_decoder().frameRate();
192}
193
194
195
196bool FFmpegImageStream::isImageTranslucent() const
197{
198    return m_decoder->video_decoder().alphaChannel();
199}
200
201
202
203void FFmpegImageStream::run()
204{
205    try
206    {
207        bool done = false;
208
209        while (! done)
210        {
211            if (_status == PLAYING)
212            {
213                bool no_cmd;
214                const Command cmd = m_commands->timedPop(no_cmd, 1);
215
216                if (no_cmd)
217                {
218                    m_decoder->readNextPacket();
219                }
220                else
221                    done = ! handleCommand(cmd);
222            }
223            else
224            {
225                done = ! handleCommand(m_commands->pop());
226            }
227        }
228    }
229
230    catch (const std::exception & error)
231    {
232        OSG_WARN << "FFmpegImageStream::run : " << error.what() << std::endl;
233    }
234
235    catch (...)
236    {
237        OSG_WARN << "FFmpegImageStream::run : unhandled exception" << std::endl;
238    }
239
240    OSG_NOTICE<<"Finished FFmpegImageStream::run()"<<std::endl;
241}
242
243
244
245void FFmpegImageStream::applyLoopingMode()
246{
247    m_decoder->loop(getLoopingMode() == LOOPING);
248}
249
250
251
252bool FFmpegImageStream::handleCommand(const Command cmd)
253{
254    switch (cmd)
255    {
256    case CMD_PLAY:
257        cmdPlay();
258        return true;
259
260    case CMD_PAUSE:
261        cmdPause();
262        return true;
263
264    case CMD_REWIND:
265        cmdRewind();
266        return true;
267
268    case CMD_SEEK:
269        cmdSeek(m_seek_time);
270        return true;
271
272    case CMD_STOP:
273        return false;
274
275    default:
276        assert(false);
277        return false;
278    }
279}
280
281
282
283void FFmpegImageStream::cmdPlay()
284{
285    if (_status == PAUSED)
286    {
287        if (! m_decoder->audio_decoder().isRunning())
288            m_decoder->audio_decoder().start();
289
290        if (! m_decoder->video_decoder().isRunning())
291            m_decoder->video_decoder().start();
292
293        m_decoder->video_decoder().pause(false);
294        m_decoder->audio_decoder().pause(false);
295    }
296
297    _status = PLAYING;
298}
299
300
301
302void FFmpegImageStream::cmdPause()
303{
304    if (_status == PLAYING)
305    {
306        m_decoder->video_decoder().pause(true);
307        m_decoder->audio_decoder().pause(true);
308    }
309
310    _status = PAUSED;
311}
312
313
314
315void FFmpegImageStream::cmdRewind()
316{
317    m_decoder->rewind();
318}
319
320void FFmpegImageStream::cmdSeek(double time)
321{
322    m_decoder->seek(time);
323}
324
325
326void FFmpegImageStream::publishNewFrame(const FFmpegDecoderVideo &, void * user_data)
327{
328    FFmpegImageStream * const this_ = reinterpret_cast<FFmpegImageStream*>(user_data);
329
330#if 1
331    this_->setImage(
332        this_->m_decoder->video_decoder().width(), this_->m_decoder->video_decoder().height(), 1, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE,
333        const_cast<unsigned char *>(this_->m_decoder->video_decoder().image()), NO_DELETE
334    );
335#else
336    /** \bug If viewer.realize() hasn't been already called, this doesn't work? */
337    this_->dirty();
338#endif
339
340    OpenThreads::ScopedLock<Mutex> lock(this_->m_mutex);
341
342    if (! this_->m_frame_published_flag)
343    {
344        this_->m_frame_published_flag = true;
345        this_->m_frame_published_cond.signal();
346    }
347}
348
349
350
351} // namespace osgFFmpeg
Note: See TracBrowser for help on using the browser.