Первая попытка у меня была с DirectShow, я до сих пор с содроганием вспоминаю его АПИ. Оно работало но очень тормозило на больших видео файлах (FullHD)
Вторая - захват через OpenCV, работает быстро и поддерживает много форматов, но увы без звука, и нужно самому синхронизировать скорость.
И вот мне подсказали про VLC плеер.
http://www.videolan.org/vlc/
И как оказалось нормальных примеров с пояснениями даже на английском языке не так много, тем более под OpenGL.
Есть туториал с SDL связкой, но я не использую SDL в своем проекте, по этому пришлось хорошенько покопаться прежде чем все заработало.
Плюс ко всему половина из примеров на старых версиях, и в новых эти комманды не поддерживаются.
Ну довольно слов, вот код с пояснениями, + проект на MSVC++ Express 2010.
#include "stdafx.h"
#define GLEW_STATIC 1
#include <GL\glew.h>
#include <GL\gl.h>
#include <GL\glu.h>
#include <GL\glaux.h>
#include <GL\glfw.h>
#pragma comment( lib, "glu32.lib" )
#pragma comment( lib, "opengl32.lib" )
#pragma comment( lib, "glew32s.lib" )
#pragma comment( lib, "GLAUX.lib" )
#pragma comment ( lib , "GLFW.lib")
#pragma comment(linker, "/nodefaultlib:libcmt.lib")
#include <vlc\vlc.h>
#pragma comment (lib,"libvlc.lib")
int graphicsWidth = 800;
int graphicsHeight = 600;
int textureWidth = 512;
int textureHeight = 512;
unsigned char * pixels;
void *lock( void *data, void **p_pixels )
{
*p_pixels = pixels;
return NULL;
}
void display( void *data, void *id )
{
(void) data;
}
void unlock( void *data, void *id, void *const *ipixels )
{
}
int _tmain( int argc, _TCHAR* argv[] )
{
glfwInit();
glfwOpenWindowHint( GLFW_WINDOW_NO_RESIZE, GL_TRUE );
glfwOpenWindow( graphicsWidth, graphicsHeight, 0, 0, 0, 0, 24, 0, GLFW_WINDOW );
GLFWvidmode desktopMode;
glfwGetDesktopMode( &desktopMode );
glfwSetWindowPos( desktopMode.Width/2 - graphicsWidth/2, desktopMode.Height/2 - graphicsHeight/2 );
glewInit();
glEnable( GL_TEXTURE_2D );
GLuint glTexture;
glGenTextures( 1, &glTexture );
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, glTexture );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8.0f );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
pixels=new unsigned char[ textureWidth * textureHeight * 4 ];
libvlc_instance_t *libvlc;
libvlc_media_t *m;
libvlc_media_player_t *mp;
char const *vlc_argv[] =
{
"--no-xlib",
"-q",
"--no-video-title-show",
"--quiet",
"--ignore-config",
"--vout", "vmem",
"-I", "dumy"
};
int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv);
libvlc = libvlc_new( vlc_argc, vlc_argv );
mp = libvlc_media_player_new( libvlc );
libvlc_video_set_callbacks( mp, lock, unlock, display, NULL );
libvlc_video_set_format( mp, "RV32", textureWidth, textureHeight, textureWidth*4 );
m = libvlc_media_new_path( libvlc, "Video/time_machine.avi" );
libvlc_media_player_set_media( mp, m );
libvlc_media_release( m );
libvlc_media_player_play( mp );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 50.0f, (float)graphicsWidth/(float)graphicsHeight, 0.1f, 1000.0f );
gluLookAt( 0.0f, -1.0f, -3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glRotatef( -40.0f, 0.0f, 1.0f, 0.0f );
while(glfwGetWindowParam(GLFW_OPENED))
{
if( glfwGetKey(GLFW_KEY_ESC)==GLFW_PRESS ) break;
glTexSubImage2D ( GL_TEXTURE_2D, 0, 0, 0, textureWidth, textureHeight, GL_BGRA, GL_UNSIGNED_BYTE, pixels );
glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
glRotatef( 0.01f, 0.0f, 1.0f, 0.0f );
glBegin( GL_QUADS );
glTexCoord2f( 1.0f, 0.0f );
glVertex3f( -1.0f, 1.0f, 0.0f );
glTexCoord2f( 0.0f, 0.0f );
glVertex3f( 1.0f, 1.0f, 0.0f );
glTexCoord2f( 0.0f, 1.0f );
glVertex3f( 1.0f, -1.0f, 0.0f );
glTexCoord2f( 1.0f, 1.0f );
glVertex3f( -1.0f, -1.0f, 0.0f );
glEnd();
glfwSwapBuffers();
}
libvlc_media_player_stop( mp );
while ( libvlc_media_player_is_playing( mp ) )
{
glfwPollEvents();
}
glDeleteTextures( 1, &glTexture );
delete pixels;
libvlc_media_player_release( mp );
libvlc_release( libvlc );
return 0;
}
Важно!
VLC плеер воспроизводит видео через свои плагины, папка plugins должна быть в корне проекта, плеер сам найдет и подключит нужные.
Все файлы в проекте VLC от 2.0.5 версии, просто копируйте в свой проект - подключайте как у меня и все заработает.
Если вы все же захотите самостоятельно подключить VLC в свой проект используя СДК с официального сайта - могут возникнуть сложности. Дело в том, что lib файлы из СДК содержат функции которых нет в ДЛЛ, пришлось делать lib из DLL по этому примеру
http://wiki.videolan.org/GenerateLibFromDll
Архив с проектом
https://goo.gl/kE7gbU
#GLFW, #OpenGL, #VLC, #видео
20 июня 2013
(Обновление: 9 июля 2016)
Комментарии [4]