mirror of
https://github.com/tuxbox-neutrino/libstb-hal.git
synced 2025-08-27 07:23:11 +02:00
generic-pc: rework glfb / cVideo internals
* hide implementation details in private classes / objects * remove unneccessary internals from library include files The goal is to finally have identical include files for all platforms to faciliate easy cross-platform library installation.
This commit is contained in:
@@ -36,8 +36,8 @@
|
|||||||
#include "lt_debug.h"
|
#include "lt_debug.h"
|
||||||
|
|
||||||
/* needed for getSTC :-( */
|
/* needed for getSTC :-( */
|
||||||
#include "video_lib.h"
|
#include "video_priv.h"
|
||||||
extern cVideo *videoDecoder;
|
extern VDec *vdec;
|
||||||
|
|
||||||
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_DEMUX, this, args)
|
#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_DEMUX, this, args)
|
||||||
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_DEMUX, this, args)
|
#define lt_info(args...) _lt_info(TRIPLE_DEBUG_DEMUX, this, args)
|
||||||
@@ -478,8 +478,8 @@ void cDemux::removePid(unsigned short Pid)
|
|||||||
void cDemux::getSTC(int64_t * STC)
|
void cDemux::getSTC(int64_t * STC)
|
||||||
{
|
{
|
||||||
int64_t pts = 0;
|
int64_t pts = 0;
|
||||||
if (videoDecoder)
|
if (vdec)
|
||||||
pts = videoDecoder->GetPTS();
|
pts = vdec->GetPTS();
|
||||||
*STC = pts;
|
*STC = pts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -37,8 +37,8 @@
|
|||||||
#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 "video_lib.h"
|
#include "video_priv.h"
|
||||||
#include "audio_lib.h"
|
#include "audio_lib.h"
|
||||||
|
|
||||||
#include "lt_debug.h"
|
#include "lt_debug.h"
|
||||||
@@ -49,13 +49,39 @@
|
|||||||
#define lt_info(args...) _lt_info(HAL_DEBUG_INIT, this, args)
|
#define lt_info(args...) _lt_info(HAL_DEBUG_INIT, this, args)
|
||||||
|
|
||||||
|
|
||||||
extern cVideo *videoDecoder;
|
extern VDec *vdec;
|
||||||
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];
|
||||||
@@ -76,19 +102,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);
|
||||||
@@ -96,20 +122,17 @@ 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()
|
||||||
{
|
{
|
||||||
mSpecialMap[GLUT_KEY_UP] = KEY_UP;
|
mSpecialMap[GLUT_KEY_UP] = KEY_UP;
|
||||||
mSpecialMap[GLUT_KEY_DOWN] = KEY_DOWN;
|
mSpecialMap[GLUT_KEY_DOWN] = KEY_DOWN;
|
||||||
@@ -155,9 +178,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();
|
||||||
@@ -172,16 +207,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
|
||||||
@@ -189,20 +223,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");
|
||||||
}
|
}
|
||||||
|
|
||||||
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... */
|
||||||
@@ -211,12 +245,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);
|
||||||
@@ -244,7 +279,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);
|
||||||
@@ -253,56 +288,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();
|
||||||
@@ -430,12 +465,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;
|
||||||
|
|
||||||
@@ -455,7 +490,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,
|
||||||
@@ -473,17 +508,17 @@ void GLFramebuffer::drawSquare(float size, float x_factor)
|
|||||||
1.0, 1.0,
|
1.0, 1.0,
|
||||||
};
|
};
|
||||||
if (x_factor > -99.0) { /* x_factor == -100 => OSD */
|
if (x_factor > -99.0) { /* x_factor == -100 => OSD */
|
||||||
if (videoDecoder &&
|
if (vdec &&
|
||||||
videoDecoder->pig_x > 0 && videoDecoder->pig_y > 0 &&
|
vdec->pig_x > 0 && vdec->pig_y > 0 &&
|
||||||
videoDecoder->pig_w > 0 && videoDecoder->pig_h > 0) {
|
vdec->pig_w > 0 && vdec->pig_h > 0) {
|
||||||
/* these calculations even consider cropping and panscan mode
|
/* these calculations even consider cropping and panscan mode
|
||||||
* maybe this could be done with some clever opengl tricks? */
|
* maybe this could be done with some clever opengl tricks? */
|
||||||
double w2 = (double)mState.width * 0.5l;
|
double w2 = (double)mState.width * 0.5l;
|
||||||
double h2 = (double)mState.height * 0.5l;
|
double h2 = (double)mState.height * 0.5l;
|
||||||
double x = (double)(videoDecoder->pig_x - w2) / w2 / x_factor / size;
|
double x = (double)(vdec->pig_x - w2) / w2 / x_factor / size;
|
||||||
double y = (double)(h2 - videoDecoder->pig_y) / h2 / size;
|
double y = (double)(h2 - vdec->pig_y) / h2 / size;
|
||||||
double w = (double)videoDecoder->pig_w / w2;
|
double w = (double)vdec->pig_w / w2;
|
||||||
double h = (double)videoDecoder->pig_h / h2;
|
double h = (double)vdec->pig_h / h2;
|
||||||
x += ((1.0l - x_factor * size) / 2.0l) * w / x_factor / size;
|
x += ((1.0l - x_factor * size) / 2.0l) * w / x_factor / size;
|
||||||
y += ((size - 1.0l) / 2.0l) * h / size;
|
y += ((size - 1.0l) / 2.0l) * h / size;
|
||||||
vertices[0] = x + w; /* top right x */
|
vertices[0] = x + w; /* top right x */
|
||||||
@@ -511,11 +546,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);
|
||||||
@@ -523,12 +558,12 @@ 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 (!vdec) /* cannot start yet */
|
||||||
return;
|
return;
|
||||||
static bool warn = true;
|
static bool warn = true;
|
||||||
cVideo::SWFramebuffer *buf = videoDecoder->getDecBuf();
|
VDec::SWFramebuffer *buf = vdec->getDecBuf();
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
if (warn)
|
if (warn)
|
||||||
lt_info("GLFB::%s did not get a buffer...\n", __func__);
|
lt_info("GLFB::%s did not get a buffer...\n", __func__);
|
||||||
@@ -560,8 +595,7 @@ void GLFramebuffer::bltDisplayBuffer()
|
|||||||
* this implementation is pretty naive and not working too well, but
|
* this implementation is pretty naive and not working too well, but
|
||||||
* better this than nothing... :-) */
|
* better this than nothing... :-) */
|
||||||
int64_t apts = 0;
|
int64_t apts = 0;
|
||||||
/* 18000 is the magic value for A/V sync in my libao->pulseaudio->intel_hda setup */
|
int64_t vpts = buf->pts();
|
||||||
int64_t vpts = buf->pts() + 18000;
|
|
||||||
if (audioDecoder)
|
if (audioDecoder)
|
||||||
apts = audioDecoder->getPts();
|
apts = audioDecoder->getPts();
|
||||||
if (apts != last_apts) {
|
if (apts != last_apts) {
|
||||||
@@ -571,7 +605,7 @@ void GLFramebuffer::bltDisplayBuffer()
|
|||||||
else if (sleep_us > 1000)
|
else if (sleep_us > 1000)
|
||||||
sleep_us -= 1000;
|
sleep_us -= 1000;
|
||||||
last_apts = apts;
|
last_apts = apts;
|
||||||
videoDecoder->getPictureInfo(dummy1, dummy2, rate);
|
vdec->getPictureInfo(dummy1, dummy2, rate);
|
||||||
if (rate > 0)
|
if (rate > 0)
|
||||||
rate = 2000000 / rate; /* limit to half the frame rate */
|
rate = 2000000 / rate; /* limit to half the frame rate */
|
||||||
else
|
else
|
||||||
@@ -582,11 +616,5 @@ void GLFramebuffer::bltDisplayBuffer()
|
|||||||
sleep_us = 1;
|
sleep_us = 1;
|
||||||
}
|
}
|
||||||
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, vdec->buf_num);
|
||||||
}
|
|
||||||
|
|
||||||
void GLFramebuffer::clear()
|
|
||||||
{
|
|
||||||
/* clears front and back buffer */
|
|
||||||
memset(&mOSDBuffer[0], 0, mOSDBuffer.size());
|
|
||||||
}
|
}
|
||||||
|
@@ -16,92 +16,25 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __glthread__
|
#ifndef __glfb__
|
||||||
#define __glthread__
|
#define __glfb__
|
||||||
#include <OpenThreads/Thread>
|
#include <OpenThreads/Thread>
|
||||||
#include <OpenThreads/Mutex>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
|
||||||
#include <GL/glew.h>
|
|
||||||
#include <GL/freeglut.h>
|
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <linux/fb.h> /* for screeninfo etc. */
|
#include <linux/fb.h> /* for screeninfo etc. */
|
||||||
extern "C" {
|
|
||||||
#include <libavutil/rational.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
class GLFramebuffer : public OpenThreads::Thread
|
class GLFramebuffer : public OpenThreads::Thread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GLFramebuffer(int x, int y);
|
GLFramebuffer(int x, int y);
|
||||||
~GLFramebuffer();
|
~GLFramebuffer();
|
||||||
|
std::vector<unsigned char> *getOSDBuffer() { return &osd_buf; } /* pointer to OSD bounce buffer */
|
||||||
void run();
|
void blit();
|
||||||
std::vector<unsigned char> *getOSDBuffer() { return &mOSDBuffer; } /* pointer to OSD bounce buffer */
|
fb_var_screeninfo getScreenInfo() { return si; }
|
||||||
|
|
||||||
int getOSDWidth() { return mState.width; }
|
|
||||||
int getOSDHeight() { return mState.height; }
|
|
||||||
void blit() { mState.blit = true; }
|
|
||||||
|
|
||||||
void setOutputFormat(AVRational a, int h, int c) { mOA = a; *mY = h; mCrop = c; mReInit = true; }
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
fb_var_screeninfo getScreenInfo() { return screeninfo; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
fb_var_screeninfo screeninfo;
|
fb_var_screeninfo si;
|
||||||
int *mX;
|
std::vector<unsigned char> osd_buf; /* silly bounce buffer */
|
||||||
int *mY;
|
void run(); /* for OpenThreads::Thread */
|
||||||
int _mX[2]; /* output window size */
|
void *pdata; /* not yet used */
|
||||||
int _mY[2]; /* [0] = normal, [1] = fullscreen */
|
|
||||||
AVRational mOA; /* output window aspect ratio */
|
|
||||||
AVRational mVA; /* video aspect ratio */
|
|
||||||
AVRational _mVA; /* for detecting changes in mVA */
|
|
||||||
bool mVAchanged;
|
|
||||||
float zoom; /* for cropping */
|
|
||||||
float xscale; /* and aspect ratio */
|
|
||||||
int mCrop; /* DISPLAY_AR_MODE */
|
|
||||||
|
|
||||||
bool mFullscreen; /* fullscreen? */
|
|
||||||
bool mReInit; /* setup things for GL */
|
|
||||||
OpenThreads::Mutex mReInitLock;
|
|
||||||
bool mShutDown; /* if set main loop is left */
|
|
||||||
bool mInitDone; /* condition predicate */
|
|
||||||
// OpenThreads::Condition mInitCond; /* condition variable for init */
|
|
||||||
// mutable OpenThreads::Mutex mMutex; /* lock our data */
|
|
||||||
|
|
||||||
std::vector<unsigned char> mOSDBuffer; /* silly bounce buffer */
|
|
||||||
|
|
||||||
std::map<unsigned char, int> mKeyMap;
|
|
||||||
std::map<int, int> mSpecialMap;
|
|
||||||
int input_fd;
|
|
||||||
int64_t last_apts;
|
|
||||||
|
|
||||||
static void rendercb(); /* callback for GLUT */
|
|
||||||
void render(); /* actual render function */
|
|
||||||
static void keyboardcb(unsigned char key, int x, int y);
|
|
||||||
static void specialcb(int key, int x, int y);
|
|
||||||
static void resizecb(int w, int h);
|
|
||||||
void checkReinit(int w, int h); /* e.g. in case window was resized */
|
|
||||||
|
|
||||||
void initKeys(); /* setup key bindings for window */
|
|
||||||
void setupCtx(); /* create the window and make the context current */
|
|
||||||
void setupOSDBuffer(); /* create the OSD buffer */
|
|
||||||
void setupGLObjects(); /* PBOs, textures and stuff */
|
|
||||||
void releaseGLObjects();
|
|
||||||
void drawSquare(float size, float x_factor = 1); /* do not be square */
|
|
||||||
|
|
||||||
struct {
|
|
||||||
int width; /* width and height, fixed for a framebuffer instance */
|
|
||||||
int height;
|
|
||||||
GLuint osdtex; /* holds the OSD texture */
|
|
||||||
GLuint pbo; /* PBO we use for transfer to texture */
|
|
||||||
GLuint displaytex; /* holds the display texture */
|
|
||||||
GLuint displaypbo;
|
|
||||||
bool blit;
|
|
||||||
} mState;
|
|
||||||
|
|
||||||
void bltOSDBuffer();
|
|
||||||
void bltDisplayBuffer();
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
109
generic-pc/glfb_priv.h
Normal file
109
generic-pc/glfb_priv.h
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2010 Carsten Juttner <carjay@gmx.net>
|
||||||
|
Copyright 2012,2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it 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.
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
|
||||||
|
********************************************************************
|
||||||
|
private stuff of the GLFB thread that is only used inside libstb-hal
|
||||||
|
and not exposed to the application.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __glfb_priv__
|
||||||
|
#define __glfb_priv__
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GL/freeglut.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <linux/fb.h> /* for screeninfo etc. */
|
||||||
|
#include "glfb.h"
|
||||||
|
extern "C" {
|
||||||
|
#include <libavutil/rational.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
class GLFbPC
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GLFbPC(int x, int y, std::vector<unsigned char> &buf);
|
||||||
|
~GLFbPC();
|
||||||
|
std::vector<unsigned char> *getOSDBuffer() { return osd_buf; } /* pointer to OSD bounce buffer */
|
||||||
|
int getOSDWidth() { return mState.width; }
|
||||||
|
int getOSDHeight() { return mState.height; }
|
||||||
|
void blit() { mState.blit = true; };
|
||||||
|
fb_var_screeninfo getScreenInfo() { return si; }
|
||||||
|
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
|
||||||
|
private:
|
||||||
|
*/
|
||||||
|
fb_var_screeninfo si;
|
||||||
|
int *mX;
|
||||||
|
int *mY;
|
||||||
|
int _mX[2]; /* output window size */
|
||||||
|
int _mY[2]; /* [0] = normal, [1] = fullscreen */
|
||||||
|
AVRational mOA; /* output window aspect ratio */
|
||||||
|
AVRational mVA; /* video aspect ratio */
|
||||||
|
AVRational _mVA; /* for detecting changes in mVA */
|
||||||
|
bool mVAchanged;
|
||||||
|
float zoom; /* for cropping */
|
||||||
|
float xscale; /* and aspect ratio */
|
||||||
|
int mCrop; /* DISPLAY_AR_MODE */
|
||||||
|
|
||||||
|
bool mFullscreen; /* fullscreen? */
|
||||||
|
bool mReInit; /* setup things for GL */
|
||||||
|
OpenThreads::Mutex mReInitLock;
|
||||||
|
bool mShutDown; /* if set main loop is left */
|
||||||
|
bool mInitDone; /* condition predicate */
|
||||||
|
// OpenThreads::Condition mInitCond; /* condition variable for init */
|
||||||
|
// mutable OpenThreads::Mutex mMutex; /* lock our data */
|
||||||
|
|
||||||
|
std::vector<unsigned char> *osd_buf; /* silly bounce buffer */
|
||||||
|
|
||||||
|
std::map<unsigned char, int> mKeyMap;
|
||||||
|
std::map<int, int> mSpecialMap;
|
||||||
|
int input_fd;
|
||||||
|
int64_t last_apts;
|
||||||
|
void run();
|
||||||
|
|
||||||
|
static void rendercb(); /* callback for GLUT */
|
||||||
|
void render(); /* actual render function */
|
||||||
|
static void keyboardcb(unsigned char key, int x, int y);
|
||||||
|
static void specialcb(int key, int x, int y);
|
||||||
|
static void resizecb(int w, int h);
|
||||||
|
void checkReinit(int w, int h); /* e.g. in case window was resized */
|
||||||
|
|
||||||
|
void initKeys(); /* setup key bindings for window */
|
||||||
|
#if 0
|
||||||
|
void setupCtx(); /* create the window and make the context current */
|
||||||
|
void setupOSDBuffer(); /* create the OSD buffer */
|
||||||
|
#endif
|
||||||
|
void setupGLObjects(); /* PBOs, textures and stuff */
|
||||||
|
void releaseGLObjects();
|
||||||
|
void drawSquare(float size, float x_factor = 1); /* do not be square */
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int width; /* width and height, fixed for a framebuffer instance */
|
||||||
|
int height;
|
||||||
|
GLuint osdtex; /* holds the OSD texture */
|
||||||
|
GLuint pbo; /* PBO we use for transfer to texture */
|
||||||
|
GLuint displaytex; /* holds the display texture */
|
||||||
|
GLuint displaypbo;
|
||||||
|
bool blit;
|
||||||
|
} mState;
|
||||||
|
|
||||||
|
void bltOSDBuffer();
|
||||||
|
void bltDisplayBuffer();
|
||||||
|
};
|
||||||
|
#endif
|
@@ -40,15 +40,17 @@ extern "C" {
|
|||||||
|
|
||||||
#include "video_lib.h"
|
#include "video_lib.h"
|
||||||
#include "dmx_lib.h"
|
#include "dmx_lib.h"
|
||||||
#include "glfb.h"
|
#include "glfb_priv.h"
|
||||||
|
#include "video_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)
|
||||||
#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_VIDEO, NULL, args)
|
#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_VIDEO, NULL, args)
|
||||||
|
|
||||||
|
VDec *vdec = NULL;
|
||||||
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;
|
||||||
@@ -68,6 +70,11 @@ static const AVRational aspect_ratios[6] = {
|
|||||||
cVideo::cVideo(int, void *, void *, unsigned int)
|
cVideo::cVideo(int, void *, void *, unsigned int)
|
||||||
{
|
{
|
||||||
lt_debug("%s\n", __func__);
|
lt_debug("%s\n", __func__);
|
||||||
|
vdec = new VDec();
|
||||||
|
}
|
||||||
|
|
||||||
|
VDec::VDec()
|
||||||
|
{
|
||||||
av_register_all();
|
av_register_all();
|
||||||
if (!HAL_nodec)
|
if (!HAL_nodec)
|
||||||
dmxbuf = (uint8_t *)malloc(DMX_BUF_SZ);
|
dmxbuf = (uint8_t *)malloc(DMX_BUF_SZ);
|
||||||
@@ -84,14 +91,27 @@ cVideo::cVideo(int, void *, void *, unsigned int)
|
|||||||
v_format = VIDEO_FORMAT_MPEG2;
|
v_format = VIDEO_FORMAT_MPEG2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VDec::~VDec(void)
|
||||||
|
{
|
||||||
|
free(dmxbuf);
|
||||||
|
}
|
||||||
|
|
||||||
cVideo::~cVideo(void)
|
cVideo::~cVideo(void)
|
||||||
{
|
{
|
||||||
Stop();
|
Stop();
|
||||||
/* ouch :-( */
|
/* ouch :-( */
|
||||||
videoDecoder = NULL;
|
// videoDecoder = NULL;
|
||||||
|
delete vdec;
|
||||||
|
// vdec = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int cVideo::setAspectRatio(int vformat, int cropping)
|
int cVideo::setAspectRatio(int vformat, int cropping)
|
||||||
|
{
|
||||||
|
return vdec->setAspectRatio(vformat, cropping);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VDec::setAspectRatio(int vformat, int cropping)
|
||||||
{
|
{
|
||||||
lt_info("%s(%d, %d)\n", __func__, vformat, cropping);
|
lt_info("%s(%d, %d)\n", __func__, vformat, cropping);
|
||||||
if (vformat >= 0)
|
if (vformat >= 0)
|
||||||
@@ -99,11 +119,16 @@ 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) /* don't know what to do with this */
|
if (display_aspect < DISPLAY_AR_RAW) /* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cVideo::getAspectRatio(void)
|
int cVideo::getAspectRatio(void)
|
||||||
|
{
|
||||||
|
return vdec->getAspectRatio();
|
||||||
|
}
|
||||||
|
|
||||||
|
int VDec::getAspectRatio(void)
|
||||||
{
|
{
|
||||||
buf_m.lock();
|
buf_m.lock();
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@@ -132,12 +157,22 @@ int cVideo::getAspectRatio(void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cVideo::setCroppingMode(int)
|
int cVideo::setCroppingMode(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cVideo::Start(void *, unsigned short, unsigned short, void *)
|
int cVideo::Start(void *, unsigned short, unsigned short, void *)
|
||||||
|
{
|
||||||
|
return vdec->Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cVideo::Stop(bool b)
|
||||||
|
{
|
||||||
|
return vdec->Stop(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VDec::Start()
|
||||||
{
|
{
|
||||||
lt_debug("%s running %d >\n", __func__, thread_running);
|
lt_debug("%s running %d >\n", __func__, thread_running);
|
||||||
if (!thread_running && !HAL_nodec)
|
if (!thread_running && !HAL_nodec)
|
||||||
@@ -146,7 +181,7 @@ int cVideo::Start(void *, unsigned short, unsigned short, void *)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cVideo::Stop(bool)
|
int VDec::Stop(bool)
|
||||||
{
|
{
|
||||||
lt_debug("%s running %d >\n", __func__, thread_running);
|
lt_debug("%s running %d >\n", __func__, thread_running);
|
||||||
if (thread_running) {
|
if (thread_running) {
|
||||||
@@ -163,6 +198,11 @@ int cVideo::setBlank(int)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int cVideo::SetVideoSystem(int system, bool)
|
int cVideo::SetVideoSystem(int system, bool)
|
||||||
|
{
|
||||||
|
return vdec->SetVideoSystem(system);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VDec::SetVideoSystem(int system)
|
||||||
{
|
{
|
||||||
int h;
|
int h;
|
||||||
switch(system)
|
switch(system)
|
||||||
@@ -195,16 +235,16 @@ int cVideo::SetVideoSystem(int system, bool)
|
|||||||
lt_info("%s: unhandled value %d\n", __func__, system);
|
lt_info("%s: unhandled value %d\n", __func__, system);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
v_std = (VIDEO_STD) system;
|
// v_std = (VIDEO_STD) system;
|
||||||
output_h = h;
|
output_h = h;
|
||||||
if (display_aspect < DISPLAY_AR_RAW) /* don't know what to do with this */
|
if (display_aspect < DISPLAY_AR_RAW) /* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cVideo::getPlayState(void)
|
int cVideo::getPlayState(void)
|
||||||
{
|
{
|
||||||
return VIDEO_PLAYING;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cVideo::SetVideoMode(analog_mode_t)
|
void cVideo::SetVideoMode(analog_mode_t)
|
||||||
@@ -212,6 +252,11 @@ void cVideo::SetVideoMode(analog_mode_t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cVideo::ShowPicture(const char *fname)
|
void cVideo::ShowPicture(const char *fname)
|
||||||
|
{
|
||||||
|
vdec->ShowPicture(fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VDec::ShowPicture(const char *fname)
|
||||||
{
|
{
|
||||||
lt_info("%s(%s)\n", __func__, fname);
|
lt_info("%s(%s)\n", __func__, fname);
|
||||||
if (access(fname, R_OK))
|
if (access(fname, R_OK))
|
||||||
@@ -327,6 +372,11 @@ int cVideo::getBlank(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cVideo::Pig(int x, int y, int w, int h, int, int)
|
void cVideo::Pig(int x, int y, int w, int h, int, int)
|
||||||
|
{
|
||||||
|
vdec->Pig(x, y, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VDec::Pig(int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
pig_x = x;
|
pig_x = x;
|
||||||
pig_y = y;
|
pig_y = y;
|
||||||
@@ -336,9 +386,14 @@ void cVideo::Pig(int x, int y, int w, int h, int, int)
|
|||||||
|
|
||||||
void cVideo::getPictureInfo(int &width, int &height, int &rate)
|
void cVideo::getPictureInfo(int &width, int &height, int &rate)
|
||||||
{
|
{
|
||||||
width = dec_w;
|
vdec->getPictureInfo(width, height, rate);
|
||||||
height = dec_h;
|
}
|
||||||
rate = dec_r;
|
|
||||||
|
void VDec::getPictureInfo(int &width, int &height, int &rate)
|
||||||
|
{
|
||||||
|
width = vdec->dec_w;
|
||||||
|
height = vdec->dec_h;
|
||||||
|
rate = vdec->dec_r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cVideo::SetSyncMode(AVSYNC_TYPE)
|
void cVideo::SetSyncMode(AVSYNC_TYPE)
|
||||||
@@ -346,12 +401,17 @@ void cVideo::SetSyncMode(AVSYNC_TYPE)
|
|||||||
};
|
};
|
||||||
|
|
||||||
int cVideo::SetStreamType(VIDEO_FORMAT v)
|
int cVideo::SetStreamType(VIDEO_FORMAT v)
|
||||||
|
{
|
||||||
|
return vdec->SetStreamType(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
int VDec::SetStreamType(VIDEO_FORMAT v)
|
||||||
{
|
{
|
||||||
v_format = v;
|
v_format = v;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cVideo::SWFramebuffer *cVideo::getDecBuf(void)
|
VDec::SWFramebuffer *VDec::getDecBuf(void)
|
||||||
{
|
{
|
||||||
buf_m.lock();
|
buf_m.lock();
|
||||||
if (buf_num == 0) {
|
if (buf_num == 0) {
|
||||||
@@ -390,7 +450,7 @@ static int my_read(void *, uint8_t *buf, int buf_size)
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cVideo::run(void)
|
void VDec::run(void)
|
||||||
{
|
{
|
||||||
lt_info("====================== start decoder thread ================================\n");
|
lt_info("====================== start decoder thread ================================\n");
|
||||||
AVCodec *codec;
|
AVCodec *codec;
|
||||||
@@ -507,7 +567,10 @@ 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 (v_format == VIDEO_FORMAT_MPEG2)
|
if (v_format == VIDEO_FORMAT_MPEG2)
|
||||||
|
vpts += 90000*4/10; /* 400ms */
|
||||||
|
else
|
||||||
vpts += 90000*3/10; /* 300ms */
|
vpts += 90000*3/10; /* 300ms */
|
||||||
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);
|
||||||
@@ -573,7 +636,7 @@ static bool swscale(unsigned char *src, unsigned char *dst, int sw, int sh, int
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video, bool get_osd, bool scale_to_video)
|
bool VDec::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video, bool get_osd, bool scale_to_video)
|
||||||
{
|
{
|
||||||
lt_info("%s: data 0x%p xres %d yres %d vid %d osd %d scale %d\n",
|
lt_info("%s: data 0x%p xres %d yres %d vid %d osd %d scale %d\n",
|
||||||
__func__, data, xres, yres, get_video, get_osd, scale_to_video);
|
__func__, data, xres, yres, get_video, get_osd, scale_to_video);
|
||||||
@@ -581,8 +644,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) {
|
||||||
@@ -601,7 +664,7 @@ bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool ge
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (get_osd)
|
if (get_osd)
|
||||||
osd = glfb->getOSDBuffer();
|
osd = glfb_priv->getOSDBuffer();
|
||||||
unsigned int need = avpicture_get_size(PIX_FMT_RGB32, xres, yres);
|
unsigned int need = avpicture_get_size(PIX_FMT_RGB32, xres, yres);
|
||||||
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? */
|
||||||
@@ -651,7 +714,7 @@ bool cVideo::GetScreenImage(unsigned char * &data, int &xres, int &yres, bool ge
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t cVideo::GetPTS(void)
|
int64_t VDec::GetPTS(void)
|
||||||
{
|
{
|
||||||
int64_t pts = 0;
|
int64_t pts = 0;
|
||||||
buf_m.lock();
|
buf_m.lock();
|
||||||
|
@@ -1,15 +1,26 @@
|
|||||||
#ifndef _VIDEO_TD_H
|
/*
|
||||||
#define _VIDEO_TD_H
|
Copyright 2010-2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it 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.
|
||||||
|
|
||||||
|
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 _VIDEO_LIB_H
|
||||||
|
#define _VIDEO_LIB_H
|
||||||
|
|
||||||
#include <OpenThreads/Thread>
|
|
||||||
#include <OpenThreads/Mutex>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <linux/dvb/video.h>
|
|
||||||
#include <cs_types.h>
|
#include <cs_types.h>
|
||||||
#include "dmx_lib.h"
|
|
||||||
extern "C" {
|
|
||||||
#include <libavutil/rational.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ANALOG_SD_RGB_CINCH = 0x00,
|
ANALOG_SD_RGB_CINCH = 0x00,
|
||||||
@@ -26,11 +37,25 @@ typedef enum {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
VIDEO_FORMAT_MPEG2 = 0,
|
VIDEO_FORMAT_MPEG2 = 0,
|
||||||
VIDEO_FORMAT_MPEG4,
|
VIDEO_FORMAT_MPEG4, /* H264 */
|
||||||
VIDEO_FORMAT_VC1,
|
VIDEO_FORMAT_VC1,
|
||||||
VIDEO_FORMAT_JPEG,
|
VIDEO_FORMAT_JPEG,
|
||||||
VIDEO_FORMAT_GIF,
|
VIDEO_FORMAT_GIF,
|
||||||
VIDEO_FORMAT_PNG
|
VIDEO_FORMAT_PNG,
|
||||||
|
VIDEO_FORMAT_DIVX,/* DIVX 3.11 */
|
||||||
|
VIDEO_FORMAT_MPEG4PART2,/* MPEG4 SVH, MPEG4 SP, MPEG4 ASP, DIVX4,5,6 */
|
||||||
|
VIDEO_FORMAT_REALVIDEO8,
|
||||||
|
VIDEO_FORMAT_REALVIDEO9,
|
||||||
|
VIDEO_FORMAT_ON2_VP6,
|
||||||
|
VIDEO_FORMAT_ON2_VP8,
|
||||||
|
VIDEO_FORMAT_SORENSON_SPARK,
|
||||||
|
VIDEO_FORMAT_H263,
|
||||||
|
VIDEO_FORMAT_H263_ENCODER,
|
||||||
|
VIDEO_FORMAT_H264_ENCODER,
|
||||||
|
VIDEO_FORMAT_MPEG4PART2_ENCODER,
|
||||||
|
VIDEO_FORMAT_AVS,
|
||||||
|
VIDEO_FORMAT_VIP656,
|
||||||
|
VIDEO_FORMAT_UNSUPPORTED
|
||||||
} VIDEO_FORMAT;
|
} VIDEO_FORMAT;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -96,8 +121,9 @@ typedef enum {
|
|||||||
VIDEO_STD_1080P30,
|
VIDEO_STD_1080P30,
|
||||||
VIDEO_STD_1080P24,
|
VIDEO_STD_1080P24,
|
||||||
VIDEO_STD_1080P25,
|
VIDEO_STD_1080P25,
|
||||||
|
VIDEO_STD_1080P50,
|
||||||
|
VIDEO_STD_1080P60,
|
||||||
VIDEO_STD_AUTO,
|
VIDEO_STD_AUTO,
|
||||||
VIDEO_STD_1080P50, /* SPARK only */
|
|
||||||
VIDEO_STD_MAX
|
VIDEO_STD_MAX
|
||||||
} VIDEO_STD;
|
} VIDEO_STD;
|
||||||
|
|
||||||
@@ -118,34 +144,10 @@ typedef enum
|
|||||||
VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS
|
VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS
|
||||||
} VIDEO_CONTROL;
|
} VIDEO_CONTROL;
|
||||||
|
|
||||||
|
class cDemux;
|
||||||
|
|
||||||
#define VDEC_MAXBUFS 0x30
|
class cVideo
|
||||||
class cVideo : public OpenThreads::Thread
|
|
||||||
{
|
{
|
||||||
friend class GLFramebuffer;
|
|
||||||
friend class cDemux;
|
|
||||||
private:
|
|
||||||
/* called from GL thread */
|
|
||||||
class SWFramebuffer : public std::vector<unsigned char>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SWFramebuffer() : mWidth(0), mHeight(0) {}
|
|
||||||
void width(int w) { mWidth = w; }
|
|
||||||
void height(int h) { mHeight = h; }
|
|
||||||
void pts(uint64_t p) { mPts = p; }
|
|
||||||
void AR(AVRational a) { mAR = a; }
|
|
||||||
int width() const { return mWidth; }
|
|
||||||
int height() const { return mHeight; }
|
|
||||||
int64_t pts() const { return mPts; }
|
|
||||||
AVRational AR() const { return mAR; }
|
|
||||||
private:
|
|
||||||
int mWidth;
|
|
||||||
int mHeight;
|
|
||||||
int64_t mPts;
|
|
||||||
AVRational mAR;
|
|
||||||
};
|
|
||||||
int buf_in, buf_out, buf_num;
|
|
||||||
int64_t GetPTS(void);
|
|
||||||
public:
|
public:
|
||||||
/* constructor & destructor */
|
/* constructor & destructor */
|
||||||
cVideo(int mode, void *, void *, unsigned int unit = 0);
|
cVideo(int mode, void *, void *, unsigned int unit = 0);
|
||||||
@@ -160,7 +162,7 @@ class cVideo : public OpenThreads::Thread
|
|||||||
int setAspectRatio(int aspect, int mode);
|
int setAspectRatio(int aspect, int mode);
|
||||||
|
|
||||||
/* cropping mode */
|
/* cropping mode */
|
||||||
int setCroppingMode(int x = 0 /*vidDispMode_t x = VID_DISPMODE_NORM*/);
|
int setCroppingMode(void);
|
||||||
|
|
||||||
/* get play state */
|
/* get play state */
|
||||||
int getPlayState(void);
|
int getPlayState(void);
|
||||||
@@ -197,24 +199,8 @@ class cVideo : public OpenThreads::Thread
|
|||||||
int StopVBI(void) { return 0; };
|
int StopVBI(void) { return 0; };
|
||||||
void SetDemux(cDemux *dmx);
|
void SetDemux(cDemux *dmx);
|
||||||
bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false);
|
bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false);
|
||||||
SWFramebuffer *getDecBuf(void);
|
|
||||||
private:
|
private:
|
||||||
void run();
|
void *pdata; /* not yet used */
|
||||||
SWFramebuffer buffers[VDEC_MAXBUFS];
|
|
||||||
int dec_w, dec_h;
|
|
||||||
int dec_r;
|
|
||||||
bool w_h_changed;
|
|
||||||
bool thread_running;
|
|
||||||
VIDEO_FORMAT v_format;
|
|
||||||
VIDEO_STD v_std;
|
|
||||||
OpenThreads::Mutex buf_m;
|
|
||||||
DISPLAY_AR display_aspect;
|
|
||||||
DISPLAY_AR_MODE display_crop;
|
|
||||||
int output_h;
|
|
||||||
int pig_x;
|
|
||||||
int pig_y;
|
|
||||||
int pig_w;
|
|
||||||
int pig_h;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
104
generic-pc/video_priv.h
Normal file
104
generic-pc/video_priv.h
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2013 Stefan Seyfried <seife@tuxboxcvs.slipkontur.de>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it 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.
|
||||||
|
|
||||||
|
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 __vdec__
|
||||||
|
|
||||||
|
#include <OpenThreads/Thread>
|
||||||
|
#include <OpenThreads/Mutex>
|
||||||
|
|
||||||
|
#include "video_lib.h"
|
||||||
|
extern "C" {
|
||||||
|
#include <libavutil/rational.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VDEC_MAXBUFS 0x40
|
||||||
|
class VDec : public OpenThreads::Thread
|
||||||
|
{
|
||||||
|
friend class GLFbPC;
|
||||||
|
friend class cDemux;
|
||||||
|
private:
|
||||||
|
/* called from GL thread */
|
||||||
|
class SWFramebuffer : public std::vector<unsigned char>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SWFramebuffer() : mWidth(0), mHeight(0) {}
|
||||||
|
void width(int w) { mWidth = w; }
|
||||||
|
void height(int h) { mHeight = h; }
|
||||||
|
void pts(uint64_t p) { mPts = p; }
|
||||||
|
void AR(AVRational a) { mAR = a; }
|
||||||
|
int width() const { return mWidth; }
|
||||||
|
int height() const { return mHeight; }
|
||||||
|
int64_t pts() const { return mPts; }
|
||||||
|
AVRational AR() const { return mAR; }
|
||||||
|
private:
|
||||||
|
int mWidth;
|
||||||
|
int mHeight;
|
||||||
|
int64_t mPts;
|
||||||
|
AVRational mAR;
|
||||||
|
};
|
||||||
|
int buf_in, buf_out, buf_num;
|
||||||
|
public:
|
||||||
|
/* constructor & destructor */
|
||||||
|
VDec(void);
|
||||||
|
~VDec(void);
|
||||||
|
/* aspect ratio */
|
||||||
|
int getAspectRatio(void);
|
||||||
|
int setAspectRatio(int aspect, int mode);
|
||||||
|
void getPictureInfo(int &width, int &height, int &rate);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* cropping mode */
|
||||||
|
int setCroppingMode(int x = 0 /*vidDispMode_t x = VID_DISPMODE_NORM*/);
|
||||||
|
|
||||||
|
/* get play state */
|
||||||
|
int getPlayState(void);
|
||||||
|
|
||||||
|
/* blank on freeze */
|
||||||
|
int getBlank(void);
|
||||||
|
int setBlank(int enable);
|
||||||
|
#endif
|
||||||
|
int SetVideoSystem(int system);
|
||||||
|
|
||||||
|
/* change video play state. Parameters are all unused. */
|
||||||
|
int Start();
|
||||||
|
int Stop(bool blank = true);
|
||||||
|
|
||||||
|
int SetStreamType(VIDEO_FORMAT type);
|
||||||
|
void ShowPicture(const char * fname);
|
||||||
|
void Pig(int x, int y, int w, int h);
|
||||||
|
bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false);
|
||||||
|
SWFramebuffer *getDecBuf(void);
|
||||||
|
int64_t GetPTS(void);
|
||||||
|
private:
|
||||||
|
void run();
|
||||||
|
SWFramebuffer buffers[VDEC_MAXBUFS];
|
||||||
|
int dec_w, dec_h;
|
||||||
|
int dec_r;
|
||||||
|
bool w_h_changed;
|
||||||
|
bool thread_running;
|
||||||
|
VIDEO_FORMAT v_format;
|
||||||
|
OpenThreads::Mutex buf_m;
|
||||||
|
DISPLAY_AR display_aspect;
|
||||||
|
DISPLAY_AR_MODE display_crop;
|
||||||
|
int output_h;
|
||||||
|
VIDEO_STD v_std;
|
||||||
|
int pig_x;
|
||||||
|
int pig_y;
|
||||||
|
int pig_w;
|
||||||
|
int pig_h;
|
||||||
|
};
|
||||||
|
#endif
|
Reference in New Issue
Block a user