Introduce FFmpegAudioStream implementation

This commit is contained in:
Robert Osfield 2009-03-03 16:51:01 +00:00
parent e0959ea804
commit e035decd95
14 changed files with 198 additions and 76 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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)
{

View File

@ -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;

View File

@ -15,7 +15,7 @@
using namespace osg;
AudioSinkInterface::AudioSinkInterface() :
AudioSink::AudioSink() :
_delay(0.0)
{
}

View File

@ -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)

View File

@ -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
)

View 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

View 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

View File

@ -56,7 +56,7 @@ class FormatContextPtr
};
class FFmpegDecoder
class FFmpegDecoder : public osg::Referenced
{
public:

View File

@ -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;
}

View File

@ -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();

View File

@ -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

View File

@ -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;