generic-pc: rework glfb (thx seife)

This commit is contained in:
max_10
2018-09-21 19:00:11 +02:00
committed by Thilo Graf
parent c8c7f0c45f
commit cf45b80334
6 changed files with 191 additions and 114 deletions

View File

@@ -38,8 +38,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <linux/input.h> #include <linux/input.h>
#include "glfb.h" #include "glfb_priv.h"
#include <GL/glx.h>
#include "video_lib.h" #include "video_lib.h"
#include "audio_lib.h" #include "audio_lib.h"
@@ -54,10 +53,36 @@
extern cVideo *videoDecoder; extern cVideo *videoDecoder;
extern cAudio *audioDecoder; extern cAudio *audioDecoder;
static GLFramebuffer *gThiz = 0; /* GLUT does not allow for an arbitrary argument to the render func */ /* the private class that does stuff only needed inside libstb-hal.
* is used e.g. by cVideo... */
GLFbPC *glfb_priv = NULL;
GLFramebuffer::GLFramebuffer(int x, int y): mReInit(true), mShutDown(false), mInitDone(false) GLFramebuffer::GLFramebuffer(int x, int y)
{ {
Init();
glfb_priv = new GLFbPC(x, y, osd_buf);
si = glfb_priv->getScreenInfo();
start();
while (!glfb_priv->mInitDone)
usleep(1);
}
GLFramebuffer::~GLFramebuffer()
{
glfb_priv->mShutDown = true;
join();
delete glfb_priv;
glfb_priv = NULL;
}
void GLFramebuffer::blit()
{
glfb_priv->blit();
}
GLFbPC::GLFbPC(int x, int y, std::vector<unsigned char> &buf): mReInit(true), mShutDown(false), mInitDone(false)
{
osd_buf = &buf;
mState.width = x; mState.width = x;
mState.height = y; mState.height = y;
mX = &_mX[0]; mX = &_mX[0];
@@ -78,19 +103,19 @@ GLFramebuffer::GLFramebuffer(int x, int y): mReInit(true), mShutDown(false), mIn
last_apts = 0; last_apts = 0;
/* linux framebuffer compat mode */ /* linux framebuffer compat mode */
screeninfo.bits_per_pixel = 32; si.bits_per_pixel = 32;
screeninfo.xres = mState.width; si.xres = mState.width;
screeninfo.xres_virtual = screeninfo.xres; si.xres_virtual = si.xres;
screeninfo.yres = mState.height; si.yres = mState.height;
screeninfo.yres_virtual = screeninfo.yres; si.yres_virtual = si.yres;
screeninfo.blue.length = 8; si.blue.length = 8;
screeninfo.blue.offset = 0; si.blue.offset = 0;
screeninfo.green.length = 8; si.green.length = 8;
screeninfo.green.offset = 8; si.green.offset = 8;
screeninfo.red.length = 8; si.red.length = 8;
screeninfo.red.offset = 16; si.red.offset = 16;
screeninfo.transp.length = 8; si.transp.length = 8;
screeninfo.transp.offset = 24; si.transp.offset = 24;
unlink("/tmp/neutrino.input"); unlink("/tmp/neutrino.input");
mkfifo("/tmp/neutrino.input", 0600); mkfifo("/tmp/neutrino.input", 0600);
@@ -98,21 +123,22 @@ GLFramebuffer::GLFramebuffer(int x, int y): mReInit(true), mShutDown(false), mIn
if (input_fd < 0) if (input_fd < 0)
lt_info("%s: could not open /tmp/neutrino.input FIFO: %m\n", __func__); lt_info("%s: could not open /tmp/neutrino.input FIFO: %m\n", __func__);
initKeys(); initKeys();
OpenThreads::Thread::start();
while (!mInitDone)
usleep(1);
} }
GLFramebuffer::~GLFramebuffer() GLFbPC::~GLFbPC()
{ {
mShutDown = true; mShutDown = true;
OpenThreads::Thread::join();
if (input_fd >= 0) if (input_fd >= 0)
close(input_fd); close(input_fd);
osd_buf->clear();
} }
void GLFramebuffer::initKeys() void GLFbPC::initKeys()
{ {
/*
Keep in sync with initKeys() in clutterfb.cpp
*/
mSpecialMap[GLUT_KEY_UP] = KEY_UP; mSpecialMap[GLUT_KEY_UP] = KEY_UP;
mSpecialMap[GLUT_KEY_DOWN] = KEY_DOWN; mSpecialMap[GLUT_KEY_DOWN] = KEY_DOWN;
mSpecialMap[GLUT_KEY_LEFT] = KEY_LEFT; mSpecialMap[GLUT_KEY_LEFT] = KEY_LEFT;
@@ -133,8 +159,8 @@ void GLFramebuffer::initKeys()
mSpecialMap[GLUT_KEY_F11] = KEY_NEXT; mSpecialMap[GLUT_KEY_F11] = KEY_NEXT;
mSpecialMap[GLUT_KEY_F12] = KEY_PREVIOUS; mSpecialMap[GLUT_KEY_F12] = KEY_PREVIOUS;
mSpecialMap[GLUT_KEY_PAGE_UP] = KEY_PAGEUP; mSpecialMap[GLUT_KEY_PAGE_UP] = KEY_PAGEUP;
mSpecialMap[GLUT_KEY_PAGE_DOWN] = KEY_PAGEDOWN; mSpecialMap[GLUT_KEY_PAGE_DOWN] = KEY_PAGEDOWN;
mKeyMap[0x0d] = KEY_OK; mKeyMap[0x0d] = KEY_OK;
mKeyMap[0x1b] = KEY_EXIT; mKeyMap[0x1b] = KEY_EXIT;
@@ -177,9 +203,21 @@ void GLFramebuffer::initKeys()
void GLFramebuffer::run() void GLFramebuffer::run()
{ {
setupCtx(); int argc = 1;
setupOSDBuffer(); int x = glfb_priv->mState.width;
mInitDone = true; /* signal that setup is finished */ int y = glfb_priv->mState.height;
/* some dummy commandline for GLUT to be happy */
char const *argv[2] = { "neutrino", 0 };
lt_info("GLFB: GL thread starting x %d y %d\n", x, y);
glutInit(&argc, const_cast<char **>(argv));
glutInitWindowSize(x, y);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Neutrino");
/* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */
int fbmem = x * y * 4 * 2;
osd_buf.resize(fbmem);
lt_info("GLFB: OSD buffer set to %d bytes at 0x%p\n", fbmem, osd_buf.data());
glfb_priv->mInitDone = true; /* signal that setup is finished */
/* init the good stuff */ /* init the good stuff */
GLenum err = glewInit(); GLenum err = glewInit();
@@ -194,16 +232,15 @@ void GLFramebuffer::run()
} }
else else
{ {
gThiz = this;
glutSetCursor(GLUT_CURSOR_NONE); glutSetCursor(GLUT_CURSOR_NONE);
glutDisplayFunc(GLFramebuffer::rendercb); glutDisplayFunc(GLFbPC::rendercb);
glutKeyboardFunc(GLFramebuffer::keyboardcb); glutKeyboardFunc(GLFbPC::keyboardcb);
glutSpecialFunc(GLFramebuffer::specialcb); glutSpecialFunc(GLFbPC::specialcb);
glutReshapeFunc(GLFramebuffer::resizecb); glutReshapeFunc(GLFbPC::resizecb);
setupGLObjects(); /* needs GLEW prototypes */ glfb_priv->setupGLObjects(); /* needs GLEW prototypes */
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION); glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
glutMainLoop(); glutMainLoop();
releaseGLObjects(); glfb_priv->releaseGLObjects();
} }
} }
else else
@@ -211,21 +248,20 @@ void GLFramebuffer::run()
lt_info("GLFB: GL thread stopping\n"); lt_info("GLFB: GL thread stopping\n");
} }
#if 0
void GLFramebuffer::setupCtx() void GLFbPC::setupCtx()
{ {
int argc = 1; int argc = 1;
/* some dummy commandline for GLUT to be happy */ /* some dummy commandline for GLUT to be happy */
char const *argv[2] = { "neutrino", 0 }; char const *argv[2] = { "neutrino", 0 };
lt_info("GLFB: GL thread starting\n"); lt_info("GLFB: GL thread starting x %d y %d\n", mX[0], mY[0]);
glutInit(&argc, const_cast<char **>(argv)); glutInit(&argc, const_cast<char **>(argv));
glutInitWindowSize(mX[0], mY[0]); glutInitWindowSize(mX[0], mY[0]);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("Neutrino"); glutCreateWindow("Neutrino");
GLWinID = glXGetCurrentDrawable(); // this was the holy grail to get the right window handle for gstreamer :D
} }
void GLFramebuffer::setupOSDBuffer() void GLFbPC::setupOSDBuffer()
{ /* the OSD buffer size can be decoupled from the actual { /* the OSD buffer size can be decoupled from the actual
window size since the GL can blit-stretch with no window size since the GL can blit-stretch with no
trouble at all, ah, the luxury of ignorance... */ trouble at all, ah, the luxury of ignorance... */
@@ -234,12 +270,13 @@ void GLFramebuffer::setupOSDBuffer()
{ {
/* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */ /* 32bit FB depth, *2 because tuxtxt uses a shadow buffer */
int fbmem = mState.width * mState.height * 4 * 2; int fbmem = mState.width * mState.height * 4 * 2;
mOSDBuffer.resize(fbmem); osd_buf->resize(fbmem);
lt_info("GLFB: OSD buffer set to %d bytes\n", fbmem); lt_info("GLFB: OSD buffer set to %d bytes at 0x%p\n", fbmem, osd_buf->data());
} }
} }
#endif
void GLFramebuffer::setupGLObjects() void GLFbPC::setupGLObjects()
{ {
unsigned char buf[4] = { 0, 0, 0, 0 }; /* 1 black pixel */ unsigned char buf[4] = { 0, 0, 0, 0 }; /* 1 black pixel */
glGenTextures(1, &mState.osdtex); glGenTextures(1, &mState.osdtex);
@@ -267,7 +304,7 @@ void GLFramebuffer::setupGLObjects()
} }
void GLFramebuffer::releaseGLObjects() void GLFbPC::releaseGLObjects()
{ {
glDeleteBuffers(1, &mState.pbo); glDeleteBuffers(1, &mState.pbo);
glDeleteBuffers(1, &mState.displaypbo); glDeleteBuffers(1, &mState.displaypbo);
@@ -276,56 +313,56 @@ void GLFramebuffer::releaseGLObjects()
} }
/* static */ void GLFramebuffer::rendercb() /* static */ void GLFbPC::rendercb()
{ {
gThiz->render(); glfb_priv->render();
} }
/* static */ void GLFramebuffer::keyboardcb(unsigned char key, int /*x*/, int /*y*/) /* static */ void GLFbPC::keyboardcb(unsigned char key, int /*x*/, int /*y*/)
{ {
lt_debug_c("GLFB::%s: 0x%x\n", __func__, key); lt_debug_c("GLFB::%s: 0x%x\n", __func__, key);
struct input_event ev; struct input_event ev;
if (key == 'f') if (key == 'f')
{ {
lt_info_c("GLFB::%s: toggle fullscreen %s\n", __func__, gThiz->mFullscreen?"off":"on"); lt_info_c("GLFB::%s: toggle fullscreen %s\n", __func__, glfb_priv->mFullscreen?"off":"on");
gThiz->mFullscreen = !(gThiz->mFullscreen); glfb_priv->mFullscreen = !(glfb_priv->mFullscreen);
gThiz->mReInit = true; glfb_priv->mReInit = true;
return; return;
} }
std::map<unsigned char, int>::const_iterator i = gThiz->mKeyMap.find(key); std::map<unsigned char, int>::const_iterator i = glfb_priv->mKeyMap.find(key);
if (i == gThiz->mKeyMap.end()) if (i == glfb_priv->mKeyMap.end())
return; return;
ev.code = i->second; ev.code = i->second;
ev.value = 1; /* key own */ ev.value = 1; /* key own */
ev.type = EV_KEY; ev.type = EV_KEY;
gettimeofday(&ev.time, NULL); gettimeofday(&ev.time, NULL);
lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code); lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
write(gThiz->input_fd, &ev, sizeof(ev)); write(glfb_priv->input_fd, &ev, sizeof(ev));
ev.value = 0; /* neutrino is stupid, so push key up directly after key down */ ev.value = 0; /* neutrino is stupid, so push key up directly after key down */
write(gThiz->input_fd, &ev, sizeof(ev)); write(glfb_priv->input_fd, &ev, sizeof(ev));
} }
/* static */ void GLFramebuffer::specialcb(int key, int /*x*/, int /*y*/) /* static */ void GLFbPC::specialcb(int key, int /*x*/, int /*y*/)
{ {
lt_debug_c("GLFB::%s: 0x%x\n", __func__, key); lt_debug_c("GLFB::%s: 0x%x\n", __func__, key);
struct input_event ev; struct input_event ev;
std::map<int, int>::const_iterator i = gThiz->mSpecialMap.find(key); std::map<int, int>::const_iterator i = glfb_priv->mSpecialMap.find(key);
if (i == gThiz->mSpecialMap.end()) if (i == glfb_priv->mSpecialMap.end())
return; return;
ev.code = i->second; ev.code = i->second;
ev.value = 1; ev.value = 1;
ev.type = EV_KEY; ev.type = EV_KEY;
gettimeofday(&ev.time, NULL); gettimeofday(&ev.time, NULL);
lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code); lt_debug_c("GLFB::%s: pushing 0x%x\n", __func__, ev.code);
write(gThiz->input_fd, &ev, sizeof(ev)); write(glfb_priv->input_fd, &ev, sizeof(ev));
ev.value = 0; ev.value = 0;
write(gThiz->input_fd, &ev, sizeof(ev)); write(glfb_priv->input_fd, &ev, sizeof(ev));
} }
int sleep_us = 30000; int sleep_us = 30000;
void GLFramebuffer::render() void GLFbPC::render()
{ {
if(mShutDown) if(mShutDown)
glutLeaveMainLoop(); glutLeaveMainLoop();
@@ -453,12 +490,12 @@ void GLFramebuffer::render()
glutPostRedisplay(); glutPostRedisplay();
} }
/* static */ void GLFramebuffer::resizecb(int w, int h) /* static */ void GLFbPC::resizecb(int w, int h)
{ {
gThiz->checkReinit(w, h); glfb_priv->checkReinit(w, h);
} }
void GLFramebuffer::checkReinit(int x, int y) void GLFbPC::checkReinit(int x, int y)
{ {
static int last_x = 0, last_y = 0; static int last_x = 0, last_y = 0;
@@ -478,7 +515,7 @@ void GLFramebuffer::checkReinit(int x, int y)
last_y = y; last_y = y;
} }
void GLFramebuffer::drawSquare(float size, float x_factor) void GLFbPC::drawSquare(float size, float x_factor)
{ {
GLfloat vertices[] = { GLfloat vertices[] = {
1.0f, 1.0f, 1.0f, 1.0f,
@@ -534,11 +571,11 @@ void GLFramebuffer::drawSquare(float size, float x_factor)
} }
void GLFramebuffer::bltOSDBuffer() void GLFbPC::bltOSDBuffer()
{ {
/* FIXME: copy each time */ /* FIXME: copy each time */
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mState.pbo); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, mState.pbo);
glBufferData(GL_PIXEL_UNPACK_BUFFER, mOSDBuffer.size(), &mOSDBuffer[0], GL_STREAM_DRAW_ARB); glBufferData(GL_PIXEL_UNPACK_BUFFER, osd_buf->size(), osd_buf->data(), GL_STREAM_DRAW_ARB);
glBindTexture(GL_TEXTURE_2D, mState.osdtex); glBindTexture(GL_TEXTURE_2D, mState.osdtex);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mState.width, mState.height, GL_BGRA, GL_UNSIGNED_BYTE, 0); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mState.width, mState.height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
@@ -546,7 +583,7 @@ void GLFramebuffer::bltOSDBuffer()
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
} }
void GLFramebuffer::bltDisplayBuffer() void GLFbPC::bltDisplayBuffer()
{ {
if (!videoDecoder) /* cannot start yet */ if (!videoDecoder) /* cannot start yet */
return; return;
@@ -554,7 +591,7 @@ void GLFramebuffer::bltDisplayBuffer()
cVideo::SWFramebuffer *buf = videoDecoder->getDecBuf(); cVideo::SWFramebuffer *buf = videoDecoder->getDecBuf();
if (!buf) { if (!buf) {
if (warn) if (warn)
lt_debug("GLFB::%s did not get a buffer...\n", __func__); lt_info("GLFB::%s did not get a buffer...\n", __func__);
warn = false; warn = false;
return; return;
} }
@@ -607,9 +644,3 @@ void GLFramebuffer::bltDisplayBuffer()
lt_debug("vpts: 0x%" PRIx64 " apts: 0x%" PRIx64 " diff: %6.3f sleep_us %d buf %d\n", lt_debug("vpts: 0x%" PRIx64 " apts: 0x%" PRIx64 " diff: %6.3f sleep_us %d buf %d\n",
buf->pts(), apts, (buf->pts() - apts)/90000.0, sleep_us, videoDecoder->buf_num); buf->pts(), apts, (buf->pts() - apts)/90000.0, sleep_us, videoDecoder->buf_num);
} }
void GLFramebuffer::clear()
{
/* clears front and back buffer */
memset(&mOSDBuffer[0], 0, mOSDBuffer.size());
}

