Skip to content

Commit a5af4bb

Browse files
authored
nvidia codec improve (#721)
* chore: lower the log level for vaapi/nvidia codec. * fix compile. * fix benchmark for libwebrtc m137. * Modify the Cuda Context singleton. * Avoid crashes caused by decoding failure. * Removed unnecessary null checks. * tidy. * fix. * check the cuda device count. * fix.
1 parent 81a5de0 commit a5af4bb

21 files changed

+150
-75
lines changed

webrtc-sys/src/nvidia/NvCodec/NvCodec/NvDecoder/NvDecoder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ int NvDecoder::HandlePictureDecode(CUVIDPICPARAMS *pPicParams) {
521521
}
522522
m_nPicNumInDecodeOrder[pPicParams->CurrPicIdx] = m_nDecodePicCnt++;
523523
CUDA_DRVAPI_CALL(cuCtxPushCurrent(m_cuContext));
524-
NVDEC_API_CALL(cuvidDecodePicture(m_hDecoder, pPicParams));
524+
cuvidDecodePicture(m_hDecoder, pPicParams);
525525
if (m_bForce_zero_latency && ((!pPicParams->field_pic_flag) || (pPicParams->second_field)))
526526
{
527527
CUVIDPARSERDISPINFO dispInfo;

webrtc-sys/src/nvidia/cuda_context.cpp

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,58 @@ static bool load_cuda_modules() {
6161
return true;
6262
}
6363

64+
static bool check_cuda_device() {
65+
int device_count = 0;
66+
int driver_version = 0;
67+
68+
CUCTX_CUDA_CALL_ERROR(cuDriverGetVersion(&driver_version));
69+
if (kRequiredDriverVersion > driver_version) {
70+
RTC_LOG(LS_ERROR)
71+
<< "CUDA driver version is not higher than the required version. "
72+
<< driver_version;
73+
return false;
74+
}
75+
76+
CUresult result = cuInit(0);
77+
if (result != CUDA_SUCCESS) {
78+
RTC_LOG(LS_ERROR) << "Failed to initialize CUDA.";
79+
return false;
80+
}
81+
82+
result = cuDeviceGetCount(&device_count);
83+
if (result != CUDA_SUCCESS) {
84+
RTC_LOG(LS_ERROR) << "Failed to get CUDA device count.";
85+
return false;
86+
}
87+
88+
if (device_count == 0) {
89+
RTC_LOG(LS_ERROR) << "No CUDA devices found.";
90+
return false;
91+
}
92+
93+
return true;
94+
}
95+
96+
CudaContext* CudaContext::GetInstance() {
97+
static CudaContext instance;
98+
return &instance;
99+
}
100+
101+
bool CudaContext::IsAvailable() {
102+
return load_cuda_modules() && check_cuda_device();
103+
}
104+
64105
bool CudaContext::Initialize() {
65106
// Initialize CUDA context
66107

67108
bool success = load_cuda_modules();
68109
if (!success) {
69-
std::cout << "Failed to load CUDA modules. maybe the NVIDIA driver is not installed?" << std::endl;
110+
RTC_LOG(LS_ERROR) << "Failed to load CUDA modules. maybe the NVIDIA driver "
111+
"is not installed?";
70112
return false;
71113
}
72114

73-
int numDevices = 0;
115+
int num_devices = 0;
74116
CUdevice cu_device = 0;
75117
CUcontext context = nullptr;
76118

@@ -84,7 +126,23 @@ bool CudaContext::Initialize() {
84126
return false;
85127
}
86128

87-
CUCTX_CUDA_CALL_ERROR(cuInit(0));
129+
CUresult result = cuInit(0);
130+
if (result != CUDA_SUCCESS) {
131+
RTC_LOG(LS_ERROR) << "Failed to initialize CUDA.";
132+
return false;
133+
}
134+
135+
result = cuDeviceGetCount(&num_devices);
136+
if (result != CUDA_SUCCESS) {
137+
RTC_LOG(LS_ERROR) << "Failed to get CUDA device count.";
138+
return false;
139+
}
140+
141+
if (num_devices == 0) {
142+
RTC_LOG(LS_ERROR) << "No CUDA devices found.";
143+
return false;
144+
}
145+
88146
CUCTX_CUDA_CALL_ERROR(cuDeviceGet(&cu_device, 0));
89147

90148
char device_name[80];
@@ -104,6 +162,22 @@ bool CudaContext::Initialize() {
104162
return true;
105163
}
106164

165+
CUcontext CudaContext::GetContext() const {
166+
RTC_DCHECK(cu_context_ != nullptr);
167+
// Ensure the context is current
168+
CUcontext current;
169+
if (cuCtxGetCurrent(&current) != CUDA_SUCCESS) {
170+
throw;
171+
}
172+
if (cu_context_ == current) {
173+
return cu_context_;
174+
}
175+
if (cuCtxSetCurrent(cu_context_) != CUDA_SUCCESS) {
176+
throw;
177+
}
178+
return cu_context_;
179+
}
180+
107181
void CudaContext::Shutdown() {
108182
// Shutdown CUDA context
109183
if (cu_context_) {

webrtc-sys/src/nvidia/cuda_context.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@ namespace livekit {
88
class CudaContext {
99
public:
1010
CudaContext() = default;
11-
~CudaContext() { Shutdown(); }
11+
~CudaContext() = default;
1212

13+
static bool IsAvailable();
14+
15+
static CudaContext* GetInstance();
1316
bool Initialize();
1417
bool IsInitialized() const { return cu_context_ != nullptr; }
15-
CUcontext GetContext() const { return cu_context_; }
16-
CUdevice GetDevice() const { return cu_device_; }
18+
CUcontext GetContext() const;
19+
1720
void Shutdown();
1821

1922
private:

webrtc-sys/src/nvidia/h264_encoder_impl.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ int32_t NvidiaH264EncoderImpl::InitEncode(
248248

249249
int32_t NvidiaH264EncoderImpl::RegisterEncodeCompleteCallback(
250250
EncodedImageCallback* callback) {
251-
RTC_DCHECK(callback);
252251
encoded_image_callback_ = callback;
253252
return WEBRTC_VIDEO_CODEC_OK;
254253
}

webrtc-sys/src/nvidia/nvidia_decoder_factory.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#include <modules/video_coding/codecs/h264/include/h264.h>
44

55
#include <memory>
6-
#include <iostream>
76

87
#include "cuda_context.h"
98
#include "h264_decoder_impl.h"
@@ -65,7 +64,7 @@ std::vector<SdpVideoFormat> SupportedNvDecoderCodecs(CUcontext context) {
6564
}
6665

6766
NvidiaVideoDecoderFactory::NvidiaVideoDecoderFactory()
68-
: cu_context_(std::make_unique<livekit::CudaContext>()) {
67+
: cu_context_(livekit::CudaContext::GetInstance()) {
6968
if (cu_context_->Initialize()) {
7069
supported_formats_ = SupportedNvDecoderCodecs(cu_context_->GetContext());
7170
} else {
@@ -78,12 +77,11 @@ NvidiaVideoDecoderFactory::NvidiaVideoDecoderFactory()
7877
NvidiaVideoDecoderFactory::~NvidiaVideoDecoderFactory() {}
7978

8079
bool NvidiaVideoDecoderFactory::IsSupported() {
81-
// Check if the CUDA context can be initialized.
82-
auto cu_context = std::make_unique<livekit::CudaContext>();
83-
if (!cu_context->Initialize()) {
84-
std::cout << "Failed to initialize CUDA context." << std::endl;
80+
if (!livekit::CudaContext::IsAvailable()) {
81+
RTC_LOG(LS_WARNING) << "Cuda Context is not available.";
8582
return false;
8683
}
84+
8785
std::cout << "Nvidia Decoder is supported." << std::endl;
8886
return true;
8987
}
@@ -96,7 +94,7 @@ std::unique_ptr<VideoDecoder> NvidiaVideoDecoderFactory::Create(
9694
if (format.IsSameCodec(supported_format)) {
9795
// If the format is supported, create and return the encoder.
9896
if (!cu_context_) {
99-
cu_context_ = std::make_unique<livekit::CudaContext>();
97+
cu_context_ = livekit::CudaContext::GetInstance();
10098
if (!cu_context_->Initialize()) {
10199
RTC_LOG(LS_ERROR) << "Failed to initialize CUDA context.";
102100
return nullptr;

webrtc-sys/src/nvidia/nvidia_decoder_factory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class NvidiaVideoDecoderFactory : public VideoDecoderFactory {
2626

2727
private:
2828
std::vector<SdpVideoFormat> supported_formats_;
29-
std::unique_ptr<livekit::CudaContext> cu_context_;
29+
livekit::CudaContext* cu_context_;
3030
};
3131

3232
} // namespace webrtc

webrtc-sys/src/nvidia/nvidia_encoder_factory.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#include "nvidia_encoder_factory.h"
22

33
#include <memory>
4-
#include <iostream>
54

65
#include "cuda_context.h"
76
#include "h264_encoder_impl.h"
@@ -30,10 +29,8 @@ NvidiaVideoEncoderFactory::NvidiaVideoEncoderFactory() {
3029
NvidiaVideoEncoderFactory::~NvidiaVideoEncoderFactory() {}
3130

3231
bool NvidiaVideoEncoderFactory::IsSupported() {
33-
// Check if the CUDA context can be initialized.
34-
auto cu_context = std::make_unique<livekit::CudaContext>();
35-
if (!cu_context->Initialize()) {
36-
std::cout << "Failed to initialize CUDA context." << std::endl;
32+
if (!livekit::CudaContext::IsAvailable()) {
33+
RTC_LOG(LS_WARNING) << "Cuda Context is not available.";
3734
return false;
3835
}
3936

@@ -49,7 +46,7 @@ std::unique_ptr<VideoEncoder> NvidiaVideoEncoderFactory::Create(
4946
if (format.IsSameCodec(supported_format)) {
5047
// If the format is supported, create and return the encoder.
5148
if (!cu_context_) {
52-
cu_context_ = std::make_unique<livekit::CudaContext>();
49+
cu_context_ = livekit::CudaContext::GetInstance();
5350
if (!cu_context_->Initialize()) {
5451
RTC_LOG(LS_ERROR) << "Failed to initialize CUDA context.";
5552
return nullptr;

webrtc-sys/src/nvidia/nvidia_encoder_factory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class NvidiaVideoEncoderFactory : public VideoEncoderFactory {
3434

3535
private:
3636
std::vector<SdpVideoFormat> supported_formats_;
37-
std::unique_ptr<livekit::CudaContext> cu_context_;
37+
livekit::CudaContext* cu_context_ = nullptr;
3838
};
3939

4040
} // namespace webrtc

webrtc-sys/src/vaapi/h264_encoder_impl.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ int32_t VAAPIH264EncoderWrapper::InitEncode(
163163

164164
int32_t VAAPIH264EncoderWrapper::RegisterEncodeCompleteCallback(
165165
EncodedImageCallback* callback) {
166-
RTC_DCHECK(callback);
167166
encoded_image_callback_ = callback;
168167
return WEBRTC_VIDEO_CODEC_OK;
169168
}

webrtc-sys/src/vaapi/vaapi_display_drm.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include <stdio.h>
55
#include <stdlib.h>
66
#include <unistd.h>
7-
#include <iostream>
87

98
#ifdef IN_LIBVA
109
#include "va/drm/va_drm.h"
@@ -111,7 +110,8 @@ namespace livekit {
111110
bool VaapiDisplayDrm::Open() {
112111
va_display_ = va_open_display_drm(&drm_fd_);
113112
if (!va_display_) {
114-
std::cout << "Failed to open VA display. Maybe the AMD video driver or libva-dev/libdrm-dev is not installed?" << std::endl;
113+
RTC_LOG(LS_ERROR) << "Failed to open VA drm display. Maybe the AMD video "
114+
"driver or libva-dev/libdrm-dev is not installed?";
115115
return false;
116116
}
117117
return true;

0 commit comments

Comments
 (0)