Fix jump in recordings

Fix in CUVID Bufferhandling
This commit is contained in:
jojo61 2019-10-11 11:47:11 +02:00
parent 6eb0a7f35a
commit a2b52bb804
4 changed files with 218 additions and 158 deletions

26
audio.c
View File

@ -2044,7 +2044,7 @@ static int AudioNextRing(void)
// stop, if not enough in next buffer // stop, if not enough in next buffer
used = RingBufferUsedBytes(AudioRing[AudioRingRead].RingBuffer); used = RingBufferUsedBytes(AudioRing[AudioRingRead].RingBuffer);
if (AudioStartThreshold * 4 < used || (AudioVideoIsReady if (AudioStartThreshold * 10 < used || (AudioVideoIsReady
&& AudioStartThreshold < used)) { && AudioStartThreshold < used)) {
return 0; return 0;
} }
@ -2228,6 +2228,24 @@ static const AudioModule *AudioModules[] = {
&NoopModule, &NoopModule,
}; };
void AudioDelayms(int delayms) {
int count;
unsigned char *p;
#ifdef DEBUG
printf("Try Delay Audio for %d ms Samplerate %d Channels %d bps %d\n",
delayms,AudioRing[AudioRingWrite].HwSampleRate,AudioRing[AudioRingWrite].HwChannels,AudioBytesProSample);
#endif
count = delayms * AudioRing[AudioRingWrite].HwSampleRate * AudioRing[AudioRingWrite].HwChannels * AudioBytesProSample / 1000;
if (delayms < 5000 && delayms > 0) { // not more than 5seconds
p = calloc(1,count);
RingBufferWrite(AudioRing[AudioRingWrite].RingBuffer, p, count);
free(p);
}
}
/** /**
** Place samples in audio output queue. ** Place samples in audio output queue.
** **
@ -2334,7 +2352,7 @@ void AudioEnqueue(const void *samples, int count)
} }
// forced start or enough video + audio buffered // forced start or enough video + audio buffered
// for some exotic channels * 4 too small // for some exotic channels * 4 too small
if (AudioStartThreshold * 4 < n || (AudioVideoIsReady if (AudioStartThreshold * 10 < n || (AudioVideoIsReady
// if ((AudioVideoIsReady // if ((AudioVideoIsReady
&& AudioStartThreshold < n)) { && AudioStartThreshold < n)) {
// restart play-back // restart play-back
@ -2390,7 +2408,7 @@ void AudioVideoReady(int64_t pts)
Timestamp2String(pts), Timestamp2String(audio_pts), Timestamp2String(pts), Timestamp2String(audio_pts),
(int)(pts - audio_pts) / 90, AudioRunning ? "running" : "ready"); (int)(pts - audio_pts) / 90, AudioRunning ? "running" : "ready");
if (!AudioRunning || 1) { if (!AudioRunning) {
int skip; int skip;
// buffer ~15 video frames // buffer ~15 video frames
@ -2420,8 +2438,6 @@ void AudioVideoReady(int64_t pts)
} }
else { else {
Debug(3,"No audio skip -> should skip %d\n",skip/90); Debug(3,"No audio skip -> should skip %d\n",skip/90);
AudioRunning = 0;
usleep(abs(skip/90)*1000);
} }
// FIXME: skip<0 we need bigger audio buffer // FIXME: skip<0 we need bigger audio buffer

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR \n" "Project-Id-Version: VDR \n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2019-01-04 09:19+0100\n" "POT-Creation-Date: 2019-10-04 14:23+0200\n"
"PO-Revision-Date: blabla\n" "PO-Revision-Date: blabla\n"
"Last-Translator: blabla\n" "Last-Translator: blabla\n"
"Language-Team: blabla\n" "Language-Team: blabla\n"
@ -251,9 +251,6 @@ msgstr ""
msgid "audio: %6dHz supports %d %d %d %d %d %d %d %d channels\n" msgid "audio: %6dHz supports %d %d %d %d %d %d %d %d channels\n"
msgstr "" msgstr ""
msgid "codec: buggy libav, use ffmpeg\n"
msgstr ""
msgid "codec: can't allocate vodeo decoder\n" msgid "codec: can't allocate vodeo decoder\n"
msgstr "" msgstr ""
@ -266,6 +263,9 @@ msgstr ""
msgid "codec: can't allocate video codec context\n" msgid "codec: can't allocate video codec context\n"
msgstr "" msgstr ""
msgid "VAAPI Refcounts invalid\n"
msgstr ""
msgid "codec: can't set option deint to video codec!\n" msgid "codec: can't set option deint to video codec!\n"
msgstr "" msgstr ""
@ -284,6 +284,9 @@ msgstr ""
msgid "codec: can't allocate video decoder frame buffer\n" msgid "codec: can't allocate video decoder frame buffer\n"
msgstr "" msgstr ""
msgid "video: Init of YADIF Filter failed\n"
msgstr ""
msgid "codec: can't allocate audio decoder\n" msgid "codec: can't allocate audio decoder\n"
msgstr "" msgstr ""
@ -327,21 +330,9 @@ msgstr ""
msgid "codec/audio: can't open resample\n" msgid "codec/audio: can't open resample\n"
msgstr "" msgstr ""
msgid "codec/audio: latm\n" msgid "A software and GPU emulated UHD device"
msgstr "" msgstr ""
msgid "codec/audio: bad audio frame\n"
msgstr ""
msgid "codec/audio: error more than one frame data\n"
msgstr ""
msgid "codec/audio: no frame\n"
msgstr ""
msgid "A software and GPU emulated HD device"
msgstr "Ein Software und GPU emulieres HD-Gerät"
msgid "SoftUHD" msgid "SoftUHD"
msgstr "" msgstr ""
@ -801,15 +792,12 @@ msgstr ""
msgid "[softhddev] ready%s\n" msgid "[softhddev] ready%s\n"
msgstr "" msgstr ""
msgid "video/glx: can't make glx context current\n" msgid "video/egl: GlxSetupWindow can't make egl context current\n"
msgstr "" msgstr ""
msgid "video/glx: no v-sync\n" msgid "video/glx: no v-sync\n"
msgstr "" msgstr ""
msgid "glewinit failed\n"
msgstr ""
msgid "video/glx: no GLX support\n" msgid "video/glx: no GLX support\n"
msgstr "" msgstr ""
@ -820,15 +808,6 @@ msgstr ""
msgid "did not get FBconfig" msgid "did not get FBconfig"
msgstr "" msgstr ""
msgid "video/glx: can't get a RGB visual\n"
msgstr ""
msgid "video/glx: no valid visual found\n"
msgstr ""
msgid "video/glx: need atleast 8-bits per RGB\n"
msgstr ""
msgid "video/glx: can't create glx context\n" msgid "video/glx: can't create glx context\n"
msgstr "" msgstr ""
@ -850,6 +829,9 @@ msgstr ""
msgid "video/glx: SGI v-sync enabled\n" msgid "video/glx: SGI v-sync enabled\n"
msgstr "" msgstr ""
msgid "video/egl: can't create egl context\n"
msgstr ""
msgid "video/cuvid: surface needed not set\n" msgid "video/cuvid: surface needed not set\n"
msgstr "" msgstr ""
@ -857,6 +839,27 @@ msgstr ""
msgid "video/cuvid: release surface %#08x, which is not in use\n" msgid "video/cuvid: release surface %#08x, which is not in use\n"
msgstr "" msgstr ""
msgid "Wrong ES version \n"
msgstr ""
msgid " Could not bind API!\n"
msgstr ""
msgid "Can't get EGL Extentions\n"
msgstr ""
msgid "Could not initialize EGL.\n"
msgstr ""
msgid "Could not create EGL Context\n"
msgstr ""
msgid "Could not create EGL surface!\n"
msgstr ""
msgid "Could not make context current!\n"
msgstr ""
msgid "video/cuvid: out of decoders\n" msgid "video/cuvid: out of decoders\n"
msgstr "" msgstr ""
@ -866,7 +869,7 @@ msgstr ""
msgid "video/cuvid: decoder not in decoder list.\n" msgid "video/cuvid: decoder not in decoder list.\n"
msgstr "" msgstr ""
msgid "video/glx: glx error\n" msgid "video/egl: egl init error\n"
msgstr "" msgstr ""
#, c-format #, c-format
@ -952,6 +955,9 @@ msgstr ""
msgid "Failed initializing libplacebo renderer\n" msgid "Failed initializing libplacebo renderer\n"
msgstr "" msgstr ""
msgid "video/egl: can't create thread egl context\n"
msgstr ""
msgid "video: can't queue cancel video display thread\n" msgid "video: can't queue cancel video display thread\n"
msgstr "" msgstr ""
@ -986,6 +992,9 @@ msgstr ""
msgid "video: error closing display\n" msgid "video: error closing display\n"
msgstr "" msgstr ""
#~ msgid "A software and GPU emulated HD device"
#~ msgstr "Ein Software und GPU emulieres HD-Gerät"
#~ msgid "Use studio levels (vdpau only)" #~ msgid "Use studio levels (vdpau only)"
#~ msgstr "Benutze Studio Levels (nur vdpau)" #~ msgstr "Benutze Studio Levels (nur vdpau)"

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 = "2.0.0" static const char *const VERSION = "2.1.0"
#ifdef GIT_REV #ifdef GIT_REV
"-GIT" GIT_REV "-GIT" GIT_REV
#endif #endif

277
video.c
View File

@ -445,7 +445,7 @@ static xcb_atom_t NetWmStateAbove;
extern uint32_t VideoSwitch; ///< ticks for channel switch extern uint32_t VideoSwitch; ///< ticks for channel switch
#endif #endif
extern void AudioVideoReady(int64_t); ///< tell audio video is ready extern void AudioVideoReady(int64_t); ///< tell audio video is ready
extern int AudioDelay;
#ifdef USE_VIDEO_THREAD #ifdef USE_VIDEO_THREAD
@ -456,7 +456,7 @@ static pthread_mutex_t VideoLockMutex; ///< video lock mutex
pthread_mutex_t OSDMutex; ///< OSD update mutex pthread_mutex_t OSDMutex; ///< OSD update mutex
#endif #endif
int skipwait;
static pthread_t VideoDisplayThread; ///< video display thread static pthread_t VideoDisplayThread; ///< video display thread
//static pthread_cond_t VideoDisplayWakeupCond; ///< wakeup condition variable //static pthread_cond_t VideoDisplayWakeupCond; ///< wakeup condition variable
@ -489,6 +489,7 @@ static char EnableDPMSatBlackScreen; ///< flag we should enable dpms at black sc
static int EglEnabled; ///< use EGL static int EglEnabled; ///< use EGL
static int GlxVSyncEnabled = 1; ///< enable/disable v-sync static int GlxVSyncEnabled = 1; ///< enable/disable v-sync
#ifdef CUVID #ifdef CUVID
static GLXContext eglSharedContext; ///< shared gl context static GLXContext eglSharedContext; ///< shared gl context
static GLXContext eglContext; ///< our gl context static GLXContext eglContext; ///< our gl context
@ -758,6 +759,33 @@ static void VideoUpdateOutput(AVRational input_aspect_ratio, int input_width,
*crop_x, *crop_y); *crop_x, *crop_y);
return; return;
} }
static uint64_t test_time=0;
///
/// Lock video thread.
///
#define VideoThreadLock(void)\
{\
if (VideoThread) {\
if (pthread_mutex_lock(&VideoLockMutex)) {\
Error(_("video: can't lock thread\n"));\
}\
}\
}
// test_time = GetusTicks();
// printf("Lock start....");
///
/// Unlock video thread.
///
#define VideoThreadUnlock(void)\
{\
if (VideoThread) {\
if (pthread_mutex_unlock(&VideoLockMutex)) {\
Error(_("video: can't unlock thread\n"));\
}\
}\
}
// printf("Video Locked for %d\n",(GetusTicks()-test_time)/1000);
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// GLX // GLX
@ -1435,7 +1463,11 @@ struct ext_buf {
int fd; int fd;
#ifdef CUVID #ifdef CUVID
CUexternalMemory mem; CUexternalMemory mem;
CUdeviceptr buf; CUmipmappedArray mma;
// CUdeviceptr buf;
CUexternalSemaphore ss;
CUexternalSemaphore ws;
const struct pl_sysnc *sysnc;
#endif #endif
}; };
#endif #endif
@ -1523,8 +1555,8 @@ typedef struct _cuvid_decoder_
#ifdef PLACEBO #ifdef PLACEBO
struct pl_image pl_images[CODEC_SURFACES_MAX+1]; // images for Placebo chain struct pl_image pl_images[CODEC_SURFACES_MAX+1]; // images for Placebo chain
// const struct pl_tex *pl_tex_in[CODEC_SURFACES_MAX+1][2]; // Textures in image // const struct pl_tex *pl_tex_in[CODEC_SURFACES_MAX+1][2]; // Textures in image
const struct pl_buf *pl_buf_Y[2],*pl_buf_UV[2]; // buffer for Texture upload // const struct pl_buf *pl_buf_Y[2],*pl_buf_UV[2]; // buffer for Texture upload
struct ext_buf ebuf[4]; // for managing vk buffer struct ext_buf ebuf[CODEC_SURFACES_MAX+1]; // for managing vk buffer
#endif #endif
@ -1765,7 +1797,7 @@ static void CuvidDestroySurfaces(CuvidDecoder * decoder)
} }
} }
#ifdef PLACEBO #ifdef PLACEBO
#ifdef CUVID #ifdef CUVID1
pl_buf_destroy(p->gpu,&decoder->pl_buf_Y[0]); pl_buf_destroy(p->gpu,&decoder->pl_buf_Y[0]);
pl_buf_destroy(p->gpu,&decoder->pl_buf_UV[0]); pl_buf_destroy(p->gpu,&decoder->pl_buf_UV[0]);
pl_buf_destroy(p->gpu,&decoder->pl_buf_Y[1]); pl_buf_destroy(p->gpu,&decoder->pl_buf_Y[1]);
@ -1986,7 +2018,7 @@ static bool create_context_cb(EGLDisplay display,
EGL_RED_SIZE, 10, EGL_RED_SIZE, 10,
EGL_GREEN_SIZE, 10, EGL_GREEN_SIZE, 10,
EGL_BLUE_SIZE, 10, EGL_BLUE_SIZE, 10,
EGL_ALPHA_SIZE, 8, EGL_ALPHA_SIZE, 2,
EGL_RENDERABLE_TYPE, rend, EGL_RENDERABLE_TYPE, rend,
EGL_NONE EGL_NONE
}; };
@ -1994,13 +2026,20 @@ static bool create_context_cb(EGLDisplay display,
attribs = attributes10; attribs = attributes10;
// if (!eglChooseConfig(display, attributes10, NULL, 0, &num_configs)) { // try 10 Bit if (!eglChooseConfig(display, attributes10, NULL, 0, &num_configs)) { // try 10 Bit
Debug(3," 10 Bit egl Failed\n");
attribs = attributes8; attribs = attributes8;
if (!eglChooseConfig(display, attributes8, NULL, 0, &num_configs)) { // try 8 Bit if (!eglChooseConfig(display, attributes8, NULL, 0, &num_configs)) { // try 8 Bit
num_configs = 0; num_configs = 0;
} }
// } } else if (num_configs == 0) {
EglCheck();
Debug(3," 10 Bit egl Failed\n");
attribs = attributes8;
if (!eglChooseConfig(display, attributes8, NULL, 0, &num_configs)) { // try 8 Bit
num_configs = 0;
}
}
EGLConfig *configs = malloc(sizeof(EGLConfig) * num_configs); EGLConfig *configs = malloc(sizeof(EGLConfig) * num_configs);
if (!eglChooseConfig(display, attribs, configs, num_configs, &num_configs)) if (!eglChooseConfig(display, attribs, configs, num_configs, &num_configs))
num_configs = 0; num_configs = 0;
@ -2240,7 +2279,7 @@ static void CuvidDelHwDecoder(CuvidDecoder * decoder)
int i; int i;
Debug(3,"cuvid del hw decoder \n"); Debug(3,"cuvid del hw decoder \n");
if (decoder == CuvidDecoders[0]) if (decoder == CuvidDecoders[0])
pthread_mutex_lock(&VideoLockMutex); VideoThreadLock();
#ifndef PLACEBO #ifndef PLACEBO
#ifdef CUVID #ifdef CUVID
glXMakeCurrent(XlibDisplay, VideoWindow, eglContext); glXMakeCurrent(XlibDisplay, VideoWindow, eglContext);
@ -2254,7 +2293,7 @@ Debug(3,"cuvid del hw decoder \n");
CuvidDestroySurfaces(decoder); CuvidDestroySurfaces(decoder);
} }
if (decoder == CuvidDecoders[0]) if (decoder == CuvidDecoders[0])
pthread_mutex_unlock(&VideoLockMutex); VideoThreadUnlock();
// glXMakeCurrent(XlibDisplay, None, NULL); // glXMakeCurrent(XlibDisplay, None, NULL);
for (i = 0; i < CuvidDecoderN; ++i) { for (i = 0; i < CuvidDecoderN; ++i) {
@ -2344,7 +2383,7 @@ void SDK_CHECK_ERROR_GL() {
void void
createTextureDst(CuvidDecoder * decoder,int anz, unsigned int size_x, unsigned int size_y, enum AVPixelFormat PixFmt) createTextureDst(CuvidDecoder * decoder,int anz, unsigned int size_x, unsigned int size_y, enum AVPixelFormat PixFmt)
{ {
int n,i,size=1; int n,i,size=1,fd;
const struct pl_fmt *fmt; const struct pl_fmt *fmt;
struct pl_tex *tex; struct pl_tex *tex;
struct pl_image *img; struct pl_image *img;
@ -2368,14 +2407,14 @@ createTextureDst(CuvidDecoder * decoder,int anz, unsigned int size_x, unsigned i
size = 2; size = 2;
} }
if (decoder->pl_images[i].planes[n].texture) { if (decoder->pl_images[i].planes[n].texture) {
#ifdef VAAPI //#ifdef VAAPI
if (p->has_dma_buf && decoder->pl_images[i].planes[n].texture->params.shared_mem.handle.fd) { if (decoder->pl_images[i].planes[n].texture->params.shared_mem.handle.fd) {
close(decoder->pl_images[i].planes[n].texture->params.shared_mem.handle.fd); close(decoder->pl_images[i].planes[n].texture->params.shared_mem.handle.fd);
} }
#endif //#endif
pl_tex_destroy(p->gpu,&decoder->pl_images[i].planes[n].texture); // delete old texture pl_tex_destroy(p->gpu,&decoder->pl_images[i].planes[n].texture); // delete old texture
} }
// decoder->pl_tex_in[i][n] = pl_tex_create(p->gpu, &(struct pl_tex_params) {
if (p->has_dma_buf == 0) { if (p->has_dma_buf == 0) {
decoder->pl_images[i].planes[n].texture = pl_tex_create(p->gpu, &(struct pl_tex_params) { decoder->pl_images[i].planes[n].texture = pl_tex_create(p->gpu, &(struct pl_tex_params) {
.w = n==0?size_x:size_x/2, .w = n==0?size_x:size_x/2,
@ -2386,11 +2425,11 @@ createTextureDst(CuvidDecoder * decoder,int anz, unsigned int size_x, unsigned i
.host_writable = true, .host_writable = true,
.sample_mode = PL_TEX_SAMPLE_LINEAR, .sample_mode = PL_TEX_SAMPLE_LINEAR,
.address_mode = PL_TEX_ADDRESS_CLAMP, .address_mode = PL_TEX_ADDRESS_CLAMP,
.export_handle = PL_HANDLE_FD,
}); });
} }
// make planes for image // make planes for image
pl = &decoder->pl_images[i].planes[n]; pl = &decoder->pl_images[i].planes[n];
// pl->texture = decoder->pl_tex_in[i][n];
pl->components = n==0?1:2; pl->components = n==0?1:2;
pl->shift_x = 0.0f; pl->shift_x = 0.0f;
pl->shift_y = 0.0f; pl->shift_y = 0.0f;
@ -2408,6 +2447,30 @@ createTextureDst(CuvidDecoder * decoder,int anz, unsigned int size_x, unsigned i
if (!ok) { if (!ok) {
Fatal(_("Unable to create placebo textures")); Fatal(_("Unable to create placebo textures"));
} }
#ifdef CUVID
fd = dup(decoder->pl_images[i].planes[n].texture->shared_mem.handle.fd);
CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = {
.type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD,
.handle.fd = fd,
.size = decoder->pl_images[i].planes[n].texture->shared_mem.size, // image_width * image_height * bytes,
.flags = 0,
};
checkCudaErrors(cuImportExternalMemory(&decoder->ebuf[i*2+n].mem, &ext_desc)); // Import Memory segment
CUDA_EXTERNAL_MEMORY_MIPMAPPED_ARRAY_DESC tex_desc = {
.offset = decoder->pl_images[i].planes[n].texture->shared_mem.offset,
.arrayDesc = {
.Width = n==0?size_x:size_x/2,
.Height = n==0?size_y:size_y/2,
.Depth = 0,
.Format = PixFmt == AV_PIX_FMT_NV12 ? CU_AD_FORMAT_UNSIGNED_INT8:CU_AD_FORMAT_UNSIGNED_INT16,
.NumChannels = n==0?1:2,
.Flags = 0,
},
.numLevels = 1,
};
checkCudaErrors(cuExternalMemoryGetMappedMipmappedArray(&decoder->ebuf[i*2+n].mma,decoder->ebuf[i*2+n].mem,&tex_desc));
checkCudaErrors(cuMipmappedArrayGetLevel(&decoder->cu_array[i][n],decoder->ebuf[i*2+n].mma,0));
#endif
} }
// make image // make image
img = &decoder->pl_images[i]; img = &decoder->pl_images[i];
@ -2425,7 +2488,7 @@ createTextureDst(CuvidDecoder * decoder,int anz, unsigned int size_x, unsigned i
img->height = size_y; img->height = size_y;
img->num_overlays = 0; img->num_overlays = 0;
} }
#ifdef CUVID #ifdef CUVID1
decoder->pl_buf_Y[0] = pl_buf_create(p->gpu, &(struct pl_buf_params) { // buffer for Y texture upload decoder->pl_buf_Y[0] = pl_buf_create(p->gpu, &(struct pl_buf_params) { // buffer for Y texture upload
.type = PL_BUF_TEX_TRANSFER, .type = PL_BUF_TEX_TRANSFER,
.size = size_x * size_y * size, .size = size_x * size_y * size,
@ -2534,7 +2597,7 @@ void generateVAAPIImage(CuvidDecoder * decoder,int index, const AVFrame *frame,i
{ {
int n; int n;
VAStatus status; VAStatus status;
static int toggle = 0; int toggle = 0;
uint64_t first_time; uint64_t first_time;
VADRMPRIMESurfaceDescriptor desc; VADRMPRIMESurfaceDescriptor desc;
@ -2608,31 +2671,55 @@ void generateVAAPIImage(CuvidDecoder * decoder,int index, const AVFrame *frame,i
#ifdef CUVID #ifdef CUVID
// copy image and process using CUDA // copy image and process using CUDA
void generateCUDAImage(CuvidDecoder * decoder,int index, const AVFrame *frame,int image_width , int image_height, int bytes) void generateCUDAImage(CuvidDecoder * decoder,int index, const AVFrame *frame,int image_width , int image_height, int bytes)
{
int n;
for (n = 0; n < 2; n++) { //
// widthInBytes must account for the chroma plane
// elements being two samples wide.
CUDA_MEMCPY2D cpy = {
.srcMemoryType = CU_MEMORYTYPE_DEVICE,
.dstMemoryType = CU_MEMORYTYPE_ARRAY,
.srcDevice = (CUdeviceptr)frame->data[n],
.srcPitch = frame->linesize[n],
.srcY = 0,
.dstArray = decoder->cu_array[index][n],
.WidthInBytes = image_width * bytes,
.Height = n==0?image_height:image_height/2 ,
};
checkCudaErrors(cuMemcpy2D(&cpy));
}
}
#if 0
void generateCUDAImage(CuvidDecoder * decoder,int index, const AVFrame *frame,int image_width , int image_height, int bytes)
{ {
int n; int n;
static int toggle = 0; static int toggle = 0;
uint64_t first_time; uint64_t first_time;
// struct ext_buf ebuf[2]; // struct ext_buf ebuf[2];
//first_time = GetusTicks(); first_time = GetusTicks();
VideoThreadLock(); VideoThreadLock();
//printf("Upload buf to texture for frame %d in size %d-%d\n",index,image_width,image_height); //printf("Upload buf to texture for frame %d in size %d-%d\n",index,image_width,image_height);
if (decoder->pl_buf_Y[toggle]) if (decoder->pl_buf_Y[toggle])
while (pl_buf_poll(p->gpu,decoder->pl_buf_Y[toggle], 000000)) { // 5 ms while (pl_buf_poll(p->gpu,decoder->pl_buf_Y[toggle], 000000)) { // 5 ms
VideoThreadUnlock(); VideoThreadUnlock();
usleep(1); usleep(100);
VideoThreadLock(); VideoThreadLock();
} }
else else {
VideoThreadUnlock();
return; return;
}
if (decoder->pl_buf_UV[toggle]) if (decoder->pl_buf_UV[toggle])
while (pl_buf_poll(p->gpu,decoder->pl_buf_UV[toggle], 000000)) { while (pl_buf_poll(p->gpu,decoder->pl_buf_UV[toggle], 000000)) {
VideoThreadUnlock(); VideoThreadUnlock();
usleep(1); usleep(100);
VideoThreadLock(); VideoThreadLock();
} }
else else {
VideoThreadUnlock();
return; return;
}
// printf("1 got Image buffers %2.2f\n",(float)(GetusTicks()-first_time)/1000000.0); // printf("1 got Image buffers %2.2f\n",(float)(GetusTicks()-first_time)/1000000.0);
for (n = 0; n < 2; n++) { // Copy 2 Planes from Cuda decoder to upload Buffer for (n = 0; n < 2; n++) { // Copy 2 Planes from Cuda decoder to upload Buffer
@ -2666,9 +2753,12 @@ void generateCUDAImage(CuvidDecoder * decoder,int index, const AVFrame *frame,in
// toggle = toggle==0?1:0; // toggle = toggle==0?1:0;
// pl_gpu_flush(p->gpu); // pl_gpu_flush(p->gpu);
VideoThreadUnlock(); VideoThreadUnlock();
if (((float)(GetusTicks()-first_time)/1000000.0) > 15.0) {
// printf("made Image buffers %2.2f ms\n",(float)(GetusTicks()-first_time)/1000000.0);
}
} }
#endif #endif
#endif
#else #else
void void
@ -2727,7 +2817,6 @@ createTextureDst(CuvidDecoder * decoder,int anz, unsigned int size_x, unsigned i
void generateCUDAImage(CuvidDecoder * decoder,int index, const AVFrame *frame,int image_width , int image_height, int bytes) void generateCUDAImage(CuvidDecoder * decoder,int index, const AVFrame *frame,int image_width , int image_height, int bytes)
{ {
int n; int n;
for (n = 0; n < 2; n++) { // for (n = 0; n < 2; n++) { //
// widthInBytes must account for the chroma plane // widthInBytes must account for the chroma plane
// elements being two samples wide. // elements being two samples wide.
@ -2768,7 +2857,7 @@ void generateVAAPIImage(CuvidDecoder * decoder,int index, const AVFrame *frame,i
{ {
int n,i; int n,i;
VAStatus status; VAStatus status;
static int toggle = 0;
uint64_t first_time; uint64_t first_time;
VADRMPRIMESurfaceDescriptor desc; VADRMPRIMESurfaceDescriptor desc;
@ -3220,6 +3309,7 @@ static enum AVPixelFormat Cuvid_get_format(CuvidDecoder * decoder,
if (*fmt_idx != AV_PIX_FMT_CUDA) { if (*fmt_idx != AV_PIX_FMT_CUDA) {
Fatal(_("video: no valid profile found\n")); Fatal(_("video: no valid profile found\n"));
} }
decoder->newchannel = 1;
if (ist->GetFormatDone) if (ist->GetFormatDone)
return AV_PIX_FMT_CUDA; return AV_PIX_FMT_CUDA;
#endif #endif
@ -3885,14 +3975,6 @@ static void CuvidRenderFrame(CuvidDecoder * decoder,
int surface; int surface;
enum AVColorSpace color; enum AVColorSpace color;
#ifdef CUVID
if (skipwait > 1) {
skipwait--;
av_frame_free(&frame);
return;
}
#endif
// update aspect ratio changes // update aspect ratio changes
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,60,100) #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53,60,100)
if (decoder->InputWidth && decoder->InputHeight if (decoder->InputWidth && decoder->InputHeight
@ -3978,7 +4060,6 @@ static void CuvidRenderFrame(CuvidDecoder * decoder,
VideoThreadLock(); VideoThreadLock();
vaSyncSurface(decoder->VaDisplay,(unsigned int)frame->data[3]); vaSyncSurface(decoder->VaDisplay,(unsigned int)frame->data[3]);
output = av_frame_alloc(); output = av_frame_alloc();
// av_frame_ref(output,frame);
av_hwframe_transfer_data(output,frame,0); av_hwframe_transfer_data(output,frame,0);
av_frame_copy_props(output,frame); av_frame_copy_props(output,frame);
// printf("Save Surface ID %d %p %p\n",surface,decoder->pl_images[surface].planes[0].texture,decoder->pl_images[surface].planes[1].texture); // printf("Save Surface ID %d %p %p\n",surface,decoder->pl_images[surface].planes[0].texture,decoder->pl_images[surface].planes[1].texture);
@ -4231,17 +4312,21 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused))int lev
// img->color.light = PL_COLOR_LIGHT_SCENE_709_1886; // img->color.light = PL_COLOR_LIGHT_SCENE_709_1886;
// img->color.light = PL_COLOR_LIGHT_DISPLAY; // img->color.light = PL_COLOR_LIGHT_DISPLAY;
break; break;
#ifdef CUVID
case AVCOL_SPC_BT2020_NCL: case AVCOL_SPC_BT2020_NCL:
img->repr.sys = PL_COLOR_SYSTEM_BT_2020_NC; img->repr.sys = PL_COLOR_SYSTEM_BT_2020_NC;
memcpy(&img->repr,&pl_color_repr_uhdtv,sizeof(struct pl_color_repr)); memcpy(&img->repr,&pl_color_repr_uhdtv,sizeof(struct pl_color_repr));
memcpy(&img->color,&pl_color_space_bt2020_hlg,sizeof(struct pl_color_space)); memcpy(&img->color,&pl_color_space_bt2020_hlg,sizeof(struct pl_color_space));
deband.grain = 0.0f; // no grain in HDR deband.grain = 0.0f; // no grain in HDR
img->color.sig_scale = 2.0f;
#ifdef VAAPI
render_params.peak_detect_params = NULL;
#endif
// img->color.primaries = PL_COLOR_PRIM_BT_2020; // img->color.primaries = PL_COLOR_PRIM_BT_2020;
// img->color.transfer = PL_COLOR_TRC_HLG; // img->color.transfer = PL_COLOR_TRC_HLG;
// img->color.light = PL_COLOR_LIGHT_SCENE_HLG; // img->color.light = PL_COLOR_LIGHT_SCENE_HLG;
break; break;
#endif
default: // fallback default: // fallback
img->repr.sys = PL_COLOR_SYSTEM_BT_709; img->repr.sys = PL_COLOR_SYSTEM_BT_709;
memcpy(&img->color,&pl_color_space_bt709,sizeof(struct pl_color_space)); memcpy(&img->color,&pl_color_space_bt709,sizeof(struct pl_color_space));
@ -4320,7 +4405,7 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused))int lev
target->num_overlays = 0; target->num_overlays = 0;
} }
if (decoder->newchannel && current == 0 ) { if (decoder->newchannel && current == 0 ) {
colors.brightness = -1.0f; colors.brightness = -1.0f;
colors.contrast = 0.0f; colors.contrast = 0.0f;
if (!pl_render_image(p->renderer, &decoder->pl_images[current], target, &render_params)) { if (!pl_render_image(p->renderer, &decoder->pl_images[current], target, &render_params)) {
@ -4470,14 +4555,10 @@ static void CuvidDisplayFrame(void)
// last_time = GetusTicks(); // last_time = GetusTicks();
//printf("Roundtrip Displayframe %d\n",diff); //printf("Roundtrip Displayframe %d\n",diff);
if (diff < 15000 && skipwait != 1) { if (diff < 15000) {
//printf("Sleep %d\n",15000-diff); //printf("Sleep %d\n",15000-diff);
usleep((15000 - diff));// * 1000); usleep((15000 - diff));// * 1000);
} else if (skipwait != 1) { }
#ifdef CUVID
usleep(15000);
#endif
}
#endif #endif
if (!p->swapchain) if (!p->swapchain)
@ -4486,6 +4567,7 @@ static void CuvidDisplayFrame(void)
//last_time = GetusTicks(); //last_time = GetusTicks();
#ifdef CUVID #ifdef CUVID
first_time = GetusTicks();
VideoThreadLock(); VideoThreadLock();
if (!first) { if (!first) {
// last_time = GetusTicks(); // last_time = GetusTicks();
@ -4494,17 +4576,15 @@ static void CuvidDisplayFrame(void)
pl_swapchain_swap_buffers(p->swapchain); // swap buffers pl_swapchain_swap_buffers(p->swapchain); // swap buffers
// printf("submit and swap %d\n",(GetusTicks()-last_time)/1000000); // printf("submit and swap %d\n",(GetusTicks()-last_time)/1000000);
} }
#endif #endif
first = 0; first = 0;
last_time = GetusTicks(); last_time = GetusTicks();
while (!pl_swapchain_start_frame(p->swapchain, &frame)) { // get new frame wait for previous to swap while (!pl_swapchain_start_frame(p->swapchain, &frame)) { // get new frame wait for previous to swap
usleep(5); usleep(5);
} }
// last_time = GetusTicks();
//printf("wait for frame %d\n",(GetusTicks()-last_time)/1000000);
if (!frame.fbo) { if (!frame.fbo) {
#ifdef CUVID #ifdef CUVID
@ -4571,7 +4651,7 @@ static void CuvidDisplayFrame(void)
decoder->StartCounter++; decoder->StartCounter++;
filled = atomic_read(&decoder->SurfacesFilled); filled = atomic_read(&decoder->SurfacesFilled);
//printf("Filled %d\n",filled);
// 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
@ -4664,6 +4744,7 @@ static void CuvidDisplayFrame(void)
// printf("submit and swap %d us\n",(GetusTicks()-first_time)/1000); // printf("submit and swap %d us\n",(GetusTicks()-first_time)/1000);
#endif #endif
VideoThreadUnlock(); VideoThreadUnlock();
// printf("Display time %d\n",(GetusTicks()-first_time)/1000000);
#else #else
#ifdef CUVID #ifdef CUVID
glXGetVideoSyncSGI (&Count); // get current frame glXGetVideoSyncSGI (&Count); // get current frame
@ -4720,7 +4801,7 @@ static int64_t CuvidGetClock(const CuvidDecoder * decoder)
return decoder->PTS - 20 * 90 * (2 * atomic_read(&decoder->SurfacesFilled) - decoder->SurfaceField - 2 + 2); return decoder->PTS - 20 * 90 * (2 * atomic_read(&decoder->SurfacesFilled) - decoder->SurfaceField - 2 + 2);
} }
// + 2 in driver queue // + 2 in driver queue
return decoder->PTS - 20 * 90 * (atomic_read(&decoder->SurfacesFilled)+SWAP_BUFFER_SIZE-1); // +2 return decoder->PTS - 20 * 90 * (atomic_read(&decoder->SurfacesFilled)+SWAP_BUFFER_SIZE-1 +2); // +2
} }
/// ///
@ -4790,7 +4871,7 @@ void CuvidGetStats(CuvidDecoder * decoder, int *missed, int *duped,
/// ///
/// @param decoder CUVID hw decoder /// @param decoder CUVID hw decoder
/// ///
void AudioDelayms(int);
static void CuvidSyncDecoder(CuvidDecoder * decoder) static void CuvidSyncDecoder(CuvidDecoder * decoder)
{ {
int filled; int filled;
@ -4858,27 +4939,11 @@ static void CuvidSyncDecoder(CuvidDecoder * decoder)
// decoder->Frameproc = diff/90; // decoder->Frameproc = diff/90;
// printf("Roundtrip sync %d\n",(GetusTicks()-last_time)/1000); // printf("Roundtrip sync %d\n",(GetusTicks()-last_time)/1000);
// last_time = GetusTicks(); // last_time = GetusTicks();
#ifdef CUVID1
if (skipwait <= 1) {
if ((diff/90) > 55) {
skipwait = 1;
} else if ((diff/90) < -200 && filled > 1) {
skipwait = 3;
decoder->SyncCounter = 1;
} else if ((diff/90) < -100 && filled > 1) {
skipwait = 2;
decoder->SyncCounter = 1;
} else {
decoder->SyncCounter = 1;
skipwait = 0;
}
}
#else
skipwait =0;
#endif
#if 0 #if 0
if (abs(diff/90)> 55 ) { if (abs(diff/90)> 0 ) {
printf(" Diff %d filled %d skipwait %d \n",diff/90,filled,skipwait); printf(" Diff %d filled %d \n",diff/90,filled);
} }
#endif #endif
if (abs(diff) > 5000 * 90) { // more than 5s if (abs(diff) > 5000 * 90) { // more than 5s
@ -4888,27 +4953,25 @@ static void CuvidSyncDecoder(CuvidDecoder * decoder)
// goto out; // goto out;
} else if (diff > 100 * 90) { } else if (diff > 100 * 90) {
// FIXME: this quicker sync step, did not work with new code! // FIXME: this quicker sync step, did not work with new code!
err = CuvidMessage(4, "video: slow down video, duping frame\n"); err = CuvidMessage(4, "video: slow down video, duping frame %d\n",diff/90);
++decoder->FramesDuped; ++decoder->FramesDuped;
decoder->SyncCounter = 1; decoder->SyncCounter = 1;
goto out; goto out;
} else if (diff > 55 * 90) { } else if (diff > 55 * 90) {
err = CuvidMessage(3, "video: slow down video, duping frame\n"); err = CuvidMessage(3, "video: slow down video, duping frame %d \n",diff/90);
++decoder->FramesDuped; ++decoder->FramesDuped;
decoder->SyncCounter = 1; decoder->SyncCounter = 1;
goto out; goto out;
} else if (diff < -25 * 90) { } else if ((diff < -35 * 90)) {
err = CuvidMessage(3, "video: speed up video, droping frame\n"); if (filled > 2) {
++decoder->FramesDropped; err = CuvidMessage(3, "video: speed up video, droping frame %d\n",diff/90);
CuvidAdvanceDecoderFrame(decoder); ++decoder->FramesDropped;
CuvidAdvanceDecoderFrame(decoder);
// if ((AudioDelay == 0) && (filled < 3)) }
// AudioDelay = abs(diff/90); else if ((diff < -65 * 90)) // give it some time to get frames to drop
// if (filled >2 && diff < -55) AudioDelayms(abs(diff/90));
// CuvidAdvanceDecoderFrame(decoder);
// filled = atomic_read(&decoder->SurfacesFilled); decoder->SyncCounter = 3;
// Debug(3,"hinter drop frame filled %d\n",atomic_read(&decoder->SurfacesFilled));
decoder->SyncCounter = 1;
} }
#if defined(DEBUG) || defined(AV_INFO) #if defined(DEBUG) || defined(AV_INFO)
if (!decoder->SyncCounter && decoder->StartCounter < 1000) { if (!decoder->SyncCounter && decoder->StartCounter < 1000) {
@ -5104,7 +5167,7 @@ static void CuvidDisplayHandlerThread(void)
decoded = 0; decoded = 0;
#ifndef PLACEBO #ifndef PLACEBO
pthread_mutex_lock(&VideoLockMutex); VideoThreadLock();
#endif #endif
for (i = 0; i < CuvidDecoderN; ++i) { for (i = 0; i < CuvidDecoderN; ++i) {
@ -5144,7 +5207,7 @@ static void CuvidDisplayHandlerThread(void)
} }
#ifndef PLACEBO #ifndef PLACEBO
pthread_mutex_unlock(&VideoLockMutex); VideoThreadUnlock();
#endif #endif
if (!decoded) { // nothing decoded, sleep if (!decoded) { // nothing decoded, sleep
@ -5153,7 +5216,7 @@ static void CuvidDisplayHandlerThread(void)
} }
#ifdef PLACEBO #ifdef PLACEBO
// usleep(1000); usleep(1000);
#endif #endif
// all decoder buffers are full // all decoder buffers are full
@ -5168,9 +5231,9 @@ static void CuvidDisplayHandlerThread(void)
} }
} }
#ifndef PLACEBO #ifndef PLACEBO
pthread_mutex_lock(&VideoLockMutex); VideoThreadLock();
CuvidSyncDisplayFrame(); CuvidSyncDisplayFrame();
pthread_mutex_unlock(&VideoLockMutex); VideoThreadUnlock();
#endif #endif
return; return;
} }
@ -5740,35 +5803,7 @@ void VideoSetVideoEventCallback(void (*videoEventCallback)(void))
#ifdef USE_VIDEO_THREAD #ifdef USE_VIDEO_THREAD
static uint64_t test_time=0;
///
/// Lock video thread.
///
void VideoThreadLock(void)
{
if (VideoThread) {
if (pthread_mutex_lock(&VideoLockMutex)) {
Error(_("video: can't lock thread\n"));
}
// test_time = GetusTicks();
// printf("Lock start....");
}
}
///
/// Unlock video thread.
///
void VideoThreadUnlock(void)
{
if (VideoThread) {
if (pthread_mutex_unlock(&VideoLockMutex)) {
Error(_("video: can't unlock thread\n"));
}
// printf("Video Locked for %d\n",(GetusTicks()-test_time)/1000000);
}
}
#ifdef PLACEBO #ifdef PLACEBO
void pl_log_intern(void *stream, enum pl_log_level level, const char *msg) void pl_log_intern(void *stream, enum pl_log_level level, const char *msg)
@ -6010,7 +6045,7 @@ static void VideoThreadExit(void)
if (pthread_cancel(VideoDisplayThread)) { if (pthread_cancel(VideoDisplayThread)) {
Error(_("video: can't queue cancel video display thread\n")); Error(_("video: can't queue cancel video display thread\n"));
} }
usleep(200000); // 200ms
if (pthread_join(VideoDisplayThread, &retval) || retval != PTHREAD_CANCELED) { if (pthread_join(VideoDisplayThread, &retval) || retval != PTHREAD_CANCELED) {
Error(_("video: can't cancel video display thread\n")); Error(_("video: can't cancel video display thread\n"));
} }