I’m trying to extract individual frames from Cinder-WMFVideo so I can run some CV algorithms on each frame. I’m a bit shaky on how exactly the WMF Decoder works, but it looks like generally the decoding is happening on a separate thread (hence the need for the Shared Texture Lock) and then using an interop to share the texture between DirectX and OpenGL. Which is great for drawing textures, but not so helpful for pixel operations on the CPU.
My first thought was just to add a function to the player to extract the source:
ci::ImageSourceRef ciWMFVideoPlayer::getImageSource() {
mPlayer->mEVRPresenter->lockSharedTexture();
ci::ImageSourceRef source = mTex->createSource();
mPlayer->mEVRPresenter->unlockSharedTexture();
return source;
}
but this just returns an ImageSource with no data – the correct rows and columns, but the data pointer is empty.
I suspected that I was having issues with the texture being shared, so I tried copying the texture first, and then creating a source from:
ci::ImageSourceRef ciWMFVideoPlayer::getImageSource() {
mPlayer->mEVRPresenter->lockSharedTexture();
int w = mTex->getWidth();
int h = mTex->getHeight();
gl::Texture2d::Format format;
format.setInternalFormat(mTex->getInternalFormat());
ci::gl::TextureRef copyTex = gl::Texture::create(w, h, format);
glCopyImageSubData(mTex->getId(), mTex->getTarget(), 0, 0, 0, 0,
copyTex->getId(), copyTex->getTarget(), 0, 0, 0, 0,
w, h, 1);
mPlayer->mEVRPresenter->unlockSharedTexture();
return copyTex->createSource();
}
And this works, but sure seems to be sloooow – it’s the second-slowest part of my code (after cinder::toOcv()).
Is there a better way to do this?