1
0
mirror of https://github.com/jojo61/vdr-plugin-softhdcuvid.git synced 2023-10-10 13:37:41 +02:00

First support for VAAPI

This commit is contained in:
jojo61 2019-08-22 12:34:29 +02:00
parent fae0d3a9bd
commit 5c2b801a45
8 changed files with 1058 additions and 290 deletions

118
Makefile
View File

@ -1,6 +1,6 @@
# #
# Makefile for a Video Disk Recorder plugin # Makefile for a Video Disk Recorder plugin
# #
# $Id: 2a41981a57e5e83036463c6a08c84b86ed9d2be3 $ # $Id: 2a41981a57e5e83036463c6a08c84b86ed9d2be3 $
# The official name of this plugin. # The official name of this plugin.
@ -11,35 +11,46 @@ PLUGIN = softhdcuvid
### Configuration (edit this for your needs) ### Configuration (edit this for your needs)
# what kind of driver do we make -
# if VAAPI is enabled the drivername is softhdvaapi
# if CUVID is enabled the drivername is softhdcuvid
#VAAPI=1
CUVID=1
# support OPENGLOSD - only configurable with cuvid
OPENGLOSD=1
# use Libplacebo - only configurable with cuvid
LIBPLACEBO=1
# use YADIF deint - only configurable with cuvid
YADIF=0
#--------------------- no more config needed past this point--------------------------------
# support alsa audio output module # support alsa audio output module
ALSA ?= $(shell pkg-config --exists alsa && echo 1) ALSA ?= $(shell pkg-config --exists alsa && echo 1)
# support OSS audio output module # support OSS audio output module
OSS ?= 1 OSS ?= 1
# support OPENGLOSD
OPENGLOSD=1
# use Libplacebo # use DMPS
LIBPLACEBO=0
# use DMPS
SCREENSAVER=1 SCREENSAVER=1
OPENGL=1 OPENGL=1
# use ffmpeg libswresample
#SWRESAMPLE ?= $(shell pkg-config --exists libswresample && echo 1)
SWRESAMPLE = 1
# use libav libavresample
ifneq ($(SWRESAMPLE),1)
AVRESAMPLE ?= $(shell pkg-config --exists libavresample && echo 1)
AVRESAMPLE = 0
endif
CONFIG := #-DDEBUG #-DOSD_DEBUG # enable debug output+functions # use ffmpeg libswresample
CONFIG += -DCUVID # enable CUVID decoder SWRESAMPLE ?= $(shell pkg-config --exists libswresample && echo 1)
#CONFIG += -DYADIF # enable yadif_cuda deinterlacer SWRESAMPLE = 1
# use libav libavresample
#ifneq ($(SWRESAMPLE),1)
#AVRESAMPLE ?= $(shell pkg-config --exists libavresample && echo 1#)
#AVRESAMPLE = 1
#endif
CONFIG := -DDEBUG #-DOSD_DEBUG # enable debug output+functions
CONFIG += -DHAVE_GL # needed for mpv libs CONFIG += -DHAVE_GL # needed for mpv libs
#CONFIG += -DSTILL_DEBUG=2 # still picture debug verbose level #CONFIG += -DSTILL_DEBUG=2 # still picture debug verbose level
CONFIG += -DAV_INFO -DAV_INFO_TIME=3000 # info/debug a/v sync CONFIG += -DAV_INFO -DAV_INFO_TIME=3000 # info/debug a/v sync
CONFIG += -DUSE_PIP # PIP support CONFIG += -DUSE_PIP # PIP support
#CONFIG += -DHAVE_PTHREAD_NAME # supports new pthread_setname_np #CONFIG += -DHAVE_PTHREAD_NAME # supports new pthread_setname_np
@ -54,8 +65,9 @@ CONFIG += -DUSE_VDR_SPU # use VDR SPU decoder.
### The version number of this plugin (taken from the main source file): ### The version number of this plugin (taken from the main source file):
VERSION = $(shell grep 'static const char \*const VERSION *=' $(PLUGIN).cpp | awk '{ print $$7 }' | sed -e 's/[";]//g') VERSION = $(shell grep 'static const char \*const VERSION *=' softhdcuvid.cpp | awk '{ print $$7 }' | sed -e 's/[";]//g')
GIT_REV = $(shell git describe --always 2>/dev/null) GIT_REV = $(shell git describe --always 2>/dev/null)
### The name of the distribution archive:
### The directory environment: ### The directory environment:
@ -87,14 +99,7 @@ APIVERSION = $(call PKGCFG,apiversion)
-include $(PLGCFG) -include $(PLGCFG)
### The name of the distribution archive:
ARCHIVE = $(PLUGIN)-$(VERSION)
PACKAGE = vdr-$(ARCHIVE)
### The name of the shared object file:
SOFILE = libvdr-$(PLUGIN).so
### Parse softhddevice config ### Parse softhddevice config
@ -103,16 +108,20 @@ CONFIG += -DUSE_ALSA
_CFLAGS += $(shell pkg-config --cflags alsa) _CFLAGS += $(shell pkg-config --cflags alsa)
LIBS += $(shell pkg-config --libs alsa) LIBS += $(shell pkg-config --libs alsa)
endif endif
ifeq ($(OSS),1) ifeq ($(OSS),1)
CONFIG += -DUSE_OSS CONFIG += -DUSE_OSS
endif endif
ifeq ($(OPENGL),1) ifeq ($(OPENGL),1)
_CFLAGS += $(shell pkg-config --cflags libva-glx) _CFLAGS += $(shell pkg-config --cflags libva-glx)
LIBS += $(shell pkg-config --libs libva-glx) LIBS += $(shell pkg-config --libs libva-glx)
endif endif
ifeq ($(OPENGLOSD),1) ifeq ($(OPENGLOSD),1)
CONFIG += -DUSE_OPENGLOSD CONFIG += -DUSE_OPENGLOSD
endif endif
ifeq ($(OPENGL),1) ifeq ($(OPENGL),1)
CONFIG += -DUSE_GLX CONFIG += -DUSE_GLX
_CFLAGS += $(shell pkg-config --cflags gl glu glew) _CFLAGS += $(shell pkg-config --cflags gl glu glew)
@ -122,18 +131,43 @@ LIBS += $(shell pkg-config --libs glew)
_CFLAGS += $(shell pkg-config --cflags freetype2) _CFLAGS += $(shell pkg-config --cflags freetype2)
LIBS += $(shell pkg-config --libs freetype2) LIBS += $(shell pkg-config --libs freetype2)
endif endif
ifeq ($(VAAPI),1)
CONFIG += -DVAAPI
LIBPLACEBO=1
PLUGIN = softhdvaapi
endif
ifeq ($(LIBPLACEBO),1) ifeq ($(LIBPLACEBO),1)
CONFIG += -DPLACEBO CONFIG += -DPLACEBO
endif endif
ifeq ($(CUVID),1)
CONFIG += -DCUVID # enable CUVID decoder
ifeq ($(YADIF),1)
CONFIG += -DYADIF # Yadif only with CUVID
endif
endif
ARCHIVE = $(PLUGIN)-$(VERSION)
PACKAGE = vdr-$(ARCHIVE)
### The name of the shared object file:
SOFILE = libvdr-$(PLUGIN).so
# #
# Test that libswresample is available # Test that libswresample is available
# #
ifneq (exists, $(shell pkg-config libswresample && echo exists)) #ifneq (exists, $(shell pkg-config libswresample && echo exists))
$(warning ******************************************************************) # $(warning ******************************************************************)
$(warning 'libswresample' not found!) # $(warning 'libswresample' not found!)
$(error ******************************************************************) # $(error ******************************************************************)
endif #endif
# #
# Test and set config for libavutil # Test and set config for libavutil
@ -179,11 +213,11 @@ CONFIG += -DUSE_SWRESAMPLE
_CFLAGS += $(shell pkg-config --cflags libswresample) _CFLAGS += $(shell pkg-config --cflags libswresample)
LIBS += $(shell pkg-config --libs libswresample) LIBS += $(shell pkg-config --libs libswresample)
endif endif
#ifeq ($(AVRESAMPLE),1) ifeq ($(AVRESAMPLE),1)
#CONFIG += -DUSE_AVRESAMPLE CONFIG += -DUSE_AVRESAMPLE
#_CFLAGS += $(shell pkg-config --cflags libavresample) _CFLAGS += $(shell pkg-config --cflags libavresample)
#LIBS += $(shell pkg-config --libs libavresample) LIBS += $(shell pkg-config --libs libavresample)
#endif endif
#_CFLAGS += $(shell pkg-config --cflags libavcodec x11 x11-xcb xcb xcb-icccm) #_CFLAGS += $(shell pkg-config --cflags libavcodec x11 x11-xcb xcb xcb-icccm)
#LIBS += -lrt $(shell pkg-config --libs libavcodec x11 x11-xcb xcb xcb-icccm) #LIBS += -lrt $(shell pkg-config --libs libavcodec x11 x11-xcb xcb xcb-icccm)
@ -200,7 +234,11 @@ ifeq ($(LIBPLACEBO),1)
LIBS += -lplacebo -lglut LIBS += -lplacebo -lglut
endif endif
LIBS += -lGLEW -lGLX -ldl -lcuda -L/usr/local/cuda/targets/x86_64-linux/lib -lcudart -lnvcuvid ifeq ($(CUVID),1)
LIBS += -lcuda -L/usr/local/cuda/targets/x86_64-linux/lib -lcudart -lnvcuvid
endif
LIBS += -lGLEW -lGLX -ldl
### Includes and Defines (add further entries here): ### Includes and Defines (add further entries here):
INCLUDES += INCLUDES +=
@ -218,12 +256,12 @@ override CFLAGS += $(_CFLAGS) $(DEFINES) $(INCLUDES) \
### The object files (add further files here): ### The object files (add further files here):
OBJS = $(PLUGIN).o softhddev.o video.o audio.o codec.o ringbuffer.o OBJS = softhdcuvid.o softhddev.o video.o audio.o codec.o ringbuffer.o
ifeq ($(OPENGLOSD),1) ifeq ($(OPENGLOSD),1)
OBJS += openglosd.o OBJS += openglosd.o
endif endif
SRCS = $(wildcard $(OBJS:.o=.c)) $(PLUGIN).cpp SRCS = $(wildcard $(OBJS:.o=.c)) softhdcuvid.cpp
### The main target: ### The main target:

