calculo para saber, digamos assim, o tempo de permanencia de cada quadro em milissegundos (o porque mais para frente). canvas->resize(width, height); resize(getDefaultWidth(), getDefaultHeight());Agora que eu sei o tamanho do video, redimensiono o canvas. Depois dele a janela principal.Explicando rapidamente o que acontece aqui: por padrao, a janela principal e configurada para ficar com o menor tamanho em que caibam todos os filhos. Como eu redimensionei um deles (depois de todos criados), as funcoes getDefaultWidth() e getDefaultHeight() retornam as dimensoes necessarias para caber todo mundo novamente. image = new FXImage(getApp(), 0, IMAGE_KEEP|IMAGE_OWNED|IMAGE_SHMP|IMAGE_SHMI, width, height); image->create(); dummy = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, 4); cvSetData(dummy, image->getData(), CV_AUTO_STEP);Criando as imagens. Nada de especial, ja falei sobre isso. getApp()->addTimeout(this, ID_FRAME, 0); return 1;}Bom, a ultima coisa a fazer aqui e disparar um timer para recuperar os quadros do video e desenha-los. Nao queremos esperar, entao o tempo e 0.Quadro-a-quadrolong FoxVideoPlayerMainWindow::onTimeoutFrame(FXObject*, FXSelector, void*) { if (!capture) return 1; frame = cvQueryFrame(capture); if (frame) { cvCvtColor(frame, dummy, CV_BGR2RGBA); image->render(); canvas->update(); getApp()->addTimeout(this, ID_FRAME, freq); } else canvas->update(); return 1;}Toda vez que essa funcao e chamada, o proximo quadro do video e recuperado com cvQueryFrame(). Se nao for nulo (ou seja, o video ainda nao acabou), os espacos de cor sao convertidos com cvCvtColor(). Como dummy utiliza os pixels de image, e como se eu estivesse pintando duas imagens de uma vez so (mas, na verdade, e uma imagem so com duas representacoes).Em seguida, vem uma operacao importante. E algo que eu demorei muito para entender. Uma imagem (pelo menos no FOX Toolkit, nao sei quando a outras bibliotecas de interface grafica) tem duas representacoes, uma no lado do cliente outra do servidor. O lado do cliente e esse vetor de pixels que pode ser acessado por meio de image->getData(). O lado do servidor e o servidor grafico (no meu caso, o X; nao sei qual seria no caso do Uindous ou do Macos). Quando o lado do cliente e alterado, e necessario transferir os pixels para o servidor com render(). Sem isso, seria exibida sempre a mesma imagem que foi criada, apenas um retangulo preto. So por curiosidade, restore() faz o inverso, recupera os pixels do servidor e poe de volta no cliente.Tendo a nova imagem no lado do servidor, basta atualizar o canvas. Depois, agenda a recuperacao do proximo quadro, desta vez respeitando a frequencia de quadros do video.Quando o video termina, cvQueryFrame() returna nulo. Neste caso, nao e mais necessario agendar o proximo quadro. Apenas atualiza o canvas, que sera pintado de preto, apenas para nao ficar exibindo o ultimo quadro do video.ResultadoO resultado disso tudo pode ser observado neste video que eu gravei:ConclusaoBem, isto foi apenas o basico necessario. Apenas exibi o video, sem aplicar nenhum processamento. Isso, obviamente, deve ser feito depois de recuperar o quadro e antes de converte-lo para RGBA.Alem disso, no exemplo o video e carregado de um arquivo, mas o OpenCV tambem captura video pela webcam.Um abraco e ate a proxima.