From 35ec6cee40777a18a3ef0e416da26af4de243f64 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 12 Jan 2007 22:07:33 +0000 Subject: [PATCH] From Riccardo Corsi, "this should be the final version of the qt-plugin ported to windows and cleaned up to avoid crashes on exit. Stephan and I tested it on Mac and Win. Just a couple of notes: * the plugin is able to load both regular 2D images and movie stream. There is a #define QT_HANDLE_IMAGES_ALSO mechanism to indicate whether to use it for images or not. This is defined by default on Mac only, to avoid conflicts with the standard windows plugins. See comments on QTUtils.h * de-initialization of quicktime before exit is now left to an observer, which calls exitQuicktime() when last media loaded with the plugin is released. This prevent a crash on exit without need of any extra call external to the plugin." --- src/osgPlugins/quicktime/QTUtils.cpp | 10 ++- src/osgPlugins/quicktime/QTUtils.h | 8 ++ .../quicktime/QuicktimeImageStream.cpp | 33 ++++---- .../quicktime/QuicktimeImageStream.h | 40 +++++----- src/osgPlugins/quicktime/ReaderWriterQT.cpp | 75 ++++++++++++++----- 5 files changed, 105 insertions(+), 61 deletions(-) diff --git a/src/osgPlugins/quicktime/QTUtils.cpp b/src/osgPlugins/quicktime/QTUtils.cpp index 3a14c14c7..0cbf0b0ca 100644 --- a/src/osgPlugins/quicktime/QTUtils.cpp +++ b/src/osgPlugins/quicktime/QTUtils.cpp @@ -27,7 +27,7 @@ using namespace std; #endif OSErr err = EnterMovies(); if (err!=0) - osg::notify(osg::FATAL) << "Error while initializing quicktime: " << err << endl; + osg::notify(osg::FATAL) << "Error while initializing quicktime: " << err << endl; else osg::notify(osg::DEBUG_INFO) << "Quicktime initialized successfully" << endl; registerQTReader(); @@ -45,6 +45,9 @@ using namespace std; 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"); @@ -59,8 +62,9 @@ using namespace std; r->addFileExtensionAlias("mpg", "qt"); r->addFileExtensionAlias("mpv", "qt"); r->addFileExtensionAlias("dv", "qt"); - r->addFileExtensionAlias("mp4", "qt"); - r->addFileExtensionAlias("m4v", "qt"); + r->addFileExtensionAlias("mp4", "qt"); + r->addFileExtensionAlias("m4v", "qt"); + #endif } }; diff --git a/src/osgPlugins/quicktime/QTUtils.h b/src/osgPlugins/quicktime/QTUtils.h index 4df4cae75..e92cebc3f 100644 --- a/src/osgPlugins/quicktime/QTUtils.h +++ b/src/osgPlugins/quicktime/QTUtils.h @@ -10,9 +10,17 @@ #ifndef QTUTILS_HEADER_ #define QTUTILS_HEADER_ +// Quicktime plugin is able to load regular 2D images +// besides movie streams. +// It is used as default image loader on __APPLE__ +// Uncomment this define to use it as image loader +// on other platforms. +// #define QT_HANDLE_IMAGES_ALSO + #ifdef __APPLE__ #include #include + #define QT_HANDLE_IMAGES_ALSO #else #include #include diff --git a/src/osgPlugins/quicktime/QuicktimeImageStream.cpp b/src/osgPlugins/quicktime/QuicktimeImageStream.cpp index f46a9e5a4..3747eec7b 100644 --- a/src/osgPlugins/quicktime/QuicktimeImageStream.cpp +++ b/src/osgPlugins/quicktime/QuicktimeImageStream.cpp @@ -38,22 +38,21 @@ #define IDLE_TIMEOUT 150000L #define ERR_MSG(no,msg) osg::notify(osg::WARN) << "QT-ImageStream: " << msg << " failed with error " << no << std::endl; -static OpenThreads::Mutex* s_qtMutex = new OpenThreads::Mutex; - int QuicktimeImageStream::_qtInstanceCount = 0; // Constructor: setup and start thread QuicktimeImageStream::QuicktimeImageStream(std::string fileName) : ImageStream() { - // ricky + /* + // ricky if(_qtInstanceCount == 0) - { - OpenThreads::ScopedLock lock(*s_qtMutex); + { osg::notify(osg::NOTICE) << "quicktime Init" << std::endl; initQuicktime(); } - ++ _qtInstanceCount; + ++ _qtInstanceCount; // end ricky + */ _len = 0; @@ -81,21 +80,20 @@ QuicktimeImageStream::~QuicktimeImageStream() quit(true); } - // ricky + /* + // ricky -- _qtInstanceCount; if(_qtInstanceCount == 0) { - OpenThreads::ScopedLock lock(*s_qtMutex); osg::notify(osg::NOTICE) << "quicktime Exit" << std::endl; exitQuicktime(); - } + } // end ricky + */ // clean up quicktime movies. - { - OpenThreads::ScopedLock lock(*s_qtMutex); - delete _data; - } + delete _data; + } @@ -131,14 +129,10 @@ void QuicktimeImageStream::load(std::string fileName) { osg::notify(osg::DEBUG_INFO) << "QT-ImageStream: loading quicktime movie from " << fileName << std::endl; - OpenThreads::ScopedLock lock(*s_qtMutex); - _data->load(this, fileName); _len = _data->getMovieDuration(); _current = 0; - - } void QuicktimeImageStream::quit(bool wiatForThreadToExit) @@ -177,8 +171,6 @@ void QuicktimeImageStream::run() osg::notify(osg::DEBUG_INFO) << "movietime: " << _data->getMovieTime() << " rate: " << _data->getMovieRate() << " state " << cmd << " playing: " << playing << " done " << done << " " << _wrIndex << "/" << _rdIndex << std::endl; // Handle commands { - OpenThreads::ScopedLock lock(*s_qtMutex); - if (cmd != THREAD_IDLE) { osg::notify(osg::DEBUG_INFO) << "new cmd: " << cmd << std::endl; switch (cmd) { @@ -265,8 +257,9 @@ void QuicktimeImageStream::run() rewind(); } // orig - //pause(); + //pause(); + //end ricky } } diff --git a/src/osgPlugins/quicktime/QuicktimeImageStream.h b/src/osgPlugins/quicktime/QuicktimeImageStream.h index 7c40937c6..6f5b913ee 100644 --- a/src/osgPlugins/quicktime/QuicktimeImageStream.h +++ b/src/osgPlugins/quicktime/QuicktimeImageStream.h @@ -1,26 +1,26 @@ // -*-c++-*- /* - * Copyright (C) 2004 Stephan Huber http://digitalmind.de - * - * The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for - * real-time rendering of large 3D photo-realistic models. - * The OSG homepage is http://www.openscenegraph.org/ - * - * This software is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ +* Copyright (C) 2004 Stephan Huber http://digitalmind.de +* +* The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for +* real-time rendering of large 3D photo-realistic models. +* The OSG homepage is http://www.openscenegraph.org/ +* +* This software is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This software is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ #ifndef _QUICKTIMEIMAGESTREAM_H_ #define _QUICKTIMEIMAGESTREAM_H_ diff --git a/src/osgPlugins/quicktime/ReaderWriterQT.cpp b/src/osgPlugins/quicktime/ReaderWriterQT.cpp index a4ea8367b..2e997c46a 100644 --- a/src/osgPlugins/quicktime/ReaderWriterQT.cpp +++ b/src/osgPlugins/quicktime/ReaderWriterQT.cpp @@ -3,6 +3,8 @@ #include +#include + #include "osg/GL" #include "osgDB/FileNameUtils" @@ -23,6 +25,35 @@ 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 @@ -46,7 +77,9 @@ public: { // this should be the only image importer required on the Mac // dont know what else it supports, but these will do - return + return + + #ifdef QT_HANDLE_IMAGES_ALSO osgDB::equalCaseInsensitive(extension,"rgb") || osgDB::equalCaseInsensitive(extension,"rgba") || osgDB::equalCaseInsensitive(extension,"jpg") || @@ -58,28 +91,27 @@ public: osgDB::equalCaseInsensitive(extension,"pict") || osgDB::equalCaseInsensitive(extension,"pct") || osgDB::equalCaseInsensitive(extension,"tga") || - osgDB::equalCaseInsensitive(extension,"psd") || - + osgDB::equalCaseInsensitive(extension,"psd") || + #endif + acceptsMovieExtension(extension); } - virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options*) const - { - - // ricky - // If using only the QuicktimeImageStream class for the movies, you can comment - // out this line, as the init function is called inside the QTImageStream - // ctor. - // It is left here for compatibility with the original plugin, to handle - // regular 2D images as well. - initQuicktime(); - + virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const + { std::string ext = osgDB::getLowerCaseFileExtension(file); if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; - std::string fileName = osgDB::findDataFile( file ); + std::string fileName = osgDB::findDataFile( file, options); if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; + // Note from Riccardo Corsi + // Quicktime initialization is done here, when a media is found + // and before any image or movie is loaded. + // After the first call the function does nothing. + // The cleaning up is left to the QuicktimeExitObserver (see below) + initQuicktime(); + // if the file is a movie file then load as an ImageStream. if (acceptsMovieExtension(ext)) { @@ -90,9 +122,13 @@ public: // to get things off the ground. QuicktimeImageStream* moov = new QuicktimeImageStream(fileName); // moov->play(); + + // add the media to the observer for proper clean up on exit + _qtExitObserver.addMedia(moov); + return moov; } - + long origWidth, origHeight,buffWidth,buffHeight,buffDepth,origDepth; // NOTE - implememntation means that this will always return 32 bits, so it is hard to work out if @@ -211,6 +247,10 @@ public: osg::Image::USE_NEW_DELETE ); notify(DEBUG_INFO) << "image read ok "<