Skip to content

Commit c519e97

Browse files
authored
Merge pull request #347 from thesword53/decode-fix
Fix some potential deadlocks and H.264 video decode error when seeking
2 parents bd98448 + ae80f52 commit c519e97

File tree

2 files changed

+31
-7
lines changed

2 files changed

+31
-7
lines changed

src/vabackend.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,14 @@ static void* resolveSurfaces(void *param) {
428428
ctx->surfaceQueueReadIdx = 0;
429429
}
430430

431+
if (surface->decodeFailed) {
432+
pthread_mutex_lock(&surface->mutex);
433+
surface->resolving = 0;
434+
pthread_cond_signal(&surface->cond);
435+
pthread_mutex_unlock(&surface->mutex);
436+
continue;
437+
}
438+
431439
CUdeviceptr deviceMemory = (CUdeviceptr) NULL;
432440
unsigned int pitch = 0;
433441

@@ -440,6 +448,10 @@ static void* resolveSurfaces(void *param) {
440448

441449
//LOG("Mapping surface %d", surface->pictureIdx);
442450
if (CHECK_CUDA_RESULT(cv->cuvidMapVideoFrame(ctx->decoder, surface->pictureIdx, &deviceMemory, &pitch, &procParams))) {
451+
pthread_mutex_lock(&surface->mutex);
452+
surface->resolving = 0;
453+
pthread_cond_signal(&surface->cond);
454+
pthread_mutex_unlock(&surface->mutex);
443455
continue;
444456
}
445457
//LOG("Mapped surface %d to %p (%d)", surface->pictureIdx, (void*)deviceMemory, pitch);
@@ -1048,17 +1060,17 @@ static VAStatus nvCreateContext(
10481060
if (num_render_targets) {
10491061
// Update the decoder configuration to match the passed in surfaces.
10501062
NVSurface *surface = (NVSurface *) getObjectPtr(drv, render_targets[0]);
1063+
if (!surface) {
1064+
return VA_STATUS_ERROR_INVALID_PARAMETER;
1065+
}
10511066
cfg->surfaceFormat = surface->format;
10521067
cfg->chromaFormat = surface->chromaFormat;
10531068
cfg->bitDepth = surface->bitDepth;
10541069
}
10551070

1056-
if (drv->surfaceCount <= 1 && num_render_targets == 0) {
1057-
LOG("0/1 surfaces have been passed to vaCreateContext, this might cause errors. Setting surface count to 32");
1058-
num_render_targets = 32;
1059-
}
1071+
// Setting to maximun value if num_render_targets == 0 to prevent picture index overflow as additional surfaces can be created after calling nvCreateContext
1072+
int surfaceCount = num_render_targets > 0 ? num_render_targets : 32;
10601073

1061-
int surfaceCount = drv->surfaceCount > 1 ? drv->surfaceCount : num_render_targets;
10621074
if (surfaceCount > 32) {
10631075
LOG("Application requested %d surface(s), limiting to 32. This may cause issues.", surfaceCount);
10641076
surfaceCount = 32;
@@ -1120,6 +1132,7 @@ static VAStatus nvCreateContext(
11201132
nvCtx->width = picture_width;
11211133
nvCtx->height = picture_height;
11221134
nvCtx->codec = selectedCodec;
1135+
nvCtx->surfaceCount = surfaceCount;
11231136

11241137
pthread_mutexattr_t attrib;
11251138
pthread_mutexattr_init(&attrib);
@@ -1297,6 +1310,9 @@ static VAStatus nvBeginPicture(
12971310

12981311
//if this surface hasn't been used before, give it a new picture index
12991312
if (surface->pictureIdx == -1) {
1313+
if (nvCtx->currentPictureId == nvCtx->surfaceCount) {
1314+
return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
1315+
}
13001316
surface->pictureIdx = nvCtx->currentPictureId++;
13011317
}
13021318

@@ -1366,11 +1382,16 @@ static VAStatus nvEndPicture(
13661382
nvCtx->bitstreamBuffer.size = 0;
13671383
nvCtx->sliceOffsets.size = 0;
13681384

1385+
CHECK_CUDA_RESULT_RETURN(cu->cuCtxPushCurrent(drv->cudaContext), VA_STATUS_ERROR_OPERATION_FAILED);
13691386
CUresult result = cv->cuvidDecodePicture(nvCtx->decoder, picParams);
1387+
CHECK_CUDA_RESULT_RETURN(cu->cuCtxPopCurrent(NULL), VA_STATUS_ERROR_OPERATION_FAILED);
1388+
1389+
VAStatus status = VA_STATUS_SUCCESS;
1390+
13701391
if (result != CUDA_SUCCESS)
13711392
{
13721393
LOG("cuvidDecodePicture failed: %d", result);
1373-
return VA_STATUS_ERROR_DECODING_ERROR;
1394+
status = VA_STATUS_ERROR_DECODING_ERROR;
13741395
}
13751396
//LOG("Decoded frame successfully to idx: %d (%p)", picParams->CurrPicIdx, nvCtx->renderTarget);
13761397

@@ -1379,6 +1400,7 @@ static VAStatus nvEndPicture(
13791400
surface->context = nvCtx;
13801401
surface->topFieldFirst = !picParams->bottom_field_flag;
13811402
surface->secondField = picParams->second_field;
1403+
surface->decodeFailed = status != VA_STATUS_SUCCESS;
13821404

13831405
//TODO check we're not overflowing the queue
13841406
pthread_mutex_lock(&nvCtx->resolveMutex);
@@ -1391,7 +1413,7 @@ static VAStatus nvEndPicture(
13911413
//Wake up the resolve thread
13921414
pthread_cond_signal(&nvCtx->resolveCondition);
13931415

1394-
return VA_STATUS_SUCCESS;
1416+
return status;
13951417
}
13961418

13971419
static VAStatus nvSyncSurface(

src/vabackend.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ typedef struct
6767
int resolving;
6868
pthread_mutex_t mutex;
6969
pthread_cond_t cond;
70+
bool decodeFailed;
7071
} NVSurface;
7172

7273
typedef enum
@@ -178,6 +179,7 @@ typedef struct _NVContext
178179
int surfaceQueueWriteIdx;
179180
bool exiting;
180181
pthread_mutex_t surfaceCreationMutex;
182+
int surfaceCount;
181183
} NVContext;
182184

183185
typedef struct

0 commit comments

Comments
 (0)