View File

@@ -14,12 +14,14 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
********************************************************************
private stuff of the GLFB thread that is only used inside libstb-hal
and not exposed to the application.
*/ */
#ifndef __glthread__ #ifndef __glfb_priv__
#define __glthread__ #define __glfb_priv__
#include <config.h>
#include <OpenThreads/Thread>
#include <OpenThreads/Mutex> #include <OpenThreads/Mutex>
#include <vector> #include <vector>
#include <map> #include <map>
@@ -32,28 +34,26 @@
#if USE_CLUTTER #if USE_CLUTTER
#include <clutter/clutter.h> #include <clutter/clutter.h>
#endif #endif
#include "glfb.h"
extern "C" { extern "C" {
#include <libavutil/rational.h> #include <libavutil/rational.h>
} }
class GLFramebuffer : public OpenThreads::Thread class GLFbPC
{ {
public: public:
GLFramebuffer(int x, int y); GLFbPC(int x, int y, std::vector<unsigned char> &buf);
~GLFramebuffer(); ~GLFbPC();
void run(); std::vector<unsigned char> *getOSDBuffer() { return osd_buf; } /* pointer to OSD bounce buffer */
std::vector<unsigned char> *getOSDBuffer() { return &mOSDBuffer; } /* pointer to OSD bounce buffer */
int getOSDWidth() { return mState.width; } int getOSDWidth() { return mState.width; }
int getOSDHeight() { return mState.height; } int getOSDHeight() { return mState.height; }
void blit() { mState.blit = true; } void blit() { mState.blit = true; };
fb_var_screeninfo getScreenInfo() { return screeninfo; } fb_var_screeninfo getScreenInfo() { return si; }
void setOutputFormat(AVRational a, int h, int c) { mOA = a; *mY = h; mCrop = c; mReInit = true; } void setOutputFormat(AVRational a, int h, int c) { mOA = a; *mY = h; mCrop = c; mReInit = true; }
/* just make everything public for simplicity - this is only used inside libstb-hal anyway
void clear();
int getWindowID() { return GLWinID; }
private: private:
fb_var_screeninfo screeninfo; */
fb_var_screeninfo si;
int *mX; int *mX;
int *mY; int *mY;
int _mX[2]; /* output window size */ int _mX[2]; /* output window size */
@@ -65,7 +65,6 @@ private:
float zoom; /* for cropping */ float zoom; /* for cropping */
float xscale; /* and aspect ratio */ float xscale; /* and aspect ratio */
int mCrop; /* DISPLAY_AR_MODE */ int mCrop; /* DISPLAY_AR_MODE */
int GLWinID;
bool mFullscreen; /* fullscreen? */ bool mFullscreen; /* fullscreen? */
bool mReInit; /* setup things for GL */ bool mReInit; /* setup things for GL */
@@ -75,7 +74,7 @@ private:
// OpenThreads::Condition mInitCond; /* condition variable for init */ // OpenThreads::Condition mInitCond; /* condition variable for init */
// mutable OpenThreads::Mutex mMutex; /* lock our data */ // mutable OpenThreads::Mutex mMutex; /* lock our data */
std::vector<unsigned char> mOSDBuffer; /* silly bounce buffer */ std::vector<unsigned char> *osd_buf; /* silly bounce buffer */
#if USE_OPENGL #if USE_OPENGL
std::map<unsigned char, int> mKeyMap; std::map<unsigned char, int> mKeyMap;
@@ -86,6 +85,7 @@ private:
#endif #endif
int input_fd; int input_fd;
int64_t last_apts; int64_t last_apts;
void run();
static void rendercb(); /* callback for GLUT */ static void rendercb(); /* callback for GLUT */
void render(); /* actual render function */ void render(); /* actual render function */
@@ -103,8 +103,10 @@ private:
#endif #endif
void initKeys(); /* setup key bindings for window */ void initKeys(); /* setup key bindings for window */
#if 0
void setupCtx(); /* create the window and make the context current */ void setupCtx(); /* create the window and make the context current */
void setupOSDBuffer(); /* create the OSD buffer */ void setupOSDBuffer(); /* create the OSD buffer */
#endif
struct { struct {
int width; /* width and height, fixed for a framebuffer instance */ int width; /* width and height, fixed for a framebuffer instance */

View File

@@ -1,4 +1,5 @@
#include <cstring> #include <cstring>
#include <cstdlib>
#include <unistd.h> #include <unistd.h>
#include "init_td.h" #include "init_td.h"

View File

@@ -49,7 +49,7 @@ extern "C" {
#include "video_lib.h" #include "video_lib.h"
#include "dmx_hal.h" #include "dmx_hal.h"
#include "glfb.h" #include "glfb_priv.h"
#include "lt_debug.h" #include "lt_debug.h"
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args) #define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_VIDEO, this, args)
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args) #define lt_info(args...) _lt_info(TRIPLE_DEBUG_VIDEO, this, args)
@@ -57,7 +57,7 @@ extern "C" {
cVideo *videoDecoder = NULL; cVideo *videoDecoder = NULL;
extern cDemux *videoDemux; extern cDemux *videoDemux;
extern GLFramebuffer *glfb; extern GLFbPC *glfb_priv;
int system_rev = 0; int system_rev = 0;
extern bool HAL_nodec; extern bool HAL_nodec;
@@ -111,7 +111,7 @@ int cVideo::setAspectRatio(int vformat, int cropping)
if (cropping >= 0) if (cropping >= 0)
display_crop = (DISPLAY_AR_MODE) cropping; display_crop = (DISPLAY_AR_MODE) cropping;
if (display_aspect < DISPLAY_AR_RAW && output_h > 0) /* don't know what to do with this */ if (display_aspect < DISPLAY_AR_RAW && output_h > 0) /* don't know what to do with this */
glfb->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop); glfb_priv->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop);
return 0; return 0;
} }
@@ -222,7 +222,7 @@ int cVideo::SetVideoSystem(int system, bool)
// v_std = (VIDEO_STD) system; // v_std = (VIDEO_STD) system;
output_h = h; output_h = h;
if (display_aspect < DISPLAY_AR_RAW && output_h > 0) /* don't know what to do with this */ if (display_aspect < DISPLAY_AR_RAW && output_h > 0) /* don't know what to do with this */
glfb->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop); glfb_priv->setOutputFormat(aspect_ratios[display_aspect], output_h, display_crop);
return 0; return 0;
} }
@@ -369,6 +369,7 @@ void cVideo::Pig(int x, int y, int w, int h, int /*osd_w*/, int /*osd_h*/, int /
pig_y = y; pig_y = y;
pig_w = w; pig_w = w;
pig_h = h; pig_h = h;
pig_changed = true;
} }
void cVideo::getPictureInfo(int &width, int &height, int &rate) void cVideo::getPictureInfo(int &width, int &height, int &rate)
@@ -572,10 +573,18 @@ void cVideo::run(void)
f->width(c->width); f->width(c->width);
f->height(c->height); f->height(c->height);
int64_t vpts = av_frame_get_best_effort_timestamp(frame); int64_t vpts = av_frame_get_best_effort_timestamp(frame);
/* a/v delay determined experimentally :-) */
#if USE_OPENGL
if (v_format == VIDEO_FORMAT_MPEG2) if (v_format == VIDEO_FORMAT_MPEG2)
vpts += 90000*4/10; /* 400ms */ vpts += 90000*4/10; /* 400ms */
else else
vpts += 90000*3/10; /* 300ms */ vpts += 90000*3/10; /* 300ms */
#endif
#if USE_CLUTTER
/* no idea why there's a difference between OpenGL and clutter rendering... */
if (v_format == VIDEO_FORMAT_MPEG2)
vpts += 90000*3/10; /* 300ms */
#endif
f->pts(vpts); f->pts(vpts);
AVRational a = av_guess_sample_aspect_ratio(avfc, avfc->streams[0], frame); AVRational a = av_guess_sample_aspect_ratio(avfc, avfc->streams[0], frame);
f->AR(a); f->AR(a);
@@ -675,8 +684,8 @@ bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool ge
std::vector<unsigned char> *osd = NULL; std::vector<unsigned char> *osd = NULL;
std::vector<unsigned char> s_osd; /* scaled OSD */ std::vector<unsigned char> s_osd; /* scaled OSD */
int vid_w = 0, vid_h = 0; int vid_w = 0, vid_h = 0;
int osd_w = glfb->getOSDWidth(); int osd_w = glfb_priv->getOSDWidth();
int osd_h = glfb->getOSDHeight(); int osd_h = glfb_priv->getOSDHeight();
xres = osd_w; xres = osd_w;
yres = osd_h; yres = osd_h;
if (get_video) { if (get_video) {
@@ -700,24 +709,26 @@ bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool ge
yres = osd_h; yres = osd_h;
} }
if (get_osd) if (get_osd)
osd = glfb->getOSDBuffer(); osd = glfb_priv->getOSDBuffer();
unsigned int need = av_image_get_buffer_size(AV_PIX_FMT_RGB32, xres, yres, 1); unsigned int need = av_image_get_buffer_size(AV_PIX_FMT_RGB32, xres, yres, 1);
data = (unsigned char *)realloc(data, need); /* will be freed by caller */ data = (unsigned char *)realloc(data, need); /* will be freed by caller */
if (data == NULL) /* out of memory? */ if (data == NULL) /* out of memory? */
return false; return false;
if (get_video) { if (get_video) {
//memcpy dont work with copy BGR24 to RGB32 #if USE_OPENGL //memcpy dont work with copy BGR24 to RGB32
if (vid_w != xres || vid_h != yres){ /* scale video into data... */ if (vid_w != xres || vid_h != yres){ /* scale video into data... */
bool ret = swscale(&video[0], data, vid_w, vid_h, xres, yres, AV_PIX_FMT_RGB32); #endif
bool ret = swscale(&video[0], data, vid_w, vid_h, xres, yres,VDEC_PIXFMT);
if(!ret){ if(!ret){
free(data); free(data);
return false; return false;
} }
//memcpy dont work with copy BGR24 to RGB32 #if USE_OPENGL //memcpy dont work with copy BGR24 to RGB32
} else { /* get_video and no fancy scaling needed */ }else{ /* get_video and no fancy scaling needed */
memcpy(data, &video[0], xres * yres * sizeof(uint32_t)); memcpy(data, &video[0], xres * yres * sizeof(uint32_t));
} }
#endif
} }
if (get_osd && (osd_w != xres || osd_h != yres)) { if (get_osd && (osd_w != xres || osd_h != yres)) {

View File

@@ -120,10 +120,10 @@ typedef enum
} VIDEO_CONTROL; } VIDEO_CONTROL;
#define VDEC_MAXBUFS 0x30 #define VDEC_MAXBUFS 0x40
class cVideo : public OpenThreads::Thread class cVideo : public OpenThreads::Thread
{ {
friend class GLFramebuffer; friend class GLFbPC;
friend class cDemux; friend class cDemux;
private: private:
/* called from GL thread */ /* called from GL thread */

View File

@@ -1,10 +1,42 @@
#include <config.h> /*
#if HAVE_GENERIC_HARDWARE Copyright 2010 Carsten Juttner <carjay@gmx.net>
#if BOXMODEL_RASPI Copyright 2012,2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
#include "../raspi/glfb.h"
#else This program is free software; you can redistribute it and/or modify
#include "../generic-pc/glfb.h" it under the terms of the GNU General Public License as published by
#endif the Free Software Foundation; either version 2 of the License, or
#else (at your option) any later version.
#error glfb.h only works with HAVE_GENERIC_HARDWARE defined
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __glfb__
#define __glfb__
#include <OpenThreads/Thread>
#include <vector>
#include <linux/fb.h> /* for screeninfo etc. */
class GLFramebuffer : public OpenThreads::Thread
{
public:
GLFramebuffer(int x, int y);
~GLFramebuffer();
std::vector<unsigned char> *getOSDBuffer() { return &osd_buf; } /* pointer to OSD bounce buffer */
void blit();
fb_var_screeninfo getScreenInfo() { return si; }
private:
fb_var_screeninfo si;
std::vector<unsigned char> osd_buf; /* silly bounce buffer */
void run(); /* for OpenThreads::Thread */
void setup();
void blit_osd();
void *pdata; /* not yet used */
};
#endif #endif