View File

@ -40,13 +40,17 @@ A software and GPU emulated UHD output device plugin for VDR.
To compile you must have the 'requires' installed. To compile you must have the 'requires' installed.
This is a fork of johns original softhddevice work and I reworked ist to support HEVC with CUDA and opengl output. This is a fork of johns original softhddevice work and I reworked it to support HEVC with CUDA and opengl output.
Currently I have tested it with a GTX 1050 from NVIDIA. SD, HD and UHD is working. Currently I have tested it with a GTX 1050 from NVIDIA. SD, HD and UHD is working.
Current Status NVIDA: Current Status NVIDIA:
The CUDA driver supports HEVC with 8 Bit and 10 Bit up to UHD resolution. Opengl is able to output also 10 Bit, but NVIDIA does not support to output 10 Bit via HDMI. The CUDA driver supports HEVC with 8 Bit and 10 Bit up to UHD resolution. Opengl is able to output also 10 Bit, but NVIDIA does not support to output 10 Bit via HDMI.
Only via DisplayPort you can get 10 Bit output to a compatible screen. This is a restriction from NVIDIA. Only via DisplayPort you can get 10 Bit output to a compatible screen. This is a restriction from NVIDIA.
Current Status with VAAPI
You need libplacebo.
It is still beta and I tested it with Intel VAAPI. If you have problmes with the shaders then copy the drirc file in your home directory as .drirc
AMD VAAPI is broken by AMD and will not work currently. The vaapi_deinterlace is broken and the amdgpu driver is instable. I have not testet with amdgpupro
You have to adapt the Makefile to your needs. I use FFMPEG 4.0 You have to adapt the Makefile to your needs. I use FFMPEG 4.0
The Makefile expects the CUDA SDK in /usr/local/cuda. Currently it is tested with CUDA 10 The Makefile expects the CUDA SDK in /usr/local/cuda. Currently it is tested with CUDA 10

