Getting movie surface pixel in setup

Hi I’m new to Cinder.
I want to get pixels from movie in setup but I get error: Thread 1: EXC_BAD_ACCESS (code=1, address=0x0).
Here is the code:

class testApp : public App {
  public:
    qtime::MovieSurfaceRef mMov;
    SurfaceRef mSurf;
    Color8u mCol;
};

void testApp::setup()
{
    mMov = qtime::MovieSurface::create( getAssetPath("movie.mov") );
    mSurf = mMov->getSurface();
    float x = randFloat( getWindowWidth() );
    float y = randFloat( getWindowHeight() );
    mCol = mSurf->getPixel( ivec2(x, y) );
}

Thanks a lot for your help!

Hi,

opening and playing the movie is an asynchronous process. The operating system needs time to read the video and audio streams, detect their format, decode them, synchronize them and send them to display and audio output. Therefor, you’ll need to obtain the Surface in the update() method, because it will be called many times per second. Also, check if the Surface is valid before trying to access the pixels.

-Paul

I thought there are some ways to access movie surface in the setup() method. Thank you very much Paul!

You could try something like this:

do {
    mSurf = mMov->getSurface();
    std::this_thread::sleep_for( std::chrono::milliseconds( 0 ) );
} while( !mSurf );

, but that will only work if all QuickTime processing is done on a separate thread.

Any hints on handling QT from a separate thread safely? I was getting crashes when I tried it.

I’ve tried to load QuickTime on a separate thread but it crashes. Any advice and suggestions will be greatly appreciated!

This works for me but I’m not sure if this is the way Paul has suggested.

void testApp::loadSurf(gl::ContextRef context, qtime::MovieSurfaceRef& mov, SurfaceRef& surf, const string file)
{
    ThreadSetup thSetup;
    context->makeCurrent();
    mov = qtime::MovieSurface::create((getAssetPath(file)));
    while(!surf) surf=mov->getSurface();
}

void testApp::setup()
{
    gl::ContextRef ctx = gl::Context::create(gl::context());
    mTh = shared_ptr<thread>(new thread(bind(&testApp::loadSurf, this, ctx, ref(mMov), ref(mSurf), "sample.mov")));
}

Hi,

that’s a good way to do it. You’re creating a shared context for the QuickTime thread, allowing you to use textures created from the movie in both threads. Your code, however, is not creating any textures at the moment, so I am not sure you need a shared context at all.

-Paul