Files
glest-source/source/shared_lib/sources/graphics/video_player.cpp
2012-05-12 23:59:40 +00:00

325 lines
8.1 KiB
C++

// ==============================================================
// This file is part of MegaGlest Shared Library (www.glest.org)
//
// Copyright (C) 2012 Mark Vejvoda (mark_vejvoda@hotmail.com)
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include <GL/glew.h>
#include "video_player.h"
#include <SDL.h>
#include <SDL_mutex.h>
#include <vector>
#if defined(WIN32)
#include <windows.h>
#endif
#ifdef HAS_LIBVLC
#include <vlc/vlc.h>
#endif
struct ctx {
GLuint textureId; // Texture ID
SDL_Surface *surf;
SDL_mutex *mutex;
int width;
int height;
void *rawData;
};
// Load a texture
static void loadTexture(struct ctx *ctx) {
void *rawData = ctx->rawData;
Uint8 * pixelSource = 0;
Uint8 * pixelDestination = (Uint8 *) rawData;
Uint32 pix = 0;
for (unsigned int i = ctx->height; i > 0; i--) {
for (unsigned int j = 0; j < ctx->width; j++) {
pixelSource = (Uint8 *) ctx->surf->pixels + (i-1) * ctx->surf->pitch + j * 2;
pix = *(Uint16 *) pixelSource;
SDL_GetRGBA(pix, ctx->surf->format, &(pixelDestination[0]), &(pixelDestination[1]), &(pixelDestination[2]), &(pixelDestination[3]));
pixelDestination += 4;
}
}
// Building the texture
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, ctx->textureId);
glTexImage2D(GL_TEXTURE_2D, 0, 4, ctx->width, ctx->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (Uint8 *) rawData);
}
static void *lock(void *data, void **p_pixels) {
struct ctx *ctx = (struct ctx *)data;
SDL_LockMutex(ctx->mutex);
SDL_LockSurface(ctx->surf);
*p_pixels = ctx->surf->pixels;
return NULL; /* picture identifier, not needed here */
}
static void unlock(void *data, void *id, void *const *p_pixels) {
struct ctx *ctx = (struct ctx *)data;
/* VLC just rendered the video, but we can also render stuff */
SDL_UnlockSurface(ctx->surf);
SDL_UnlockMutex(ctx->mutex);
}
static void display(void *data, void *id) {
/* VLC wants to display the video */
(void) data;
}
VideoPlayer::VideoPlayer(string filename, SDL_Surface *surface,
int width, int height,int colorBits,string pluginsPath) {
this->filename = filename;
this->surface = surface;
this->width = width;
this->height = height;
this->colorBits = colorBits;
this->pluginsPath = pluginsPath;
this->stop = false;
}
VideoPlayer::~VideoPlayer() {
}
bool VideoPlayer::hasBackEndVideoPlayer() {
#ifdef HAS_LIBVLC
return true;
#endif
return false;
}
void VideoPlayer::PlayVideo() {
#ifdef HAS_LIBVLC
libvlc_instance_t *libvlc = NULL;
libvlc_media_t *m = NULL;
libvlc_media_player_t *mp = NULL;
// string pluginParam = "";
// if(pluginsPath != "") {
// pluginParam = "--plugin-path=" + pluginsPath;
// }
std::vector<const char *> vlc_argv;
vlc_argv.push_back("--no-xlib" /* tell VLC to not use Xlib */);
vlc_argv.push_back("--no-video-title-show");
// vlc_argv.push_back(pluginParam.c_str());
int vlc_argc = vlc_argv.size();
// char const *vlc_argv[] =
// {
// //"--no-audio", /* skip any audio track */
// "--no-xlib", /* tell VLC to not use Xlib */
// "--no-video-title-show",
// pluginParam.c_str(),
// };
// int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv);
#endif
SDL_Surface *empty = NULL;
SDL_Event event;
int done = 0, action = 0, pause = 0, n = 0;
struct ctx ctx;
ctx.width = width;
ctx.height = height;
ctx.rawData = (void *) malloc(width * height * 4);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
// Init Texture
glGenTextures(1, &ctx.textureId);
glBindTexture(GL_TEXTURE_2D, ctx.textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
empty = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
colorBits, 0, 0, 0, 0);
ctx.surf = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
colorBits, 0x001f, 0x07e0, 0xf800, 0);
ctx.mutex = SDL_CreateMutex();
bool successLoadingVLC = false;
#ifdef HAS_LIBVLC
/*
* Initialise libVLC
*/
libvlc = libvlc_new(vlc_argc, &vlc_argv[0]);
if(libvlc == NULL) {
// For windows check registry for install path
#if defined(WIN32) && !defined(__MINGW32__)
//Open the registry key.
wstring subKey = L"Software\\VideoLAN\\VLC";
HKEY keyHandle;
//DWORD dwDisposition;
LONG lres = RegOpenKeyEx(HKEY_LOCAL_MACHINE,subKey.c_str(),0, KEY_READ, &keyHandle);
if(lres == ERROR_SUCCESS) {
std::string strValue;
//GetStringRegKey(keyHandle, L"", strValue, L"");
char szBuffer[4096];
DWORD dwBufferSize = sizeof(szBuffer);
ULONG nError = RegQueryValueEx(keyHandle, L"", 0, NULL, (LPBYTE)szBuffer, &dwBufferSize);
if (ERROR_SUCCESS == nError) {
strValue = szBuffer;
}
RegCloseKey(keyHandle);
if(strValue != "") {
#if defined(WIN32)
strValue = "VLC_PLUGIN_PATH=" + strValue;
_putenv(strValue.c_str());
#else
setenv("VLC_PLUGIN_PATH",strValue.c_str(),1);
#endif
libvlc = libvlc_new(vlc_argc, &vlc_argv[0]);
}
}
#endif
if(libvlc == NULL) {
#if defined(WIN32)
_putenv("VLC_PLUGIN_PATH=c:\\program files\\videolan\\vlc\\plugins");
#else
setenv("VLC_PLUGIN_PATH","c:\\program files\\videolan\\vlc\\plugins",1);
#endif
libvlc = libvlc_new(vlc_argc, &vlc_argv[0]);
}
if(libvlc == NULL) {
#if defined(WIN32)
_putenv("VLC_PLUGIN_PATH=\\program files\\videolan\\vlc\\plugins");
#else
setenv("VLC_PLUGIN_PATH","\\program files\\videolan\\vlc\\plugins",1);
#endif
libvlc = libvlc_new(vlc_argc, &vlc_argv[0]);
if(libvlc == NULL) {
#if defined(WIN32)
_putenv("VLC_PLUGIN_PATH=c:\\program files (x86)\\videolan\\vlc\\plugins");
#else
setenv("VLC_PLUGIN_PATH","c:\\program files (x86)\\videolan\\vlc\\plugins",1);
#endif
libvlc = libvlc_new(vlc_argc, &vlc_argv[0]);
if(libvlc == NULL) {
#if defined(WIN32)
_putenv("VLC_PLUGIN_PATH=\\program files (x86)\\videolan\\vlc\\plugins");
#else
setenv("VLC_PLUGIN_PATH","\\program files (x86)\\videolan\\vlc\\plugins",1);
#endif
libvlc = libvlc_new(vlc_argc, &vlc_argv[0]);
}
}
}
}
if(libvlc != NULL) {
m = libvlc_media_new_path(libvlc, filename.c_str());
mp = libvlc_media_player_new_from_media(m);
libvlc_media_release(m);
libvlc_video_set_callbacks(mp, lock, unlock, display, &ctx);
libvlc_video_set_format(mp, "RV16", width, height, this->surface->pitch);
libvlc_media_player_play(mp);
successLoadingVLC = true;
}
#endif
/*
* Main loop
*/
bool needToQuit = false;
while(successLoadingVLC == true && !done && stop == false) {
action = 0;
/* Keys: enter (fullscreen), space (pause), escape (quit) */
while( SDL_PollEvent( &event ) ) {
switch(event.type) {
case SDL_QUIT:
done = 1;
needToQuit = true;
break;
case SDL_KEYDOWN:
action = event.key.keysym.sym;
break;
case SDL_MOUSEBUTTONDOWN:
done = 1;
break;
}
}
if(!done && stop == false) {
switch(action) {
case SDLK_ESCAPE:
done = 1;
break;
case SDLK_RETURN:
//options ^= SDL_FULLSCREEN;
//screen = SDL_SetVideoMode(WIDTH, HEIGHT, 0, options);
done = 1;
break;
case ' ':
//pause = !pause;
break;
}
if(!pause) {
n++;
}
loadTexture(&ctx); // Loading the texture
// Square
glBegin(GL_QUADS);
glTexCoord2d(0, 1);
glVertex2f(-0.85, 0.85);
glTexCoord2d(1, 1);
glVertex2f(0.85, 0.85);
glTexCoord2d(1, 0);
glVertex2f(0.85, -0.85);
glTexCoord2d(0, 0);
glVertex2f(-0.85, -0.85);
glEnd();
SDL_GL_SwapBuffers();
}
}
#ifdef HAS_LIBVLC
if(libvlc != NULL) {
/*
* Stop stream and clean up libVLC
*/
libvlc_media_player_stop(mp);
libvlc_media_player_release(mp);
libvlc_release(libvlc);
}
#endif
/*
* Close window and clean up libSDL
*/
SDL_DestroyMutex(ctx.mutex);
SDL_FreeSurface(ctx.surf);
SDL_FreeSurface(empty);
glDeleteTextures(1, &ctx.textureId);
free(ctx.rawData);
if(needToQuit == true) {
SDL_Event quit_event = {SDL_QUIT};
SDL_PushEvent(&quit_event);
}
}