179
codec.c
View File

@ -1,3 +1,4 @@
/// ///
/// @file codec.c @brief Codec functions /// @file codec.c @brief Codec functions
/// ///
@ -200,16 +201,20 @@ static int Codec_get_buffer2(AVCodecContext * video_ctx, AVFrame * frame, int fl
if (!decoder->GetFormatDone) { // get_format missing if (!decoder->GetFormatDone) { // get_format missing
enum AVPixelFormat fmts[2]; enum AVPixelFormat fmts[2];
fprintf(stderr, "codec: buggy libav, use ffmpeg\n"); // fprintf(stderr, "codec: buggy libav, use ffmpeg\n");
Warning(_("codec: buggy libav, use ffmpeg\n")); // Warning(_("codec: buggy libav, use ffmpeg\n"));
fmts[0] = video_ctx->pix_fmt; fmts[0] = video_ctx->pix_fmt;
fmts[1] = AV_PIX_FMT_NONE; fmts[1] = AV_PIX_FMT_NONE;
Codec_get_format(video_ctx, fmts); Codec_get_format(video_ctx, fmts);
} }
if (decoder->hwaccel_get_buffer && (AV_PIX_FMT_VDPAU == decoder->hwaccel_pix_fmt || AV_PIX_FMT_CUDA == decoder->hwaccel_pix_fmt)) { #if 0
if (decoder->hwaccel_get_buffer && (AV_PIX_FMT_VDPAU == decoder->hwaccel_pix_fmt ||
AV_PIX_FMT_CUDA == decoder->hwaccel_pix_fmt ||
AV_PIX_FMT_VAAPI == decoder->hwaccel_pix_fmt)) {
//Debug(3,"hwaccel get_buffer\n"); //Debug(3,"hwaccel get_buffer\n");
return decoder->hwaccel_get_buffer(video_ctx, frame, flags); return decoder->hwaccel_get_buffer(video_ctx, frame, flags);
} }
#endif
//Debug(3, "codec: fallback to default get_buffer\n"); //Debug(3, "codec: fallback to default get_buffer\n");
return avcodec_default_get_buffer2(video_ctx, frame, flags); return avcodec_default_get_buffer2(video_ctx, frame, flags);
} }
@ -268,6 +273,7 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
} }
name = "NULL"; name = "NULL";
#ifdef CUVID
if (!strcasecmp(VideoGetDriverName(), "cuvid")) { if (!strcasecmp(VideoGetDriverName(), "cuvid")) {
switch (codec_id) { switch (codec_id) {
case AV_CODEC_ID_MPEG2VIDEO: case AV_CODEC_ID_MPEG2VIDEO:
@ -281,11 +287,11 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
break; break;
} }
} }
#endif
if (name && (video_codec = avcodec_find_decoder_by_name(name))) { if (name && (video_codec = avcodec_find_decoder_by_name(name))) {
Debug(3, "codec: decoder found\n"); Debug(3, "codec: decoder found\n");
} else { } else if ((video_codec = avcodec_find_decoder(codec_id))==NULL) {
Debug(3,"Decoder %s not supported\n",name); Debug(3,"Decoder %s not supported %p\n",name,video_codec);
Fatal(_(" No decoder found")); Fatal(_(" No decoder found"));
} }
@ -309,13 +315,45 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
decoder->VideoCtx->pkt_timebase.den = 90000; decoder->VideoCtx->pkt_timebase.den = 90000;
decoder->VideoCtx->framerate.num = 50; decoder->VideoCtx->framerate.num = 50;
decoder->VideoCtx->framerate.den = 1; decoder->VideoCtx->framerate.den = 1;
decoder->VideoCtx->extra_hw_frames = 8; // VIDEO_SURFACES_MAX +1
pthread_mutex_lock(&CodecLockMutex); pthread_mutex_lock(&CodecLockMutex);
// open codec // open codec
#ifdef YADIF #ifdef YADIF
deint = 0; deint = 2;
#endif #endif
#ifdef VAAPI
if (video_codec->capabilities & (AV_CODEC_CAP_AUTO_THREADS)) {
Debug(3,"codec: auto threads enabled");
decoder->VideoCtx->thread_count = 0;
}
if (video_codec->capabilities & AV_CODEC_CAP_TRUNCATED) {
Debug(3,"codec: supports truncated packets");
//decoder->VideoCtx->flags |= CODEC_FLAG_TRUNCATED;
}
// FIXME: own memory management for video frames.
if (video_codec->capabilities & AV_CODEC_CAP_DR1) {
Debug(3,"codec: can use own buffer management");
}
if (video_codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) {
Debug(3,"codec: supports frame threads");
decoder->VideoCtx->thread_count = 0;
// decoder->VideoCtx->thread_type |= FF_THREAD_FRAME;
}
if (video_codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
Debug(3,"codec: supports slice threads");
decoder->VideoCtx->thread_count = 0;
// decoder->VideoCtx->thread_type |= FF_THREAD_SLICE;
}
if (av_opt_set_int(decoder->VideoCtx, "refcounted_frames", 1, 0)<0)
Fatal(_("VAAPI Refcounts invalid\n"));
decoder->VideoCtx->thread_safe_callbacks = 0;
#endif
#ifdef CUVID
if (strcmp(decoder->VideoCodec->long_name,"Nvidia CUVID MPEG2VIDEO decoder") == 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", deint ,0) < 0) { // adaptive if (av_opt_set_int(decoder->VideoCtx->priv_data, "deint", deint ,0) < 0) { // adaptive
pthread_mutex_unlock(&CodecLockMutex); pthread_mutex_unlock(&CodecLockMutex);
@ -348,7 +386,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"));
} }
} }
#endif
if ((ret = avcodec_open2(decoder->VideoCtx, video_codec, NULL)) < 0) { if ((ret = avcodec_open2(decoder->VideoCtx, video_codec, NULL)) < 0) {
pthread_mutex_unlock(&CodecLockMutex); pthread_mutex_unlock(&CodecLockMutex);
@ -363,24 +401,25 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
//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;
// av_log_set_level(AV_LOG_DEBUG);
av_log_set_level(0);
decoder->VideoCtx->get_format = Codec_get_format; decoder->VideoCtx->get_format = Codec_get_format;
decoder->VideoCtx->get_buffer2 = Codec_get_buffer2; decoder->VideoCtx->get_buffer2 = Codec_get_buffer2;
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(decoder->VideoCodec->long_name,"Nvidia CUVID") != NULL) decoder->VideoCtx->hwaccel_context = VideoGetHwAccelContext(decoder->HwDecoder);
decoder->VideoCtx->hwaccel_context = VideoGetHwAccelContext(decoder->HwDecoder);
// //
// Prepare frame buffer for decoder // Prepare frame buffer for decoder
// //
#if 0
if (!(decoder->Frame = av_frame_alloc())) { if (!(decoder->Frame = av_frame_alloc())) {
Fatal(_("codec: can't allocate video decoder frame buffer\n")); Fatal(_("codec: can't allocate video decoder frame buffer\n"));
} }
#endif
// reset buggy ffmpeg/libav flag // reset buggy ffmpeg/libav flag
decoder->GetFormatDone = 0; decoder->GetFormatDone = 0;
#ifdef YADIF #ifdef YADIF
@ -401,7 +440,7 @@ void CodecVideoClose(VideoDecoder *video_decoder)
{ {
// FIXME: play buffered data // FIXME: play buffered data
av_frame_free(&video_decoder->Frame); // callee does checks // av_frame_free(&video_decoder->Frame); // callee does checks
Debug(3,"CodecVideoClose\n"); Debug(3,"CodecVideoClose\n");
if (video_decoder->VideoCtx) { if (video_decoder->VideoCtx) {
@ -465,37 +504,100 @@ extern int CuvidTestSurfaces();
extern int init_filters(AVCodecContext * dec_ctx,void * decoder,AVFrame *frame); extern int init_filters(AVCodecContext * dec_ctx,void * decoder,AVFrame *frame);
extern int push_filters(AVCodecContext * dec_ctx,void * decoder,AVFrame *frame); extern int push_filters(AVCodecContext * dec_ctx,void * decoder,AVFrame *frame);
#endif #endif
#ifdef VAAPI
void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
{
AVCodecContext *video_ctx = decoder->VideoCtx;
if (video_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
int ret;
AVPacket pkt[1];
AVFrame *frame;
*pkt = *avpkt; // use copy
ret = avcodec_send_packet(video_ctx, pkt);
if (ret < 0) {
Debug(4,"codec: sending video packet failed");
return;
}
frame = av_frame_alloc();
ret = avcodec_receive_frame(video_ctx, frame);
if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) {
Debug(4,"codec: receiving video frame failed");
av_frame_free(&frame);
return;
}
if (ret >= 0) {
if (decoder->filter ) {
if (decoder->filter == 1) {
if (init_filters(video_ctx,decoder->HwDecoder,frame) < 0) {
Debug(3,"video: Init of VAAPI deint Filter failed\n");
decoder->filter = 0;
}
else {
Debug(3,"Init VAAPI deint ok\n");
decoder->filter = 2;
}
}
if (frame->interlaced_frame && decoder->filter == 2 && (frame->height != 720)) { // broken ZDF sends Interlaced flag
ret = push_filters(video_ctx,decoder->HwDecoder,frame);
return;
}
}
VideoRenderFrame(decoder->HwDecoder, video_ctx, frame);
}
else {
av_frame_free(&frame);
}
}
}
#endif
#ifdef CUVID
void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt) void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
{ {
AVCodecContext *video_ctx; AVCodecContext *video_ctx;
AVFrame *frame; AVFrame *frame
;
int ret,ret1; int ret,ret1;
int got_frame; int got_frame;
int consumed = 0; int consumed = 0;
static uint64_t first_time = 0;
const AVPacket *pkt; const AVPacket *pkt;
next_part: next_part:
video_ctx = decoder->VideoCtx; video_ctx = decoder->VideoCtx;
frame = decoder->Frame;
pkt = avpkt; // use copy pkt = avpkt; // use copy
got_frame = 0; got_frame = 0;
// printf("decode packet %d\n",(GetusTicks()-first_time)/1000000);
ret1 = avcodec_send_packet(video_ctx, pkt); ret1 = avcodec_send_packet(video_ctx, pkt);
// first_time = GetusTicks();
if (ret1 >= 0) { if (ret1 >= 0) {
consumed = 1; consumed = 1;
} }
if (!CuvidTestSurfaces())
usleep(1000);
//printf("send packet to decode %s\n",consumed?"ok":"Full");
if ((ret1 == AVERROR(EAGAIN) || ret1 == AVERROR_EOF || ret1 >= 0) && CuvidTestSurfaces()) { if ((ret1 == AVERROR(EAGAIN) || ret1 == AVERROR_EOF || ret1 >= 0) && CuvidTestSurfaces()) {
ret = 0; ret = 0;
while ((ret >= 0) && CuvidTestSurfaces()) { // get frames until empty snd Surfaces avail. while ((ret >= 0) && CuvidTestSurfaces()) { // get frames until empty snd Surfaces avail.
frame = av_frame_alloc();
ret = avcodec_receive_frame(video_ctx, frame); // get new frame ret = avcodec_receive_frame(video_ctx, frame); // get new frame
if (ret >= 0) { // one is avail. if (ret >= 0) { // one is avail.
got_frame = 1; got_frame = 1;
} }
else { else {
got_frame = 0; got_frame = 0;
} }
// printf("got %s packet from decoder\n",got_frame?"1":"no");
if (got_frame) { // frame completed if (got_frame) { // frame completed
#ifdef YADIF #ifdef YADIF
if (decoder->filter ) { if (decoder->filter ) {
@ -511,12 +613,13 @@ next_part:
} }
if (frame->interlaced_frame && decoder->filter == 2 && (frame->height != 720)) { // broken ZDF sends Interlaced flag if (frame->interlaced_frame && decoder->filter == 2 && (frame->height != 720)) { // broken ZDF sends Interlaced flag
ret = push_filters(video_ctx,decoder->HwDecoder,frame); ret = push_filters(video_ctx,decoder->HwDecoder,frame);
av_frame_unref(frame); // av_frame_unref(frame);
continue; continue;
} }
} }
#endif #endif
#ifdef FFMPEG_WORKAROUND_ARTIFACTS #ifdef FFMPEG_WORKAROUND_ARTIFACTS
if (!CodecUsePossibleDefectFrames && decoder->FirstKeyFrame) { if (!CodecUsePossibleDefectFrames && decoder->FirstKeyFrame) {
decoder->FirstKeyFrame++; decoder->FirstKeyFrame++;
if (frame->key_frame || (decoder->FirstKeyFrame > 3)) { // key frame is not reliable if (frame->key_frame || (decoder->FirstKeyFrame > 3)) { // key frame is not reliable
@ -524,31 +627,35 @@ next_part:
decoder->FirstKeyFrame = 0; decoder->FirstKeyFrame = 0;
VideoRenderFrame(decoder->HwDecoder, video_ctx, frame); VideoRenderFrame(decoder->HwDecoder, video_ctx, frame);
} }
av_frame_unref(frame); // av_frame_unref(frame);
} else { } else {
//DisplayPts(video_ctx, frame); //DisplayPts(video_ctx, frame);
VideoRenderFrame(decoder->HwDecoder, video_ctx, frame); VideoRenderFrame(decoder->HwDecoder, video_ctx, frame);
av_frame_unref(frame); // av_frame_unref(frame);
} }
#else #else
//DisplayPts(video_ctx, frame); //DisplayPts(video_ctx, frame);
VideoRenderFrame(decoder->HwDecoder, video_ctx, frame); VideoRenderFrame(decoder->HwDecoder, video_ctx, frame);
av_frame_unref(frame); // av_frame_unref(frame);
#endif #endif
// printf("got frame\n"); } else {
} else { av_frame_free(&frame);
// printf("codec: got no frame %d send %d\n",ret,ret1); // printf("codec: got no frame %d send %d\n",ret,ret1);
} }
} }
if (!CuvidTestSurfaces()) {
usleep(1000);
}
} else { } else {
// consumed = 1; // consumed = 1;
} }
if (!consumed) { if (!consumed) {
goto next_part; // try again to stuff decoder goto next_part; // try again to stuff decoder
} }
}
}
#endif
/** /**
** Flush the video decoder. ** Flush the video decoder.
@ -702,7 +809,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id)
Debug(3, "codec: using audio codec ID %#06x (%s)\n", codec_id, Debug(3, "codec: using audio codec ID %#06x (%s)\n", codec_id,
avcodec_get_name(codec_id)); avcodec_get_name(codec_id));
if (!(audio_codec = avcodec_find_decoder_by_name(avcodec_get_name(codec_id)))) { if (!(audio_codec = avcodec_find_decoder(codec_id))) {
// if (!(audio_codec = avcodec_find_decoder(codec_id))) { // if (!(audio_codec = avcodec_find_decoder(codec_id))) {
Fatal(_("codec: codec ID %#06x not found\n"), codec_id); Fatal(_("codec: codec ID %#06x not found\n"), codec_id);
// FIXME: errors aren't fatal // FIXME: errors aren't fatal
@ -1291,7 +1398,7 @@ void CodecAudioEnqueue(AudioDecoder * audio_decoder, int16_t * data, int count)
#ifdef USE_AUDIO_DRIFT_CORRECTION #ifdef USE_AUDIO_DRIFT_CORRECTION
if ((CodecAudioDrift & CORRECT_PCM) && audio_decoder->AvResample) { if ((CodecAudioDrift & CORRECT_PCM) && audio_decoder->AvResample) {
int16_t buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 + int16_t buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 +
FF_INPUT_BUFFER_PADDING_SIZE] __attribute__ ((aligned(16))); AV_INPUT_BUFFER_PADDING_SIZE] __attribute__ ((aligned(16)));
int16_t buftmp[MAX_CHANNELS][(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4]; int16_t buftmp[MAX_CHANNELS][(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4];
int consumed; int consumed;
int i; int i;
@ -1383,7 +1490,7 @@ int myavcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples,
// in the caller may be able to be optimized. // in the caller may be able to be optimized.
ret = avcodec_receive_frame(avctx,frame); ret = avcodec_receive_frame(avctx,frame);
if (ret == 0) if (ret == 0)
got_frame = true; got_frame = 1;
if (ret == AVERROR(EAGAIN)) if (ret == AVERROR(EAGAIN))
ret = 0; ret = 0;
if (ret == 0) if (ret == 0)
@ -1392,7 +1499,7 @@ int myavcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples,
ret = 0; ret = 0;
else if (ret < 0) else if (ret < 0)
{ {
Debug(3, "codec/audio: audio decode error: %1 (%2)\n",av_make_error_string(error, sizeof(error), ret),got_frame); // Debug(3, "codec/audio: audio decode error: %1 (%2)\n",av_make_error_string(error, sizeof(error), ret),got_frame);
return ret; return ret;
} }
else else
@ -1434,7 +1541,7 @@ int myavcodec_decode_audio3(AVCodecContext *avctx, int16_t *samples,
void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt) void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
{ {
int16_t buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 + int16_t buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 +
FF_INPUT_BUFFER_PADDING_SIZE] __attribute__ ((aligned(16))); AV_INPUT_BUFFER_PADDING_SIZE] __attribute__ ((aligned(16)));
int buf_sz; int buf_sz;
int l; int l;
AVCodecContext *audio_ctx; AVCodecContext *audio_ctx;
@ -1470,7 +1577,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
// need to resample audio // need to resample audio
if (audio_decoder->ReSample) { if (audio_decoder->ReSample) {
int16_t outbuf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 + int16_t outbuf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 +
FF_INPUT_BUFFER_PADDING_SIZE] AV_INPUT_BUFFER_PADDING_SIZE]
__attribute__ ((aligned(16))); __attribute__ ((aligned(16)));
int outlen; int outlen;

View File

@ -61,10 +61,10 @@ struct _video_decoder_
//#ifdef FFMPEG_WORKAROUND_ARTIFACTS //#ifdef FFMPEG_WORKAROUND_ARTIFACTS
int FirstKeyFrame; ///< flag first frame int FirstKeyFrame; ///< flag first frame
//#endif //#endif
AVFrame *Frame; ///< decoded video frame // AVFrame *Frame; ///< decoded video frame
#ifdef YADIF
int filter; // flag for yadif filter int filter; // flag for deint filter
#endif
/* hwaccel options */ /* hwaccel options */
enum HWAccelID hwaccel_id; enum HWAccelID hwaccel_id;
char *hwaccel_device; char *hwaccel_device;

