From Riccardo Corsi, "in attach you'll find a patch to cleanup a little bit the (de)initialization code of QuickTime environment from the quickTime pluging.

It basically removes the static init() and exit() functions,and move them inside the observer class (the one that cleans everything up when the last media is unloaded).

It also add an extra check to clean up on exit if the QuickTime env is initialized, but no media is succesfully loaded / written (it might happens with streaming resources).

I tested it under WinXP with zero, one and multiple videos.

Stephan reads in copy: could you kindly check if everything runs smooth under OSX as well? Also, have you got a chance to test it with streaming media?
"
This commit is contained in:
Robert Osfield 2009-02-11 17:14:53 +00:00
parent 04351b0af8
commit c385e11aff
4 changed files with 120 additions and 126 deletions

View File

@ -34,7 +34,6 @@ QuicktimeImportExport::QuicktimeImportExport()
: _error(0), : _error(0),
_lastError("") _lastError("")
{ {
initQuicktime();
} }

View File

@ -16,81 +16,6 @@
using namespace std; using namespace std;
class QuicktimeInitializer : public osg::Referenced {
public:
QuicktimeInitializer() :osg::Referenced() {
#ifndef __APPLE__
InitializeQTML(0);
#endif
OSErr err = EnterMovies();
if (err!=0)
osg::notify(osg::FATAL) << "Error while initializing quicktime: " << err << endl;
else
osg::notify(osg::DEBUG_INFO) << "Quicktime initialized successfully" << endl;
static bool registered = false;
if (!registered){
registerQTReader();
registered = true;
}
}
~QuicktimeInitializer() {
#ifndef __APPLE__
ExitMovies();
#endif
//osg::notify(osg::DEBUG_INFO) << "Quicktime deinitialized successfully" << endl;
}
protected:
void registerQTReader() {
osgDB::Registry* r = osgDB::Registry::instance();
r->addFileExtensionAlias("mov", "qt");
#ifdef QT_HANDLE_IMAGES_ALSO
r->addFileExtensionAlias("jpg", "qt");
r->addFileExtensionAlias("jpe", "qt");
r->addFileExtensionAlias("jpeg", "qt");
r->addFileExtensionAlias("tif", "qt");
r->addFileExtensionAlias("tiff", "qt");
r->addFileExtensionAlias("gif", "qt");
r->addFileExtensionAlias("png", "qt");
r->addFileExtensionAlias("psd", "qt");
r->addFileExtensionAlias("tga", "qt");
r->addFileExtensionAlias("mov", "qt");
r->addFileExtensionAlias("avi", "qt");
r->addFileExtensionAlias("mpg", "qt");
r->addFileExtensionAlias("mpv", "qt");
r->addFileExtensionAlias("dv", "qt");
r->addFileExtensionAlias("mp4", "qt");
r->addFileExtensionAlias("m4v", "qt");
#endif
}
};
void initQuicktime(bool erase) {
static osg::ref_ptr<QuicktimeInitializer> s_qt_init = new QuicktimeInitializer();
if (erase) {
s_qt_init = NULL;
} else if (!s_qt_init.valid())
{
s_qt_init = new QuicktimeInitializer();
}
}
void exitQuicktime() {
initQuicktime(true);
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// MakeFSSPecFromPath // MakeFSSPecFromPath
// wandelt einen Posix-Pfad in ein FSSpec um. // wandelt einen Posix-Pfad in ein FSSpec um.

View File

@ -50,16 +50,6 @@
#endif #endif
/**
* inits Quicktime, if erase = true, the Quicktime-stuff gets cleaned, call it before your app exits
* @param erase true, if you want to cleanup quicktime-related stuff
*/
void initQuicktime(bool erase = false);
/** cleans up all quicktime-related stuff */
void exitQuicktime();
/** constructs an FSSpec out of an path */ /** constructs an FSSpec out of an path */
OSStatus MakeFSSpecFromPath(const char* path, FSSpec* spec); OSStatus MakeFSSpecFromPath(const char* path, FSSpec* spec);

View File

@ -36,46 +36,94 @@
using namespace osg; using namespace osg;
// This class is used as a helper to de-initialize
// properly quicktime, when the last media loaded
// with the quicktime plugin is released.
// All loaded media must be added to the observer
// (see ReaderWriterQT::readImage() function)
class QuicktimeExitObserver : public osg::Observer
{
public:
QuicktimeExitObserver () : _instanceCount(0)
{
}
virtual ~QuicktimeExitObserver()
{
};
void addMedia(Image* ptr)
{
ptr->addObserver(this);
++ _instanceCount;
}
virtual void objectDeleted(void*)
{
-- _instanceCount;
if(_instanceCount== 0)
exitQuicktime();
}
private:
unsigned int _instanceCount;
};
class ReaderWriterQT : public osgDB::ReaderWriter class ReaderWriterQT : public osgDB::ReaderWriter
{ {
public: public:
// This class is used as a helper to de-initialize
// properly quicktime, when the last media loaded
// with the quicktime plugin is released.
// All loaded media must be added to the observer
// (see ReaderWriterQT::readImage() function)
class QuicktimeInitializer : public osg::Observer
{
public:
QuicktimeInitializer ():
_instanceCount(0),
_setup(false)
{}
virtual ~QuicktimeInitializer()
{
// When we get here, the exit() function
// should have been called, when last media was released.
// In case no media has been added after initialization,
// let's perform an extra check
if (_setup && _instanceCount == 0)
{
exit();
}
};
void addMedia(Image* ptr)
{
ptr->addObserver(this);
++ _instanceCount;
}
virtual void objectDeleted(void*)
{
-- _instanceCount;
if(_instanceCount== 0)
exit();
}
void init()
{
if (!_setup)
{
#ifndef __APPLE__
InitializeQTML(0);
#endif
OSErr err = EnterMovies();
if (err!=0)
osg::notify(osg::FATAL) << "Error while initializing quicktime: " << err << std::endl;
else
osg::notify(osg::DEBUG_INFO) << "Quicktime initialized successfully" << std::endl;
_setup = true;
}
}
void exit()
{
#ifndef __APPLE__
ExitMovies();
#endif
_setup = false;
}
private:
unsigned int _instanceCount;
bool _setup;
};
ReaderWriterQT::ReaderWriterQT() ReaderWriterQT::ReaderWriterQT()
{ {
registerQtReader();
supportsExtension("mov","Movie format"); supportsExtension("mov","Movie format");
supportsExtension("mpg","Movie format"); supportsExtension("mpg","Movie format");
supportsExtension("mpv","Movie format"); supportsExtension("mpv","Movie format");
@ -228,8 +276,9 @@ public:
// Quicktime initialization is done here, when a media is found // Quicktime initialization is done here, when a media is found
// and before any image or movie is loaded. // and before any image or movie is loaded.
// After the first call the function does nothing. // After the first call the function does nothing.
// The cleaning up is left to the QuicktimeExitObserver (see below) // The cleaning up is left to the QuicktimeInitializer (see below)
initQuicktime(); _qtExitObserver.init();
// //
QuicktimeLiveImageStream* p_qt_image_stream = new QuicktimeLiveImageStream(osgDB::getNameLessExtension(file)); QuicktimeLiveImageStream* p_qt_image_stream = new QuicktimeLiveImageStream(osgDB::getNameLessExtension(file));
// add the media to the observer for proper clean up on exit // add the media to the observer for proper clean up on exit
@ -252,8 +301,8 @@ public:
// Quicktime initialization is done here, when a media is found // Quicktime initialization is done here, when a media is found
// and before any image or movie is loaded. // and before any image or movie is loaded.
// After the first call the function does nothing. // After the first call the function does nothing.
// The cleaning up is left to the QuicktimeExitObserver (see below) // The cleaning up is left to the QuicktimeInitializer (see below)
initQuicktime(); _qtExitObserver.init();
// if the file is a movie file then load as an ImageStream. // if the file is a movie file then load as an ImageStream.
@ -317,6 +366,8 @@ public:
} }
} }
_qtExitObserver.init();
QuicktimeImportExport importer; QuicktimeImportExport importer;
osg::ref_ptr<osg::Image> image = importer.readFromStream(is, filename, sizeHint); osg::ref_ptr<osg::Image> image = importer.readFromStream(is, filename, sizeHint);
@ -334,7 +385,7 @@ public:
std::string ext = osgDB::getFileExtension(fileName); std::string ext = osgDB::getFileExtension(fileName);
if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
initQuicktime(); _qtExitObserver.init();
//Buidl map of extension <-> osFileTypes //Buidl map of extension <-> osFileTypes
std::map<std::string, OSType> extmap; std::map<std::string, OSType> extmap;
@ -386,6 +437,8 @@ public:
} }
} }
_qtExitObserver.init();
QuicktimeImportExport exporter; QuicktimeImportExport exporter;
exporter.writeToStream(os, const_cast<osg::Image*>(&img), filename); exporter.writeToStream(os, const_cast<osg::Image*>(&img), filename);
@ -395,8 +448,35 @@ public:
return WriteResult::ERROR_IN_WRITING_FILE; return WriteResult::ERROR_IN_WRITING_FILE;
} }
protected:
mutable QuicktimeExitObserver _qtExitObserver; //internal utils
void registerQtReader() const
{
osgDB::Registry* r = osgDB::Registry::instance();
r->addFileExtensionAlias("mov", "qt");
#ifdef QT_HANDLE_IMAGES_ALSO
r->addFileExtensionAlias("jpg", "qt");
r->addFileExtensionAlias("jpe", "qt");
r->addFileExtensionAlias("jpeg", "qt");
r->addFileExtensionAlias("tif", "qt");
r->addFileExtensionAlias("tiff", "qt");
r->addFileExtensionAlias("gif", "qt");
r->addFileExtensionAlias("png", "qt");
r->addFileExtensionAlias("psd", "qt");
r->addFileExtensionAlias("tga", "qt");
r->addFileExtensionAlias("mov", "qt");
r->addFileExtensionAlias("avi", "qt");
r->addFileExtensionAlias("mpg", "qt");
r->addFileExtensionAlias("mpv", "qt");
r->addFileExtensionAlias("dv", "qt");
r->addFileExtensionAlias("mp4", "qt");
r->addFileExtensionAlias("m4v", "qt");
#endif
}
mutable QuicktimeInitializer _qtExitObserver;
}; };
// now register with Registry to instantiate the above // now register with Registry to instantiate the above