: Documentation : Multimedia Tutorials

Introduction

A common request from AR application developers is the ability to play a movie on a marker. Fortunately, OpenSceneGraph has support for video textures via the osg::ImageStream class. There are loader plugins that use this class to add video support for various formats, such as Apple QuickTime. In this tutorial, we will use this plugin to load and play a QuickTime movie on a marker.

Prerequisites

Depending on your operating system, you may need to build the QuickTime plugin to continue this tutorial.

Under Windows, you need to have the QuickTime SDK installed, and point CMake to the correct include directory and library file when building OpenSceneGraph.

Loading and Playing a QuickTime Movie

To simplify the loading the playing of the movie, we create a small class to encapsulate this behaviour. By making the class a subclass of osg::Group, we can simply add an instance of this class to the scene graph.

class Movie : public osg::Group {

private:
    osg::ref_ptr<osg::ImageStream> mImageStream;
    osg::ref_ptr<osg::Texture> mVideoTexture;
    osg::ref_ptr<osg::Geode> mVideoGeode;

public:
    Movie(std::string filename) : osg::Group() {

        osg::Image* img = osgDB::readImageFile(filename);
        mImageStream = dynamic_cast<osg::ImageStream*>(img);

        if (mImageStream.valid()) {
            std::cout << "Got movie" << std::endl;
            mImageStream->play();
        } else {
            std::cout << "No movie!" << std::endl;
        }

        float aspectRatio = (float)img->t() / (float)img->s();
        float videoWidth = 180;
        float videoHeight = videoWidth * aspectRatio;

        mVideoGeode = new osg::Geode();

        bool texRect = true;

        if (texRect) {
            mVideoTexture = new osg::TextureRectangle(img);
            mVideoGeode->addDrawable(osg::createTexturedQuadGeometry(
                osg::Vec3(-videoWidth / 2, -videoHeight / 2, 0),
                osg::Vec3(videoWidth, 0, 0),
                osg::Vec3(0, videoHeight, 0),
                0,  img->t(), img->s(), 0));

        } else {
            mVideoTexture = new osg::Texture2D(img);
            mVideoGeode->addDrawable(osg::createTexturedQuadGeometry(
                osg::Vec3(-videoWidth / 2, -videoHeight / 2, 0),
                osg::Vec3(videoWidth, 0, 0),
                osg::Vec3(0, videoHeight, 0),
                0,  1,1, 0));


        }

        mVideoGeode->getOrCreateStateSet()->setTextureAttributeAndModes(0, mVideoTexture.get());
        this->addChild(mVideoGeode.get());

    }


    void pause() {
        if (mImageStream.valid()) {
            if (mImageStream->getStatus() == osg::ImageStream::PLAYING) {
                mImageStream->pause();
            } else if (mImageStream->getStatus() == osg::ImageStream::PAUSED) {
                mImageStream->play();
            }
        }
    }
};