28
drirc Normal file
View File

@ -0,0 +1,28 @@
<driconf>
<device screen="0" driver="i965">
<application name="Default">
<option name="always_flush_cache" value="false" />
<option name="mesa_no_error" value="false" />
<option name="precise_trig" value="false" />
<option name="mesa_glthread" value="false" />
<option name="disable_glsl_line_continuations" value="false" />
<option name="disable_blend_func_extended" value="false" />
<option name="shader_precompile" value="true" />
<option name="clamp_max_samples" value="-1" />
<option name="allow_glsl_extension_directive_midshader" value="false" />
<option name="allow_rgb10_configs" value="true" />
<option name="allow_glsl_cross_stage_interpolation_mismatch" value="false" />
<option name="force_glsl_abs_sqrt" value="false" />
<option name="dual_color_blend_by_location" value="false" />
<option name="bo_reuse" value="1" />
<option name="always_flush_batch" value="false" />
<option name="allow_rgb565_configs" value="true" />
<option name="allow_glsl_builtin_variable_redeclaration" value="true" />
<option name="force_glsl_extensions_warn" value="false" />
<option name="disable_throttling" value="false" />
<option name="force_glsl_version" value="330" />
<option name="glsl_zero_init" value="false" />
<option name="allow_higher_compat_version" value="true" />
</application>
</device>
</driconf>

