diff --git a/src/osgPlugins/ffmpeg/CMakeLists.txt b/src/osgPlugins/ffmpeg/CMakeLists.txt index a0dc7d7b1..b9c0340ed 100644 --- a/src/osgPlugins/ffmpeg/CMakeLists.txt +++ b/src/osgPlugins/ffmpeg/CMakeLists.txt @@ -26,6 +26,7 @@ SET(TARGET_SRC FFmpegDecoderVideo.cpp FFmpegImageStream.cpp FFmpegAudioStream.cpp + FFmpegParameters.cpp ReaderWriterFFmpeg.cpp ) @@ -39,6 +40,7 @@ SET(TARGET_H FFmpegPacket.hpp FFmpegImageStream.hpp FFmpegAudioStream.hpp + FFmpegParameters.hpp MessageQueue.hpp ) diff --git a/src/osgPlugins/ffmpeg/FFmpegDecoder.cpp b/src/osgPlugins/ffmpeg/FFmpegDecoder.cpp index 85cabbac3..bd1308519 100644 --- a/src/osgPlugins/ffmpeg/FFmpegDecoder.cpp +++ b/src/osgPlugins/ffmpeg/FFmpegDecoder.cpp @@ -1,5 +1,6 @@ #include "FFmpegDecoder.hpp" +#include "FFmpegParameters.hpp" #include #include @@ -36,7 +37,7 @@ FFmpegDecoder::~FFmpegDecoder() } -bool FFmpegDecoder::open(const std::string & filename) +bool FFmpegDecoder::open(const std::string & filename, FFmpegParameters* parameters) { try { @@ -100,7 +101,9 @@ bool FFmpegDecoder::open(const std::string & filename) } else { - if (av_open_input_file(&p_format_context, filename.c_str(), 0, 0, 0) !=0 ) + AVInputFormat* av_format = (parameters ? parameters->getFormat() : 0); + AVFormatParameters* av_params = (parameters ? parameters->getFormatParameter() : 0); + if (av_open_input_file(&p_format_context, filename.c_str(), av_format, 0, av_params) !=0 ) throw std::runtime_error("av_open_input_file() failed"); } diff --git a/src/osgPlugins/ffmpeg/FFmpegDecoder.hpp b/src/osgPlugins/ffmpeg/FFmpegDecoder.hpp index a783f0161..f0212214b 100644 --- a/src/osgPlugins/ffmpeg/FFmpegDecoder.hpp +++ b/src/osgPlugins/ffmpeg/FFmpegDecoder.hpp @@ -10,6 +10,8 @@ namespace osgFFmpeg { +class FFmpegParameters; + class FormatContextPtr { public: @@ -65,7 +67,7 @@ public: FFmpegDecoder(); ~FFmpegDecoder(); - bool open(const std::string & filename); + bool open(const std::string & filename, FFmpegParameters* parameters); void close(bool waitForThreadToExit); bool readNextPacket(); diff --git a/src/osgPlugins/ffmpeg/FFmpegImageStream.cpp b/src/osgPlugins/ffmpeg/FFmpegImageStream.cpp index bd25ef8bd..89984628c 100644 --- a/src/osgPlugins/ffmpeg/FFmpegImageStream.cpp +++ b/src/osgPlugins/ffmpeg/FFmpegImageStream.cpp @@ -1,6 +1,7 @@ #include "FFmpegImageStream.hpp" #include "FFmpegAudioStream.hpp" +#include "FFmpegParameters.hpp" #include #include @@ -60,11 +61,11 @@ FFmpegImageStream::~FFmpegImageStream() -bool FFmpegImageStream::open(const std::string & filename) +bool FFmpegImageStream::open(const std::string & filename, FFmpegParameters* parameters) { setFileName(filename); - if (! m_decoder->open(filename)) + if (! m_decoder->open(filename, parameters)) return false; setImage( diff --git a/src/osgPlugins/ffmpeg/FFmpegImageStream.hpp b/src/osgPlugins/ffmpeg/FFmpegImageStream.hpp index 4395a58df..11cb332b7 100644 --- a/src/osgPlugins/ffmpeg/FFmpegImageStream.hpp +++ b/src/osgPlugins/ffmpeg/FFmpegImageStream.hpp @@ -15,6 +15,8 @@ namespace osgFFmpeg template class MessageQueue; + + class FFmpegParameters; class FFmpegImageStream : public osg::ImageStream, public OpenThreads::Thread { @@ -25,7 +27,7 @@ namespace osgFFmpeg META_Object(osgFFmpeg, FFmpegImageStream); - bool open(const std::string & filename); + bool open(const std::string & filename, FFmpegParameters* parameters); virtual void play(); virtual void pause(); diff --git a/src/osgPlugins/ffmpeg/FFmpegParameters.cpp b/src/osgPlugins/ffmpeg/FFmpegParameters.cpp new file mode 100644 index 000000000..b64e0315c --- /dev/null +++ b/src/osgPlugins/ffmpeg/FFmpegParameters.cpp @@ -0,0 +1,79 @@ + +#include "FFmpegParameters.hpp" + +#include +#include +#include + + + +namespace osgFFmpeg { + + + +FFmpegParameters::FFmpegParameters() : + m_format(0) +{ + memset(&m_parameters, 0, sizeof(m_parameters)); +} + + +FFmpegParameters::~FFmpegParameters() +{} + + +void FFmpegParameters::parse(const std::string& name, const std::string& value) +{ + if (value.empty()) + { + return; + } + else if (name == "format") + { + avdevice_register_all(); + m_format = av_find_input_format(value.c_str()); + if (!m_format) + OSG_NOTICE<<"Failed to apply input video format: "<> audio_sample_rate; + m_parameters.sample_rate = audio_sample_rate; + } +} + + + +} // namespace osgFFmpeg diff --git a/src/osgPlugins/ffmpeg/FFmpegParameters.hpp b/src/osgPlugins/ffmpeg/FFmpegParameters.hpp new file mode 100644 index 000000000..1c2d4b922 --- /dev/null +++ b/src/osgPlugins/ffmpeg/FFmpegParameters.hpp @@ -0,0 +1,40 @@ + +#ifndef HEADER_GUARD_OSGFFMPEG_FFMPEG_PARAMETERS_H +#define HEADER_GUARD_OSGFFMPEG_FFMPEG_PARAMETERS_H + +#include "FFmpegHeaders.hpp" + +#include + + +namespace osgFFmpeg { + + + +class FFmpegParameters : public osg::Referenced +{ +public: + + FFmpegParameters(); + ~FFmpegParameters(); + + bool isFormatAvailable() const { return m_format!=NULL; } + + AVInputFormat* getFormat() { return m_format; } + AVFormatParameters* getFormatParameter() { return &m_parameters; } + + void parse(const std::string& name, const std::string& value); + +protected: + + AVInputFormat* m_format; + AVFormatParameters m_parameters; +}; + + + +} // namespace osgFFmpeg + + + +#endif // HEADER_GUARD_OSGFFMPEG_FFMPEG_PARAMETERS_H diff --git a/src/osgPlugins/ffmpeg/ReaderWriterFFmpeg.cpp b/src/osgPlugins/ffmpeg/ReaderWriterFFmpeg.cpp index c58b59d6b..c108235cb 100644 --- a/src/osgPlugins/ffmpeg/ReaderWriterFFmpeg.cpp +++ b/src/osgPlugins/ffmpeg/ReaderWriterFFmpeg.cpp @@ -13,6 +13,7 @@ #include "FFmpegHeaders.hpp" #include "FFmpegImageStream.hpp" +#include "FFmpegParameters.hpp" #include #include @@ -49,6 +50,12 @@ public: supportsExtension("sav", "MPEG-4"); supportsExtension("3gp", "MPEG-4"); supportsExtension("sdp", "MPEG-4"); + + supportsOption("format", "Force setting input format (e.g. vfwcap for Windows webcam)"); + supportsOption("pixel_format", "Set pixel format"); + supportsOption("frame_size", "Set frame size (e.g. 320x240)"); + supportsOption("frame_rate", "Set frame rate (e.g. 25)"); + supportsOption("audio_sample_rate", "Set audio sampling rate (e.g. 44100)"); #ifdef USE_AV_LOCK_MANAGER // enable thread locking @@ -75,9 +82,16 @@ public: if (filename.compare(0, 5, "/dev/")==0) { - return readImageStream(filename, options); + return readImageStream(filename, NULL); } - + + osg::ref_ptr parameters(new osgFFmpeg::FFmpegParameters); + parseOptions(parameters.get(), options); + if (parameters->isFormatAvailable()) + { + return readImageStream(filename, parameters.get()); + } + if (! acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; @@ -88,22 +102,36 @@ public: if (path.empty()) return ReadResult::FILE_NOT_FOUND; - return readImageStream(path, options); + return readImageStream(path, parameters.get()); } - ReadResult readImageStream(const std::string& filename, const osgDB::ReaderWriter::Options * options) const + ReadResult readImageStream(const std::string& filename, osgFFmpeg::FFmpegParameters* parameters) const { OSG_INFO << "ReaderWriterFFmpeg::readImage " << filename << std::endl; osg::ref_ptr image_stream(new osgFFmpeg::FFmpegImageStream); - if (! image_stream->open(filename)) + if (! image_stream->open(filename, parameters)) return ReadResult::FILE_NOT_HANDLED; return image_stream.release(); } private: + + void parseOptions(osgFFmpeg::FFmpegParameters* parameters, const osgDB::ReaderWriter::Options * options) const + { + if (options && options->getNumPluginStringData()>0) + { + const FormatDescriptionMap& supportedOptList = supportedOptions(); + for (FormatDescriptionMap::const_iterator itr = supportedOptList.begin(); + itr != supportedOptList.end(); ++itr) + { + const std::string& name = itr->first; + parameters->parse(name, options->getPluginStringData(name)); + } + } + } #ifdef USE_AV_LOCK_MANAGER static int lockMgr(void **mutex, enum AVLockOp op)