mirror of
https://github.com/jojo61/vdr-plugin-softhdcuvid.git
synced 2023-10-10 13:37:41 +02:00
GRAB enabled
This commit is contained in:
parent
fdedeb6944
commit
35af60f504
@ -53,7 +53,7 @@ The Makefile expects the CUDA SDK in /usr/local/cuda. Currently it is tested wit
|
|||||||
|
|
||||||
Unfortunatly FFMEG has a bug with deinterlacing cuda frames. So you have to patch the file in libavcodec/cuviddec.c
|
Unfortunatly FFMEG has a bug with deinterlacing cuda frames. So you have to patch the file in libavcodec/cuviddec.c
|
||||||
|
|
||||||
Somewhere near line 360 depending on your release:
|
Somewhere near line 860 depending on your release:
|
||||||
old:
|
old:
|
||||||
ctx->frame_queue = av_fifo_alloc(ctx->nb_surfaces * sizeof(CuvidParsedFrame));
|
ctx->frame_queue = av_fifo_alloc(ctx->nb_surfaces * sizeof(CuvidParsedFrame));
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ The Makefile expects the CUDA SDK in /usr/local/cuda. Currently it is tested wit
|
|||||||
|
|
||||||
Unfortunatly FFMEG has a bug with deinterlacing cuda frames. So you have to patch the file in libavcodec/cuviddec.c
|
Unfortunatly FFMEG has a bug with deinterlacing cuda frames. So you have to patch the file in libavcodec/cuviddec.c
|
||||||
|
|
||||||
Somewhere near line 360 depending on your release:
|
Somewhere near line 860 depending on your release:
|
||||||
old:
|
old:
|
||||||
ctx->frame_queue = av_fifo_alloc(ctx->nb_surfaces * sizeof(CuvidParsedFrame));
|
ctx->frame_queue = av_fifo_alloc(ctx->nb_surfaces * sizeof(CuvidParsedFrame));
|
||||||
|
|
||||||
|
15
codec.c
15
codec.c
@ -291,7 +291,7 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (name && (video_codec = avcodec_find_decoder_by_name(name))) {
|
if (name && (video_codec = avcodec_find_decoder_by_name(name))) {
|
||||||
Debug(3, "codec: cuvid decoder found\n");
|
Debug(3, "codec: decoder found\n");
|
||||||
} else {
|
} else {
|
||||||
Debug(3,"Decoder %s not supported\n",name);
|
Debug(3,"Decoder %s not supported\n",name);
|
||||||
Fatal(_(" No decoder found"));
|
Fatal(_(" No decoder found"));
|
||||||
@ -299,6 +299,8 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
|
|||||||
|
|
||||||
decoder->VideoCodec = video_codec;
|
decoder->VideoCodec = video_codec;
|
||||||
|
|
||||||
|
Debug(3, "codec: video '%s'\n", decoder->VideoCodec->long_name);
|
||||||
|
|
||||||
if (!(decoder->VideoCtx = avcodec_alloc_context3(video_codec))) {
|
if (!(decoder->VideoCtx = avcodec_alloc_context3(video_codec))) {
|
||||||
Fatal(_("codec: can't allocate video codec context\n"));
|
Fatal(_("codec: can't allocate video codec context\n"));
|
||||||
}
|
}
|
||||||
@ -319,8 +321,8 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
|
|||||||
pthread_mutex_lock(&CodecLockMutex);
|
pthread_mutex_lock(&CodecLockMutex);
|
||||||
// open codec
|
// open codec
|
||||||
|
|
||||||
if (name && strcmp(name,"mpeg2_cuvid") == 0) { // deinterlace for mpeg2 is somehow broken
|
if (strcmp(decoder->VideoCodec->long_name,"Nvidia CUVID MPEG2VIDEO decoder") == 0) { // deinterlace for mpeg2 is somehow broken
|
||||||
if (av_opt_set_int(decoder->VideoCtx->priv_data, "deint", 2 ,0) < 0) { // weave
|
if (av_opt_set_int(decoder->VideoCtx->priv_data, "deint", 2 ,0) < 0) { // adaptive
|
||||||
pthread_mutex_unlock(&CodecLockMutex);
|
pthread_mutex_unlock(&CodecLockMutex);
|
||||||
Fatal(_("codec: can't set option deint to video codec!\n"));
|
Fatal(_("codec: can't set option deint to video codec!\n"));
|
||||||
}
|
}
|
||||||
@ -333,7 +335,7 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
|
|||||||
Fatal(_("codec: can't set option drop 2.field to video codec!\n"));
|
Fatal(_("codec: can't set option drop 2.field to video codec!\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strstr(name,"cuvid") != NULL) {
|
else if (strstr(decoder->VideoCodec->long_name,"Nvidia CUVID") != NULL) {
|
||||||
if (av_opt_set_int(decoder->VideoCtx->priv_data, "deint", 2 ,0) < 0) { // adaptive
|
if (av_opt_set_int(decoder->VideoCtx->priv_data, "deint", 2 ,0) < 0) { // adaptive
|
||||||
pthread_mutex_unlock(&CodecLockMutex);
|
pthread_mutex_unlock(&CodecLockMutex);
|
||||||
Fatal(_("codec: can't set option deint to video codec!\n"));
|
Fatal(_("codec: can't set option deint to video codec!\n"));
|
||||||
@ -355,9 +357,6 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
|
|||||||
|
|
||||||
decoder->VideoCtx->opaque = decoder; // our structure
|
decoder->VideoCtx->opaque = decoder; // our structure
|
||||||
|
|
||||||
Debug(3, "codec: video '%s'\n", decoder->VideoCodec->long_name);
|
|
||||||
|
|
||||||
|
|
||||||
//decoder->VideoCtx->debug = FF_DEBUG_STARTCODE;
|
//decoder->VideoCtx->debug = FF_DEBUG_STARTCODE;
|
||||||
//decoder->VideoCtx->err_recognition |= AV_EF_EXPLODE;
|
//decoder->VideoCtx->err_recognition |= AV_EF_EXPLODE;
|
||||||
|
|
||||||
@ -367,7 +366,7 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
|
|||||||
decoder->VideoCtx->thread_count = 1;
|
decoder->VideoCtx->thread_count = 1;
|
||||||
decoder->VideoCtx->active_thread_type = 0;
|
decoder->VideoCtx->active_thread_type = 0;
|
||||||
decoder->VideoCtx->draw_horiz_band = NULL;
|
decoder->VideoCtx->draw_horiz_band = NULL;
|
||||||
if (strstr(name,"cuvid"))
|
if (strstr(decoder->VideoCodec->long_name,"Nvidia CUVID") != NULL)
|
||||||
decoder->VideoCtx->hwaccel_context = VideoGetHwAccelContext(decoder->HwDecoder);
|
decoder->VideoCtx->hwaccel_context = VideoGetHwAccelContext(decoder->HwDecoder);
|
||||||
|
|
||||||
|
|
||||||
|
21
shaders.h
21
shaders.h
@ -31,7 +31,7 @@ char fragment[] = {"\
|
|||||||
#version 330\n\
|
#version 330\n\
|
||||||
#define texture1D texture\n\
|
#define texture1D texture\n\
|
||||||
#define texture3D texture\n\
|
#define texture3D texture\n\
|
||||||
out vec4 out_color;\n\
|
layout(location = 0) out vec4 out_color;\n\
|
||||||
in vec2 texcoord0;\n\
|
in vec2 texcoord0;\n\
|
||||||
in vec2 texcoord1;\n\
|
in vec2 texcoord1;\n\
|
||||||
in vec2 texcoord2;\n\
|
in vec2 texcoord2;\n\
|
||||||
@ -64,7 +64,7 @@ char fragment_bt2100[] = {"\
|
|||||||
#version 330\n\
|
#version 330\n\
|
||||||
#define texture1D texture\n\
|
#define texture1D texture\n\
|
||||||
#define texture3D texture\n\
|
#define texture3D texture\n\
|
||||||
out vec4 out_color;\n\
|
layout(location = 0) out vec4 out_color;\n\
|
||||||
in vec2 texcoord0;\n\
|
in vec2 texcoord0;\n\
|
||||||
in vec2 texcoord1;\n\
|
in vec2 texcoord1;\n\
|
||||||
in vec2 texcoord2;\n\
|
in vec2 texcoord2;\n\
|
||||||
@ -292,12 +292,13 @@ static GLuint sc_generate(GLuint gl_prog, enum AVColorSpace colorspace) {
|
|||||||
return gl_prog;
|
return gl_prog;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void render_pass_quad()
|
static void render_pass_quad(int flip)
|
||||||
{
|
{
|
||||||
struct vertex va[4];
|
struct vertex va[4];
|
||||||
int n;
|
int n;
|
||||||
const struct gl_vao_entry *e;
|
const struct gl_vao_entry *e;
|
||||||
// uhhhh what a hack
|
// uhhhh what a hack
|
||||||
|
if (!flip ) {
|
||||||
va[0].position.x = (float) -1.0;
|
va[0].position.x = (float) -1.0;
|
||||||
va[0].position.y = (float) 1.0;
|
va[0].position.y = (float) 1.0;
|
||||||
va[1].position.x = (float) -1.0;
|
va[1].position.x = (float) -1.0;
|
||||||
@ -306,7 +307,16 @@ static void render_pass_quad()
|
|||||||
va[2].position.y = (float) 1.0;
|
va[2].position.y = (float) 1.0;
|
||||||
va[3].position.x = (float) 1.0;
|
va[3].position.x = (float) 1.0;
|
||||||
va[3].position.y = (float) -1.0;
|
va[3].position.y = (float) -1.0;
|
||||||
|
} else {
|
||||||
|
va[0].position.x = (float) -1.0;
|
||||||
|
va[0].position.y = (float) -1.0;
|
||||||
|
va[1].position.x = (float) -1.0;
|
||||||
|
va[1].position.y = (float) 1.0;
|
||||||
|
va[2].position.x = (float) 1.0;
|
||||||
|
va[2].position.y = (float) -1.0;
|
||||||
|
va[3].position.x = (float) 1.0;
|
||||||
|
va[3].position.y = (float) 1.0;
|
||||||
|
}
|
||||||
va[0].texcoord[0].x = (float) 0.0;
|
va[0].texcoord[0].x = (float) 0.0;
|
||||||
va[0].texcoord[0].y = (float) 0.0;
|
va[0].texcoord[0].y = (float) 0.0;
|
||||||
va[0].texcoord[1].x = (float) 0.0;
|
va[0].texcoord[1].x = (float) 0.0;
|
||||||
@ -343,9 +353,6 @@ static void render_pass_quad()
|
|||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
for ( n = 0; vertex_vao[n].name; n++)
|
for ( n = 0; vertex_vao[n].name; n++)
|
||||||
glDisableVertexAttribArray(n);
|
glDisableVertexAttribArray(n);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2887,8 +2887,7 @@ int cSoftHdDevice::PlayTsAudio(const uchar * data, int length)
|
|||||||
uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int width,
|
uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int width,
|
||||||
int height)
|
int height)
|
||||||
{
|
{
|
||||||
dsyslog("[softhddev]%s: %d, %d, %d, %dx%d\n", __FUNCTION__, size, jpeg,
|
dsyslog("[softhddev]%s: %d, %d, %d, %dx%d\n", __FUNCTION__, size, jpeg, quality, width, height);
|
||||||
quality, width, height);
|
|
||||||
|
|
||||||
if (SuspendMode != NOT_SUSPENDED) {
|
if (SuspendMode != NOT_SUSPENDED) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2937,8 +2936,7 @@ void cSoftHdDevice::ScaleVideo(const cRect & rect)
|
|||||||
extern "C" uint8_t * CreateJpeg(uint8_t * image, int *size, int quality,
|
extern "C" uint8_t * CreateJpeg(uint8_t * image, int *size, int quality,
|
||||||
int width, int height)
|
int width, int height)
|
||||||
{
|
{
|
||||||
return (uint8_t *) RgbToJpeg((uchar *) image, width, height, *size,
|
return (uint8_t *) RgbToJpeg((uchar *) image, width, height, *size, quality);
|
||||||
quality);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@ -3490,6 +3488,65 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
|
|||||||
bool cPluginSoftHdDevice::Service(const char *id, void *data)
|
bool cPluginSoftHdDevice::Service(const char *id, void *data)
|
||||||
{
|
{
|
||||||
//dsyslog("[softhddev]%s: id %s\n", __FUNCTION__, id);
|
//dsyslog("[softhddev]%s: id %s\n", __FUNCTION__, id);
|
||||||
|
if (strcmp(id, OSD_3DMODE_SERVICE) == 0) {
|
||||||
|
SoftHDDevice_Osd3DModeService_v1_0_t *r;
|
||||||
|
|
||||||
|
r = (SoftHDDevice_Osd3DModeService_v1_0_t *) data;
|
||||||
|
VideoSetOsd3DMode(r->Mode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(id, ATMO_GRAB_SERVICE) == 0) {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
|
||||||
|
if (data == NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SuspendMode != NOT_SUSPENDED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SoftHDDevice_AtmoGrabService_v1_0_t *r =
|
||||||
|
(SoftHDDevice_AtmoGrabService_v1_0_t *) data;
|
||||||
|
if (r->structSize != sizeof(SoftHDDevice_AtmoGrabService_v1_0_t)
|
||||||
|
|| r->analyseSize < 64 || r->analyseSize > 256
|
||||||
|
|| r->clippedOverscan < 0 || r->clippedOverscan > 200) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
width = r->analyseSize * -1; // Internal marker for Atmo grab service
|
||||||
|
height = r->clippedOverscan;
|
||||||
|
|
||||||
|
r->img = VideoGrabService(&r->imgSize, &width, &height);
|
||||||
|
if (r->img == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
r->imgType = GRAB_IMG_RGBA_FORMAT_B8G8R8A8;
|
||||||
|
r->width = width;
|
||||||
|
r->height = height;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(id, ATMO1_GRAB_SERVICE) == 0) {
|
||||||
|
SoftHDDevice_AtmoGrabService_v1_1_t *r;
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SuspendMode != NOT_SUSPENDED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = (SoftHDDevice_AtmoGrabService_v1_1_t *) data;
|
||||||
|
r->img = VideoGrabService(&r->size, &r->width, &r->height);
|
||||||
|
if (!r->img) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
299
video.c
299
video.c
@ -41,7 +41,7 @@
|
|||||||
#define USE_XLIB_XCB ///< use xlib/xcb backend
|
#define USE_XLIB_XCB ///< use xlib/xcb backend
|
||||||
#define noUSE_SCREENSAVER ///< support disable screensaver
|
#define noUSE_SCREENSAVER ///< support disable screensaver
|
||||||
//#define USE_AUTOCROP ///< compile auto-crop support
|
//#define USE_AUTOCROP ///< compile auto-crop support
|
||||||
//#define USE_GRAB ///< experimental grab code
|
#define USE_GRAB ///< experimental grab code
|
||||||
//#define USE_GLX ///< outdated GLX code
|
//#define USE_GLX ///< outdated GLX code
|
||||||
#define USE_DOUBLEBUFFER ///< use GLX double buffers
|
#define USE_DOUBLEBUFFER ///< use GLX double buffers
|
||||||
//#define USE_VAAPI ///< enable vaapi support
|
//#define USE_VAAPI ///< enable vaapi support
|
||||||
@ -1582,6 +1582,9 @@ typedef struct _cuvid_decoder_
|
|||||||
AutoCropCtx AutoCrop[1]; ///< auto-crop variables
|
AutoCropCtx AutoCrop[1]; ///< auto-crop variables
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int grabwidth,grabheight,grab; // Grab Data
|
||||||
|
void *grabbase;
|
||||||
|
|
||||||
int SurfacesNeeded; ///< number of surface to request
|
int SurfacesNeeded; ///< number of surface to request
|
||||||
int SurfaceUsedN; ///< number of used video surfaces
|
int SurfaceUsedN; ///< number of used video surfaces
|
||||||
/// used video surface ids
|
/// used video surface ids
|
||||||
@ -2215,74 +2218,7 @@ static int cuvid_get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void cuvid_uninit(AVCodecContext *avctx)
|
|
||||||
{
|
|
||||||
VideoDecoder *ist = avctx->opaque;
|
|
||||||
av_buffer_unref(&ist->hw_frames_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int init_cuvid(AVCodecContext *avctx,CuvidDecoder * decoder)
|
|
||||||
{
|
|
||||||
VideoDecoder *ist = avctx->opaque;
|
|
||||||
AVHWFramesContext *frames_ctx;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
unsigned int device_count,version;
|
|
||||||
CUdevice device;
|
|
||||||
AVHWDeviceContext *device_ctx;
|
|
||||||
AVCUDADeviceContext *device_hwctx;
|
|
||||||
CUcontext dummy;
|
|
||||||
|
|
||||||
AVBufferRef *hw_device_ctx = NULL;
|
|
||||||
|
|
||||||
hw_device_ctx = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA);
|
|
||||||
|
|
||||||
if (!hw_device_ctx)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
device_ctx = (void *)hw_device_ctx->data;
|
|
||||||
|
|
||||||
device_hwctx = device_ctx->hwctx;
|
|
||||||
device_hwctx->cuda_ctx = decoder->cuda_ctx;
|
|
||||||
|
|
||||||
ret = av_hwdevice_ctx_init(hw_device_ctx);
|
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
Debug(3, "av_hwdevice_ctx_init failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ab hier frames init
|
|
||||||
av_buffer_unref(&ist->hw_frames_ctx);
|
|
||||||
ist->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx);
|
|
||||||
if (!ist->hw_frames_ctx) {
|
|
||||||
Debug(3, "Error creating a CUDA frames context\n");
|
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
frames_ctx = (AVHWFramesContext*)ist->hw_frames_ctx->data;
|
|
||||||
|
|
||||||
frames_ctx->format = AV_PIX_FMT_CUDA;
|
|
||||||
frames_ctx->sw_format = avctx->sw_pix_fmt;
|
|
||||||
frames_ctx->width = avctx->width;
|
|
||||||
frames_ctx->height = avctx->height;
|
|
||||||
|
|
||||||
Debug(3, "Initializing CUDA frames context: sw_format = %s, width = %d, height = %d\n",
|
|
||||||
av_get_pix_fmt_name(frames_ctx->sw_format), frames_ctx->width, frames_ctx->height);
|
|
||||||
|
|
||||||
ret = av_hwframe_ctx_init(ist->hw_frames_ctx);
|
|
||||||
if (ret < 0) {
|
|
||||||
Debug(3, "Error initializing a CUDA frame pool\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ist->hwaccel_uninit = cuvid_uninit;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
///
|
///
|
||||||
/// Callback to negotiate the PixelFormat.
|
/// Callback to negotiate the PixelFormat.
|
||||||
///
|
///
|
||||||
@ -2373,6 +2309,72 @@ static enum AVPixelFormat Cuvid_get_format(CuvidDecoder * decoder,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_GRAB
|
#ifdef USE_GRAB
|
||||||
|
|
||||||
|
int get_RGB(CuvidDecoder *decoder) {
|
||||||
|
uint8_t *base = decoder->grabbase;;
|
||||||
|
int width = decoder->grabwidth;
|
||||||
|
int height = decoder->grabheight;
|
||||||
|
GLuint fb,texture;
|
||||||
|
int current,i;
|
||||||
|
GLint texLoc;
|
||||||
|
|
||||||
|
glGenTextures(1, &texture);
|
||||||
|
GlxCheck();
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
GlxCheck();
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
GlxCheck();
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
|
||||||
|
GlxCheck();
|
||||||
|
|
||||||
|
glGenFramebuffers(1, &fb);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
|
||||||
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
|
Debug(3,"video/cuvid: grab Framebuffer is not complete!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = decoder->SurfacesRb[decoder->SurfaceRead];
|
||||||
|
|
||||||
|
glViewport(0,0,width, height);
|
||||||
|
|
||||||
|
if (gl_prog == 0)
|
||||||
|
gl_prog = sc_generate(gl_prog, decoder->ColorSpace); // generate shader programm
|
||||||
|
|
||||||
|
glUseProgram(gl_prog);
|
||||||
|
texLoc = glGetUniformLocation(gl_prog, "texture0");
|
||||||
|
glUniform1i(texLoc, 0);
|
||||||
|
texLoc = glGetUniformLocation(gl_prog, "texture1");
|
||||||
|
glUniform1i(texLoc, 1);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D,decoder->gl_textures[current*2+0]);
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glBindTexture(GL_TEXTURE_2D,decoder->gl_textures[current*2+1]);
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||||
|
|
||||||
|
render_pass_quad(1);
|
||||||
|
glUseProgram(0);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
|
Debug(3,"Read pixels %d %d\n",width,height);
|
||||||
|
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
|
glReadPixels(0,0,width,height,GL_BGRA,GL_UNSIGNED_BYTE,base);
|
||||||
|
GlxCheck();
|
||||||
|
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
glDeleteTextures(1,&texture);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Grab output surface already locked.
|
/// Grab output surface already locked.
|
||||||
///
|
///
|
||||||
@ -2380,35 +2382,33 @@ static enum AVPixelFormat Cuvid_get_format(CuvidDecoder * decoder,
|
|||||||
/// @param ret_width[in,out] width of output
|
/// @param ret_width[in,out] width of output
|
||||||
/// @param ret_height[in,out] height of output
|
/// @param ret_height[in,out] height of output
|
||||||
///
|
///
|
||||||
static uint8_t *CuvidGrabOutputSurfaceLocked(int *ret_size, int *ret_width,
|
static uint8_t *CuvidGrabOutputSurfaceLocked(int *ret_size, int *ret_width, int *ret_height)
|
||||||
int *ret_height)
|
|
||||||
{
|
{
|
||||||
VdpOutputSurface surface;
|
int surface,i;
|
||||||
VdpStatus status;
|
|
||||||
VdpRGBAFormat rgba_format;
|
int rgba_format;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t width;
|
uint32_t width;
|
||||||
uint32_t height;
|
uint32_t height;
|
||||||
void *base;
|
uint8_t *base;
|
||||||
void *data[1];
|
void *data[1];
|
||||||
uint32_t pitches[1];
|
uint32_t pitches[1];
|
||||||
VdpRect source_rect;
|
VdpRect source_rect;
|
||||||
VdpRect output_rect;
|
VdpRect output_rect;
|
||||||
|
CuvidDecoder *decoder;
|
||||||
|
|
||||||
surface = CuvidSurfacesRb[CuvidOutputSurfaceIndex];
|
decoder = CuvidDecoders[0];
|
||||||
|
if (decoder == NULL) // no video aktiv
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// surface = CuvidSurfacesRb[CuvidOutputSurfaceIndex];
|
||||||
|
|
||||||
// get real surface size
|
// get real surface size
|
||||||
status =
|
width = decoder->InputWidth;
|
||||||
CuvidOutputSurfaceGetParameters(surface, &rgba_format, &width,
|
height = decoder->InputHeight;
|
||||||
&height);
|
|
||||||
if (status != VDP_STATUS_OK) {
|
|
||||||
Error(_("video/vdpau: can't get output surface parameters: %s\n"),
|
|
||||||
CuvidGetErrorString(status));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug(3, "video/vdpau: grab %dx%d format %d\n", width, height,
|
|
||||||
rgba_format);
|
Debug(3, "video/cuvid: grab %dx%d\n", width, height);
|
||||||
|
|
||||||
source_rect.x0 = 0;
|
source_rect.x0 = 0;
|
||||||
source_rect.y0 = 0;
|
source_rect.y0 = 0;
|
||||||
@ -2441,78 +2441,34 @@ static uint8_t *CuvidGrabOutputSurfaceLocked(int *ret_size, int *ret_width,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug(3, "video/vdpau: grab source rect %d,%d:%d,%d dest dim %dx%d\n",
|
Debug(3, "video/cuvid: grab source rect %d,%d:%d,%d dest dim %dx%d\n",
|
||||||
source_rect.x0, source_rect.y0, source_rect.x1, source_rect.y1,
|
source_rect.x0, source_rect.y0, source_rect.x1, source_rect.y1,
|
||||||
width, height);
|
width, height);
|
||||||
|
|
||||||
if ((source_rect.x1 - source_rect.x0) != width
|
|
||||||
|| (source_rect.y1 - source_rect.y0) != height) {
|
|
||||||
output_rect.x0 = 0;
|
output_rect.x0 = 0;
|
||||||
output_rect.y0 = 0;
|
output_rect.y0 = 0;
|
||||||
output_rect.x1 = width;
|
output_rect.x1 = width;
|
||||||
output_rect.y1 = height;
|
output_rect.y1 = height;
|
||||||
|
|
||||||
status =
|
|
||||||
CuvidOutputSurfaceRenderOutputSurface(CuvidGrabRenderSurface,
|
|
||||||
&output_rect, surface, &source_rect, NULL, NULL,
|
|
||||||
VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
|
|
||||||
if (status != VDP_STATUS_OK) {
|
|
||||||
Error(_("video/vdpau: can't render output surface: %s\n"),
|
|
||||||
CuvidGetErrorString(status));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
surface = CuvidGrabRenderSurface;
|
|
||||||
source_rect = output_rect;
|
|
||||||
#if 0
|
|
||||||
// FIXME: what if CuvidGrabRenderSurface has different sizes
|
|
||||||
// get real surface size
|
|
||||||
status =
|
|
||||||
CuvidOutputSurfaceGetParameters(surface, &rgba_format, &width,
|
|
||||||
&height);
|
|
||||||
if (status != VDP_STATUS_OK) {
|
|
||||||
Error(_
|
|
||||||
("video/vdpau: can't get output surface parameters: %s\n"),
|
|
||||||
CuvidGetErrorString(status));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (width != output_rect.x1 || height != output_rect.y1) {
|
|
||||||
// FIXME: this warning can be removed, is now for debug only
|
|
||||||
Warning(_("video/vdpau: video surface size mismatch\n"));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (rgba_format) {
|
|
||||||
case VDP_RGBA_FORMAT_B8G8R8A8:
|
|
||||||
case VDP_RGBA_FORMAT_R8G8B8A8:
|
|
||||||
size = width * height * sizeof(uint32_t);
|
size = width * height * sizeof(uint32_t);
|
||||||
base = malloc(size);
|
|
||||||
if (!base) {
|
|
||||||
Error(_("video/vdpau: out of memory\n"));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
pitches[0] = width * sizeof(uint32_t);
|
|
||||||
data[0] = base;
|
|
||||||
break;
|
|
||||||
case VDP_RGBA_FORMAT_R10G10B10A2:
|
|
||||||
case VDP_RGBA_FORMAT_B10G10R10A2:
|
|
||||||
case VDP_RGBA_FORMAT_A8:
|
|
||||||
default:
|
|
||||||
Error(_("video/vdpau: unsupported rgba format %d\n"), rgba_format);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
base = malloc(size);
|
||||||
status = CuvidOutputSurfaceGetBitsNative(surface, &source_rect, data, pitches);
|
|
||||||
if (status != VDP_STATUS_OK) {
|
if (!base) {
|
||||||
Error(_("video/vdpau: can't get video surface bits native: %s\n"),
|
Error(_("video/cuvid: out of memory\n"));
|
||||||
CuvidGetErrorString(status));
|
|
||||||
free(base);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
decoder->grabbase = base;
|
||||||
|
decoder->grabwidth = width;
|
||||||
|
decoder->grabheight = height;
|
||||||
|
decoder->grab = 1;
|
||||||
|
|
||||||
|
while(decoder->grab) {
|
||||||
|
usleep(1000); // wait for data
|
||||||
|
}
|
||||||
|
Debug(3,"got grab data\n");
|
||||||
|
|
||||||
if (ret_size) {
|
if (ret_size) {
|
||||||
*ret_size = size;
|
*ret_size = size;
|
||||||
}
|
}
|
||||||
@ -2522,8 +2478,10 @@ static uint8_t *CuvidGrabOutputSurfaceLocked(int *ret_size, int *ret_width,
|
|||||||
if (ret_height) {
|
if (ret_height) {
|
||||||
*ret_height = height;
|
*ret_height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
return base;
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -2538,13 +2496,11 @@ static uint8_t *CuvidGrabOutputSurface(int *ret_size, int *ret_width,
|
|||||||
{
|
{
|
||||||
uint8_t *img;
|
uint8_t *img;
|
||||||
|
|
||||||
if (CuvidGrabRenderSurface == VDP_INVALID_HANDLE) {
|
// pthread_mutex_lock(&CuvidGrabMutex);
|
||||||
return NULL; // vdpau video module not yet initialized
|
// pthread_mutex_lock(&VideoLockMutex);
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(&CuvidGrabMutex);
|
|
||||||
img = CuvidGrabOutputSurfaceLocked(ret_size, ret_width, ret_height);
|
img = CuvidGrabOutputSurfaceLocked(ret_size, ret_width, ret_height);
|
||||||
pthread_mutex_unlock(&CuvidGrabMutex);
|
// pthread_mutex_unlock(&VideoLockMutex);
|
||||||
|
// pthread_mutex_unlock(&CuvidGrabMutex);
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2934,15 +2890,11 @@ static void CuvidMixVideo(CuvidDecoder * decoder, int level)
|
|||||||
int w = decoder->InputWidth;
|
int w = decoder->InputWidth;
|
||||||
int h = decoder->InputHeight;
|
int h = decoder->InputHeight;
|
||||||
int y;
|
int y;
|
||||||
CUgraphicsResource cuResource;
|
|
||||||
CUcontext dummy=NULL;
|
|
||||||
GLint texLoc;
|
GLint texLoc;
|
||||||
|
|
||||||
size_t nSize = 0;
|
size_t nSize = 0;
|
||||||
static uint32_t lasttime = 0;
|
static uint32_t lasttime = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_AUTOCROP
|
#ifdef USE_AUTOCROP
|
||||||
// FIXME: can move to render frame
|
// FIXME: can move to render frame
|
||||||
CuvidCheckAutoCrop(decoder);
|
CuvidCheckAutoCrop(decoder);
|
||||||
@ -2974,18 +2926,10 @@ static void CuvidMixVideo(CuvidDecoder * decoder, int level)
|
|||||||
|
|
||||||
// Render Progressive frame and simple interlaced
|
// Render Progressive frame and simple interlaced
|
||||||
|
|
||||||
//printf("decoder Y %d\n",decoder->OutputY);
|
|
||||||
|
|
||||||
|
|
||||||
y = VideoWindowHeight - decoder->OutputY - decoder->OutputHeight;
|
y = VideoWindowHeight - decoder->OutputY - decoder->OutputHeight;
|
||||||
if (y <0 )
|
if (y <0 )
|
||||||
y = 0;
|
y = 0;
|
||||||
glViewport(decoder->OutputX, y, decoder->OutputWidth, decoder->OutputHeight);
|
glViewport(decoder->OutputX, y, decoder->OutputWidth, decoder->OutputHeight);
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glLoadIdentity();
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glLoadIdentity();
|
|
||||||
glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
|
|
||||||
|
|
||||||
if (gl_prog == 0)
|
if (gl_prog == 0)
|
||||||
gl_prog = sc_generate(gl_prog, decoder->ColorSpace); // generate shader programm
|
gl_prog = sc_generate(gl_prog, decoder->ColorSpace); // generate shader programm
|
||||||
@ -3001,11 +2945,11 @@ static void CuvidMixVideo(CuvidDecoder * decoder, int level)
|
|||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
glBindTexture(GL_TEXTURE_2D,decoder->gl_textures[current*2+1]);
|
glBindTexture(GL_TEXTURE_2D,decoder->gl_textures[current*2+1]);
|
||||||
|
|
||||||
render_pass_quad();
|
render_pass_quad(0);
|
||||||
|
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
//printf("render frame %d ",current);
|
|
||||||
Debug(4, "video/vdpau: yy video surface %p displayed\n", current, decoder->SurfaceRead);
|
Debug(4, "video/vdpau: yy video surface %p displayed\n", current, decoder->SurfaceRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3136,13 +3080,17 @@ static void CuvidDisplayFrame(void)
|
|||||||
// need 1 frame for progressive, 3 frames for interlaced
|
// need 1 frame for progressive, 3 frames for interlaced
|
||||||
if (filled < 1 + 2 * decoder->Interlaced) {
|
if (filled < 1 + 2 * decoder->Interlaced) {
|
||||||
// FIXME: rewrite MixVideo to support less surfaces
|
// FIXME: rewrite MixVideo to support less surfaces
|
||||||
if ((VideoShowBlackPicture && !decoder->TrickSpeed) || decoder->Closing < -300) {
|
if ((VideoShowBlackPicture && !decoder->TrickSpeed) || (VideoShowBlackPicture && decoder->Closing < -300)) {
|
||||||
CuvidBlackSurface(decoder);
|
CuvidBlackSurface(decoder);
|
||||||
CuvidMessage(3, "video/cuvid: black surface displayed\n");
|
CuvidMessage(3, "video/cuvid: black surface displayed\n");
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
CuvidMixVideo(decoder, i);
|
CuvidMixVideo(decoder, i);
|
||||||
|
if (i==0 && decoder->grab) { // Grab frame
|
||||||
|
get_RGB(decoder);
|
||||||
|
decoder->grab = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// add osd to surface
|
// add osd to surface
|
||||||
@ -3641,26 +3589,21 @@ static const uint8_t OsdZeros[4096 * 2160 * 4]; ///< 0 for clear osd
|
|||||||
static const VideoModule CuvidModule = {
|
static const VideoModule CuvidModule = {
|
||||||
.Name = "cuvid",
|
.Name = "cuvid",
|
||||||
.Enabled = 1,
|
.Enabled = 1,
|
||||||
.NewHwDecoder =
|
.NewHwDecoder = (VideoHwDecoder * (*const)(VideoStream *)) CuvidNewHwDecoder,
|
||||||
(VideoHwDecoder * (*const)(VideoStream *)) CuvidNewHwDecoder,
|
|
||||||
.DelHwDecoder = (void (*const) (VideoHwDecoder *))CuvidDelHwDecoder,
|
.DelHwDecoder = (void (*const) (VideoHwDecoder *))CuvidDelHwDecoder,
|
||||||
.GetSurface = (unsigned (*const) (VideoHwDecoder *,
|
.GetSurface = (unsigned (*const) (VideoHwDecoder *, const AVCodecContext *))CuvidGetVideoSurface,
|
||||||
const AVCodecContext *))CuvidGetVideoSurface,
|
.ReleaseSurface = (void (*const) (VideoHwDecoder *, unsigned))CuvidReleaseSurface,
|
||||||
.ReleaseSurface =
|
|
||||||
(void (*const) (VideoHwDecoder *, unsigned))CuvidReleaseSurface,
|
|
||||||
.get_format = (enum AVPixelFormat(*const) (VideoHwDecoder *,
|
.get_format = (enum AVPixelFormat(*const) (VideoHwDecoder *,
|
||||||
AVCodecContext *, const enum AVPixelFormat *))Cuvid_get_format,
|
AVCodecContext *, const enum AVPixelFormat *))Cuvid_get_format,
|
||||||
.RenderFrame = (void (*const) (VideoHwDecoder *,
|
.RenderFrame = (void (*const) (VideoHwDecoder *,
|
||||||
const AVCodecContext *, const AVFrame *))CuvidSyncRenderFrame,
|
const AVCodecContext *, const AVFrame *))CuvidSyncRenderFrame,
|
||||||
.GetHwAccelContext = (void *(*const)(VideoHwDecoder *))
|
.GetHwAccelContext = (void *(*const)(VideoHwDecoder *)) CuvidGetHwAccelContext,
|
||||||
CuvidGetHwAccelContext,
|
|
||||||
.SetClock = (void (*const) (VideoHwDecoder *, int64_t))CuvidSetClock,
|
.SetClock = (void (*const) (VideoHwDecoder *, int64_t))CuvidSetClock,
|
||||||
.GetClock = (int64_t(*const) (const VideoHwDecoder *))CuvidGetClock,
|
.GetClock = (int64_t(*const) (const VideoHwDecoder *))CuvidGetClock,
|
||||||
.SetClosing = (void (*const) (const VideoHwDecoder *))CuvidSetClosing,
|
.SetClosing = (void (*const) (const VideoHwDecoder *))CuvidSetClosing,
|
||||||
.ResetStart = (void (*const) (const VideoHwDecoder *))CuvidResetStart,
|
.ResetStart = (void (*const) (const VideoHwDecoder *))CuvidResetStart,
|
||||||
.SetTrickSpeed =
|
.SetTrickSpeed = (void (*const) (const VideoHwDecoder *, int))CuvidSetTrickSpeed,
|
||||||
(void (*const) (const VideoHwDecoder *, int))CuvidSetTrickSpeed,
|
.GrabOutput = CuvidGrabOutputSurface,
|
||||||
// .GrabOutput = NULL,
|
|
||||||
.GetStats = (void (*const) (VideoHwDecoder *, int *, int *, int *,
|
.GetStats = (void (*const) (VideoHwDecoder *, int *, int *, int *,
|
||||||
int *))CuvidGetStats,
|
int *))CuvidGetStats,
|
||||||
.SetBackground = CuvidSetBackground,
|
.SetBackground = CuvidSetBackground,
|
||||||
|
Loading…
Reference in New Issue
Block a user