Introduce FFmpegAudioStream implementation
This commit is contained in:
parent
e0959ea804
commit
e035decd95
@ -310,6 +310,7 @@ FIND_PACKAGE(CURL)
|
||||
FIND_PACKAGE(ITK)
|
||||
FIND_PACKAGE(LibVNCServer)
|
||||
FIND_PACKAGE(OurDCMTK)
|
||||
FIND_PACKAGE(OpenAL)
|
||||
FIND_PACKAGE(XUL)
|
||||
FIND_PACKAGE(FFmpeg)
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
#this file is automatically generated
|
||||
|
||||
# INCLUDE_DIRECTORIES( ${OPENAL_INCLUDE_DIR} )
|
||||
|
||||
SET(TARGET_SRC osgmovie.cpp )
|
||||
SET(TARGET_ADDED_LIBRARIES osgGA )
|
||||
|
||||
# SET(TARGET_EXTERNAL_LIBRARIES ${OPENAL_LIBRARY} alut)
|
||||
|
||||
#### end var setup ###
|
||||
SETUP_EXAMPLE(osgmovie)
|
||||
|
@ -320,6 +320,30 @@ osg::Geometry* myCreateTexturedQuadGeometry(const osg::Vec3& pos,float width,flo
|
||||
}
|
||||
}
|
||||
|
||||
class CustomAudioSink : public osg::AudioSink
|
||||
{
|
||||
public:
|
||||
|
||||
CustomAudioSink(osg::AudioStream* audioStream):
|
||||
_playing(false),
|
||||
_audioStream(audioStream) {}
|
||||
|
||||
virtual void startPlaying()
|
||||
{
|
||||
_playing = true;
|
||||
osg::notify(osg::NOTICE)<<"CustomAudioSink()::startPlaying()"<<std::endl;
|
||||
|
||||
osg::notify(osg::NOTICE)<<" audioFrequency()="<<_audioStream->audioFrequency()<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" audioNbChannels()="<<_audioStream->audioNbChannels()<<std::endl;
|
||||
osg::notify(osg::NOTICE)<<" audioSampleFormat()="<<_audioStream->audioSampleFormat()<<std::endl;
|
||||
|
||||
}
|
||||
virtual bool playing() const { return _playing; }
|
||||
|
||||
bool _playing;
|
||||
osg::observer_ptr<osg::AudioStream> _audioStream;
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// use an ArgumentParser object to manage the program arguments.
|
||||
@ -426,13 +450,28 @@ int main(int argc, char** argv)
|
||||
|
||||
bool xyPlane = fullscreen;
|
||||
|
||||
bool useOpenALAudio = false;
|
||||
while(arguments.read("--OpenAL")) { useOpenALAudio = true; }
|
||||
|
||||
for(int i=1;i<arguments.argc();++i)
|
||||
{
|
||||
if (arguments.isString(i))
|
||||
{
|
||||
osg::Image* image = osgDB::readImageFile(arguments[i]);
|
||||
osg::ImageStream* imagestream = dynamic_cast<osg::ImageStream*>(image);
|
||||
if (imagestream) imagestream->play();
|
||||
if (imagestream)
|
||||
{
|
||||
osg::ImageStream::AudioStreams& audioStreams = imagestream->getAudioStreams();
|
||||
if (useOpenALAudio && !audioStreams.empty())
|
||||
{
|
||||
osg::AudioStream* audioStream = audioStreams[0].get();
|
||||
osg::notify(osg::NOTICE)<<"AudioStream read ["<<audioStream->getName()<<"]"<<std::endl;
|
||||
audioStream->setAudioSink(new CustomAudioSink(audioStream));
|
||||
}
|
||||
|
||||
|
||||
imagestream->play();
|
||||
}
|
||||
|
||||
if (image)
|
||||
{
|
||||
|
@ -18,12 +18,12 @@
|
||||
|
||||
namespace osg {
|
||||
|
||||
/** Pure virtual AudioSinkInterface bass class that is used to connect the audio system with AudioStreams. */
|
||||
class OSG_EXPORT AudioSinkInterface : public osg::Object
|
||||
/** Pure virtual AudioSink bass class that is used to connect the audio system with AudioStreams. */
|
||||
class OSG_EXPORT AudioSink : public osg::Object
|
||||
{
|
||||
public:
|
||||
|
||||
AudioSinkInterface();
|
||||
AudioSink();
|
||||
|
||||
virtual void startPlaying() = 0;
|
||||
virtual bool playing() const = 0;
|
||||
@ -36,8 +36,8 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
virtual AudioSinkInterface * cloneType() const { return 0; }
|
||||
virtual AudioSinkInterface * clone(const osg::CopyOp &) const { return 0; }
|
||||
virtual AudioSink * cloneType() const { return 0; }
|
||||
virtual AudioSink * clone(const osg::CopyOp &) const { return 0; }
|
||||
|
||||
double _delay;
|
||||
};
|
||||
@ -55,7 +55,7 @@ class OSG_EXPORT AudioStream : public osg::Object
|
||||
virtual const char* libraryName() const { return "osg"; }
|
||||
virtual const char* className() const { return "AudioStream"; }
|
||||
|
||||
virtual void setAudioSink(osg::AudioSinkInterface* audio_sink) = 0;
|
||||
virtual void setAudioSink(osg::AudioSink* audio_sink) = 0;
|
||||
|
||||
virtual void consumeAudioBuffer(void * const buffer, const size_t size) = 0;
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
using namespace osg;
|
||||
|
||||
AudioSinkInterface::AudioSinkInterface() :
|
||||
AudioSink::AudioSink() :
|
||||
_delay(0.0)
|
||||
{
|
||||
}
|
||||
|
@ -200,6 +200,10 @@ IF(FFMPEG_FOUND)
|
||||
ADD_SUBDIRECTORY(ffmpeg)
|
||||
ENDIF(FFMPEG_FOUND)
|
||||
|
||||
IF(OPENAL_FOUND)
|
||||
ADD_SUBDIRECTORY(OpenAL)
|
||||
ENDIF(OPENAL_FOUND)
|
||||
|
||||
IF(QUICKTIME_FOUND)
|
||||
ADD_SUBDIRECTORY(quicktime)
|
||||
ENDIF(QUICKTIME_FOUND)
|
||||
|
@ -19,6 +19,7 @@ SET(TARGET_SRC
|
||||
FFmpegDecoder.cpp
|
||||
FFmpegDecoderVideo.cpp
|
||||
FFmpegImageStream.cpp
|
||||
FFmpegAudioStream.cpp
|
||||
ReaderWriterFFmpeg.cpp
|
||||
)
|
||||
|
||||
@ -30,6 +31,8 @@ SET(TARGET_H
|
||||
FFmpegDecoderVideo.hpp
|
||||
FFmpegHeaders.hpp
|
||||
FFmpegPacket.hpp
|
||||
FFmpegImageStream.hpp
|
||||
FFmpegAudioStream.hpp
|
||||
MessageQueue.hpp
|
||||
)
|
||||
|
||||
|
79
src/osgPlugins/ffmpeg/FFmpegAudioStream.cpp
Normal file
79
src/osgPlugins/ffmpeg/FFmpegAudioStream.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
|
||||
#include "FFmpegAudioStream.hpp"
|
||||
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include "FFmpegDecoder.hpp"
|
||||
#include "MessageQueue.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
|
||||
namespace osgFFmpeg {
|
||||
|
||||
|
||||
|
||||
FFmpegAudioStream::FFmpegAudioStream(FFmpegDecoder* decoder):
|
||||
m_decoder(decoder)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
FFmpegAudioStream::FFmpegAudioStream(const FFmpegAudioStream & audio, const osg::CopyOp & copyop) :
|
||||
osg::AudioStream(audio, copyop)
|
||||
{
|
||||
}
|
||||
|
||||
FFmpegAudioStream::~FFmpegAudioStream()
|
||||
{
|
||||
}
|
||||
|
||||
void FFmpegAudioStream::setAudioSink(osg::AudioSink* audio_sink)
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"FFmpegAudioStream::setAudioSink( "<<audio_sink<<")"<<std::endl;
|
||||
m_decoder->audio_decoder().setAudioSink(audio_sink);
|
||||
}
|
||||
|
||||
|
||||
void FFmpegAudioStream::consumeAudioBuffer(void * const buffer, const size_t size)
|
||||
{
|
||||
m_decoder->audio_decoder().fillBuffer(buffer, size);
|
||||
}
|
||||
|
||||
double FFmpegAudioStream::duration() const
|
||||
{
|
||||
return m_decoder->duration();
|
||||
}
|
||||
|
||||
|
||||
bool FFmpegAudioStream::audioStream() const
|
||||
{
|
||||
return m_decoder->audio_decoder().validContext();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int FFmpegAudioStream::audioFrequency() const
|
||||
{
|
||||
return m_decoder->audio_decoder().frequency();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int FFmpegAudioStream::audioNbChannels() const
|
||||
{
|
||||
return m_decoder->audio_decoder().nbChannels();
|
||||
}
|
||||
|
||||
|
||||
|
||||
osg::AudioStream::SampleFormat FFmpegAudioStream::audioSampleFormat() const
|
||||
{
|
||||
return m_decoder->audio_decoder().sampleFormat();
|
||||
}
|
||||
|
||||
|
||||
} // namespace osgFFmpeg
|
43
src/osgPlugins/ffmpeg/FFmpegAudioStream.hpp
Normal file
43
src/osgPlugins/ffmpeg/FFmpegAudioStream.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
|
||||
#ifndef HEADER_GUARD_OSGFFMPEG_FFMPEG_AUDIO_STREAM_H
|
||||
#define HEADER_GUARD_OSGFFMPEG_FFMPEG_AUDIO_STREAM_H
|
||||
|
||||
#include <osg/AudioStream>
|
||||
#include "FFmpegDecoder.hpp"
|
||||
|
||||
namespace osgFFmpeg
|
||||
{
|
||||
|
||||
class FFmpegAudioStream : public osg::AudioStream
|
||||
{
|
||||
public:
|
||||
|
||||
FFmpegAudioStream(FFmpegDecoder* decoder=0);
|
||||
FFmpegAudioStream(const FFmpegAudioStream & audio, const osg::CopyOp & copyop = osg::CopyOp::SHALLOW_COPY);
|
||||
|
||||
META_Object(osgFFmpeg, FFmpegAudioStream);
|
||||
|
||||
virtual void setAudioSink(osg::AudioSink* audio_sink);
|
||||
|
||||
void consumeAudioBuffer(void * const buffer, const size_t size);
|
||||
|
||||
bool audioStream() const;
|
||||
int audioFrequency() const;
|
||||
int audioNbChannels() const;
|
||||
osg::AudioStream::SampleFormat audioSampleFormat() const;
|
||||
|
||||
double duration() const;
|
||||
|
||||
private:
|
||||
|
||||
virtual ~FFmpegAudioStream();
|
||||
|
||||
osg::ref_ptr<FFmpegDecoder> m_decoder;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // HEADER_GUARD_OSGFFMPEG_FFMPEG_IMAGE_STREAM_H
|
@ -56,7 +56,7 @@ class FormatContextPtr
|
||||
};
|
||||
|
||||
|
||||
class FFmpegDecoder
|
||||
class FFmpegDecoder : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
|
||||
|
@ -106,9 +106,10 @@ void FFmpegDecoderAudio::run()
|
||||
|
||||
|
||||
|
||||
void FFmpegDecoderAudio::setAudioSink(osg::ref_ptr<osg::AudioSinkInterface> audio_sink)
|
||||
void FFmpegDecoderAudio::setAudioSink(osg::ref_ptr<osg::AudioSink> audio_sink)
|
||||
{
|
||||
// The FFmpegDecoderAudio object takes the responsability of destroying the audio_sink.
|
||||
osg::notify(osg::NOTICE)<<"Assigning "<<audio_sink<<std::endl;
|
||||
m_audio_sink = audio_sink;
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ public:
|
||||
void open(AVStream * stream);
|
||||
virtual void run();
|
||||
|
||||
void setAudioSink(osg::ref_ptr<osg::AudioSinkInterface> audio_sink);
|
||||
void setAudioSink(osg::ref_ptr<osg::AudioSink> audio_sink);
|
||||
void fillBuffer(void * buffer, size_t size);
|
||||
|
||||
bool validContext() const;
|
||||
@ -42,7 +42,7 @@ public:
|
||||
private:
|
||||
|
||||
//typedef boost::shared_ptr<AVFrame> FramePtr;
|
||||
typedef osg::ref_ptr<osg::AudioSinkInterface> SinkPtr;
|
||||
typedef osg::ref_ptr<osg::AudioSink> SinkPtr;
|
||||
typedef std::vector<uint8_t> Buffer;
|
||||
|
||||
void decodeLoop();
|
||||
|
@ -1,12 +1,10 @@
|
||||
|
||||
#include "FFmpegImageStream.hpp"
|
||||
#include "FFmpegAudioStream.hpp"
|
||||
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <osg/Notify>
|
||||
|
||||
#include "FFmpegDecoder.hpp"
|
||||
#include "MessageQueue.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
@ -44,7 +42,6 @@ FFmpegImageStream::~FFmpegImageStream()
|
||||
quit(true);
|
||||
|
||||
delete m_commands;
|
||||
delete m_decoder;
|
||||
}
|
||||
|
||||
|
||||
@ -64,6 +61,13 @@ bool FFmpegImageStream::open(const std::string & filename)
|
||||
m_decoder->video_decoder().setUserData(this);
|
||||
m_decoder->video_decoder().setPublishCallback(publishNewFrame);
|
||||
|
||||
if (m_decoder->audio_decoder().validContext())
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Attaching FFmpegAudioStream"<<std::endl;
|
||||
|
||||
getAudioStreams().push_back(new FFmpegAudioStream(m_decoder.get()));
|
||||
}
|
||||
|
||||
_status = PAUSED;
|
||||
applyLoopingMode();
|
||||
|
||||
@ -120,20 +124,6 @@ void FFmpegImageStream::quit(bool waitForThreadToExit)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FFmpegImageStream::setAudioSink(osg::AudioSinkInterface* audio_sink)
|
||||
{
|
||||
m_decoder->audio_decoder().setAudioSink(audio_sink);
|
||||
}
|
||||
|
||||
|
||||
void FFmpegImageStream::consumeAudioBuffer(void * const buffer, const size_t size)
|
||||
{
|
||||
m_decoder->audio_decoder().fillBuffer(buffer, size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
double FFmpegImageStream::duration() const
|
||||
{
|
||||
return m_decoder->duration();
|
||||
@ -161,35 +151,6 @@ double FFmpegImageStream::videoFrameRate() const
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool FFmpegImageStream::audioStream() const
|
||||
{
|
||||
return m_decoder->audio_decoder().validContext();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int FFmpegImageStream::audioFrequency() const
|
||||
{
|
||||
return m_decoder->audio_decoder().frequency();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int FFmpegImageStream::audioNbChannels() const
|
||||
{
|
||||
return m_decoder->audio_decoder().nbChannels();
|
||||
}
|
||||
|
||||
|
||||
|
||||
osg::AudioStream::SampleFormat FFmpegImageStream::audioSampleFormat() const
|
||||
{
|
||||
return m_decoder->audio_decoder().sampleFormat();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FFmpegImageStream::run()
|
||||
{
|
||||
try
|
||||
|
@ -7,17 +7,15 @@
|
||||
#include <OpenThreads/Condition>
|
||||
#include <OpenThreads/Thread>
|
||||
|
||||
#include "FFmpegDecoder.hpp"
|
||||
#include "MessageQueue.hpp"
|
||||
|
||||
namespace osgFFmpeg
|
||||
{
|
||||
|
||||
class FFmpegDecoder;
|
||||
class FFmpegDecoderAudio;
|
||||
class FFmpegDecoderVideo;
|
||||
|
||||
template <class T>
|
||||
class MessageQueue;
|
||||
|
||||
|
||||
class FFmpegImageStream : public osg::ImageStream, public OpenThreads::Thread
|
||||
{
|
||||
public:
|
||||
@ -34,15 +32,6 @@ namespace osgFFmpeg
|
||||
virtual void rewind();
|
||||
virtual void quit(bool waitForThreadToExit = true);
|
||||
|
||||
virtual void setAudioSink(osg::AudioSinkInterface* audio_sink);
|
||||
|
||||
void consumeAudioBuffer(void * const buffer, const size_t size);
|
||||
|
||||
bool audioStream() const;
|
||||
int audioFrequency() const;
|
||||
int audioNbChannels() const;
|
||||
osg::AudioStream::SampleFormat audioSampleFormat() const;
|
||||
|
||||
double duration() const;
|
||||
|
||||
bool videoAlphaChannel() const;
|
||||
@ -76,7 +65,7 @@ namespace osgFFmpeg
|
||||
|
||||
static void publishNewFrame(const FFmpegDecoderVideo &, void * user_data);
|
||||
|
||||
FFmpegDecoder * m_decoder;
|
||||
osg::ref_ptr<FFmpegDecoder> m_decoder;
|
||||
CommandQueue * m_commands;
|
||||
|
||||
Mutex m_mutex;
|
||||
|
Loading…
Reference in New Issue
Block a user