View File

@ -18,7 +18,7 @@ void ConvertColor(const GLint &colARGB, glm::vec4 &col) {
* cShader * cShader
****************************************************************************************/ ****************************************************************************************/
#ifdef CUVID
const char *rectVertexShader = const char *rectVertexShader =
"#version 330 core \n\ "#version 330 core \n\
\ \
@ -116,6 +116,106 @@ void main() \
} \ } \
"; ";
#else
const char *rectVertexShader =
"\n\
\
layout (location = 0) in vec2 position; \
out vec4 rectCol; \
uniform vec4 inColor; \
uniform mat4 projection; \
\
void main() \
{ \
gl_Position = projection * vec4(position.x, position.y, 0.0, 1.0); \
rectCol = inColor; \
} \
";
const char *rectFragmentShader =
"#version 330 core \n\
\
in vec4 rectCol; \
out vec4 color; \
\
void main() \
{ \
color = rectCol; \
} \
";
const char *textureVertexShader =
"\n\
\
layout (location = 0) in vec2 position; \
layout (location = 1) in vec2 texCoords; \
\
out vec2 TexCoords; \
out vec4 alphaValue;\
\
uniform mat4 projection; \
uniform vec4 alpha; \
\
void main() \
{ \
gl_Position = projection * vec4(position.x, position.y, 0.0, 1.0); \
TexCoords = texCoords; \
alphaValue = alpha; \
} \
";
const char *textureFragmentShader =
"\n\
in vec2 TexCoords; \
in vec4 alphaValue; \
out vec4 color; \
\
uniform sampler2D screenTexture; \
\
void main() \
{ \
color = texture(screenTexture, TexCoords) * alphaValue; \
} \
";
const char *textVertexShader =
"\n\
\
layout (location = 0) in vec2 position; \
layout (location = 1) in vec2 texCoords; \
\
out vec2 TexCoords; \
out vec4 textColor; \
\
uniform mat4 projection; \
uniform vec4 inColor; \
\
void main() \
{ \
gl_Position = projection * vec4(position.x, position.y, 0.0, 1.0); \
TexCoords = texCoords; \
textColor = inColor; \
} \
";
const char *textFragmentShader =
"\n\
in vec2 TexCoords; \
in vec4 textColor; \
\
out vec4 color; \
\
uniform sampler2D glyphTexture; \
\
void main() \
{ \
vec4 sampled = vec4(1.0, 1.0, 1.0, texture(glyphTexture, TexCoords).r); \
color = textColor * sampled; \
} \
";
#endif
static cShader *Shaders[stCount]; static cShader *Shaders[stCount];
void cShader::Use(void) { void cShader::Use(void) {
@ -1588,7 +1688,7 @@ extern "C" int GlxInitopengl();
bool cOglThread::InitOpenGL(void) { bool cOglThread::InitOpenGL(void) {
#ifdef PLACEBO #ifdef PLACEBO
const char *displayName = X11DisplayName; const char *displayName = X11DisplayName;
if (!displayName) { if (!displayName) {
displayName = getenv("DISPLAY"); displayName = getenv("DISPLAY");

View File

@ -67,7 +67,7 @@ extern "C"
/// vdr-plugin version number. /// vdr-plugin version number.
/// Makefile extracts the version number for generating the file name /// Makefile extracts the version number for generating the file name
/// for the distribution archive. /// for the distribution archive.
static const char *const VERSION = "1.1.0" static const char *const VERSION = "2.0.0"
#ifdef GIT_REV #ifdef GIT_REV
"-GIT" GIT_REV "-GIT" GIT_REV
#endif #endif
@ -75,7 +75,7 @@ static const char *const VERSION = "1.1.0"
/// vdr-plugin description. /// vdr-plugin description.
static const char *const DESCRIPTION = static const char *const DESCRIPTION =
trNOOP("A software and GPU emulated HD device"); trNOOP("A software and GPU emulated UHD device");
/// vdr-plugin text of main menu entry /// vdr-plugin text of main menu entry
static const char *MAINMENUENTRY = trNOOP("SoftUHD"); static const char *MAINMENUENTRY = trNOOP("SoftUHD");
@ -232,7 +232,7 @@ class cSoftRemote:public cRemote
** @param release flag key released ** @param release flag key released
*/ */
bool Put(const char *code, bool repeat = false, bool release = false) { bool Put(const char *code, bool repeat = false, bool release = false) {
return cRemote::Put(code, repeat, release); return cRemote::Put(code, repeat, release);
} }
}; };
@ -249,40 +249,38 @@ extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat,
int release, const char *letter) int release, const char *letter)
{ {
cRemote *remote; cRemote *remote;
cSoftRemote *csoft; cSoftRemote *csoft;
if (!keymap || !key) { if (!keymap || !key) {
return; return;
} }
// find remote // find remote
for (remote = Remotes.First(); remote; remote = Remotes.Next(remote)) { for (remote = Remotes.First(); remote; remote = Remotes.Next(remote)) {
if (!strcmp(remote->Name(), keymap)) { if (!strcmp(remote->Name(), keymap)) {
break; break;
} }
} }
// if remote not already exists, create it // if remote not already exists, create it
if (remote) { if (remote) {
csoft = (cSoftRemote *) remote; csoft = (cSoftRemote *) remote;
} else { } else {
dsyslog("[softhddev]%s: remote '%s' not found\n", __FUNCTION__, dsyslog("[softhddev]%s: remote '%s' not found\n", __FUNCTION__, keymap);
keymap); csoft = new cSoftRemote(keymap);
csoft = new cSoftRemote(keymap);
} }
//dsyslog("[softhddev]%s %s, %s, %s\n", __FUNCTION__, keymap, key, letter); //dsyslog("[softhddev]%s %s, %s, %s\n", __FUNCTION__, keymap, key, letter);
if (key[1]) { // no single character if (key[1]) { // no single character
if (!csoft->Put(key, repeat, release) && letter if (!csoft->Put(key, repeat, release) && letter && !cRemote::IsLearning()) {
&& !cRemote::IsLearning()) { cCharSetConv conv;
cCharSetConv conv; unsigned code;
unsigned code;
code = Utf8CharGet(conv.Convert(letter)); code = Utf8CharGet(conv.Convert(letter));
if (code <= 0xFF) { if (code <= 0xFF) {
cRemote::Put(KBDKEY(code)); // feed it for edit mode cRemote::Put(KBDKEY(code)); // feed it for edit mode
} }
} }
} else if (!csoft->Put(key, repeat, release)) { } else if (!csoft->Put(key, repeat, release)) {
cRemote::Put(KBDKEY(key[0])); // feed it for edit mode cRemote::Put(KBDKEY(key[0])); // feed it for edit mode
} }
} }

861
video.c

File diff suppressed because it is too large Load Diff